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