1 #ifndef boxm2_scene_h_
2 #define boxm2_scene_h_
3 //:
4 // \file
5 // \brief  Boxm2 Scene models a very generic scene, only specifies dimensions
6 // \author Andrew Miller
7 // \date   26 Oct 2010
8 //
9 #include <iostream>
10 #include <iosfwd>
11 #include <vector>
12 #include <string>
13 #include <cassert>
14 #include <boxm2/basic/boxm2_block_id.h>
15 #include <boxm2/boxm2_block_metadata.h>
16 #include <vpgl/vpgl_lvcs.h>
17 #include <vgl/vgl_point_3d.h>
18 #include <vgl/vgl_box_3d.h>
19 #include <vgl/vgl_box_2d.h>
20 #ifdef _MSC_VER
21 #  include <vcl_msvc_warnings.h>
22 #endif
23 #include <vul/vul_file.h>
24 
25 //smart pointer stuff
26 #include <vbl/vbl_ref_count.h>
27 #include <vbl/vbl_smart_ptr.h>
28 
29 //vpgl camera
30 #include <vpgl/vpgl_generic_camera.h>
31 #include <vpgl/vpgl_perspective_camera.h>
32 #include <vpgl/vpgl_affine_camera.h>
33 
34 
35 //: block info that can be easily made into a buffer and sent to gpu
36 struct boxm2_scene_info
37 {
38   //world information
39   float    scene_origin[4];          // scene origin (point)
40   int      scene_dims[4];            // number of blocks in each dimension
41   float    block_len;                // size of each block (can only be 1 number now that we've established blocks are cubes)
42   float    epsilon;                  // block_len/100.0 (placed here to avoid using a register)
43   float    pinit;
44   // tree meta information
45   int      root_level;               // root_level of trees
46   int      num_buffer;               // number of buffers (both data and tree)
47   int      tree_buffer_length;       // length of tree buffer (number of cells/trees)
48   int      data_buffer_length;       // length of data buffer (number of cells)
49 };
50 
51 class boxm2_scene_info_wrapper : public vbl_ref_count
52 {
53   public:
54     boxm2_scene_info * info;
55 };
56 //Smart_Pointer typedef for boxm2_scene
57 class boxm2_scene;
58 typedef vbl_smart_ptr<boxm2_scene> boxm2_scene_sptr;
59 typedef vbl_smart_ptr<boxm2_scene_info_wrapper> boxm2_scene_info_wrapper_sptr;
60 
61 //: boxm2_scene: simple scene model that maintains (in world coordinates)
62 //      - scene origin
63 //      - number of blocks in each dimension
64 //      - size of each block in each dimension
65 //      - lvcs information
66 //      - xml path on disk and data path (directory) on disk
67 class boxm2_scene : public vbl_ref_count
68 {
69   public:
70     //: empty scene, needs to be initialized manually
boxm2_scene()71     boxm2_scene() {boxm2_scene::get_count()++;}
72 
73     boxm2_scene(std::string const& data_path, vgl_point_3d<double> const& origin, int version = 2);
74 
75     //: create a scene with a single block
76     // scene_dir      - path to scene directory
77     // scene_name     - path to xml file is scene_dir + scene_name.xml
78     // data_path      - binary data is stored in scene_dir + data_path
79     // prefixes       - the set of prefix strings defining the databases stored in the model(appearances)
80     // scene_box      - the 3-d bounding box for the scene in global coordinates
81     // sub_block_len  - the length of the octree block (sub_block) assumed to be a cube
82     // init/max level - the number of levels in the refined tree
83     // max_mb         - the maximum storage for a block (not typically used)
84     // p_init         - the initial probability of surface occupancy
85     // n_illum_bins   - number of illumination bins
86     // version        - scene format version
87     boxm2_scene(std::string const& scene_dir, std::string const& scene_name, std::string const& data_path, std::vector<std::string> const& prefixes,
88                 vgl_box_3d<double> const& scene_box, double sub_block_len, int init_level = 1,
89                 int max_level = 4, double max_mb=1200, double p_init=0.001, int n_illum_bins = 1, int version = 2);
90 
91     //: initializes the scene from the buffer that loaded an XML file in.
92     // this is added for decoupling from the local filesystem to load the scene
93     boxm2_scene(const char* buffer);
94 
95     //: initializes scene from xmlFile
96     boxm2_scene(std::string const& filename);
97 
98     //: copy constructor
99     boxm2_scene(boxm2_scene const& other_scene);
100 
101     //: destructor
102     ~boxm2_scene() override = default;
103 
104     //:create an in-memory copy of the scene with unique id
105     boxm2_scene_sptr clone_no_disk();
106 
107     //: save scene xml file
108     void save_scene();
109 
110     //: return a vector of block ids in visibility order
111     std::vector<boxm2_block_id> get_vis_blocks(vpgl_generic_camera<double>* cam, double dist = -1.0);
112     std::vector<boxm2_block_id> get_vis_blocks(vpgl_perspective_camera<double>* cam, double dist = -1.0);
113     std::vector<boxm2_block_id> get_vis_blocks(vpgl_affine_camera<double>* cam);
114     std::vector<boxm2_block_id> get_vis_blocks(vpgl_camera_double_sptr & cam, double dist = -1.0) {
115       if ( cam->type_name() == "vpgl_generic_camera" )
116         return this->get_vis_blocks( (vpgl_generic_camera<double>*) cam.ptr(), dist );
117       else if ( cam->type_name() == "vpgl_perspective_camera" )
118         return this->get_vis_blocks( (vpgl_perspective_camera<double>*) cam.ptr(), dist );
119       else if ( cam->type_name() == "vpgl_affine_camera" )
120         return this->get_vis_blocks( (vpgl_affine_camera<double>*) cam.ptr() );
121       else
122         std::cout<<"boxm2_scene::get_vis_blocks doesn't support camera type "<<cam->type_name()<<std::endl;
123       //else return empty
124       std::vector<boxm2_block_id> empty;
125       return empty;
126     }
127     //: visibility order from point, blocks must intersect with cam box
128     std::vector<boxm2_block_id>
129     get_vis_order_from_pt(vgl_point_3d<double> const& pt,
130                           vgl_box_2d<double> camBox = vgl_box_2d<double>(), double distance=-1.0);
131     std::vector<boxm2_block_id> get_vis_blocks_opt(vpgl_perspective_camera<double>* cam, unsigned int ni, unsigned int nj);
132     //: visibility order using a ray given by origin and direction vector, the block needs to be in the front direction as given by this ray
133     std::vector<boxm2_block_id>
134     get_vis_order_from_ray(vgl_point_3d<double> const& origin, vgl_vector_3d<double> const& dir, double distance);
135 
136     //: return all blocks with center less than dist from the given point
137     std::vector<boxm2_block_id> get_vis_blocks(vgl_point_3d<double> const& pt, double dist);
138 
139     //: return a heap pointer to a scene info
140     boxm2_scene_info* get_blk_metadata(boxm2_block_id const& id);
block_exists(boxm2_block_id const & id)141     bool block_exists(boxm2_block_id const& id) const { return blocks_.find(id) != blocks_.end(); }
block_on_disk(boxm2_block_id const & id)142     bool block_on_disk(boxm2_block_id const& id) const { return vul_file::exists( data_path_ + id.to_string() + ".bin"); }
data_on_disk(boxm2_block_id const & id,std::string const & data_type)143     bool data_on_disk(boxm2_block_id const& id, std::string const& data_type) {
144       return vul_file::exists(data_path_ + data_type + "_" + id.to_string() + ".bin");
145     }
146 
147     //: a list of block metadata...
blocks()148     std::map<boxm2_block_id, boxm2_block_metadata>& blocks() { return blocks_; }
num_blocks()149     unsigned num_blocks() const { return (unsigned) blocks_.size(); }
150 
151     float finest_resolution();
152     //: mutable reference
get_block_metadata(boxm2_block_id const & id)153     boxm2_block_metadata& get_block_metadata(boxm2_block_id const& id)
154     {
155         assert(blocks_.find(id) != blocks_.end());
156         return blocks_[id];
157     }
158     //: const so return a copy
159     boxm2_block_metadata get_block_metadata_const(boxm2_block_id const& id) const;
160 
161     //: return number of trees in block
num_trees_in_block(boxm2_block_id const & id)162     int num_trees_in_block(boxm2_block_id const& id) {
163       assert(blocks_.find(id) != blocks_.end());
164       boxm2_block_metadata& d = blocks_[id];
165       return d.sub_block_num_.x() * d.sub_block_num_.y() * d.sub_block_num_.z();
166     }
167 
168     std::vector<boxm2_block_id> get_block_ids() const;
169 
170     //: gets a tight bounding box for the scene
171     vgl_box_3d<double>      bounding_box() const;
172     //: gets a tight bounding box for the scene
173     vgl_box_3d<int>         bounding_box_blk_ids() const;
174 
175     //: gets the smallest block index in all dimensions
176     void min_block_index(vgl_point_3d<int> &idx,
177                          vgl_point_3d<double> &local_origin) const;
178     //: gets max block index in all dims
179     void max_block_index(vgl_point_3d<int> &idx,
180                          vgl_point_3d<double> &local_origin) const;
181 
182     // returns the dimesnsion of the scene grid where each grid element is a block
183     vgl_vector_3d<unsigned int>   scene_dimensions() const;
184 
185     //: If a block contains a 3-d point, set the local coordinates of the point
186     bool block_contains(vgl_point_3d<double> const& p, boxm2_block_id const& bid,
187                         vgl_point_3d<double>& local_coords) const;
188 
189     //: If a scene contains a 3-d point, set the block id, else return false. The local coordinates of the point are also returned
190     bool contains(vgl_point_3d<double> const& p, boxm2_block_id& bid,
191                   vgl_point_3d<double>& local_coords) const;
192 
193     //: scene dimensions accessors
local_origin()194     vgl_point_3d<double>    local_origin()const { return local_origin_; }
rpc_origin()195     vgl_point_3d<double>    rpc_origin()  const { return rpc_origin_; }
lvcs()196     vpgl_lvcs               lvcs()        const { return lvcs_; }
197 
198     //: scene path accessors
xml_path()199     std::string              xml_path()    const { return xml_path_; }
data_path()200     std::string              data_path()   const { return data_path_; }
201 
202     //: appearance model accessor
appearances()203     std::vector<std::string> appearances()  const { return appearances_; }
204     bool has_data_type(std::string const& data_type);
num_illumination_bins()205     int num_illumination_bins() const {return num_illumination_bins_;}
206 
207     //: scene version number
version()208     int version() const { return version_; }
set_version(int v)209     void set_version(int v) { version_ = v; }
210     //: unique scene id
id()211     unsigned id() const {return id_;}
212     //: scene mutators
set_local_origin(vgl_point_3d<double> org)213     void set_local_origin(vgl_point_3d<double> org) { local_origin_ = org; }
set_rpc_origin(vgl_point_3d<double> rpc)214     void set_rpc_origin(vgl_point_3d<double> rpc)   { rpc_origin_ = rpc; }
set_lvcs(vpgl_lvcs lvcs)215     void set_lvcs(vpgl_lvcs lvcs)                   { lvcs_ = lvcs; }
set_blocks(std::map<boxm2_block_id,boxm2_block_metadata> blocks)216     void set_blocks(std::map<boxm2_block_id, boxm2_block_metadata> blocks) { blocks_ = blocks; }
217     void add_block_metadata(boxm2_block_metadata data);
set_appearances(std::vector<std::string> const & appearances)218     void set_appearances(std::vector<std::string> const& appearances){ this->appearances_ = appearances; }
set_num_illumination_bins(int num_bins)219     void set_num_illumination_bins(int num_bins) { this->num_illumination_bins_ = num_bins; }
220 
221     //: scene path mutators
set_xml_path(std::string const & path)222     void set_xml_path(std::string const& path)              { xml_path_ = path; }
set_data_path(std::string const & path)223     void set_data_path(std::string const& path)             { data_path_ = path+"/"; }
224 
225   private:
226     //: unique scene id
227     unsigned id_;
228     // count of constructed scenes to generate a unique id
229     static unsigned& get_count();
230     //: world scene information
231     vpgl_lvcs               lvcs_;
232     vgl_point_3d<double>    local_origin_;
233     vgl_point_3d<double>    rpc_origin_;
234 
235     //: location on disk of xml file and data/block files
236     std::string data_path_, xml_path_;
237 
238     //: list of block meta data available to this scene
239     std::map<boxm2_block_id, boxm2_block_metadata> blocks_;
240 
241     //: list of appearance models/observation models used by this scene
242     std::vector<std::string> appearances_;
243     int num_illumination_bins_;
244     int version_;
245 
246     bool is_block_visible(boxm2_block_metadata & data, vpgl_camera<double> const& cam, unsigned ni, unsigned nj );
247 };
248 
249 
250 //: utility class for sorting id's by their distance
251 class boxm2_dist_id_pair
252 {
253   public:
boxm2_dist_id_pair(double dist,boxm2_block_id const & id)254     boxm2_dist_id_pair(double dist, boxm2_block_id const& id) : dist_(dist), id_(id) {}
255     double dist_;
256     boxm2_block_id id_;
257 
258     inline bool operator < (boxm2_dist_id_pair const& v) const {
259       return dist_ < v.dist_;
260     }
261 };
262 
263 //: scene output stream operator
264 std::ostream& operator<<(std::ostream &s, boxm2_scene& scene);
265 
266 //: scene xml write function
267 void x_write(std::ostream &os, boxm2_scene& scene, std::string const& name);
268 
269 
270 //--- IO read/write for sptrs--------------------------------------------------
271 //: Binary write boxm2_scene scene to stream
272 void vsl_b_write(vsl_b_ostream& os, boxm2_scene const& scene);
273 void vsl_b_write(vsl_b_ostream& os, const boxm2_scene* &p);
274 void vsl_b_write(vsl_b_ostream& os, boxm2_scene_sptr& sptr);
275 void vsl_b_write(vsl_b_ostream& os, boxm2_scene_sptr const& sptr);
276 
277 //: Binary load boxm2_scene scene from stream.
278 void vsl_b_read(vsl_b_istream& is, boxm2_scene &scene);
279 void vsl_b_read(vsl_b_istream& is, boxm2_scene* p);
280 void vsl_b_read(vsl_b_istream& is, boxm2_scene_sptr& sptr);
281 void vsl_b_read(vsl_b_istream& is, boxm2_scene_sptr const& sptr);
282 
283 //: Binary write boxm2_scene scene to stream
284 void vsl_b_write(vsl_b_ostream& os, boxm2_scene_info_wrapper const& scene);
285 void vsl_b_write(vsl_b_ostream& os, const boxm2_scene_info_wrapper* &p);
286 void vsl_b_write(vsl_b_ostream& os, boxm2_scene_info_wrapper_sptr& sptr);
287 void vsl_b_write(vsl_b_ostream& os, boxm2_scene_info_wrapper_sptr const& sptr);
288 
289 //: Binary load boxm2_scene scene from stream.
290 void vsl_b_read(vsl_b_istream& is, boxm2_scene_info_wrapper &scene);
291 void vsl_b_read(vsl_b_istream& is, boxm2_scene_info_wrapper* p);
292 void vsl_b_read(vsl_b_istream& is, boxm2_scene_info_wrapper_sptr& sptr);
293 void vsl_b_read(vsl_b_istream& is, boxm2_scene_info_wrapper_sptr const& sptr);
294 
295 
296 #endif // boxm2_scene_h_
297