1 : /******************************************************************************
2 : * $Id: ogr_xplane_nav_reader.cpp
3 : *
4 : * Project: X-Plane nav.dat file reader
5 : * Purpose: Implements OGRXPlaneNavReader class
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_nav_reader.h"
31 :
32 : CPL_CVSID("$Id: ogr_xplane_nav_reader.cpp 21634 2011-02-06 14:45:00Z rouault $");
33 :
34 : /************************************************************************/
35 : /* OGRXPlaneCreateNavFileReader */
36 : /************************************************************************/
37 :
38 1 : OGRXPlaneReader* OGRXPlaneCreateNavFileReader( OGRXPlaneDataSource* poDataSource )
39 : {
40 1 : OGRXPlaneReader* poReader = new OGRXPlaneNavReader(poDataSource);
41 1 : return poReader;
42 : }
43 :
44 :
45 : /************************************************************************/
46 : /* OGRXPlaneNavReader() */
47 : /************************************************************************/
48 0 : OGRXPlaneNavReader::OGRXPlaneNavReader()
49 : {
50 0 : poILSLayer = NULL;
51 0 : poVORLayer = NULL;
52 0 : poNDBLayer = NULL;
53 0 : poGSLayer = NULL;
54 0 : poMarkerLayer = NULL;
55 0 : poDMELayer = NULL;
56 0 : poDMEILSLayer = NULL;
57 0 : }
58 :
59 : /************************************************************************/
60 : /* OGRXPlaneNavReader() */
61 : /************************************************************************/
62 :
63 1 : OGRXPlaneNavReader::OGRXPlaneNavReader( OGRXPlaneDataSource* poDataSource )
64 : {
65 1 : poILSLayer = new OGRXPlaneILSLayer();
66 2 : poVORLayer = new OGRXPlaneVORLayer();
67 2 : poNDBLayer = new OGRXPlaneNDBLayer();
68 2 : poGSLayer = new OGRXPlaneGSLayer();
69 2 : poMarkerLayer = new OGRXPlaneMarkerLayer();
70 2 : poDMELayer = new OGRXPlaneDMELayer();
71 2 : poDMEILSLayer = new OGRXPlaneDMEILSLayer();
72 :
73 1 : poDataSource->RegisterLayer(poILSLayer);
74 1 : poDataSource->RegisterLayer(poVORLayer);
75 1 : poDataSource->RegisterLayer(poNDBLayer);
76 1 : poDataSource->RegisterLayer(poGSLayer);
77 1 : poDataSource->RegisterLayer(poMarkerLayer);
78 1 : poDataSource->RegisterLayer(poDMELayer);
79 1 : poDataSource->RegisterLayer(poDMEILSLayer);
80 1 : }
81 :
82 : /************************************************************************/
83 : /* CloneForLayer() */
84 : /************************************************************************/
85 :
86 0 : OGRXPlaneReader* OGRXPlaneNavReader::CloneForLayer(OGRXPlaneLayer* poLayer)
87 : {
88 0 : OGRXPlaneNavReader* poReader = new OGRXPlaneNavReader();
89 :
90 0 : poReader->poInterestLayer = poLayer;
91 :
92 0 : SET_IF_INTEREST_LAYER(poILSLayer);
93 0 : SET_IF_INTEREST_LAYER(poVORLayer);
94 0 : SET_IF_INTEREST_LAYER(poNDBLayer);
95 0 : SET_IF_INTEREST_LAYER(poGSLayer);
96 0 : SET_IF_INTEREST_LAYER(poMarkerLayer);
97 0 : SET_IF_INTEREST_LAYER(poDMELayer);
98 0 : SET_IF_INTEREST_LAYER(poDMEILSLayer);
99 :
100 0 : if (pszFilename)
101 : {
102 0 : poReader->pszFilename = CPLStrdup(pszFilename);
103 0 : poReader->fp = VSIFOpenL( pszFilename, "rb" );
104 : }
105 :
106 0 : return poReader;
107 : }
108 :
109 : /************************************************************************/
110 : /* IsRecognizedVersion() */
111 : /************************************************************************/
112 :
113 1 : int OGRXPlaneNavReader::IsRecognizedVersion( const char* pszVersionString)
114 : {
115 : return EQUALN(pszVersionString, "810 Version", 11) ||
116 1 : EQUALN(pszVersionString, "740 Version", 11);
117 : }
118 :
119 : /************************************************************************/
120 : /* Read() */
121 : /************************************************************************/
122 :
123 1 : void OGRXPlaneNavReader::Read()
124 : {
125 : const char* pszLine;
126 29 : while((pszLine = CPLReadLineL(fp)) != NULL)
127 : {
128 : int nType;
129 28 : papszTokens = CSLTokenizeString(pszLine);
130 28 : nTokens = CSLCount(papszTokens);
131 :
132 28 : nLineNumber ++;
133 :
134 28 : if (nTokens == 1 && strcmp(papszTokens[0], "99") == 0)
135 : {
136 1 : CSLDestroy(papszTokens);
137 1 : papszTokens = NULL;
138 1 : bEOF = TRUE;
139 1 : return;
140 : }
141 27 : else if (nTokens == 0 || assertMinCol(9) == FALSE)
142 : {
143 2 : CSLDestroy(papszTokens);
144 2 : papszTokens = NULL;
145 2 : continue;
146 : }
147 :
148 25 : nType = atoi(papszTokens[0]);
149 25 : if (!((nType >= NAVAID_NDB && nType <= NAVAID_IM) ||
150 : nType == NAVAID_DME_COLOC || nType == NAVAID_DME_STANDALONE))
151 : {
152 : CPLDebug("XPlane", "Line %d : bad feature code '%s'",
153 0 : nLineNumber, papszTokens[0]);
154 0 : CSLDestroy(papszTokens);
155 0 : papszTokens = NULL;
156 0 : continue;
157 : }
158 :
159 25 : ParseRecord(nType);
160 :
161 25 : CSLDestroy(papszTokens);
162 25 : papszTokens = NULL;
163 :
164 25 : if (poInterestLayer && poInterestLayer->IsEmpty() == FALSE)
165 0 : return;
166 : }
167 :
168 0 : papszTokens = NULL;
169 0 : bEOF = TRUE;
170 : }
171 :
172 : /************************************************************************/
173 : /* ParseRecord() */
174 : /************************************************************************/
175 :
176 25 : void OGRXPlaneNavReader::ParseRecord(int nType)
177 : {
178 : double dfVal, dfLat, dfLon, dfElevation, dfFrequency, dfRange;
179 25 : double dfSlavedVariation = 0, dfTrueHeading = 0,
180 25 : dfDMEBias = 0, dfSlope = 0;
181 : char* pszNavaidId;
182 :
183 25 : RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
184 :
185 : /* feet to meter */
186 24 : RET_IF_FAIL(readDoubleWithBoundsAndConversion(&dfElevation, 3, "elevation", FEET_TO_METER, -1000., 10000.));
187 :
188 24 : RET_IF_FAIL(readDouble(&dfFrequency, 4, "frequency"));
189 : /* NDB frequencies are in kHz. Others must be divided by 100 */
190 : /* to get a frequency in MHz */
191 24 : if (nType != NAVAID_NDB)
192 20 : dfFrequency /= 100.;
193 :
194 : /* nautical miles to kilometer */
195 24 : RET_IF_FAIL(readDouble(&dfRange, 5, "range"));
196 24 : dfRange *= NM_TO_KM;
197 :
198 24 : pszNavaidId = papszTokens[7];
199 :
200 24 : if (nType == NAVAID_NDB)
201 : {
202 4 : const char* pszSubType = "";
203 4 : CPLString osNavaidName;
204 11 : if (EQUAL(papszTokens[nTokens-1], "NDB") ||
205 2 : EQUAL(papszTokens[nTokens-1], "LOM") ||
206 1 : EQUAL(papszTokens[nTokens-1], "NDB-DME"))
207 : {
208 4 : pszSubType = papszTokens[nTokens-1];
209 4 : nTokens--;
210 : }
211 : else
212 : {
213 0 : CPLDebug("XPlane", "Unexpected NDB subtype : %s", papszTokens[nTokens-1]);
214 : }
215 :
216 4 : osNavaidName = readStringUntilEnd(8);
217 :
218 4 : if (poNDBLayer)
219 : poNDBLayer->AddFeature(pszNavaidId, osNavaidName, pszSubType,
220 : dfLat, dfLon,
221 4 : dfElevation, dfFrequency, dfRange);
222 : }
223 20 : else if (nType == NAVAID_VOR)
224 : {
225 3 : const char* pszSubType = "";
226 3 : CPLString osNavaidName;
227 :
228 3 : RET_IF_FAIL(readDoubleWithBounds(&dfSlavedVariation, 6, "slaved variation", -180., 180.));
229 :
230 9 : if (EQUAL(papszTokens[nTokens-1], "VOR") ||
231 2 : EQUAL(papszTokens[nTokens-1], "VORTAC") ||
232 1 : EQUAL(papszTokens[nTokens-1], "VOR-DME"))
233 : {
234 3 : pszSubType = papszTokens[nTokens-1];
235 3 : nTokens--;
236 : }
237 : else
238 : {
239 0 : CPLDebug("XPlane", "Unexpected VOR subtype : %s", papszTokens[nTokens-1]);
240 : }
241 :
242 3 : osNavaidName = readStringUntilEnd(8);
243 :
244 3 : if (poVORLayer)
245 : poVORLayer->AddFeature(pszNavaidId, osNavaidName, pszSubType,
246 : dfLat, dfLon,
247 3 : dfElevation, dfFrequency, dfRange, dfSlavedVariation);
248 : }
249 23 : else if (nType == NAVAID_LOC_ILS || nType == NAVAID_LOC_STANDALONE)
250 : {
251 : const char* pszAptICAO, * pszRwyNum, * pszSubType;
252 :
253 6 : RET_IF_FAIL(readDoubleWithBounds(&dfTrueHeading, 6, "true heading", 0., 360.));
254 :
255 6 : RET_IF_FAIL(assertMinCol(11));
256 :
257 6 : pszAptICAO = papszTokens[8];
258 6 : pszRwyNum = papszTokens[9];
259 6 : pszSubType = papszTokens[10];
260 :
261 6 : if (EQUAL(pszSubType, "ILS-cat-I") ||
262 : EQUAL(pszSubType, "ILS-cat-II") ||
263 : EQUAL(pszSubType, "ILS-cat-III") ||
264 : EQUAL(pszSubType, "LOC") ||
265 : EQUAL(pszSubType, "LDA") ||
266 : EQUAL(pszSubType, "SDF") ||
267 : EQUAL(pszSubType, "IGS") ||
268 : EQUAL(pszSubType, "LDA-GS"))
269 : {
270 6 : if (poILSLayer)
271 : poILSLayer->AddFeature(pszNavaidId, pszAptICAO, pszRwyNum, pszSubType,
272 : dfLat, dfLon,
273 6 : dfElevation, dfFrequency, dfRange, dfTrueHeading);
274 : }
275 : else
276 : {
277 : CPLDebug("XPlane", "Line %d : invalid localizer subtype: '%s'",
278 0 : nLineNumber, pszSubType);
279 0 : return;
280 : }
281 : }
282 11 : else if (nType == NAVAID_GS)
283 : {
284 : const char* pszAptICAO, * pszRwyNum, * pszSubType;
285 :
286 1 : RET_IF_FAIL(readDouble(&dfVal, 6, "slope & heading"));
287 1 : dfSlope = (int)(dfVal / 1000) / 100.;
288 1 : dfTrueHeading = dfVal - dfSlope * 100000;
289 1 : if (dfTrueHeading < 0 || dfTrueHeading > 360)
290 : {
291 : CPLDebug("XPlane", "Line %d : invalid true heading '%f'",
292 0 : nLineNumber, dfTrueHeading);
293 0 : return;
294 : }
295 :
296 1 : RET_IF_FAIL(assertMinCol(11));
297 :
298 1 : pszAptICAO = papszTokens[8];
299 1 : pszRwyNum = papszTokens[9];
300 1 : pszSubType = papszTokens[10];
301 :
302 1 : if (EQUAL(pszSubType, "GS") )
303 : {
304 1 : if (poGSLayer)
305 : poGSLayer->AddFeature(pszNavaidId, pszAptICAO, pszRwyNum,
306 : dfLat, dfLon,
307 1 : dfElevation, dfFrequency, dfRange, dfTrueHeading, dfSlope);
308 : }
309 : else
310 : {
311 : CPLDebug("XPlane", "Line %d : invalid glideslope subtype: '%s'",
312 0 : nLineNumber, pszSubType);
313 0 : return;
314 : }
315 : }
316 13 : else if (nType == NAVAID_OM || nType == NAVAID_MM || nType == NAVAID_IM)
317 : {
318 : const char* pszAptICAO, * pszRwyNum, * pszSubType;
319 :
320 3 : RET_IF_FAIL(readDoubleWithBounds(&dfTrueHeading, 6, "true heading", 0., 360.));
321 :
322 3 : RET_IF_FAIL(assertMinCol(11));
323 :
324 3 : pszAptICAO = papszTokens[8];
325 3 : pszRwyNum = papszTokens[9];
326 3 : pszSubType = papszTokens[10];
327 :
328 3 : if (EQUAL(pszSubType, "OM") ||
329 : EQUAL(pszSubType, "MM") ||
330 : EQUAL(pszSubType, "IM") )
331 : {
332 3 : if (poMarkerLayer)
333 : poMarkerLayer->AddFeature(pszAptICAO, pszRwyNum, pszSubType,
334 : dfLat, dfLon,
335 3 : dfElevation, dfTrueHeading);
336 : }
337 : else
338 : {
339 : CPLDebug("XPlane", "Line %d : invalid localizer marker subtype: '%s'",
340 0 : nLineNumber, pszSubType);
341 0 : return;
342 : }
343 : }
344 14 : else if (nType == NAVAID_DME_COLOC || nType == NAVAID_DME_STANDALONE)
345 : {
346 7 : const char* pszSubType = "";
347 7 : CPLString osNavaidName;
348 :
349 7 : RET_IF_FAIL(readDouble(&dfDMEBias, 6, "DME bias"));
350 7 : dfDMEBias *= NM_TO_KM;
351 :
352 7 : if (EQUAL(papszTokens[nTokens-1], "DME-ILS"))
353 : {
354 : char* pszAptICAO, * pszRwyNum, * pszSubType;
355 1 : if (nTokens != 11)
356 : {
357 : CPLDebug("XPlane", "Line %d : not enough columns : %d",
358 0 : nLineNumber, nTokens);
359 : return;
360 : }
361 :
362 1 : pszAptICAO = papszTokens[8];
363 1 : pszRwyNum = papszTokens[9];
364 1 : pszSubType = papszTokens[10];
365 :
366 1 : if (poDMEILSLayer)
367 : poDMEILSLayer->AddFeature(pszNavaidId, pszAptICAO, pszRwyNum,
368 : dfLat, dfLon,
369 1 : dfElevation, dfFrequency, dfRange, dfDMEBias);
370 : }
371 : else
372 : {
373 6 : if (EQUAL(papszTokens[nTokens-1], "DME"))
374 : {
375 6 : nTokens--;
376 17 : if (EQUAL(papszTokens[nTokens-1], "VORTAC") ||
377 5 : EQUAL(papszTokens[nTokens-1], "VOR-DME") ||
378 4 : EQUAL(papszTokens[nTokens-1], "TACAN") ||
379 2 : EQUAL(papszTokens[nTokens-1], "NDB-DME"))
380 : {
381 5 : pszSubType = papszTokens[nTokens-1];
382 5 : nTokens--;
383 : }
384 : }
385 : else
386 : {
387 : CPLDebug("XPlane", "Line %d : Unexpected DME subtype : %s",
388 0 : nLineNumber, papszTokens[nTokens-1]);
389 : }
390 :
391 6 : osNavaidName = readStringUntilEnd(8);
392 :
393 6 : if (poDMELayer)
394 : poDMELayer->AddFeature(pszNavaidId, osNavaidName, pszSubType,
395 : dfLat, dfLon,
396 6 : dfElevation, dfFrequency, dfRange, dfDMEBias);
397 0 : }
398 : }
399 : else
400 : {
401 0 : CPLAssert(0);
402 : }
403 :
404 : }
405 :
406 :
407 : /************************************************************************/
408 : /* OGRXPlaneILSLayer() */
409 : /************************************************************************/
410 :
411 1 : OGRXPlaneILSLayer::OGRXPlaneILSLayer() : OGRXPlaneLayer("ILS")
412 : {
413 1 : poFeatureDefn->SetGeomType( wkbPoint );
414 :
415 1 : OGRFieldDefn oFieldID("navaid_id", OFTString );
416 1 : oFieldID.SetWidth( 4 );
417 1 : poFeatureDefn->AddFieldDefn( &oFieldID );
418 :
419 1 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
420 1 : oFieldAptICAO.SetWidth( 4 );
421 1 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
422 :
423 1 : OGRFieldDefn oFieldRwyNum("rwy_num", OFTString );
424 1 : oFieldRwyNum.SetWidth( 3 );
425 1 : poFeatureDefn->AddFieldDefn( &oFieldRwyNum );
426 :
427 1 : OGRFieldDefn oFieldSubType("subtype", OFTString );
428 1 : oFieldSubType.SetWidth( 10 );
429 1 : poFeatureDefn->AddFieldDefn( &oFieldSubType );
430 :
431 1 : OGRFieldDefn oFieldElev("elevation_m", OFTReal );
432 1 : oFieldElev.SetWidth( 8 );
433 1 : oFieldElev.SetPrecision( 2 );
434 1 : poFeatureDefn->AddFieldDefn( &oFieldElev );
435 :
436 1 : OGRFieldDefn oFieldFreq("freq_mhz", OFTReal );
437 1 : oFieldFreq.SetWidth( 7 );
438 1 : oFieldFreq.SetPrecision( 3 );
439 1 : poFeatureDefn->AddFieldDefn( &oFieldFreq );
440 :
441 1 : OGRFieldDefn oFieldRange("range_km", OFTReal );
442 1 : oFieldRange.SetWidth( 7 );
443 1 : oFieldRange.SetPrecision( 3 );
444 1 : poFeatureDefn->AddFieldDefn( &oFieldRange );
445 :
446 1 : OGRFieldDefn oFieldTrueHeading("true_heading_deg", OFTReal );
447 1 : oFieldTrueHeading.SetWidth( 6 );
448 1 : oFieldTrueHeading.SetPrecision( 2 );
449 1 : poFeatureDefn->AddFieldDefn( &oFieldTrueHeading );
450 1 : }
451 :
452 : /************************************************************************/
453 : /* AddFeature() */
454 : /************************************************************************/
455 :
456 : OGRFeature*
457 6 : OGRXPlaneILSLayer::AddFeature(const char* pszNavaidID,
458 : const char* pszAptICAO,
459 : const char* pszRwyNum,
460 : const char* pszSubType,
461 : double dfLat,
462 : double dfLon,
463 : double dfEle,
464 : double dfFreq,
465 : double dfRange,
466 : double dfTrueHeading)
467 : {
468 6 : int nCount = 0;
469 6 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
470 12 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
471 6 : poFeature->SetField( nCount++, pszNavaidID );
472 6 : poFeature->SetField( nCount++, pszAptICAO );
473 6 : poFeature->SetField( nCount++, pszRwyNum );
474 6 : poFeature->SetField( nCount++, pszSubType );
475 6 : poFeature->SetField( nCount++, dfEle );
476 6 : poFeature->SetField( nCount++, dfFreq );
477 6 : poFeature->SetField( nCount++, dfRange );
478 6 : poFeature->SetField( nCount++, dfTrueHeading );
479 :
480 6 : RegisterFeature(poFeature);
481 :
482 6 : return poFeature;
483 : }
484 :
485 : /************************************************************************/
486 : /* OGRXPlaneVORLayer() */
487 : /************************************************************************/
488 :
489 :
490 1 : OGRXPlaneVORLayer::OGRXPlaneVORLayer() : OGRXPlaneLayer("VOR")
491 : {
492 1 : poFeatureDefn->SetGeomType( wkbPoint );
493 :
494 1 : OGRFieldDefn oFieldID("navaid_id", OFTString );
495 1 : oFieldID.SetWidth( 4 );
496 1 : poFeatureDefn->AddFieldDefn( &oFieldID );
497 :
498 1 : OGRFieldDefn oFieldName("navaid_name", OFTString );
499 1 : poFeatureDefn->AddFieldDefn( &oFieldName );
500 :
501 1 : OGRFieldDefn oFieldSubType("subtype", OFTString );
502 1 : oFieldSubType.SetWidth( 10 );
503 1 : poFeatureDefn->AddFieldDefn( &oFieldSubType );
504 :
505 1 : OGRFieldDefn oFieldElev("elevation_m", OFTReal );
506 1 : oFieldElev.SetWidth( 8 );
507 1 : oFieldElev.SetPrecision( 2 );
508 1 : poFeatureDefn->AddFieldDefn( &oFieldElev );
509 :
510 1 : OGRFieldDefn oFieldFreq("freq_mhz", OFTReal );
511 1 : oFieldFreq.SetWidth( 7 );
512 1 : oFieldFreq.SetPrecision( 3 );
513 1 : poFeatureDefn->AddFieldDefn( &oFieldFreq );
514 :
515 1 : OGRFieldDefn oFieldRange("range_km", OFTReal );
516 1 : oFieldRange.SetWidth( 7 );
517 1 : oFieldRange.SetPrecision( 3 );
518 1 : poFeatureDefn->AddFieldDefn( &oFieldRange );
519 :
520 1 : OGRFieldDefn oFieldSlavedVariation("slaved_variation_deg", OFTReal );
521 1 : oFieldSlavedVariation.SetWidth( 6 );
522 1 : oFieldSlavedVariation.SetPrecision( 2 );
523 1 : poFeatureDefn->AddFieldDefn( &oFieldSlavedVariation );
524 1 : }
525 :
526 : /************************************************************************/
527 : /* AddFeature() */
528 : /************************************************************************/
529 :
530 : OGRFeature*
531 3 : OGRXPlaneVORLayer::AddFeature(const char* pszNavaidID,
532 : const char* pszNavaidName,
533 : const char* pszSubType,
534 : double dfLat,
535 : double dfLon,
536 : double dfEle,
537 : double dfFreq,
538 : double dfRange,
539 : double dfSlavedVariation)
540 : {
541 3 : int nCount = 0;
542 3 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
543 6 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
544 3 : poFeature->SetField( nCount++, pszNavaidID );
545 3 : poFeature->SetField( nCount++, pszNavaidName );
546 3 : poFeature->SetField( nCount++, pszSubType );
547 3 : poFeature->SetField( nCount++, dfEle );
548 3 : poFeature->SetField( nCount++, dfFreq );
549 3 : poFeature->SetField( nCount++, dfRange );
550 3 : poFeature->SetField( nCount++, dfSlavedVariation );
551 :
552 3 : RegisterFeature(poFeature);
553 :
554 3 : return poFeature;
555 : }
556 :
557 : /************************************************************************/
558 : /* OGRXPlaneNDBLayer() */
559 : /************************************************************************/
560 :
561 1 : OGRXPlaneNDBLayer::OGRXPlaneNDBLayer() : OGRXPlaneLayer("NDB")
562 : {
563 1 : poFeatureDefn->SetGeomType( wkbPoint );
564 :
565 1 : OGRFieldDefn oFieldID("navaid_id", OFTString );
566 1 : oFieldID.SetWidth( 4 );
567 1 : poFeatureDefn->AddFieldDefn( &oFieldID );
568 :
569 1 : OGRFieldDefn oFieldName("navaid_name", OFTString );
570 1 : poFeatureDefn->AddFieldDefn( &oFieldName );
571 :
572 1 : OGRFieldDefn oFieldSubType("subtype", OFTString );
573 1 : oFieldSubType.SetWidth( 10 );
574 1 : poFeatureDefn->AddFieldDefn( &oFieldSubType );
575 :
576 1 : OGRFieldDefn oFieldElev("elevation_m", OFTReal );
577 1 : oFieldElev.SetWidth( 8 );
578 1 : oFieldElev.SetPrecision( 2 );
579 1 : poFeatureDefn->AddFieldDefn( &oFieldElev );
580 :
581 1 : OGRFieldDefn oFieldFreq("freq_khz", OFTReal );
582 1 : oFieldFreq.SetWidth( 7 );
583 1 : oFieldFreq.SetPrecision( 3 );
584 1 : poFeatureDefn->AddFieldDefn( &oFieldFreq );
585 :
586 1 : OGRFieldDefn oFieldRange("range_km", OFTReal );
587 1 : oFieldRange.SetWidth( 7 );
588 1 : oFieldRange.SetPrecision( 3 );
589 1 : poFeatureDefn->AddFieldDefn( &oFieldRange );
590 1 : }
591 :
592 : /************************************************************************/
593 : /* AddFeature() */
594 : /************************************************************************/
595 :
596 : OGRFeature*
597 4 : OGRXPlaneNDBLayer::AddFeature(const char* pszNavaidID,
598 : const char* pszNavaidName,
599 : const char* pszSubType,
600 : double dfLat,
601 : double dfLon,
602 : double dfEle,
603 : double dfFreq,
604 : double dfRange)
605 : {
606 4 : int nCount = 0;
607 4 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
608 8 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
609 4 : poFeature->SetField( nCount++, pszNavaidID );
610 4 : poFeature->SetField( nCount++, pszNavaidName );
611 4 : poFeature->SetField( nCount++, pszSubType );
612 4 : poFeature->SetField( nCount++, dfEle );
613 4 : poFeature->SetField( nCount++, dfFreq );
614 4 : poFeature->SetField( nCount++, dfRange );
615 :
616 4 : RegisterFeature(poFeature);
617 :
618 4 : return poFeature;
619 : }
620 :
621 : /************************************************************************/
622 : /* OGRXPlaneGSLayer */
623 : /************************************************************************/
624 :
625 1 : OGRXPlaneGSLayer::OGRXPlaneGSLayer() : OGRXPlaneLayer("GS")
626 : {
627 1 : poFeatureDefn->SetGeomType( wkbPoint );
628 :
629 1 : OGRFieldDefn oFieldID("navaid_id", OFTString );
630 1 : oFieldID.SetWidth( 4 );
631 1 : poFeatureDefn->AddFieldDefn( &oFieldID );
632 :
633 1 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
634 1 : oFieldAptICAO.SetWidth( 4 );
635 1 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
636 :
637 1 : OGRFieldDefn oFieldRwyNum("rwy_num", OFTString );
638 1 : oFieldRwyNum.SetWidth( 3 );
639 1 : poFeatureDefn->AddFieldDefn( &oFieldRwyNum );
640 :
641 1 : OGRFieldDefn oFieldElev("elevation_m", OFTReal );
642 1 : oFieldElev.SetWidth( 8 );
643 1 : oFieldElev.SetPrecision( 2 );
644 1 : poFeatureDefn->AddFieldDefn( &oFieldElev );
645 :
646 1 : OGRFieldDefn oFieldFreq("freq_mhz", OFTReal );
647 1 : oFieldFreq.SetWidth( 7 );
648 1 : oFieldFreq.SetPrecision( 3 );
649 1 : poFeatureDefn->AddFieldDefn( &oFieldFreq );
650 :
651 1 : OGRFieldDefn oFieldRange("range_km", OFTReal );
652 1 : oFieldRange.SetWidth( 7 );
653 1 : oFieldRange.SetPrecision( 3 );
654 1 : poFeatureDefn->AddFieldDefn( &oFieldRange );
655 :
656 1 : OGRFieldDefn oFieldTrueHeading("true_heading_deg", OFTReal );
657 1 : oFieldTrueHeading.SetWidth( 6 );
658 1 : oFieldTrueHeading.SetPrecision( 2 );
659 1 : poFeatureDefn->AddFieldDefn( &oFieldTrueHeading );
660 :
661 1 : OGRFieldDefn oFieldGlideSlope("glide_slope", OFTReal );
662 1 : oFieldGlideSlope.SetWidth( 6 );
663 1 : oFieldGlideSlope.SetPrecision( 2 );
664 1 : poFeatureDefn->AddFieldDefn( &oFieldGlideSlope );
665 1 : }
666 :
667 : /************************************************************************/
668 : /* AddFeature() */
669 : /************************************************************************/
670 :
671 : OGRFeature*
672 1 : OGRXPlaneGSLayer::AddFeature(const char* pszNavaidID,
673 : const char* pszAptICAO,
674 : const char* pszRwyNum,
675 : double dfLat,
676 : double dfLon,
677 : double dfEle,
678 : double dfFreq,
679 : double dfRange,
680 : double dfTrueHeading,
681 : double dfSlope)
682 : {
683 1 : int nCount = 0;
684 1 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
685 2 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
686 1 : poFeature->SetField( nCount++, pszNavaidID );
687 1 : poFeature->SetField( nCount++, pszAptICAO );
688 1 : poFeature->SetField( nCount++, pszRwyNum );
689 1 : poFeature->SetField( nCount++, dfEle );
690 1 : poFeature->SetField( nCount++, dfFreq );
691 1 : poFeature->SetField( nCount++, dfRange );
692 1 : poFeature->SetField( nCount++, dfTrueHeading );
693 1 : poFeature->SetField( nCount++, dfSlope );
694 :
695 1 : RegisterFeature(poFeature);
696 :
697 1 : return poFeature;
698 : }
699 :
700 :
701 : /************************************************************************/
702 : /* OGRXPlaneMarkerLayer */
703 : /************************************************************************/
704 :
705 1 : OGRXPlaneMarkerLayer::OGRXPlaneMarkerLayer() : OGRXPlaneLayer("Marker")
706 : {
707 1 : poFeatureDefn->SetGeomType( wkbPoint );
708 :
709 1 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
710 1 : oFieldAptICAO.SetWidth( 4 );
711 1 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
712 :
713 1 : OGRFieldDefn oFieldRwyNum("rwy_num", OFTString );
714 1 : oFieldRwyNum.SetWidth( 3 );
715 1 : poFeatureDefn->AddFieldDefn( &oFieldRwyNum );
716 :
717 1 : OGRFieldDefn oFieldSubType("subtype", OFTString );
718 1 : oFieldSubType.SetWidth( 10 );
719 1 : poFeatureDefn->AddFieldDefn( &oFieldSubType );
720 :
721 1 : OGRFieldDefn oFieldElev("elevation_m", OFTReal );
722 1 : oFieldElev.SetWidth( 8 );
723 1 : oFieldElev.SetPrecision( 2 );
724 1 : poFeatureDefn->AddFieldDefn( &oFieldElev );
725 :
726 1 : OGRFieldDefn oFieldTrueHeading("true_heading_deg", OFTReal );
727 1 : oFieldTrueHeading.SetWidth( 6 );
728 1 : oFieldTrueHeading.SetPrecision( 2 );
729 1 : poFeatureDefn->AddFieldDefn( &oFieldTrueHeading );
730 1 : }
731 :
732 : /************************************************************************/
733 : /* AddFeature() */
734 : /************************************************************************/
735 :
736 : OGRFeature*
737 3 : OGRXPlaneMarkerLayer::AddFeature(const char* pszAptICAO,
738 : const char* pszRwyNum,
739 : const char* pszSubType,
740 : double dfLat,
741 : double dfLon,
742 : double dfEle,
743 : double dfTrueHeading)
744 : {
745 3 : int nCount = 0;
746 3 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
747 6 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
748 3 : poFeature->SetField( nCount++, pszAptICAO );
749 3 : poFeature->SetField( nCount++, pszRwyNum );
750 3 : poFeature->SetField( nCount++, pszSubType );
751 3 : poFeature->SetField( nCount++, dfEle );
752 3 : poFeature->SetField( nCount++, dfTrueHeading );
753 :
754 3 : RegisterFeature(poFeature);
755 :
756 3 : return poFeature;
757 : }
758 :
759 : /************************************************************************/
760 : /* OGRXPlaneDMEILSLayer */
761 : /************************************************************************/
762 :
763 1 : OGRXPlaneDMEILSLayer::OGRXPlaneDMEILSLayer() : OGRXPlaneLayer("DMEILS")
764 : {
765 1 : poFeatureDefn->SetGeomType( wkbPoint );
766 :
767 1 : OGRFieldDefn oFieldID("navaid_id", OFTString );
768 1 : oFieldID.SetWidth( 4 );
769 1 : poFeatureDefn->AddFieldDefn( &oFieldID );
770 :
771 1 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
772 1 : oFieldAptICAO.SetWidth( 4 );
773 1 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
774 :
775 1 : OGRFieldDefn oFieldRwyNum("rwy_num", OFTString );
776 1 : oFieldRwyNum.SetWidth( 3 );
777 1 : poFeatureDefn->AddFieldDefn( &oFieldRwyNum );
778 :
779 1 : OGRFieldDefn oFieldElev("elevation_m", OFTReal );
780 1 : oFieldElev.SetWidth( 8 );
781 1 : oFieldElev.SetPrecision( 2 );
782 1 : poFeatureDefn->AddFieldDefn( &oFieldElev );
783 :
784 1 : OGRFieldDefn oFieldFreq("freq_mhz", OFTReal );
785 1 : oFieldFreq.SetWidth( 7 );
786 1 : oFieldFreq.SetPrecision( 3 );
787 1 : poFeatureDefn->AddFieldDefn( &oFieldFreq );
788 :
789 1 : OGRFieldDefn oFieldRange("range_km", OFTReal );
790 1 : oFieldRange.SetWidth( 7 );
791 1 : oFieldRange.SetPrecision( 3 );
792 1 : poFeatureDefn->AddFieldDefn( &oFieldRange );
793 :
794 1 : OGRFieldDefn oFieldBias("bias_km", OFTReal );
795 1 : oFieldBias.SetWidth( 6 );
796 1 : oFieldBias.SetPrecision( 2 );
797 1 : poFeatureDefn->AddFieldDefn( &oFieldBias );
798 1 : }
799 :
800 : /************************************************************************/
801 : /* AddFeature() */
802 : /************************************************************************/
803 :
804 : OGRFeature*
805 1 : OGRXPlaneDMEILSLayer::AddFeature(const char* pszNavaidID,
806 : const char* pszAptICAO,
807 : const char* pszRwyNum,
808 : double dfLat,
809 : double dfLon,
810 : double dfEle,
811 : double dfFreq,
812 : double dfRange,
813 : double dfBias)
814 : {
815 1 : int nCount = 0;
816 1 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
817 2 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
818 1 : poFeature->SetField( nCount++, pszNavaidID );
819 1 : poFeature->SetField( nCount++, pszAptICAO );
820 1 : poFeature->SetField( nCount++, pszRwyNum );
821 1 : poFeature->SetField( nCount++, dfEle );
822 1 : poFeature->SetField( nCount++, dfFreq );
823 1 : poFeature->SetField( nCount++, dfRange );
824 1 : poFeature->SetField( nCount++, dfBias );
825 :
826 1 : RegisterFeature(poFeature);
827 :
828 1 : return poFeature;
829 : }
830 :
831 : /************************************************************************/
832 : /* OGRXPlaneDMELayer */
833 : /************************************************************************/
834 :
835 :
836 1 : OGRXPlaneDMELayer::OGRXPlaneDMELayer() : OGRXPlaneLayer("DME")
837 : {
838 1 : poFeatureDefn->SetGeomType( wkbPoint );
839 :
840 1 : OGRFieldDefn oFieldID("navaid_id", OFTString );
841 1 : oFieldID.SetWidth( 4 );
842 1 : poFeatureDefn->AddFieldDefn( &oFieldID );
843 :
844 1 : OGRFieldDefn oFieldName("navaid_name", OFTString );
845 1 : poFeatureDefn->AddFieldDefn( &oFieldName );
846 :
847 1 : OGRFieldDefn oFieldSubType("subtype", OFTString );
848 1 : oFieldSubType.SetWidth( 10 );
849 1 : poFeatureDefn->AddFieldDefn( &oFieldSubType );
850 :
851 1 : OGRFieldDefn oFieldElev("elevation_m", OFTReal );
852 1 : oFieldElev.SetWidth( 8 );
853 1 : oFieldElev.SetPrecision( 2 );
854 1 : poFeatureDefn->AddFieldDefn( &oFieldElev );
855 :
856 1 : OGRFieldDefn oFieldFreq("freq_mhz", OFTReal );
857 1 : oFieldFreq.SetWidth( 7 );
858 1 : oFieldFreq.SetPrecision( 3 );
859 1 : poFeatureDefn->AddFieldDefn( &oFieldFreq );
860 :
861 1 : OGRFieldDefn oFieldRange("range_km", OFTReal );
862 1 : oFieldRange.SetWidth( 7 );
863 1 : oFieldRange.SetPrecision( 3 );
864 1 : poFeatureDefn->AddFieldDefn( &oFieldRange );
865 :
866 1 : OGRFieldDefn oFieldBias("bias_km", OFTReal );
867 1 : oFieldBias.SetWidth( 6 );
868 1 : oFieldBias.SetPrecision( 2 );
869 1 : poFeatureDefn->AddFieldDefn( &oFieldBias );
870 1 : }
871 :
872 : /************************************************************************/
873 : /* AddFeature() */
874 : /************************************************************************/
875 :
876 : OGRFeature*
877 6 : OGRXPlaneDMELayer::AddFeature(const char* pszNavaidID,
878 : const char* pszNavaidName,
879 : const char* pszSubType,
880 : double dfLat,
881 : double dfLon,
882 : double dfEle,
883 : double dfFreq,
884 : double dfRange,
885 : double dfBias)
886 : {
887 6 : int nCount = 0;
888 6 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
889 12 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
890 6 : poFeature->SetField( nCount++, pszNavaidID );
891 6 : poFeature->SetField( nCount++, pszNavaidName );
892 6 : poFeature->SetField( nCount++, pszSubType );
893 6 : poFeature->SetField( nCount++, dfEle );
894 6 : poFeature->SetField( nCount++, dfFreq );
895 6 : poFeature->SetField( nCount++, dfRange );
896 6 : poFeature->SetField( nCount++, dfBias );
897 :
898 6 : RegisterFeature(poFeature);
899 :
900 6 : return poFeature;
901 : }
|