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