1 // This is contrib/brl/bbas/volm/exe/volm_create_bvxm_scene.cxx
2 //:
3 // \file
4 // \brief  executable create candidate regions for each geo index leaf.  For each leaf, it will output
5 //         the outer contour polygon and inner counter polygon, as binary format
6 //
7 // \author Yi Dong
8 // \date October 20, 2014
9 // \verbatim
10 //  Modifications
11 // \endverbatim
12 //
13 #include "vul/vul_file.h"
14 #include "vul/vul_arg.h"
15 #include "vgl/vgl_intersection.h"
16 #include <vgl/io/vgl_io_polygon.h>
17 #include <bkml/bkml_write.h>
18 #include <bkml/bkml_parser.h>
19 #include <volm/volm_io.h>
20 #include <volm/volm_candidate_region_parser.h>
21 #include <volm/volm_geo_index.h>
22 #include <volm/volm_geo_index_sptr.h>
23 #include <volm/volm_loc_hyp.h>
24 #include <volm/volm_loc_hyp_sptr.h>
25 #include <volm/volm_tile.h>
26 #include <volm/volm_utils.h>
27 #include <volm/volm_candidate_list.h>
28 
29 static void write_out_polygon(std::string const& out_folder, std::string const& region_str, std::string const& leaf_str_pre, vgl_polygon<double> const& poly);
30 
main(int argc,char ** argv)31 int main(int argc, char** argv)
32 {
33   // inputs
34   vul_arg<unsigned>      world_id("-world", "ROI world id", 9999);
35   vul_arg<std::string>  geo_folder("-geo", "folder to read the geo hypotheses", "");
36   vul_arg<std::string>   cand_file("-cand", "candidate region kml file", "");
37   vul_arg<std::string>  out_folder("-out", "output folder", "");
38   vul_arg<std::string> region_name("-name", "candidate region name.  Default -- \"Region\"", "Region");
39   vul_arg<bool>         use_inner("-inner", "option to use inner boundary", false);
40   vul_arg<bool>            is_kml("-kml", "option to generate output kml", false);
41   vul_arg<unsigned>       tile_id("-tile", "ROI tile id", 9999);
42   vul_arg<int>            leaf_id("-leaf", "leaf id to generate kml file from parsed candidate region", -1);
43   vul_arg_parse(argc, argv);
44 
45   // input check
46   if (geo_folder().compare("") == 0 || out_folder().compare("") == 0)
47   {
48     vul_arg_display_usage_and_exit();
49     return volm_io::EXE_ARGUMENT_ERROR;
50   }
51   std::string log_file = out_folder() + "/log_candidate_region.xml";
52   std::stringstream log;
53 
54   if (!is_kml())  // create candidate polygon for each tile
55   {
56     // get all possible tiles for given world
57     std::vector<volm_tile> tiles;
58     if (!volm_tile::generate_tiles(world_id(), tiles)) {
59       log << "ERROR: unknown ROI world id: " << world_id() << "!\n";
60       volm_io::write_error_log(log_file, log.str());  return volm_io::EXE_ARGUMENT_ERROR;
61     }
62 
63     // parse the polygons from candidate region
64     if (!vul_file::exists(cand_file())) {
65       log << "ERROR: can not find candidate region kml file: " <<cand_file() << "!\n";
66       volm_io::write_error_log(log_file, log.str());  return volm_io::EXE_ARGUMENT_ERROR;
67     }
68     std::cout << "============  Start to create candidate region for each geo leaf ============\n";
69     std::cout << "  parsing candidate polygon from kml file: " << cand_file() << "..." << std::endl;
70     vgl_polygon<double> outer;
71     vgl_polygon<double> inner;
72     unsigned n_out, n_in;
73     vgl_polygon<double> poly_all = volm_candidate_region_parser::parse_polygon_with_inner(cand_file(), region_name(), outer, inner, n_out, n_in);
74     std::cout << "    " << outer.num_sheets() << " candidate region are parsed\n";
75     std::cout << "    " << inner.num_sheets() << " inner contour are parsed\n";
76 
77     // loop over each tile
78     for (unsigned tile_id = 0; tile_id < tiles.size(); tile_id++)
79     {
80       std::stringstream file_name_pre;
81       file_name_pre << geo_folder() << "/geo_index_tile_" << tile_id;
82       // ignore tile if there is not geo location database for current tile
83       if (!vul_file::exists(file_name_pre.str()+".txt"))
84         continue;
85       std::cout << "  Creating candidate region for each leaf in tile " << tile_id << "...\n";
86       float min_size;
87       volm_geo_index_node_sptr root = volm_geo_index::read_and_construct(file_name_pre.str()+".txt", min_size);
88       volm_geo_index::read_hyps(root, file_name_pre.str());
89       std::vector<volm_geo_index_node_sptr> loc_leaves;
90       loc_leaves.clear();
91       volm_geo_index::get_leaves_with_hyps(root, loc_leaves);
92       std::cout << "    " << loc_leaves.size() << " location leaves exist for tile " << tile_id << std::endl;
93       // create candidate polygon for each leaf
94       unsigned n_leaf = loc_leaves.size();
95       for (unsigned l_idx = 0; l_idx < n_leaf; l_idx++)
96       {
97         volm_geo_index_node_sptr leaf = loc_leaves[l_idx];
98         std::cout << '.' << std::flush;
99         // form the outer region
100         // check whether there is an outer region covers the entire leaf
101         bool found = false;
102         for (unsigned s_idx = 0; (s_idx < n_out && !found); s_idx++)
103         {
104           if (volm_utils::poly_contains(outer[s_idx], leaf->extent_)) {
105             found = true;
106             // write out the polygon
107             vgl_polygon<double> leaf_out(outer[s_idx]);
108             write_out_polygon(out_folder(), "outer", leaf->get_string(), leaf_out);
109           }
110         }
111         // obtain all outer region that intersects with leaf
112         if (!found) {
113           vgl_polygon<double> leaf_out;
114           for (unsigned s_idx = 0; s_idx < n_out; s_idx++) {
115             vgl_polygon<double> single_sheet(outer[s_idx]);
116             if (vgl_intersection(leaf->extent_, single_sheet))
117               leaf_out.push_back(outer[s_idx]);
118           }
119           // write out the polygon
120           write_out_polygon(out_folder(), "outer", leaf->get_string(), leaf_out);
121         }
122         // form the inner region if necessary
123         if (use_inner()) {
124           // check whether there is an inner region covers the entire leaf
125           bool found = false;
126           for (unsigned s_idx = 0; (s_idx < n_in && !found); s_idx++) {
127             if (volm_utils::poly_contains(inner[s_idx], leaf->extent_)) {
128               found = true;
129               // write out the polygon
130               vgl_polygon<double> leaf_in(inner[s_idx]);
131               write_out_polygon(out_folder(), "inner", leaf->get_string(), leaf_in);
132             }
133           }
134           if (!found) {
135             vgl_polygon<double> leaf_in;
136             for (unsigned s_idx = 0; s_idx < n_in; s_idx++) {
137               vgl_polygon<double> single_sheet(inner[s_idx]);
138               if (vgl_intersection(leaf->extent_, single_sheet))
139                 leaf_in.push_back(inner[s_idx]);
140             }
141             // write out the inner polygon
142             write_out_polygon(out_folder(), "inner", leaf->get_string(), leaf_in);
143           }
144         }
145       } // end of loop over each leaf in a tile
146       std::cout << '\n';
147     } // end of loop over each tile
148     return volm_io::SUCCESS;
149   }
150   else  // visualize the candidate region for given leaf and tile
151   {
152     std::cout << "============  Start to visualize the candidate region for tile " << tile_id() << ", leaf " << leaf_id() << " ============\n";
153     // load the geo index for given leaf and tile
154     std::stringstream file_name_pre;
155     file_name_pre << geo_folder() << "/geo_index_tile_" << tile_id();
156     if (!vul_file::exists(file_name_pre.str()+".txt")) {
157       log << "ERROR: can not find file " << file_name_pre.str() << ".txt for tile " << tile_id() << "\n!";
158       volm_io::write_error_log(log_file, log.str());  return volm_io::EXE_ARGUMENT_ERROR;
159     }
160     float min_size;
161     volm_geo_index_node_sptr root = volm_geo_index::read_and_construct(file_name_pre.str()+".txt", min_size);
162     volm_geo_index::read_hyps(root, file_name_pre.str());
163     std::vector<volm_geo_index_node_sptr> loc_leaves;
164     loc_leaves.clear();
165     volm_geo_index::get_leaves_with_hyps(root, loc_leaves);
166     if (leaf_id() < 0 || leaf_id() >= loc_leaves.size()) {
167       log << "ERROR: input leaf id " << leaf_id() << " is incorrect!\n";
168       volm_io::write_error_log(log_file, log.str());  return volm_io::EXE_ARGUMENT_ERROR;
169     }
170     volm_geo_index_node_sptr leaf = loc_leaves[leaf_id()];
171     // load the created candidate region
172     std::string outer_region_file = out_folder() + "/cand_region_outer_" + leaf->get_string() + ".bin";
173     if (!vul_file::exists(outer_region_file)) {
174       std::cout << "leaf " << leaf->extent_ << " is outside of candidate region" << std::endl;
175       return volm_io::SUCCESS;
176     }
177     vgl_polygon<double> outer;
178     vsl_b_ifstream ifs_out(outer_region_file);
179     vsl_b_read(ifs_out, outer);
180     ifs_out.close();
181     // load the inner region if exists
182     std::string inner_region_file = out_folder() + "/cand_region_inner_" + leaf->get_string() + ".bin";
183     vgl_polygon<double> inner;
184     inner.clear();
185     if (vul_file::exists(inner_region_file)) {
186       vsl_b_ifstream ifs_in(inner_region_file);
187       vsl_b_read(ifs_in, inner);
188       ifs_in.close();
189     }
190     std::string kml_file = out_folder() + "/cand_region_" + leaf->get_string() + ".kml";
191     std::ofstream ofs(kml_file.c_str());
192     bkml_write::open_document(ofs);
193     // write out the kml file
194     if (inner.num_sheets() == 0) {
195 
196       std::stringstream name;
197       name << "leaf_" << leaf_id() << "_cand_" << outer.num_sheets();
198       bkml_write::write_polygon(ofs, outer, name.str(), "", 1.0, 3.0, 0.45, 0, 255, 0);
199     }
200     else {
201       // form the polygon pair
202       std::vector<std::pair<vgl_polygon<double>, vgl_polygon<double> > > cand_poly;
203       for (unsigned s_idx = 0; s_idx < outer.num_sheets(); s_idx++) {
204         vgl_polygon<double> inside = volm_utils::poly_contains(outer[s_idx], inner);
205         std::pair<vgl_polygon<double>, vgl_polygon<double> > cand_region(vgl_polygon<double>(outer[s_idx]), inside);
206         cand_poly.push_back(cand_region);
207       }
208       // write out the kml file
209       std::stringstream name;
210       name << "leaf_" << leaf_id() << "_cand_" << cand_poly.size();
211       bkml_write::write_polygon(ofs, cand_poly, name.str(), "", 1.0, 3.0, 0.45, 0, 255, 0);
212     }
213 
214     // write the location hypotheses into kml file for visualization
215     if (volm_utils::poly_contains(outer, leaf->extent_) && inner.num_sheets() == 0) {
216       // the leaf is entirely inside the candidate region, put all loc into kml
217       std::cout << leaf->hyps_->locs_.size() << " locations are inside candidate region" << std::endl;
218       vgl_point_3d<double> h_pt;
219       while ( leaf->hyps_->get_next(0, 1, h_pt) ) {
220         std::stringstream loc_name;
221         loc_name << "hyps_" << std::setprecision(6) << h_pt.x() << std::setprecision(6) << h_pt.y();
222         bkml_write::write_location_as_box(ofs, h_pt.x(), h_pt.y(), h_pt.z(), loc_name.str(), "", 1E-5, 255, 131, 250);
223       }
224 
225     }
226     else {
227       vgl_point_3d<double> h_pt;
228       unsigned cnt = 0;
229       while ( leaf->hyps_->get_next(0, 1, h_pt) ) {
230         if (volm_candidate_list::inside_candidate_region(inner, outer, h_pt.x(), h_pt.y())) {
231           cnt++;
232           std::stringstream loc_name;
233           loc_name << "hyps_" << std::setprecision(6) << h_pt.x() << std::setprecision(6) << h_pt.y();
234           bkml_write::write_location_as_box(ofs, h_pt.x(), h_pt.y(), h_pt.z(), loc_name.str(), "", 2E-5, 255, 131, 250);
235         }
236       }
237       std::cout << cnt << " locations are inside candidate region" << std::endl;
238     }
239     bkml_write::close_document(ofs);
240     ofs.close();
241     return volm_io::SUCCESS;;
242   }
243   return volm_io::SUCCESS;
244 }
245 
246 #if 0
247   // inputs
248   vul_arg<unsigned>   tile_id("-tile", "ROI tile_id", 9999);
249   vul_arg<std::string> geo_folder("-geo", "folder to read the geo hypotheses", "");
250   vul_arg<std::string>  cand_file("-cand", "candidate region kml file", "");
251   vul_arg<std::string> out_folder("-out", "output folder", "");
252   vul_arg<std::string> region_name("-name", "candidate region name.  Default -- \"Region\"", "Region");
253   vul_arg<bool>       use_inner("-inner", "option to use inner boundary", false);
254   vul_arg<bool>       is_kml("-kml", "option to generate output kml", false);
255   vul_arg<int>       leaf_id("-leaf", "leaf id to generate kml file from parsed candidate region", -1);
256   vul_arg_parse(argc, argv);
257   // input check
258   if (geo_folder().compare("") == 0 || out_folder().compare("") == 0 || tile_id() == 9999)
259   {
260     vul_arg_display_usage_and_exit();
261     return volm_io::EXE_ARGUMENT_ERROR;
262   }
263 
264   // load geo location
265   std::stringstream file_name_pre;
266   file_name_pre << geo_folder() << "/geo_index_tile_" << tile_id();
267   if (!vul_file::exists(file_name_pre.str()+".txt")) {
268     log << "ERROR: can not find file " << file_name_pre.str() << ".txt for tile " << tile_id() << "\n!";
269     volm_io::write_error_log(log_file, log.str());  return volm_io::EXE_ARGUMENT_ERROR;
270   }
271   float min_size;
272   volm_geo_index_node_sptr root = volm_geo_index::read_and_construct(file_name_pre.str()+".txt", min_size);
273   volm_geo_index::read_hyps(root, file_name_pre.str());
274   std::vector<volm_geo_index_node_sptr> loc_leaves;
275   loc_leaves.clear();
276   volm_geo_index::get_leaves_with_hyps(root, loc_leaves);
277   std::cout << loc_leaves.size() << " location leaves exist for tile " << tile_id() << std::endl;
278 
279   if (!is_kml())  // create candidate polygon for each leaf
280   {
281     // parse the polygons from candidate region
282     if (!vul_file::exists(cand_file())) {
283       log << "ERROR: can not find candidate region kml file: " <<cand_file() << "!\n";
284       volm_io::write_error_log(log_file, log.str());  return volm_io::EXE_ARGUMENT_ERROR;
285     }
286     std::cout << "============  START!!!! ============\n";
287     std::cout << "  parsing candidate polygon from kml file: " << cand_file() << "..." << std::endl;
288     vgl_polygon<double> outer;
289     vgl_polygon<double> inner;
290     unsigned n_out, n_in;
291     vgl_polygon<double> poly_all = volm_candidate_region_parser::parse_polygon_with_inner(cand_file(), region_name(), outer, inner, n_out, n_in);
292     std::cout << "    " << outer.num_sheets() << " candidate region are parsed\n";
293     std::cout << "    " << inner.num_sheets() << " inner contour are parsed\n";
294 
295     // create candidate polygon for each leaf
296     unsigned n_leaf = loc_leaves.size();
297     for (unsigned l_idx = 0; l_idx < n_leaf; l_idx++) {
298       volm_geo_index_node_sptr leaf = loc_leaves[l_idx];
299       std::cout << "    generate candidate region for leaf " << l_idx << " -- " << leaf->extent_ << "..." << std::endl;
300       // form the outer region
301       // check whether there is an outer region covers the entire leaf
302       bool found = false;
303       for (unsigned s_idx = 0; (s_idx < n_out && !found); s_idx++) {
304         if (volm_utils::poly_contains(outer[s_idx], leaf->extent_)) {
305           found = true;
306           // write out the polygon
307           vgl_polygon<double> leaf_out(outer[s_idx]);
308           write_out_polygon(out_folder(), "outer", leaf->get_string(), leaf_out);
309         }
310       }
311       // obtain all outer region that intersects with leaf
312       if (!found) {
313         vgl_polygon<double> leaf_out;
314         for (unsigned s_idx = 0; s_idx < n_out; s_idx++) {
315           vgl_polygon<double> single_sheet(outer[s_idx]);
316           if (vgl_intersection(leaf->extent_, single_sheet))
317             leaf_out.push_back(outer[s_idx]);
318         }
319         // write out the polygon
320         write_out_polygon(out_folder(), "outer", leaf->get_string(), leaf_out);
321       }
322 
323       // form the inner region if necessary
324       if (use_inner()) {
325         // check whether there is an inner region covers the entire leaf
326         bool found = false;
327         for (unsigned s_idx = 0; (s_idx < n_in && !found); s_idx++) {
328           if (volm_utils::poly_contains(inner[s_idx], leaf->extent_)) {
329             found = true;
330             // write out the polygon
331             vgl_polygon<double> leaf_in(inner[s_idx]);
332             write_out_polygon(out_folder(), "inner", leaf->get_string(), leaf_in);
333           }
334         }
335         if (!found) {
336           vgl_polygon<double> leaf_in;
337           for (unsigned s_idx = 0; s_idx < n_in; s_idx++) {
338             vgl_polygon<double> single_sheet(inner[s_idx]);
339             if (vgl_intersection(leaf->extent_, single_sheet))
340               leaf_in.push_back(inner[s_idx]);
341           }
342           // write out the inner polygon
343           write_out_polygon(out_folder(), "inner", leaf->get_string(), leaf_in);
344         }
345       }
346     } // end of the loop over each leaf
347     return volm_io::SUCCESS;
348   }
349   else  // read the created polygon for given leaf
350   {
351     std::cout << "  generate candidate region kml for leaf " << leaf_id() << std::endl;
352     // obtain the desired leaf
353     if (leaf_id() < 0 || leaf_id() >= loc_leaves.size()) {
354       log << "ERROR: input leaf id " << leaf_id() << " is incorrect!\n";
355       volm_io::write_error_log(log_file, log.str());  return volm_io::EXE_ARGUMENT_ERROR;
356     }
357     volm_geo_index_node_sptr leaf = loc_leaves[leaf_id()];
358     // load the created candidate region
359     std::string outer_region_file = out_folder() + "/cand_region_outer_" + leaf->get_string() + ".bin";
360     if (!vul_file::exists(outer_region_file)) {
361       std::cout << "leaf " << leaf->extent_ << " is outside of candidate region" << std::endl;
362       return volm_io::SUCCESS;
363     }
364     vgl_polygon<double> outer;
365     vsl_b_ifstream ifs_out(outer_region_file);
366     vsl_b_read(ifs_out, outer);
367     ifs_out.close();
368     // load the inner region if exists
369     std::string inner_region_file = out_folder() + "/cand_region_inner_" + leaf->get_string() + ".bin";
370     vgl_polygon<double> inner;
371     inner.clear();
372     if (vul_file::exists(inner_region_file)) {
373       vsl_b_ifstream ifs_in(inner_region_file);
374       vsl_b_read(ifs_in, inner);
375       ifs_in.close();
376     }
377     std::string kml_file = out_folder() + "/cand_region_" + leaf->get_string() + ".kml";
378     std::ofstream ofs(kml_file.c_str());
379     bkml_write::open_document(ofs);
380     // write out the kml file
381     if (inner.num_sheets() == 0) {
382 
383       std::stringstream name;
384       name << "leaf_" << leaf_id() << "_cand_" << outer.num_sheets();
385       bkml_write::write_polygon(ofs, outer, name.str(), "", 1.0, 3.0, 0.45, 0, 255, 0);
386     }
387     else {
388       // form the polygon pair
389       std::vector<std::pair<vgl_polygon<double>, vgl_polygon<double> > > cand_poly;
390       for (unsigned s_idx = 0; s_idx < outer.num_sheets(); s_idx++) {
391         vgl_polygon<double> inside = volm_utils::poly_contains(outer[s_idx], inner);
392         std::pair<vgl_polygon<double>, vgl_polygon<double> > cand_region(vgl_polygon<double>(outer[s_idx]), inside);
393         cand_poly.push_back(cand_region);
394       }
395       // write out the kml file
396       std::stringstream name;
397       name << "leaf_" << leaf_id() << "_cand_" << cand_poly.size();
398       bkml_write::write_polygon(ofs, cand_poly, name.str(), "", 1.0, 3.0, 0.45, 0, 255, 0);
399     }
400 
401     // write the location hypotheses into kml file for visualization
402     if (volm_utils::poly_contains(outer, leaf->extent_) && inner.num_sheets() == 0) {
403       // the leaf is entirely inside the candidate region, put all loc into kml
404       std::cout << leaf->hyps_->locs_.size() << " locations are inside candidate region" << std::endl;
405       vgl_point_3d<double> h_pt;
406       while ( leaf->hyps_->get_next(0, 1, h_pt) ) {
407         std::stringstream loc_name;
408         loc_name << "hyps_" << std::setprecision(6) << h_pt.x() << std::setprecision(6) << h_pt.y();
409         bkml_write::write_location_as_box(ofs, h_pt.x(), h_pt.y(), h_pt.z(), loc_name.str(), "", 1E-5, 255, 131, 250);
410       }
411 
412     }
413     else {
414       vgl_point_3d<double> h_pt;
415       unsigned cnt = 0;
416       while ( leaf->hyps_->get_next(0, 1, h_pt) ) {
417         if (volm_candidate_list::inside_candidate_region(inner, outer, h_pt.x(), h_pt.y())) {
418           cnt++;
419           std::stringstream loc_name;
420           loc_name << "hyps_" << std::setprecision(6) << h_pt.x() << std::setprecision(6) << h_pt.y();
421           bkml_write::write_location_as_box(ofs, h_pt.x(), h_pt.y(), h_pt.z(), loc_name.str(), "", 2E-5, 255, 131, 250);
422         }
423       }
424       std::cout << cnt << " locations are inside candidate region" << std::endl;
425     }
426     bkml_write::close_document(ofs);
427     ofs.close();
428     return volm_io::SUCCESS;;
429   }
430   return volm_io::SUCCESS;
431 }
432 #endif
433 
434 
write_out_polygon(std::string const & out_folder,std::string const & region_str,std::string const & leaf_str_pre,vgl_polygon<double> const & poly)435 void write_out_polygon(std::string const& out_folder, std::string const& region_str, std::string const& leaf_str_pre, vgl_polygon<double> const& poly)
436 {
437   if (poly.num_sheets() == 0)
438     return;
439   std::string out_file = out_folder + "/cand_region_" + region_str + "_" + leaf_str_pre + ".bin";
440   vsl_b_ofstream ofs(out_file);
441   vsl_b_write(ofs, poly);
442   ofs.close();
443 }
444