1 : /******************************************************************************
2 : * $Id: kmlnode.cpp 24177 2012-03-31 10:22:36Z 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 558 : std::string Nodetype2String(Nodetype const& type)
40 : {
41 558 : if(type == Empty)
42 0 : return "Empty";
43 558 : else if(type == Rest)
44 0 : return "Rest";
45 558 : else if(type == Mixed)
46 4 : return "Mixed";
47 554 : else if(type == Point)
48 142 : return "Point";
49 412 : else if(type == LineString)
50 154 : return "LineString";
51 258 : else if(type == Polygon)
52 258 : 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 162912 : bool isNumberDigit(const char cIn)
67 : {
68 : return ( cIn == '-' || cIn == '+' ||
69 : (cIn >= '0' && cIn <= '9') ||
70 162912 : cIn == '.' || cIn == 'e' || cIn == 'E' );
71 : }
72 :
73 : static
74 4588 : Coordinate* ParseCoordinate(std::string const& text)
75 : {
76 4588 : int pos = 0;
77 4588 : const char* pszStr = text.c_str();
78 4588 : Coordinate *psTmp = new Coordinate();
79 :
80 : // X coordinate
81 4588 : psTmp->dfLongitude = CPLAtof(pszStr);
82 83646 : while(isNumberDigit(pszStr[pos++]));
83 :
84 : // Y coordinate
85 4588 : if(pszStr[pos - 1] != ',')
86 : {
87 0 : delete psTmp;
88 0 : return NULL;
89 : }
90 :
91 4588 : psTmp->dfLatitude = CPLAtof(pszStr + pos);
92 79266 : while(isNumberDigit(pszStr[pos++]));
93 :
94 : // Z coordinate
95 4588 : if(pszStr[pos - 1] != ',')
96 : {
97 162 : psTmp->bHasZ = FALSE;
98 162 : psTmp->dfAltitude = 0;
99 162 : return psTmp;
100 : }
101 :
102 4426 : psTmp->bHasZ = TRUE;
103 4426 : psTmp->dfAltitude = CPLAtof(pszStr + pos);
104 :
105 4426 : return psTmp;
106 : }
107 :
108 : /************************************************************************/
109 : /* KMLNode methods */
110 : /************************************************************************/
111 :
112 3380 : KMLNode::KMLNode()
113 : {
114 3380 : poParent_ = NULL;
115 3380 : pvpoChildren_ = new std::vector<KMLNode*>;
116 6760 : pvsContent_ = new std::vector<std::string>;
117 6760 : pvoAttributes_ = new std::vector<Attribute*>;
118 3380 : eType_ = Unknown;
119 3380 : nLayerNumber_ = -1;
120 3380 : b25D_ = FALSE;
121 3380 : nNumFeatures_ = -1;
122 3380 : }
123 :
124 3380 : KMLNode::~KMLNode()
125 : {
126 3380 : CPLAssert( NULL != pvpoChildren_ );
127 3380 : CPLAssert( NULL != pvoAttributes_ );
128 :
129 3380 : kml_nodes_t::iterator itChild;
130 4728 : for( itChild = pvpoChildren_->begin();
131 : itChild != pvpoChildren_->end(); ++itChild)
132 : {
133 1348 : delete (*itChild);
134 : }
135 3380 : delete pvpoChildren_;
136 :
137 3380 : kml_attributes_t::iterator itAttr;
138 4198 : for( itAttr = pvoAttributes_->begin();
139 : itAttr != pvoAttributes_->end(); ++itAttr)
140 : {
141 818 : delete (*itAttr);
142 : }
143 3380 : delete pvoAttributes_;
144 :
145 3380 : delete pvsContent_;
146 3380 : }
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 1334 : int KMLNode::classify(KML* poKML, int nRecLevel)
204 : {
205 1334 : Nodetype curr = Unknown;
206 1334 : Nodetype all = Empty;
207 :
208 : /* Arbitrary value, but certainly large enough for reasonable usages ! */
209 1334 : 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 NULL;
215 : }
216 :
217 : //CPLDebug("KML", "%s<%s>", genSpaces(), sName_.c_str());
218 : //nDepth ++;
219 :
220 1334 : if(sName_.compare("Point") == 0)
221 54 : eType_ = Point;
222 1280 : else if(sName_.compare("LineString") == 0)
223 54 : eType_ = LineString;
224 1226 : else if(sName_.compare("Polygon") == 0)
225 80 : eType_ = Polygon;
226 1146 : else if(poKML->isRest(sName_))
227 198 : eType_ = Empty;
228 948 : else if(sName_.compare("coordinates") == 0)
229 : {
230 : unsigned int nCountP;
231 1466 : for(nCountP = 0; nCountP < pvsContent_->size(); nCountP++)
232 : {
233 1268 : const char* pszCoord = (*pvsContent_)[nCountP].c_str();
234 1268 : int nComma = 0;
235 2368 : while(TRUE)
236 : {
237 3636 : pszCoord = strchr(pszCoord, ',');
238 3636 : if (pszCoord)
239 : {
240 2368 : nComma ++;
241 2368 : pszCoord ++;
242 : }
243 : else
244 : break;
245 : }
246 1268 : if (nComma == 2)
247 1100 : b25D_ = TRUE;
248 : }
249 : }
250 :
251 1334 : const kml_nodes_t::size_type size = pvpoChildren_->size();
252 2650 : 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 1316 : if (!(*pvpoChildren_)[z]->classify(poKML, nRecLevel + 1))
258 0 : return FALSE;
259 :
260 1316 : curr = (*pvpoChildren_)[z]->eType_;
261 1316 : b25D_ |= (*pvpoChildren_)[z]->b25D_;
262 :
263 : // Compare and return if it is mixed
264 1372 : if(curr != all && all != Empty && curr != Empty)
265 : {
266 56 : if (sName_.compare("MultiGeometry") == 0)
267 4 : eType_ = MultiGeometry;
268 : else
269 52 : eType_ = Mixed;
270 : }
271 1260 : else if(curr != Empty)
272 : {
273 398 : all = curr;
274 : }
275 : }
276 :
277 1334 : if(eType_ == Unknown)
278 : {
279 932 : if (sName_.compare("MultiGeometry") == 0)
280 : {
281 18 : if (all == Point)
282 6 : eType_ = MultiPoint;
283 12 : else if (all == LineString)
284 4 : eType_ = MultiLineString;
285 8 : else if (all == Polygon)
286 4 : eType_ = MultiPolygon;
287 : else
288 4 : eType_ = MultiGeometry;
289 : }
290 : else
291 914 : eType_ = all;
292 : }
293 :
294 : //nDepth --;
295 : //CPLDebug("KML", "%s</%s> --> eType=%s", genSpaces(), sName_.c_str(), Nodetype2String(eType_).c_str());
296 :
297 1334 : return TRUE;
298 : }
299 :
300 1242 : void KMLNode::eliminateEmpty(KML* poKML)
301 : {
302 2496 : for(kml_nodes_t::size_type z = 0; z < pvpoChildren_->size(); z++)
303 : {
304 2842 : if((*pvpoChildren_)[z]->eType_ == Empty
305 800 : && (poKML->isContainer((*pvpoChildren_)[z]->sName_)
306 788 : || poKML->isFeatureContainer((*pvpoChildren_)[z]->sName_)))
307 : {
308 28 : delete (*pvpoChildren_)[z];
309 28 : pvpoChildren_->erase(pvpoChildren_->begin() + z);
310 28 : z--;
311 : }
312 : else
313 : {
314 1226 : (*pvpoChildren_)[z]->eliminateEmpty(poKML);
315 : }
316 : }
317 1242 : }
318 :
319 38 : bool KMLNode::hasOnlyEmpty() const
320 : {
321 58 : for(kml_nodes_t::size_type z = 0; z < pvpoChildren_->size(); z++)
322 : {
323 34 : if((*pvpoChildren_)[z]->eType_ != Empty)
324 : {
325 14 : return false;
326 : }
327 : else
328 : {
329 20 : if (!(*pvpoChildren_)[z]->hasOnlyEmpty())
330 0 : return false;
331 : }
332 : }
333 :
334 24 : return true;
335 : }
336 :
337 0 : void KMLNode::setType(Nodetype oNotet)
338 : {
339 0 : eType_ = oNotet;
340 0 : }
341 :
342 190 : Nodetype KMLNode::getType() const
343 : {
344 190 : return eType_;
345 : }
346 :
347 3380 : void KMLNode::setName(std::string const& sIn)
348 : {
349 3380 : sName_ = sIn;
350 3380 : }
351 :
352 11194 : const std::string& KMLNode::getName() const
353 : {
354 11194 : return sName_;
355 : }
356 :
357 3380 : void KMLNode::setLevel(std::size_t nLev)
358 : {
359 3380 : nLevel_ = nLev;
360 3380 : }
361 :
362 0 : std::size_t KMLNode::getLevel() const
363 : {
364 0 : return nLevel_;
365 : }
366 :
367 818 : void KMLNode::addAttribute(Attribute *poAttr)
368 : {
369 818 : pvoAttributes_->push_back(poAttr);
370 818 : }
371 :
372 3362 : void KMLNode::setParent(KMLNode* poPar)
373 : {
374 3362 : poParent_ = poPar;
375 3362 : }
376 :
377 6742 : KMLNode* KMLNode::getParent() const
378 : {
379 6742 : return poParent_;
380 : }
381 :
382 1376 : void KMLNode::addChildren(KMLNode *poChil)
383 : {
384 1376 : pvpoChildren_->push_back(poChil);
385 1376 : }
386 :
387 466 : std::size_t KMLNode::countChildren()
388 : {
389 466 : return pvpoChildren_->size();
390 : }
391 :
392 752 : KMLNode* KMLNode::getChild(std::size_t index) const
393 : {
394 752 : return (*pvpoChildren_)[index];
395 : }
396 :
397 5342 : void KMLNode::addContent(std::string const& text)
398 : {
399 5342 : pvsContent_->push_back(text);
400 5342 : }
401 :
402 10634 : void KMLNode::appendContent(std::string const& text)
403 : {
404 10634 : std::string& tmp = (*pvsContent_)[pvsContent_->size() - 1];
405 10634 : tmp += text;
406 10634 : }
407 :
408 2994 : std::string KMLNode::getContent(std::size_t index) const
409 : {
410 2994 : return (*pvsContent_)[index];
411 : }
412 :
413 1268 : void KMLNode::deleteContent(std::size_t index)
414 : {
415 1268 : if( index < pvsContent_->size() )
416 : {
417 1268 : pvsContent_->erase(pvsContent_->begin() + index);
418 : }
419 1268 : }
420 :
421 17206 : std::size_t KMLNode::numContent()
422 : {
423 17206 : return pvsContent_->size();
424 : }
425 :
426 50 : void KMLNode::setLayerNumber(int nNum)
427 : {
428 50 : nLayerNumber_ = nNum;
429 50 : }
430 :
431 0 : int KMLNode::getLayerNumber() const
432 : {
433 0 : return nLayerNumber_;
434 : }
435 :
436 584 : std::string KMLNode::getNameElement() const
437 : {
438 584 : kml_nodes_t::size_type subsize = 0;
439 584 : kml_nodes_t::size_type size = pvpoChildren_->size();
440 :
441 646 : for( kml_nodes_t::size_type i = 0; i < size; ++i )
442 : {
443 584 : if( (*pvpoChildren_)[i]->sName_.compare("name") == 0 )
444 : {
445 522 : subsize = (*pvpoChildren_)[i]->pvsContent_->size();
446 522 : if( subsize > 0 )
447 : {
448 522 : return (*(*pvpoChildren_)[i]->pvsContent_)[0];
449 : }
450 0 : break;
451 : }
452 : }
453 62 : return "";
454 : }
455 :
456 534 : std::string KMLNode::getDescriptionElement() const
457 : {
458 534 : kml_nodes_t::size_type subsize = 0;
459 534 : kml_nodes_t::size_type size = pvpoChildren_->size();
460 1318 : for( kml_nodes_t::size_type i = 0; i < size; ++i )
461 : {
462 1010 : if( (*pvpoChildren_)[i]->sName_.compare("description") == 0 )
463 : {
464 226 : subsize = (*pvpoChildren_)[i]->pvsContent_->size();
465 226 : if ( subsize > 0 )
466 : {
467 226 : return (*(*pvpoChildren_)[i]->pvsContent_)[0];
468 : }
469 0 : break;
470 : }
471 : }
472 308 : return "";
473 : }
474 :
475 718 : std::size_t KMLNode::getNumFeatures()
476 : {
477 718 : if (nNumFeatures_ < 0)
478 : {
479 36 : std::size_t nNum = 0;
480 36 : kml_nodes_t::size_type size = pvpoChildren_->size();
481 :
482 230 : for( kml_nodes_t::size_type i = 0; i < size; ++i )
483 : {
484 194 : if( (*pvpoChildren_)[i]->sName_ == "Placemark" )
485 138 : nNum++;
486 : }
487 36 : nNumFeatures_ = (int)nNum;
488 : }
489 718 : return nNumFeatures_;
490 : }
491 :
492 564 : OGRGeometry* KMLNode::getGeometry(Nodetype eType)
493 : {
494 : unsigned int nCount, nCount2, nCountP;
495 564 : OGRGeometry* poGeom = NULL;
496 564 : KMLNode* poCoor = NULL;
497 564 : Coordinate* psCoord = NULL;
498 :
499 564 : if (sName_.compare("Point") == 0)
500 : {
501 : // Search coordinate Element
502 188 : for(nCount = 0; nCount < pvpoChildren_->size(); nCount++)
503 : {
504 184 : if((*pvpoChildren_)[nCount]->sName_.compare("coordinates") == 0)
505 : {
506 136 : poCoor = (*pvpoChildren_)[nCount];
507 136 : for(nCountP = 0; nCountP < poCoor->pvsContent_->size(); nCountP++)
508 : {
509 134 : psCoord = ParseCoordinate((*poCoor->pvsContent_)[nCountP]);
510 134 : if(psCoord != NULL)
511 : {
512 134 : if (psCoord->bHasZ)
513 : poGeom = new OGRPoint(psCoord->dfLongitude,
514 : psCoord->dfLatitude,
515 118 : psCoord->dfAltitude);
516 : else
517 : poGeom = new OGRPoint(psCoord->dfLongitude,
518 16 : psCoord->dfLatitude);
519 134 : delete psCoord;
520 134 : return poGeom;
521 : }
522 : }
523 : }
524 : }
525 4 : poGeom = new OGRPoint();
526 : }
527 426 : else if (sName_.compare("LineString") == 0)
528 : {
529 : // Search coordinate Element
530 158 : poGeom = new OGRLineString();
531 398 : for(nCount = 0; nCount < pvpoChildren_->size(); nCount++)
532 : {
533 240 : if((*pvpoChildren_)[nCount]->sName_.compare("coordinates") == 0)
534 : {
535 156 : poCoor = (*pvpoChildren_)[nCount];
536 1220 : for(nCountP = 0; nCountP < poCoor->pvsContent_->size(); nCountP++)
537 : {
538 1064 : psCoord = ParseCoordinate((*poCoor->pvsContent_)[nCountP]);
539 1064 : if(psCoord != NULL)
540 : {
541 1064 : if (psCoord->bHasZ)
542 : ((OGRLineString*)poGeom)->addPoint(psCoord->dfLongitude,
543 : psCoord->dfLatitude,
544 1036 : psCoord->dfAltitude);
545 : else
546 : ((OGRLineString*)poGeom)->addPoint(psCoord->dfLongitude,
547 28 : psCoord->dfLatitude);
548 1064 : delete psCoord;
549 : }
550 : }
551 : }
552 : }
553 : }
554 268 : else if (sName_.compare("Polygon") == 0)
555 : {
556 : //*********************************
557 : // Search outerBoundaryIs Element
558 : //*********************************
559 246 : poGeom = new OGRPolygon();
560 752 : for(nCount = 0; nCount < pvpoChildren_->size(); nCount++)
561 : {
562 506 : if((*pvpoChildren_)[nCount]->sName_.compare("outerBoundaryIs") == 0 &&
563 : (*pvpoChildren_)[nCount]->pvpoChildren_->size() > 0)
564 : {
565 242 : poCoor = (*(*pvpoChildren_)[nCount]->pvpoChildren_)[0];
566 : }
567 : }
568 : // No outer boundary found
569 246 : if(poCoor == NULL)
570 : {
571 4 : return poGeom;
572 : }
573 : // Search coordinate Element
574 242 : OGRLinearRing* poLinearRing = NULL;
575 482 : for(nCount = 0; nCount < poCoor->pvpoChildren_->size(); nCount++)
576 : {
577 240 : if((*poCoor->pvpoChildren_)[nCount]->sName_.compare("coordinates") == 0)
578 : {
579 3428 : for(nCountP = 0; nCountP < (*poCoor->pvpoChildren_)[nCount]->pvsContent_->size(); nCountP++)
580 : {
581 3188 : psCoord = ParseCoordinate((*(*poCoor->pvpoChildren_)[nCount]->pvsContent_)[nCountP]);
582 3188 : if(psCoord != NULL)
583 : {
584 3188 : if (poLinearRing == NULL)
585 : {
586 238 : poLinearRing = new OGRLinearRing();
587 : }
588 3188 : if (psCoord->bHasZ)
589 : poLinearRing->addPoint(psCoord->dfLongitude,
590 : psCoord->dfLatitude,
591 3104 : psCoord->dfAltitude);
592 : else
593 : poLinearRing->addPoint(psCoord->dfLongitude,
594 84 : psCoord->dfLatitude);
595 3188 : delete psCoord;
596 : }
597 : }
598 : }
599 : }
600 : // No outer boundary coordinates found
601 242 : if(poLinearRing == NULL)
602 : {
603 4 : return poGeom;
604 : }
605 :
606 238 : ((OGRPolygon*)poGeom)->addRingDirectly(poLinearRing);
607 238 : poLinearRing = NULL;
608 :
609 : //*********************************
610 : // Search innerBoundaryIs Elements
611 : //*********************************
612 :
613 738 : for(nCount2 = 0; nCount2 < pvpoChildren_->size(); nCount2++)
614 : {
615 500 : if((*pvpoChildren_)[nCount2]->sName_.compare("innerBoundaryIs") == 0)
616 : {
617 42 : if (poLinearRing)
618 0 : ((OGRPolygon*)poGeom)->addRingDirectly(poLinearRing);
619 42 : poLinearRing = NULL;
620 :
621 42 : if ((*pvpoChildren_)[nCount2]->pvpoChildren_->size() == 0)
622 2 : continue;
623 :
624 40 : poLinearRing = new OGRLinearRing();
625 :
626 40 : poCoor = (*(*pvpoChildren_)[nCount2]->pvpoChildren_)[0];
627 : // Search coordinate Element
628 78 : for(nCount = 0; nCount < poCoor->pvpoChildren_->size(); nCount++)
629 : {
630 38 : if((*poCoor->pvpoChildren_)[nCount]->sName_.compare("coordinates") == 0)
631 : {
632 240 : for(nCountP = 0; nCountP < (*poCoor->pvpoChildren_)[nCount]->pvsContent_->size(); nCountP++)
633 : {
634 202 : psCoord = ParseCoordinate((*(*poCoor->pvpoChildren_)[nCount]->pvsContent_)[nCountP]);
635 202 : if(psCoord != NULL)
636 : {
637 202 : if (psCoord->bHasZ)
638 : poLinearRing->addPoint(psCoord->dfLongitude,
639 : psCoord->dfLatitude,
640 168 : psCoord->dfAltitude);
641 : else
642 : poLinearRing->addPoint(psCoord->dfLongitude,
643 34 : psCoord->dfLatitude);
644 202 : delete psCoord;
645 : }
646 : }
647 : }
648 : }
649 : }
650 : }
651 :
652 238 : if (poLinearRing)
653 40 : ((OGRPolygon*)poGeom)->addRingDirectly(poLinearRing);
654 : }
655 22 : else if (sName_.compare("MultiGeometry") == 0)
656 : {
657 22 : if (eType == MultiPoint)
658 6 : poGeom = new OGRMultiPoint();
659 16 : else if (eType == MultiLineString)
660 4 : poGeom = new OGRMultiLineString();
661 12 : else if (eType == MultiPolygon)
662 4 : poGeom = new OGRMultiPolygon();
663 : else
664 8 : poGeom = new OGRGeometryCollection();
665 52 : for(nCount = 0; nCount < pvpoChildren_->size(); nCount++)
666 : {
667 30 : OGRGeometry* poSubGeom = (*pvpoChildren_)[nCount]->getGeometry();
668 30 : if (poSubGeom)
669 30 : ((OGRGeometryCollection*)poGeom)->addGeometryDirectly(poSubGeom);
670 : }
671 : }
672 :
673 422 : return poGeom;
674 : }
675 :
676 660 : Feature* KMLNode::getFeature(std::size_t nNum, int& nLastAsked, int &nLastCount)
677 : {
678 660 : unsigned int nCount, nCountP = 0;
679 660 : KMLNode* poFeat = NULL;
680 660 : KMLNode* poTemp = NULL;
681 :
682 660 : if(nNum >= this->getNumFeatures())
683 126 : return NULL;
684 :
685 534 : if (nLastAsked + 1 != (int)nNum)
686 : {
687 0 : nCount = 0;
688 0 : nCountP = 0;
689 : }
690 : else
691 : {
692 534 : nCount = nLastCount + 1;
693 534 : nCountP = nLastAsked + 1;
694 : }
695 :
696 902 : for(; nCount < pvpoChildren_->size(); nCount++)
697 : {
698 902 : if((*pvpoChildren_)[nCount]->sName_.compare("Placemark") == 0)
699 : {
700 534 : if(nCountP == nNum)
701 : {
702 534 : poFeat = (*pvpoChildren_)[nCount];
703 534 : break;
704 : }
705 0 : nCountP++;
706 : }
707 : }
708 :
709 534 : nLastAsked = nNum;
710 534 : nLastCount = nCount;
711 :
712 534 : if(poFeat == NULL)
713 0 : return NULL;
714 :
715 : // Create a feature structure
716 534 : Feature *psReturn = new Feature;
717 : // Build up the name
718 1068 : psReturn->sName = poFeat->getNameElement();
719 : // Build up the description
720 1068 : psReturn->sDescription = poFeat->getDescriptionElement();
721 : // the type
722 534 : psReturn->eType = poFeat->eType_;
723 :
724 534 : std::string sElementName;
725 1456 : if(poFeat->eType_ == Point ||
726 : poFeat->eType_ == LineString ||
727 : poFeat->eType_ == Polygon)
728 512 : sElementName = Nodetype2String(poFeat->eType_);
729 44 : else if (poFeat->eType_ == MultiGeometry ||
730 : poFeat->eType_ == MultiPoint ||
731 : poFeat->eType_ == MultiLineString ||
732 : poFeat->eType_ == MultiPolygon)
733 22 : sElementName = "MultiGeometry";
734 : else
735 : {
736 0 : delete psReturn;
737 0 : return NULL;
738 : }
739 :
740 1236 : for(nCount = 0; nCount < poFeat->pvpoChildren_->size(); nCount++)
741 : {
742 1236 : if((*poFeat->pvpoChildren_)[nCount]->sName_.compare(sElementName) == 0)
743 : {
744 534 : poTemp = (*poFeat->pvpoChildren_)[nCount];
745 534 : psReturn->poGeom = poTemp->getGeometry(poFeat->eType_);
746 534 : if(psReturn->poGeom)
747 534 : 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 4029 : }
|