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

Generated by: LCOV version 1.14