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