1 #include <iostream>
2 #include <string>
3 #include <algorithm>
4 #include <fstream>
5 #include <sstream>
6 #include <cmath>
7 #include <cstddef>
8 #include "boxm2_scene.h"
9 //:
10 // \file
11 #ifdef _MSC_VER
12 #  include "vcl_msvc_warnings.h"
13 #endif
14 /* xml includes */
15 #include "vsl/vsl_basic_xml_element.h"
16 #include <vgl/xio/vgl_xio_point_3d.h>
17 #include <vgl/xio/vgl_xio_vector_3d.h>
18 #include <boxm2/boxm2_scene_parser.h>
19 #include <vpgl/xio/vpgl_xio_lvcs.h>
20 
21 //vgl includes
22 #include "vgl/vgl_vector_3d.h"
23 #include "vgl/vgl_distance.h"
24 #include "vgl/vgl_box_2d.h"
25 #include "vgl/vgl_box_3d.h"
26 #include "vgl/vgl_point_3d.h"
27 
28 #include "vgl/vgl_intersection.h"
29 
30 //vsph include
31 #include <vsph/vsph_camera_bounds.h>
32 
33 //vul include
34 #include "vul/vul_file.h"
35 
36 
boxm2_scene(std::string const & data_path,vgl_point_3d<double> const & origin,int version)37 boxm2_scene::boxm2_scene(std::string const& data_path, vgl_point_3d<double> const& origin, int version)
38 {
39   local_origin_=origin;
40   data_path_   = data_path;
41   xml_path_  = data_path_ + "/scene.xml";
42   num_illumination_bins_ = -1;
43   version_ = version;
44   id_ = boxm2_scene::get_count();
45   boxm2_scene::get_count()++;
46 }
47 //create a scene with one block
boxm2_scene(std::string const & scene_dir,std::string const & scene_name,std::string const & data_path,std::vector<std::string> const & prefixes,vgl_box_3d<double> const & scene_box,double sub_block_len,int init_level,int max_level,double,double,int n_illum_bins,int version)48 boxm2_scene::boxm2_scene(std::string const& scene_dir, std::string const& scene_name, std::string const& data_path, std::vector<std::string> const& prefixes,
49             vgl_box_3d<double> const& scene_box, double sub_block_len, int init_level,
50                          int max_level, double  /*max_mb*/, double  /*p_init*/, int n_illum_bins, int version){
51   num_illumination_bins_ = n_illum_bins;
52   version_ = version;
53   id_ = boxm2_scene::get_count();
54   boxm2_scene::get_count()++;
55   boxm2_block_id bid(0,0,0);
56   boxm2_block_metadata md;
57   md.id_ = bid;
58   vgl_point_3d<double> origin = scene_box.min_point();
59   auto dim_x = static_cast<unsigned>(std::ceil(scene_box.width()/sub_block_len));
60   auto dim_y = static_cast<unsigned>(std::ceil(scene_box.height()/sub_block_len));
61   auto dim_z = static_cast<unsigned>(std::ceil(scene_box.depth()/sub_block_len));
62   md.local_origin_ = origin;
63   md.sub_block_dim_ = vgl_vector_3d<double>(sub_block_len, sub_block_len, sub_block_len);
64   md.sub_block_num_ = vgl_vector_3d<unsigned>(dim_x, dim_y, dim_z);
65   md.init_level_ = init_level;
66   md.max_level_ = max_level;
67   md.max_mb_ = 400;
68   md.p_init_ = .001;
69   md.version_ = version;
70   blocks_[bid]=md;
71   appearances_ = prefixes;
72   this->set_local_origin(origin);
73   this->set_rpc_origin(origin);
74   vpgl_lvcs lvcs;
75   this->set_lvcs(lvcs);
76   this->set_xml_path(scene_dir + scene_name + ".xml");
77   this->set_data_path(scene_dir + data_path );
78 }
boxm2_scene(const char * buffer)79 boxm2_scene::boxm2_scene(const char* buffer)
80 {
81   boxm2_scene_parser parser;
82   if (!parser.parseString(buffer)) {
83     std::cerr << XML_ErrorString(parser.XML_GetErrorCode()) << " at line "
84              << parser.XML_GetCurrentLineNumber() << '\n';
85     return;
86   }
87 
88   //store data path
89   data_path_ = parser.path();
90   xml_path_  = data_path_ + "scene.xml";
91 
92   //lvcs, origin, block dimension
93   parser.lvcs(lvcs_);
94   local_origin_ = parser.origin();
95   rpc_origin_   = parser.origin();
96 
97   //store BLOCKS
98   blocks_ = parser.blocks();
99 
100   //store list of appearances
101   appearances_ = parser.appearances();
102   num_illumination_bins_ = parser.num_illumination_bins();
103   version_ = parser.version();
104   id_ = boxm2_scene::get_count();
105   boxm2_scene::get_count()++;
106 }
107 
108 //: initializes Scene from XML file
boxm2_scene(std::string const & filename)109 boxm2_scene::boxm2_scene(std::string const& filename)
110 {
111   std::ifstream ifs;
112   // we must throw an exception on failure in a constructor
113   ifs.exceptions(std::ifstream::failbit | std::ifstream::badbit);
114   ifs.open(filename.c_str());
115   std::stringstream buffer;
116   buffer << ifs.rdbuf();
117 
118   //xml parser
119   xml_path_ = filename;
120   boxm2_scene_parser parser;
121 
122   if (!parser.parseString(buffer.str().c_str())) {
123     std::cerr << XML_ErrorString(parser.XML_GetErrorCode()) << " at line "
124              << parser.XML_GetCurrentLineNumber() << '\n';
125     throw std::ifstream::failure("Error parsing file.");
126   }
127 
128   //store data path
129   if(parser.is_model_local_to_scene_path()) {
130     // to make the model (data) path relative to the scene file,
131     // set the 'is_model_local' bool attribute of the <scene_paths> tag
132     std::string basepath = vul_file::dirname(filename); // cant return an empty string
133     data_path_ = basepath + "/" + parser.path(); // not normalized, but thats ok
134   }
135   else {
136     // the data path is relative to the current working directory of the process
137     data_path_ = parser.path();
138   }
139 
140   //lvcs, origin, block dimension
141   parser.lvcs(lvcs_);
142   local_origin_ = parser.origin();
143   rpc_origin_   = parser.origin();
144 
145   //store BLOCKS
146   blocks_ = parser.blocks();
147 
148   //store list of appearances
149   appearances_ = parser.appearances();
150   num_illumination_bins_ = parser.num_illumination_bins();
151   version_ = parser.version();
152   id_ = boxm2_scene::get_count();
153   boxm2_scene::get_count()++;
154 }
155 // pretty much a straignt copy but provide a unique id
boxm2_scene(boxm2_scene const & other_scene)156 boxm2_scene::boxm2_scene(boxm2_scene const& other_scene){
157   lvcs_ = other_scene.lvcs();
158   local_origin_ = other_scene.local_origin();
159   rpc_origin_ = other_scene.rpc_origin();
160   data_path_ = other_scene.data_path();
161   xml_path_ = other_scene.xml_path();
162   auto& non_const_scene = const_cast<boxm2_scene&>(other_scene);
163   blocks_ = non_const_scene.blocks();
164   appearances_ = other_scene.appearances();
165   num_illumination_bins_ = other_scene.num_illumination_bins();
166   version_ = other_scene.version();
167   id_ = boxm2_scene::get_count();
168   boxm2_scene::get_count()++;
169 }
170 
clone_no_disk()171 boxm2_scene_sptr boxm2_scene::clone_no_disk(){
172   auto* clone = new boxm2_scene();
173   clone->set_lvcs(this->lvcs_);
174   clone->set_local_origin(this->local_origin_);
175   clone->set_rpc_origin(this->rpc_origin_);
176   clone->set_data_path("");
177   clone->set_xml_path("");
178   clone->set_blocks(this->blocks_);
179   clone->set_appearances(this->appearances_);
180   clone->set_num_illumination_bins(this->num_illumination_bins_);
181   clone->set_version(this->version_);
182   return clone;
183 }
184 
185 //: add a block meta data...
add_block_metadata(boxm2_block_metadata data)186 void boxm2_scene::add_block_metadata(boxm2_block_metadata data)
187 {
188   if ( blocks_.find(data.id_) != blocks_.end() )
189   {
190     std::cout<<"Boxm2 SCENE: Overwriting block metadata for id: "<<data.id_<<std::endl;
191   }
192   blocks_[data.id_] = data;
193 }
194 
get_block_ids() const195 std::vector<boxm2_block_id> boxm2_scene::get_block_ids() const
196 {
197   std::map<boxm2_block_id, boxm2_block_metadata>::const_iterator iter;
198   std::vector<boxm2_block_id> block_ids;
199   for (iter = blocks_.begin(); iter != blocks_.end(); ++iter) {
200     block_ids.push_back(iter->first);
201   }
202   return block_ids;
203 }
204 
205 boxm2_block_metadata boxm2_scene::
get_block_metadata_const(boxm2_block_id const & id) const206 get_block_metadata_const(boxm2_block_id const& id) const
207 {
208   std::map<boxm2_block_id, boxm2_block_metadata>::const_iterator iter;
209   for (iter = blocks_.begin(); iter != blocks_.end(); ++iter)
210     if ((*iter).first == id)
211       return (*iter).second;
212   return boxm2_block_metadata();
213 }
214 
215 #include <boxm2/boxm2_blocks_vis_graph.h>
216 
get_vis_blocks(vpgl_generic_camera<double> * cam,double)217 std::vector<boxm2_block_id> boxm2_scene::get_vis_blocks(vpgl_generic_camera<double>* cam, double  /*dist*/)
218 {
219   boxm2_block_vis_graph g(blocks_,*cam);
220   std::vector<boxm2_block_id> vis_order = g.get_ordered_ids();
221   return vis_order;
222 }
223 
get_vis_blocks(vpgl_affine_camera<double> * cam)224 std::vector<boxm2_block_id> boxm2_scene::get_vis_blocks(vpgl_affine_camera<double>* cam)
225 {
226   std::vector<boxm2_block_id> vis_order;
227   if (!cam) {
228     std::cout << "null camera in boxm2_scene::get_vis_blocks(.)\n";
229     return vis_order;
230   }
231   vgl_homg_point_3d<double> cam_center_ideal = cam->camera_center();
232   vgl_vector_3d<double> ray_dir(cam_center_ideal.x(), cam_center_ideal.y(), cam_center_ideal.z());
233 
234   vgl_box_3d<int> idx_bbox;
235   for (auto & block : blocks_) {
236     boxm2_block_id const& id = block.first;
237     idx_bbox.add(vgl_point_3d<int>(id.i_, id.j_, id.k_));
238   }
239   int closest_i = ray_dir.x() > 0? idx_bbox.min_x() : idx_bbox.max_x();
240   int closest_j = ray_dir.y() > 0? idx_bbox.min_y() : idx_bbox.max_y();
241   int closest_k = ray_dir.z() > 0? idx_bbox.min_z() : idx_bbox.max_z();
242 
243   // visibility ordering is based on manhattan distance of block index from that of closest block.
244   std::vector<boxm2_dist_id_pair> manhattan_distances;
245   for (auto & block : blocks_)
246   {
247     // dec: we would perform a visibility test here if we had ni,nj.
248     //if(!this->is_block_visible(iter->second,*cam,ni,nj))
249     //  continue;
250 
251     int manhattan_distance = std::abs(block.first.i_ - closest_i) +
252                              std::abs(block.first.j_ - closest_j) +
253                              std::abs(block.first.k_ - closest_k);
254 
255     manhattan_distances.emplace_back(manhattan_distance, block.first );
256   }
257 
258     //sort distances
259     std::sort(manhattan_distances.begin(), manhattan_distances.end());
260     //put blocks in "vis_order"
261     std::vector<boxm2_dist_id_pair>::iterator di;
262     for (di = manhattan_distances.begin(); di != manhattan_distances.end(); ++di) {
263         vis_order.push_back(di->id_);
264     }
265     return vis_order;
266 }
267 
268 
get_vis_blocks(vpgl_perspective_camera<double> * cam,double dist)269 std::vector<boxm2_block_id> boxm2_scene::get_vis_blocks(vpgl_perspective_camera<double>* cam, double dist)
270 {
271   std::vector<boxm2_block_id> vis_order;
272   if (!cam) {
273     std::cout << "null camera in boxm2_scene::get_vis_blocks(.)\n";
274     return vis_order;
275   }
276 
277   //---------------------------------------
278   //find intersection box
279   //---------------------------------------
280   vgl_box_3d<double> sceneBB = this->bounding_box();
281   vgl_box_2d<double> lowBox, highBox;
282   vsph_camera_bounds::planar_bounding_box(*cam, lowBox, sceneBB.min_z());
283   vsph_camera_bounds::planar_bounding_box(*cam, highBox, sceneBB.max_z());
284   vgl_box_2d<double> camBox;
285   camBox.add(lowBox);
286   camBox.add(highBox);
287 
288   //grab visibility order from camera center
289   vgl_point_3d<double> cam_center = cam->camera_center();
290 
291 
292   return get_vis_order_from_pt(cam_center, camBox, dist);
293 }
get_vis_blocks_opt(vpgl_perspective_camera<double> * cam,unsigned int ni,unsigned int nj)294 std::vector<boxm2_block_id> boxm2_scene::get_vis_blocks_opt(vpgl_perspective_camera<double>* cam,  unsigned int ni, unsigned int nj)
295 {
296     std::vector<boxm2_block_id> vis_order;
297     if (!cam) {
298         std::cout << "null camera in boxm2_scene::get_vis_blocks(.)\n";
299         return vis_order;
300     }
301     //grab visibility order from camera center
302     vgl_point_3d<double> cam_center = cam->camera_center();
303     //Map of distance, id
304     std::vector<boxm2_dist_id_pair> distances;
305     //get camera center and order blocks distance from the cam center
306     //for non-projective cameras there may not be a single center of projection
307     //so instead get the ray origin farthest from the scene origin.
308     std::map<boxm2_block_id, boxm2_block_metadata>::iterator iter;
309     for (iter = blocks_.begin(); iter != blocks_.end(); ++iter)
310     {
311         if(!this->is_block_visible(iter->second,*cam,ni,nj))
312             continue;
313         vgl_point_3d<double>&    blk_o   = (iter->second).local_origin_;
314         vgl_vector_3d<double>&   blk_dim = (iter->second).sub_block_dim_;
315         vgl_vector_3d<unsigned>& blk_num = (iter->second).sub_block_num_;
316         vgl_vector_3d<double>    length(blk_dim.x()*blk_num.x(),
317                                         blk_dim.y()*blk_num.y(),
318                                         blk_dim.z()*blk_num.z());
319 
320         //make sure there is a non empty intersection here
321         vgl_box_2d<double> blkBox(blk_o.x(), blk_o.x()+length.x(),blk_o.y(), blk_o.y()+length.y());
322         vgl_point_3d<double> blk_center = blk_o + length/2.0;
323 
324         double dist = vgl_distance( blk_center, cam_center);
325         distances.emplace_back(dist, iter->first );
326 
327     }
328 
329     //sort distances
330     std::sort(distances.begin(), distances.end());
331     //put blocks in "vis_order"
332     std::vector<boxm2_dist_id_pair>::iterator di;
333     for (di = distances.begin(); di != distances.end(); ++di)
334         vis_order.push_back(di->id_);
335     return vis_order;
336 }
337 std::vector<boxm2_block_id>
get_vis_order_from_pt(vgl_point_3d<double> const & pt,vgl_box_2d<double> camBox,double distance)338 boxm2_scene::get_vis_order_from_pt(vgl_point_3d<double> const& pt,
339                                    vgl_box_2d<double> camBox, double distance)
340 {
341   //Map of distance, id
342   std::vector<boxm2_block_id> vis_order;
343   std::vector<boxm2_dist_id_pair> distances;
344 
345   //get camera center and order blocks distance from the cam center
346   //for non-projective cameras there may not be a single center of projection
347   //so instead get the ray origin farthest from the scene origin.
348   std::map<boxm2_block_id, boxm2_block_metadata>::iterator iter;
349   for (iter = blocks_.begin(); iter != blocks_.end(); ++iter) {
350     vgl_point_3d<double>&    blk_o   = (iter->second).local_origin_;
351     vgl_vector_3d<double>&   blk_dim = (iter->second).sub_block_dim_;
352     vgl_vector_3d<unsigned>& blk_num = (iter->second).sub_block_num_;
353     vgl_vector_3d<double>    length(blk_dim.x()*blk_num.x(),
354                                     blk_dim.y()*blk_num.y(),
355                                     blk_dim.z()*blk_num.z());
356 
357     //make sure there is a non empty intersection here
358     vgl_box_2d<double> blkBox(blk_o.x(), blk_o.x()+length.x(),
359                               blk_o.y(), blk_o.y()+length.y());
360     vgl_box_2d<double> intersect = vgl_intersection(camBox, blkBox);
361 
362       vgl_point_3d<double> blk_center = blk_o + length/2.0;
363 
364       double dist = vgl_distance( blk_center, pt);
365 
366       if (distance > 0 && dist < distance)
367         distances.emplace_back(dist, iter->first );
368       else
369         distances.emplace_back(dist, iter->first );
370 
371   }
372 
373   //sort distances
374   std::sort(distances.begin(), distances.end());
375 
376   //put blocks in "vis_order"
377   std::vector<boxm2_dist_id_pair>::iterator di;
378   for (di = distances.begin(); di != distances.end(); ++di)
379     vis_order.push_back(di->id_);
380   return vis_order;
381 }
382 //: return all blocks with center less than dist from the given point
get_vis_blocks(vgl_point_3d<double> const & pt,double distance)383 std::vector<boxm2_block_id> boxm2_scene::get_vis_blocks(vgl_point_3d<double> const& pt, double distance)
384 {
385   std::vector<boxm2_block_id> vis_order;
386   std::map<boxm2_block_id, boxm2_block_metadata>::iterator iter;
387   for (iter = blocks_.begin(); iter != blocks_.end(); ++iter) {
388     vgl_point_3d<double>&    blk_o   = (iter->second).local_origin_;
389     vgl_vector_3d<double>&   blk_dim = (iter->second).sub_block_dim_;
390     vgl_vector_3d<unsigned>& blk_num = (iter->second).sub_block_num_;
391     vgl_vector_3d<double>    length(blk_dim.x()*blk_num.x(),
392                                     blk_dim.y()*blk_num.y(),
393                                     blk_dim.z()*blk_num.z());
394     vgl_point_3d<double> blk_center = blk_o + length/2.0;
395     double dist = vgl_distance( blk_center, pt);
396     if (dist <= distance)
397       vis_order.push_back(iter->first);
398   }
399   return vis_order;
400 }
401 
402 
403 std::vector<boxm2_block_id>
get_vis_order_from_ray(vgl_point_3d<double> const & origin,vgl_vector_3d<double> const & dir,double distance)404 boxm2_scene::get_vis_order_from_ray(vgl_point_3d<double> const& origin, vgl_vector_3d<double> const& dir, double distance)
405 {
406   // Map of distance, id
407   std::vector<boxm2_block_id> vis_order;
408   std::vector<boxm2_dist_id_pair> distances;
409 
410   // get camera center and order blocks distance from the cam center
411   // do not insert blocks if they are in front of the camera!
412   std::map<boxm2_block_id, boxm2_block_metadata>::iterator iter;
413   for (iter = blocks_.begin(); iter != blocks_.end(); ++iter) {
414     vgl_point_3d<double>&    blk_o   = (iter->second).local_origin_;
415     vgl_vector_3d<double>&   blk_dim = (iter->second).sub_block_dim_;
416     vgl_vector_3d<unsigned>& blk_num = (iter->second).sub_block_num_;
417     vgl_vector_3d<double>    length(blk_dim.x()*blk_num.x(),
418                                     blk_dim.y()*blk_num.y(),
419                                     blk_dim.z()*blk_num.z());
420 
421     vgl_point_3d<double> blk_center = blk_o + length/2.0;
422 
423     // ray from origin to blk center
424     vgl_vector_3d<double> blk_ray = blk_center - origin;
425     vgl_vector_3d<double> blk_ray_n = normalized(blk_ray);
426 
427     // check if the blk ray and camera ray are pointing to the same direction
428     double cos = dot_product(dir, blk_ray_n);
429     if (cos > 0) { // an angle in (-pi/2,pi/2)
430       double dist = vgl_distance( blk_center, origin);
431       if (distance > 0 && dist < distance)
432         distances.emplace_back(dist, iter->first );
433       else
434         distances.emplace_back(dist, iter->first );
435     }
436   }
437 
438   //sort distances
439   std::sort(distances.begin(), distances.end());
440 
441   //put blocks in "vis_order"
442   std::vector<boxm2_dist_id_pair>::iterator di;
443   for (di = distances.begin(); di != distances.end(); ++di)
444     vis_order.push_back(di->id_);
445   return vis_order;
446 }
447 
448 //: If a block contains a 3-d point, set the local coordinates of the point
block_contains(vgl_point_3d<double> const & p,boxm2_block_id const & bid,vgl_point_3d<double> & local_coords) const449 bool boxm2_scene::block_contains(vgl_point_3d<double> const& p, boxm2_block_id const& bid,
450                                  vgl_point_3d<double>& local_coords) const
451 {
452   boxm2_block_metadata md = this->get_block_metadata_const(bid);
453   if (md.init_level_ == 0) // block does not exist
454     return false;
455   vgl_vector_3d<double> dims(md.sub_block_dim_.x()*md.sub_block_num_.x(),
456                              md.sub_block_dim_.y()*md.sub_block_num_.y(),
457                              md.sub_block_dim_.z()*md.sub_block_num_.z());
458 
459   vgl_point_3d<double> lorigin = md.local_origin_;
460   vgl_box_3d<double> bbox(lorigin,lorigin+dims);
461   if (p.x() >= bbox.min_x() && p.x() < bbox.max_x() &&
462       p.y() >= bbox.min_y() && p.y() < bbox.max_y() &&
463       p.z() >= bbox.min_z() && p.z() < bbox.max_z())
464   {//Slightly different than bbox.contains, which was wrong on block boundary
465     double local_x=(p.x()-md.local_origin_.x())/md.sub_block_dim_.x();
466     double local_y=(p.y()-md.local_origin_.y())/md.sub_block_dim_.y();
467     double local_z=(p.z()-md.local_origin_.z())/md.sub_block_dim_.z();
468     local_coords.set(local_x, local_y, local_z);
469     return true;
470   }
471   return false;
472 }
473 
474 //: find the block containing the specified point, else return false
475 //  Local coordinates are also returned
contains(vgl_point_3d<double> const & p,boxm2_block_id & bid,vgl_point_3d<double> & local_coords) const476 bool boxm2_scene::contains(vgl_point_3d<double> const& p, boxm2_block_id& bid,
477                            vgl_point_3d<double>& local_coords) const
478 {
479   std::vector<boxm2_block_id> block_ids = this->get_block_ids();
480   for (auto & block_id : block_ids)
481   {
482     if (this->block_contains(p, block_id, local_coords)) {
483       bid = block_id;
484       return true;
485     }
486   }
487   return false;
488 }
489 
490 //: save scene (xml file)
save_scene()491 void boxm2_scene::save_scene()
492 {
493   //write out to XML file
494   std::ofstream xmlstrm(xml_path_.c_str());
495   x_write(xmlstrm, (*this), "scene");
496   xmlstrm.close();
497 }
498 
499 //: return a heap pointer to a scene info
get_blk_metadata(boxm2_block_id const & id)500 boxm2_scene_info* boxm2_scene::get_blk_metadata(boxm2_block_id const& id)
501 {
502   if ( blocks_.find(id) == blocks_.end() )
503   {
504     std::cerr<<"\nboxm2_scene::get_blk_metadata: Block doesn't exist: "<<id<<"\n\n";
505     return nullptr;
506   }
507 
508   boxm2_block_metadata data = blocks_[id];
509   auto* info = new boxm2_scene_info();
510 
511   info->scene_origin[0] = (float) data.local_origin_.x();
512   info->scene_origin[1] = (float) data.local_origin_.y();
513   info->scene_origin[2] = (float) data.local_origin_.z();
514   info->scene_origin[3] = (float) 0.0f;
515 
516   info->scene_dims[0] = (int) data.sub_block_num_.x();  // number of blocks in each dimension
517   info->scene_dims[1] = (int) data.sub_block_num_.y();
518   info->scene_dims[2] = (int) data.sub_block_num_.z();
519   info->scene_dims[3] = (int) 0;
520 
521   info->block_len = (float) data.sub_block_dim_.x();
522   info->epsilon   = (float) (info->block_len / 100.0f);
523 
524   info->root_level = data.max_level_-1;
525   info->num_buffer = 0;
526   info->tree_buffer_length = 0;
527   info->data_buffer_length = 0;
528   info->pinit = data.p_init_;
529   return info;
530 }
531 
532 
bounding_box() const533 vgl_box_3d<double> boxm2_scene::bounding_box() const
534 {
535   double xmin=10e10, xmax=-10e10;
536   double ymin=10e10, ymax=-10e10;
537   double zmin=10e10, zmax=-10e10;
538 
539   //iterate through each block
540   std::map<boxm2_block_id, boxm2_block_metadata>::const_iterator iter;
541   for (iter = blocks_.begin(); iter != blocks_.end(); ++iter)
542   {
543     //determine xmin, ymin, zmin using block_o
544     vgl_point_3d<double>  blk_o = (iter->second).local_origin_;
545     if (blk_o.x() < xmin) xmin = blk_o.x();
546     if (blk_o.y() < ymin) ymin = blk_o.y();
547     if (blk_o.z() < zmin) zmin = blk_o.z();
548 
549     //get block max point
550     vgl_vector_3d<double>   blk_dim = (iter->second).sub_block_dim_;
551     vgl_vector_3d<unsigned> blk_num = (iter->second).sub_block_num_;
552     vgl_vector_3d<double>   length(blk_dim.x()*blk_num.x(),
553                                    blk_dim.y()*blk_num.y(),
554                                    blk_dim.z()*blk_num.z());
555     vgl_point_3d<double> blk_max = blk_o + length;
556     if (blk_max.x() > xmax) xmax = blk_max.x();
557     if (blk_max.y() > ymax) ymax = blk_max.y();
558     if (blk_max.z() > zmax) zmax = blk_max.z();
559   }
560 
561   //: Construct from ranges in \a x,y,z (take care with order of inputs).
562   //  The \a x range is given by the 1st and 4th coordinates,
563   //  the \a y range is given by the 2nd and 5th coordinates,
564   //  the \a z range is given by the 3rd and 6th coordinates.
565   return {xmin, ymin, zmin,
566                             xmax, ymax, zmax};
567 }
568 
bounding_box_blk_ids() const569 vgl_box_3d<int> boxm2_scene::bounding_box_blk_ids() const
570 {
571   vgl_box_3d<int> bbox;
572   //iterate through each block
573   std::map<boxm2_block_id, boxm2_block_metadata>::const_iterator iter;
574   for (iter = blocks_.begin(); iter != blocks_.end(); ++iter)
575     bbox.add(vgl_point_3d<int> ( iter->first.i(),iter->first.j(), iter->first.k()) ) ;
576 
577   return bbox;
578 }
579 
scene_dimensions() const580 vgl_vector_3d<unsigned int>  boxm2_scene::scene_dimensions() const
581 {
582   std::vector<boxm2_block_id> ids = this->get_block_ids();
583 
584   if (ids.empty())
585     return {0,0,0};
586 
587   int max_i=ids[0].i(),max_j=ids[0].j(),max_k=ids[0].k();
588   int min_i=ids[0].i(),min_j=ids[0].j(),min_k=ids[0].k();
589 
590   for (auto & id : ids) {
591     if (id.i() > max_i)
592       max_i=id.i();
593     if (id.j() > max_j)
594       max_j=id.j();
595     if (id.k() > max_k)
596       max_k=id.k();
597 
598     if (id.i() < min_i)
599       min_i=id.i();
600     if (id.j() < min_j)
601       min_j=id.j();
602     if (id.k() < min_k)
603       min_k=id.k();
604   }
605   max_i++; max_j++; max_k++;
606 
607   return {static_cast<unsigned int>((max_i-min_i)),static_cast<unsigned int>((max_j - min_j)),static_cast<unsigned int>((max_k-min_k))};
608 }
609 
610 //: gets the smallest block index
min_block_index(vgl_point_3d<int> & idx,vgl_point_3d<double> & local_origin) const611 void boxm2_scene::min_block_index (vgl_point_3d<int> &idx,
612                                    vgl_point_3d<double> &local_origin) const
613 {
614   auto iter= blocks_.begin();
615 
616   boxm2_block_id id = iter->first;
617   boxm2_block_metadata data = iter->second;
618 
619   int min_i=id.i(),min_j=id.j(),min_k=id.k();
620   double min_x = data.local_origin_.x(), min_y= data.local_origin_.y(), min_z= data.local_origin_.z();
621 
622   for (; iter != blocks_.end(); ++iter) {
623     id = iter->first;
624     data = iter->second;
625 
626     if (id.i() < min_i) {
627       min_i=id.i();
628       min_x = data.local_origin_.x();
629     }
630     if (id.j() < min_j) {
631       min_j=id.j();
632       min_y = data.local_origin_.y();
633     }
634     if (id.k() < min_k) {
635       min_k=id.k();
636       min_z = data.local_origin_.z();
637     }
638   }
639 
640   idx.set(min_i,min_j,min_k);
641   local_origin.set(min_x, min_y, min_z);
642 }
finest_resolution()643 float boxm2_scene::finest_resolution()
644 {
645     std::map<boxm2_block_id, boxm2_block_metadata>::const_iterator iter= blocks_.begin();
646     boxm2_block_metadata data = iter->second;
647 
648     float final_level = data.max_level_;
649     float block_dim = data.sub_block_dim_.x() ;
650 
651     return block_dim / std::pow(2.0f,final_level-1) ;
652 }
653 //: gets the smallest block index
max_block_index(vgl_point_3d<int> & idx,vgl_point_3d<double> & local_origin) const654 void boxm2_scene::max_block_index (vgl_point_3d<int> &idx,
655                                    vgl_point_3d<double> &local_origin) const
656 {
657   auto iter= blocks_.begin();
658 
659   boxm2_block_id id = iter->first;
660   boxm2_block_metadata data = iter->second;
661 
662   int max_i=id.i(),max_j=id.j(),max_k=id.k();
663   double max_x = data.local_origin_.x(), max_y= data.local_origin_.y(), max_z= data.local_origin_.z();
664 
665   for (; iter != blocks_.end(); ++iter) {
666     id = iter->first;
667     data = iter->second;
668 
669     if (id.i() > max_i) {
670       max_i=id.i();
671       max_x = data.local_origin_.x();
672     }
673     if (id.j() > max_j) {
674       max_j=id.j();
675       max_y = data.local_origin_.y();
676     }
677     if (id.k() > max_k) {
678       max_k=id.k();
679       max_z = data.local_origin_.z();
680     }
681   }
682 
683   idx.set(max_i,max_j,max_k);
684   local_origin.set(max_x, max_y, max_z);
685 }
686 
get_count()687 unsigned& boxm2_scene::get_count()
688 {
689   static unsigned count;
690   return count;
691 }
692 
693 //: returns true if the scene has specified data type (simple linear search)
has_data_type(std::string const & data_type)694 bool boxm2_scene::has_data_type(std::string const& data_type)
695 {
696   for (const auto & appearance : appearances_)
697     if ( appearance == data_type )
698       return true;
699   return false;
700 }
701 
is_block_visible(boxm2_block_metadata & data,vpgl_camera<double> const & cam,unsigned int ni,unsigned int nj)702 bool boxm2_scene::is_block_visible(boxm2_block_metadata & data, vpgl_camera<double> const& cam, unsigned int ni, unsigned int nj )
703 {
704     vgl_box_3d<double> bbox = data.bbox();
705     std::vector<vgl_point_3d<double> > vertices =  bbox.vertices() ;
706     vgl_box_2d<double> projectionbox;
707     for(auto & vertice : vertices)
708     {
709         double u,v;
710         cam.project(vertice.x(),vertice.y(),vertice.z(),u,v);
711         projectionbox.add(vgl_point_2d<double>(u,v) );
712     }
713     vgl_box_2d<double> imagebbox(0,ni,0,nj);
714     vgl_box_2d<double> ibox = vgl_intersection<double>(imagebbox,projectionbox);
715     return !(ibox.is_empty());
716 }
717 //---------------------------------------------------------------------
718 // NON CLASS FUNCTIONS
719 //---------------------------------------------------------------------
720 //------------XML WRITE------------------------------------------------
x_write(std::ostream & os,boxm2_scene & scene,std::string const & name)721 void x_write(std::ostream &os, boxm2_scene& scene, std::string const& name)
722 {
723   //open root tag
724   vsl_basic_xml_element scene_elm(name);
725   scene_elm.x_write_open(os);
726 
727   //write lvcs information
728   vpgl_lvcs lvcs = scene.lvcs();
729   x_write(os, lvcs, LVCS_TAG);
730   x_write(os, scene.local_origin(), LOCAL_ORIGIN_TAG);
731 
732   //write scene path for (needs to know where blocks are)
733   std::string path = scene.data_path();
734   vsl_basic_xml_element paths(SCENE_PATHS_TAG);
735   paths.add_attribute("path", path + '/');
736   paths.x_write(os);
737 
738   vsl_basic_xml_element ver(VERSION_TAG);
739   ver.add_attribute("number", scene.version());
740   ver.x_write(os);
741 
742   //write list of appearance models
743 
744   std::vector<std::string> apps = scene.appearances();
745   for (const auto & app : apps)
746   {
747     vsl_basic_xml_element apms(APM_TAG);
748     apms.add_attribute("apm", app);
749     apms.x_write(os);
750   }
751   if (scene.num_illumination_bins() > 0) {
752     vsl_basic_xml_element apms(APM_TAG);
753     std::stringstream ss; ss << scene.num_illumination_bins();
754     apms.add_attribute("num_illumination_bins", ss.str());
755     apms.x_write(os);
756   }
757 
758   //write block information for each block
759   std::map<boxm2_block_id, boxm2_block_metadata> blocks = scene.blocks();
760   std::map<boxm2_block_id, boxm2_block_metadata>::iterator iter;
761   for (iter = blocks.begin(); iter != blocks.end(); ++iter) {
762     boxm2_block_id id = iter->first;
763     boxm2_block_metadata data = iter->second;
764     vsl_basic_xml_element block(BLOCK_TAG);
765 
766     //add block id attribute
767     block.add_attribute("id_i", id.i());
768     block.add_attribute("id_j", id.j());
769     block.add_attribute("id_k", id.k());
770 
771     //block local origin
772     block.add_attribute("origin_x", data.local_origin_.x());
773     block.add_attribute("origin_y", data.local_origin_.y());
774     block.add_attribute("origin_z", data.local_origin_.z());
775 
776     //sub block dimensions
777     block.add_attribute("dim_x", data.sub_block_dim_.x());
778     block.add_attribute("dim_y", data.sub_block_dim_.y());
779     block.add_attribute("dim_z", data.sub_block_dim_.z());
780 
781     //sub block numbers
782     block.add_attribute("num_x", (int) data.sub_block_num_.x());
783     block.add_attribute("num_y", (int) data.sub_block_num_.y());
784     block.add_attribute("num_z", (int) data.sub_block_num_.z());
785 
786     //block init level
787     block.add_attribute("init_level", data.init_level_);
788 
789     //block max level
790     block.add_attribute("max_level", data.max_level_);
791 
792     //block max_mb
793     block.add_attribute("max_mb", data.max_mb_);
794 
795     //block prob init
796     block.add_attribute("p_init", data.p_init_);
797 
798           //block prob init
799     block.add_attribute("random", 0);
800 
801     //write tag to stream
802     block.x_write(os);
803   }
804 
805   //clse up tag
806   scene_elm.x_write_close(os);
807 }
808 
809 //------------IO Stream------------------------------------------------
operator <<(std::ostream & s,boxm2_scene & scene)810 std::ostream& operator <<(std::ostream &s, boxm2_scene& scene)
811 {
812   s <<"--- BOXM2_SCENE -----------------------------\n"
813     <<"xml_path:         "<<scene.xml_path()<<'\n'
814     <<"data_path:        "<<scene.data_path()<<'\n'
815     <<"world origin:     "<<scene.rpc_origin()<<'\n'
816     <<"list of APMs:     "<<'\n';
817 
818   //list appearance models for this scene
819   std::vector<std::string> apps = scene.appearances();
820   for (const auto & app : apps)
821     s << "    " << app << ", ";
822   s << '\n';
823   vpgl_lvcs lvcs = scene.lvcs();
824   s << lvcs << '\n';
825 
826   vgl_box_3d<double> bb = scene.bounding_box();
827   vgl_point_3d<double> minp = bb.min_point();
828   vgl_point_3d<double> maxp = bb.max_point();
829   s << "bounds : ( " << minp.x() << ' ' << minp.y() << ' ' << minp.z()
830     << " )==>( " << maxp.x() << ' ' << maxp.y() << ' ' << maxp.z() << " )\n";
831 
832   //list of block ids for this scene....
833   vgl_vector_3d<unsigned> dims = scene.scene_dimensions();
834   s << "block array dims(" << dims.x() << ' ' << dims.y() << ' ' << dims.z() << ")\n";
835   std::map<boxm2_block_id, boxm2_block_metadata>& blk = scene.blocks();
836   s << " blocks:==>\n";
837   for (auto & bit : blk) {
838     s << bit.second.id_ << ' ';
839     vgl_point_3d<double> org = bit.second.local_origin_;
840     s << ", org( " << org.x() << ' ' << org.y() << ' ' << org.z() << ") ";
841     vgl_vector_3d<double> dim = bit.second.sub_block_dim_;
842     s << ", dim( " << dim.x() << ' ' << dim.y() << ' ' << dim.z() << ") ";
843     vgl_vector_3d<unsigned> num = bit.second.sub_block_num_;
844     s << ", num( " << num.x() << ' ' << num.y() << ' ' << num.z() << ")\n";
845   }
846   s << "<=====:end blocks\n";
847   return s;
848 }
849 
850 //: Binary write boxm2_scene to stream
vsl_b_write(vsl_b_ostream &,boxm2_scene const &)851 void vsl_b_write(vsl_b_ostream& /*os*/, boxm2_scene const& /*bit_scene*/) {}
852 //: Binary write boxm2_scene pointer to stream
vsl_b_write(vsl_b_ostream &,boxm2_scene * const &)853 void vsl_b_write(vsl_b_ostream& /*os*/, boxm2_scene* const& /*ph*/) {}
854 //: Binary write boxm2_scene smart pointer to stream
vsl_b_write(vsl_b_ostream &,boxm2_scene_sptr &)855 void vsl_b_write(vsl_b_ostream& /*os*/, boxm2_scene_sptr&) {}
856 //: Binary write boxm2_scene smart pointer to stream
vsl_b_write(vsl_b_ostream &,boxm2_scene_sptr const &)857 void vsl_b_write(vsl_b_ostream& /*os*/, boxm2_scene_sptr const&) {}
858 
859 //: Binary load boxm scene from stream.
vsl_b_read(vsl_b_istream &,boxm2_scene &)860 void vsl_b_read(vsl_b_istream& /*is*/, boxm2_scene& /*bit_scene*/) {}
861 //: Binary load boxm scene pointer from stream.
vsl_b_read(vsl_b_istream &,boxm2_scene *)862 void vsl_b_read(vsl_b_istream& /*is*/, boxm2_scene* /*ph*/) {}
863 //: Binary load boxm scene smart pointer from stream.
vsl_b_read(vsl_b_istream &,boxm2_scene_sptr &)864 void vsl_b_read(vsl_b_istream& /*is*/, boxm2_scene_sptr&) {}
865 //: Binary load boxm scene smart pointer from stream.
vsl_b_read(vsl_b_istream &,boxm2_scene_sptr const &)866 void vsl_b_read(vsl_b_istream& /*is*/, boxm2_scene_sptr const&) {}
867 
868 //: Binary write boxm2_scene_info_wrapper to stream
vsl_b_write(vsl_b_ostream &,boxm2_scene_info_wrapper const &)869 void vsl_b_write(vsl_b_ostream& /*os*/, boxm2_scene_info_wrapper const&) {}
870 //: Binary write boxm2_scene_info_wrapper pointer to stream
vsl_b_write(vsl_b_ostream &,const boxm2_scene_info_wrapper * &)871 void vsl_b_write(vsl_b_ostream& /*os*/, const boxm2_scene_info_wrapper* &) {}
872 //: Binary write boxm2_scene_info_wrapper smart pointer to stream
vsl_b_write(vsl_b_ostream &,boxm2_scene_info_wrapper_sptr &)873 void vsl_b_write(vsl_b_ostream& /*os*/, boxm2_scene_info_wrapper_sptr&) {}
874 //: Binary write boxm2_scene_info_wrapper smart pointer to stream
vsl_b_write(vsl_b_ostream &,boxm2_scene_info_wrapper_sptr const &)875 void vsl_b_write(vsl_b_ostream& /*os*/, boxm2_scene_info_wrapper_sptr const&) {}
876 
877 //: Binary load boxm2_scene_info_wrapper from stream.
vsl_b_read(vsl_b_istream &,boxm2_scene_info_wrapper &)878 void vsl_b_read(vsl_b_istream& /*is*/, boxm2_scene_info_wrapper &) {}
879 //: Binary load boxm2_scene_info_wrapper pointer from stream.
vsl_b_read(vsl_b_istream &,boxm2_scene_info_wrapper *)880 void vsl_b_read(vsl_b_istream& /*is*/, boxm2_scene_info_wrapper*) {}
881 //: Binary load boxm2_scene_info_wrapper smart pointer from stream.
vsl_b_read(vsl_b_istream &,boxm2_scene_info_wrapper_sptr &)882 void vsl_b_read(vsl_b_istream& /*is*/, boxm2_scene_info_wrapper_sptr&) {}
883 //: Binary load boxm2_scene_info_wrapper smart pointer from stream.
vsl_b_read(vsl_b_istream &,boxm2_scene_info_wrapper_sptr const &)884 void vsl_b_read(vsl_b_istream& /*is*/, boxm2_scene_info_wrapper_sptr const&) {}
885