LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/kml - ogrkmldatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 134 108 80.6 %
Date: 2010-01-09 Functions: 12 10 83.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrkmldatasource.cpp 16908 2009-05-02 14:53:26Z 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              62 : OGRKMLDataSource::OGRKMLDataSource()
      42                 : {
      43              62 :     pszName_ = NULL;
      44              62 :     pszNameField_ = NULL;
      45              62 :     pszDescriptionField_ = NULL;
      46              62 :     pszAltitudeMode_ = NULL;
      47              62 :     papoLayers_ = NULL;
      48              62 :     nLayers_ = 0;
      49                 :     
      50              62 :     fpOutput_ = NULL;
      51                 : 
      52              62 :     papszCreateOptions_ = NULL;
      53                 :   
      54              62 :   bIssuedCTError_ = false;
      55                 : 
      56                 : #ifdef HAVE_EXPAT
      57              62 :     poKMLFile_ = NULL;
      58                 : #endif
      59              62 : }
      60                 : 
      61                 : /************************************************************************/
      62                 : /*                        ~OGRKMLDataSource()                           */
      63                 : /************************************************************************/
      64                 : 
      65             124 : OGRKMLDataSource::~OGRKMLDataSource()
      66                 : {
      67              62 :     if( fpOutput_ != NULL )
      68                 :     {
      69               1 :         VSIFPrintf( fpOutput_, "%s", "</Folder></Document></kml>\n" );
      70                 : 
      71               1 :         if( fpOutput_ != stdout )
      72               1 :             VSIFClose( fpOutput_ );
      73                 :     }
      74                 : 
      75              62 :     CSLDestroy( papszCreateOptions_ );
      76              62 :     CPLFree( pszName_ );
      77              62 :     CPLFree( pszNameField_ );
      78              62 :     CPLFree( pszDescriptionField_ );
      79              62 :     CPLFree( pszAltitudeMode_ );
      80                 : 
      81              73 :     for( int i = 0; i < nLayers_; i++ )
      82                 :     {
      83              11 :         delete papoLayers_[i];
      84                 :     }
      85                 : 
      86              62 :     CPLFree( papoLayers_ );
      87                 : 
      88                 : #ifdef HAVE_EXPAT    
      89              62 :     delete poKMLFile_;
      90                 : #endif
      91             124 : }
      92                 : 
      93                 : /************************************************************************/
      94                 : /*                                Open()                                */
      95                 : /************************************************************************/
      96                 : 
      97                 : #ifdef HAVE_EXPAT
      98              61 : int OGRKMLDataSource::Open( const char * pszNewName, int bTestOpen )
      99                 : {
     100                 :     CPLAssert( NULL != pszNewName );
     101                 : 
     102              61 :     int nCount = 0;
     103              61 :     OGRKMLLayer *poLayer = NULL;
     104                 :     OGRwkbGeometryType poGeotype;
     105                 : 
     106                 : /* -------------------------------------------------------------------- */
     107                 : /*      Create a KML object and open the source file.                   */
     108                 : /* -------------------------------------------------------------------- */
     109              61 :     poKMLFile_ = new KMLVector();
     110                 : 
     111              61 :     if( !poKMLFile_->open( pszNewName ) )
     112                 :     {
     113               5 :         delete poKMLFile_;
     114               5 :         poKMLFile_ = NULL;
     115               5 :         return FALSE;
     116                 :     }
     117                 : 
     118              56 :     pszName_ = CPLStrdup( pszNewName );
     119                 : 
     120                 : /* -------------------------------------------------------------------- */
     121                 : /*      If we aren't sure it is KML, validate it by start parsing       */
     122                 : /* -------------------------------------------------------------------- */
     123              56 :     if( bTestOpen && !poKMLFile_->isValid() )
     124                 :     {
     125              53 :         delete poKMLFile_;
     126              53 :         poKMLFile_ = NULL;
     127              53 :         return FALSE;
     128                 :     }
     129                 : 
     130                 : /* -------------------------------------------------------------------- */
     131                 : /*      Prescan the KML file so we can later work with the structure    */
     132                 : /* -------------------------------------------------------------------- */
     133               3 :     poKMLFile_->parse();
     134                 : 
     135                 : /* -------------------------------------------------------------------- */
     136                 : /*      Classify the nodes                                              */
     137                 : /* -------------------------------------------------------------------- */
     138               3 :     poKMLFile_->classifyNodes();
     139                 : 
     140                 : /* -------------------------------------------------------------------- */
     141                 : /*      Eliminate the empty containers                                  */
     142                 : /* -------------------------------------------------------------------- */
     143               3 :     poKMLFile_->eliminateEmpty();
     144                 : 
     145                 : /* -------------------------------------------------------------------- */
     146                 : /*      Find layers to use in the KML structure                         */
     147                 : /* -------------------------------------------------------------------- */
     148               3 :     poKMLFile_->findLayers(NULL);
     149                 : 
     150                 : /* -------------------------------------------------------------------- */
     151                 : /*      Print the structure                                             */
     152                 : /* -------------------------------------------------------------------- */
     153               3 :     if( CPLGetConfigOption("KML_DEBUG",NULL) != NULL )
     154               0 :         poKMLFile_->print(3);
     155                 : 
     156               3 :     nLayers_ = poKMLFile_->getNumLayers();
     157                 : 
     158                 : /* -------------------------------------------------------------------- */
     159                 : /*      Allocate memory for the Layers                                  */
     160                 : /* -------------------------------------------------------------------- */
     161                 :     papoLayers_ = (OGRKMLLayer **)
     162               3 :         CPLMalloc( sizeof(OGRKMLLayer *) * nLayers_ );
     163                 : 
     164                 :     OGRSpatialReference *poSRS = new OGRSpatialReference("GEOGCS[\"WGS 84\", "
     165                 :         "   DATUM[\"WGS_1984\","
     166                 :         "       SPHEROID[\"WGS 84\",6378137,298.257223563,"
     167                 :         "           AUTHORITY[\"EPSG\",\"7030\"]],"
     168                 :         "           AUTHORITY[\"EPSG\",\"6326\"]],"
     169                 :         "       PRIMEM[\"Greenwich\",0,"
     170                 :         "           AUTHORITY[\"EPSG\",\"8901\"]],"
     171                 :         "       UNIT[\"degree\",0.01745329251994328,"
     172                 :         "           AUTHORITY[\"EPSG\",\"9122\"]],"
     173               3 :         "           AUTHORITY[\"EPSG\",\"4326\"]]");
     174                 : 
     175                 : /* -------------------------------------------------------------------- */
     176                 : /*      Create the Layers and fill them                                 */
     177                 : /* -------------------------------------------------------------------- */
     178              12 :     for( nCount = 0; nCount < nLayers_; nCount++ )
     179                 :     {
     180               9 :         if( !poKMLFile_->selectLayer(nCount) )
     181                 :         {
     182                 :             CPLError( CE_Failure, CPLE_AppDefined,
     183               0 :                       "There are no layers or a layer can not be found!");
     184               0 :             break;
     185                 :         }
     186                 : 
     187               9 :         if( poKMLFile_->getCurrentType() == Point )
     188               4 :             poGeotype = wkbPoint;
     189               5 :         else if( poKMLFile_->getCurrentType() == LineString )
     190               1 :             poGeotype = wkbLineString;
     191               4 :         else if( poKMLFile_->getCurrentType() == Polygon )
     192               3 :             poGeotype = wkbPolygon;
     193               1 :         else if( poKMLFile_->getCurrentType() == MultiPoint )
     194               0 :             poGeotype = wkbMultiPoint;
     195               1 :         else if( poKMLFile_->getCurrentType() == MultiLineString )
     196               0 :             poGeotype = wkbMultiLineString;
     197               1 :         else if( poKMLFile_->getCurrentType() == MultiPolygon )
     198               0 :             poGeotype = wkbMultiPolygon;
     199               1 :         else if( poKMLFile_->getCurrentType() == MultiGeometry )
     200               0 :             poGeotype = wkbGeometryCollection;
     201                 :         else
     202               1 :             poGeotype = wkbUnknown;
     203                 :         
     204               9 :         if (poGeotype != wkbUnknown && poKMLFile_->is25D())
     205               7 :             poGeotype = (OGRwkbGeometryType) (poGeotype | wkb25DBit);
     206                 : 
     207                 : /* -------------------------------------------------------------------- */
     208                 : /*      Create the layer object.                                        */
     209                 : /* -------------------------------------------------------------------- */
     210               9 :         CPLString sName( poKMLFile_->getCurrentName() );
     211                 : 
     212               9 :         if( sName.empty() )
     213                 :         {
     214               1 :             sName.Printf( "Layer #%d", nCount );
     215                 :         }
     216                 : 
     217               9 :         poLayer = new OGRKMLLayer( sName.c_str(), poSRS, FALSE, poGeotype, this );
     218                 : 
     219               9 :         poLayer->SetLayerNumber( nCount );
     220                 : 
     221                 : /* -------------------------------------------------------------------- */
     222                 : /*      Add layer to data source layer list.                            */
     223                 : /* -------------------------------------------------------------------- */
     224               9 :         papoLayers_[nCount] = poLayer;
     225                 :     }
     226                 :     
     227               3 :     poSRS->Release();
     228                 :     
     229               3 :     return TRUE;  
     230                 : }
     231                 : #endif /* HAVE_EXPAT */
     232                 : 
     233                 : /************************************************************************/
     234                 : /*                               Create()                               */
     235                 : /************************************************************************/
     236                 : 
     237               1 : int OGRKMLDataSource::Create( const char* pszName, char** papszOptions )
     238                 : {
     239                 :     CPLAssert( NULL != pszName );
     240                 : 
     241               1 :     if( fpOutput_ != NULL )
     242                 :     {
     243                 :         CPLAssert( FALSE );
     244               0 :         return FALSE;
     245                 :     }
     246                 : 
     247               1 :     if (CSLFetchNameValue(papszOptions, "NameField"))
     248               0 :         pszNameField_ = CPLStrdup(CSLFetchNameValue(papszOptions, "NameField"));
     249                 :     else
     250               1 :         pszNameField_ = CPLStrdup("Name");
     251                 :     
     252               1 :     if (CSLFetchNameValue(papszOptions, "DescriptionField"))
     253               0 :         pszDescriptionField_ = CPLStrdup(CSLFetchNameValue(papszOptions, "DescriptionField"));
     254                 :     else
     255               1 :         pszDescriptionField_ = CPLStrdup("Description");
     256                 : 
     257               1 :     pszAltitudeMode_ = CPLStrdup(CSLFetchNameValue(papszOptions, "AltitudeMode")); 
     258               1 :     if( (NULL != pszAltitudeMode_) && strlen(pszAltitudeMode_) > 0) 
     259                 :     {
     260                 :         //Check to see that the specified AltitudeMode is valid 
     261               0 :         if ( EQUAL(pszAltitudeMode_, "clampToGround")
     262                 :              || EQUAL(pszAltitudeMode_, "relativeToGround")
     263                 :              || EQUAL(pszAltitudeMode_, "absolute")) 
     264                 :         { 
     265               0 :             CPLDebug("KML", "Using '%s' for AltitudeMode", pszAltitudeMode_); 
     266                 :         } 
     267                 :         else 
     268                 :         { 
     269               0 :             CPLFree( pszAltitudeMode_ ); 
     270               0 :             pszAltitudeMode_ = NULL; 
     271               0 :             CPLError( CE_Warning, CPLE_AppDefined, "Invalide AltitideMode specified, ignoring" );  
     272                 :         } 
     273                 :     } 
     274                 :     else 
     275                 :     { 
     276               1 :         CPLFree( pszAltitudeMode_ ); 
     277               1 :         pszAltitudeMode_ = NULL; 
     278                 :     } 
     279                 :     
     280                 : /* -------------------------------------------------------------------- */
     281                 : /*      Create the output file.                                         */
     282                 : /* -------------------------------------------------------------------- */
     283               1 :     pszName_ = CPLStrdup( pszName );
     284                 : 
     285               1 :     if( EQUAL(pszName, "stdout") )
     286               0 :         fpOutput_ = stdout;
     287                 :     else
     288               1 :         fpOutput_ = VSIFOpen( pszName, "wt+" );
     289                 : 
     290               1 :     if( fpOutput_ == NULL )
     291                 :     {
     292                 :         CPLError( CE_Failure, CPLE_OpenFailed, 
     293               0 :                   "Failed to create KML file %s.", pszName );
     294               0 :         return FALSE;
     295                 :     }
     296                 : 
     297                 : /* -------------------------------------------------------------------- */
     298                 : /*      Write out "standard" header.                                    */
     299                 : /* -------------------------------------------------------------------- */
     300               1 :     VSIFPrintf( fpOutput_, "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" ); 
     301                 : 
     302               1 :     nSchemaInsertLocation_ = VSIFTell( fpOutput_ );
     303                 :     
     304               1 :     VSIFPrintf( fpOutput_, "<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n<Document>" );
     305                 : 
     306               1 :     return TRUE;
     307                 : }
     308                 : 
     309                 : /************************************************************************/
     310                 : /*                            CreateLayer()                             */
     311                 : /************************************************************************/
     312                 : 
     313                 : OGRLayer *
     314               2 : OGRKMLDataSource::CreateLayer( const char * pszLayerName,
     315                 :                                OGRSpatialReference *poSRS,
     316                 :                                OGRwkbGeometryType eType,
     317                 :                                char ** papszOptions )
     318                 : {
     319                 :     CPLAssert( NULL != pszLayerName);
     320                 : 
     321                 : /* -------------------------------------------------------------------- */
     322                 : /*      Verify we are in update mode.                                   */
     323                 : /* -------------------------------------------------------------------- */
     324               2 :     if( fpOutput_ == NULL )
     325                 :     {
     326                 :         CPLError( CE_Failure, CPLE_NoWriteAccess,
     327                 :                   "Data source %s opened for read access.\n"
     328                 :                   "New layer %s cannot be created.\n",
     329               0 :                   pszName_, pszLayerName );
     330                 : 
     331               0 :         return NULL;
     332                 :     }
     333                 : 
     334                 : /* -------------------------------------------------------------------- */
     335                 : /*      Close the previous layer (if there is one open)                 */
     336                 : /* -------------------------------------------------------------------- */
     337               2 :     if (GetLayerCount() > 0)
     338                 :     {
     339               1 :         VSIFPrintf( fpOutput_, "</Folder>\n");
     340                 :     }
     341                 :     
     342                 : /* -------------------------------------------------------------------- */
     343                 : /*      Ensure name is safe as an element name.                         */
     344                 : /* -------------------------------------------------------------------- */
     345               2 :     char *pszCleanLayerName = CPLStrdup( pszLayerName );
     346                 : 
     347               2 :     CPLCleanXMLElementName( pszCleanLayerName );
     348               2 :     if( strcmp(pszCleanLayerName, pszLayerName) != 0 )
     349                 :     {
     350                 :         CPLError( CE_Warning, CPLE_AppDefined, 
     351                 :                   "Layer name '%s' adjusted to '%s' for XML validity.",
     352               0 :                   pszLayerName, pszCleanLayerName );
     353                 :     }
     354               2 :     VSIFPrintf( fpOutput_, "<Folder><name>%s</name>\n", pszCleanLayerName);
     355                 :     
     356                 : /* -------------------------------------------------------------------- */
     357                 : /*      Create the layer object.                                        */
     358                 : /* -------------------------------------------------------------------- */
     359                 :     OGRKMLLayer *poLayer;
     360               2 :     poLayer = new OGRKMLLayer( pszCleanLayerName, poSRS, TRUE, eType, this );
     361                 :     
     362               2 :     CPLFree( pszCleanLayerName );
     363                 : 
     364                 : /* -------------------------------------------------------------------- */
     365                 : /*      Add layer to data source layer list.                            */
     366                 : /* -------------------------------------------------------------------- */
     367                 :     papoLayers_ = (OGRKMLLayer **)
     368               2 :         CPLRealloc( papoLayers_,  sizeof(OGRKMLLayer *) * (nLayers_+1) );
     369                 :     
     370               2 :     papoLayers_[nLayers_++] = poLayer;
     371                 : 
     372               2 :     return poLayer;
     373                 : }
     374                 : 
     375                 : /************************************************************************/
     376                 : /*                           TestCapability()                           */
     377                 : /************************************************************************/
     378                 : 
     379               0 : int OGRKMLDataSource::TestCapability( const char * pszCap )
     380                 : 
     381                 : {
     382               0 :     if( EQUAL(pszCap, ODsCCreateLayer) )
     383               0 :         return TRUE;
     384                 :     else
     385               0 :         return FALSE;
     386                 : }
     387                 : 
     388                 : /************************************************************************/
     389                 : /*                              GetLayer()                              */
     390                 : /************************************************************************/
     391                 : 
     392              21 : OGRLayer *OGRKMLDataSource::GetLayer( int iLayer )
     393                 : {
     394              21 :     if( iLayer < 0 || iLayer >= nLayers_ )
     395               0 :         return NULL;
     396                 :     else
     397              21 :         return papoLayers_[iLayer];
     398                 : }
     399                 : 
     400                 : /************************************************************************/
     401                 : /*                            GrowExtents()                             */
     402                 : /************************************************************************/
     403                 : 
     404               9 : void OGRKMLDataSource::GrowExtents( OGREnvelope *psGeomBounds )
     405                 : {
     406                 :     CPLAssert( NULL != psGeomBounds );
     407                 : 
     408               9 :     oEnvelope_.Merge( *psGeomBounds );
     409            1149 : }

Generated by: LCOV version 1.7