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