LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/geojson - ogrgeojsonreader.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 507 365 72.0 %
Date: 2010-01-09 Functions: 27 24 88.9 %

       1                 : /******************************************************************************
       2                 :  * $Id$
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implementation of OGRGeoJSONReader 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 "ogrgeojsonreader.h"
      30                 : #include "ogrgeojsonutils.h"
      31                 : #include "ogr_geojson.h"
      32                 : #include <jsonc/json.h> // JSON-C
      33                 : #include <ogr_api.h>
      34                 : 
      35                 : /************************************************************************/
      36                 : /*                           OGRGeoJSONReader                           */
      37                 : /************************************************************************/
      38                 : 
      39              14 : OGRGeoJSONReader::OGRGeoJSONReader()
      40                 :     : poGJObject_( NULL ), poLayer_( NULL ),
      41                 :         bGeometryPreserve_( true ),
      42              14 :         bAttributesSkip_( false )
      43                 : {
      44                 :     // Take a deep breath and get to work.
      45              14 : }
      46                 : 
      47                 : /************************************************************************/
      48                 : /*                          ~OGRGeoJSONReader                           */
      49                 : /************************************************************************/
      50                 : 
      51              14 : OGRGeoJSONReader::~OGRGeoJSONReader()
      52                 : {
      53              14 :     if( NULL != poGJObject_ )
      54                 :     {
      55              14 :         json_object_put(poGJObject_);
      56                 :     }
      57                 : 
      58              14 :     poGJObject_ = NULL;
      59              14 :     poLayer_ = NULL;
      60              14 : }
      61                 : 
      62                 : /************************************************************************/
      63                 : /*                           Parse                                      */
      64                 : /************************************************************************/
      65                 : 
      66              14 : OGRErr OGRGeoJSONReader::Parse( const char* pszText )
      67                 : {
      68              14 :     if( NULL != pszText )
      69                 :     {
      70              14 :         json_tokener* jstok = NULL;
      71              14 :         json_object* jsobj = NULL;
      72                 : 
      73              14 :         jstok = json_tokener_new();
      74              14 :         jsobj = json_tokener_parse_ex(jstok, pszText, -1);
      75              14 :         if( jstok->err != json_tokener_success)
      76                 :         {
      77                 :             CPLError( CE_Failure, CPLE_AppDefined,
      78                 :                       "GeoJSON parsing error: %s (at offset %d)",
      79               0 :                     json_tokener_errors[jstok->err], jstok->char_offset);
      80                 :             
      81               0 :             json_tokener_free(jstok);
      82               0 :             return OGRERR_CORRUPT_DATA;
      83                 :         }
      84              14 :         json_tokener_free(jstok);
      85                 : 
      86                 :         /* JSON tree is shared for while lifetime of the reader object
      87                 :          * and will be released in the destructor.
      88                 :          */
      89              14 :         poGJObject_ = jsobj;
      90                 :     }
      91                 : 
      92              14 :     return OGRERR_NONE;
      93                 : }
      94                 : 
      95                 : /************************************************************************/
      96                 : /*                           ReadLayer                                  */
      97                 : /************************************************************************/
      98                 : 
      99              14 : OGRGeoJSONLayer* OGRGeoJSONReader::ReadLayer( const char* pszName,
     100                 :                                               OGRGeoJSONDataSource* poDS )
     101                 : {
     102                 :     CPLAssert( NULL == poLayer_ );
     103                 : 
     104              14 :     if( NULL == poGJObject_ )
     105                 :     {
     106                 :         CPLDebug( "GeoJSON",
     107               0 :                   "Missing parset GeoJSON data. Forgot to call Parse()?" );
     108               0 :         return NULL;
     109                 :     }
     110                 :         
     111                 :     poLayer_ = new OGRGeoJSONLayer( pszName, NULL,
     112                 :                                    OGRGeoJSONLayer::DefaultGeometryType,
     113              14 :                                    NULL, poDS );
     114                 : 
     115              14 :     if( !GenerateLayerDefn() )
     116                 :     {
     117                 :         CPLError( CE_Failure, CPLE_AppDefined,
     118               0 :             "Layer schema generation failed." );
     119                 : 
     120               0 :         delete poLayer_;
     121               0 :         return NULL;
     122                 :     }
     123                 : 
     124                 : /* -------------------------------------------------------------------- */
     125                 : /*      Translate single geometry-only Feature object.                  */
     126                 : /* -------------------------------------------------------------------- */
     127              14 :     GeoJSONObject::Type objType = OGRGeoJSONGetType( poGJObject_ );
     128                 : 
     129              22 :     if( GeoJSONObject::ePoint == objType
     130                 :         || GeoJSONObject::eMultiPoint == objType
     131                 :         || GeoJSONObject::eLineString == objType
     132                 :         || GeoJSONObject::eMultiLineString == objType
     133                 :         || GeoJSONObject::ePolygon == objType
     134                 :         || GeoJSONObject::eMultiPolygon == objType
     135                 :         || GeoJSONObject::eGeometryCollection == objType )
     136                 :     {
     137               8 :         OGRGeometry* poGeometry = NULL;
     138               8 :         poGeometry = ReadGeometry( poGJObject_ );
     139               8 :         if( !AddFeature( poGeometry ) )
     140                 :         {
     141                 :             CPLDebug( "GeoJSON",
     142               0 :                       "Translation of single geometry failed." );
     143               0 :             delete poLayer_;
     144               0 :             return NULL;
     145                 :         }
     146                 :     }
     147                 : /* -------------------------------------------------------------------- */
     148                 : /*      Translate single but complete Feature object.                   */
     149                 : /* -------------------------------------------------------------------- */
     150               6 :     else if( GeoJSONObject::eFeature == objType )
     151                 :     {
     152               0 :         OGRFeature* poFeature = NULL;
     153               0 :         poFeature = ReadFeature( poGJObject_ );
     154               0 :         if( !AddFeature( poFeature ) )
     155                 :         {
     156                 :             CPLDebug( "GeoJSON",
     157               0 :                       "Translation of single feature failed." );
     158                 : 
     159               0 :             delete poLayer_;
     160               0 :             return NULL;
     161                 :         }
     162                 :     }
     163                 : /* -------------------------------------------------------------------- */
     164                 : /*      Translate multi-feature FeatureCollection object.               */
     165                 : /* -------------------------------------------------------------------- */
     166               6 :     else if( GeoJSONObject::eFeatureCollection == objType )
     167                 :     {
     168               6 :         OGRGeoJSONLayer* poThisLayer = NULL;
     169               6 :         poThisLayer = ReadFeatureCollection( poGJObject_ );
     170                 :         CPLAssert( poLayer_ == poThisLayer );
     171                 :     }
     172                 :     else
     173                 :     {
     174                 :         CPLError( CE_Failure, CPLE_AppDefined,
     175               0 :             "Unrecognized GeoJSON structure." );
     176                 : 
     177               0 :         delete poLayer_;
     178               0 :         return NULL;
     179                 :     }
     180                 : 
     181              14 :     OGRSpatialReference* poSRS = NULL;
     182              14 :     poSRS = OGRGeoJSONReadSpatialReference( poGJObject_ );
     183              14 :     if (poSRS == NULL ) {
     184                 :         // If there is none defined, we use 4326
     185              13 :         poSRS = new OGRSpatialReference();
     186              13 :         if( OGRERR_NONE != poSRS->importFromEPSG( 4326 ) )
     187                 :         {
     188               0 :             delete poSRS;
     189               0 :             poSRS = NULL;
     190                 :         }
     191              13 :         poLayer_->SetSpatialRef( poSRS );
     192              13 :         delete poSRS;
     193                 :     }
     194                 :     else {
     195               1 :         poLayer_->SetSpatialRef( poSRS );
     196               1 :         delete poSRS;
     197                 :     }
     198                 : 
     199                 :     // TODO: FeatureCollection
     200                 : 
     201              14 :     return poLayer_;
     202                 : }
     203                 : 
     204              16 : OGRSpatialReference* OGRGeoJSONReadSpatialReference( json_object* poObj) {
     205                 :     
     206                 : /* -------------------------------------------------------------------- */
     207                 : /*      Read spatial reference definition.                              */
     208                 : /* -------------------------------------------------------------------- */
     209              16 :     OGRSpatialReference* poSRS = NULL;
     210                 : 
     211              16 :     json_object* poObjSrs = OGRGeoJSONFindMemberByName( poObj, "crs" );
     212              16 :     if( NULL != poObjSrs )
     213                 :     {
     214               3 :         json_object* poObjSrsType = OGRGeoJSONFindMemberByName( poObjSrs, "type" );
     215               3 :         const char* pszSrsType = json_object_get_string( poObjSrsType );
     216                 : 
     217                 :         // TODO: Add URL and URN types support
     218               3 :         if( EQUALN( pszSrsType, "NAME", 4 ) )
     219                 :         {
     220               3 :             json_object* poObjSrsProps = OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
     221                 :             CPLAssert( NULL != poObjSrsProps );
     222                 : 
     223               3 :             json_object* poNameURL = OGRGeoJSONFindMemberByName( poObjSrsProps, "name" );
     224                 :             CPLAssert( NULL != poNameURL );
     225                 : 
     226               3 :             const char* pszName = json_object_get_string( poNameURL );
     227                 : 
     228               3 :             poSRS = new OGRSpatialReference();
     229               3 :             if( OGRERR_NONE != poSRS->SetFromUserInput( pszName ) )
     230                 :             {
     231               0 :                 delete poSRS;
     232               0 :                 poSRS = NULL;
     233                 :             }
     234                 :         }
     235                 : 
     236               3 :         if( EQUALN( pszSrsType, "EPSG", 4 ) )
     237                 :         {
     238               0 :             json_object* poObjSrsProps = OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
     239                 :             CPLAssert( NULL != poObjSrsProps );
     240                 : 
     241               0 :             json_object* poObjCode = OGRGeoJSONFindMemberByName( poObjSrsProps, "code" );
     242                 :             CPLAssert( NULL != poObjCode );
     243                 : 
     244               0 :             int nEPSG = json_object_get_int( poObjCode );
     245                 : 
     246               0 :             poSRS = new OGRSpatialReference();
     247               0 :             if( OGRERR_NONE != poSRS->importFromEPSG( nEPSG ) )
     248                 :             {
     249               0 :                 delete poSRS;
     250               0 :                 poSRS = NULL;
     251                 :             }
     252                 :         }
     253               3 :         if( EQUALN( pszSrsType, "URL", 3 ) || EQUALN( pszSrsType, "LINK", 4 )  )
     254                 :         {
     255               0 :             json_object* poObjSrsProps = OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
     256                 :             CPLAssert( NULL != poObjSrsProps );
     257                 : 
     258               0 :             json_object* poObjURL = OGRGeoJSONFindMemberByName( poObjSrsProps, "url" );
     259                 :             
     260               0 :             if (NULL == poObjURL) {
     261               0 :                 poObjURL = OGRGeoJSONFindMemberByName( poObjSrsProps, "href" );
     262                 :             }
     263                 :             CPLAssert( NULL != poObjURL );
     264                 : 
     265               0 :             const char* pszURL = json_object_get_string( poObjURL );
     266                 : 
     267               0 :             poSRS = new OGRSpatialReference();
     268               0 :             if( OGRERR_NONE != poSRS->importFromUrl( pszURL ) )
     269                 :             {
     270               0 :                 delete poSRS;
     271               0 :                 poSRS = NULL;
     272                 : 
     273                 :             }
     274                 :         }
     275                 :     }
     276                 :     
     277              16 :     return poSRS;
     278                 : }
     279                 : /************************************************************************/
     280                 : /*                           SetPreserveGeometryType                    */
     281                 : /************************************************************************/
     282                 : 
     283               0 : void OGRGeoJSONReader::SetPreserveGeometryType( bool bPreserve )
     284                 : {
     285               0 :     bGeometryPreserve_ = bPreserve;
     286               0 : }
     287                 : 
     288                 : /************************************************************************/
     289                 : /*                           SetSkipAttributes                          */
     290                 : /************************************************************************/
     291                 : 
     292               0 : void OGRGeoJSONReader::SetSkipAttributes( bool bSkip )
     293                 : {
     294               0 :     bAttributesSkip_ = bSkip;
     295               0 : }
     296                 : 
     297                 : /************************************************************************/
     298                 : /*                           GenerateFeatureDefn                        */
     299                 : /************************************************************************/
     300                 : 
     301              14 : bool OGRGeoJSONReader::GenerateLayerDefn()
     302                 : {
     303                 :     CPLAssert( NULL != poGJObject_ );
     304                 :     CPLAssert( NULL != poLayer_->GetLayerDefn() );
     305                 :     CPLAssert( 0 == poLayer_->GetLayerDefn()->GetFieldCount() );
     306                 : 
     307              14 :     bool bSuccess = true;
     308                 : 
     309              14 :     if( bAttributesSkip_ )
     310               0 :         return true;
     311                 : 
     312                 : /* -------------------------------------------------------------------- */
     313                 : /*      Scan all features and generate layer definition.        */
     314                 : /* -------------------------------------------------------------------- */
     315              14 :     GeoJSONObject::Type objType = OGRGeoJSONGetType( poGJObject_ );
     316              14 :     if( GeoJSONObject::eFeature == objType )
     317                 :     {
     318               0 :         bSuccess = GenerateFeatureDefn( poGJObject_ );
     319                 :     }
     320              14 :     else if( GeoJSONObject::eFeatureCollection == objType )
     321                 :     {
     322               6 :         json_object* poObjFeatures = NULL;
     323               6 :         poObjFeatures = OGRGeoJSONFindMemberByName( poGJObject_, "features" );
     324               6 :         if( NULL != poObjFeatures
     325                 :             && json_type_array == json_object_get_type( poObjFeatures ) )
     326                 :         {
     327               6 :             json_object* poObjFeature = NULL;
     328               6 :             const int nFeatures = json_object_array_length( poObjFeatures );
     329              12 :             for( int i = 0; i < nFeatures; ++i )
     330                 :             {
     331               6 :                 poObjFeature = json_object_array_get_idx( poObjFeatures, i );
     332               6 :                 if( !GenerateFeatureDefn( poObjFeature ) )
     333                 :                 {
     334               0 :                     CPLDebug( "GeoJSON", "Create feature schema failure." );
     335               0 :                     bSuccess = false;
     336                 :                 }
     337                 :             }
     338                 :         }
     339                 :         else
     340                 :         {
     341                 :             CPLError( CE_Failure, CPLE_AppDefined,
     342                 :                       "Invalid FeatureCollection object. "
     343               0 :                       "Missing \'features\' member." );
     344               0 :             bSuccess = false;
     345                 :         }
     346                 :     }
     347                 : 
     348                 : /* -------------------------------------------------------------------- */
     349                 : /*      Validate and add FID column if necessary.                       */
     350                 : /* -------------------------------------------------------------------- */
     351              14 :   OGRFeatureDefn* poLayerDefn = poLayer_->GetLayerDefn();
     352                 :   CPLAssert( NULL != poLayerDefn );
     353                 : 
     354              14 :   bool bHasFID = false;
     355                 : 
     356              26 :   for( int i = 0; i < poLayerDefn->GetFieldCount(); ++i )
     357                 :   {
     358              12 :     OGRFieldDefn* poDefn = poLayerDefn->GetFieldDefn(i);
     359              12 :     if( EQUAL( poDefn->GetNameRef(), OGRGeoJSONLayer::DefaultFIDColumn )
     360                 :       && OFTInteger == poDefn->GetType() )
     361                 :     {
     362               0 :       poLayer_->SetFIDColumn( poDefn->GetNameRef() );
     363               0 :             bHasFID = true;
     364               0 :             break;
     365                 :     }
     366                 :   }
     367                 : 
     368                 :     // TODO - mloskot: This is wrong! We want to add only FID field if
     369                 :     // found in source layer (by default name or by FID_PROPERTY= specifier,
     370                 :     // the latter has to be implemented).
     371                 :     /*
     372                 :     if( !bHasFID )
     373                 :     {
     374                 :         OGRFieldDefn fldDefn( OGRGeoJSONLayer::DefaultFIDColumn, OFTInteger );
     375                 :         poLayerDefn->AddFieldDefn( &fldDefn );
     376                 :         poLayer_->SetFIDColumn( fldDefn.GetNameRef() );
     377                 :     }
     378                 :     */
     379                 : 
     380              14 :     return bSuccess;
     381                 : }
     382                 : 
     383               6 : bool OGRGeoJSONReader::GenerateFeatureDefn( json_object* poObj )
     384                 : {
     385               6 :     OGRFeatureDefn* poDefn = poLayer_->GetLayerDefn();
     386                 :     CPLAssert( NULL != poDefn );
     387                 : 
     388               6 :     bool bSuccess = false;
     389                 : 
     390                 : /* -------------------------------------------------------------------- */
     391                 : /*      Read collection of properties.                  */
     392                 : /* -------------------------------------------------------------------- */
     393               6 :     json_object* poObjProps = NULL;
     394               6 :     poObjProps = OGRGeoJSONFindMemberByName( poObj, "properties" );
     395               6 :     if( NULL != poObjProps )
     396                 :     {
     397                 :         json_object_iter it;
     398               6 :         it.key = NULL;
     399               6 :         it.val = NULL;
     400               6 :         it.entry = NULL;
     401              18 :         json_object_object_foreachC( poObjProps, it )
     402                 :         {
     403              12 :             if( -1 == poDefn->GetFieldIndex( it.key ) )
     404                 :             {
     405                 :                 OGRFieldDefn fldDefn( it.key,
     406              12 :                     GeoJSONPropertyToFieldType( it.val ) );
     407              12 :                 poDefn->AddFieldDefn( &fldDefn );
     408                 :             }
     409                 :         }
     410                 : 
     411               6 :         bSuccess = true; // SUCCESS
     412                 :     }
     413                 :     else
     414                 :     {
     415                 :         CPLError( CE_Failure, CPLE_AppDefined,
     416                 :                   "Invalid Feature object. "
     417               0 :                   "Missing \'properties\' member." );
     418                 :     }
     419                 : 
     420               6 :     return bSuccess;
     421                 : }
     422                 : 
     423                 : /************************************************************************/
     424                 : /*                           AddFeature                                 */
     425                 : /************************************************************************/
     426                 : 
     427               8 : bool OGRGeoJSONReader::AddFeature( OGRGeometry* poGeometry )
     428                 : {
     429               8 :     bool bAdded = false;
     430                 : 
     431                 :     // TODO: Should we check if geometry is of type of 
     432                 :     //       wkbGeometryCollection ?
     433                 : 
     434               8 :     if( NULL != poGeometry )
     435                 :     {
     436               8 :         OGRFeature* poFeature = NULL;
     437               8 :         poFeature = new OGRFeature( poLayer_->GetLayerDefn() );
     438               8 :         poFeature->SetGeometryDirectly( poGeometry );
     439                 : 
     440               8 :         bAdded = AddFeature( poFeature );
     441                 :     }
     442                 :     
     443               8 :     return bAdded;
     444                 : }
     445                 : 
     446                 : /************************************************************************/
     447                 : /*                           AddFeature                                 */
     448                 : /************************************************************************/
     449                 : 
     450              14 : bool OGRGeoJSONReader::AddFeature( OGRFeature* poFeature )
     451                 : {
     452              14 :     bool bAdded = false;
     453                 :   
     454              14 :     if( NULL != poFeature )
     455                 :     {
     456              14 :         poLayer_->AddFeature( poFeature );
     457              14 :         bAdded = true;
     458              14 :         delete poFeature;
     459                 :     }
     460                 : 
     461              14 :     return bAdded;
     462                 : }
     463                 : 
     464                 : /************************************************************************/
     465                 : /*                           ReadGeometry                               */
     466                 : /************************************************************************/
     467                 : 
     468              14 : OGRGeometry* OGRGeoJSONReader::ReadGeometry( json_object* poObj )
     469                 : {
     470              14 :     OGRGeometry* poGeometry = NULL;
     471                 : 
     472              14 :     poGeometry = OGRGeoJSONReadGeometry( poObj );
     473                 : 
     474                 : /* -------------------------------------------------------------------- */
     475                 : /*      Wrap geometry with GeometryCollection as a common denominator.  */
     476                 : /*      Sometimes a GeoJSON text may consist of objects of different    */
     477                 : /*      geometry types. Users may request wrapping all geometries with  */
     478                 : /*      OGRGeometryCollection type by using option                      */
     479                 : /*      GEOMETRY_AS_COLLECTION=NO|YES (NO is default).                 */
     480                 : /* -------------------------------------------------------------------- */
     481              14 :     if( NULL != poGeometry )
     482                 :     {
     483              14 :         if( !bGeometryPreserve_ 
     484               0 :             && wkbGeometryCollection != poGeometry->getGeometryType() )
     485                 :         {
     486               0 :             OGRGeometryCollection* poMetaGeometry = NULL;
     487               0 :             poMetaGeometry = new OGRGeometryCollection();
     488               0 :             poMetaGeometry->addGeometryDirectly( poGeometry );
     489               0 :             return poMetaGeometry;
     490                 :         }
     491                 :     }
     492                 : 
     493              14 :     return poGeometry;
     494                 : }
     495                 : 
     496                 : /************************************************************************/
     497                 : /*                           ReadFeature()                              */
     498                 : /************************************************************************/
     499                 : 
     500               6 : OGRFeature* OGRGeoJSONReader::ReadFeature( json_object* poObj )
     501                 : {
     502                 :     CPLAssert( NULL != poObj );
     503                 :     CPLAssert( NULL != poLayer_ );
     504                 : 
     505               6 :     OGRFeature* poFeature = NULL;
     506               6 :     poFeature = new OGRFeature( poLayer_->GetLayerDefn() );
     507                 : 
     508                 : /* -------------------------------------------------------------------- */
     509                 : /*      Translate GeoJSON "properties" object to feature attributes.    */
     510                 : /* -------------------------------------------------------------------- */
     511                 :     CPLAssert( NULL != poFeature );
     512                 : 
     513               6 :     json_object* poObjProps = NULL;
     514               6 :     poObjProps = OGRGeoJSONFindMemberByName( poObj, "properties" );
     515              12 :     if( !bAttributesSkip_ && NULL != poObjProps )
     516                 :     {
     517               6 :         int nField = -1;
     518               6 :         OGRFieldDefn* poFieldDefn = NULL;
     519                 :         json_object_iter it;
     520               6 :         it.key = NULL;
     521               6 :         it.val = NULL;
     522               6 :         it.entry = NULL;
     523              18 :         json_object_object_foreachC( poObjProps, it )
     524                 :         {
     525              12 :             nField = poFeature->GetFieldIndex(it.key);
     526              12 :             poFieldDefn = poFeature->GetFieldDefnRef(nField);
     527                 :             CPLAssert( NULL != poFieldDefn );
     528                 : 
     529                 :       /* Unset FID. */
     530              12 :       poFeature->SetFID( -1 );
     531                 : 
     532              12 :             if( OFTInteger == poFieldDefn->GetType() )
     533                 :       {
     534               0 :                 poFeature->SetField( nField, json_object_get_int(it.val) );
     535                 :         
     536                 :         /* Check if FID available and set correct value. */
     537               0 :         if( EQUAL( it.key, poLayer_->GetFIDColumn() ) )
     538               0 :           poFeature->SetFID( json_object_get_int(it.val) );
     539                 :       }
     540              12 :             else if( OFTReal == poFieldDefn->GetType() )
     541                 :       {
     542               6 :                 poFeature->SetField( nField, json_object_get_double(it.val) );
     543                 :       }
     544                 :             else
     545                 :       {
     546               6 :                 poFeature->SetField( nField, json_object_get_string(it.val) );
     547                 :       }
     548                 :         }
     549                 :     }
     550                 : 
     551                 : /* -------------------------------------------------------------------- */
     552                 : /*      If FID not set, try to use feature-level ID if available        */
     553                 : /*      and of integral type. Otherwise, leave unset (-1) then index    */
     554                 : /*      in features sequence will be used as FID.                       */
     555                 : /* -------------------------------------------------------------------- */
     556               6 :     if( -1 == poFeature->GetFID() )
     557                 :     {
     558               6 :         json_object* poObjId = NULL;
     559               6 :         poObjId = OGRGeoJSONFindMemberByName( poObj, OGRGeoJSONLayer::DefaultFIDColumn );
     560               6 :         if( NULL != poObjId
     561               0 :             && EQUAL( OGRGeoJSONLayer::DefaultFIDColumn, poLayer_->GetFIDColumn() )
     562                 :             && OFTInteger == GeoJSONPropertyToFieldType( poObjId ) )
     563                 :         {
     564               0 :             poFeature->SetFID( json_object_get_int( poObjId ) );
     565               0 :             int nField = poFeature->GetFieldIndex( poLayer_->GetFIDColumn() );
     566               0 :             if( -1 != nField )
     567               0 :                 poFeature->SetField( nField, (int) poFeature->GetFID() );
     568                 :         }
     569                 :     }
     570                 : 
     571                 : /* -------------------------------------------------------------------- */
     572                 : /*      Translate geometry sub-object of GeoJSON Feature.               */
     573                 : /* -------------------------------------------------------------------- */
     574               6 :     json_object* poObjGeom = NULL;
     575                 : 
     576               6 :     json_object* poTmp = poObj;
     577                 : 
     578                 :     json_object_iter it;
     579               6 :     it.key = NULL;
     580               6 :     it.val = NULL;
     581               6 :     it.entry = NULL;    
     582              24 :     json_object_object_foreachC(poTmp, it)
     583                 :     {
     584              18 :         if( EQUAL( it.key, "geometry" ) ) {
     585               6 :             if (it.val != NULL)
     586               6 :                 poObjGeom = it.val;
     587                 :             // we're done.  They had 'geometry':null
     588                 :             else
     589               0 :                 return poFeature;
     590                 :         }
     591                 :     }
     592                 :     
     593               6 :     if( NULL != poObjGeom )
     594                 :     {
     595                 :         // NOTE: If geometry can not be parsed or read correctly
     596                 :         //       then NULL geometry is assigned to a feature and
     597                 :         //       geometry type for layer is classified as wkbUnknown.
     598               6 :         OGRGeometry* poGeometry = ReadGeometry( poObjGeom );
     599               6 :         if( NULL != poGeometry )
     600                 :         {
     601               6 :             poFeature->SetGeometryDirectly( poGeometry );
     602                 :         }
     603                 :     }
     604                 :     else
     605                 :     {
     606                 :         CPLError( CE_Failure, CPLE_AppDefined,
     607                 :                   "Invalid Feature object. "
     608               0 :                   "Missing \'geometry\' member." );
     609               0 :         return NULL;
     610                 :     }
     611                 : 
     612               6 :     return poFeature;
     613                 : }
     614                 : 
     615                 : /************************************************************************/
     616                 : /*                           ReadFeatureCollection()                    */
     617                 : /************************************************************************/
     618                 : 
     619                 : OGRGeoJSONLayer*
     620               6 : OGRGeoJSONReader::ReadFeatureCollection( json_object* poObj )
     621                 : {
     622                 :     CPLAssert( NULL != poLayer_ );
     623                 : 
     624               6 :     json_object* poObjFeatures = NULL;
     625               6 :     poObjFeatures = OGRGeoJSONFindMemberByName( poObj, "features" );
     626               6 :     if( NULL == poObjFeatures )
     627                 :     {
     628                 :         CPLError( CE_Failure, CPLE_AppDefined,
     629                 :                   "Invalid FeatureCollection object. "
     630               0 :                   "Missing \'features\' member." );
     631               0 :         return NULL;
     632                 :     }
     633                 : 
     634               6 :     if( json_type_array == json_object_get_type( poObjFeatures ) )
     635                 :     {
     636               6 :         bool bAdded = false;
     637               6 :         OGRFeature* poFeature = NULL;
     638               6 :         json_object* poObjFeature = NULL;
     639                 : 
     640               6 :         const int nFeatures = json_object_array_length( poObjFeatures );
     641              12 :         for( int i = 0; i < nFeatures; ++i )
     642                 :         {
     643               6 :             poObjFeature = json_object_array_get_idx( poObjFeatures, i );
     644               6 :             poFeature = OGRGeoJSONReader::ReadFeature( poObjFeature );
     645               6 :             bAdded = AddFeature( poFeature );
     646                 :             CPLAssert( bAdded );
     647                 :         }
     648                 :         CPLAssert( nFeatures == poLayer_->GetFeatureCount() );
     649                 :     }
     650                 : 
     651                 :     // We're returning class member to follow the same pattern of
     652                 :     // Read* functions call convention.
     653                 :     CPLAssert( NULL != poLayer_ );
     654               6 :     return poLayer_;
     655                 : }
     656                 : 
     657                 : /************************************************************************/
     658                 : /*                           OGRGeoJSONFindMemberByName                 */
     659                 : /************************************************************************/
     660                 : 
     661             137 : json_object* OGRGeoJSONFindMemberByName( json_object* poObj,
     662                 :                                          const char* pszName )
     663                 : {
     664             137 :     if( NULL == pszName || NULL == poObj)
     665               0 :         return NULL;
     666                 : 
     667             137 :     json_object* poTmp = poObj;
     668                 : 
     669                 :     json_object_iter it;
     670             137 :     it.key = NULL;
     671             137 :     it.val = NULL;
     672             137 :     it.entry = NULL;
     673             137 :     if( NULL != json_object_get_object(poTmp) )
     674                 :     {
     675                 :         CPLAssert( NULL != json_object_get_object(poTmp)->head );
     676                 : 
     677             268 :         for( it.entry = json_object_get_object(poTmp)->head;
     678                 :              ( it.entry ?
     679                 :                ( it.key = (char*)it.entry->k,
     680                 :                  it.val = (json_object*)it.entry->v, it.entry) : 0);
     681                 :              it.entry = it.entry->next)
     682                 :         {
     683             233 :             if( EQUAL( it.key, pszName ) )
     684             102 :                 return it.val;
     685                 :         }
     686                 :     }
     687                 : 
     688              35 :     return NULL;
     689                 : }
     690                 : 
     691                 : /************************************************************************/
     692                 : /*                           OGRGeoJSONGetType                          */
     693                 : /************************************************************************/
     694                 : 
     695              46 : GeoJSONObject::Type OGRGeoJSONGetType( json_object* poObj )
     696                 : {
     697              46 :     if( NULL == poObj )
     698               0 :         return GeoJSONObject::eUnknown;
     699                 : 
     700              46 :     json_object* poObjType = NULL;
     701              46 :     poObjType = OGRGeoJSONFindMemberByName( poObj, "type" );
     702              46 :     if( NULL == poObjType )
     703               0 :         return GeoJSONObject::eUnknown;
     704                 : 
     705              46 :     const char* name = json_object_get_string( poObjType );
     706              46 :     if( EQUAL( name, "Point" ) )
     707               6 :         return GeoJSONObject::ePoint;
     708              40 :     else if( EQUAL( name, "LineString" ) )
     709               6 :         return GeoJSONObject::eLineString;
     710              34 :     else if( EQUAL( name, "Polygon" ) )
     711               4 :         return GeoJSONObject::ePolygon;
     712              30 :     else if( EQUAL( name, "MultiPoint" ) )
     713               4 :         return GeoJSONObject::eMultiPoint;
     714              26 :     else if( EQUAL( name, "MultiLineString" ) )
     715               4 :         return GeoJSONObject::eMultiLineString;
     716              22 :     else if( EQUAL( name, "MultiPolygon" ) )
     717               4 :         return GeoJSONObject::eMultiPolygon;
     718              18 :     else if( EQUAL( name, "GeometryCollection" ) )
     719               6 :         return GeoJSONObject::eGeometryCollection;
     720              12 :     else if( EQUAL( name, "Feature" ) )
     721               0 :         return GeoJSONObject::eFeature;
     722              12 :     else if( EQUAL( name, "FeatureCollection" ) )
     723              12 :         return GeoJSONObject::eFeatureCollection;
     724                 :     else
     725               0 :         return GeoJSONObject::eUnknown;
     726                 : }
     727                 : 
     728                 : /************************************************************************/
     729                 : /*                           OGRGeoJSONReadGeometry                     */
     730                 : /************************************************************************/
     731                 : 
     732              18 : OGRGeometry* OGRGeoJSONReadGeometry( json_object* poObj )
     733                 : {
     734              18 :     OGRGeometry* poGeometry = NULL;
     735                 : 
     736              18 :     GeoJSONObject::Type objType = OGRGeoJSONGetType( poObj );
     737              18 :     if( GeoJSONObject::ePoint == objType )
     738               4 :         poGeometry = OGRGeoJSONReadPoint( poObj );
     739              14 :     else if( GeoJSONObject::eMultiPoint == objType )
     740               2 :         poGeometry = OGRGeoJSONReadMultiPoint( poObj );
     741              12 :     else if( GeoJSONObject::eLineString == objType )
     742               4 :         poGeometry = OGRGeoJSONReadLineString( poObj );
     743               8 :     else if( GeoJSONObject::eMultiLineString == objType )
     744               2 :         poGeometry = OGRGeoJSONReadMultiLineString( poObj );
     745               6 :     else if( GeoJSONObject::ePolygon == objType )
     746               2 :         poGeometry = OGRGeoJSONReadPolygon( poObj );
     747               4 :     else if( GeoJSONObject::eMultiPolygon == objType )
     748               2 :         poGeometry = OGRGeoJSONReadMultiPolygon( poObj );
     749               2 :     else if( GeoJSONObject::eGeometryCollection == objType )
     750               2 :         poGeometry = OGRGeoJSONReadGeometryCollection( poObj );
     751                 :     else
     752                 :     {
     753                 :         CPLDebug( "GeoJSON",
     754                 :                   "Unsupported geometry type detected. "
     755               0 :                   "Feature gets NULL geometry assigned." );
     756                 :     }
     757                 :     // If we have a crs object in the current object, let's try and 
     758                 :     // set it too.
     759                 :     
     760              18 :     json_object* poObjSrs = OGRGeoJSONFindMemberByName( poObj, "crs" );
     761              18 :     if (poObjSrs != NULL) {
     762               2 :         OGRSpatialReference* poSRS = OGRGeoJSONReadSpatialReference(poObj);
     763               2 :         if (poSRS != NULL) {
     764               2 :             poGeometry->assignSpatialReference(poSRS);
     765               2 :             poSRS->Release();
     766                 :         }
     767                 :     }
     768              18 :     return poGeometry;
     769                 : }
     770                 : 
     771                 : /************************************************************************/
     772                 : /*                           OGRGeoJSONReadRawPoint                     */
     773                 : /************************************************************************/
     774                 : 
     775              64 : bool OGRGeoJSONReadRawPoint( json_object* poObj, OGRPoint& point )
     776                 : {
     777                 :     CPLAssert( NULL != poObj );
     778                 : 
     779              64 :     if( json_type_array == json_object_get_type( poObj ) ) 
     780                 :     {
     781              64 :         const int nSize = json_object_array_length( poObj );
     782              64 :         int iType = 0;
     783                 : 
     784              64 :         if( nSize != GeoJSONObject::eMinCoordinateDimension
     785                 :             && nSize != GeoJSONObject::eMaxCoordinateDimension )
     786                 :         {
     787                 :             CPLDebug( "GeoJSON",
     788               0 :                       "Invalid coord dimension. Only 2D and 3D supported." );
     789               0 :             return false;
     790                 :         }
     791                 : 
     792              64 :         json_object* poObjCoord = NULL;
     793                 : 
     794                 :         // Read X coordinate
     795              64 :         poObjCoord = json_object_array_get_idx( poObj, 0 );
     796                 :         
     797              64 :         iType = json_object_get_type(poObjCoord);
     798              64 :         if ( (json_type_double != iType) && (json_type_int != iType) )
     799                 :         {
     800                 :             CPLError( CE_Failure, CPLE_AppDefined,
     801                 :                       "Invalid X coordinate. Type is not double or integer for \'%s\'.",
     802               0 :                       json_object_to_json_string(poObj) );
     803               0 :             return false;
     804                 :         }
     805                 :         
     806              64 :         if (iType == json_type_double)
     807              64 :             point.setX(json_object_get_double( poObjCoord ));
     808                 :         else
     809               0 :             point.setX(json_object_get_int( poObjCoord ));
     810                 :         
     811                 :         // Read Y coordiante
     812              64 :         poObjCoord = json_object_array_get_idx( poObj, 1 );
     813                 :         
     814              64 :         iType = json_object_get_type(poObjCoord);
     815              64 :         if ( (json_type_double != iType) && (json_type_int != iType) )
     816                 :         {
     817                 :             CPLError( CE_Failure, CPLE_AppDefined,
     818                 :                       "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
     819               0 :                       json_object_to_json_string(poObj) );
     820               0 :             return false;
     821                 :         }
     822                 : 
     823              64 :         if (iType == json_type_double)
     824              64 :             point.setY(json_object_get_double( poObjCoord ));
     825                 :         else
     826               0 :             point.setY(json_object_get_int( poObjCoord ));
     827                 :         
     828                 :         // Read Z coordinate
     829              64 :         if( nSize == GeoJSONObject::eMaxCoordinateDimension )
     830                 :         {
     831                 :             // Don't *expect* mixed-dimension geometries, although the 
     832                 :             // spec doesn't explicitly forbid this.
     833               0 :             poObjCoord = json_object_array_get_idx( poObj, 2 );
     834                 :             
     835               0 :             iType = json_object_get_type(poObjCoord);
     836               0 :             if ( (json_type_double != iType) && (json_type_int != iType) )
     837                 :             {
     838                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     839                 :                           "Invalid Z coordinate. Type is not double or integer for \'%s\'.",
     840               0 :                           json_object_to_json_string(poObj) );
     841               0 :                 return false;
     842                 :             }
     843                 : 
     844               0 :             if (iType == json_type_double)
     845               0 :                 point.setZ(json_object_get_double( poObjCoord ));
     846                 :             else
     847               0 :                 point.setZ(json_object_get_int( poObjCoord ));
     848                 :         }
     849                 :         else
     850                 :         {
     851              64 :             point.flattenTo2D();
     852                 :         }
     853              64 :         return true;
     854                 :     }
     855                 :     
     856               0 :     return false;
     857                 : }
     858                 : 
     859                 : /************************************************************************/
     860                 : /*                           OGRGeoJSONReadPoint                        */
     861                 : /************************************************************************/
     862                 : 
     863               4 : OGRPoint* OGRGeoJSONReadPoint( json_object* poObj )
     864                 : {
     865                 :     CPLAssert( NULL != poObj );
     866                 : 
     867               4 :     OGRPoint* poPoint = new OGRPoint();
     868                 : 
     869               4 :     json_object* poObjCoords = NULL;
     870               4 :     poObjCoords = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
     871               4 :     if( NULL == poObjCoords )
     872                 :     {
     873                 :         CPLError( CE_Failure, CPLE_AppDefined,
     874               0 :                   "Invalid Point object. Missing \'coordinates\' member." );
     875               0 :         return NULL;
     876                 :     }
     877                 : 
     878               4 :     if( !OGRGeoJSONReadRawPoint( poObjCoords, *poPoint ) )
     879                 :     {
     880               0 :         CPLDebug( "GeoJSON", "Point: raw point parsing failure." );
     881               0 :         delete poPoint;
     882               0 :         return NULL;
     883                 :     }
     884                 : 
     885               4 :     return poPoint;
     886                 : }
     887                 : 
     888                 : /************************************************************************/
     889                 : /*                           OGRGeoJSONReadMultiPoint                   */
     890                 : /************************************************************************/
     891                 : 
     892               2 : OGRMultiPoint* OGRGeoJSONReadMultiPoint( json_object* poObj )
     893                 : {
     894                 :     CPLAssert( NULL != poObj );
     895                 : 
     896               2 :     OGRMultiPoint* poMultiPoint = NULL;
     897                 : 
     898               2 :     json_object* poObjPoints = NULL;
     899               2 :     poObjPoints = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
     900               2 :     if( NULL == poObjPoints )
     901                 :     {
     902                 :         CPLError( CE_Failure, CPLE_AppDefined,
     903                 :                   "Invalid MultiPoint object. "
     904               0 :                   "Missing \'coordinates\' member." );
     905               0 :         return NULL;
     906                 :     }
     907                 : 
     908               2 :     if( json_type_array == json_object_get_type( poObjPoints ) )
     909                 :     {
     910               2 :         const int nPoints = json_object_array_length( poObjPoints );
     911                 : 
     912               2 :         poMultiPoint = new OGRMultiPoint();
     913                 : 
     914               2 :         for( int i = 0; i < nPoints; ++i)
     915                 :         {
     916               4 :             json_object* poObjCoords = NULL;
     917               4 :             poObjCoords = json_object_array_get_idx( poObjPoints, i );
     918                 :             
     919               4 :             OGRPoint pt;
     920               4 :             if( !OGRGeoJSONReadRawPoint( poObjCoords, pt ) )
     921                 :             {
     922               0 :                 delete poMultiPoint;
     923                 :                 CPLDebug( "GeoJSON",
     924               0 :                           "LineString: raw point parsing failure." );
     925               0 :                 return NULL;
     926                 :             }
     927               4 :             poMultiPoint->addGeometry( &pt );
     928                 :         }
     929                 :     }
     930                 : 
     931               2 :     return poMultiPoint;
     932                 : }
     933                 : 
     934                 : /************************************************************************/
     935                 : /*                           OGRGeoJSONReadLineString                   */
     936                 : /************************************************************************/
     937                 : 
     938               8 : OGRLineString* OGRGeoJSONReadLineString( json_object* poObj , bool bRaw)
     939                 : {
     940                 :     CPLAssert( NULL != poObj );
     941                 : 
     942               8 :     OGRLineString* poLine = NULL;
     943               8 :     json_object* poObjPoints = NULL;
     944                 :     
     945               8 :     if( !bRaw )
     946                 :     {
     947               4 :         poObjPoints = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
     948               4 :         if( NULL == poObjPoints )
     949                 :         {
     950                 :             CPLError( CE_Failure, CPLE_AppDefined,
     951                 :                     "Invalid LineString object. "
     952               0 :                     "Missing \'coordinates\' member." );
     953               0 :                 return NULL;
     954                 :         }
     955                 :     }
     956                 :     else
     957                 :     {
     958               4 :         poObjPoints = poObj;
     959                 :     }
     960                 : 
     961               8 :     if( json_type_array == json_object_get_type( poObjPoints ) )
     962                 :     {
     963               8 :         const int nPoints = json_object_array_length( poObjPoints );
     964                 : 
     965               8 :         poLine = new OGRLineString();
     966               8 :         poLine->setNumPoints( nPoints );
     967                 : 
     968               8 :         for( int i = 0; i < nPoints; ++i)
     969                 :         {
     970              16 :             json_object* poObjCoords = NULL;
     971              16 :             poObjCoords = json_object_array_get_idx( poObjPoints, i );
     972                 :             
     973              16 :             OGRPoint pt;
     974              16 :             if( !OGRGeoJSONReadRawPoint( poObjCoords, pt ) )
     975                 :             {
     976               0 :                 delete poLine;
     977                 :                 CPLDebug( "GeoJSON",
     978               0 :                           "LineString: raw point parsing failure." );
     979               0 :                 return NULL;
     980                 :             }
     981              16 :             if (pt.getCoordinateDimension() == 2) {
     982              16 :                 poLine->setPoint( i, pt.getX(), pt.getY());
     983                 :             } else {
     984               0 :                 poLine->setPoint( i, pt.getX(), pt.getY(), pt.getZ() );
     985                 :             }
     986                 :             
     987                 :         }
     988                 :     }
     989                 : 
     990               8 :     return poLine;
     991                 : }
     992                 : 
     993                 : /************************************************************************/
     994                 : /*                           OGRGeoJSONReadMultiLineString              */
     995                 : /************************************************************************/
     996                 : 
     997               2 : OGRMultiLineString* OGRGeoJSONReadMultiLineString( json_object* poObj )
     998                 : {
     999                 :     CPLAssert( NULL != poObj );
    1000                 : 
    1001               2 :     OGRMultiLineString* poMultiLine = NULL;
    1002                 : 
    1003               2 :     json_object* poObjLines = NULL;
    1004               2 :     poObjLines = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
    1005               2 :     if( NULL == poObjLines )
    1006                 :     {
    1007                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1008                 :                   "Invalid MultiLineString object. "
    1009               0 :                   "Missing \'coordinates\' member." );
    1010               0 :         return NULL;
    1011                 :     }
    1012                 : 
    1013               2 :     if( json_type_array == json_object_get_type( poObjLines ) )
    1014                 :     {
    1015               2 :         const int nLines = json_object_array_length( poObjLines );
    1016                 : 
    1017               2 :         poMultiLine = new OGRMultiLineString();
    1018                 : 
    1019               6 :         for( int i = 0; i < nLines; ++i)
    1020                 :         {
    1021               4 :             json_object* poObjLine = NULL;
    1022               4 :             poObjLine = json_object_array_get_idx( poObjLines, i );
    1023                 : 
    1024               4 :             OGRLineString* poLine = OGRGeoJSONReadLineString( poObjLine , true );
    1025               4 :             if( NULL != poLine )
    1026                 :             {
    1027               4 :                 poMultiLine->addGeometryDirectly( poLine );
    1028                 :             }
    1029                 :         }
    1030                 :     }
    1031                 : 
    1032               2 :     return poMultiLine;
    1033                 : }
    1034                 : 
    1035                 : /************************************************************************/
    1036                 : /*                           OGRGeoJSONReadLinearRing                   */
    1037                 : /************************************************************************/
    1038                 : 
    1039               8 : OGRLinearRing* OGRGeoJSONReadLinearRing( json_object* poObj )
    1040                 : {
    1041                 :     CPLAssert( NULL != poObj );
    1042                 : 
    1043               8 :     OGRLinearRing* poRing = NULL;
    1044                 : 
    1045               8 :     if( json_type_array == json_object_get_type( poObj ) )
    1046                 :     {
    1047               8 :         const int nPoints = json_object_array_length( poObj );
    1048                 : 
    1049               8 :         poRing= new OGRLinearRing();
    1050               8 :         poRing->setNumPoints( nPoints );
    1051                 : 
    1052               8 :         for( int i = 0; i < nPoints; ++i)
    1053                 :         {
    1054              40 :             json_object* poObjCoords = NULL;
    1055              40 :             poObjCoords = json_object_array_get_idx( poObj, i );
    1056                 :             
    1057              40 :             OGRPoint pt;
    1058              40 :             if( !OGRGeoJSONReadRawPoint( poObjCoords, pt ) )
    1059                 :             {
    1060               0 :                 delete poRing;
    1061                 :                 CPLDebug( "GeoJSON",
    1062               0 :                           "LinearRing: raw point parsing failure." );
    1063               0 :                 return NULL;
    1064                 :             }
    1065                 :             
    1066              40 :             if( 2 == pt.getCoordinateDimension() )
    1067              40 :                 poRing->setPoint( i, pt.getX(), pt.getY());
    1068                 :             else
    1069               0 :                 poRing->setPoint( i, pt.getX(), pt.getY(), pt.getZ() );
    1070                 :         }
    1071                 :     }
    1072                 : 
    1073               8 :     return poRing;
    1074                 : }
    1075                 : 
    1076                 : /************************************************************************/
    1077                 : /*                           OGRGeoJSONReadPolygon                      */
    1078                 : /************************************************************************/
    1079                 : 
    1080               7 : OGRPolygon* OGRGeoJSONReadPolygon( json_object* poObj , bool bRaw )
    1081                 : {
    1082                 :     CPLAssert( NULL != poObj );
    1083                 : 
    1084               7 :     OGRPolygon* poPolygon = NULL;
    1085                 : 
    1086               7 :     json_object* poObjRings = NULL;
    1087                 :     
    1088               7 :     if( !bRaw )
    1089                 :     {
    1090               2 :         poObjRings = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
    1091               2 :         if( NULL == poObjRings )
    1092                 :         {
    1093                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1094                 :                       "Invalid Polygon object. "
    1095               0 :                       "Missing \'geometries\' member." );
    1096               0 :             return NULL;
    1097                 :         }
    1098                 :     }
    1099                 :     else
    1100                 :     {
    1101               5 :         poObjRings = poObj;
    1102                 :     }
    1103                 :     
    1104               7 :     if( json_type_array == json_object_get_type( poObjRings ) )
    1105                 :     {
    1106               7 :         const int nRings = json_object_array_length( poObjRings );
    1107               7 :         if( nRings > 0 )
    1108                 :         {
    1109               7 :             json_object* poObjPoints = NULL;
    1110               7 :             poObjPoints = json_object_array_get_idx( poObjRings, 0 );
    1111                 : 
    1112               7 :             OGRLinearRing* poRing = OGRGeoJSONReadLinearRing( poObjPoints );
    1113               7 :             if( NULL != poRing )
    1114                 :             {
    1115               7 :                 poPolygon = new OGRPolygon();
    1116               7 :                 poPolygon->addRingDirectly( poRing );
    1117                 :             }
    1118                 : 
    1119               8 :             for( int i = 1; i < nRings && NULL != poPolygon; ++i )
    1120                 :             {
    1121               1 :                 poObjPoints = json_object_array_get_idx( poObjRings, i );
    1122               1 :                 OGRLinearRing* poRing = OGRGeoJSONReadLinearRing( poObjPoints );
    1123               1 :                 if( NULL != poRing )
    1124                 :                 {
    1125               1 :                     poPolygon->addRingDirectly( poRing );
    1126                 :                 }
    1127                 :             }
    1128                 :         }
    1129                 :     }
    1130                 : 
    1131               7 :     return poPolygon;
    1132                 : }
    1133                 : 
    1134                 : /************************************************************************/
    1135                 : /*                           OGRGeoJSONReadMultiPolygon                 */
    1136                 : /************************************************************************/
    1137                 : 
    1138               2 : OGRMultiPolygon* OGRGeoJSONReadMultiPolygon( json_object* poObj )
    1139                 : {
    1140                 :     CPLAssert( NULL != poObj );
    1141                 : 
    1142               2 :     OGRMultiPolygon* poMultiPoly = NULL;
    1143                 : 
    1144               2 :     json_object* poObjPolys = NULL;
    1145               2 :     poObjPolys = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
    1146               2 :     if( NULL == poObjPolys )
    1147                 :     {
    1148                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1149                 :                   "Invalid MultiPolygon object. "
    1150               0 :                   "Missing \'coordinates\' member." );
    1151               0 :         return NULL;
    1152                 :     }
    1153                 : 
    1154               2 :     if( json_type_array == json_object_get_type( poObjPolys ) )
    1155                 :     {
    1156               2 :         const int nPolys = json_object_array_length( poObjPolys );
    1157                 : 
    1158               2 :         poMultiPoly = new OGRMultiPolygon();
    1159                 : 
    1160               7 :         for( int i = 0; i < nPolys; ++i)
    1161                 :         {
    1162                 : 
    1163               5 :             json_object* poObjPoly = NULL;
    1164               5 :             poObjPoly = json_object_array_get_idx( poObjPolys, i );
    1165                 : 
    1166               5 :             OGRPolygon* poPoly = OGRGeoJSONReadPolygon( poObjPoly , true );
    1167               5 :             if( NULL != poPoly )
    1168                 :             {
    1169               5 :                 poMultiPoly->addGeometryDirectly( poPoly );
    1170                 :             }            
    1171                 :             
    1172                 :         }
    1173                 :     }
    1174                 : 
    1175               2 :     return poMultiPoly;
    1176                 : }
    1177                 : /************************************************************************/
    1178                 : /*                           OGRGeoJSONReadGeometryCollection           */
    1179                 : /************************************************************************/
    1180                 : 
    1181               2 : OGRGeometryCollection* OGRGeoJSONReadGeometryCollection( json_object* poObj )
    1182                 : {
    1183                 :     CPLAssert( NULL != poObj );
    1184                 : 
    1185               2 :     OGRGeometry* poGeometry = NULL;
    1186               2 :     OGRGeometryCollection* poCollection = NULL;
    1187                 : 
    1188               2 :     json_object* poObjGeoms = NULL;
    1189               2 :     poObjGeoms = OGRGeoJSONFindMemberByName( poObj, "geometries" );
    1190               2 :     if( NULL == poObjGeoms )
    1191                 :     {
    1192                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1193                 :                   "Invalid GeometryCollection object. "
    1194               0 :                   "Missing \'geometries\' member." );
    1195               0 :         return NULL;
    1196                 :     }
    1197                 : 
    1198               2 :     if( json_type_array == json_object_get_type( poObjGeoms ) )
    1199                 :     {
    1200               2 :         const int nGeoms = json_object_array_length( poObjGeoms );
    1201               2 :         if( nGeoms > 0 )
    1202                 :         {
    1203               2 :             poCollection = new OGRGeometryCollection();
    1204                 :         }
    1205                 : 
    1206               2 :         json_object* poObjGeom = NULL;
    1207               6 :         for( int i = 0; i < nGeoms; ++i )
    1208                 :         {
    1209               4 :             poObjGeom = json_object_array_get_idx( poObjGeoms, i );
    1210                 : 
    1211               4 :             poGeometry = OGRGeoJSONReadGeometry( poObjGeom );
    1212               4 :             if( NULL != poGeometry )
    1213                 :             {
    1214               4 :                 poCollection->addGeometryDirectly( poGeometry );
    1215                 :             }
    1216                 :         }
    1217                 :     }
    1218                 : 
    1219               2 :     return poCollection;
    1220                 : }
    1221                 : 
    1222                 : /************************************************************************/
    1223                 : /*                           OGR_G_ExportToJson                         */
    1224                 : /************************************************************************/
    1225                 : 
    1226               0 : OGRGeometryH OGR_G_CreateGeometryFromJson( const char* pszJson )
    1227                 : {
    1228               0 :     VALIDATE_POINTER1( pszJson, "OGR_G_CreateGeometryFromJson", NULL );
    1229                 : 
    1230               0 :     if( NULL != pszJson )
    1231                 :     {
    1232               0 :         json_tokener* jstok = NULL;
    1233               0 :         json_object* poObj = NULL;
    1234                 : 
    1235               0 :         jstok = json_tokener_new();
    1236               0 :         poObj = json_tokener_parse_ex(jstok, pszJson, -1);
    1237               0 :         if( jstok->err != json_tokener_success)
    1238                 :         {
    1239                 :             CPLError( CE_Failure, CPLE_AppDefined,
    1240                 :                       "GeoJSON parsing error: %s (at offset %d)",
    1241               0 :                       json_tokener_errors[jstok->err], jstok->char_offset);
    1242               0 :             json_tokener_free(jstok);
    1243               0 :             return NULL;
    1244                 :         }
    1245               0 :         json_tokener_free(jstok);
    1246                 : 
    1247               0 :         OGRGeometry* poGeometry = NULL;
    1248               0 :         poGeometry = OGRGeoJSONReadGeometry( poObj );
    1249                 :         
    1250                 :         /* Release JSON tree. */
    1251               0 :         json_object_put( poObj );
    1252                 : 
    1253               0 :         return (OGRGeometryH)poGeometry;
    1254                 :     }
    1255                 : 
    1256                 :     /* Translation failed */
    1257               0 :     return NULL;
    1258                 : }
    1259                 : 

Generated by: LCOV version 1.7