Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: KML Translator
4 : * Purpose: Implements OGRLIBKMLDriver
5 : * Author: Brian Case, rush at winkey dot org
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2010, Brian Case
9 : * Copyright (c) 2010-2014, Even Rouault <even dot rouault at spatialys.com>
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 :
30 : #ifndef HAVE_OGR_LIBKML_H
31 : #define HAVE_OGR_LIBKML_H
32 :
33 : #include "ogrsf_frmts.h"
34 :
35 : #include "libkml_headers.h"
36 :
37 : #include <map>
38 :
39 : class OGRLIBKMLDataSource;
40 :
41 : CPLString OGRLIBKMLGetSanitizedNCName(const char *pszName);
42 :
43 : /******************************************************************************
44 : layer class
45 : ******************************************************************************/
46 :
47 : class OGRLIBKMLLayer final : public OGRLayer,
48 : public OGRGetNextFeatureThroughRaw<OGRLIBKMLLayer>
49 : {
50 : int bUpdate;
51 :
52 : int nFeatures;
53 : int iFeature;
54 : long nFID;
55 : const char *m_pszName;
56 : const char *m_pszFileName;
57 :
58 : kmldom::ContainerPtr m_poKmlLayer;
59 : kmldom::ElementPtr m_poKmlLayerRoot;
60 : kmldom::UpdatePtr m_poKmlUpdate;
61 :
62 : OGRLIBKMLDataSource *m_poOgrDS;
63 : OGRFeatureDefn *m_poOgrFeatureDefn;
64 : kmldom::SchemaPtr m_poKmlSchema;
65 : OGRSpatialReference *m_poOgrSRS;
66 : std::unique_ptr<OGRCoordinateTransformation> m_poCT{};
67 :
68 : bool m_bReadGroundOverlay;
69 : bool m_bUseSimpleField;
70 :
71 : bool m_bWriteRegion;
72 : bool m_bRegionBoundsAuto;
73 : double m_dfRegionMinLodPixels;
74 : double m_dfRegionMaxLodPixels;
75 : double m_dfRegionMinFadeExtent;
76 : double m_dfRegionMaxFadeExtent;
77 : double m_dfRegionMinX;
78 : double m_dfRegionMinY;
79 : double m_dfRegionMaxX;
80 : double m_dfRegionMaxY;
81 :
82 : CPLString osListStyleType;
83 : CPLString osListStyleIconHref;
84 :
85 : bool m_bUpdateIsFolder;
86 :
87 : OGRFeature *GetNextRawFeature();
88 :
89 : public:
90 : OGRLIBKMLLayer(const char *pszLayerName, OGRwkbGeometryType eGType,
91 : const OGRSpatialReference *poSRSIn,
92 : OGRLIBKMLDataSource *poOgrDS, kmldom::ElementPtr poKmlRoot,
93 : kmldom::ContainerPtr poKmlContainer,
94 : kmldom::UpdatePtr poKmlUpdate, const char *pszFileName,
95 : int bNew, int bUpdate);
96 : virtual ~OGRLIBKMLLayer();
97 :
98 825 : void ResetReading() override
99 : {
100 825 : iFeature = 0;
101 825 : nFID = 1;
102 825 : }
103 887 : DEFINE_GET_NEXT_FEATURE_THROUGH_RAW(OGRLIBKMLLayer)
104 :
105 4146 : OGRFeatureDefn *GetLayerDefn() override
106 : {
107 4146 : return m_poOgrFeatureDefn;
108 : }
109 :
110 : // OGRErr SetAttributeFilter(const char * );
111 : OGRErr ICreateFeature(OGRFeature *poOgrFeat) override;
112 : OGRErr ISetFeature(OGRFeature *poOgrFeat) override;
113 : OGRErr DeleteFeature(GIntBig nFID) override;
114 :
115 : GIntBig GetFeatureCount(int bForce = TRUE) override;
116 : OGRErr GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
117 :
118 30 : virtual OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent,
119 : int bForce) override
120 : {
121 30 : return OGRLayer::GetExtent(iGeomField, psExtent, bForce);
122 : }
123 :
124 : // const char *GetInfo( const char * );
125 :
126 : OGRErr CreateField(const OGRFieldDefn *poField,
127 : int bApproxOK = TRUE) override;
128 :
129 : OGRErr SyncToDisk() override;
130 :
131 : OGRStyleTable *GetStyleTable() override;
132 : void SetStyleTableDirectly(OGRStyleTable *poStyleTable) override;
133 : void SetStyleTable(OGRStyleTable *poStyleTable) override;
134 :
135 335 : const char *GetName() override
136 : {
137 335 : return m_pszName;
138 : }
139 :
140 : int TestCapability(const char *) override;
141 :
142 : GDALDataset *GetDataset() override;
143 :
144 208 : kmldom::ContainerPtr GetKmlLayer()
145 : {
146 208 : return m_poKmlLayer;
147 : }
148 :
149 39 : kmldom::ElementPtr GetKmlLayerRoot()
150 : {
151 39 : return m_poKmlLayerRoot;
152 : }
153 :
154 210 : kmldom::SchemaPtr GetKmlSchema()
155 : {
156 210 : return m_poKmlSchema;
157 : }
158 :
159 71 : const char *GetFileName()
160 : {
161 71 : return m_pszFileName;
162 : }
163 :
164 : void SetLookAt(const char *pszLookatLongitude,
165 : const char *pszLookatLatitude, const char *pszLookatAltitude,
166 : const char *pszLookatHeading, const char *pszLookatTilt,
167 : const char *pszLookatRange,
168 : const char *pszLookatAltitudeMode);
169 : void SetCamera(const char *pszCameraLongitude,
170 : const char *pszCameraLatitude, const char *pszCameraAltitude,
171 : const char *pszCameraHeading, const char *pszCameraTilt,
172 : const char *pszCameraRoll,
173 : const char *pszCameraAltitudeMode);
174 :
175 : static CPLString LaunderFieldNames(CPLString osName);
176 :
177 : void SetWriteRegion(double dfMinLodPixels, double dfMaxLodPixels,
178 : double dfMinFadeExtent, double dfMaxFadeExtent);
179 : void SetRegionBounds(double dfMinX, double dfMinY, double dfMaxX,
180 : double dfMaxY);
181 :
182 : void SetScreenOverlay(const char *pszSOHref, const char *pszSOName,
183 : const char *pszSODescription,
184 : const char *pszSOOverlayX, const char *pszSOOverlayY,
185 : const char *pszSOOverlayXUnits,
186 : const char *pszSOOverlayYUnits,
187 : const char *pszSOScreenX, const char *pszSOScreenY,
188 : const char *pszSOScreenXUnits,
189 : const char *pszSOScreenYUnits, const char *pszSOSizeX,
190 : const char *pszSOSizeY, const char *pszSOSizeXUnits,
191 : const char *pszSOSizeYUnits);
192 :
193 : void SetListStyle(const char *pszListStyleType,
194 : const char *pszListStyleIconHref);
195 :
196 : void Finalize(kmldom::DocumentPtr poKmlDocument);
197 :
198 0 : void SetUpdateIsFolder(int bUpdateIsFolder)
199 : {
200 0 : m_bUpdateIsFolder = CPL_TO_BOOL(bUpdateIsFolder);
201 0 : }
202 : };
203 :
204 : /******************************************************************************
205 : datasource class
206 : ******************************************************************************/
207 :
208 : class OGRLIBKMLDataSource final : public OGRDataSource
209 : {
210 : char *m_pszName;
211 : bool m_bIssuedCTError = false;
212 :
213 : /***** layers *****/
214 : OGRLIBKMLLayer **papoLayers;
215 : int nLayers;
216 : int nAllocated;
217 : std::map<CPLString, OGRLIBKMLLayer *> m_oMapLayers;
218 :
219 : bool bUpdate;
220 : bool bUpdated;
221 : CPLString osUpdateTargetHref;
222 :
223 : char **m_papszOptions;
224 :
225 : /***** for kml files *****/
226 : bool m_isKml;
227 : kmldom::KmlPtr m_poKmlDSKml;
228 : kmldom::ContainerPtr m_poKmlDSContainer;
229 : kmldom::UpdatePtr m_poKmlUpdate;
230 :
231 : /***** for kmz files *****/
232 : bool m_isKmz;
233 : kmldom::ContainerPtr m_poKmlDocKml;
234 : kmldom::ElementPtr m_poKmlDocKmlRoot;
235 : kmldom::ContainerPtr m_poKmlStyleKml;
236 : char *pszStylePath;
237 :
238 : /***** for dir *****/
239 : int m_isDir;
240 :
241 : /***** the kml factory *****/
242 : kmldom::KmlFactory *m_poKmlFactory;
243 :
244 : /***** style table pointer *****/
245 : void SetCommonOptions(kmldom::ContainerPtr poKmlContainer,
246 : CSLConstList papszOptions);
247 :
248 : void ParseDocumentOptions(kmldom::KmlPtr poKml,
249 : kmldom::DocumentPtr poKmlDocument);
250 :
251 : public:
252 : explicit OGRLIBKMLDataSource(kmldom::KmlFactory *poKmlFactory);
253 : ~OGRLIBKMLDataSource();
254 :
255 0 : const char *GetName() override
256 : {
257 0 : return m_pszName;
258 : }
259 :
260 21 : int GetLayerCount() override
261 : {
262 21 : return nLayers;
263 : }
264 :
265 : OGRLayer *GetLayer(int) override;
266 : OGRLayer *GetLayerByName(const char *) override;
267 : OGRErr DeleteLayer(int) override;
268 :
269 : OGRLayer *ICreateLayer(const char *pszName,
270 : const OGRGeomFieldDefn *poGeomFieldDefn,
271 : CSLConstList papszOptions) override;
272 :
273 : OGRStyleTable *GetStyleTable() override;
274 : void SetStyleTableDirectly(OGRStyleTable *poStyleTable) override;
275 : void SetStyleTable(OGRStyleTable *poStyleTable) override;
276 :
277 : int Open(const char *pszFilename, int bUpdate);
278 : int Create(const char *pszFilename, char **papszOptions);
279 :
280 : CPLErr FlushCache(bool bAtClosing) override;
281 : int TestCapability(const char *) override;
282 :
283 424 : kmldom::KmlFactory *GetKmlFactory()
284 : {
285 424 : return m_poKmlFactory;
286 : }
287 :
288 447 : const char *GetStylePath()
289 : {
290 447 : return pszStylePath;
291 : }
292 :
293 : int ParseIntoStyleTable(std::string *oKmlStyleKml,
294 : const char *pszStylePath);
295 :
296 : // KmzFile *GetKmz() { return m_poKmlKmzfile; }
297 :
298 196 : int IsKml() const
299 : {
300 196 : return m_isKml;
301 : }
302 :
303 253 : int IsKmz() const
304 : {
305 253 : return m_isKmz;
306 : }
307 :
308 187 : int IsDir() const
309 : {
310 187 : return m_isDir;
311 : }
312 :
313 306 : void Updated()
314 : {
315 306 : bUpdated = true;
316 306 : }
317 :
318 : int ParseLayers(kmldom::ContainerPtr poKmlContainer, bool bRecurse);
319 : kmldom::SchemaPtr FindSchema(const char *pszSchemaUrl);
320 :
321 0 : bool IsFirstCTError() const
322 : {
323 0 : return !m_bIssuedCTError;
324 : }
325 :
326 0 : void IssuedFirstCTError()
327 : {
328 0 : m_bIssuedCTError = true;
329 0 : }
330 :
331 : private:
332 : /***** methods to write out various datasource types at destroy *****/
333 : bool WriteKml();
334 : bool WriteKmz();
335 : bool WriteDir();
336 :
337 : /***** methods to open various datasource types *****/
338 : int OpenKmz(const char *pszFilename, int bUpdate);
339 : int OpenKml(const char *pszFilename, int bUpdate);
340 : int OpenDir(const char *pszFilename, int bUpdate);
341 :
342 : /***** methods to create various datasource types *****/
343 : int CreateKml(const char *pszFilename, char **papszOptions);
344 : int CreateKmz(const char *pszFilename, char **papszOptions);
345 : int CreateDir(const char *pszFilename, char **papszOptions);
346 :
347 : /***** methods to create layers on various datasource types *****/
348 : OGRLIBKMLLayer *CreateLayerKml(const char *pszLayerName,
349 : const OGRSpatialReference *poOgrSRS,
350 : OGRwkbGeometryType eGType,
351 : CSLConstList papszOptions);
352 : OGRLIBKMLLayer *CreateLayerKmz(const char *pszLayerName,
353 : const OGRSpatialReference *poOgrSRS,
354 : OGRwkbGeometryType eGType,
355 : CSLConstList papszOptions);
356 :
357 : /***** methods to delete layers on various datasource types *****/
358 : OGRErr DeleteLayerKml(int);
359 : OGRErr DeleteLayerKmz(int);
360 :
361 : /***** methods to write a styletable to various datasource types *****/
362 : void SetStyleTable2Kml(OGRStyleTable *poStyleTable);
363 : void SetStyleTable2Kmz(OGRStyleTable *poStyleTable);
364 :
365 : OGRLIBKMLLayer *
366 : AddLayer(const char *pszLayerName, OGRwkbGeometryType eGType,
367 : const OGRSpatialReference *poSRS, OGRLIBKMLDataSource *poOgrDS,
368 : kmldom::ElementPtr poKmlRoot, kmldom::ContainerPtr poKmlContainer,
369 : const char *pszFileName, int bNew, int bUpdate, int nGuess);
370 : };
371 :
372 : #endif
|