1 : /******************************************************************************
2 : * $Id: ogr_xplane_reader.cpp 21634 2011-02-06 14:45:00Z rouault $
3 : *
4 : * Project: X-Plane aeronautical data reader
5 : * Purpose: Definition of classes for OGR X-Plane aeronautical data driver.
6 : * Author: Even Rouault, even dot rouault at mines dash paris dot org
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2008, Even Rouault
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 : #include "cpl_vsi_virtual.h"
31 :
32 : #include "ogr_xplane_reader.h"
33 :
34 : CPL_CVSID("$Id: ogr_xplane_reader.cpp 21634 2011-02-06 14:45:00Z rouault $");
35 :
36 : /***********************************************************************/
37 : /* OGRXPlaneReader() */
38 : /***********************************************************************/
39 :
40 5 : OGRXPlaneReader::OGRXPlaneReader()
41 : {
42 5 : papszTokens = NULL;
43 5 : fp = NULL;
44 5 : pszFilename = NULL;
45 5 : bEOF = FALSE;
46 5 : nLineNumber = 0;
47 5 : poInterestLayer = NULL;
48 5 : nTokens = 0;
49 5 : }
50 :
51 : /***********************************************************************/
52 : /* ~OGRXPlaneReader() */
53 : /***********************************************************************/
54 :
55 5 : OGRXPlaneReader::~OGRXPlaneReader()
56 : {
57 5 : CPLFree(pszFilename);
58 5 : pszFilename = NULL;
59 :
60 5 : CSLDestroy(papszTokens);
61 5 : papszTokens = NULL;
62 :
63 5 : if (fp != NULL)
64 5 : VSIFCloseL(fp);
65 5 : fp = NULL;
66 5 : }
67 :
68 : /************************************************************************/
69 : /* StartParsing() */
70 : /************************************************************************/
71 :
72 5 : int OGRXPlaneReader::StartParsing( const char * pszFilename )
73 : {
74 5 : fp = VSIFOpenL( pszFilename, "rb" );
75 5 : if (fp == NULL)
76 0 : return FALSE;
77 :
78 5 : fp = (VSILFILE*) VSICreateBufferedReaderHandle ( (VSIVirtualHandle*) fp );
79 :
80 5 : const char* pszLine = CPLReadLineL(fp);
81 5 : if (!pszLine || (strcmp(pszLine, "I") != 0 &&
82 : strcmp(pszLine, "A") != 0))
83 : {
84 0 : VSIFCloseL(fp);
85 0 : fp = NULL;
86 0 : return FALSE;
87 : }
88 :
89 5 : pszLine = CPLReadLineL(fp);
90 5 : if (!pszLine || IsRecognizedVersion(pszLine) == FALSE)
91 : {
92 0 : VSIFCloseL(fp);
93 0 : fp = NULL;
94 0 : return FALSE;
95 : }
96 :
97 5 : CPLFree(this->pszFilename);
98 5 : this->pszFilename = CPLStrdup(pszFilename);
99 :
100 5 : nLineNumber = 2;
101 5 : CPLDebug("XPlane", "Version/Copyright : %s", pszLine);
102 :
103 5 : Rewind();
104 :
105 5 : return TRUE;
106 : }
107 :
108 : /************************************************************************/
109 : /* Rewind() */
110 : /************************************************************************/
111 :
112 7 : void OGRXPlaneReader::Rewind()
113 : {
114 7 : if (fp != NULL)
115 : {
116 5 : VSIRewindL(fp);
117 5 : CPLReadLineL(fp);
118 5 : CPLReadLineL(fp);
119 :
120 5 : nLineNumber = 2;
121 :
122 5 : CSLDestroy(papszTokens);
123 5 : papszTokens = NULL;
124 :
125 5 : bEOF = FALSE;
126 : }
127 7 : }
128 :
129 : /************************************************************************/
130 : /* GetNextFeature() */
131 : /************************************************************************/
132 :
133 0 : int OGRXPlaneReader::GetNextFeature()
134 : {
135 0 : if (fp == NULL || bEOF == TRUE || poInterestLayer == NULL)
136 0 : return FALSE;
137 :
138 0 : Read();
139 0 : return TRUE;
140 : }
141 :
142 : /************************************************************************/
143 : /* ReadWholeFile() */
144 : /************************************************************************/
145 :
146 5 : int OGRXPlaneReader::ReadWholeFile()
147 : {
148 5 : if (fp == NULL || bEOF == TRUE || nLineNumber != 2 || poInterestLayer != NULL)
149 0 : return FALSE;
150 :
151 5 : Read();
152 5 : return TRUE;
153 : }
154 :
155 :
156 : /***********************************************************************/
157 : /* assertMinCol() */
158 : /***********************************************************************/
159 :
160 2825 : int OGRXPlaneReader::assertMinCol(int nMinColNum)
161 : {
162 2825 : if (nTokens < nMinColNum)
163 : {
164 : CPLDebug("XPlane", "Line %d : not enough columns : %d. %d is the minimum required",
165 0 : nLineNumber, nTokens, nMinColNum);
166 0 : return FALSE;
167 : }
168 2825 : return TRUE;
169 : }
170 :
171 :
172 : /***********************************************************************/
173 : /* readDouble() */
174 : /***********************************************************************/
175 :
176 5728 : int OGRXPlaneReader::readDouble(double* pdfValue, int iToken, const char* pszTokenDesc)
177 : {
178 : char* pszNext;
179 5728 : *pdfValue = CPLStrtod(papszTokens[iToken], &pszNext);
180 5728 : if (*pszNext != '\0' )
181 : {
182 : CPLDebug("XPlane", "Line %d : invalid %s '%s'",
183 0 : nLineNumber, pszTokenDesc, papszTokens[iToken]);
184 0 : return FALSE;
185 : }
186 5728 : return TRUE;
187 : }
188 :
189 : /***********************************************************************/
190 : /* readDoubleWithBoundsAndConversion() */
191 : /***********************************************************************/
192 :
193 4529 : int OGRXPlaneReader::readDoubleWithBoundsAndConversion(
194 : double* pdfValue, int iToken, const char* pszTokenDesc,
195 : double dfFactor, double dfLowerBound, double dfUpperBound)
196 : {
197 4529 : int bRet = readDouble(pdfValue, iToken, pszTokenDesc);
198 4529 : if (bRet)
199 : {
200 4529 : *pdfValue *= dfFactor;
201 4529 : if (*pdfValue < dfLowerBound || *pdfValue > dfUpperBound)
202 : {
203 : CPLDebug("XPlane", "Line %d : %s '%s' out of bounds [%f, %f]",
204 : nLineNumber, pszTokenDesc, papszTokens[iToken],
205 1 : dfLowerBound / dfFactor, dfUpperBound / dfFactor);
206 1 : return FALSE;
207 : }
208 : }
209 4528 : return bRet;
210 : }
211 :
212 : /***********************************************************************/
213 : /* readDoubleWithBounds() */
214 : /***********************************************************************/
215 :
216 4485 : int OGRXPlaneReader::readDoubleWithBounds(
217 : double* pdfValue, int iToken, const char* pszTokenDesc,
218 : double dfLowerBound, double dfUpperBound)
219 : {
220 : return readDoubleWithBoundsAndConversion(pdfValue, iToken, pszTokenDesc,
221 4485 : 1., dfLowerBound, dfUpperBound);
222 : }
223 :
224 : /***********************************************************************/
225 : /* readStringUntilEnd() */
226 : /***********************************************************************/
227 :
228 309 : CPLString OGRXPlaneReader::readStringUntilEnd(int iFirstTokenIndice)
229 : {
230 309 : CPLString osResult;
231 309 : if (nTokens > iFirstTokenIndice)
232 : {
233 : int i;
234 309 : int nIDsToSum = nTokens - iFirstTokenIndice;
235 309 : const unsigned char* pszStr = (const unsigned char*)papszTokens[iFirstTokenIndice];
236 1732 : for(int j=0;pszStr[j];j++)
237 : {
238 2846 : if (pszStr[j] >= 32 && pszStr[j] <= 127)
239 1423 : osResult += pszStr[j];
240 : else
241 0 : CPLDebug("XPlane", "Line %d : string with non ASCII characters", nLineNumber);
242 : }
243 477 : for(i=1;i<nIDsToSum;i++)
244 : {
245 168 : osResult += " ";
246 168 : pszStr = (const unsigned char*)papszTokens[iFirstTokenIndice + i];
247 889 : for(int j=0;pszStr[j];j++)
248 : {
249 1442 : if (pszStr[j] >= 32 && pszStr[j] <= 127)
250 721 : osResult += pszStr[j];
251 : else
252 0 : CPLDebug("XPlane", "Line %d : string with non ASCII characters", nLineNumber);
253 : }
254 : }
255 : }
256 0 : return osResult;
257 : }
258 :
259 :
260 : /***********************************************************************/
261 : /* readLatLon() */
262 : /***********************************************************************/
263 :
264 1625 : int OGRXPlaneReader::readLatLon(double* pdfLat, double* pdfLon, int iToken)
265 : {
266 1625 : int bRet = readDoubleWithBounds(pdfLat, iToken, "latitude", -90., 90.);
267 1625 : bRet &= readDoubleWithBounds(pdfLon, iToken + 1, "longitude", -180., 180.);
268 1625 : return bRet;
269 : }
270 :
271 : /***********************************************************************/
272 : /* readTrueHeading() */
273 : /***********************************************************************/
274 :
275 667 : int OGRXPlaneReader::readTrueHeading(double* pdfTrueHeading, int iToken, const char* pszTokenDesc)
276 : {
277 667 : int bRet = readDoubleWithBounds(pdfTrueHeading, iToken, pszTokenDesc, -180., 360.);
278 667 : if (bRet)
279 : {
280 667 : if (*pdfTrueHeading < 0.)
281 0 : *pdfTrueHeading += 180.;
282 : }
283 667 : return bRet;
284 : }
285 :
286 :
287 :
288 : /***********************************************************************/
289 : /* OGRXPlaneEnumeration() */
290 : /***********************************************************************/
291 :
292 :
293 7843 : OGRXPlaneEnumeration::OGRXPlaneEnumeration(const char *pszEnumerationName,
294 : const sEnumerationElement* osElements,
295 : int nElements) :
296 : m_pszEnumerationName(pszEnumerationName),
297 : m_osElements(osElements),
298 7843 : m_nElements(nElements)
299 : {
300 7843 : }
301 :
302 : /***********************************************************************/
303 : /* GetText() */
304 : /***********************************************************************/
305 :
306 899 : const char* OGRXPlaneEnumeration::GetText(int eValue)
307 : {
308 : int i;
309 1796 : for(i=0;i<m_nElements;i++)
310 : {
311 1794 : if (m_osElements[i].eValue == eValue)
312 897 : return m_osElements[i].pszText;
313 : }
314 : CPLDebug("XPlane", "Unknown value (%d) for enumeration %s",
315 2 : eValue, m_pszEnumerationName);
316 2 : return NULL;
317 : }
318 :
319 : /***********************************************************************/
320 : /* GetValue() */
321 : /***********************************************************************/
322 :
323 0 : int OGRXPlaneEnumeration::GetValue(const char* pszText)
324 : {
325 : int i;
326 0 : if (pszText != NULL)
327 : {
328 0 : for(i=0;i<m_nElements;i++)
329 : {
330 0 : if (strcmp(m_osElements[i].pszText, pszText) == 0)
331 0 : return m_osElements[i].eValue;
332 : }
333 : }
334 : CPLDebug("XPlane", "Unknown text (%s) for enumeration %s",
335 0 : pszText, m_pszEnumerationName);
336 0 : return -1;
337 : }
|