LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/geojson - ogrgeojsonlayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 128 82 64.1 %
Date: 2010-01-09 Functions: 22 13 59.1 %

       1                 : /******************************************************************************
       2                 :  * $Id$
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implementation of OGRGeoJSONLayer class (OGR GeoJSON Driver).
       6                 :  * Author:   Mateusz Loskot, mateusz@loskot.net
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2007, Mateusz Loskot
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : #include "ogr_geojson.h"
      30                 : #include "ogrgeojsonwriter.h"
      31                 : #include <jsonc/json.h> // JSON-C
      32                 : #include <algorithm> // for_each, find_if
      33                 : 
      34                 : /* Remove annoying warnings Microsoft Visual C++ */
      35                 : #if defined(_MSC_VER)
      36                 : #  pragma warning(disable:4512)
      37                 : #endif
      38                 : 
      39                 : /************************************************************************/
      40                 : /*                       STATIC MEMBERS DEFINITION                      */
      41                 : /************************************************************************/
      42                 : 
      43                 : const char* const OGRGeoJSONLayer::DefaultName = "OGRGeoJSON";
      44                 : const char* const OGRGeoJSONLayer::DefaultFIDColumn = "id";
      45                 : const OGRwkbGeometryType OGRGeoJSONLayer::DefaultGeometryType = wkbUnknown;
      46                 : 
      47                 : /************************************************************************/
      48                 : /*                           OGRGeoJSONLayer                            */
      49                 : /************************************************************************/
      50                 : 
      51              20 : OGRGeoJSONLayer::OGRGeoJSONLayer( const char* pszName,
      52                 :                                   OGRSpatialReference* poSRSIn,
      53                 :                                   OGRwkbGeometryType eGType,
      54                 :                                   char** papszOptions,
      55                 :                                   OGRGeoJSONDataSource* poDS )
      56              20 :     : iterCurrent_( seqFeatures_.end() ), poDS_( poDS ), poFeatureDefn_(new OGRFeatureDefn( pszName ) ), poSRS_( NULL ), nOutCounter_( 0 )
      57                 : {
      58                 :     UNREFERENCED_PARAM(papszOptions);
      59                 : 
      60                 :     CPLAssert( NULL != poDS_ );
      61                 :     CPLAssert( NULL != poFeatureDefn_ );
      62                 :     
      63              20 :     poFeatureDefn_->Reference();
      64              20 :     poFeatureDefn_->SetGeomType( eGType );
      65                 : 
      66              20 :     if( NULL != poSRSIn )
      67                 :     {
      68               0 :         SetSpatialRef( poSRSIn );
      69                 :     }
      70              20 : }
      71                 : 
      72                 : /************************************************************************/
      73                 : /*                          ~OGRGeoJSONLayer                            */
      74                 : /************************************************************************/
      75                 : 
      76              40 : OGRGeoJSONLayer::~OGRGeoJSONLayer()
      77                 : {
      78              20 :     FILE* fp = poDS_->GetOutputFile();
      79              20 :     if( NULL != fp )
      80                 :     {
      81               6 :         VSIFPrintf( fp, "\n]\n}\n" );
      82                 :     }
      83                 : 
      84                 :     std::for_each(seqFeatures_.begin(), seqFeatures_.end(),
      85              20 :                   OGRFeature::DestroyFeature);
      86                 : 
      87              20 :     if( NULL != poFeatureDefn_ )
      88                 :     {
      89              20 :         poFeatureDefn_->Release();
      90                 :     }
      91                 : 
      92              20 :     if( NULL != poSRS_ )
      93                 :     {
      94              14 :         poSRS_->Release();   
      95                 :     }
      96              40 : }
      97                 : 
      98                 : /************************************************************************/
      99                 : /*                           GetLayerDefn                               */
     100                 : /************************************************************************/
     101                 : 
     102              84 : OGRFeatureDefn* OGRGeoJSONLayer::GetLayerDefn()
     103                 : {
     104              84 :     return poFeatureDefn_;
     105                 : }
     106                 : 
     107                 : /************************************************************************/
     108                 : /*                           GetSpatialRef                              */
     109                 : /************************************************************************/
     110                 : 
     111               1 : OGRSpatialReference* OGRGeoJSONLayer::GetSpatialRef()
     112                 : {
     113               1 :     return poSRS_;
     114                 : }
     115                 : 
     116              14 : void OGRGeoJSONLayer::SetSpatialRef( OGRSpatialReference* poSRSIn )
     117                 : {
     118              14 :     if( NULL == poSRSIn )
     119                 :     {
     120               0 :         poSRS_ = NULL;
     121                 :         // poSRS_ = new OGRSpatialReference();
     122                 :         // if( OGRERR_NONE != poSRS_->importFromEPSG( 4326 ) )
     123                 :         // {
     124                 :         //     delete poSRS_;
     125                 :         //     poSRS_ = NULL;
     126                 :         // }
     127                 :     }
     128                 :     else
     129                 :     {
     130              14 :         poSRS_ = poSRSIn->Clone(); 
     131                 :     }
     132              14 : }
     133                 : 
     134                 : /************************************************************************/
     135                 : /*                           GetFeatureCount                            */
     136                 : /************************************************************************/
     137                 : 
     138               8 : int OGRGeoJSONLayer::GetFeatureCount( int bForce )
     139                 : {
     140               8 :     if (m_poFilterGeom == NULL && m_poAttrQuery == NULL)
     141               8 :         return static_cast<int>( seqFeatures_.size() );
     142                 :     else
     143               0 :         return OGRLayer::GetFeatureCount(bForce);
     144                 : }
     145                 : 
     146                 : /************************************************************************/
     147                 : /*                           ResetReading                               */
     148                 : /************************************************************************/
     149                 : 
     150              42 : void OGRGeoJSONLayer::ResetReading()
     151                 : {
     152              42 :     iterCurrent_ = seqFeatures_.begin();
     153              42 : }
     154                 : 
     155                 : /*======================================================================*/
     156                 : /*                           Features Filter Utilities                  */
     157                 : /*======================================================================*/
     158                 : 
     159                 : /*******************************************/
     160                 : /*          EvaluateSpatialFilter          */
     161                 : /*******************************************/
     162                 : 
     163               0 : bool OGRGeoJSONLayer::EvaluateSpatialFilter( OGRGeometry* poGeometry )
     164                 : {
     165               0 :     return ( FilterGeometry( poGeometry ) == 0 ? false : true );
     166                 : }
     167                 : 
     168                 : /*******************************************/
     169                 : /*          SpatialFilterPredicate         */
     170                 : /*******************************************/
     171                 : 
     172                 : struct SpatialFilterPredicate
     173                 : {
     174               0 :     explicit SpatialFilterPredicate(OGRGeoJSONLayer& layer)
     175               0 :         : layer_(layer)
     176               0 :     {}
     177               0 :     bool operator()( OGRFeature* p )
     178                 :     {
     179               0 :         return layer_.EvaluateSpatialFilter( p->GetGeometryRef() );
     180                 :     }
     181                 : 
     182                 : private:
     183                 : 
     184                 :     OGRGeoJSONLayer& layer_;
     185                 : };
     186                 : 
     187                 : /*******************************************/
     188                 : /*          AttributeFilterPredicate       */
     189                 : /*******************************************/
     190                 : 
     191                 : struct AttributeFilterPredicate
     192                 : {
     193               0 :     explicit AttributeFilterPredicate(OGRFeatureQuery& query)
     194               0 :         : query_(query)
     195               0 :     {}
     196                 : 
     197               0 :     bool operator()( OGRFeature* p )
     198                 :     {
     199               0 :         return ( query_.Evaluate( p ) == 0 ? false : true );
     200                 :     }
     201                 : 
     202                 : private:
     203                 : 
     204                 :     OGRFeatureQuery& query_;
     205                 : };
     206                 : 
     207                 : /************************************************************************/
     208                 : /*                           GetNextFeature                             */
     209                 : /************************************************************************/
     210                 : 
     211              47 : OGRFeature* OGRGeoJSONLayer::GetNextFeature()
     212                 : {
     213              47 :     bool bSingle = false;
     214                 : 
     215              47 :     if( NULL != m_poFilterGeom )
     216                 :     {
     217                 :         iterCurrent_ = std::find_if( iterCurrent_, seqFeatures_.end(),
     218               0 :                        SpatialFilterPredicate(*this) );
     219               0 :         bSingle = (iterCurrent_ != seqFeatures_.end());
     220                 :     }
     221                 : 
     222              47 :     if( NULL != m_poAttrQuery )
     223                 :     {
     224                 :         FeaturesSeq::iterator seqEnd = 
     225               0 :             ( bSingle ? iterCurrent_ : seqFeatures_.end() );
     226                 : 
     227                 :         iterCurrent_ = std::find_if( iterCurrent_, seqEnd,
     228               0 :                        AttributeFilterPredicate(*m_poAttrQuery) );
     229                 :     }
     230                 : 
     231              47 :     if( iterCurrent_ != seqFeatures_.end() )
     232                 :     {
     233              27 :         OGRFeature* poFeature = (*iterCurrent_);
     234                 :         CPLAssert( NULL != poFeature );
     235                 : 
     236              27 :         OGRFeature* poFeatureCopy = poFeature->Clone();
     237                 :         CPLAssert( NULL != poFeatureCopy );
     238                 : 
     239              27 :         if (poFeatureCopy->GetGeometryRef() != NULL && poSRS_ != NULL)
     240                 :         {
     241              27 :             poFeatureCopy->GetGeometryRef()->assignSpatialReference( poSRS_ );
     242                 :         }
     243                 : 
     244              27 :         ++iterCurrent_;
     245              27 :         return poFeatureCopy;
     246                 :     }
     247                 : 
     248              20 :     return NULL;
     249                 : }
     250                 : 
     251                 : /************************************************************************/
     252                 : /*                           GetFeature                             */
     253                 : /************************************************************************/
     254                 : 
     255               0 : OGRFeature* OGRGeoJSONLayer::GetFeature( long nFID )
     256                 : {
     257               0 :   OGRFeature* poFeature = NULL;
     258               0 :   poFeature = OGRLayer::GetFeature( nFID );
     259                 : 
     260               0 :   return poFeature;
     261                 : }
     262                 : 
     263                 : /************************************************************************/
     264                 : /*                           CreateFeature                              */
     265                 : /************************************************************************/
     266                 : 
     267               6 : OGRErr OGRGeoJSONLayer::CreateFeature( OGRFeature* poFeature )
     268                 : {
     269               6 :     FILE* fp = poDS_->GetOutputFile();
     270               6 :     if( NULL == poFeature )
     271                 :     {
     272               0 :         CPLDebug( "GeoJSON", "Target datasource file is invalid." );
     273               0 :         return CE_Failure;
     274                 :     }
     275                 : 
     276               6 :     if( NULL == poFeature )
     277                 :     {
     278               0 :         CPLDebug( "GeoJSON", "Feature is null" );
     279               0 :         return OGRERR_INVALID_HANDLE;
     280                 :     }
     281                 : 
     282               6 :     json_object* poObj = OGRGeoJSONWriteFeature( poFeature );
     283                 :     CPLAssert( NULL != poObj );
     284                 : 
     285               6 :     if( nOutCounter_ > 0 )
     286                 :     {
     287                 :         /* Separate "Feature" entries in "FeatureCollection" object. */
     288               0 :         VSIFPrintf( fp, ",\n" );
     289                 :     }
     290               6 :     VSIFPrintf( fp, "%s\n", json_object_to_json_string( poObj ) );
     291                 : 
     292               6 :     json_object_put( poObj );
     293                 : 
     294               6 :     ++nOutCounter_;
     295                 : 
     296               6 :     return OGRERR_NONE;
     297                 : }
     298                 : 
     299              12 : OGRErr OGRGeoJSONLayer::CreateField(OGRFieldDefn* poField, int bApproxOK)
     300                 : {
     301                 :     UNREFERENCED_PARAM(bApproxOK);
     302                 : 
     303              18 :     for( int i = 0; i < poFeatureDefn_->GetFieldCount(); ++i )
     304                 :     {
     305               6 :         OGRFieldDefn* poDefn = poFeatureDefn_->GetFieldDefn(i);
     306                 :         CPLAssert( NULL != poDefn );
     307                 : 
     308               6 :         if( EQUAL( poDefn->GetNameRef(), poField->GetNameRef() ) )
     309                 :         {
     310                 :             CPLDebug( "GeoJSON", "Field '%s' already present in schema",
     311               0 :                       poField->GetNameRef() );
     312                 :             
     313                 :             // TODO - mloskot: Is this return code correct?
     314               0 :             return OGRERR_NONE;
     315                 :         }
     316                 :     }
     317                 : 
     318              12 :     poFeatureDefn_->AddFieldDefn( poField );
     319                 : 
     320              12 :     return OGRERR_NONE;
     321                 : }
     322                 : 
     323                 : /************************************************************************/
     324                 : /*                           TestCapability                             */
     325                 : /************************************************************************/
     326                 : 
     327               0 : int OGRGeoJSONLayer::TestCapability( const char* pszCap )
     328                 : {
     329                 :     UNREFERENCED_PARAM(pszCap);
     330                 : 
     331               0 :     return FALSE;
     332                 : }
     333                 : 
     334                 : /************************************************************************/
     335                 : /*                           GetFIDColumn                               */
     336                 : /************************************************************************/
     337                 :   
     338               0 : const char* OGRGeoJSONLayer::GetFIDColumn()
     339                 : {
     340               0 :   return sFIDColumn_.c_str();
     341                 : }
     342                 : 
     343                 : /************************************************************************/
     344                 : /*                           SetFIDColumn                               */
     345                 : /************************************************************************/
     346                 : 
     347               0 : void OGRGeoJSONLayer::SetFIDColumn( const char* pszFIDColumn )
     348                 : {
     349               0 :   sFIDColumn_ = pszFIDColumn;
     350               0 : }
     351                 : 
     352                 : /************************************************************************/
     353                 : /*                           AddFeature                                 */
     354                 : /************************************************************************/
     355                 : 
     356              14 : void OGRGeoJSONLayer::AddFeature( OGRFeature* poFeature )
     357                 : {
     358                 :     CPLAssert( NULL != poFeature );
     359                 : 
     360                 :     // NOTE - mloskot:
     361                 :     // Features may not be sorted according to FID values.
     362                 : 
     363                 :     // TODO: Should we check if feature already exists?
     364                 :     // TODO: Think about sync operation, upload, etc.
     365                 : 
     366              14 :     OGRFeature* poNewFeature = NULL;
     367              14 :     poNewFeature = poFeature->Clone();
     368                 : 
     369                 : 
     370              14 :     if( -1 == poNewFeature->GetFID() )
     371                 :     {
     372              14 :         int nFID = static_cast<int>(seqFeatures_.size());
     373              14 :         poNewFeature->SetFID( nFID );
     374                 : 
     375                 :         // TODO - mlokot: We need to redesign creation of FID column
     376              14 :         int nField = poNewFeature->GetFieldIndex( DefaultFIDColumn );
     377              14 :         if( -1 != nField )
     378                 :         {
     379               0 :             poNewFeature->SetField( nField, nFID );
     380                 :         }
     381                 :     }
     382                 : 
     383              14 :     seqFeatures_.push_back( poNewFeature );
     384              14 : }
     385                 : 
     386                 : /************************************************************************/
     387                 : /*                           DetectGeometryType                         */
     388                 : /************************************************************************/
     389                 : 
     390              14 : void OGRGeoJSONLayer::DetectGeometryType()
     391                 : {
     392              14 :     OGRwkbGeometryType featType = wkbUnknown;
     393              14 :     OGRGeometry* poGeometry = NULL;
     394              14 :     FeaturesSeq::const_iterator it = seqFeatures_.begin();
     395              14 :     FeaturesSeq::const_iterator end = seqFeatures_.end();
     396                 :     
     397              14 :     if( it != end )
     398                 :     {
     399              14 :         poGeometry = (*it)->GetGeometryRef();
     400              14 :         if( NULL != poGeometry )
     401                 :         {
     402              14 :             featType = poGeometry->getGeometryType();
     403              14 :             if( featType != poFeatureDefn_->GetGeomType() )
     404                 :             {
     405              14 :                 poFeatureDefn_->SetGeomType( featType );
     406                 :             }
     407                 :         }
     408              14 :         ++it;
     409                 :     }
     410                 : 
     411              28 :     while( it != end )
     412                 :     {
     413               0 :         poGeometry = (*it)->GetGeometryRef();
     414               0 :         if( NULL != poGeometry )
     415                 :         {
     416               0 :             featType = poGeometry->getGeometryType();
     417               0 :             if( featType != poFeatureDefn_->GetGeomType() )
     418                 :             {
     419                 :                 CPLDebug( "GeoJSON",
     420               0 :                     "Detected layer of mixed-geometry type features." );
     421               0 :                 poFeatureDefn_->SetGeomType( DefaultGeometryType );
     422               0 :                 break;
     423                 :             }
     424                 :         }
     425               0 :         ++it;
     426                 :     }
     427              14 : }

Generated by: LCOV version 1.7