LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/kml - ogrkmllayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 195 142 72.8 %
Date: 2010-01-09 Functions: 15 11 73.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrkmllayer.cpp 16908 2009-05-02 14:53:26Z rouault $
       3                 :  *
       4                 :  * Project:  KML Driver
       5                 :  * Purpose:  Implementation of OGRKMLLayer class.
       6                 :  * Author:   Christopher Condit, condit@sdsc.edu
       7                 :  *           Jens Oberender, j.obi@troja.net
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2006, Christopher Condit
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "ogr_kml.h"
      32                 : #include "ogr_api.h"
      33                 : #include "cpl_conv.h"
      34                 : #include "cpl_string.h"
      35                 : #include "ogr_p.h"
      36                 : 
      37                 : /* Function utility to dump OGRGeometry to KML text. */
      38                 : char *OGR_G_ExportToKML( OGRGeometryH hGeometry, const char* pszAltitudeMode );
      39                 : 
      40                 : /************************************************************************/
      41                 : /*                           OGRKMLLayer()                              */
      42                 : /************************************************************************/
      43                 : 
      44              11 : OGRKMLLayer::OGRKMLLayer( const char * pszName,
      45                 :                           OGRSpatialReference *poSRSIn, int bWriterIn,
      46                 :                           OGRwkbGeometryType eReqType,
      47              11 :                           OGRKMLDataSource *poDSIn )
      48                 : {     
      49              11 :     poCT_ = NULL;
      50                 : 
      51                 :     /* KML should be created as WGS84. */
      52              11 :     if( poSRSIn != NULL )
      53                 :     {
      54              10 :         poSRS_ = new OGRSpatialReference(NULL);   
      55              10 :         poSRS_->SetWellKnownGeogCS( "WGS84" );
      56              10 :         if (!poSRS_->IsSame(poSRSIn))
      57                 :         {
      58               1 :             poCT_ = OGRCreateCoordinateTransformation( poSRSIn, poSRS_ );
      59               1 :             if( poCT_ == NULL && poDSIn->IsFirstCTError() )
      60                 :             {
      61                 :                 /* If we can't create a transformation, issue a warning - but continue the transformation*/
      62               0 :                 char *pszWKT = NULL;
      63                 : 
      64               0 :                 poSRSIn->exportToPrettyWkt( &pszWKT, FALSE );
      65                 : 
      66                 :                 CPLError( CE_Warning, CPLE_AppDefined,
      67                 :                         "Failed to create coordinate transformation between the\n"
      68                 :                         "input coordinate system and WGS84.  This may be because they\n"
      69                 :                         "are not transformable, or because projection services\n"
      70                 :                         "(PROJ.4 DLL/.so) could not be loaded.\n" 
      71                 :                         "KML geometries may not render correctly.\n"
      72                 :                         "This message will not be issued any more. \n"
      73                 :                         "\nSource:\n%s\n", 
      74               0 :                         pszWKT );
      75                 : 
      76               0 :                 CPLFree( pszWKT );
      77               0 :                 poDSIn->IssuedFirstCTError(); 
      78                 :             }
      79                 :         }
      80                 :     }
      81                 :     else
      82                 :     {
      83               1 :         poSRS_ = NULL;
      84                 :     }
      85                 : 
      86              11 :     iNextKMLId_ = 0;
      87              11 :     nTotalKMLCount_ = -1;
      88              11 :     nLastAsked = -1;
      89              11 :     nLastCount = -1;
      90                 : 
      91              11 :     poDS_ = poDSIn;
      92                 :     
      93              11 :     poFeatureDefn_ = new OGRFeatureDefn( pszName );
      94              11 :     poFeatureDefn_->Reference();
      95              11 :     poFeatureDefn_->SetGeomType( eReqType );
      96                 : 
      97              11 :     OGRFieldDefn oFieldName( "Name", OFTString );
      98              11 :     poFeatureDefn_->AddFieldDefn( &oFieldName );
      99                 :     
     100              11 :     OGRFieldDefn oFieldDesc( "Description", OFTString );
     101              11 :     poFeatureDefn_->AddFieldDefn( &oFieldDesc );
     102                 : 
     103              11 :     bWriter_ = bWriterIn;
     104              11 :     nWroteFeatureCount_ = 0;
     105                 : 
     106              11 :     pszName_ = CPLStrdup(pszName);
     107              11 : }
     108                 : 
     109                 : /************************************************************************/
     110                 : /*                           ~OGRKMLLayer()                             */
     111                 : /************************************************************************/
     112                 : 
     113              22 : OGRKMLLayer::~OGRKMLLayer()
     114                 : {
     115              11 :     if( NULL != poFeatureDefn_ )
     116              11 :         poFeatureDefn_->Release();
     117                 : 
     118              11 :     if( NULL != poSRS_ )
     119              10 :         poSRS_->Release();
     120                 :   
     121              11 :     if( NULL != poCT_ )
     122               1 :         delete poCT_;
     123                 :   
     124              11 :     CPLFree( pszName_ );
     125              22 : }
     126                 : 
     127                 : /************************************************************************/
     128                 : /*                            GetLayerDefn()                            */
     129                 : /************************************************************************/
     130                 : 
     131              31 : OGRFeatureDefn* OGRKMLLayer::GetLayerDefn()
     132                 : {
     133              31 :     return poFeatureDefn_;
     134                 : }
     135                 : 
     136                 : /************************************************************************/
     137                 : /*                            ResetReading()                            */
     138                 : /************************************************************************/
     139                 : 
     140               3 : void OGRKMLLayer::ResetReading()
     141                 : {
     142               3 :     iNextKMLId_ = 0;    
     143               3 :     nLastAsked = -1;
     144               3 :     nLastCount = -1;
     145               3 : }
     146                 : 
     147                 : /************************************************************************/
     148                 : /*                           GetNextFeature()                           */
     149                 : /************************************************************************/
     150                 : 
     151              32 : OGRFeature *OGRKMLLayer::GetNextFeature()
     152                 : {
     153                 : #ifndef HAVE_EXPAT
     154                 :     return NULL;
     155                 : #else
     156                 :     /* -------------------------------------------------------------------- */
     157                 :     /*      Loop till we find a feature matching our criteria.              */
     158                 :     /* -------------------------------------------------------------------- */
     159              32 :     KML *poKMLFile = poDS_->GetKMLFile();
     160              32 :     poKMLFile->selectLayer(nLayerNumber_);
     161                 : 
     162               0 :     while(TRUE)
     163                 :     {
     164              32 :         Feature *poFeatureKML = NULL;
     165              32 :         poFeatureKML = poKMLFile->getFeature(iNextKMLId_++, nLastAsked, nLastCount);
     166                 :     
     167              32 :         if(poFeatureKML == NULL)
     168               2 :             return NULL;
     169                 :     
     170                 :         CPLAssert( poFeatureKML != NULL );
     171                 :     
     172              30 :         OGRFeature *poFeature = new OGRFeature( poFeatureDefn_ );
     173                 :         
     174              30 :         if(poFeatureKML->poGeom)
     175                 :         {
     176              30 :             poFeature->SetGeometryDirectly(poFeatureKML->poGeom);
     177              30 :             poFeatureKML->poGeom = NULL;
     178                 :         }
     179                 :     
     180                 :         // Add fields
     181              30 :         poFeature->SetField( poFeatureDefn_->GetFieldIndex("Name"), poFeatureKML->sName.c_str() );
     182              30 :         poFeature->SetField( poFeatureDefn_->GetFieldIndex("Description"), poFeatureKML->sDescription.c_str() );
     183              30 :         poFeature->SetFID( iNextKMLId_ - 1 );
     184                 :     
     185                 :         // Clean up
     186              30 :         delete poFeatureKML;
     187                 :     
     188              30 :         if( poFeature->GetGeometryRef() != NULL && poSRS_ != NULL)
     189                 :         {
     190              30 :             poFeature->GetGeometryRef()->assignSpatialReference( poSRS_ );
     191                 :         }
     192                 :     
     193                 :         /* Check spatial/attribute filters */
     194              30 :         if ((m_poFilterGeom == NULL || FilterGeometry( poFeature->GetGeometryRef() ) ) &&
     195                 :             (m_poAttrQuery == NULL || m_poAttrQuery->Evaluate( poFeature )) )
     196                 :         {
     197                 :         // Return the feature
     198              30 :             return poFeature;
     199                 :         }
     200                 :         else
     201                 :         {
     202               0 :             delete poFeature;
     203                 :         }
     204                 :     }
     205                 : 
     206                 : #endif /* HAVE_EXPAT */
     207                 : }
     208                 : 
     209                 : /************************************************************************/
     210                 : /*                          GetFeatureCount()                           */
     211                 : /************************************************************************/
     212                 : 
     213               1 : int OGRKMLLayer::GetFeatureCount( int bForce )
     214                 : {
     215               1 :     int nCount = 0;
     216                 : 
     217                 : #ifdef HAVE_EXPAT
     218               1 :     if (m_poFilterGeom == NULL && m_poAttrQuery == NULL)
     219                 :     {
     220               1 :         KML *poKMLFile = poDS_->GetKMLFile();
     221               1 :         if( NULL != poKMLFile )
     222                 :         {
     223               1 :             poKMLFile->selectLayer(nLayerNumber_);
     224               1 :             nCount = poKMLFile->getNumFeatures();
     225                 :         }
     226                 :     }
     227                 :     else
     228               0 :         return OGRLayer::GetFeatureCount(bForce);
     229                 : #endif
     230                 : 
     231               1 :     return nCount;
     232                 : }
     233                 : 
     234                 : /************************************************************************/
     235                 : /*                           CreateFeature()                            */
     236                 : /************************************************************************/
     237                 : 
     238               9 : OGRErr OGRKMLLayer::CreateFeature( OGRFeature* poFeature )
     239                 : {
     240                 :     CPLAssert( NULL != poFeature );
     241                 :     CPLAssert( NULL != poDS_ );
     242                 : 
     243               9 :     if( !bWriter_ )
     244               0 :         return OGRERR_FAILURE;
     245                 : 
     246               9 :     FILE *fp = poDS_->GetOutputFP();
     247                 :     CPLAssert( NULL != fp );
     248                 : 
     249                 :     // If we haven't writen any features yet, output the layer's schema
     250               9 :     if (0 == nWroteFeatureCount_)
     251                 :     {
     252               2 :         VSIFPrintf( fp, "<Schema name=\"%s\" id=\"%s\">\n", pszName_, pszName_ );
     253               2 :         OGRFeatureDefn *featureDefinition = GetLayerDefn();
     254               6 :         for (int j=0; j < featureDefinition->GetFieldCount(); j++)
     255                 :         {
     256               4 :             OGRFieldDefn *fieldDefinition = featureDefinition->GetFieldDefn(j);      
     257               4 :             const char* pszKMLType = NULL;
     258               4 :             const char* pszKMLEltName = NULL;
     259                 :             // Match the OGR type to the GDAL type
     260               4 :             switch (fieldDefinition->GetType())
     261                 :             {
     262                 :               case OFTInteger:
     263               0 :                 pszKMLType = "int";
     264               0 :                 pszKMLEltName = "SimpleField";
     265               0 :                 break;
     266                 :               case OFTIntegerList:
     267               0 :                 pszKMLType = "int";
     268               0 :                 pszKMLEltName = "SimpleArrayField";
     269               0 :                 break;
     270                 :               case OFTReal:
     271               0 :                 pszKMLType = "float";
     272               0 :                 pszKMLEltName = "SimpleField";
     273               0 :                 break;
     274                 :               case OFTRealList:
     275               0 :                 pszKMLType = "float";
     276               0 :                 pszKMLEltName = "SimpleArrayField";
     277               0 :                 break;
     278                 :               case OFTString:
     279               4 :                 pszKMLType = "string";
     280               4 :                 pszKMLEltName = "SimpleField";
     281               4 :                 break;
     282                 :               case OFTStringList:
     283               0 :                 pszKMLType = "string";
     284               0 :                 pszKMLEltName = "SimpleArrayField";
     285               0 :                 break;
     286                 :               case OFTBinary:
     287               0 :                 pszKMLType = "bool";
     288               0 :                 pszKMLEltName = "SimpleField";
     289               0 :                 break;
     290                 :                 //TODO: KML doesn't handle these data types yet...
     291                 :               case OFTDate:                
     292                 :               case OFTTime:                
     293                 :               case OFTDateTime:
     294               0 :                 pszKMLType = "string";
     295               0 :                 pszKMLEltName = "SimpleField";                
     296               0 :                 break;
     297                 : 
     298                 :               default:
     299               0 :                 pszKMLType = "string";
     300               0 :                 pszKMLEltName = "SimpleField";
     301                 :                 break;
     302                 :             }
     303                 :             VSIFPrintf( fp, "\t<%s name=\"%s\" type=\"%s\"></%s>\n", 
     304               4 :                         pszKMLEltName, fieldDefinition->GetNameRef() ,pszKMLType, pszKMLEltName );
     305                 :         }
     306               2 :         VSIFPrintf( fp, "</Schema>\n" );
     307                 :     }
     308                 : 
     309               9 :     VSIFPrintf( fp, "  <Placemark>\n" );
     310                 : 
     311               9 :     if( poFeature->GetFID() == OGRNullFID )
     312               9 :         poFeature->SetFID( iNextKMLId_++ );
     313                 : 
     314                 :     // Find and write the name element
     315               9 :     if (NULL != poDS_->GetNameField())
     316                 :     {
     317              27 :         for( int iField = 0; iField < poFeatureDefn_->GetFieldCount(); iField++ )
     318                 :         {        
     319              18 :             OGRFieldDefn *poField = poFeatureDefn_->GetFieldDefn( iField );
     320                 : 
     321              18 :             if( poFeature->IsFieldSet( iField )
     322                 :                 && EQUAL(poField->GetNameRef(), poDS_->GetNameField()) )
     323                 :             {           
     324               1 :                 const char *pszRaw = poFeature->GetFieldAsString( iField );
     325               2 :                 while( *pszRaw == ' ' )
     326               0 :                     pszRaw++;
     327                 : 
     328               1 :                 char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw );
     329                 : 
     330               1 :                 VSIFPrintf( fp, "\t<name>%s</name>\n", pszEscaped);
     331               1 :                 CPLFree( pszEscaped );
     332                 :             }
     333                 :         }
     334                 :     }
     335                 : 
     336               9 :     if (NULL != poDS_->GetDescriptionField())
     337                 :     {
     338              27 :         for( int iField = 0; iField < poFeatureDefn_->GetFieldCount(); iField++ )
     339                 :         {        
     340              18 :             OGRFieldDefn *poField = poFeatureDefn_->GetFieldDefn( iField );
     341                 : 
     342              18 :             if( poFeature->IsFieldSet( iField )
     343                 :                 && EQUAL(poField->GetNameRef(), poDS_->GetDescriptionField()) )
     344                 :             {           
     345               1 :                 const char *pszRaw = poFeature->GetFieldAsString( iField );
     346               2 :                 while( *pszRaw == ' ' )
     347               0 :                     pszRaw++;
     348                 : 
     349               1 :                 char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw );
     350                 : 
     351               1 :                 VSIFPrintf( fp, "\t<description>%s</description>\n", pszEscaped);
     352               1 :                 CPLFree( pszEscaped );
     353                 :             }
     354                 :         }
     355                 :     }
     356                 : 
     357               9 :     OGRwkbGeometryType eGeomType = wkbFlatten(poFeatureDefn_->GetGeomType());
     358               9 :     if ( wkbPolygon == eGeomType
     359                 :          || wkbMultiPolygon == eGeomType
     360                 :          || wkbLineString == eGeomType
     361                 :          || wkbMultiLineString == eGeomType )
     362                 :     {
     363                 :         //If we're dealing with a polygon, add a line style that will stand out a bit
     364               0 :         VSIFPrintf( fp, "  <Style><LineStyle><color>ff0000ff</color></LineStyle>");
     365               0 :         VSIFPrintf( fp, "  <PolyStyle><fill>0</fill></PolyStyle></Style>\n" );
     366                 :     }
     367                 : 
     368               9 :     int bHasFoundOtherField = FALSE;
     369                 : 
     370                 :     // Write all fields as SchemaData
     371              27 :     for( int iField = 0; iField < poFeatureDefn_->GetFieldCount(); iField++ )
     372                 :     {
     373              18 :         OGRFieldDefn *poField = poFeatureDefn_->GetFieldDefn( iField );
     374                 : 
     375              18 :         if( poFeature->IsFieldSet( iField ))
     376                 :         {
     377               2 :             if (!bHasFoundOtherField)
     378                 :             {                
     379               1 :                 VSIFPrintf( fp, "\t<ExtendedData><SchemaData schemaUrl=\"#%s\">\n", pszName_ );
     380               1 :                 bHasFoundOtherField = TRUE;
     381                 :             }
     382               2 :             const char *pszRaw = poFeature->GetFieldAsString( iField );
     383                 : 
     384               4 :             while( *pszRaw == ' ' )
     385               0 :                 pszRaw++;
     386                 : 
     387               2 :             char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw );
     388                 : 
     389                 :             VSIFPrintf( fp, "\t\t<SimpleData name=\"%s\">%s</SimpleData>\n", 
     390               2 :                         poField->GetNameRef(), pszEscaped);
     391                 : 
     392               2 :             CPLFree( pszEscaped );
     393                 :         }
     394                 :     }
     395                 : 
     396               9 :     if (bHasFoundOtherField)
     397                 :     {
     398               1 :         VSIFPrintf( fp, "\t</SchemaData></ExtendedData>\n" );
     399                 :     }
     400                 : 
     401                 :     // Write out Geometry - for now it isn't indented properly.
     402               9 :     if( poFeature->GetGeometryRef() != NULL )
     403                 :     {
     404               9 :         char* pszGeometry = NULL;
     405               9 :         OGREnvelope sGeomBounds;
     406                 :         OGRGeometry* poWGS84Geom; 
     407                 : 
     408               9 :         if (NULL != poCT_)
     409                 :         {
     410               1 :             poWGS84Geom = poFeature->GetGeometryRef()->clone();
     411               1 :             poWGS84Geom->transform( poCT_ );
     412                 :         }
     413                 :         else
     414                 :         {
     415               8 :             poWGS84Geom = poFeature->GetGeometryRef();
     416                 :         }
     417                 :   
     418                 :         // TODO - porting
     419                 :         // pszGeometry = poFeature->GetGeometryRef()->exportToKML();
     420                 :         pszGeometry = 
     421                 :             OGR_G_ExportToKML( (OGRGeometryH)poWGS84Geom,
     422               9 :                                poDS_->GetAltitudeMode());
     423                 :         
     424               9 :         VSIFPrintf( fp, "      %s\n", pszGeometry );
     425               9 :         CPLFree( pszGeometry );
     426                 : 
     427               9 :         poWGS84Geom->getEnvelope( &sGeomBounds );
     428               9 :         poDS_->GrowExtents( &sGeomBounds );
     429                 : 
     430               9 :         if (NULL != poCT_)
     431                 :         {
     432               1 :             delete poWGS84Geom;
     433                 :         }
     434                 :     }
     435                 :     
     436               9 :     VSIFPrintf( fp, "  </Placemark>\n" );
     437               9 :     nWroteFeatureCount_++;
     438               9 :     return OGRERR_NONE;
     439                 : }
     440                 : 
     441                 : /************************************************************************/
     442                 : /*                           TestCapability()                           */
     443                 : /************************************************************************/
     444                 : 
     445               0 : int OGRKMLLayer::TestCapability( const char * pszCap )
     446                 : {
     447               0 :     if( EQUAL(pszCap, OLCSequentialWrite) )
     448                 :     {
     449               0 :         return bWriter_;
     450                 :     }
     451               0 :     else if( EQUAL(pszCap, OLCCreateField) )
     452                 :     {
     453               0 :         return bWriter_ && iNextKMLId_ == 0;
     454                 :     }
     455               0 :     else if( EQUAL(pszCap,OLCFastFeatureCount) )
     456                 :     {
     457                 : //        if( poFClass == NULL 
     458                 : //            || m_poFilterGeom != NULL 
     459                 : //            || m_poAttrQuery != NULL )
     460               0 :             return FALSE;
     461                 : 
     462                 : //        return poFClass->GetFeatureCount() != -1;
     463                 :     }
     464                 : 
     465               0 :     return FALSE;
     466                 : }
     467                 : 
     468                 : /************************************************************************/
     469                 : /*                            CreateField()                             */
     470                 : /************************************************************************/
     471                 : 
     472               0 : OGRErr OGRKMLLayer::CreateField( OGRFieldDefn *poField, int bApproxOK )
     473                 : {
     474               0 :     if( !bWriter_ || iNextKMLId_ != 0 )
     475               0 :         return OGRERR_FAILURE;
     476                 :       
     477               0 :   OGRFieldDefn oCleanCopy( poField );
     478               0 :     poFeatureDefn_->AddFieldDefn( &oCleanCopy );
     479                 : 
     480               0 :     return OGRERR_NONE;
     481                 : }
     482                 : 
     483                 : /************************************************************************/
     484                 : /*                           GetSpatialRef()                            */
     485                 : /************************************************************************/
     486                 : 
     487               0 : OGRSpatialReference *OGRKMLLayer::GetSpatialRef()
     488                 : {
     489               0 :     return poSRS_;
     490                 : }
     491                 : 
     492                 : /************************************************************************/
     493                 : /*                           SetLayerNumber()                           */
     494                 : /************************************************************************/
     495                 : 
     496               9 : void OGRKMLLayer::SetLayerNumber( int nLayer )
     497                 : {
     498               9 :     nLayerNumber_ = nLayer;
     499            1149 : }
     500                 : 

Generated by: LCOV version 1.7