Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: KML Driver
4 : * Purpose: Class for building up the node structure of the kml file.
5 : * Author: Jens Oberender, j.obi@troja.net
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2007, Jens Oberender
9 : * Copyright (c) 2007-2012, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "cpl_port.h"
31 : #include "kmlnode.h"
32 :
33 : #include <cstring>
34 : #include <memory>
35 : #include <string>
36 : #include <vector>
37 :
38 : #include "cpl_conv.h"
39 : #include "cpl_error.h"
40 : #include "ogr_geometry.h"
41 :
42 : /************************************************************************/
43 : /* Help functions */
44 : /************************************************************************/
45 :
46 790 : std::string Nodetype2String(Nodetype const &type)
47 : {
48 790 : if (type == Empty)
49 0 : return "Empty";
50 790 : else if (type == Rest)
51 0 : return "Rest";
52 790 : else if (type == Mixed)
53 3 : return "Mixed";
54 787 : else if (type == Point)
55 187 : return "Point";
56 600 : else if (type == LineString)
57 243 : return "LineString";
58 357 : else if (type == Polygon)
59 357 : return "Polygon";
60 0 : else if (type == MultiGeometry)
61 0 : return "MultiGeometry";
62 0 : else if (type == MultiPoint)
63 0 : return "MultiPoint";
64 0 : else if (type == MultiLineString)
65 0 : return "MultiLineString";
66 0 : else if (type == MultiPolygon)
67 0 : return "MultiPolygon";
68 : else
69 0 : return "Unknown";
70 : }
71 :
72 234484 : static bool isNumberDigit(const char cIn)
73 : {
74 228109 : return (cIn == '-' || cIn == '+' || (cIn >= '0' && cIn <= '9') ||
75 462593 : cIn == '.' || cIn == 'e' || cIn == 'E');
76 : }
77 :
78 6469 : static Coordinate *ParseCoordinate(std::string const &text)
79 : {
80 6469 : int pos = 0;
81 6469 : const char *pszStr = text.c_str();
82 6469 : Coordinate *psTmp = new Coordinate();
83 :
84 : // X coordinate
85 6469 : psTmp->dfLongitude = CPLAtof(pszStr);
86 120403 : while (isNumberDigit(pszStr[pos++]))
87 : ;
88 :
89 : // Y coordinate
90 6469 : if (pszStr[pos - 1] != ',')
91 : {
92 0 : delete psTmp;
93 0 : return nullptr;
94 : }
95 :
96 6469 : psTmp->dfLatitude = CPLAtof(pszStr + pos);
97 114081 : while (isNumberDigit(pszStr[pos++]))
98 : ;
99 :
100 : // Z coordinate
101 6469 : if (pszStr[pos - 1] != ',')
102 : {
103 87 : psTmp->bHasZ = false;
104 87 : psTmp->dfAltitude = 0;
105 87 : return psTmp;
106 : }
107 :
108 6382 : psTmp->bHasZ = true;
109 6382 : psTmp->dfAltitude = CPLAtof(pszStr + pos);
110 :
111 6382 : return psTmp;
112 : }
113 :
114 : /************************************************************************/
115 : /* KMLNode methods */
116 : /************************************************************************/
117 :
118 5659 : KMLNode::KMLNode()
119 5659 : : pvpoChildren_(new std::vector<KMLNode *>),
120 5659 : pvsContent_(new std::vector<std::string>),
121 5659 : pvoAttributes_(new std::vector<Attribute *>), poParent_(nullptr),
122 : nLevel_(0), eType_(Unknown), b25D_(false), nLayerNumber_(-1),
123 16977 : nNumFeatures_(-1)
124 : {
125 5659 : }
126 :
127 5659 : KMLNode::~KMLNode()
128 : {
129 5659 : CPLAssert(nullptr != pvpoChildren_);
130 5659 : CPLAssert(nullptr != pvoAttributes_);
131 :
132 5659 : kml_nodes_t::iterator itChild;
133 7699 : for (itChild = pvpoChildren_->begin(); itChild != pvpoChildren_->end();
134 2040 : ++itChild)
135 : {
136 2040 : delete (*itChild);
137 : }
138 5659 : delete pvpoChildren_;
139 :
140 5659 : kml_attributes_t::iterator itAttr;
141 7086 : for (itAttr = pvoAttributes_->begin(); itAttr != pvoAttributes_->end();
142 1427 : ++itAttr)
143 : {
144 1427 : delete (*itAttr);
145 : }
146 5659 : delete pvoAttributes_;
147 :
148 5659 : delete pvsContent_;
149 5659 : }
150 :
151 0 : void KMLNode::print(unsigned int what)
152 : {
153 0 : std::string indent;
154 0 : for (std::size_t l = 0; l < nLevel_; l++)
155 0 : indent += " ";
156 :
157 0 : if (nLevel_ > 0)
158 : {
159 0 : if (nLayerNumber_ > -1)
160 : {
161 0 : CPLDebug("KML",
162 : "%s%s (nLevel: %d Type: %s poParent: %s "
163 : "pvpoChildren_: %d pvsContent_: %d pvoAttributes_: %d) "
164 : "<--- Layer #%d",
165 0 : indent.c_str(), sName_.c_str(), static_cast<int>(nLevel_),
166 0 : Nodetype2String(eType_).c_str(), poParent_->sName_.c_str(),
167 0 : static_cast<int>(pvpoChildren_->size()),
168 0 : static_cast<int>(pvsContent_->size()),
169 0 : static_cast<int>(pvoAttributes_->size()), nLayerNumber_);
170 : }
171 : else
172 : {
173 0 : CPLDebug("KML",
174 : "%s%s (nLevel: %d Type: %s poParent: %s "
175 : "pvpoChildren_: %d pvsContent_: %d pvoAttributes_: %d)",
176 0 : indent.c_str(), sName_.c_str(), static_cast<int>(nLevel_),
177 0 : Nodetype2String(eType_).c_str(), poParent_->sName_.c_str(),
178 0 : static_cast<int>(pvpoChildren_->size()),
179 0 : static_cast<int>(pvsContent_->size()),
180 0 : static_cast<int>(pvoAttributes_->size()));
181 : }
182 : }
183 : else
184 : {
185 0 : CPLDebug("KML",
186 : "%s%s (nLevel: %d Type: %s pvpoChildren_: %d "
187 : "pvsContent_: %d pvoAttributes_: %d)",
188 0 : indent.c_str(), sName_.c_str(), static_cast<int>(nLevel_),
189 0 : Nodetype2String(eType_).c_str(),
190 0 : static_cast<int>(pvpoChildren_->size()),
191 0 : static_cast<int>(pvsContent_->size()),
192 0 : static_cast<int>(pvoAttributes_->size()));
193 : }
194 :
195 0 : if (what == 1 || what == 3)
196 : {
197 0 : for (kml_content_t::size_type z = 0; z < pvsContent_->size(); z++)
198 0 : CPLDebug("KML", "%s|->pvsContent_: '%s'", indent.c_str(),
199 0 : (*pvsContent_)[z].c_str());
200 : }
201 :
202 0 : if (what == 2 || what == 3)
203 : {
204 0 : for (kml_attributes_t::size_type z = 0; z < pvoAttributes_->size(); z++)
205 0 : CPLDebug("KML", "%s|->pvoAttributes_: %s = '%s'", indent.c_str(),
206 0 : (*pvoAttributes_)[z]->sName.c_str(),
207 0 : (*pvoAttributes_)[z]->sValue.c_str());
208 : }
209 :
210 0 : for (kml_nodes_t::size_type z = 0; z < pvpoChildren_->size(); z++)
211 0 : (*pvpoChildren_)[z]->print(what);
212 0 : }
213 :
214 1995 : int KMLNode::classify(KML *poKML, int nRecLevel)
215 : {
216 1995 : Nodetype all = Empty;
217 :
218 : /* Arbitrary value, but certainly large enough for reasonable usages ! */
219 1995 : if (nRecLevel == 32)
220 : {
221 0 : CPLError(CE_Failure, CPLE_AppDefined,
222 : "Too many recursion levels (%d) while parsing KML geometry.",
223 : nRecLevel);
224 0 : return FALSE;
225 : }
226 :
227 1995 : if (sName_.compare("Point") == 0)
228 63 : eType_ = Point;
229 1932 : else if (sName_.compare("LineString") == 0)
230 78 : eType_ = LineString;
231 1854 : else if (sName_.compare("Polygon") == 0)
232 113 : eType_ = Polygon;
233 1741 : else if (poKML->isRest(sName_))
234 261 : eType_ = Empty;
235 1480 : else if (sName_.compare("coordinates") == 0)
236 : {
237 2372 : for (unsigned int nCountP = 0; nCountP < pvsContent_->size(); nCountP++)
238 : {
239 2105 : const char *pszCoord = (*pvsContent_)[nCountP].c_str();
240 2105 : int nComma = 0;
241 : while (true)
242 : {
243 4116 : pszCoord = strchr(pszCoord, ',');
244 6221 : if (pszCoord)
245 : {
246 4116 : nComma++;
247 4116 : pszCoord++;
248 : }
249 : else
250 2105 : break;
251 : }
252 2105 : if (nComma == 2)
253 2011 : b25D_ = true;
254 : }
255 : }
256 :
257 1995 : const kml_nodes_t::size_type size = pvpoChildren_->size();
258 3967 : for (kml_nodes_t::size_type z = 0; z < size; z++)
259 : {
260 : // Classify pvpoChildren_
261 1972 : if (!(*pvpoChildren_)[z]->classify(poKML, nRecLevel + 1))
262 0 : return FALSE;
263 :
264 1972 : Nodetype curr = (*pvpoChildren_)[z]->eType_;
265 1972 : b25D_ |= (*pvpoChildren_)[z]->b25D_;
266 :
267 : // Compare and return if it is mixed
268 1972 : if (curr != all && all != Empty && curr != Empty)
269 : {
270 90 : if (sName_.compare("MultiGeometry") == 0 ||
271 88 : sName_.compare("MultiPolygon") == 0 ||
272 134 : sName_.compare("MultiLineString") == 0 ||
273 44 : sName_.compare("MultiPoint") == 0)
274 2 : eType_ = MultiGeometry;
275 : else
276 44 : eType_ = Mixed;
277 : }
278 1926 : else if (curr != Empty)
279 : {
280 582 : all = curr;
281 : }
282 : }
283 :
284 1995 : if (eType_ == Unknown)
285 : {
286 2917 : if (sName_.compare("MultiGeometry") == 0 ||
287 2907 : sName_.compare("MultiPolygon") == 0 ||
288 4370 : sName_.compare("MultiLineString") == 0 ||
289 1452 : sName_.compare("MultiPoint") == 0)
290 : {
291 12 : if (all == Point)
292 4 : eType_ = MultiPoint;
293 8 : else if (all == LineString)
294 3 : eType_ = MultiLineString;
295 5 : else if (all == Polygon)
296 3 : eType_ = MultiPolygon;
297 : else
298 2 : eType_ = MultiGeometry;
299 : }
300 : else
301 1451 : eType_ = all;
302 : }
303 :
304 1995 : return TRUE;
305 : }
306 :
307 116 : void KMLNode::unregisterLayerIfMatchingThisNode(KML *poKML)
308 : {
309 190 : for (std::size_t z = 0; z < countChildren(); z++)
310 : {
311 74 : getChild(z)->unregisterLayerIfMatchingThisNode(poKML);
312 : }
313 116 : poKML->unregisterLayerIfMatchingThisNode(this);
314 116 : }
315 :
316 1868 : void KMLNode::eliminateEmpty(KML *poKML)
317 : {
318 3756 : for (kml_nodes_t::size_type z = 0; z < pvpoChildren_->size();)
319 : {
320 3148 : if ((*pvpoChildren_)[z]->eType_ == Empty &&
321 1260 : (poKML->isContainer((*pvpoChildren_)[z]->sName_) ||
322 1236 : poKML->isFeatureContainer((*pvpoChildren_)[z]->sName_)))
323 : {
324 42 : (*pvpoChildren_)[z]->unregisterLayerIfMatchingThisNode(poKML);
325 42 : delete (*pvpoChildren_)[z];
326 42 : pvpoChildren_->erase(pvpoChildren_->begin() + z);
327 : }
328 : else
329 : {
330 1846 : (*pvpoChildren_)[z]->eliminateEmpty(poKML);
331 1846 : ++z;
332 : }
333 : }
334 1868 : }
335 :
336 43 : bool KMLNode::hasOnlyEmpty() const
337 : {
338 63 : for (kml_nodes_t::size_type z = 0; z < pvpoChildren_->size(); z++)
339 : {
340 39 : if ((*pvpoChildren_)[z]->eType_ != Empty)
341 : {
342 19 : return false;
343 : }
344 : else
345 : {
346 20 : if (!(*pvpoChildren_)[z]->hasOnlyEmpty())
347 0 : return false;
348 : }
349 : }
350 :
351 24 : return true;
352 : }
353 :
354 0 : void KMLNode::setType(Nodetype oNotet)
355 : {
356 0 : eType_ = oNotet;
357 0 : }
358 :
359 285 : Nodetype KMLNode::getType() const
360 : {
361 285 : return eType_;
362 : }
363 :
364 5659 : void KMLNode::setName(std::string const &sIn)
365 : {
366 5659 : sName_ = sIn;
367 5659 : }
368 :
369 18605 : const std::string &KMLNode::getName() const
370 : {
371 18605 : return sName_;
372 : }
373 :
374 5659 : void KMLNode::setLevel(std::size_t nLev)
375 : {
376 5659 : nLevel_ = nLev;
377 5659 : }
378 :
379 0 : std::size_t KMLNode::getLevel() const
380 : {
381 0 : return nLevel_;
382 : }
383 :
384 1427 : void KMLNode::addAttribute(Attribute *poAttr)
385 : {
386 1427 : pvoAttributes_->push_back(poAttr);
387 1427 : }
388 :
389 5635 : void KMLNode::setParent(KMLNode *poPar)
390 : {
391 5635 : poParent_ = poPar;
392 5635 : }
393 :
394 11294 : KMLNode *KMLNode::getParent() const
395 : {
396 11294 : return poParent_;
397 : }
398 :
399 2082 : void KMLNode::addChildren(KMLNode *poChil)
400 : {
401 2082 : pvpoChildren_->push_back(poChil);
402 2082 : }
403 :
404 920 : std::size_t KMLNode::countChildren() const
405 : {
406 920 : return pvpoChildren_->size();
407 : }
408 :
409 1246 : KMLNode *KMLNode::getChild(std::size_t index) const
410 : {
411 1246 : return (*pvpoChildren_)[index];
412 : }
413 :
414 9192 : void KMLNode::addContent(std::string const &text)
415 : {
416 9192 : pvsContent_->push_back(text);
417 9192 : }
418 :
419 19024 : void KMLNode::appendContent(std::string const &text)
420 : {
421 19024 : pvsContent_->back() += text;
422 19024 : }
423 :
424 5232 : std::string KMLNode::getContent(std::size_t index) const
425 : {
426 5232 : return (*pvsContent_)[index];
427 : }
428 :
429 2117 : void KMLNode::deleteContent(std::size_t index)
430 : {
431 2117 : if (index < pvsContent_->size())
432 : {
433 2117 : pvsContent_->erase(pvsContent_->begin() + index);
434 : }
435 2117 : }
436 :
437 30182 : std::size_t KMLNode::numContent() const
438 : {
439 30182 : return pvsContent_->size();
440 : }
441 :
442 83 : void KMLNode::setLayerNumber(int nNum)
443 : {
444 83 : nLayerNumber_ = nNum;
445 83 : }
446 :
447 0 : int KMLNode::getLayerNumber() const
448 : {
449 0 : return nLayerNumber_;
450 : }
451 :
452 809 : std::string KMLNode::getNameElement() const
453 : {
454 809 : const kml_nodes_t::size_type size = pvpoChildren_->size();
455 :
456 844 : for (kml_nodes_t::size_type i = 0; i < size; ++i)
457 : {
458 808 : if ((*pvpoChildren_)[i]->sName_.compare("name") == 0)
459 : {
460 773 : const auto subsize = (*pvpoChildren_)[i]->pvsContent_->size();
461 773 : if (subsize > 0)
462 : {
463 773 : return (*(*pvpoChildren_)[i]->pvsContent_)[0];
464 : }
465 0 : break;
466 : }
467 : }
468 36 : return "";
469 : }
470 :
471 727 : std::string KMLNode::getDescriptionElement() const
472 : {
473 727 : const kml_nodes_t::size_type size = pvpoChildren_->size();
474 1812 : for (kml_nodes_t::size_type i = 0; i < size; ++i)
475 : {
476 1422 : if ((*pvpoChildren_)[i]->sName_.compare("description") == 0)
477 : {
478 337 : const auto subsize = (*pvpoChildren_)[i]->pvsContent_->size();
479 337 : if (subsize > 0)
480 : {
481 337 : return (*(*pvpoChildren_)[i]->pvsContent_)[0];
482 : }
483 0 : break;
484 : }
485 : }
486 390 : return "";
487 : }
488 :
489 977 : std::size_t KMLNode::getNumFeatures()
490 : {
491 977 : if (nNumFeatures_ < 0)
492 : {
493 27 : std::size_t nNum = 0;
494 27 : kml_nodes_t::size_type size = pvpoChildren_->size();
495 :
496 154 : for (kml_nodes_t::size_type i = 0; i < size; ++i)
497 : {
498 127 : if ((*pvpoChildren_)[i]->sName_ == "Placemark")
499 88 : nNum++;
500 : }
501 27 : nNumFeatures_ = (int)nNum;
502 : }
503 977 : return nNumFeatures_;
504 : }
505 :
506 745 : OGRGeometry *KMLNode::getGeometry(Nodetype eType)
507 : {
508 745 : OGRGeometry *poGeom = nullptr;
509 745 : KMLNode *poCoor = nullptr;
510 745 : Coordinate *psCoord = nullptr;
511 :
512 745 : if (sName_.compare("Point") == 0)
513 : {
514 : // Search coordinate Element
515 232 : for (unsigned int nCount = 0; nCount < pvpoChildren_->size(); nCount++)
516 : {
517 230 : if ((*pvpoChildren_)[nCount]->sName_.compare("coordinates") == 0)
518 : {
519 166 : poCoor = (*pvpoChildren_)[nCount];
520 166 : for (unsigned int nCountP = 0;
521 166 : nCountP < poCoor->pvsContent_->size(); nCountP++)
522 : {
523 165 : psCoord = ParseCoordinate((*poCoor->pvsContent_)[nCountP]);
524 165 : if (psCoord != nullptr)
525 : {
526 165 : if (psCoord->bHasZ)
527 156 : poGeom = new OGRPoint(psCoord->dfLongitude,
528 : psCoord->dfLatitude,
529 156 : psCoord->dfAltitude);
530 : else
531 9 : poGeom = new OGRPoint(psCoord->dfLongitude,
532 9 : psCoord->dfLatitude);
533 165 : delete psCoord;
534 165 : return poGeom;
535 : }
536 : }
537 : }
538 : }
539 2 : poGeom = new OGRPoint();
540 : }
541 578 : else if (sName_.compare("LineString") == 0)
542 : {
543 : // Search coordinate Element
544 236 : poGeom = new OGRLineString();
545 607 : for (unsigned int nCount = 0; nCount < pvpoChildren_->size(); nCount++)
546 : {
547 371 : if ((*pvpoChildren_)[nCount]->sName_.compare("coordinates") == 0)
548 : {
549 235 : poCoor = (*pvpoChildren_)[nCount];
550 1927 : for (unsigned int nCountP = 0;
551 1927 : nCountP < poCoor->pvsContent_->size(); nCountP++)
552 : {
553 1692 : psCoord = ParseCoordinate((*poCoor->pvsContent_)[nCountP]);
554 1692 : if (psCoord != nullptr)
555 : {
556 1692 : if (psCoord->bHasZ)
557 1678 : poGeom->toLineString()->addPoint(
558 : psCoord->dfLongitude, psCoord->dfLatitude,
559 : psCoord->dfAltitude);
560 : else
561 14 : poGeom->toLineString()->addPoint(
562 : psCoord->dfLongitude, psCoord->dfLatitude);
563 1692 : delete psCoord;
564 : }
565 : }
566 : }
567 : }
568 : }
569 342 : else if (sName_.compare("Polygon") == 0)
570 : {
571 : //*********************************
572 : // Search outerBoundaryIs Element
573 : //*********************************
574 328 : poGeom = new OGRPolygon();
575 1018 : for (unsigned int nCount = 0; nCount < pvpoChildren_->size(); nCount++)
576 : {
577 690 : if ((*pvpoChildren_)[nCount]->sName_.compare("outerBoundaryIs") ==
578 1017 : 0 &&
579 327 : !(*pvpoChildren_)[nCount]->pvpoChildren_->empty())
580 : {
581 326 : poCoor = (*(*pvpoChildren_)[nCount]->pvpoChildren_)[0];
582 : }
583 : }
584 : // No outer boundary found
585 328 : if (poCoor == nullptr)
586 : {
587 2 : return poGeom;
588 : }
589 : // Search coordinate Element
590 326 : OGRLinearRing *poLinearRing = nullptr;
591 651 : for (unsigned int nCount = 0; nCount < poCoor->pvpoChildren_->size();
592 : nCount++)
593 : {
594 325 : if ((*poCoor->pvpoChildren_)[nCount]->sName_.compare(
595 325 : "coordinates") == 0)
596 : {
597 4668 : for (unsigned int nCountP = 0;
598 4668 : nCountP <
599 4668 : (*poCoor->pvpoChildren_)[nCount]->pvsContent_->size();
600 : nCountP++)
601 : {
602 8686 : psCoord = ParseCoordinate((*(*poCoor->pvpoChildren_)[nCount]
603 4343 : ->pvsContent_)[nCountP]);
604 4343 : if (psCoord != nullptr)
605 : {
606 4343 : if (poLinearRing == nullptr)
607 : {
608 324 : poLinearRing = new OGRLinearRing();
609 : }
610 4343 : if (psCoord->bHasZ)
611 4296 : poLinearRing->addPoint(psCoord->dfLongitude,
612 : psCoord->dfLatitude,
613 : psCoord->dfAltitude);
614 : else
615 47 : poLinearRing->addPoint(psCoord->dfLongitude,
616 : psCoord->dfLatitude);
617 4343 : delete psCoord;
618 : }
619 : }
620 : }
621 : }
622 : // No outer boundary coordinates found
623 326 : if (poLinearRing == nullptr)
624 : {
625 2 : return poGeom;
626 : }
627 :
628 324 : poGeom->toPolygon()->addRingDirectly(poLinearRing);
629 324 : poLinearRing = nullptr;
630 :
631 : //*********************************
632 : // Search innerBoundaryIs Elements
633 : //*********************************
634 :
635 1011 : for (unsigned int nCount2 = 0; nCount2 < pvpoChildren_->size();
636 : nCount2++)
637 : {
638 687 : if ((*pvpoChildren_)[nCount2]->sName_.compare("innerBoundaryIs") ==
639 : 0)
640 : {
641 49 : if (poLinearRing)
642 0 : poGeom->toPolygon()->addRingDirectly(poLinearRing);
643 49 : poLinearRing = nullptr;
644 :
645 49 : if ((*pvpoChildren_)[nCount2]->pvpoChildren_->empty())
646 1 : continue;
647 :
648 48 : poLinearRing = new OGRLinearRing();
649 :
650 48 : poCoor = (*(*pvpoChildren_)[nCount2]->pvpoChildren_)[0];
651 : // Search coordinate Element
652 95 : for (unsigned int nCount = 0;
653 95 : nCount < poCoor->pvpoChildren_->size(); nCount++)
654 : {
655 47 : if ((*poCoor->pvpoChildren_)[nCount]->sName_.compare(
656 47 : "coordinates") == 0)
657 : {
658 316 : for (unsigned int nCountP = 0;
659 632 : nCountP < (*poCoor->pvpoChildren_)[nCount]
660 316 : ->pvsContent_->size();
661 : nCountP++)
662 : {
663 269 : psCoord = ParseCoordinate(
664 269 : (*(*poCoor->pvpoChildren_)[nCount]
665 269 : ->pvsContent_)[nCountP]);
666 269 : if (psCoord != nullptr)
667 : {
668 269 : if (psCoord->bHasZ)
669 252 : poLinearRing->addPoint(psCoord->dfLongitude,
670 : psCoord->dfLatitude,
671 : psCoord->dfAltitude);
672 : else
673 17 : poLinearRing->addPoint(psCoord->dfLongitude,
674 : psCoord->dfLatitude);
675 269 : delete psCoord;
676 : }
677 : }
678 : }
679 : }
680 : }
681 : }
682 :
683 324 : if (poLinearRing)
684 48 : poGeom->toPolygon()->addRingDirectly(poLinearRing);
685 : }
686 17 : else if (sName_.compare("MultiGeometry") == 0 ||
687 5 : sName_.compare("MultiPolygon") == 0 ||
688 19 : sName_.compare("MultiLineString") == 0 ||
689 1 : sName_.compare("MultiPoint") == 0)
690 : {
691 14 : if (eType == MultiPoint)
692 4 : poGeom = new OGRMultiPoint();
693 10 : else if (eType == MultiLineString)
694 3 : poGeom = new OGRMultiLineString();
695 7 : else if (eType == MultiPolygon)
696 3 : poGeom = new OGRMultiPolygon();
697 : else
698 4 : poGeom = new OGRGeometryCollection();
699 32 : for (unsigned int nCount = 0; nCount < pvpoChildren_->size(); nCount++)
700 : {
701 18 : OGRGeometry *poSubGeom = (*pvpoChildren_)[nCount]->getGeometry();
702 18 : if (poSubGeom)
703 18 : poGeom->toGeometryCollection()->addGeometryDirectly(poSubGeom);
704 : }
705 : }
706 :
707 576 : return poGeom;
708 : }
709 :
710 916 : Feature *KMLNode::getFeature(std::size_t nNum, int &nLastAsked, int &nLastCount)
711 : {
712 916 : if (nNum >= getNumFeatures())
713 189 : return nullptr;
714 :
715 727 : unsigned int nCount = 0;
716 727 : unsigned int nCountP = 0;
717 727 : KMLNode *poFeat = nullptr;
718 727 : KMLNode *poTemp = nullptr;
719 :
720 727 : if (nLastAsked + 1 != static_cast<int>(nNum))
721 : {
722 : // nCount = 0;
723 : // nCountP = 0;
724 : }
725 : else
726 : {
727 727 : nCount = nLastCount + 1;
728 727 : nCountP = nLastAsked + 1;
729 : }
730 :
731 1262 : for (; nCount < pvpoChildren_->size(); nCount++)
732 : {
733 1262 : if ((*pvpoChildren_)[nCount]->sName_.compare("Placemark") == 0)
734 : {
735 727 : if (nCountP == nNum)
736 : {
737 727 : poFeat = (*pvpoChildren_)[nCount];
738 727 : break;
739 : }
740 0 : nCountP++;
741 : }
742 : }
743 :
744 727 : nLastAsked = static_cast<int>(nNum);
745 727 : nLastCount = nCount;
746 :
747 727 : if (poFeat == nullptr)
748 0 : return nullptr;
749 :
750 : // Create a feature structure
751 727 : Feature *psReturn = new Feature;
752 : // Build up the name
753 727 : psReturn->sName = poFeat->getNameElement();
754 : // Build up the description
755 727 : psReturn->sDescription = poFeat->getDescriptionElement();
756 : // the type
757 727 : psReturn->eType = poFeat->eType_;
758 :
759 1454 : std::string sElementName;
760 727 : if (poFeat->eType_ == Point || poFeat->eType_ == LineString ||
761 338 : poFeat->eType_ == Polygon)
762 713 : sElementName = Nodetype2String(poFeat->eType_);
763 14 : else if (poFeat->eType_ == MultiGeometry || poFeat->eType_ == MultiPoint ||
764 6 : poFeat->eType_ == MultiLineString ||
765 3 : poFeat->eType_ == MultiPolygon)
766 14 : sElementName = "MultiGeometry";
767 : else
768 : {
769 0 : delete psReturn;
770 0 : return nullptr;
771 : }
772 :
773 1759 : for (nCount = 0; nCount < poFeat->pvpoChildren_->size(); nCount++)
774 : {
775 1759 : const auto &sName = (*poFeat->pvpoChildren_)[nCount]->sName_;
776 2797 : if (sName.compare(sElementName) == 0 ||
777 1038 : (sElementName == "MultiGeometry" &&
778 6 : (sName == "MultiPolygon" || sName == "MultiLineString" ||
779 1 : sName == "MultiPoint")))
780 : {
781 727 : poTemp = (*poFeat->pvpoChildren_)[nCount];
782 727 : psReturn->poGeom = poTemp->getGeometry(poFeat->eType_);
783 727 : if (psReturn->poGeom)
784 727 : return psReturn;
785 : else
786 : {
787 0 : delete psReturn;
788 0 : return nullptr;
789 : }
790 : }
791 : }
792 :
793 0 : delete psReturn;
794 0 : return nullptr;
795 : }
|