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