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