1 : /******************************************************************************
2 : * $Id: ogrgeojsonwritelayer.cpp 23663 2011-12-30 11:17:23Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implementation of OGRGeoJSONWriteLayer class (OGR GeoJSON Driver).
6 : * Author: Mateusz Loskot, mateusz@loskot.net
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2011, Even Rouault
10 : * Copyright (c) 2007, Mateusz Loskot
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 : #include "ogr_geojson.h"
31 : #include "ogrgeojsonwriter.h"
32 :
33 : /* Remove annoying warnings Microsoft Visual C++ */
34 : #if defined(_MSC_VER)
35 : # pragma warning(disable:4512)
36 : #endif
37 :
38 : /************************************************************************/
39 : /* OGRGeoJSONWriteLayer() */
40 : /************************************************************************/
41 :
42 30 : OGRGeoJSONWriteLayer::OGRGeoJSONWriteLayer( const char* pszName,
43 : OGRwkbGeometryType eGType,
44 : char** papszOptions,
45 : OGRGeoJSONDataSource* poDS )
46 30 : : poDS_( poDS ), poFeatureDefn_(new OGRFeatureDefn( pszName ) ), nOutCounter_( 0 )
47 : {
48 30 : bWriteBBOX = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "WRITE_BBOX", "FALSE"));
49 30 : bBBOX3D = FALSE;
50 :
51 30 : poFeatureDefn_->Reference();
52 30 : poFeatureDefn_->SetGeomType( eGType );
53 :
54 30 : nCoordPrecision = atoi(CSLFetchNameValueDef(papszOptions, "COORDINATE_PRECISION", "-1"));
55 30 : }
56 :
57 : /************************************************************************/
58 : /* ~OGRGeoJSONWriteLayer() */
59 : /************************************************************************/
60 :
61 30 : OGRGeoJSONWriteLayer::~OGRGeoJSONWriteLayer()
62 : {
63 30 : VSILFILE* fp = poDS_->GetOutputFile();
64 :
65 30 : VSIFPrintfL( fp, "\n]" );
66 :
67 30 : if( bWriteBBOX && sEnvelopeLayer.IsInit() )
68 : {
69 2 : json_object* poObjBBOX = json_object_new_array();
70 : json_object_array_add(poObjBBOX,
71 2 : json_object_new_double_with_precision(sEnvelopeLayer.MinX, nCoordPrecision));
72 : json_object_array_add(poObjBBOX,
73 2 : json_object_new_double_with_precision(sEnvelopeLayer.MinY, nCoordPrecision));
74 2 : if( bBBOX3D )
75 : json_object_array_add(poObjBBOX,
76 0 : json_object_new_double_with_precision(sEnvelopeLayer.MinZ, nCoordPrecision));
77 : json_object_array_add(poObjBBOX,
78 2 : json_object_new_double_with_precision(sEnvelopeLayer.MaxX, nCoordPrecision));
79 : json_object_array_add(poObjBBOX,
80 2 : json_object_new_double_with_precision(sEnvelopeLayer.MaxY, nCoordPrecision));
81 2 : if( bBBOX3D )
82 : json_object_array_add(poObjBBOX,
83 0 : json_object_new_double_with_precision(sEnvelopeLayer.MaxZ, nCoordPrecision));
84 :
85 2 : const char* pszBBOX = json_object_to_json_string( poObjBBOX );
86 2 : if( poDS_->GetFpOutputIsSeekable() )
87 : {
88 2 : VSIFSeekL(fp, poDS_->GetBBOXInsertLocation(), SEEK_SET);
89 2 : if (strlen(pszBBOX) + 9 < SPACE_FOR_BBOX)
90 2 : VSIFPrintfL( fp, "\"bbox\": %s,", pszBBOX );
91 2 : VSIFSeekL(fp, 0, SEEK_END);
92 : }
93 : else
94 : {
95 0 : VSIFPrintfL( fp, ",\n\"bbox\": %s", pszBBOX );
96 : }
97 :
98 2 : json_object_put( poObjBBOX );
99 : }
100 :
101 30 : VSIFPrintfL( fp, "\n}\n" );
102 :
103 30 : if( NULL != poFeatureDefn_ )
104 : {
105 30 : poFeatureDefn_->Release();
106 : }
107 30 : }
108 :
109 : /************************************************************************/
110 : /* CreateFeature() */
111 : /************************************************************************/
112 :
113 54 : OGRErr OGRGeoJSONWriteLayer::CreateFeature( OGRFeature* poFeature )
114 : {
115 54 : VSILFILE* fp = poDS_->GetOutputFile();
116 :
117 54 : if( NULL == poFeature )
118 : {
119 0 : CPLDebug( "GeoJSON", "Feature is null" );
120 0 : return OGRERR_INVALID_HANDLE;
121 : }
122 :
123 54 : json_object* poObj = OGRGeoJSONWriteFeature( poFeature, bWriteBBOX, nCoordPrecision );
124 54 : CPLAssert( NULL != poObj );
125 :
126 54 : if( nOutCounter_ > 0 )
127 : {
128 : /* Separate "Feature" entries in "FeatureCollection" object. */
129 24 : VSIFPrintfL( fp, ",\n" );
130 : }
131 54 : VSIFPrintfL( fp, "%s", json_object_to_json_string( poObj ) );
132 :
133 54 : json_object_put( poObj );
134 :
135 54 : ++nOutCounter_;
136 :
137 54 : OGRGeometry* poGeometry = poFeature->GetGeometryRef();
138 54 : if ( bWriteBBOX && !poGeometry->IsEmpty() )
139 : {
140 4 : OGREnvelope3D sEnvelope;
141 4 : poGeometry->getEnvelope(&sEnvelope);
142 :
143 4 : if( poGeometry->getCoordinateDimension() == 3 )
144 0 : bBBOX3D = TRUE;
145 :
146 4 : sEnvelopeLayer.Merge(sEnvelope);
147 : }
148 :
149 54 : return OGRERR_NONE;
150 : }
151 :
152 : /************************************************************************/
153 : /* CreateField() */
154 : /************************************************************************/
155 :
156 52 : OGRErr OGRGeoJSONWriteLayer::CreateField(OGRFieldDefn* poField, int bApproxOK)
157 : {
158 : UNREFERENCED_PARAM(bApproxOK);
159 :
160 78 : for( int i = 0; i < poFeatureDefn_->GetFieldCount(); ++i )
161 : {
162 26 : OGRFieldDefn* poDefn = poFeatureDefn_->GetFieldDefn(i);
163 26 : CPLAssert( NULL != poDefn );
164 :
165 26 : if( EQUAL( poDefn->GetNameRef(), poField->GetNameRef() ) )
166 : {
167 : CPLDebug( "GeoJSON", "Field '%s' already present in schema",
168 0 : poField->GetNameRef() );
169 :
170 : // TODO - mloskot: Is this return code correct?
171 0 : return OGRERR_NONE;
172 : }
173 : }
174 :
175 52 : poFeatureDefn_->AddFieldDefn( poField );
176 :
177 52 : return OGRERR_NONE;
178 : }
179 :
180 : /************************************************************************/
181 : /* TestCapability() */
182 : /************************************************************************/
183 :
184 0 : int OGRGeoJSONWriteLayer::TestCapability( const char* pszCap )
185 : {
186 0 : if (EQUAL(pszCap, OLCCreateField))
187 0 : return TRUE;
188 0 : else if (EQUAL(pszCap, OLCSequentialWrite))
189 0 : return TRUE;
190 :
191 0 : return FALSE;
192 : }
|