1 : /******************************************************************************
2 : * $Id: ogresrijsonreader.cpp 23664 2011-12-30 12:46:57Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implementation of OGRESRIJSONReader class (OGR ESRIJSON Driver)
6 : * to read ESRI Feature Service REST data
7 : * Author: Even Rouault, even dot rouault at mines dash paris dot org
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2010, Even Rouault
11 : * Copyright (c) 2007, Mateusz Loskot
12 : *
13 : * Permission is hereby granted, free of charge, to any person obtaining a
14 : * copy of this software and associated documentation files (the "Software"),
15 : * to deal in the Software without restriction, including without limitation
16 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 : * and/or sell copies of the Software, and to permit persons to whom the
18 : * Software is furnished to do so, subject to the following conditions:
19 : *
20 : * The above copyright notice and this permission notice shall be included
21 : * in all copies or substantial portions of the Software.
22 : *
23 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 : * DEALINGS IN THE SOFTWARE.
30 : ****************************************************************************/
31 :
32 : #include "ogrgeojsonreader.h"
33 : #include "ogrgeojsonutils.h"
34 : #include "ogr_geojson.h"
35 : #include <jsonc/json.h> // JSON-C
36 : #include <jsonc/json_object_private.h> // json_object_iter, complete type required
37 : #include <ogr_api.h>
38 :
39 : /************************************************************************/
40 : /* OGRESRIJSONReader() */
41 : /************************************************************************/
42 :
43 16 : OGRESRIJSONReader::OGRESRIJSONReader()
44 16 : : poGJObject_( NULL ), poLayer_( NULL )
45 : {
46 : // Take a deep breath and get to work.
47 16 : }
48 :
49 : /************************************************************************/
50 : /* ~OGRESRIJSONReader() */
51 : /************************************************************************/
52 :
53 16 : OGRESRIJSONReader::~OGRESRIJSONReader()
54 : {
55 16 : if( NULL != poGJObject_ )
56 : {
57 16 : json_object_put(poGJObject_);
58 : }
59 :
60 16 : poGJObject_ = NULL;
61 16 : poLayer_ = NULL;
62 16 : }
63 :
64 : /************************************************************************/
65 : /* Parse() */
66 : /************************************************************************/
67 :
68 16 : OGRErr OGRESRIJSONReader::Parse( const char* pszText )
69 : {
70 16 : if( NULL != pszText )
71 : {
72 16 : json_tokener* jstok = NULL;
73 16 : json_object* jsobj = NULL;
74 :
75 16 : jstok = json_tokener_new();
76 16 : jsobj = json_tokener_parse_ex(jstok, pszText, -1);
77 16 : if( jstok->err != json_tokener_success)
78 : {
79 : CPLError( CE_Failure, CPLE_AppDefined,
80 : "ESRIJSON parsing error: %s (at offset %d)",
81 0 : json_tokener_errors[jstok->err], jstok->char_offset);
82 :
83 0 : json_tokener_free(jstok);
84 0 : return OGRERR_CORRUPT_DATA;
85 : }
86 16 : json_tokener_free(jstok);
87 :
88 : /* JSON tree is shared for while lifetime of the reader object
89 : * and will be released in the destructor.
90 : */
91 16 : poGJObject_ = jsobj;
92 : }
93 :
94 16 : return OGRERR_NONE;
95 : }
96 :
97 : /************************************************************************/
98 : /* ReadLayer() */
99 : /************************************************************************/
100 :
101 16 : OGRGeoJSONLayer* OGRESRIJSONReader::ReadLayer( const char* pszName,
102 : OGRGeoJSONDataSource* poDS )
103 : {
104 16 : CPLAssert( NULL == poLayer_ );
105 :
106 16 : if( NULL == poGJObject_ )
107 : {
108 : CPLDebug( "ESRIJSON",
109 0 : "Missing parset ESRIJSON data. Forgot to call Parse()?" );
110 0 : return NULL;
111 : }
112 :
113 : poLayer_ = new OGRGeoJSONLayer( pszName, NULL,
114 : OGRESRIJSONGetGeometryType(poGJObject_),
115 16 : poDS );
116 :
117 16 : if( !GenerateLayerDefn() )
118 : {
119 : CPLError( CE_Failure, CPLE_AppDefined,
120 0 : "Layer schema generation failed." );
121 :
122 0 : delete poLayer_;
123 0 : return NULL;
124 : }
125 :
126 16 : OGRGeoJSONLayer* poThisLayer = NULL;
127 16 : poThisLayer = ReadFeatureCollection( poGJObject_ );
128 16 : if (poThisLayer == NULL)
129 : {
130 0 : delete poLayer_;
131 0 : return NULL;
132 : }
133 :
134 16 : OGRSpatialReference* poSRS = NULL;
135 16 : poSRS = OGRESRIJSONReadSpatialReference( poGJObject_ );
136 16 : if (poSRS != NULL )
137 : {
138 8 : poLayer_->SetSpatialRef( poSRS );
139 8 : delete poSRS;
140 : }
141 :
142 16 : return poLayer_;
143 : }
144 :
145 : /************************************************************************/
146 : /* GenerateFeatureDefn() */
147 : /************************************************************************/
148 :
149 16 : bool OGRESRIJSONReader::GenerateLayerDefn()
150 : {
151 16 : CPLAssert( NULL != poGJObject_ );
152 16 : CPLAssert( NULL != poLayer_->GetLayerDefn() );
153 16 : CPLAssert( 0 == poLayer_->GetLayerDefn()->GetFieldCount() );
154 :
155 16 : bool bSuccess = true;
156 :
157 : /* -------------------------------------------------------------------- */
158 : /* Scan all features and generate layer definition. */
159 : /* -------------------------------------------------------------------- */
160 16 : json_object* poObjFeatures = NULL;
161 :
162 16 : poObjFeatures = OGRGeoJSONFindMemberByName( poGJObject_, "fields" );
163 16 : if( NULL != poObjFeatures && json_type_array == json_object_get_type( poObjFeatures ) )
164 : {
165 16 : json_object* poObjFeature = NULL;
166 16 : const int nFeatures = json_object_array_length( poObjFeatures );
167 48 : for( int i = 0; i < nFeatures; ++i )
168 : {
169 32 : poObjFeature = json_object_array_get_idx( poObjFeatures, i );
170 32 : if( !GenerateFeatureDefn( poObjFeature ) )
171 : {
172 0 : CPLDebug( "GeoJSON", "Create feature schema failure." );
173 0 : bSuccess = false;
174 : }
175 : }
176 : }
177 : else
178 : {
179 0 : poObjFeatures = OGRGeoJSONFindMemberByName( poGJObject_, "fieldAliases" );
180 0 : if( NULL != poObjFeatures &&
181 : json_object_get_type(poObjFeatures) == json_type_object )
182 : {
183 0 : OGRFeatureDefn* poDefn = poLayer_->GetLayerDefn();
184 : json_object_iter it;
185 0 : it.key = NULL;
186 0 : it.val = NULL;
187 0 : it.entry = NULL;
188 0 : json_object_object_foreachC( poObjFeatures, it )
189 : {
190 0 : OGRFieldDefn fldDefn( it.key, OFTString );
191 0 : poDefn->AddFieldDefn( &fldDefn );
192 : }
193 : }
194 : else
195 : {
196 : CPLError( CE_Failure, CPLE_AppDefined,
197 : "Invalid FeatureCollection object. "
198 0 : "Missing \'fields\' member." );
199 0 : bSuccess = false;
200 : }
201 : }
202 :
203 16 : return bSuccess;
204 : }
205 :
206 : /************************************************************************/
207 : /* GenerateFeatureDefn() */
208 : /************************************************************************/
209 :
210 32 : bool OGRESRIJSONReader::GenerateFeatureDefn( json_object* poObj )
211 : {
212 32 : OGRFeatureDefn* poDefn = poLayer_->GetLayerDefn();
213 32 : CPLAssert( NULL != poDefn );
214 :
215 32 : bool bSuccess = false;
216 :
217 : /* -------------------------------------------------------------------- */
218 : /* Read collection of properties. */
219 : /* -------------------------------------------------------------------- */
220 32 : json_object* poObjName = OGRGeoJSONFindMemberByName( poObj, "name" );
221 32 : json_object* poObjType = OGRGeoJSONFindMemberByName( poObj, "type" );
222 32 : if( NULL != poObjName && NULL != poObjType )
223 : {
224 32 : OGRFieldType eFieldType = OFTString;
225 32 : if (EQUAL(json_object_get_string(poObjType), "esriFieldTypeOID"))
226 : {
227 8 : eFieldType = OFTInteger;
228 8 : poLayer_->SetFIDColumn(json_object_get_string(poObjName));
229 : }
230 24 : else if (EQUAL(json_object_get_string(poObjType), "esriFieldTypeDouble"))
231 : {
232 8 : eFieldType = OFTReal;
233 : }
234 16 : else if (EQUAL(json_object_get_string(poObjType), "esriFieldTypeSmallInteger") ||
235 : EQUAL(json_object_get_string(poObjType), "esriFieldTypeInteger") )
236 : {
237 8 : eFieldType = OFTInteger;
238 : }
239 : OGRFieldDefn fldDefn( json_object_get_string(poObjName),
240 32 : eFieldType);
241 :
242 32 : json_object* poObjLength = OGRGeoJSONFindMemberByName( poObj, "length" );
243 32 : if (poObjLength != NULL && json_object_get_type(poObjLength) == json_type_int )
244 : {
245 16 : fldDefn.SetWidth(json_object_get_int(poObjLength));
246 : }
247 :
248 32 : poDefn->AddFieldDefn( &fldDefn );
249 :
250 32 : bSuccess = true; // SUCCESS
251 : }
252 32 : return bSuccess;
253 : }
254 :
255 : /************************************************************************/
256 : /* AddFeature */
257 : /************************************************************************/
258 :
259 16 : bool OGRESRIJSONReader::AddFeature( OGRFeature* poFeature )
260 : {
261 16 : bool bAdded = false;
262 :
263 16 : if( NULL != poFeature )
264 : {
265 16 : poLayer_->AddFeature( poFeature );
266 16 : bAdded = true;
267 16 : delete poFeature;
268 : }
269 :
270 16 : return bAdded;
271 : }
272 :
273 : /************************************************************************/
274 : /* ReadGeometry() */
275 : /************************************************************************/
276 :
277 16 : OGRGeometry* OGRESRIJSONReader::ReadGeometry( json_object* poObj )
278 : {
279 16 : OGRGeometry* poGeometry = NULL;
280 :
281 16 : OGRwkbGeometryType eType = poLayer_->GetGeomType();
282 16 : if (eType == wkbPoint)
283 4 : poGeometry = OGRESRIJSONReadPoint( poObj );
284 12 : else if (eType == wkbLineString)
285 4 : poGeometry = OGRESRIJSONReadLineString( poObj );
286 8 : else if (eType == wkbPolygon)
287 4 : poGeometry = OGRESRIJSONReadPolygon( poObj );
288 4 : else if (eType == wkbMultiPoint)
289 4 : poGeometry = OGRESRIJSONReadMultiPoint( poObj );
290 :
291 16 : return poGeometry;
292 : }
293 :
294 : /************************************************************************/
295 : /* ReadFeature() */
296 : /************************************************************************/
297 :
298 16 : OGRFeature* OGRESRIJSONReader::ReadFeature( json_object* poObj )
299 : {
300 16 : CPLAssert( NULL != poObj );
301 16 : CPLAssert( NULL != poLayer_ );
302 :
303 16 : OGRFeature* poFeature = NULL;
304 16 : poFeature = new OGRFeature( poLayer_->GetLayerDefn() );
305 :
306 : /* -------------------------------------------------------------------- */
307 : /* Translate ESRIJSON "attributes" object to feature attributes. */
308 : /* -------------------------------------------------------------------- */
309 16 : CPLAssert( NULL != poFeature );
310 :
311 16 : json_object* poObjProps = NULL;
312 16 : poObjProps = OGRGeoJSONFindMemberByName( poObj, "attributes" );
313 16 : if( NULL != poObjProps &&
314 : json_object_get_type(poObjProps) == json_type_object )
315 : {
316 16 : int nField = -1;
317 16 : OGRFieldDefn* poFieldDefn = NULL;
318 : json_object_iter it;
319 16 : it.key = NULL;
320 16 : it.val = NULL;
321 16 : it.entry = NULL;
322 48 : json_object_object_foreachC( poObjProps, it )
323 : {
324 32 : nField = poFeature->GetFieldIndex(it.key);
325 32 : poFieldDefn = poFeature->GetFieldDefnRef(nField);
326 32 : if (poFieldDefn && it.val != NULL )
327 : {
328 32 : if ( EQUAL( it.key, poLayer_->GetFIDColumn() ) )
329 8 : poFeature->SetFID( json_object_get_int( it.val ) );
330 32 : poFeature->SetField( nField, json_object_get_string(it.val) );
331 : }
332 : }
333 : }
334 :
335 16 : OGRwkbGeometryType eType = poLayer_->GetGeomType();
336 16 : if (eType == wkbNone)
337 0 : return poFeature;
338 :
339 : /* -------------------------------------------------------------------- */
340 : /* Translate geometry sub-object of ESRIJSON Feature. */
341 : /* -------------------------------------------------------------------- */
342 16 : json_object* poObjGeom = NULL;
343 :
344 16 : json_object* poTmp = poObj;
345 :
346 : json_object_iter it;
347 16 : it.key = NULL;
348 16 : it.val = NULL;
349 16 : it.entry = NULL;
350 48 : json_object_object_foreachC(poTmp, it)
351 : {
352 32 : if( EQUAL( it.key, "geometry" ) ) {
353 16 : if (it.val != NULL)
354 16 : poObjGeom = it.val;
355 : // we're done. They had 'geometry':null
356 : else
357 0 : return poFeature;
358 : }
359 : }
360 :
361 16 : if( NULL != poObjGeom )
362 : {
363 16 : OGRGeometry* poGeometry = ReadGeometry( poObjGeom );
364 16 : if( NULL != poGeometry )
365 : {
366 16 : poFeature->SetGeometryDirectly( poGeometry );
367 : }
368 : }
369 : else
370 : {
371 : CPLError( CE_Failure, CPLE_AppDefined,
372 : "Invalid Feature object. "
373 0 : "Missing \'geometry\' member." );
374 0 : delete poFeature;
375 0 : return NULL;
376 : }
377 :
378 16 : return poFeature;
379 : }
380 :
381 : /************************************************************************/
382 : /* ReadFeatureCollection() */
383 : /************************************************************************/
384 :
385 : OGRGeoJSONLayer*
386 16 : OGRESRIJSONReader::ReadFeatureCollection( json_object* poObj )
387 : {
388 16 : CPLAssert( NULL != poLayer_ );
389 :
390 16 : json_object* poObjFeatures = NULL;
391 16 : poObjFeatures = OGRGeoJSONFindMemberByName( poObj, "features" );
392 16 : if( NULL == poObjFeatures )
393 : {
394 : CPLError( CE_Failure, CPLE_AppDefined,
395 : "Invalid FeatureCollection object. "
396 0 : "Missing \'features\' member." );
397 0 : return NULL;
398 : }
399 :
400 16 : if( json_type_array == json_object_get_type( poObjFeatures ) )
401 : {
402 16 : bool bAdded = false;
403 16 : OGRFeature* poFeature = NULL;
404 16 : json_object* poObjFeature = NULL;
405 :
406 16 : const int nFeatures = json_object_array_length( poObjFeatures );
407 32 : for( int i = 0; i < nFeatures; ++i )
408 : {
409 16 : poObjFeature = json_object_array_get_idx( poObjFeatures, i );
410 16 : if (poObjFeature != NULL &&
411 : json_object_get_type(poObjFeature) == json_type_object)
412 : {
413 16 : poFeature = OGRESRIJSONReader::ReadFeature( poObjFeature );
414 16 : bAdded = AddFeature( poFeature );
415 : }
416 : //CPLAssert( bAdded );
417 : }
418 : //CPLAssert( nFeatures == poLayer_->GetFeatureCount() );
419 : }
420 :
421 : // We're returning class member to follow the same pattern of
422 : // Read* functions call convention.
423 16 : CPLAssert( NULL != poLayer_ );
424 16 : return poLayer_;
425 : }
426 :
427 : /************************************************************************/
428 : /* OGRESRIJSONGetType() */
429 : /************************************************************************/
430 :
431 16 : OGRwkbGeometryType OGRESRIJSONGetGeometryType( json_object* poObj )
432 : {
433 16 : if( NULL == poObj )
434 0 : return wkbUnknown;
435 :
436 16 : json_object* poObjType = NULL;
437 16 : poObjType = OGRGeoJSONFindMemberByName( poObj, "geometryType" );
438 16 : if( NULL == poObjType )
439 : {
440 0 : return wkbNone;
441 : }
442 :
443 16 : const char* name = json_object_get_string( poObjType );
444 16 : if( EQUAL( name, "esriGeometryPoint" ) )
445 4 : return wkbPoint;
446 12 : else if( EQUAL( name, "esriGeometryPolyline" ) )
447 4 : return wkbLineString;
448 8 : else if( EQUAL( name, "esriGeometryPolygon" ) )
449 4 : return wkbPolygon;
450 4 : else if( EQUAL( name, "esriGeometryMultiPoint" ) )
451 4 : return wkbMultiPoint;
452 : else
453 0 : return wkbUnknown;
454 : }
455 :
456 : /************************************************************************/
457 : /* OGRESRIJSONReadPoint() */
458 : /************************************************************************/
459 :
460 4 : OGRPoint* OGRESRIJSONReadPoint( json_object* poObj)
461 : {
462 4 : CPLAssert( NULL != poObj );
463 :
464 4 : json_object* poObjX = OGRGeoJSONFindMemberByName( poObj, "x" );
465 4 : if( NULL == poObjX )
466 : {
467 : CPLError( CE_Failure, CPLE_AppDefined,
468 : "Invalid Point object. "
469 0 : "Missing \'x\' member." );
470 0 : return NULL;
471 : }
472 :
473 4 : int iTypeX = json_object_get_type(poObjX);
474 4 : if ( (json_type_double != iTypeX) && (json_type_int != iTypeX) )
475 : {
476 : CPLError( CE_Failure, CPLE_AppDefined,
477 : "Invalid X coordinate. Type is not double or integer for \'%s\'.",
478 0 : json_object_to_json_string(poObjX) );
479 0 : return NULL;
480 : }
481 :
482 4 : json_object* poObjY = OGRGeoJSONFindMemberByName( poObj, "y" );
483 4 : if( NULL == poObjY )
484 : {
485 : CPLError( CE_Failure, CPLE_AppDefined,
486 : "Invalid Point object. "
487 0 : "Missing \'y\' member." );
488 0 : return NULL;
489 : }
490 :
491 4 : int iTypeY = json_object_get_type(poObjY);
492 4 : if ( (json_type_double != iTypeY) && (json_type_int != iTypeY) )
493 : {
494 : CPLError( CE_Failure, CPLE_AppDefined,
495 : "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
496 0 : json_object_to_json_string(poObjY) );
497 0 : return NULL;
498 : }
499 :
500 : double dfX, dfY;
501 4 : if (iTypeX == json_type_double)
502 0 : dfX = json_object_get_double( poObjX );
503 : else
504 4 : dfX = json_object_get_int( poObjX );
505 4 : if (iTypeY == json_type_double)
506 0 : dfY = json_object_get_double( poObjY );
507 : else
508 4 : dfY = json_object_get_int( poObjY );
509 :
510 4 : return new OGRPoint(dfX, dfY);
511 : }
512 :
513 : /************************************************************************/
514 : /* OGRESRIJSONReadLineString() */
515 : /************************************************************************/
516 :
517 4 : OGRLineString* OGRESRIJSONReadLineString( json_object* poObj)
518 : {
519 4 : CPLAssert( NULL != poObj );
520 :
521 4 : OGRLineString* poLine = NULL;
522 :
523 4 : json_object* poObjPaths = OGRGeoJSONFindMemberByName( poObj, "paths" );
524 4 : if( NULL == poObjPaths )
525 : {
526 : CPLError( CE_Failure, CPLE_AppDefined,
527 : "Invalid LineString object. "
528 0 : "Missing \'paths\' member." );
529 0 : return NULL;
530 : }
531 :
532 4 : if( json_type_array != json_object_get_type( poObjPaths ) )
533 : {
534 : CPLError( CE_Failure, CPLE_AppDefined,
535 : "Invalid LineString object. "
536 0 : "Invalid \'paths\' member." );
537 0 : return NULL;
538 : }
539 :
540 4 : poLine = new OGRLineString();
541 4 : const int nPaths = json_object_array_length( poObjPaths );
542 8 : for(int iPath = 0; iPath < nPaths; iPath ++)
543 : {
544 4 : json_object* poObjPath = json_object_array_get_idx( poObjPaths, iPath );
545 4 : if ( poObjPath == NULL ||
546 : json_type_array != json_object_get_type( poObjPath ) )
547 : {
548 0 : delete poLine;
549 : CPLDebug( "ESRIJSON",
550 0 : "LineString: got non-array object." );
551 0 : return NULL;
552 : }
553 :
554 4 : const int nPoints = json_object_array_length( poObjPath );
555 12 : for(int i = 0; i < nPoints; i++)
556 : {
557 8 : json_object* poObjCoords = NULL;
558 :
559 8 : poObjCoords = json_object_array_get_idx( poObjPath, i );
560 8 : if (poObjCoords == NULL)
561 : {
562 0 : delete poLine;
563 : CPLDebug( "ESRIJSON",
564 0 : "LineString: got null object." );
565 0 : return NULL;
566 : }
567 8 : if( json_type_array != json_object_get_type( poObjCoords ) ||
568 : json_object_array_length( poObjCoords ) != 2 )
569 : {
570 0 : delete poLine;
571 : CPLDebug( "ESRIJSON",
572 0 : "LineString: got non-array object." );
573 0 : return NULL;
574 : }
575 :
576 : json_object* poObjCoord;
577 : int iType;
578 : double dfX, dfY;
579 :
580 : // Read X coordinate
581 8 : poObjCoord = json_object_array_get_idx( poObjCoords, 0 );
582 8 : if (poObjCoord == NULL)
583 : {
584 0 : CPLDebug( "ESRIJSON", "LineString: got null object." );
585 0 : delete poLine;
586 0 : return NULL;
587 : }
588 :
589 8 : iType = json_object_get_type(poObjCoord);
590 8 : if ( (json_type_double != iType) && (json_type_int != iType) )
591 : {
592 : CPLError( CE_Failure, CPLE_AppDefined,
593 : "Invalid X coordinate. Type is not double or integer for \'%s\'.",
594 0 : json_object_to_json_string(poObjCoord) );
595 0 : delete poLine;
596 0 : return NULL;
597 : }
598 :
599 8 : if (iType == json_type_double)
600 0 : dfX = json_object_get_double( poObjCoord );
601 : else
602 8 : dfX = json_object_get_int( poObjCoord );
603 :
604 : // Read Y coordinate
605 8 : poObjCoord = json_object_array_get_idx( poObjCoords, 1 );
606 8 : if (poObjCoord == NULL)
607 : {
608 0 : CPLDebug( "ESRIJSON", "LineString: got null object." );
609 0 : delete poLine;
610 0 : return NULL;
611 : }
612 :
613 8 : iType = json_object_get_type(poObjCoord);
614 8 : if ( (json_type_double != iType) && (json_type_int != iType) )
615 : {
616 : CPLError( CE_Failure, CPLE_AppDefined,
617 : "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
618 0 : json_object_to_json_string(poObjCoord) );
619 0 : delete poLine;
620 0 : return NULL;
621 : }
622 :
623 8 : if (iType == json_type_double)
624 0 : dfY = json_object_get_double( poObjCoord );
625 : else
626 8 : dfY = json_object_get_int( poObjCoord );
627 :
628 8 : poLine->addPoint( dfX, dfY );
629 : }
630 : }
631 :
632 4 : return poLine;
633 : }
634 :
635 : /************************************************************************/
636 : /* OGRESRIJSONReadPolygon() */
637 : /************************************************************************/
638 :
639 4 : OGRPolygon* OGRESRIJSONReadPolygon( json_object* poObj)
640 : {
641 4 : CPLAssert( NULL != poObj );
642 :
643 4 : OGRPolygon* poPoly = NULL;
644 :
645 4 : json_object* poObjRings = OGRGeoJSONFindMemberByName( poObj, "rings" );
646 4 : if( NULL == poObjRings )
647 : {
648 : CPLError( CE_Failure, CPLE_AppDefined,
649 : "Invalid Polygon object. "
650 0 : "Missing \'rings\' member." );
651 0 : return NULL;
652 : }
653 :
654 4 : if( json_type_array != json_object_get_type( poObjRings ) )
655 : {
656 : CPLError( CE_Failure, CPLE_AppDefined,
657 : "Invalid Polygon object. "
658 0 : "Invalid \'rings\' member." );
659 0 : return NULL;
660 : }
661 :
662 4 : poPoly = new OGRPolygon();
663 :
664 4 : const int nRings = json_object_array_length( poObjRings );
665 8 : for(int iRing = 0; iRing < nRings; iRing ++)
666 : {
667 4 : json_object* poObjRing = json_object_array_get_idx( poObjRings, iRing );
668 4 : if ( poObjRing == NULL ||
669 : json_type_array != json_object_get_type( poObjRing ) )
670 : {
671 0 : delete poPoly;
672 : CPLDebug( "ESRIJSON",
673 0 : "Polygon: got non-array object." );
674 0 : return NULL;
675 : }
676 :
677 4 : OGRLinearRing* poLine = new OGRLinearRing();
678 4 : poPoly->addRingDirectly(poLine);
679 :
680 4 : const int nPoints = json_object_array_length( poObjRing );
681 24 : for(int i = 0; i < nPoints; i++)
682 : {
683 20 : json_object* poObjCoords = NULL;
684 :
685 20 : poObjCoords = json_object_array_get_idx( poObjRing, i );
686 20 : if (poObjCoords == NULL)
687 : {
688 0 : delete poPoly;
689 : CPLDebug( "ESRIJSON",
690 0 : "Polygon: got null object." );
691 0 : return NULL;
692 : }
693 20 : if( json_type_array != json_object_get_type( poObjCoords ) ||
694 : json_object_array_length( poObjCoords ) != 2 )
695 : {
696 0 : delete poPoly;
697 : CPLDebug( "ESRIJSON",
698 0 : "Polygon: got non-array object." );
699 0 : return NULL;
700 : }
701 :
702 : json_object* poObjCoord;
703 : int iType;
704 : double dfX, dfY;
705 :
706 : // Read X coordinate
707 20 : poObjCoord = json_object_array_get_idx( poObjCoords, 0 );
708 20 : if (poObjCoord == NULL)
709 : {
710 0 : CPLDebug( "ESRIJSON", "Polygon: got null object." );
711 0 : delete poPoly;
712 0 : return NULL;
713 : }
714 :
715 20 : iType = json_object_get_type(poObjCoord);
716 20 : if ( (json_type_double != iType) && (json_type_int != iType) )
717 : {
718 : CPLError( CE_Failure, CPLE_AppDefined,
719 : "Invalid X coordinate. Type is not double or integer for \'%s\'.",
720 0 : json_object_to_json_string(poObjCoord) );
721 0 : delete poPoly;
722 0 : return NULL;
723 : }
724 :
725 20 : if (iType == json_type_double)
726 0 : dfX = json_object_get_double( poObjCoord );
727 : else
728 20 : dfX = json_object_get_int( poObjCoord );
729 :
730 : // Read Y coordinate
731 20 : poObjCoord = json_object_array_get_idx( poObjCoords, 1 );
732 20 : if (poObjCoord == NULL)
733 : {
734 0 : CPLDebug( "ESRIJSON", "Polygon: got null object." );
735 0 : delete poPoly;
736 0 : return NULL;
737 : }
738 :
739 20 : iType = json_object_get_type(poObjCoord);
740 20 : if ( (json_type_double != iType) && (json_type_int != iType) )
741 : {
742 : CPLError( CE_Failure, CPLE_AppDefined,
743 : "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
744 0 : json_object_to_json_string(poObjCoord) );
745 0 : delete poPoly;
746 0 : return NULL;
747 : }
748 :
749 20 : if (iType == json_type_double)
750 0 : dfY = json_object_get_double( poObjCoord );
751 : else
752 20 : dfY = json_object_get_int( poObjCoord );
753 :
754 20 : poLine->addPoint( dfX, dfY );
755 : }
756 : }
757 :
758 4 : return poPoly;
759 : }
760 :
761 : /************************************************************************/
762 : /* OGRESRIJSONReadMultiPoint() */
763 : /************************************************************************/
764 :
765 4 : OGRMultiPoint* OGRESRIJSONReadMultiPoint( json_object* poObj)
766 : {
767 4 : CPLAssert( NULL != poObj );
768 :
769 4 : OGRMultiPoint* poMulti = NULL;
770 :
771 4 : json_object* poObjPoints = OGRGeoJSONFindMemberByName( poObj, "points" );
772 4 : if( NULL == poObjPoints )
773 : {
774 : CPLError( CE_Failure, CPLE_AppDefined,
775 : "Invalid LineString object. "
776 0 : "Missing \'points\' member." );
777 0 : return NULL;
778 : }
779 :
780 4 : if( json_type_array != json_object_get_type( poObjPoints ) )
781 : {
782 : CPLError( CE_Failure, CPLE_AppDefined,
783 : "Invalid LineString object. "
784 0 : "Invalid \'points\' member." );
785 0 : return NULL;
786 : }
787 :
788 4 : poMulti = new OGRMultiPoint();
789 :
790 4 : const int nPoints = json_object_array_length( poObjPoints );
791 24 : for(int i = 0; i < nPoints; i++)
792 : {
793 8 : json_object* poObjCoords = NULL;
794 :
795 8 : poObjCoords = json_object_array_get_idx( poObjPoints, i );
796 8 : if (poObjCoords == NULL)
797 : {
798 0 : delete poMulti;
799 : CPLDebug( "ESRIJSON",
800 0 : "MultiPoint: got null object." );
801 0 : return NULL;
802 : }
803 8 : if( json_type_array != json_object_get_type( poObjCoords ) ||
804 : json_object_array_length( poObjCoords ) != 2 )
805 : {
806 0 : delete poMulti;
807 : CPLDebug( "ESRIJSON",
808 0 : "MultiPoint: got non-array object." );
809 0 : return NULL;
810 : }
811 :
812 : json_object* poObjCoord;
813 : int iType;
814 : double dfX, dfY;
815 :
816 : // Read X coordinate
817 8 : poObjCoord = json_object_array_get_idx( poObjCoords, 0 );
818 8 : if (poObjCoord == NULL)
819 : {
820 0 : CPLDebug( "ESRIJSON", "MultiPoint: got null object." );
821 0 : delete poMulti;
822 0 : return NULL;
823 : }
824 :
825 8 : iType = json_object_get_type(poObjCoord);
826 8 : if ( (json_type_double != iType) && (json_type_int != iType) )
827 : {
828 : CPLError( CE_Failure, CPLE_AppDefined,
829 : "Invalid X coordinate. Type is not double or integer for \'%s\'.",
830 0 : json_object_to_json_string(poObjCoord) );
831 0 : delete poMulti;
832 0 : return NULL;
833 : }
834 :
835 8 : if (iType == json_type_double)
836 0 : dfX = json_object_get_double( poObjCoord );
837 : else
838 8 : dfX = json_object_get_int( poObjCoord );
839 :
840 : // Read Y coordinate
841 8 : poObjCoord = json_object_array_get_idx( poObjCoords, 1 );
842 8 : if (poObjCoord == NULL)
843 : {
844 0 : CPLDebug( "ESRIJSON", "MultiPoint: got null object." );
845 0 : delete poMulti;
846 0 : return NULL;
847 : }
848 :
849 8 : iType = json_object_get_type(poObjCoord);
850 8 : if ( (json_type_double != iType) && (json_type_int != iType) )
851 : {
852 : CPLError( CE_Failure, CPLE_AppDefined,
853 : "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
854 0 : json_object_to_json_string(poObjCoord) );
855 0 : delete poMulti;
856 0 : return NULL;
857 : }
858 :
859 8 : if (iType == json_type_double)
860 0 : dfY = json_object_get_double( poObjCoord );
861 : else
862 8 : dfY = json_object_get_int( poObjCoord );
863 :
864 8 : poMulti->addGeometryDirectly( new OGRPoint(dfX, dfY) );
865 : }
866 :
867 4 : return poMulti;
868 : }
869 :
870 : /************************************************************************/
871 : /* OGRESRIJSONReadSpatialReference() */
872 : /************************************************************************/
873 :
874 16 : OGRSpatialReference* OGRESRIJSONReadSpatialReference( json_object* poObj )
875 : {
876 : /* -------------------------------------------------------------------- */
877 : /* Read spatial reference definition. */
878 : /* -------------------------------------------------------------------- */
879 16 : OGRSpatialReference* poSRS = NULL;
880 :
881 16 : json_object* poObjSrs = OGRGeoJSONFindMemberByName( poObj, "spatialReference" );
882 16 : if( NULL != poObjSrs )
883 : {
884 8 : json_object* poObjWkid = OGRGeoJSONFindMemberByName( poObjSrs, "wkid" );
885 8 : if (poObjWkid == NULL)
886 : {
887 0 : json_object* poObjWkt = OGRGeoJSONFindMemberByName( poObjSrs, "wkt" );
888 0 : if (poObjWkt == NULL)
889 0 : return NULL;
890 :
891 0 : char* pszWKT = (char*) json_object_get_string( poObjWkt );
892 0 : poSRS = new OGRSpatialReference();
893 0 : if( OGRERR_NONE != poSRS->importFromWkt( &pszWKT ) ||
894 : poSRS->morphFromESRI() != OGRERR_NONE )
895 : {
896 0 : delete poSRS;
897 0 : poSRS = NULL;
898 : }
899 :
900 0 : return poSRS;
901 : }
902 :
903 8 : int nEPSG = json_object_get_int( poObjWkid );
904 :
905 8 : poSRS = new OGRSpatialReference();
906 8 : if( OGRERR_NONE != poSRS->importFromEPSG( nEPSG ) )
907 : {
908 0 : delete poSRS;
909 0 : poSRS = NULL;
910 : }
911 : }
912 :
913 16 : return poSRS;
914 : }
|