LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/kml - ogrkmldatasource.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 141 111 78.7 %
Date: 2011-12-18 Functions: 14 9 64.3 %

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

Generated by: LCOV version 1.7