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