1 /******************************************************************************
2 *
3 * Project: MVT Translator
4 * Purpose: Mapbox Vector Tile decoder
5 * Author: Even Rouault, Even Rouault <even dot rouault at spatialys dot com>
6 *
7 ******************************************************************************
8 * Copyright (c) 2018, Even Rouault <even dot rouault at spatialys dot com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 ****************************************************************************/
28
29 #include "mvtutils.h"
30 #include "ogr_api.h"
31
32 /************************************************************************/
33 /* OGRMVTInitFields() */
34 /************************************************************************/
35
OGRMVTInitFields(OGRFeatureDefn * poFeatureDefn,const CPLJSONObject & oFields)36 void OGRMVTInitFields(OGRFeatureDefn* poFeatureDefn,
37 const CPLJSONObject& oFields)
38 {
39 {
40 OGRFieldDefn oFieldDefnId("mvt_id", OFTInteger64);
41 poFeatureDefn->AddFieldDefn(&oFieldDefnId);
42 }
43
44 if( oFields.IsValid() )
45 {
46 for( const auto& oField: oFields.GetChildren() )
47 {
48 if( oField.GetType() == CPLJSONObject::Type::String )
49 {
50 if( oField.ToString() == "Number" )
51 {
52 OGRFieldDefn oFieldDefn(
53 oField.GetName().c_str(), OFTReal );
54 poFeatureDefn->AddFieldDefn(&oFieldDefn);
55 }
56 else if( oField.ToString() == "Integer" ) // GDAL extension
57 {
58 OGRFieldDefn oFieldDefn(
59 oField.GetName().c_str(), OFTInteger );
60 poFeatureDefn->AddFieldDefn(&oFieldDefn);
61 }
62 else if( oField.ToString() == "Boolean" )
63 {
64 OGRFieldDefn oFieldDefn(
65 oField.GetName().c_str(), OFTInteger );
66 oFieldDefn.SetSubType(OFSTBoolean);
67 poFeatureDefn->AddFieldDefn(&oFieldDefn);
68 }
69 else
70 {
71 OGRFieldDefn oFieldDefn(
72 oField.GetName().c_str(), OFTString );
73 poFeatureDefn->AddFieldDefn(&oFieldDefn);
74 }
75 }
76 }
77 }
78 }
79
80 /************************************************************************/
81 /* OGRMVTFindGeomTypeFromTileStat() */
82 /************************************************************************/
83
OGRMVTFindGeomTypeFromTileStat(const CPLJSONArray & oTileStatLayers,const char * pszLayerName)84 OGRwkbGeometryType OGRMVTFindGeomTypeFromTileStat(
85 const CPLJSONArray& oTileStatLayers,
86 const char* pszLayerName)
87 {
88 OGRwkbGeometryType eGeomType = wkbUnknown;
89 for( int i = 0; i < oTileStatLayers.Size(); i++ )
90 {
91 CPLJSONObject oId =
92 oTileStatLayers[i].GetObj("layer");
93 if( oId.IsValid() && oId.GetType() ==
94 CPLJSONObject::Type::String )
95 {
96 if( oId.ToString() == pszLayerName )
97 {
98 CPLJSONObject oGeom =
99 oTileStatLayers[i].GetObj("geometry");
100 if( oGeom.IsValid() && oGeom.GetType() ==
101 CPLJSONObject::Type::String )
102 {
103 const std::string oGeomType(
104 oGeom.ToString());
105 // Note: this information is not
106 // reliable in case
107 // of mix of geometry types
108 if( oGeomType == "Point" )
109 {
110 eGeomType = wkbMultiPoint;
111 }
112 else if( oGeomType == "LineString" )
113 {
114 eGeomType = wkbMultiLineString;
115 }
116 else if( oGeomType == "Polygon" )
117 {
118 eGeomType = wkbMultiPolygon;
119 }
120 }
121 break;
122 }
123 }
124 }
125 return eGeomType;
126 }
127
128
129 /************************************************************************/
130 /* OGRMVTCreateFeatureFrom() */
131 /************************************************************************/
132
OGRMVTCreateFeatureFrom(OGRFeature * poSrcFeature,OGRFeatureDefn * poTargetFeatureDefn,bool bJsonField,OGRSpatialReference * poSRS)133 OGRFeature* OGRMVTCreateFeatureFrom(OGRFeature* poSrcFeature,
134 OGRFeatureDefn* poTargetFeatureDefn,
135 bool bJsonField,
136 OGRSpatialReference* poSRS)
137 {
138 OGRFeature* poFeature = new OGRFeature(poTargetFeatureDefn);
139 if( bJsonField )
140 {
141 CPLJSONObject oProperties;
142 bool bEmpty = true;
143 for( int i = 1; i < poSrcFeature->GetFieldCount(); i++ )
144 {
145 if( poSrcFeature->IsFieldSet(i) )
146 {
147 bEmpty = false;
148 OGRFieldDefn* poFDefn = poSrcFeature->GetFieldDefnRef(i);
149 if( poSrcFeature->IsFieldNull(i) )
150 {
151 oProperties.AddNull(poFDefn->GetNameRef());
152 }
153 else if( poFDefn->GetType() == OFTInteger ||
154 poFDefn->GetType() == OFTInteger64 )
155 {
156 if( poFDefn->GetSubType() == OFSTBoolean )
157 {
158 oProperties.Add(poFDefn->GetNameRef(),
159 poSrcFeature->GetFieldAsInteger(i) == 1);
160 }
161 else
162 {
163 oProperties.Add(poFDefn->GetNameRef(),
164 poSrcFeature->GetFieldAsInteger64(i));
165 }
166 }
167 else if( poFDefn->GetType() == OFTReal )
168 {
169 oProperties.Add(poFDefn->GetNameRef(),
170 poSrcFeature->GetFieldAsDouble(i));
171 }
172 else
173 {
174 oProperties.Add(poFDefn->GetNameRef(),
175 poSrcFeature->GetFieldAsString(i));
176 }
177 }
178 }
179 if( !bEmpty )
180 {
181 poFeature->SetField("json",
182 oProperties.Format(CPLJSONObject::PrettyFormat::Pretty).c_str());
183 }
184
185 OGRGeometry* poSrcGeom = poSrcFeature->GetGeometryRef();
186 if( poSrcGeom )
187 {
188 poFeature->SetGeometry( poSrcGeom );
189 }
190 #ifdef nodef
191 CPLJSONObject oObj;
192 oObj.Add("type", "Feature");
193 if( poSrcFeature->IsFieldSet(0) )
194 oObj.Add("id", poSrcFeature->GetFieldAsInteger64("mvt_id"));
195 oObj.Add("properties", oProperties);
196 if( poSrcGeom )
197 {
198 char* pszGeomJson = OGR_G_ExportToJson(
199 reinterpret_cast<OGRGeometryH>(poSrcGeom) );
200 CPLJSONDocument oJSonDoc;
201 oJSonDoc.LoadMemory(reinterpret_cast<const GByte*>(pszGeomJson));
202 CPLFree(pszGeomJson);
203 oObj.Add( "geometry", oJSonDoc.GetRoot() );
204 }
205 poFeature->SetNativeData(
206 oObj.Format(CPLJSONObject::PrettyFormat::Pretty).c_str());
207 poFeature->SetNativeMediaType("application/vnd.geo+json");
208 #endif
209 }
210 else
211 {
212 poFeature->SetFrom( poSrcFeature );
213 }
214 OGRGeometry* poGeom = poFeature->GetGeometryRef();
215 if( poGeom )
216 poGeom->assignSpatialReference(poSRS);
217 return poFeature;
218 }
219