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