1 //:
2 // \file
3 // \brief executable to take a polygonal ROI and cover it with bvxm scenes with different lvcs's
4 //
5 // \author Ozge C. Ozcanli
6 // \date August 22, 2013
7 // \verbatim
8 // Modifications
9 // Yi Dong Feb-2014 modify it to use geo coordinated geo_index leaf size to define the scene size
10 // \endverbatim
11 //
12 #include <iostream>
13 #include <volm/volm_tile.h>
14 #ifdef _MSC_VER
15 # include "vcl_msvc_warnings.h"
16 #endif
17 #include <volm/volm_osm_objects.h>
18 #include <volm/volm_geo_index2.h>
19 #include <volm/volm_io.h>
20 #include <volm/volm_io_tools.h>
21 #include "vul/vul_file.h"
22 #include "vul/vul_arg.h"
23 #include <vcl_where_root_dir.h>
24 #include "vpgl/vpgl_lvcs.h"
25 #include <bkml/bkml_parser.h>
26 #include <volm/volm_loc_hyp_sptr.h>
27 #include <bvxm/bvxm_world_params.h>
28 #include <bkml/bkml_write.h>
29 #include "vpgl/vpgl_utm.h"
30
31
main(int argc,char ** argv)32 int main(int argc, char** argv)
33 {
34 // input
35 vul_arg<std::string> in_folder("-in", "input folder to read DEM files as .tif", "");
36 vul_arg<std::string> in_poly("-poly", "region polygon as kml, the scenes that cover this polygon will be created", "");
37 vul_arg<std::string> out_folder("-out", "folder to write xml files","");
38 vul_arg<std::string> lvcs_root("-lvcs", "folder to write lvcs files","");
39 vul_arg<std::string> world_root("-world_dir", "the world folder where bvxm vox binary will be stored","");
40 vul_arg<float> voxel_size("-vox", "size of voxel in meters", 1.0f);
41 vul_arg<float> world_size_input("-size", "the size of the world in meters", 500.0f);
42 vul_arg<float> height("-height", "the amount to be added on top of the terrain height to create the scene in meters", 0.0f);
43
44 vul_arg_parse(argc, argv);
45
46 // check input
47 if (in_folder().compare("") == 0 || in_poly().compare("") == 0 || out_folder().compare("") == 0 || world_root().compare("") == 0) {
48 std::cerr << " ERROR: input is missing!\n";
49 vul_arg_display_usage_and_exit();
50 return volm_io::EXE_ARGUMENT_ERROR;
51 }
52
53 std::string lvcs_folder;
54 if (lvcs_root() == "")
55 lvcs_folder = out_folder();
56 else
57 lvcs_folder = lvcs_root();
58
59 vgl_polygon<double> poly = bkml_parser::parse_polygon(in_poly());
60 std::cout << "outer poly has: " << poly[0].size() << std::endl;
61
62 // find the bbox of ROI from its polygon
63 vgl_box_2d<double> bbox_rect;
64 for (auto i : poly[0]) {
65 bbox_rect.add(i);
66 }
67 double square_size = (bbox_rect.width() >= bbox_rect.height()) ? bbox_rect.width() : bbox_rect.height();
68 vgl_box_2d<double> bbox(bbox_rect.min_point(), square_size, square_size, vgl_box_2d<double>::min_pos);
69
70 // truncate the world size from voxel size
71 double world_size = (unsigned)std::ceil(world_size_input()/voxel_size())*(double)voxel_size();
72
73 // from defined world size, calculate the min_size of the geoindex
74 vgl_point_2d<double> ll(bbox_rect.min_x(), bbox_rect.min_y());
75 vgl_point_2d<double> ur(bbox_rect.max_x(), bbox_rect.max_y());
76 vpgl_lvcs_sptr lvcs_ll = new vpgl_lvcs(ll.y(), ll.x(), 0.0, vpgl_lvcs::wgs84, vpgl_lvcs::DEG, vpgl_lvcs::METERS);
77 vpgl_lvcs_sptr lvcs_ur = new vpgl_lvcs(ur.y(), ur.x(), 0.0, vpgl_lvcs::wgs84, vpgl_lvcs::DEG, vpgl_lvcs::METERS);
78
79 double scale_ll_x, scale_ll_y, gz;
80 lvcs_ll->local_to_global(world_size, world_size, 0.0, vpgl_lvcs::wgs84, scale_ll_x, scale_ll_y, gz);
81 scale_ll_x -= ll.x(); scale_ll_y -= ll.y();
82 double scale_ur_x, scale_ur_y;
83 lvcs_ur->local_to_global(world_size, world_size, 0.0, vpgl_lvcs::wgs84, scale_ur_x, scale_ur_y, gz);
84 scale_ur_x -= ur.x();
85 scale_ur_y -= ur.y();
86 std::cout << " pre-defined world_size is " << world_size_input() << " and voxel size is " << voxel_size() << " actual world size is " << world_size << std::endl;
87 std::cout << " bounding box for input polygon: " << bbox_rect << " expending to square: " << bbox << std::endl;
88 std::cout << " ll: " << ll << " ---> " << " scale_x = " << scale_ll_x << " scale_y = " << scale_ll_y << std::endl;
89 std::cout << " ur: " << ur << " ---> " << " scale_x = " << scale_ur_x << " scale_y = " << scale_ur_y << std::endl;
90 std::set<double> scale_set;
91 scale_set.insert(scale_ur_x); scale_set.insert(scale_ur_y); scale_set.insert(scale_ll_x); scale_set.insert(scale_ll_y);
92 double min_size = *scale_set.begin();
93 std::cout << " given maximum allowed world size " << world_size_input() << " the min_size for geo index is: " << min_size << std::endl;
94
95 // create a geo index and use the leaves as scenes, use template param as volm_loc_hyp_sptr but it won't actually be used
96 volm_geo_index2_node_sptr root = volm_geo_index2::construct_tree<volm_loc_hyp_sptr>(bbox, min_size, poly);
97 std::string txt_filename = out_folder() + "/geo_index.txt";
98 volm_geo_index2::write(root, txt_filename, min_size);
99 std::string kml_filename = out_folder() + "/scene_geo_index.kml";
100 unsigned tree_depth = volm_geo_index2::depth(root);
101 //volm_geo_index2::write_to_kml(root, tree_depth, kml_filename);
102 std::vector<volm_geo_index2_node_sptr> leaves;
103 volm_geo_index2::get_leaves(root, leaves);
104 std::cout << "the geo-index quad tree for scene has " << leaves.size() << " leaves and depth is " << tree_depth << std::endl;
105
106 // write to kml files with leaf ids (which will be used as scene ids)
107 std::ofstream ofs(kml_filename.c_str());
108 bkml_write::open_document(ofs);
109 for (unsigned i = 0; i < leaves.size(); i++) {
110 std::stringstream explanation; explanation << "scene_" << i;
111 volm_geo_index2::write_to_kml_node(ofs, leaves[i], 0, 0, explanation.str());
112 }
113 bkml_write::close_document(ofs);
114
115 // load DEM images
116 std::vector<volm_img_info> infos;
117 volm_io_tools::load_aster_dem_imgs(in_folder(), infos);
118 std::cout << " loaded " << infos.size() << " DEM tiles!\n";
119
120 // create scenes for each leaf, note the scene size is different
121 double largest_dif = 0;
122 for (unsigned i = 0; i < leaves.size(); i++) {
123 std::stringstream name; name << out_folder() << "scene_" << i;
124 vgl_point_2d<double> lower_left = leaves[i]->extent_.min_point();
125 vgl_point_2d<double> upper_right = leaves[i]->extent_.max_point();
126 // find the maximum elevation difference
127 double min = 10000.0, max = -10000.0;
128 if (!volm_io_tools::find_min_max_height(lower_left, upper_right, infos, min, max)) {
129 std::cerr << " problems in the leaf: " << lower_left << " " << upper_right << " - cannot find height!\n";
130 return volm_io::EXE_ARGUMENT_ERROR;
131 }
132 double dif = max-min;
133 if (dif > largest_dif) largest_dif = dif;
134 //construct lvcs
135 vpgl_lvcs_sptr lvcs = new vpgl_lvcs(lower_left.y(), lower_left.x(), min, vpgl_lvcs::wgs84, vpgl_lvcs::DEG, vpgl_lvcs::METERS);
136 std::stringstream name_lvcs; name_lvcs << lvcs_folder << "/scene_" << i;
137 std::string lvcs_name = name_lvcs.str() + ".lvcs";
138 std::ofstream ofs(lvcs_name.c_str());
139 if (!ofs) {
140 std::cerr << "Cannot open file: " << lvcs_name << "!\n";
141 return volm_io::EXE_ARGUMENT_ERROR;
142 }
143 lvcs->write(ofs);
144 ofs.close();
145
146 // create scene based on leaf size in lat/lon
147 vgl_point_3d<float> corner(0.0f, 0.0f, 0.0f);
148 double lx, ly, lz;
149 lvcs->global_to_local(upper_right.x(), upper_right.y(), height()+max, vpgl_lvcs::wgs84, lx, ly, lz);
150 auto dim_x = (unsigned)std::ceil(lx/voxel_size());
151 auto dim_y = (unsigned)std::ceil(ly/voxel_size());
152 auto dim_z = (unsigned)std::ceil(height()+dif);
153 vgl_vector_3d<unsigned> num_voxels(dim_x, dim_y, dim_z);
154 bvxm_world_params params;
155 std::stringstream world_dir;
156 world_dir << world_root() << "/scene_" << i;
157 if (!vul_file::is_directory(world_dir.str()))
158 vul_file::make_directory(world_dir.str());
159 params.set_params(world_dir.str(), corner, num_voxels, voxel_size(), lvcs);
160 std::string xml_name = name.str() + ".xml";
161 params.write_xml(xml_name, lvcs_name);
162 }
163
164 std::cout << "largest height difference in the whole ROI is: " << largest_dif << std::endl;
165
166
167 #if 0
168
169
170 std::vector<volm_img_info> infos;
171 volm_io_tools::load_aster_dem_imgs(in_folder(), infos);
172 std::cout << " loaded " << infos.size() << " DEM tiles!\n";
173
174 double largest_dif = 0;
175 for (unsigned i = 0; i < leaves.size(); i++) {
176 std::stringstream name; name << out_folder() << "scene_" << i ;
177 //std::cout << name.str() << std::endl;
178 //vul_file::make_directory(dir);
179 vgl_point_2d<double> lower_left = leaves[i]->extent_.min_point();
180 vgl_point_2d<double> upper_right = leaves[i]->extent_.max_point();
181
182 double min = 10000.0, max = -10000.0;
183 if (!volm_io_tools::find_min_max_height(lower_left, upper_right, infos, min, max)) {
184 std::cerr << " problems in the leaf: " << lower_left << " " << upper_right << " - cannot find height!\n";
185 return volm_io::EXE_ARGUMENT_ERROR;
186 }
187 double dif = max-min;
188 if (dif > largest_dif) largest_dif = dif;
189 //std::cout << "min: " << min << " " << max << "\n";
190
191 //construct lvcs
192 vpgl_lvcs_sptr lvcs = new vpgl_lvcs(lower_left.y(), lower_left.x(), min, vpgl_lvcs::wgs84, vpgl_lvcs::DEG, vpgl_lvcs::METERS);
193 std::string lvcs_name = name.str() + ".lvcs";
194 std::ofstream ofs(lvcs_name.c_str());
195 if (!ofs) {
196 std::cerr << "Cannot open file: " << lvcs_name << "!\n";
197 return volm_io::EXE_ARGUMENT_ERROR;
198 }
199 lvcs->write(ofs);
200 ofs.close();
201
202 vgl_point_3d<float> corner(0,0,0);
203 unsigned dim_xy = (unsigned)std::ceil(world_size()/voxel_size());
204 unsigned dim_z = (unsigned)std::ceil(dif+height());
205 vgl_vector_3d<unsigned int> num_voxels(dim_xy, dim_xy, dim_z);
206 bvxm_world_params params;
207 //params.set_params(name.str(), corner, num_voxels, voxel_size(), lvcs);
208 //params.set_params(out_folder().substr(0, out_folder().size()-1), corner, num_voxels, voxel_size(), lvcs); // for now set model dir as out_folder
209 // set bvxm_scene world parameters
210 std::stringstream world_dir;
211 world_dir << world_root() << "/scene_" << i;
212 if (!vul_file::is_directory(world_dir.str())) {
213 vul_file::make_directory(world_dir.str());
214 }
215 params.set_params(world_dir.str(), corner, num_voxels, voxel_size(), lvcs); // the world dir is now different from the out_folder where scene.xml and scene.lvcs stores
216 std::string xml_name = name.str() + ".xml";
217 params.write_xml(xml_name, lvcs_name);
218 }
219
220 std::cout << "largest height difference in the whole ROI is: " << largest_dif << '\n';
221
222 #endif
223 return volm_io::SUCCESS;
224 }
225