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