LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/kml - kmlnode.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 333 404 82.4 %
Date: 2024-11-21 22:18:42 Functions: 30 34 88.2 %

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

Generated by: LCOV version 1.14