LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/kml - kmlnode.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 355 300 84.5 %
Date: 2012-04-28 Functions: 38 31 81.6 %

       1                 : /******************************************************************************
       2                 :  * $Id: kmlnode.cpp 24177 2012-03-31 10:22:36Z rouault $
       3                 :  *
       4                 :  * Project:  KML Driver
       5                 :  * Purpose:  Class for building up the node structure of the kml file.
       6                 :  * Author:   Jens Oberender, j.obi@troja.net
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2007, Jens Oberender
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : #include "kmlnode.h"
      30                 : #include "cpl_conv.h"
      31                 : // std
      32                 : #include <string>
      33                 : #include <vector>
      34                 : 
      35                 : /************************************************************************/
      36                 : /*                           Help functions                             */
      37                 : /************************************************************************/
      38                 : 
      39             558 : std::string Nodetype2String(Nodetype const& type)
      40                 : {
      41             558 :     if(type == Empty)
      42               0 :         return "Empty";
      43             558 :     else if(type == Rest)
      44               0 :         return "Rest";
      45             558 :     else if(type == Mixed)
      46               4 :         return "Mixed";
      47             554 :     else if(type == Point)
      48             142 :         return "Point";
      49             412 :     else if(type == LineString)
      50             154 :         return "LineString";
      51             258 :     else if(type == Polygon)
      52             258 :         return "Polygon";
      53               0 :     else if(type == MultiGeometry)
      54               0 :         return "MultiGeometry";
      55               0 :     else if(type == MultiPoint)
      56               0 :         return "MultiPoint";
      57               0 :     else if(type == MultiLineString)
      58               0 :         return "MultiLineString";
      59               0 :     else if(type == MultiPolygon)
      60               0 :         return "MultiPolygon";
      61                 :     else
      62               0 :         return "Unknown";
      63                 : }
      64                 : 
      65                 : static
      66          162912 : bool isNumberDigit(const char cIn)
      67                 : {
      68                 :     return ( cIn == '-' || cIn == '+' || 
      69                 :             (cIn >= '0' && cIn <= '9') ||
      70          162912 :              cIn == '.' || cIn == 'e' || cIn == 'E' );
      71                 : }
      72                 : 
      73                 : static
      74            4588 : Coordinate* ParseCoordinate(std::string const& text)
      75                 : {
      76            4588 :     int pos = 0;
      77            4588 :     const char* pszStr = text.c_str();
      78            4588 :     Coordinate *psTmp = new Coordinate();
      79                 : 
      80                 :     // X coordinate
      81            4588 :     psTmp->dfLongitude = CPLAtof(pszStr);
      82           83646 :     while(isNumberDigit(pszStr[pos++]));
      83                 : 
      84                 :     // Y coordinate
      85            4588 :     if(pszStr[pos - 1] != ',')
      86                 :     {
      87               0 :         delete psTmp;
      88               0 :         return NULL;
      89                 :     }
      90                 : 
      91            4588 :     psTmp->dfLatitude = CPLAtof(pszStr + pos);
      92           79266 :     while(isNumberDigit(pszStr[pos++]));
      93                 : 
      94                 :     // Z coordinate
      95            4588 :     if(pszStr[pos - 1] != ',')
      96                 :     {
      97             162 :         psTmp->bHasZ = FALSE;
      98             162 :         psTmp->dfAltitude = 0;
      99             162 :         return psTmp;
     100                 :     }
     101                 : 
     102            4426 :     psTmp->bHasZ = TRUE;
     103            4426 :     psTmp->dfAltitude = CPLAtof(pszStr + pos);
     104                 : 
     105            4426 :     return psTmp;
     106                 : }
     107                 : 
     108                 : /************************************************************************/
     109                 : /*                         KMLNode methods                              */
     110                 : /************************************************************************/
     111                 : 
     112            3380 : KMLNode::KMLNode()
     113                 : {
     114            3380 :     poParent_ = NULL;
     115            3380 :     pvpoChildren_ = new std::vector<KMLNode*>;
     116            6760 :     pvsContent_ = new std::vector<std::string>;
     117            6760 :     pvoAttributes_ = new std::vector<Attribute*>;
     118            3380 :     eType_ = Unknown;
     119            3380 :     nLayerNumber_ = -1;
     120            3380 :     b25D_ = FALSE;
     121            3380 :     nNumFeatures_ = -1;
     122            3380 : }
     123                 : 
     124            3380 : KMLNode::~KMLNode()
     125                 : {
     126            3380 :     CPLAssert( NULL != pvpoChildren_ );
     127            3380 :     CPLAssert( NULL != pvoAttributes_ );
     128                 : 
     129            3380 :     kml_nodes_t::iterator itChild;
     130            4728 :     for( itChild = pvpoChildren_->begin();
     131                 :          itChild != pvpoChildren_->end(); ++itChild)
     132                 :     {
     133            1348 :         delete (*itChild);
     134                 :     }
     135            3380 :     delete pvpoChildren_;
     136                 : 
     137            3380 :     kml_attributes_t::iterator itAttr;
     138            4198 :     for( itAttr = pvoAttributes_->begin();
     139                 :          itAttr != pvoAttributes_->end(); ++itAttr)
     140                 :     {
     141             818 :         delete (*itAttr);
     142                 :     }
     143            3380 :     delete pvoAttributes_;
     144                 : 
     145            3380 :     delete pvsContent_;
     146            3380 : }
     147                 : 
     148               0 : void KMLNode::print(unsigned int what)
     149                 : {
     150               0 :     std::string indent;
     151               0 :     for(std::size_t l = 0; l < nLevel_; l++)
     152               0 :         indent += " ";
     153                 : 
     154               0 :     if(nLevel_ > 0)
     155                 :     {
     156               0 :         if(nLayerNumber_ > -1)
     157                 :         {
     158                 :             CPLDebug("KML", "%s%s (nLevel: %d Type: %s poParent: %s pvpoChildren_: %d pvsContent_: %d pvoAttributes_: %d) <--- Layer #%d", 
     159                 :                         indent.c_str(), sName_.c_str(), (int) nLevel_, Nodetype2String(eType_).c_str(), poParent_->sName_.c_str(), 
     160               0 :                         (int) pvpoChildren_->size(), (int) pvsContent_->size(), (int) pvoAttributes_->size(), nLayerNumber_);
     161                 :         }
     162                 :         else
     163                 :         {
     164                 :             CPLDebug("KML", "%s%s (nLevel: %d Type: %s poParent: %s pvpoChildren_: %d pvsContent_: %d pvoAttributes_: %d)", 
     165                 :                         indent.c_str(), sName_.c_str(), (int) nLevel_, Nodetype2String(eType_).c_str(), poParent_->sName_.c_str(), 
     166               0 :                         (int) pvpoChildren_->size(), (int) pvsContent_->size(), (int) pvoAttributes_->size());
     167                 :         }
     168                 :     }
     169                 :     else
     170                 :     {
     171                 :         CPLDebug("KML", "%s%s (nLevel: %d Type: %s pvpoChildren_: %d pvsContent_: %d pvoAttributes_: %d)", 
     172                 :                  indent.c_str(), sName_.c_str(), (int) nLevel_, Nodetype2String(eType_).c_str(), (int) pvpoChildren_->size(), 
     173               0 :                  (int) pvsContent_->size(), (int) pvoAttributes_->size());
     174                 :     }
     175                 : 
     176               0 :     if(what == 1 || what == 3)
     177                 :     {
     178               0 :         for(kml_content_t::size_type z = 0; z < pvsContent_->size(); z++)
     179               0 :             CPLDebug("KML", "%s|->pvsContent_: '%s'", indent.c_str(), (*pvsContent_)[z].c_str());
     180                 :     }
     181                 : 
     182               0 :     if(what == 2 || what == 3)
     183                 :     {
     184               0 :         for(kml_attributes_t::size_type z = 0; z < pvoAttributes_->size(); z++)
     185               0 :             CPLDebug("KML", "%s|->pvoAttributes_: %s = '%s'", indent.c_str(), (*pvoAttributes_)[z]->sName.c_str(), (*pvoAttributes_)[z]->sValue.c_str());
     186                 :     }
     187                 : 
     188               0 :     for(kml_nodes_t::size_type z = 0; z < pvpoChildren_->size(); z++)
     189               0 :         (*pvpoChildren_)[z]->print(what);
     190               0 : }
     191                 : 
     192                 : //static int nDepth = 0;
     193                 : //static char* genSpaces()
     194                 : //{
     195                 : //    static char spaces[128];
     196                 : //    int i;
     197                 : //    for(i=0;i<nDepth;i++)
     198                 : //        spaces[i] = ' ';
     199                 : //    spaces[i] = '\0';
     200                 : //    return spaces;
     201                 : //}
     202                 : 
     203            1334 : int KMLNode::classify(KML* poKML, int nRecLevel)
     204                 : {
     205            1334 :     Nodetype curr = Unknown;
     206            1334 :     Nodetype all = Empty;
     207                 : 
     208                 :     /* Arbitrary value, but certainly large enough for reasonable usages ! */
     209            1334 :     if( nRecLevel == 32 )
     210                 :     {
     211                 :         CPLError( CE_Failure, CPLE_AppDefined,
     212                 :                     "Too many recursiong level (%d) while parsing KML geometry.",
     213               0 :                     nRecLevel );
     214               0 :         return NULL;
     215                 :     }
     216                 : 
     217                 :     //CPLDebug("KML", "%s<%s>", genSpaces(), sName_.c_str());
     218                 :     //nDepth ++;
     219                 :     
     220            1334 :     if(sName_.compare("Point") == 0)
     221              54 :         eType_ = Point;
     222            1280 :     else if(sName_.compare("LineString") == 0)
     223              54 :         eType_ = LineString;
     224            1226 :     else if(sName_.compare("Polygon") == 0)
     225              80 :         eType_ = Polygon;
     226            1146 :     else if(poKML->isRest(sName_))
     227             198 :         eType_ = Empty;
     228             948 :     else if(sName_.compare("coordinates") == 0)
     229                 :     {
     230                 :         unsigned int nCountP;
     231            1466 :         for(nCountP = 0; nCountP < pvsContent_->size(); nCountP++)
     232                 :         {
     233            1268 :             const char* pszCoord = (*pvsContent_)[nCountP].c_str();
     234            1268 :             int nComma = 0;
     235            2368 :             while(TRUE)
     236                 :             {
     237            3636 :                 pszCoord = strchr(pszCoord, ',');
     238            3636 :                 if (pszCoord)
     239                 :                 {
     240            2368 :                     nComma ++;
     241            2368 :                     pszCoord ++;
     242                 :                 }
     243                 :                 else
     244                 :                     break;
     245                 :             }
     246            1268 :             if (nComma == 2)
     247            1100 :                 b25D_ = TRUE;
     248                 :         }
     249                 :     }
     250                 : 
     251            1334 :     const kml_nodes_t::size_type size = pvpoChildren_->size();
     252            2650 :     for(kml_nodes_t::size_type z = 0; z < size; z++)
     253                 :     {
     254                 :         //CPLDebug("KML", "%s[%d] %s", genSpaces(), z, (*pvpoChildren_)[z]->sName_.c_str());
     255                 : 
     256                 :         // Classify pvpoChildren_
     257            1316 :         if (!(*pvpoChildren_)[z]->classify(poKML, nRecLevel + 1))
     258               0 :             return FALSE;
     259                 : 
     260            1316 :         curr = (*pvpoChildren_)[z]->eType_;
     261            1316 :         b25D_ |= (*pvpoChildren_)[z]->b25D_;
     262                 : 
     263                 :         // Compare and return if it is mixed
     264            1372 :         if(curr != all && all != Empty && curr != Empty)
     265                 :         {
     266              56 :             if (sName_.compare("MultiGeometry") == 0)
     267               4 :                 eType_ = MultiGeometry;
     268                 :             else
     269              52 :                 eType_ = Mixed;
     270                 :         }
     271            1260 :         else if(curr != Empty)
     272                 :         {
     273             398 :             all = curr;
     274                 :         }
     275                 :     }
     276                 : 
     277            1334 :     if(eType_ == Unknown)
     278                 :     {
     279             932 :         if (sName_.compare("MultiGeometry") == 0)
     280                 :         {
     281              18 :             if (all == Point)
     282               6 :                 eType_ = MultiPoint;
     283              12 :             else if (all == LineString)
     284               4 :                 eType_ = MultiLineString;
     285               8 :             else if (all == Polygon)
     286               4 :                 eType_ = MultiPolygon;
     287                 :             else
     288               4 :                 eType_ = MultiGeometry;
     289                 :         }
     290                 :         else
     291             914 :             eType_ = all;
     292                 :     }
     293                 : 
     294                 :     //nDepth --;
     295                 :     //CPLDebug("KML", "%s</%s> --> eType=%s", genSpaces(), sName_.c_str(), Nodetype2String(eType_).c_str());
     296                 : 
     297            1334 :     return TRUE;
     298                 : }
     299                 : 
     300            1242 : void KMLNode::eliminateEmpty(KML* poKML)
     301                 : {
     302            2496 :     for(kml_nodes_t::size_type z = 0; z < pvpoChildren_->size(); z++)
     303                 :     {
     304            2842 :         if((*pvpoChildren_)[z]->eType_ == Empty
     305             800 :            && (poKML->isContainer((*pvpoChildren_)[z]->sName_)
     306             788 :                || poKML->isFeatureContainer((*pvpoChildren_)[z]->sName_)))
     307                 :         {
     308              28 :             delete (*pvpoChildren_)[z];
     309              28 :             pvpoChildren_->erase(pvpoChildren_->begin() + z);
     310              28 :             z--;
     311                 :         }
     312                 :         else
     313                 :         {
     314            1226 :             (*pvpoChildren_)[z]->eliminateEmpty(poKML);
     315                 :         }
     316                 :     }
     317            1242 : }
     318                 : 
     319              38 : bool KMLNode::hasOnlyEmpty() const
     320                 : {
     321              58 :     for(kml_nodes_t::size_type z = 0; z < pvpoChildren_->size(); z++)
     322                 :     {
     323              34 :         if((*pvpoChildren_)[z]->eType_ != Empty)
     324                 :         {
     325              14 :             return false;
     326                 :         }
     327                 :         else
     328                 :         {
     329              20 :             if (!(*pvpoChildren_)[z]->hasOnlyEmpty())
     330               0 :                 return false;
     331                 :         }
     332                 :     }
     333                 : 
     334              24 :     return true;
     335                 : }
     336                 : 
     337               0 : void KMLNode::setType(Nodetype oNotet)
     338                 : {
     339               0 :     eType_ = oNotet;
     340               0 : }
     341                 : 
     342             190 : Nodetype KMLNode::getType() const
     343                 : {
     344             190 :     return eType_;
     345                 : }
     346                 : 
     347            3380 : void KMLNode::setName(std::string const& sIn)
     348                 : {
     349            3380 :     sName_ = sIn;
     350            3380 : }
     351                 : 
     352           11194 : const std::string& KMLNode::getName() const
     353                 : {
     354           11194 :     return sName_;
     355                 : }
     356                 : 
     357            3380 : void KMLNode::setLevel(std::size_t nLev)
     358                 : {
     359            3380 :     nLevel_ = nLev;
     360            3380 : }
     361                 : 
     362               0 : std::size_t KMLNode::getLevel() const
     363                 : {
     364               0 :     return nLevel_;
     365                 : }
     366                 : 
     367             818 : void KMLNode::addAttribute(Attribute *poAttr)
     368                 : {
     369             818 :     pvoAttributes_->push_back(poAttr);
     370             818 : }
     371                 : 
     372            3362 : void KMLNode::setParent(KMLNode* poPar)
     373                 : {
     374            3362 :     poParent_ = poPar;
     375            3362 : }
     376                 : 
     377            6742 : KMLNode* KMLNode::getParent() const
     378                 : {
     379            6742 :     return poParent_;
     380                 : }
     381                 : 
     382            1376 : void KMLNode::addChildren(KMLNode *poChil)
     383                 : {
     384            1376 :     pvpoChildren_->push_back(poChil);
     385            1376 : }
     386                 : 
     387             466 : std::size_t KMLNode::countChildren()
     388                 : {
     389             466 :     return pvpoChildren_->size();
     390                 : }
     391                 : 
     392             752 : KMLNode* KMLNode::getChild(std::size_t index) const
     393                 : {
     394             752 :     return (*pvpoChildren_)[index];
     395                 : }
     396                 : 
     397            5342 : void KMLNode::addContent(std::string const& text)
     398                 : {
     399            5342 :     pvsContent_->push_back(text);
     400            5342 : }
     401                 : 
     402           10634 : void KMLNode::appendContent(std::string const& text)
     403                 : {
     404           10634 :     std::string& tmp = (*pvsContent_)[pvsContent_->size() - 1];
     405           10634 :     tmp += text;
     406           10634 : }
     407                 : 
     408            2994 : std::string KMLNode::getContent(std::size_t index) const
     409                 : {
     410            2994 :     return (*pvsContent_)[index];
     411                 : }
     412                 : 
     413            1268 : void KMLNode::deleteContent(std::size_t index)
     414                 : {
     415            1268 :     if( index < pvsContent_->size() )
     416                 :     {
     417            1268 :         pvsContent_->erase(pvsContent_->begin() + index);
     418                 :     }
     419            1268 : }
     420                 : 
     421           17206 : std::size_t KMLNode::numContent()
     422                 : {
     423           17206 :     return pvsContent_->size();
     424                 : }
     425                 : 
     426              50 : void KMLNode::setLayerNumber(int nNum)
     427                 : {
     428              50 :     nLayerNumber_ = nNum;
     429              50 : }
     430                 : 
     431               0 : int KMLNode::getLayerNumber() const
     432                 : {
     433               0 :     return nLayerNumber_;
     434                 : }
     435                 : 
     436             584 : std::string KMLNode::getNameElement() const
     437                 : {
     438             584 :     kml_nodes_t::size_type subsize = 0;
     439             584 :     kml_nodes_t::size_type size = pvpoChildren_->size();
     440                 : 
     441             646 :     for( kml_nodes_t::size_type i = 0; i < size; ++i )
     442                 :     {
     443             584 :         if( (*pvpoChildren_)[i]->sName_.compare("name") == 0 )
     444                 :         {
     445             522 :             subsize = (*pvpoChildren_)[i]->pvsContent_->size();
     446             522 :             if( subsize > 0 )
     447                 :             {
     448             522 :                 return (*(*pvpoChildren_)[i]->pvsContent_)[0];
     449                 :             }
     450               0 :             break;
     451                 :         }
     452                 :     }
     453              62 :     return "";
     454                 : }
     455                 : 
     456             534 : std::string KMLNode::getDescriptionElement() const
     457                 : {
     458             534 :     kml_nodes_t::size_type subsize = 0;
     459             534 :     kml_nodes_t::size_type size = pvpoChildren_->size();
     460            1318 :     for( kml_nodes_t::size_type i = 0; i < size; ++i )
     461                 :     {
     462            1010 :         if( (*pvpoChildren_)[i]->sName_.compare("description") == 0 )
     463                 :         {
     464             226 :             subsize = (*pvpoChildren_)[i]->pvsContent_->size();
     465             226 :             if ( subsize > 0 )
     466                 :             {
     467             226 :                 return (*(*pvpoChildren_)[i]->pvsContent_)[0];
     468                 :             }
     469               0 :             break;
     470                 :         }
     471                 :     }
     472             308 :     return "";
     473                 : }
     474                 : 
     475             718 : std::size_t KMLNode::getNumFeatures()
     476                 : {
     477             718 :     if (nNumFeatures_ < 0)
     478                 :     {
     479              36 :         std::size_t nNum = 0;
     480              36 :         kml_nodes_t::size_type size = pvpoChildren_->size();
     481                 :         
     482             230 :         for( kml_nodes_t::size_type i = 0; i < size; ++i )
     483                 :         {
     484             194 :             if( (*pvpoChildren_)[i]->sName_ == "Placemark" )
     485             138 :                 nNum++;
     486                 :         }
     487              36 :         nNumFeatures_ = (int)nNum;
     488                 :     }
     489             718 :     return nNumFeatures_;
     490                 : }
     491                 : 
     492             564 : OGRGeometry* KMLNode::getGeometry(Nodetype eType)
     493                 : {
     494                 :     unsigned int nCount, nCount2, nCountP;
     495             564 :     OGRGeometry* poGeom = NULL;
     496             564 :     KMLNode* poCoor = NULL;
     497             564 :     Coordinate* psCoord = NULL;
     498                 : 
     499             564 :     if (sName_.compare("Point") == 0)
     500                 :     {
     501                 :         // Search coordinate Element
     502             188 :         for(nCount = 0; nCount < pvpoChildren_->size(); nCount++)
     503                 :         {
     504             184 :             if((*pvpoChildren_)[nCount]->sName_.compare("coordinates") == 0)
     505                 :             {
     506             136 :                 poCoor = (*pvpoChildren_)[nCount];
     507             136 :                 for(nCountP = 0; nCountP < poCoor->pvsContent_->size(); nCountP++)
     508                 :                 {
     509             134 :                     psCoord = ParseCoordinate((*poCoor->pvsContent_)[nCountP]);
     510             134 :                     if(psCoord != NULL)
     511                 :                     {
     512             134 :                         if (psCoord->bHasZ)
     513                 :                             poGeom = new OGRPoint(psCoord->dfLongitude,
     514                 :                                                   psCoord->dfLatitude,
     515             118 :                                                   psCoord->dfAltitude);
     516                 :                         else
     517                 :                             poGeom = new OGRPoint(psCoord->dfLongitude,
     518              16 :                                                   psCoord->dfLatitude);
     519             134 :                         delete psCoord;
     520             134 :                         return poGeom;
     521                 :                     }
     522                 :                 }
     523                 :             }
     524                 :         }
     525               4 :         poGeom = new OGRPoint();
     526                 :     }
     527             426 :     else if (sName_.compare("LineString") == 0)
     528                 :     {
     529                 :         // Search coordinate Element
     530             158 :         poGeom = new OGRLineString();
     531             398 :         for(nCount = 0; nCount < pvpoChildren_->size(); nCount++)
     532                 :         {
     533             240 :             if((*pvpoChildren_)[nCount]->sName_.compare("coordinates") == 0)
     534                 :             {
     535             156 :                 poCoor = (*pvpoChildren_)[nCount];
     536            1220 :                 for(nCountP = 0; nCountP < poCoor->pvsContent_->size(); nCountP++)
     537                 :                 {
     538            1064 :                     psCoord = ParseCoordinate((*poCoor->pvsContent_)[nCountP]);
     539            1064 :                     if(psCoord != NULL)
     540                 :                     {
     541            1064 :                         if (psCoord->bHasZ)
     542                 :                             ((OGRLineString*)poGeom)->addPoint(psCoord->dfLongitude,
     543                 :                                                                psCoord->dfLatitude,
     544            1036 :                                                                psCoord->dfAltitude);
     545                 :                         else
     546                 :                             ((OGRLineString*)poGeom)->addPoint(psCoord->dfLongitude,
     547              28 :                                                                psCoord->dfLatitude);
     548            1064 :                         delete psCoord;
     549                 :                     }
     550                 :                 }
     551                 :             }
     552                 :         }
     553                 :     }
     554             268 :     else if (sName_.compare("Polygon") == 0)
     555                 :     {
     556                 :         //*********************************
     557                 :         // Search outerBoundaryIs Element
     558                 :         //*********************************
     559             246 :         poGeom = new OGRPolygon();
     560             752 :         for(nCount = 0; nCount < pvpoChildren_->size(); nCount++)
     561                 :         {
     562             506 :             if((*pvpoChildren_)[nCount]->sName_.compare("outerBoundaryIs") == 0 &&
     563                 :                (*pvpoChildren_)[nCount]->pvpoChildren_->size() > 0)
     564                 :             {
     565             242 :                 poCoor = (*(*pvpoChildren_)[nCount]->pvpoChildren_)[0];
     566                 :             }
     567                 :         }
     568                 :         // No outer boundary found
     569             246 :         if(poCoor == NULL)
     570                 :         {
     571               4 :             return poGeom;
     572                 :         }
     573                 :         // Search coordinate Element
     574             242 :         OGRLinearRing* poLinearRing = NULL;
     575             482 :         for(nCount = 0; nCount < poCoor->pvpoChildren_->size(); nCount++)
     576                 :         {
     577             240 :             if((*poCoor->pvpoChildren_)[nCount]->sName_.compare("coordinates") == 0)
     578                 :             {
     579            3428 :                 for(nCountP = 0; nCountP < (*poCoor->pvpoChildren_)[nCount]->pvsContent_->size(); nCountP++)
     580                 :                 {
     581            3188 :                     psCoord = ParseCoordinate((*(*poCoor->pvpoChildren_)[nCount]->pvsContent_)[nCountP]);
     582            3188 :                     if(psCoord != NULL)
     583                 :                     {
     584            3188 :                         if (poLinearRing == NULL)
     585                 :                         {
     586             238 :                             poLinearRing = new OGRLinearRing();
     587                 :                         }
     588            3188 :                         if (psCoord->bHasZ)
     589                 :                             poLinearRing->addPoint(psCoord->dfLongitude,
     590                 :                                                    psCoord->dfLatitude,
     591            3104 :                                                    psCoord->dfAltitude);
     592                 :                         else
     593                 :                             poLinearRing->addPoint(psCoord->dfLongitude,
     594              84 :                                                    psCoord->dfLatitude);
     595            3188 :                         delete psCoord;
     596                 :                     }
     597                 :                 }
     598                 :             }
     599                 :         }
     600                 :         // No outer boundary coordinates found
     601             242 :         if(poLinearRing == NULL)
     602                 :         {
     603               4 :             return poGeom;
     604                 :         }
     605                 : 
     606             238 :         ((OGRPolygon*)poGeom)->addRingDirectly(poLinearRing);
     607             238 :         poLinearRing = NULL;
     608                 : 
     609                 :         //*********************************
     610                 :         // Search innerBoundaryIs Elements
     611                 :         //*********************************
     612                 : 
     613             738 :         for(nCount2 = 0; nCount2 < pvpoChildren_->size(); nCount2++)
     614                 :         {
     615             500 :             if((*pvpoChildren_)[nCount2]->sName_.compare("innerBoundaryIs") == 0)
     616                 :             {
     617              42 :                 if (poLinearRing)
     618               0 :                     ((OGRPolygon*)poGeom)->addRingDirectly(poLinearRing);
     619              42 :                 poLinearRing = NULL;
     620                 : 
     621              42 :                 if ((*pvpoChildren_)[nCount2]->pvpoChildren_->size() == 0)
     622               2 :                     continue;
     623                 : 
     624              40 :                 poLinearRing = new OGRLinearRing();
     625                 : 
     626              40 :                 poCoor = (*(*pvpoChildren_)[nCount2]->pvpoChildren_)[0];
     627                 :                 // Search coordinate Element
     628              78 :                 for(nCount = 0; nCount < poCoor->pvpoChildren_->size(); nCount++)
     629                 :                 {
     630              38 :                     if((*poCoor->pvpoChildren_)[nCount]->sName_.compare("coordinates") == 0)
     631                 :                     {
     632             240 :                         for(nCountP = 0; nCountP < (*poCoor->pvpoChildren_)[nCount]->pvsContent_->size(); nCountP++)
     633                 :                         {
     634             202 :                             psCoord = ParseCoordinate((*(*poCoor->pvpoChildren_)[nCount]->pvsContent_)[nCountP]);
     635             202 :                             if(psCoord != NULL)
     636                 :                             {
     637             202 :                                 if (psCoord->bHasZ)
     638                 :                                     poLinearRing->addPoint(psCoord->dfLongitude,
     639                 :                                                         psCoord->dfLatitude,
     640             168 :                                                         psCoord->dfAltitude);
     641                 :                                 else
     642                 :                                     poLinearRing->addPoint(psCoord->dfLongitude,
     643              34 :                                                         psCoord->dfLatitude);
     644             202 :                                 delete psCoord;
     645                 :                             }
     646                 :                         }
     647                 :                     }
     648                 :                 }
     649                 :             }
     650                 :         }
     651                 : 
     652             238 :         if (poLinearRing)
     653              40 :             ((OGRPolygon*)poGeom)->addRingDirectly(poLinearRing);
     654                 :     }
     655              22 :     else if (sName_.compare("MultiGeometry") == 0)
     656                 :     {
     657              22 :         if (eType == MultiPoint)
     658               6 :             poGeom = new OGRMultiPoint();
     659              16 :         else if (eType == MultiLineString)
     660               4 :             poGeom = new OGRMultiLineString();
     661              12 :         else if (eType == MultiPolygon)
     662               4 :             poGeom = new OGRMultiPolygon();
     663                 :         else
     664               8 :             poGeom = new OGRGeometryCollection();
     665              52 :         for(nCount = 0; nCount < pvpoChildren_->size(); nCount++)
     666                 :         {
     667              30 :             OGRGeometry* poSubGeom = (*pvpoChildren_)[nCount]->getGeometry();
     668              30 :             if (poSubGeom)
     669              30 :                 ((OGRGeometryCollection*)poGeom)->addGeometryDirectly(poSubGeom);
     670                 :         }
     671                 :     }
     672                 : 
     673             422 :     return poGeom;
     674                 : }
     675                 : 
     676             660 : Feature* KMLNode::getFeature(std::size_t nNum, int& nLastAsked, int &nLastCount)
     677                 : {
     678             660 :     unsigned int nCount, nCountP = 0;
     679             660 :     KMLNode* poFeat = NULL;
     680             660 :     KMLNode* poTemp = NULL;
     681                 : 
     682             660 :     if(nNum >= this->getNumFeatures())
     683             126 :         return NULL;
     684                 : 
     685             534 :     if (nLastAsked + 1 != (int)nNum)
     686                 :     {
     687               0 :         nCount = 0;
     688               0 :         nCountP = 0;
     689                 :     }
     690                 :     else
     691                 :     {
     692             534 :         nCount = nLastCount + 1;
     693             534 :         nCountP = nLastAsked + 1;
     694                 :     }
     695                 : 
     696             902 :     for(; nCount < pvpoChildren_->size(); nCount++)
     697                 :     {
     698             902 :         if((*pvpoChildren_)[nCount]->sName_.compare("Placemark") == 0)
     699                 :         {
     700             534 :             if(nCountP == nNum)
     701                 :             {
     702             534 :                 poFeat = (*pvpoChildren_)[nCount];
     703             534 :                 break;
     704                 :             }
     705               0 :             nCountP++;
     706                 :         }
     707                 :     }
     708                 : 
     709             534 :     nLastAsked = nNum;
     710             534 :     nLastCount = nCount;
     711                 : 
     712             534 :     if(poFeat == NULL)
     713               0 :         return NULL;
     714                 :         
     715                 :     // Create a feature structure
     716             534 :     Feature *psReturn = new Feature;
     717                 :     // Build up the name
     718            1068 :     psReturn->sName = poFeat->getNameElement();
     719                 :     // Build up the description
     720            1068 :     psReturn->sDescription = poFeat->getDescriptionElement();
     721                 :     // the type
     722             534 :     psReturn->eType = poFeat->eType_;
     723                 : 
     724             534 :     std::string sElementName;
     725            1456 :     if(poFeat->eType_ == Point ||
     726                 :        poFeat->eType_ == LineString ||
     727                 :        poFeat->eType_ == Polygon)
     728             512 :         sElementName = Nodetype2String(poFeat->eType_);
     729              44 :     else if (poFeat->eType_ == MultiGeometry || 
     730                 :              poFeat->eType_ == MultiPoint || 
     731                 :              poFeat->eType_ == MultiLineString || 
     732                 :              poFeat->eType_ == MultiPolygon)
     733              22 :         sElementName = "MultiGeometry";
     734                 :     else
     735                 :     {
     736               0 :         delete psReturn;
     737               0 :         return NULL;
     738                 :     }
     739                 : 
     740            1236 :     for(nCount = 0; nCount < poFeat->pvpoChildren_->size(); nCount++)
     741                 :     {
     742            1236 :         if((*poFeat->pvpoChildren_)[nCount]->sName_.compare(sElementName) == 0)
     743                 :         {
     744             534 :             poTemp = (*poFeat->pvpoChildren_)[nCount];
     745             534 :             psReturn->poGeom = poTemp->getGeometry(poFeat->eType_);
     746             534 :             if(psReturn->poGeom)
     747             534 :                 return psReturn;
     748                 :             else
     749                 :             {
     750               0 :                 delete psReturn;
     751               0 :                 return NULL;
     752                 :             }
     753                 :         }
     754                 :     }
     755                 : 
     756               0 :     delete psReturn;
     757               0 :     return NULL;
     758            4029 : }

Generated by: LCOV version 1.7