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