1 : /******************************************************************************
2 : * $Id: kmlnode.cpp 25309 2012-12-15 12:14:44Z rouault $
3 : *
4 : * Project: KML Driver
5 : * Purpose: Class for building up the node structure of the kml file.
6 : * Author: Jens Oberender, j.obi@troja.net
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2007, Jens Oberender
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 : #include "kmlnode.h"
30 : #include "cpl_conv.h"
31 : // std
32 : #include <string>
33 : #include <vector>
34 :
35 : /************************************************************************/
36 : /* Help functions */
37 : /************************************************************************/
38 :
39 355 : std::string Nodetype2String(Nodetype const& type)
40 : {
41 355 : if(type == Empty)
42 0 : return "Empty";
43 355 : else if(type == Rest)
44 0 : return "Rest";
45 355 : else if(type == Mixed)
46 2 : return "Mixed";
47 353 : else if(type == Point)
48 87 : return "Point";
49 266 : else if(type == LineString)
50 101 : return "LineString";
51 165 : else if(type == Polygon)
52 165 : return "Polygon";
53 0 : else if(type == MultiGeometry)
54 0 : return "MultiGeometry";
55 0 : else if(type == MultiPoint)
56 0 : return "MultiPoint";
57 0 : else if(type == MultiLineString)
58 0 : return "MultiLineString";
59 0 : else if(type == MultiPolygon)
60 0 : return "MultiPolygon";
61 : else
62 0 : return "Unknown";
63 : }
64 :
65 : static
66 108184 : bool isNumberDigit(const char cIn)
67 : {
68 : return ( cIn == '-' || cIn == '+' ||
69 : (cIn >= '0' && cIn <= '9') ||
70 108184 : cIn == '.' || cIn == 'e' || cIn == 'E' );
71 : }
72 :
73 : static
74 3022 : Coordinate* ParseCoordinate(std::string const& text)
75 : {
76 3022 : int pos = 0;
77 3022 : const char* pszStr = text.c_str();
78 3022 : Coordinate *psTmp = new Coordinate();
79 :
80 : // X coordinate
81 3022 : psTmp->dfLongitude = CPLAtof(pszStr);
82 55547 : while(isNumberDigit(pszStr[pos++]));
83 :
84 : // Y coordinate
85 3022 : if(pszStr[pos - 1] != ',')
86 : {
87 0 : delete psTmp;
88 0 : return NULL;
89 : }
90 :
91 3022 : psTmp->dfLatitude = CPLAtof(pszStr + pos);
92 52637 : while(isNumberDigit(pszStr[pos++]));
93 :
94 : // Z coordinate
95 3022 : if(pszStr[pos - 1] != ',')
96 : {
97 81 : psTmp->bHasZ = FALSE;
98 81 : psTmp->dfAltitude = 0;
99 81 : return psTmp;
100 : }
101 :
102 2941 : psTmp->bHasZ = TRUE;
103 2941 : psTmp->dfAltitude = CPLAtof(pszStr + pos);
104 :
105 2941 : return psTmp;
106 : }
107 :
108 : /************************************************************************/
109 : /* KMLNode methods */
110 : /************************************************************************/
111 :
112 1690 : KMLNode::KMLNode()
113 : {
114 1690 : poParent_ = NULL;
115 1690 : pvpoChildren_ = new std::vector<KMLNode*>;
116 3380 : pvsContent_ = new std::vector<std::string>;
117 3380 : pvoAttributes_ = new std::vector<Attribute*>;
118 1690 : eType_ = Unknown;
119 1690 : nLayerNumber_ = -1;
120 1690 : b25D_ = FALSE;
121 1690 : nNumFeatures_ = -1;
122 1690 : }
123 :
124 1690 : KMLNode::~KMLNode()
125 : {
126 1690 : CPLAssert( NULL != pvpoChildren_ );
127 1690 : CPLAssert( NULL != pvoAttributes_ );
128 :
129 1690 : kml_nodes_t::iterator itChild;
130 2364 : for( itChild = pvpoChildren_->begin();
131 : itChild != pvpoChildren_->end(); ++itChild)
132 : {
133 674 : delete (*itChild);
134 : }
135 1690 : delete pvpoChildren_;
136 :
137 1690 : kml_attributes_t::iterator itAttr;
138 2099 : for( itAttr = pvoAttributes_->begin();
139 : itAttr != pvoAttributes_->end(); ++itAttr)
140 : {
141 409 : delete (*itAttr);
142 : }
143 1690 : delete pvoAttributes_;
144 :
145 1690 : delete pvsContent_;
146 1690 : }
147 :
148 0 : void KMLNode::print(unsigned int what)
149 : {
150 0 : std::string indent;
151 0 : for(std::size_t l = 0; l < nLevel_; l++)
152 0 : indent += " ";
153 :
154 0 : if(nLevel_ > 0)
155 : {
156 0 : if(nLayerNumber_ > -1)
157 : {
158 : CPLDebug("KML", "%s%s (nLevel: %d Type: %s poParent: %s pvpoChildren_: %d pvsContent_: %d pvoAttributes_: %d) <--- Layer #%d",
159 : indent.c_str(), sName_.c_str(), (int) nLevel_, Nodetype2String(eType_).c_str(), poParent_->sName_.c_str(),
160 0 : (int) pvpoChildren_->size(), (int) pvsContent_->size(), (int) pvoAttributes_->size(), nLayerNumber_);
161 : }
162 : else
163 : {
164 : CPLDebug("KML", "%s%s (nLevel: %d Type: %s poParent: %s pvpoChildren_: %d pvsContent_: %d pvoAttributes_: %d)",
165 : indent.c_str(), sName_.c_str(), (int) nLevel_, Nodetype2String(eType_).c_str(), poParent_->sName_.c_str(),
166 0 : (int) pvpoChildren_->size(), (int) pvsContent_->size(), (int) pvoAttributes_->size());
167 : }
168 : }
169 : else
170 : {
171 : CPLDebug("KML", "%s%s (nLevel: %d Type: %s pvpoChildren_: %d pvsContent_: %d pvoAttributes_: %d)",
172 : indent.c_str(), sName_.c_str(), (int) nLevel_, Nodetype2String(eType_).c_str(), (int) pvpoChildren_->size(),
173 0 : (int) pvsContent_->size(), (int) pvoAttributes_->size());
174 : }
175 :
176 0 : if(what == 1 || what == 3)
177 : {
178 0 : for(kml_content_t::size_type z = 0; z < pvsContent_->size(); z++)
179 0 : CPLDebug("KML", "%s|->pvsContent_: '%s'", indent.c_str(), (*pvsContent_)[z].c_str());
180 : }
181 :
182 0 : if(what == 2 || what == 3)
183 : {
184 0 : for(kml_attributes_t::size_type z = 0; z < pvoAttributes_->size(); z++)
185 0 : CPLDebug("KML", "%s|->pvoAttributes_: %s = '%s'", indent.c_str(), (*pvoAttributes_)[z]->sName.c_str(), (*pvoAttributes_)[z]->sValue.c_str());
186 : }
187 :
188 0 : for(kml_nodes_t::size_type z = 0; z < pvpoChildren_->size(); z++)
189 0 : (*pvpoChildren_)[z]->print(what);
190 0 : }
191 :
192 : //static int nDepth = 0;
193 : //static char* genSpaces()
194 : //{
195 : // static char spaces[128];
196 : // int i;
197 : // for(i=0;i<nDepth;i++)
198 : // spaces[i] = ' ';
199 : // spaces[i] = '\0';
200 : // return spaces;
201 : //}
202 :
203 667 : int KMLNode::classify(KML* poKML, int nRecLevel)
204 : {
205 667 : Nodetype curr = Unknown;
206 667 : Nodetype all = Empty;
207 :
208 : /* Arbitrary value, but certainly large enough for reasonable usages ! */
209 667 : if( nRecLevel == 32 )
210 : {
211 : CPLError( CE_Failure, CPLE_AppDefined,
212 : "Too many recursiong level (%d) while parsing KML geometry.",
213 0 : nRecLevel );
214 0 : return FALSE;
215 : }
216 :
217 : //CPLDebug("KML", "%s<%s>", genSpaces(), sName_.c_str());
218 : //nDepth ++;
219 :
220 667 : if(sName_.compare("Point") == 0)
221 27 : eType_ = Point;
222 640 : else if(sName_.compare("LineString") == 0)
223 27 : eType_ = LineString;
224 613 : else if(sName_.compare("Polygon") == 0)
225 40 : eType_ = Polygon;
226 573 : else if(poKML->isRest(sName_))
227 99 : eType_ = Empty;
228 474 : else if(sName_.compare("coordinates") == 0)
229 : {
230 : unsigned int nCountP;
231 733 : for(nCountP = 0; nCountP < pvsContent_->size(); nCountP++)
232 : {
233 634 : const char* pszCoord = (*pvsContent_)[nCountP].c_str();
234 634 : int nComma = 0;
235 1184 : while(TRUE)
236 : {
237 1818 : pszCoord = strchr(pszCoord, ',');
238 1818 : if (pszCoord)
239 : {
240 1184 : nComma ++;
241 1184 : pszCoord ++;
242 : }
243 : else
244 : break;
245 : }
246 634 : if (nComma == 2)
247 550 : b25D_ = TRUE;
248 : }
249 : }
250 :
251 667 : const kml_nodes_t::size_type size = pvpoChildren_->size();
252 1325 : for(kml_nodes_t::size_type z = 0; z < size; z++)
253 : {
254 : //CPLDebug("KML", "%s[%d] %s", genSpaces(), z, (*pvpoChildren_)[z]->sName_.c_str());
255 :
256 : // Classify pvpoChildren_
257 658 : if (!(*pvpoChildren_)[z]->classify(poKML, nRecLevel + 1))
258 0 : return FALSE;
259 :
260 658 : curr = (*pvpoChildren_)[z]->eType_;
261 658 : b25D_ |= (*pvpoChildren_)[z]->b25D_;
262 :
263 : // Compare and return if it is mixed
264 686 : if(curr != all && all != Empty && curr != Empty)
265 : {
266 28 : if (sName_.compare("MultiGeometry") == 0)
267 2 : eType_ = MultiGeometry;
268 : else
269 26 : eType_ = Mixed;
270 : }
271 630 : else if(curr != Empty)
272 : {
273 199 : all = curr;
274 : }
275 : }
276 :
277 667 : if(eType_ == Unknown)
278 : {
279 466 : if (sName_.compare("MultiGeometry") == 0)
280 : {
281 9 : if (all == Point)
282 3 : eType_ = MultiPoint;
283 6 : else if (all == LineString)
284 2 : eType_ = MultiLineString;
285 4 : else if (all == Polygon)
286 2 : eType_ = MultiPolygon;
287 : else
288 2 : eType_ = MultiGeometry;
289 : }
290 : else
291 457 : eType_ = all;
292 : }
293 :
294 : //nDepth --;
295 : //CPLDebug("KML", "%s</%s> --> eType=%s", genSpaces(), sName_.c_str(), Nodetype2String(eType_).c_str());
296 :
297 667 : return TRUE;
298 : }
299 :
300 621 : void KMLNode::eliminateEmpty(KML* poKML)
301 : {
302 1248 : for(kml_nodes_t::size_type z = 0; z < pvpoChildren_->size(); z++)
303 : {
304 1421 : if((*pvpoChildren_)[z]->eType_ == Empty
305 400 : && (poKML->isContainer((*pvpoChildren_)[z]->sName_)
306 394 : || poKML->isFeatureContainer((*pvpoChildren_)[z]->sName_)))
307 : {
308 14 : delete (*pvpoChildren_)[z];
309 14 : pvpoChildren_->erase(pvpoChildren_->begin() + z);
310 14 : z--;
311 : }
312 : else
313 : {
314 613 : (*pvpoChildren_)[z]->eliminateEmpty(poKML);
315 : }
316 : }
317 621 : }
318 :
319 19 : bool KMLNode::hasOnlyEmpty() const
320 : {
321 29 : for(kml_nodes_t::size_type z = 0; z < pvpoChildren_->size(); z++)
322 : {
323 17 : if((*pvpoChildren_)[z]->eType_ != Empty)
324 : {
325 7 : return false;
326 : }
327 : else
328 : {
329 10 : if (!(*pvpoChildren_)[z]->hasOnlyEmpty())
330 0 : return false;
331 : }
332 : }
333 :
334 12 : return true;
335 : }
336 :
337 0 : void KMLNode::setType(Nodetype oNotet)
338 : {
339 0 : eType_ = oNotet;
340 0 : }
341 :
342 95 : Nodetype KMLNode::getType() const
343 : {
344 95 : return eType_;
345 : }
346 :
347 1690 : void KMLNode::setName(std::string const& sIn)
348 : {
349 1690 : sName_ = sIn;
350 1690 : }
351 :
352 5597 : const std::string& KMLNode::getName() const
353 : {
354 5597 : return sName_;
355 : }
356 :
357 1690 : void KMLNode::setLevel(std::size_t nLev)
358 : {
359 1690 : nLevel_ = nLev;
360 1690 : }
361 :
362 0 : std::size_t KMLNode::getLevel() const
363 : {
364 0 : return nLevel_;
365 : }
366 :
367 409 : void KMLNode::addAttribute(Attribute *poAttr)
368 : {
369 409 : pvoAttributes_->push_back(poAttr);
370 409 : }
371 :
372 1681 : void KMLNode::setParent(KMLNode* poPar)
373 : {
374 1681 : poParent_ = poPar;
375 1681 : }
376 :
377 3371 : KMLNode* KMLNode::getParent() const
378 : {
379 3371 : return poParent_;
380 : }
381 :
382 688 : void KMLNode::addChildren(KMLNode *poChil)
383 : {
384 688 : pvpoChildren_->push_back(poChil);
385 688 : }
386 :
387 233 : std::size_t KMLNode::countChildren()
388 : {
389 233 : return pvpoChildren_->size();
390 : }
391 :
392 376 : KMLNode* KMLNode::getChild(std::size_t index) const
393 : {
394 376 : return (*pvpoChildren_)[index];
395 : }
396 :
397 2671 : void KMLNode::addContent(std::string const& text)
398 : {
399 2671 : pvsContent_->push_back(text);
400 2671 : }
401 :
402 5317 : void KMLNode::appendContent(std::string const& text)
403 : {
404 5317 : std::string& tmp = (*pvsContent_)[pvsContent_->size() - 1];
405 5317 : tmp += text;
406 5317 : }
407 :
408 1497 : std::string KMLNode::getContent(std::size_t index) const
409 : {
410 1497 : return (*pvsContent_)[index];
411 : }
412 :
413 634 : void KMLNode::deleteContent(std::size_t index)
414 : {
415 634 : if( index < pvsContent_->size() )
416 : {
417 634 : pvsContent_->erase(pvsContent_->begin() + index);
418 : }
419 634 : }
420 :
421 8603 : std::size_t KMLNode::numContent()
422 : {
423 8603 : return pvsContent_->size();
424 : }
425 :
426 25 : void KMLNode::setLayerNumber(int nNum)
427 : {
428 25 : nLayerNumber_ = nNum;
429 25 : }
430 :
431 0 : int KMLNode::getLayerNumber() const
432 : {
433 0 : return nLayerNumber_;
434 : }
435 :
436 368 : std::string KMLNode::getNameElement() const
437 : {
438 368 : kml_nodes_t::size_type subsize = 0;
439 368 : kml_nodes_t::size_type size = pvpoChildren_->size();
440 :
441 399 : for( kml_nodes_t::size_type i = 0; i < size; ++i )
442 : {
443 368 : if( (*pvpoChildren_)[i]->sName_.compare("name") == 0 )
444 : {
445 337 : subsize = (*pvpoChildren_)[i]->pvsContent_->size();
446 337 : if( subsize > 0 )
447 : {
448 337 : return (*(*pvpoChildren_)[i]->pvsContent_)[0];
449 : }
450 0 : break;
451 : }
452 : }
453 31 : return "";
454 : }
455 :
456 343 : std::string KMLNode::getDescriptionElement() const
457 : {
458 343 : kml_nodes_t::size_type subsize = 0;
459 343 : kml_nodes_t::size_type size = pvpoChildren_->size();
460 851 : for( kml_nodes_t::size_type i = 0; i < size; ++i )
461 : {
462 657 : if( (*pvpoChildren_)[i]->sName_.compare("description") == 0 )
463 : {
464 149 : subsize = (*pvpoChildren_)[i]->pvsContent_->size();
465 149 : if ( subsize > 0 )
466 : {
467 149 : return (*(*pvpoChildren_)[i]->pvsContent_)[0];
468 : }
469 0 : break;
470 : }
471 : }
472 194 : return "";
473 : }
474 :
475 459 : std::size_t KMLNode::getNumFeatures()
476 : {
477 459 : if (nNumFeatures_ < 0)
478 : {
479 18 : std::size_t nNum = 0;
480 18 : kml_nodes_t::size_type size = pvpoChildren_->size();
481 :
482 115 : for( kml_nodes_t::size_type i = 0; i < size; ++i )
483 : {
484 97 : if( (*pvpoChildren_)[i]->sName_ == "Placemark" )
485 69 : nNum++;
486 : }
487 18 : nNumFeatures_ = (int)nNum;
488 : }
489 459 : return nNumFeatures_;
490 : }
491 :
492 358 : OGRGeometry* KMLNode::getGeometry(Nodetype eType)
493 : {
494 : unsigned int nCount, nCount2, nCountP;
495 358 : OGRGeometry* poGeom = NULL;
496 358 : KMLNode* poCoor = NULL;
497 358 : Coordinate* psCoord = NULL;
498 :
499 358 : if (sName_.compare("Point") == 0)
500 : {
501 : // Search coordinate Element
502 118 : for(nCount = 0; nCount < pvpoChildren_->size(); nCount++)
503 : {
504 116 : if((*pvpoChildren_)[nCount]->sName_.compare("coordinates") == 0)
505 : {
506 84 : poCoor = (*pvpoChildren_)[nCount];
507 84 : for(nCountP = 0; nCountP < poCoor->pvsContent_->size(); nCountP++)
508 : {
509 83 : psCoord = ParseCoordinate((*poCoor->pvsContent_)[nCountP]);
510 83 : if(psCoord != NULL)
511 : {
512 83 : if (psCoord->bHasZ)
513 : poGeom = new OGRPoint(psCoord->dfLongitude,
514 : psCoord->dfLatitude,
515 75 : psCoord->dfAltitude);
516 : else
517 : poGeom = new OGRPoint(psCoord->dfLongitude,
518 8 : psCoord->dfLatitude);
519 83 : delete psCoord;
520 83 : return poGeom;
521 : }
522 : }
523 : }
524 : }
525 2 : poGeom = new OGRPoint();
526 : }
527 273 : else if (sName_.compare("LineString") == 0)
528 : {
529 : // Search coordinate Element
530 103 : poGeom = new OGRLineString();
531 263 : for(nCount = 0; nCount < pvpoChildren_->size(); nCount++)
532 : {
533 160 : if((*pvpoChildren_)[nCount]->sName_.compare("coordinates") == 0)
534 : {
535 102 : poCoor = (*pvpoChildren_)[nCount];
536 826 : for(nCountP = 0; nCountP < poCoor->pvsContent_->size(); nCountP++)
537 : {
538 724 : psCoord = ParseCoordinate((*poCoor->pvsContent_)[nCountP]);
539 724 : if(psCoord != NULL)
540 : {
541 724 : if (psCoord->bHasZ)
542 : ((OGRLineString*)poGeom)->addPoint(psCoord->dfLongitude,
543 : psCoord->dfLatitude,
544 710 : psCoord->dfAltitude);
545 : else
546 : ((OGRLineString*)poGeom)->addPoint(psCoord->dfLongitude,
547 14 : psCoord->dfLatitude);
548 724 : delete psCoord;
549 : }
550 : }
551 : }
552 : }
553 : }
554 170 : else if (sName_.compare("Polygon") == 0)
555 : {
556 : //*********************************
557 : // Search outerBoundaryIs Element
558 : //*********************************
559 159 : poGeom = new OGRPolygon();
560 488 : for(nCount = 0; nCount < pvpoChildren_->size(); nCount++)
561 : {
562 329 : if((*pvpoChildren_)[nCount]->sName_.compare("outerBoundaryIs") == 0 &&
563 : (*pvpoChildren_)[nCount]->pvpoChildren_->size() > 0)
564 : {
565 157 : poCoor = (*(*pvpoChildren_)[nCount]->pvpoChildren_)[0];
566 : }
567 : }
568 : // No outer boundary found
569 159 : if(poCoor == NULL)
570 : {
571 2 : return poGeom;
572 : }
573 : // Search coordinate Element
574 157 : OGRLinearRing* poLinearRing = NULL;
575 313 : for(nCount = 0; nCount < poCoor->pvpoChildren_->size(); nCount++)
576 : {
577 156 : if((*poCoor->pvpoChildren_)[nCount]->sName_.compare("coordinates") == 0)
578 : {
579 2246 : for(nCountP = 0; nCountP < (*poCoor->pvpoChildren_)[nCount]->pvsContent_->size(); nCountP++)
580 : {
581 2090 : psCoord = ParseCoordinate((*(*poCoor->pvpoChildren_)[nCount]->pvsContent_)[nCountP]);
582 2090 : if(psCoord != NULL)
583 : {
584 2090 : if (poLinearRing == NULL)
585 : {
586 155 : poLinearRing = new OGRLinearRing();
587 : }
588 2090 : if (psCoord->bHasZ)
589 : poLinearRing->addPoint(psCoord->dfLongitude,
590 : psCoord->dfLatitude,
591 2048 : psCoord->dfAltitude);
592 : else
593 : poLinearRing->addPoint(psCoord->dfLongitude,
594 42 : psCoord->dfLatitude);
595 2090 : delete psCoord;
596 : }
597 : }
598 : }
599 : }
600 : // No outer boundary coordinates found
601 157 : if(poLinearRing == NULL)
602 : {
603 2 : return poGeom;
604 : }
605 :
606 155 : ((OGRPolygon*)poGeom)->addRingDirectly(poLinearRing);
607 155 : poLinearRing = NULL;
608 :
609 : //*********************************
610 : // Search innerBoundaryIs Elements
611 : //*********************************
612 :
613 481 : for(nCount2 = 0; nCount2 < pvpoChildren_->size(); nCount2++)
614 : {
615 326 : if((*pvpoChildren_)[nCount2]->sName_.compare("innerBoundaryIs") == 0)
616 : {
617 25 : if (poLinearRing)
618 0 : ((OGRPolygon*)poGeom)->addRingDirectly(poLinearRing);
619 25 : poLinearRing = NULL;
620 :
621 25 : if ((*pvpoChildren_)[nCount2]->pvpoChildren_->size() == 0)
622 1 : continue;
623 :
624 24 : poLinearRing = new OGRLinearRing();
625 :
626 24 : poCoor = (*(*pvpoChildren_)[nCount2]->pvpoChildren_)[0];
627 : // Search coordinate Element
628 47 : for(nCount = 0; nCount < poCoor->pvpoChildren_->size(); nCount++)
629 : {
630 23 : if((*poCoor->pvpoChildren_)[nCount]->sName_.compare("coordinates") == 0)
631 : {
632 148 : for(nCountP = 0; nCountP < (*poCoor->pvpoChildren_)[nCount]->pvsContent_->size(); nCountP++)
633 : {
634 125 : psCoord = ParseCoordinate((*(*poCoor->pvpoChildren_)[nCount]->pvsContent_)[nCountP]);
635 125 : if(psCoord != NULL)
636 : {
637 125 : if (psCoord->bHasZ)
638 : poLinearRing->addPoint(psCoord->dfLongitude,
639 : psCoord->dfLatitude,
640 108 : psCoord->dfAltitude);
641 : else
642 : poLinearRing->addPoint(psCoord->dfLongitude,
643 17 : psCoord->dfLatitude);
644 125 : delete psCoord;
645 : }
646 : }
647 : }
648 : }
649 : }
650 : }
651 :
652 155 : if (poLinearRing)
653 24 : ((OGRPolygon*)poGeom)->addRingDirectly(poLinearRing);
654 : }
655 11 : else if (sName_.compare("MultiGeometry") == 0)
656 : {
657 11 : if (eType == MultiPoint)
658 3 : poGeom = new OGRMultiPoint();
659 8 : else if (eType == MultiLineString)
660 2 : poGeom = new OGRMultiLineString();
661 6 : else if (eType == MultiPolygon)
662 2 : poGeom = new OGRMultiPolygon();
663 : else
664 4 : poGeom = new OGRGeometryCollection();
665 26 : for(nCount = 0; nCount < pvpoChildren_->size(); nCount++)
666 : {
667 15 : OGRGeometry* poSubGeom = (*pvpoChildren_)[nCount]->getGeometry();
668 15 : if (poSubGeom)
669 15 : ((OGRGeometryCollection*)poGeom)->addGeometryDirectly(poSubGeom);
670 : }
671 : }
672 :
673 271 : return poGeom;
674 : }
675 :
676 430 : Feature* KMLNode::getFeature(std::size_t nNum, int& nLastAsked, int &nLastCount)
677 : {
678 430 : unsigned int nCount, nCountP = 0;
679 430 : KMLNode* poFeat = NULL;
680 430 : KMLNode* poTemp = NULL;
681 :
682 430 : if(nNum >= this->getNumFeatures())
683 87 : return NULL;
684 :
685 343 : if (nLastAsked + 1 != (int)nNum)
686 : {
687 0 : nCount = 0;
688 0 : nCountP = 0;
689 : }
690 : else
691 : {
692 343 : nCount = nLastCount + 1;
693 343 : nCountP = nLastAsked + 1;
694 : }
695 :
696 575 : for(; nCount < pvpoChildren_->size(); nCount++)
697 : {
698 575 : if((*pvpoChildren_)[nCount]->sName_.compare("Placemark") == 0)
699 : {
700 343 : if(nCountP == nNum)
701 : {
702 343 : poFeat = (*pvpoChildren_)[nCount];
703 343 : break;
704 : }
705 0 : nCountP++;
706 : }
707 : }
708 :
709 343 : nLastAsked = nNum;
710 343 : nLastCount = nCount;
711 :
712 343 : if(poFeat == NULL)
713 0 : return NULL;
714 :
715 : // Create a feature structure
716 343 : Feature *psReturn = new Feature;
717 : // Build up the name
718 686 : psReturn->sName = poFeat->getNameElement();
719 : // Build up the description
720 686 : psReturn->sDescription = poFeat->getDescriptionElement();
721 : // the type
722 343 : psReturn->eType = poFeat->eType_;
723 :
724 343 : std::string sElementName;
725 940 : if(poFeat->eType_ == Point ||
726 : poFeat->eType_ == LineString ||
727 : poFeat->eType_ == Polygon)
728 332 : sElementName = Nodetype2String(poFeat->eType_);
729 22 : else if (poFeat->eType_ == MultiGeometry ||
730 : poFeat->eType_ == MultiPoint ||
731 : poFeat->eType_ == MultiLineString ||
732 : poFeat->eType_ == MultiPolygon)
733 11 : sElementName = "MultiGeometry";
734 : else
735 : {
736 0 : delete psReturn;
737 0 : return NULL;
738 : }
739 :
740 806 : for(nCount = 0; nCount < poFeat->pvpoChildren_->size(); nCount++)
741 : {
742 806 : if((*poFeat->pvpoChildren_)[nCount]->sName_.compare(sElementName) == 0)
743 : {
744 343 : poTemp = (*poFeat->pvpoChildren_)[nCount];
745 343 : psReturn->poGeom = poTemp->getGeometry(poFeat->eType_);
746 343 : if(psReturn->poGeom)
747 343 : return psReturn;
748 : else
749 : {
750 0 : delete psReturn;
751 0 : return NULL;
752 : }
753 : }
754 : }
755 :
756 0 : delete psReturn;
757 0 : return NULL;
758 2139 : }
|