Line data Source code
1 : /******************************************************************************
2 : * $Id$
3 : *
4 : * Project: GPX Translator
5 : * Purpose: Definition of classes for OGR .gpx driver.
6 : * Author: Even Rouault, even dot rouault at spatialys.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2007-2010, 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 OGR_GPX_H_INCLUDED
31 : #define OGR_GPX_H_INCLUDED
32 :
33 : #include "cpl_vsi_virtual.h"
34 : #include "ogrsf_frmts.h"
35 :
36 : #ifdef HAVE_EXPAT
37 : #include "ogr_expat.h"
38 : #endif
39 :
40 : #include <limits>
41 : #include <deque>
42 :
43 : class OGRGPXDataSource;
44 :
45 : typedef enum
46 : {
47 : GPX_NONE,
48 : GPX_WPT,
49 : GPX_TRACK,
50 : GPX_ROUTE,
51 : GPX_ROUTE_POINT,
52 : GPX_TRACK_POINT,
53 : } GPXGeometryType;
54 :
55 : constexpr int PARSER_BUF_SIZE = 8192;
56 :
57 : /************************************************************************/
58 : /* OGRGPXLayer */
59 : /************************************************************************/
60 :
61 : class OGRGPXLayer final : public OGRLayer
62 : {
63 : OGRFeatureDefn *m_poFeatureDefn = nullptr;
64 : OGRSpatialReference *m_poSRS = nullptr;
65 : OGRGPXDataSource *m_poDS = nullptr;
66 :
67 : GPXGeometryType m_gpxGeomType = GPX_NONE;
68 :
69 : int m_nGPXFields = 0;
70 :
71 : bool m_bWriteMode = false;
72 : GIntBig m_nNextFID = 0;
73 : VSIVirtualHandleUniquePtr m_fpGPX{};
74 : #ifdef HAVE_EXPAT
75 : XML_Parser m_oParser = nullptr;
76 : XML_Parser m_oSchemaParser = nullptr;
77 : #endif
78 : bool m_inInterestingElement = false;
79 : bool m_hasFoundLat = false;
80 : bool m_hasFoundLon = false;
81 : #ifdef HAVE_EXPAT
82 : double m_latVal = 0;
83 : double m_lonVal = 0;
84 : #endif
85 : std::string m_osSubElementName{};
86 : std::string m_osSubElementValue{};
87 : #ifdef HAVE_EXPAT
88 : int m_iCurrentField = 0;
89 : #endif
90 :
91 : std::unique_ptr<OGRFeature> m_poFeature{};
92 : std::deque<std::unique_ptr<OGRFeature>> m_oFeatureQueue{};
93 :
94 : std::unique_ptr<OGRMultiLineString> m_multiLineString{};
95 : std::unique_ptr<OGRLineString> m_lineString{};
96 :
97 : int m_depthLevel = 0;
98 : int m_interestingDepthLevel = 0;
99 :
100 : #ifdef HAVE_EXPAT
101 : OGRFieldDefn *m_currentFieldDefn = nullptr;
102 : bool m_inExtensions = false;
103 : int m_extensionsDepthLevel = 0;
104 :
105 : bool m_inLink = 0;
106 : int m_iCountLink = 0;
107 : #endif
108 : int m_nMaxLinks = 0;
109 :
110 : bool m_bEleAs25D = false;
111 :
112 : int m_trkFID = 0;
113 : int m_trkSegId = 0;
114 : int m_trkSegPtId = 0;
115 :
116 : int m_rteFID = 0;
117 : int m_rtePtId = 0;
118 :
119 : #ifdef HAVE_EXPAT
120 : bool m_bStopParsing = false;
121 : int m_nWithoutEventCounter = 0;
122 : int m_nDataHandlerCounter = 0;
123 : #endif
124 :
125 : int m_iFirstGPXField = 0;
126 :
127 : CPL_DISALLOW_COPY_ASSIGN(OGRGPXLayer)
128 :
129 : private:
130 : void WriteFeatureAttributes(const OGRFeature *poFeature,
131 : int nIdentLevel = 1);
132 : void LoadExtensionsSchema();
133 : #ifdef HAVE_EXPAT
134 : void AddStrToSubElementValue(const char *pszStr);
135 : #endif
136 : bool OGRGPX_WriteXMLExtension(const char *pszTagName,
137 : const char *pszContent);
138 :
139 : public:
140 : OGRGPXLayer(const char *pszFilename, const char *layerName,
141 : GPXGeometryType gpxGeomType, OGRGPXDataSource *poDS,
142 : bool bWriteMode, CSLConstList papszOpenOptions);
143 : ~OGRGPXLayer();
144 :
145 : void ResetReading() override;
146 : OGRFeature *GetNextFeature() override;
147 :
148 : OGRErr ICreateFeature(OGRFeature *poFeature) override;
149 : OGRErr CreateField(const OGRFieldDefn *poField, int bApproxOK) override;
150 :
151 364 : OGRFeatureDefn *GetLayerDefn() override
152 : {
153 364 : return m_poFeatureDefn;
154 : }
155 :
156 : int TestCapability(const char *) override;
157 :
158 : GDALDataset *GetDataset() override;
159 :
160 : #ifdef HAVE_EXPAT
161 : void startElementCbk(const char *pszName, const char **ppszAttr);
162 : void endElementCbk(const char *pszName);
163 : void dataHandlerCbk(const char *data, int nLen);
164 :
165 : void startElementLoadSchemaCbk(const char *pszName, const char **ppszAttr);
166 : void endElementLoadSchemaCbk(const char *pszName);
167 : void dataHandlerLoadSchemaCbk(const char *data, int nLen);
168 : #endif
169 :
170 : static OGRErr CheckAndFixCoordinatesValidity(double *pdfLatitude,
171 : double *pdfLongitude);
172 : };
173 :
174 : /************************************************************************/
175 : /* OGRGPXDataSource */
176 : /************************************************************************/
177 :
178 : typedef enum
179 : {
180 : GPX_VALIDITY_UNKNOWN,
181 : GPX_VALIDITY_INVALID,
182 : GPX_VALIDITY_VALID
183 : } OGRGPXValidity;
184 :
185 : class OGRGPXDataSource final : public GDALDataset
186 : {
187 : std::vector<std::unique_ptr<OGRGPXLayer>> m_apoLayers{};
188 :
189 : /* Export related */
190 : VSIVirtualHandleUniquePtr m_fpOutput{};
191 : bool m_bIsBackSeekable = true;
192 : const char *m_pszEOL = "\n";
193 : vsi_l_offset m_nOffsetBounds = 0;
194 : double m_dfMinLat = std::numeric_limits<double>::infinity();
195 : double m_dfMinLon = std::numeric_limits<double>::infinity();
196 : double m_dfMaxLat = -std::numeric_limits<double>::infinity();
197 : double m_dfMaxLon = -std::numeric_limits<double>::infinity();
198 :
199 : GPXGeometryType m_lastGPXGeomTypeWritten = GPX_NONE;
200 :
201 : bool m_bUseExtensions = false;
202 : std::string m_osExtensionsNS{};
203 :
204 : #ifdef HAVE_EXPAT
205 : OGRGPXValidity m_validity = GPX_VALIDITY_UNKNOWN;
206 : std::string m_osVersion{};
207 : XML_Parser m_oCurrentParser = nullptr;
208 : int m_nDataHandlerCounter = 0;
209 : bool m_bInMetadata = false;
210 : bool m_bInMetadataAuthor = false;
211 : bool m_bInMetadataAuthorLink = false;
212 : bool m_bInMetadataCopyright = false;
213 : bool m_bInMetadataLink = false;
214 : int m_nMetadataLinkCounter = 0;
215 : int m_nDepth = 0;
216 : std::string m_osMetadataKey{};
217 : std::string m_osMetadataValue{};
218 : #endif
219 :
220 : CPL_DISALLOW_COPY_ASSIGN(OGRGPXDataSource)
221 :
222 : public:
223 54 : OGRGPXDataSource() = default;
224 : ~OGRGPXDataSource();
225 :
226 : int m_nLastRteId = -1;
227 : int m_nLastTrkId = -1;
228 : int m_nLastTrkSegId = -1;
229 :
230 : int Open(GDALOpenInfo *poOpenInfo);
231 :
232 : int Create(const char *pszFilename, char **papszOptions);
233 :
234 160 : int GetLayerCount() override
235 : {
236 160 : return static_cast<int>(m_apoLayers.size());
237 : }
238 :
239 : OGRLayer *GetLayer(int) override;
240 :
241 : OGRLayer *ICreateLayer(const char *pszName,
242 : const OGRGeomFieldDefn *poGeomFieldDefn,
243 : CSLConstList papszOptions) override;
244 :
245 : int TestCapability(const char *) override;
246 :
247 88 : VSILFILE *GetOutputFP()
248 : {
249 88 : return m_fpOutput.get();
250 : }
251 :
252 49 : void SetLastGPXGeomTypeWritten(GPXGeometryType gpxGeomType)
253 : {
254 49 : m_lastGPXGeomTypeWritten = gpxGeomType;
255 49 : }
256 :
257 105 : GPXGeometryType GetLastGPXGeomTypeWritten() const
258 : {
259 105 : return m_lastGPXGeomTypeWritten;
260 : }
261 :
262 205 : bool GetUseExtensions() const
263 : {
264 205 : return m_bUseExtensions;
265 : }
266 :
267 2 : const std::string &GetExtensionsNS() const
268 : {
269 2 : return m_osExtensionsNS;
270 : }
271 :
272 : #ifdef HAVE_EXPAT
273 : void startElementValidateCbk(const char *pszName, const char **ppszAttr);
274 : void endElementValidateCbk(const char *pszName);
275 : void dataHandlerValidateCbk(const char *data, int nLen);
276 :
277 165 : const char *GetVersion() const
278 : {
279 165 : return m_osVersion.c_str();
280 : }
281 : #endif
282 :
283 : void AddCoord(double dfLon, double dfLat);
284 :
285 : void PrintLine(const char *fmt, ...) CPL_PRINT_FUNC_FORMAT(2, 3);
286 : };
287 :
288 : #endif /* ndef OGR_GPX_H_INCLUDED */
|