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