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