1 //:
2 // \file
3 #include <sstream>
4 #include <iostream>
5 #include <cstdio>
6 #include <cstring>
7 #include <algorithm>
8 #include <cstddef>
9 #include "volm_candidate_region_parser.h"
10 //
11 #ifdef _MSC_VER
12 # include "vcl_msvc_warnings.h"
13 #endif
14
15 template <typename T>
convert(const char * t,T & d)16 void convert(const char* t, T& d)
17 {
18 std::stringstream strm(t);
19 strm >> d;
20 }
21
volm_candidate_region_parser()22 volm_candidate_region_parser::volm_candidate_region_parser()
23 {
24 init_params();
25 }
26
init_params()27 void volm_candidate_region_parser::init_params()
28 {
29 longitude_ = 0.0; latitude_ = 0.0; altitude_ = 0.0;
30 heading_ = 0.0; heading_dev_ = 0.0; tilt_ = 0.0; tilt_dev_ = 0.0;
31 top_fov_ = 0.0; top_fov_dev_ = 0.0; roll_ = 0.0; roll_dev_ = 0.0;
32 right_fov_ = 0.0; right_fov_dev_ = 0.0;
33 near_ = 0.0;
34 polyouter_.clear(); polyinner_.clear();
35 linecords_.clear();
36 points_.clear();
37 last_tag = "";
38 cord_tag_ = "";
39 current_name_ = "";
40 }
41
cdataHandler(const std::string &,const std::string &)42 void volm_candidate_region_parser::cdataHandler(const std::string& /*name*/, const std::string& /*data*/)
43 {
44 }
45
handleAtts(const XML_Char **)46 void volm_candidate_region_parser::handleAtts(const XML_Char** /*atts*/)
47 {
48 }
49
startElement(const XML_Char * name,const XML_Char **)50 void volm_candidate_region_parser::startElement(const XML_Char* name, const XML_Char** /*atts*/)
51 {
52 if (std::strcmp(name, KML_LON_TAG) == 0)
53 last_tag = KML_LON_TAG;
54 else if (std::strcmp(name, KML_LAT_TAG) == 0)
55 last_tag = KML_LAT_TAG;
56 else if (std::strcmp(name, KML_ALT_TAG) == 0)
57 last_tag = KML_ALT_TAG;
58 else if (std::strcmp(name, KML_HEAD_TAG) == 0)
59 last_tag = KML_HEAD_TAG;
60 else if (std::strcmp(name,KML_HEAD_DEV_TAG) == 0)
61 last_tag = KML_HEAD_DEV_TAG;
62 else if (std::strcmp(name, KML_TFOV_TAG) == 0)
63 last_tag = KML_TFOV_TAG;
64 else if (std::strcmp(name, KML_TFOV_DEV_TAG) == 0)
65 last_tag = KML_TFOV_DEV_TAG;
66 else if (std::strcmp(name, KML_RFOV_TAG) == 0)
67 last_tag = KML_RFOV_TAG;
68 else if (std::strcmp(name, KML_RFOV_DEV_TAG) == 0)
69 last_tag = KML_RFOV_DEV_TAG;
70 else if (std::strcmp(name, KML_ROLL_TAG) == 0)
71 last_tag = KML_ROLL_TAG;
72 else if (std::strcmp(name, KML_ROLL_DEV_TAG) == 0)
73 last_tag = KML_ROLL_DEV_TAG;
74 else if (std::strcmp(name, KML_TILT_TAG) == 0)
75 last_tag = KML_TILT_TAG;
76 else if (std::strcmp(name, KML_TILT_DEV_TAG) == 0)
77 last_tag = KML_TILT_DEV_TAG;
78 else if (std::strcmp(name, KML_NEAR_TAG) == 0)
79 last_tag = KML_NEAR_TAG;
80 else if (std::strcmp(name, KML_CORD_TAG) == 0 && cord_tag_ != "")
81 last_tag = KML_CORD_TAG;
82 else if (std::strcmp(name, KML_PLACEMARK_NAME_TAG) == 0)
83 last_tag = KML_PLACEMARK_NAME_TAG;
84 else if (std::strcmp(name, KML_POLYOB_TAG) == 0)
85 cord_tag_ = KML_POLYOB_TAG;
86 else if (std::strcmp(name, KML_POLYIB_TAG) == 0)
87 cord_tag_ = KML_POLYIB_TAG;
88 else if (std::strcmp(name, KML_LINE_TAG) == 0)
89 cord_tag_ = KML_LINE_TAG;
90 else if (std::strcmp(name, KML_POINT_TAG) == 0)
91 cord_tag_ = KML_POINT_TAG;
92 }
93
endElement(const XML_Char *)94 void volm_candidate_region_parser::endElement(const XML_Char* /*name*/)
95 {
96 }
97
charData(const XML_Char * s,int len)98 void volm_candidate_region_parser::charData(const XML_Char* s, int len)
99 {
100 const int leadingSpace = skipWhiteSpace(s);
101 if (len == 0 || len <= leadingSpace)
102 return; // called with whitespace between elements
103 if (last_tag == KML_LON_TAG) {
104 std::stringstream str;
105 for (int i = 0; i < len; i++)
106 str << s[i];
107 str >> longitude_;
108 last_tag = "";
109 }
110 else if (last_tag == KML_LAT_TAG) {
111 std::stringstream str;
112 for (int i = 0; i < len; i++)
113 str << s[i];
114 str >> latitude_;
115 last_tag = "";
116 }
117 else if (last_tag == KML_ALT_TAG) {
118 std::stringstream str;
119 for (int i = 0; i < len; i++)
120 str << s[i];
121 str >> altitude_;
122 last_tag = "";
123 }
124 else if (last_tag == KML_PLACEMARK_NAME_TAG) {
125 std::stringstream str;
126 for (int i = 0; i < len; i++)
127 str << s[i];
128 current_name_ = str.str();
129 last_tag = "";
130 }
131 else if (last_tag == KML_HEAD_TAG) {
132 std::stringstream str;
133 for (int i = 0; i < len; i++)
134 str << s[i];
135 str >> heading_;
136 last_tag = "";
137 }
138 else if (last_tag == KML_HEAD_DEV_TAG) {
139 std::stringstream str;
140 for (int i = 0; i < len; i++)
141 str << s[i];
142 str >> heading_dev_;
143 last_tag = "";
144 }
145 else if (last_tag == KML_TILT_TAG) {
146 std::stringstream str;
147 for (int i = 0; i < len; i++)
148 str << s[i];
149 str >> tilt_;
150 last_tag = "";
151 }
152 else if (last_tag == KML_TILT_DEV_TAG) {
153 std::stringstream str;
154 for (int i = 0; i < len; i++)
155 str << s[i];
156 str >> tilt_dev_;
157 last_tag = "";
158 }
159 else if (last_tag == KML_ROLL_TAG) {
160 std::stringstream str;
161 for (int i = 0; i < len; i++)
162 str << s[i];
163 str >> roll_;
164 last_tag = "";
165 }
166 else if (last_tag == KML_ROLL_DEV_TAG) {
167 std::stringstream str;
168 for (int i = 0; i < len; i++)
169 str << s[i];
170 str >> roll_dev_;
171 last_tag = "";
172 }
173 else if (last_tag == KML_TFOV_TAG) {
174 std::stringstream str;
175 for (int i = 0; i < len; i++)
176 str << s[i];
177 str >> top_fov_;
178 last_tag = "";
179 }
180 else if (last_tag == KML_TFOV_DEV_TAG) {
181 std::stringstream str;
182 for (int i = 0; i < len; i++)
183 str << s[i];
184 str >> top_fov_dev_;
185 last_tag = "";
186 }
187 else if (last_tag == KML_RFOV_TAG) {
188 std::stringstream str;
189 for (int i = 0; i < len; i++)
190 str << s[i];
191 str >> right_fov_;
192 last_tag = "";
193 }
194 else if (last_tag == KML_RFOV_DEV_TAG) {
195 std::stringstream str;
196 for (int i = 0; i < len; i++)
197 str << s[i];
198 str >> right_fov_dev_;
199 last_tag = "";
200 }
201 else if (last_tag == KML_NEAR_TAG) {
202 std::stringstream str;
203 for (int i = 0; i < len; i++)
204 str << s[i];
205 str >> near_;
206 last_tag = "";
207 }
208 else if (last_tag == KML_CORD_TAG) {
209 // get the coordinate value
210 std::stringstream str;
211 double x,y,z;
212 std::string str_s;
213 str_s = s;
214 std::size_t cord_end = str_s.find(KML_POLYCORE_END_TAG);
215
216 if (str_s[len] == '<')
217 cord_end = len;
218 else {
219 while (str_s[cord_end] != '\n')
220 cord_end--;
221 while (str_s[cord_end-1] == ' ')
222 cord_end--;
223 }
224 for (unsigned int i=0; i<cord_end; ++i)
225 str << s[i];
226 std::vector<vgl_point_3d<double> > poly_verts;
227 while (!str.eof()) {
228 str >> x; str.ignore();
229 str >> y; str.ignore();
230 str >> z; str.ignore(128, ' ');
231 vgl_point_3d<double> vpt(x, y, z);
232 // check whether same point exists inside the point list already
233 if (std::find(poly_verts.begin(), poly_verts.end(), vpt) == poly_verts.end())
234 poly_verts.push_back(vpt);
235 }
236 // put the coordinates value into different polygons
237
238 if (cord_tag_ == KML_POLYOB_TAG) {
239 polyouter_[current_name_].push_back(poly_verts);
240 region_name_ = current_name_;
241 }
242 else if (cord_tag_ == KML_POLYIB_TAG) {
243 if (region_name_.compare("") == 0)
244 region_name_ = current_name_;
245 polyinner_[region_name_].push_back(poly_verts);
246 }
247 else if (cord_tag_ == KML_LINE_TAG) {
248 linecords_[current_name_].push_back(poly_verts);
249 }
250 else if (cord_tag_ == KML_POINT_TAG) {
251 points_[current_name_].push_back(poly_verts[0]);
252 }
253 else {
254 std::cout << "WARNING: unknown shape tag: " << cord_tag_ << " (name: " << current_name_ << ") won't be parsed" << std::endl;
255 }
256 last_tag = "";
257 cord_tag_ = "";
258 current_name_ = "";
259 }
260 }
261
parse_points(std::string const & kml_file,std::string const & name)262 std::vector<vgl_point_3d<double> > volm_candidate_region_parser::parse_points(std::string const& kml_file, std::string const& name)
263 {
264 std::vector<vgl_point_3d<double> > out;
265 out.clear();
266 auto* parser = new volm_candidate_region_parser();
267 std::FILE* xmlFile = std::fopen(kml_file.c_str(), "r");
268 if (!xmlFile) {
269 std::cerr << "volm_candidate_region_parser: can not open kml file " << kml_file << '\n';
270 delete parser;
271 return out;
272 }
273 if (!parser->parseFile(xmlFile)) {
274 std::cerr << "volm_candidate_region_parser: " << XML_ErrorString(parser->XML_GetErrorCode()) << " at line "
275 << parser->XML_GetCurrentLineNumber() << '\n';
276 delete parser;
277 return out;
278 }
279 if (parser->points_.find(name) == parser->points_.end()) {
280 std::cerr << "volm_candidate_region_parser: no point named " << name << ", empty point returned!\n";
281 delete parser;
282 return out;
283 }
284 else {
285 out = parser->points_[name];
286 delete parser;
287 return out;
288 }
289 }
290
parse_lines(std::string const & kml_file,std::string const & name)291 std::vector<std::vector<vgl_point_3d<double> > > volm_candidate_region_parser::parse_lines(std::string const& kml_file, std::string const& name)
292 {
293 std::vector<std::vector<vgl_point_3d<double> > > out_lines;
294 out_lines.clear();
295 auto* parser = new volm_candidate_region_parser();
296 std::FILE* xmlFile = std::fopen(kml_file.c_str(), "r");
297 if (!xmlFile) {
298 std::cerr << "volm_candidate_region_parser: can not open kml file " << kml_file <<'\n';
299 delete parser;
300 return out_lines;
301 }
302 if (!parser->parseFile(xmlFile)) {
303 std::cerr << "volm_candidate_region_parser: " << XML_ErrorString(parser->XML_GetErrorCode()) << " at line "
304 << parser->XML_GetCurrentLineNumber() << '\n';
305 delete parser;
306 return out_lines;
307 }
308 if (parser->linecords_.find(name) == parser->linecords_.end()) {
309 std::cerr << "volm_candidate_region_parser: no line named " << name << ", empty line returned!\n";
310 delete parser;
311 return out_lines;
312 }
313 else {
314 out_lines = parser->linecords_[name];
315 delete parser;
316 return out_lines;
317 }
318 }
319
parse_polygon(std::string const & kml_file,std::string const & name)320 vgl_polygon<double> volm_candidate_region_parser::parse_polygon(std::string const& kml_file, std::string const& name)
321 {
322 vgl_polygon<double> out;
323 out.clear();
324 auto* parser = new volm_candidate_region_parser;
325 std::FILE* xmlFile = std::fopen(kml_file.c_str(), "r");
326 if (!xmlFile) {
327 std::cerr << "volm_candidate_region_parser: can not open kml file " << kml_file << '\n';
328 delete parser;
329 return out;
330 }
331 if (!parser->parseFile(xmlFile)) {
332 std::cerr << "volm_candidate_region_parser: " << XML_ErrorString(parser->XML_GetErrorCode()) << " at line "
333 << parser->XML_GetCurrentLineNumber() << '\n';
334 delete parser;
335 return out;
336 }
337 if (parser->polyouter_.find(name) == parser->polyouter_.end()) {
338 std::cerr << "volm_candidate_region_parser: no polygon region named " << name << ", empty polygon returned\n";
339 delete parser;
340 return out;
341 }
342 // create polygon
343 std::vector<std::vector<vgl_point_3d<double> > > out_sheets = parser->polyouter_[name];
344 unsigned num_sheet = out_sheets.size();
345 for (unsigned i = 0; i < num_sheet; i++)
346 {
347 unsigned n_pts = out_sheets[i].size();
348 out.new_sheet();
349 for (unsigned k = 0; k < n_pts; k++)
350 out.push_back(out_sheets[i][k].x(), out_sheets[i][k].y());
351 }
352 delete parser;
353 return out;
354 }
355
356 // parse the polygon region given the name
357 // the first n_out sheets are the exterior boundary and the following n_in sheets are the interior boundary
parse_polygon_with_inner(std::string const & kml_file,std::string const & name,vgl_polygon<double> & outer,vgl_polygon<double> & inner,unsigned & n_out,unsigned & n_in)358 vgl_polygon<double> volm_candidate_region_parser::parse_polygon_with_inner(std::string const& kml_file, std::string const& name,
359 vgl_polygon<double>& outer, vgl_polygon<double>& inner,
360 unsigned& n_out, unsigned& n_in)
361 {
362 vgl_polygon<double> poly;
363 poly.clear();
364 auto* parser = new volm_candidate_region_parser;
365 std::FILE* xmlFile = std::fopen(kml_file.c_str(), "r");
366 if (!xmlFile) {
367 std::cerr << "volm_candidate_region_parser: can not open kml file " << kml_file << '\n';
368 delete parser;
369 return poly;
370 }
371 if (!parser->parseFile(xmlFile)) {
372 std::cerr << "volm_candidate_region_parser: " << XML_ErrorString(parser->XML_GetErrorCode()) << " at line "
373 << parser->XML_GetCurrentLineNumber() << '\n';
374 delete parser;
375 return poly;
376 }
377 if (parser->polyouter_.find(name) == parser->polyouter_.end()) {
378 std::cerr << "volm_candidate_region_parser: no polygon region named " << name << ", empty polygon returned\n";
379 delete parser;
380 return poly;
381 }
382 // create polygon
383 outer.clear();
384 inner.clear();
385 // create the outer boundary polygon
386 if (parser->polyouter_.find(name) != parser->polyouter_.end()) {
387 std::vector<std::vector<vgl_point_3d<double> > > out_sheets = parser->polyouter_[name];
388 unsigned int n_sheet = out_sheets.size();
389 for (unsigned int i = 0; i < n_sheet; ++i) {
390 unsigned int n_pts = out_sheets[i].size();
391 outer.new_sheet();
392 for (unsigned int k = 0; k < n_pts; ++k)
393 outer.push_back(out_sheets[i][k].x(), out_sheets[i][k].y());
394 }
395 }
396 // create the inner boundary polygon
397 if (parser->polyinner_.find(name) != parser->polyinner_.end()) {
398 std::vector<std::vector<vgl_point_3d<double> > > in_sheet = parser->polyinner_[name];
399 unsigned n_sheet = in_sheet.size();
400 for (unsigned i = 0; i < n_sheet; i++) {
401 unsigned n_pts = in_sheet[i].size();
402 inner.new_sheet();
403 for (unsigned k = 0; k < n_pts; k++)
404 inner.push_back(in_sheet[i][k].x(), in_sheet[i][k].y());
405 }
406 }
407 // compose to form the polygon
408 n_out = outer.num_sheets();
409 n_in = inner.num_sheets();
410 for (unsigned s_idx = 0; s_idx < n_out; s_idx++)
411 poly.push_back(outer[s_idx]);
412 for (unsigned s_idx = 0; s_idx < n_in; s_idx++)
413 poly.push_back(inner[s_idx]);
414 delete parser;
415 return poly;
416 }
417