LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/kml - ogrkmldatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 144 118 81.9 %
Date: 2012-12-26 Functions: 14 10 71.4 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrkmldatasource.cpp 23978 2012-02-14 20:42:34Z rouault $
       3                 :  *
       4                 :  * Project:  KML Driver
       5                 :  * Purpose:  Implementation of OGRKMLDataSource class.
       6                 :  * Author:   Christopher Condit, condit@sdsc.edu;
       7                 :  *           Jens Oberender, j.obi@troja.net
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2006, Christopher Condit
      11                 :  *               2007, Jens Oberender
      12                 :  *
      13                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      14                 :  * copy of this software and associated documentation files (the "Software"),
      15                 :  * to deal in the Software without restriction, including without limitation
      16                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17                 :  * and/or sell copies of the Software, and to permit persons to whom the
      18                 :  * Software is furnished to do so, subject to the following conditions:
      19                 :  *
      20                 :  * The above copyright notice and this permission notice shall be included
      21                 :  * in all copies or substantial portions of the Software.
      22                 :  *
      23                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      24                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      26                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      29                 :  * DEALINGS IN THE SOFTWARE.
      30                 :  ****************************************************************************/
      31                 : #include "ogr_kml.h"
      32                 : #include "cpl_conv.h"
      33                 : #include "cpl_string.h"
      34                 : #include "cpl_error.h"
      35                 : #include "cpl_minixml.h"
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                         OGRKMLDataSource()                           */
      39                 : /************************************************************************/
      40                 : 
      41              94 : OGRKMLDataSource::OGRKMLDataSource()
      42                 : {
      43              94 :     pszName_ = NULL;
      44              94 :     pszNameField_ = NULL;
      45              94 :     pszDescriptionField_ = NULL;
      46              94 :     pszAltitudeMode_ = NULL;
      47              94 :     papoLayers_ = NULL;
      48              94 :     nLayers_ = 0;
      49                 :     
      50              94 :     fpOutput_ = NULL;
      51                 : 
      52              94 :     papszCreateOptions_ = NULL;
      53                 :   
      54              94 :   bIssuedCTError_ = false;
      55                 : 
      56                 : #ifdef HAVE_EXPAT
      57              94 :     poKMLFile_ = NULL;
      58                 : #endif
      59              94 : }
      60                 : 
      61                 : /************************************************************************/
      62                 : /*                        ~OGRKMLDataSource()                           */
      63                 : /************************************************************************/
      64                 : 
      65              94 : OGRKMLDataSource::~OGRKMLDataSource()
      66                 : {
      67              94 :     if( fpOutput_ != NULL )
      68                 :     {
      69               2 :         VSIFPrintfL( fpOutput_, "%s", "</Folder></Document></kml>\n" );
      70                 : 
      71               2 :         VSIFCloseL( fpOutput_ );
      72                 :     }
      73                 : 
      74              94 :     CSLDestroy( papszCreateOptions_ );
      75              94 :     CPLFree( pszName_ );
      76              94 :     CPLFree( pszNameField_ );
      77              94 :     CPLFree( pszDescriptionField_ );
      78              94 :     CPLFree( pszAltitudeMode_ );
      79                 : 
      80             123 :     for( int i = 0; i < nLayers_; i++ )
      81                 :     {
      82              29 :         delete papoLayers_[i];
      83                 :     }
      84                 : 
      85              94 :     CPLFree( papoLayers_ );
      86                 : 
      87                 : #ifdef HAVE_EXPAT    
      88              94 :     delete poKMLFile_;
      89                 : #endif
      90              94 : }
      91                 : 
      92                 : /************************************************************************/
      93                 : /*                                Open()                                */
      94                 : /************************************************************************/
      95                 : 
      96                 : #ifdef HAVE_EXPAT
      97              92 : int OGRKMLDataSource::Open( const char * pszNewName, int bTestOpen )
      98                 : {
      99              92 :     CPLAssert( NULL != pszNewName );
     100                 : 
     101              92 :     int nCount = 0;
     102              92 :     OGRKMLLayer *poLayer = NULL;
     103                 :     OGRwkbGeometryType poGeotype;
     104                 : 
     105                 : /* -------------------------------------------------------------------- */
     106                 : /*      Create a KML object and open the source file.                   */
     107                 : /* -------------------------------------------------------------------- */
     108              92 :     poKMLFile_ = new KMLVector();
     109                 : 
     110              92 :     if( !poKMLFile_->open( pszNewName ) )
     111                 :     {
     112              28 :         delete poKMLFile_;
     113              28 :         poKMLFile_ = NULL;
     114              28 :         return FALSE;
     115                 :     }
     116                 : 
     117              64 :     pszName_ = CPLStrdup( pszNewName );
     118                 : 
     119                 : /* -------------------------------------------------------------------- */
     120                 : /*      If we aren't sure it is KML, validate it by start parsing       */
     121                 : /* -------------------------------------------------------------------- */
     122              64 :     if( bTestOpen && !poKMLFile_->isValid() )
     123                 :     {
     124              55 :         delete poKMLFile_;
     125              55 :         poKMLFile_ = NULL;
     126              55 :         return FALSE;
     127                 :     }
     128                 : 
     129                 : /* -------------------------------------------------------------------- */
     130                 : /*      Prescan the KML file so we can later work with the structure    */
     131                 : /* -------------------------------------------------------------------- */
     132               9 :     poKMLFile_->parse();
     133                 : 
     134                 : /* -------------------------------------------------------------------- */
     135                 : /*      Classify the nodes                                              */
     136                 : /* -------------------------------------------------------------------- */
     137               9 :     if( !poKMLFile_->classifyNodes() )
     138                 :     {
     139               0 :         delete poKMLFile_;
     140               0 :         poKMLFile_ = NULL;
     141               0 :         return FALSE;
     142                 :     }
     143                 : 
     144                 : 
     145                 : /* -------------------------------------------------------------------- */
     146                 : /*      Eliminate the empty containers (if there is at least one        */
     147                 : /*      valid container !)                                              */
     148                 : /* -------------------------------------------------------------------- */
     149               9 :     int bHasOnlyEmpty = poKMLFile_->hasOnlyEmpty();
     150               9 :     if (bHasOnlyEmpty)
     151               2 :         CPLDebug("KML", "Has only empty containers");
     152                 :     else
     153               7 :         poKMLFile_->eliminateEmpty();
     154                 : 
     155                 : /* -------------------------------------------------------------------- */
     156                 : /*      Find layers to use in the KML structure                         */
     157                 : /* -------------------------------------------------------------------- */
     158               9 :     poKMLFile_->findLayers(NULL, bHasOnlyEmpty);
     159                 : 
     160                 : /* -------------------------------------------------------------------- */
     161                 : /*      Print the structure                                             */
     162                 : /* -------------------------------------------------------------------- */
     163               9 :     if( CPLGetConfigOption("KML_DEBUG",NULL) != NULL )
     164               0 :         poKMLFile_->print(3);
     165                 : 
     166               9 :     nLayers_ = poKMLFile_->getNumLayers();
     167                 : 
     168                 : /* -------------------------------------------------------------------- */
     169                 : /*      Allocate memory for the Layers                                  */
     170                 : /* -------------------------------------------------------------------- */
     171                 :     papoLayers_ = (OGRKMLLayer **)
     172               9 :         CPLMalloc( sizeof(OGRKMLLayer *) * nLayers_ );
     173                 : 
     174                 :     OGRSpatialReference *poSRS = new OGRSpatialReference("GEOGCS[\"WGS 84\", "
     175                 :         "   DATUM[\"WGS_1984\","
     176                 :         "       SPHEROID[\"WGS 84\",6378137,298.257223563,"
     177                 :         "           AUTHORITY[\"EPSG\",\"7030\"]],"
     178                 :         "           AUTHORITY[\"EPSG\",\"6326\"]],"
     179                 :         "       PRIMEM[\"Greenwich\",0,"
     180                 :         "           AUTHORITY[\"EPSG\",\"8901\"]],"
     181                 :         "       UNIT[\"degree\",0.01745329251994328,"
     182                 :         "           AUTHORITY[\"EPSG\",\"9122\"]],"
     183               9 :         "           AUTHORITY[\"EPSG\",\"4326\"]]");
     184                 : 
     185                 : /* -------------------------------------------------------------------- */
     186                 : /*      Create the Layers and fill them                                 */
     187                 : /* -------------------------------------------------------------------- */
     188              34 :     for( nCount = 0; nCount < nLayers_; nCount++ )
     189                 :     {
     190              25 :         if( !poKMLFile_->selectLayer(nCount) )
     191                 :         {
     192                 :             CPLError( CE_Failure, CPLE_AppDefined,
     193               0 :                       "There are no layers or a layer can not be found!");
     194               0 :             break;
     195                 :         }
     196                 : 
     197              25 :         if( poKMLFile_->getCurrentType() == Point )
     198               9 :             poGeotype = wkbPoint;
     199              16 :         else if( poKMLFile_->getCurrentType() == LineString )
     200               3 :             poGeotype = wkbLineString;
     201              13 :         else if( poKMLFile_->getCurrentType() == Polygon )
     202               9 :             poGeotype = wkbPolygon;
     203               4 :         else if( poKMLFile_->getCurrentType() == MultiPoint )
     204               0 :             poGeotype = wkbMultiPoint;
     205               4 :         else if( poKMLFile_->getCurrentType() == MultiLineString )
     206               0 :             poGeotype = wkbMultiLineString;
     207               4 :         else if( poKMLFile_->getCurrentType() == MultiPolygon )
     208               0 :             poGeotype = wkbMultiPolygon;
     209               4 :         else if( poKMLFile_->getCurrentType() == MultiGeometry )
     210               0 :             poGeotype = wkbGeometryCollection;
     211                 :         else
     212               4 :             poGeotype = wkbUnknown;
     213                 :         
     214              25 :         if (poGeotype != wkbUnknown && poKMLFile_->is25D())
     215              20 :             poGeotype = (OGRwkbGeometryType) (poGeotype | wkb25DBit);
     216                 : 
     217                 : /* -------------------------------------------------------------------- */
     218                 : /*      Create the layer object.                                        */
     219                 : /* -------------------------------------------------------------------- */
     220              25 :         CPLString sName( poKMLFile_->getCurrentName() );
     221                 : 
     222              25 :         if( sName.empty() )
     223                 :         {
     224               2 :             sName.Printf( "Layer #%d", nCount );
     225                 :         }
     226                 : 
     227              25 :         poLayer = new OGRKMLLayer( sName.c_str(), poSRS, FALSE, poGeotype, this );
     228                 : 
     229              25 :         poLayer->SetLayerNumber( nCount );
     230                 : 
     231                 : /* -------------------------------------------------------------------- */
     232                 : /*      Add layer to data source layer list.                            */
     233                 : /* -------------------------------------------------------------------- */
     234              25 :         papoLayers_[nCount] = poLayer;
     235                 :     }
     236                 :     
     237               9 :     poSRS->Release();
     238                 :     
     239               9 :     return TRUE;  
     240                 : }
     241                 : #endif /* HAVE_EXPAT */
     242                 : 
     243                 : /************************************************************************/
     244                 : /*                               Create()                               */
     245                 : /************************************************************************/
     246                 : 
     247               2 : int OGRKMLDataSource::Create( const char* pszName, char** papszOptions )
     248                 : {
     249               2 :     CPLAssert( NULL != pszName );
     250                 : 
     251               2 :     if( fpOutput_ != NULL )
     252                 :     {
     253               0 :         CPLAssert( FALSE );
     254               0 :         return FALSE;
     255                 :     }
     256                 : 
     257               2 :     if (CSLFetchNameValue(papszOptions, "NameField"))
     258               0 :         pszNameField_ = CPLStrdup(CSLFetchNameValue(papszOptions, "NameField"));
     259                 :     else
     260               2 :         pszNameField_ = CPLStrdup("Name");
     261                 :     
     262               2 :     if (CSLFetchNameValue(papszOptions, "DescriptionField"))
     263               0 :         pszDescriptionField_ = CPLStrdup(CSLFetchNameValue(papszOptions, "DescriptionField"));
     264                 :     else
     265               2 :         pszDescriptionField_ = CPLStrdup("Description");
     266                 : 
     267               2 :     pszAltitudeMode_ = CPLStrdup(CSLFetchNameValue(papszOptions, "AltitudeMode")); 
     268               2 :     if( (NULL != pszAltitudeMode_) && strlen(pszAltitudeMode_) > 0) 
     269                 :     {
     270                 :         //Check to see that the specified AltitudeMode is valid 
     271               0 :         if ( EQUAL(pszAltitudeMode_, "clampToGround")
     272                 :              || EQUAL(pszAltitudeMode_, "relativeToGround")
     273                 :              || EQUAL(pszAltitudeMode_, "absolute")) 
     274                 :         { 
     275               0 :             CPLDebug("KML", "Using '%s' for AltitudeMode", pszAltitudeMode_); 
     276                 :         } 
     277                 :         else 
     278                 :         { 
     279               0 :             CPLFree( pszAltitudeMode_ ); 
     280               0 :             pszAltitudeMode_ = NULL; 
     281               0 :             CPLError( CE_Warning, CPLE_AppDefined, "Invalide AltitideMode specified, ignoring" );  
     282                 :         } 
     283                 :     } 
     284                 :     else 
     285                 :     { 
     286               2 :         CPLFree( pszAltitudeMode_ ); 
     287               2 :         pszAltitudeMode_ = NULL; 
     288                 :     } 
     289                 :     
     290                 : /* -------------------------------------------------------------------- */
     291                 : /*      Create the output file.                                         */
     292                 : /* -------------------------------------------------------------------- */
     293                 : 
     294               2 :     if (strcmp(pszName, "/dev/stdout") == 0)
     295               0 :         pszName = "/vsistdout/";
     296                 : 
     297               2 :     pszName_ = CPLStrdup( pszName );
     298                 : 
     299               2 :     fpOutput_ = VSIFOpenL( pszName, "wb" );
     300               2 :     if( fpOutput_ == NULL )
     301                 :     {
     302                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     303               0 :                   "Failed to create KML file %s.", pszName );
     304               0 :         return FALSE;
     305                 :     }
     306                 : 
     307                 : /* -------------------------------------------------------------------- */
     308                 : /*      Write out "standard" header.                                    */
     309                 : /* -------------------------------------------------------------------- */
     310               2 :     VSIFPrintfL( fpOutput_, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" );  
     311                 :     
     312               2 :     VSIFPrintfL( fpOutput_, "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n<Document>" );
     313                 : 
     314               2 :     return TRUE;
     315                 : }
     316                 : 
     317                 : /************************************************************************/
     318                 : /*                            CreateLayer()                             */
     319                 : /************************************************************************/
     320                 : 
     321                 : OGRLayer *
     322               4 : OGRKMLDataSource::CreateLayer( const char * pszLayerName,
     323                 :                                OGRSpatialReference *poSRS,
     324                 :                                OGRwkbGeometryType eType,
     325                 :                                char ** papszOptions )
     326                 : {
     327               4 :     CPLAssert( NULL != pszLayerName);
     328                 : 
     329                 : /* -------------------------------------------------------------------- */
     330                 : /*      Verify we are in update mode.                                   */
     331                 : /* -------------------------------------------------------------------- */
     332               4 :     if( fpOutput_ == NULL )
     333                 :     {
     334                 :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     335                 :                   "Data source %s opened for read access.\n"
     336                 :                   "New layer %s cannot be created.\n",
     337               0 :                   pszName_, pszLayerName );
     338                 : 
     339               0 :         return NULL;
     340                 :     }
     341                 : 
     342                 : /* -------------------------------------------------------------------- */
     343                 : /*      Close the previous layer (if there is one open)                 */
     344                 : /* -------------------------------------------------------------------- */
     345               4 :     if (GetLayerCount() > 0)
     346                 :     {
     347               2 :         VSIFPrintfL( fpOutput_, "</Folder>\n");
     348               2 :         ((OGRKMLLayer*)GetLayer(GetLayerCount()-1))->SetClosedForWriting();
     349                 :     }
     350                 :     
     351                 : /* -------------------------------------------------------------------- */
     352                 : /*      Ensure name is safe as an element name.                         */
     353                 : /* -------------------------------------------------------------------- */
     354               4 :     char *pszCleanLayerName = CPLStrdup( pszLayerName );
     355                 : 
     356               4 :     CPLCleanXMLElementName( pszCleanLayerName );
     357               4 :     if( strcmp(pszCleanLayerName, pszLayerName) != 0 )
     358                 :     {
     359                 :         CPLError( CE_Warning, CPLE_AppDefined, 
     360                 :                   "Layer name '%s' adjusted to '%s' for XML validity.",
     361               0 :                   pszLayerName, pszCleanLayerName );
     362                 :     }
     363               4 :     VSIFPrintfL( fpOutput_, "<Folder><name>%s</name>\n", pszCleanLayerName);
     364                 :     
     365                 : /* -------------------------------------------------------------------- */
     366                 : /*      Create the layer object.                                        */
     367                 : /* -------------------------------------------------------------------- */
     368                 :     OGRKMLLayer *poLayer;
     369               4 :     poLayer = new OGRKMLLayer( pszCleanLayerName, poSRS, TRUE, eType, this );
     370                 :     
     371               4 :     CPLFree( pszCleanLayerName );
     372                 : 
     373                 : /* -------------------------------------------------------------------- */
     374                 : /*      Add layer to data source layer list.                            */
     375                 : /* -------------------------------------------------------------------- */
     376                 :     papoLayers_ = (OGRKMLLayer **)
     377               4 :         CPLRealloc( papoLayers_,  sizeof(OGRKMLLayer *) * (nLayers_+1) );
     378                 :     
     379               4 :     papoLayers_[nLayers_++] = poLayer;
     380                 : 
     381               4 :     return poLayer;
     382                 : }
     383                 : 
     384                 : /************************************************************************/
     385                 : /*                           TestCapability()                           */
     386                 : /************************************************************************/
     387                 : 
     388               1 : int OGRKMLDataSource::TestCapability( const char * pszCap )
     389                 : 
     390                 : {
     391               1 :     if( EQUAL(pszCap, ODsCCreateLayer) )
     392               0 :         return TRUE;
     393                 :     else
     394               1 :         return FALSE;
     395                 : }
     396                 : 
     397                 : /************************************************************************/
     398                 : /*                              GetLayer()                              */
     399                 : /************************************************************************/
     400                 : 
     401             175 : OGRLayer *OGRKMLDataSource::GetLayer( int iLayer )
     402                 : {
     403             175 :     if( iLayer < 0 || iLayer >= nLayers_ )
     404               2 :         return NULL;
     405                 :     else
     406             173 :         return papoLayers_[iLayer];
     407                 : }
     408                 : 
     409                 : /************************************************************************/
     410                 : /*                            GrowExtents()                             */
     411                 : /************************************************************************/
     412                 : 
     413               9 : void OGRKMLDataSource::GrowExtents( OGREnvelope *psGeomBounds )
     414                 : {
     415               9 :     CPLAssert( NULL != psGeomBounds );
     416                 : 
     417               9 :     oEnvelope_.Merge( *psGeomBounds );
     418            2148 : }

Generated by: LCOV version 1.7