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 2 : OGRXPlaneReader* OGRXPlaneCreateNavFileReader( OGRXPlaneDataSource* poDataSource )
39 : {
40 2 : OGRXPlaneReader* poReader = new OGRXPlaneNavReader(poDataSource);
41 2 : 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 2 : OGRXPlaneNavReader::OGRXPlaneNavReader( OGRXPlaneDataSource* poDataSource )
64 : {
65 2 : poILSLayer = new OGRXPlaneILSLayer();
66 4 : poVORLayer = new OGRXPlaneVORLayer();
67 4 : poNDBLayer = new OGRXPlaneNDBLayer();
68 4 : poGSLayer = new OGRXPlaneGSLayer();
69 4 : poMarkerLayer = new OGRXPlaneMarkerLayer();
70 4 : poDMELayer = new OGRXPlaneDMELayer();
71 4 : poDMEILSLayer = new OGRXPlaneDMEILSLayer();
72 :
73 2 : poDataSource->RegisterLayer(poILSLayer);
74 2 : poDataSource->RegisterLayer(poVORLayer);
75 2 : poDataSource->RegisterLayer(poNDBLayer);
76 2 : poDataSource->RegisterLayer(poGSLayer);
77 2 : poDataSource->RegisterLayer(poMarkerLayer);
78 2 : poDataSource->RegisterLayer(poDMELayer);
79 2 : poDataSource->RegisterLayer(poDMEILSLayer);
80 2 : }
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 2 : int OGRXPlaneNavReader::IsRecognizedVersion( const char* pszVersionString)
114 : {
115 : return EQUALN(pszVersionString, "810 Version", 11) ||
116 2 : EQUALN(pszVersionString, "740 Version", 11);
117 : }
118 :
119 : /************************************************************************/
120 : /* Read() */
121 : /************************************************************************/
122 :
123 2 : void OGRXPlaneNavReader::Read()
124 : {
125 : const char* pszLine;
126 58 : while((pszLine = CPLReadLineL(fp)) != NULL)
127 : {
128 : int nType;
129 56 : papszTokens = CSLTokenizeString(pszLine);
130 56 : nTokens = CSLCount(papszTokens);
131 :
132 56 : nLineNumber ++;
133 :
134 56 : if (nTokens == 1 && strcmp(papszTokens[0], "99") == 0)
135 : {
136 2 : CSLDestroy(papszTokens);
137 2 : papszTokens = NULL;
138 2 : bEOF = TRUE;
139 2 : return;
140 : }
141 54 : else if (nTokens == 0 || assertMinCol(9) == FALSE)
142 : {
143 4 : CSLDestroy(papszTokens);
144 4 : papszTokens = NULL;
145 4 : continue;
146 : }
147 :
148 50 : nType = atoi(papszTokens[0]);
149 50 : 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 50 : ParseRecord(nType);
160 :
161 50 : CSLDestroy(papszTokens);
162 50 : papszTokens = NULL;
163 :
164 50 : 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 50 : void OGRXPlaneNavReader::ParseRecord(int nType)
177 : {
178 : double dfVal, dfLat, dfLon, dfElevation, dfFrequency, dfRange;
179 50 : double dfSlavedVariation = 0, dfTrueHeading = 0,
180 50 : dfDMEBias = 0, dfSlope = 0;
181 : char* pszNavaidId;
182 :
183 50 : RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
184 :
185 : /* feet to meter */
186 48 : RET_IF_FAIL(readDoubleWithBoundsAndConversion(&dfElevation, 3, "elevation", FEET_TO_METER, -1000., 10000.));
187 :
188 48 : 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 48 : if (nType != NAVAID_NDB)
192 40 : dfFrequency /= 100.;
193 :
194 : /* nautical miles to kilometer */
195 48 : RET_IF_FAIL(readDouble(&dfRange, 5, "range"));
196 48 : dfRange *= NM_TO_KM;
197 :
198 48 : pszNavaidId = papszTokens[7];
199 :
200 48 : if (nType == NAVAID_NDB)
201 : {
202 8 : const char* pszSubType = "";
203 8 : CPLString osNavaidName;
204 22 : if (EQUAL(papszTokens[nTokens-1], "NDB") ||
205 4 : EQUAL(papszTokens[nTokens-1], "LOM") ||
206 2 : EQUAL(papszTokens[nTokens-1], "NDB-DME"))
207 : {
208 8 : pszSubType = papszTokens[nTokens-1];
209 8 : nTokens--;
210 : }
211 : else
212 : {
213 0 : CPLDebug("XPlane", "Unexpected NDB subtype : %s", papszTokens[nTokens-1]);
214 : }
215 :
216 8 : osNavaidName = readStringUntilEnd(8);
217 :
218 8 : if (poNDBLayer)
219 : poNDBLayer->AddFeature(pszNavaidId, osNavaidName, pszSubType,
220 : dfLat, dfLon,
221 8 : dfElevation, dfFrequency, dfRange);
222 : }
223 40 : else if (nType == NAVAID_VOR)
224 : {
225 6 : const char* pszSubType = "";
226 6 : CPLString osNavaidName;
227 :
228 6 : RET_IF_FAIL(readDoubleWithBounds(&dfSlavedVariation, 6, "slaved variation", -180., 180.));
229 :
230 18 : if (EQUAL(papszTokens[nTokens-1], "VOR") ||
231 4 : EQUAL(papszTokens[nTokens-1], "VORTAC") ||
232 2 : EQUAL(papszTokens[nTokens-1], "VOR-DME"))
233 : {
234 6 : pszSubType = papszTokens[nTokens-1];
235 6 : nTokens--;
236 : }
237 : else
238 : {
239 0 : CPLDebug("XPlane", "Unexpected VOR subtype : %s", papszTokens[nTokens-1]);
240 : }
241 :
242 6 : osNavaidName = readStringUntilEnd(8);
243 :
244 6 : if (poVORLayer)
245 : poVORLayer->AddFeature(pszNavaidId, osNavaidName, pszSubType,
246 : dfLat, dfLon,
247 6 : dfElevation, dfFrequency, dfRange, dfSlavedVariation);
248 : }
249 46 : else if (nType == NAVAID_LOC_ILS || nType == NAVAID_LOC_STANDALONE)
250 : {
251 : const char* pszAptICAO, * pszRwyNum, * pszSubType;
252 :
253 12 : RET_IF_FAIL(readDoubleWithBounds(&dfTrueHeading, 6, "true heading", 0., 360.));
254 :
255 12 : RET_IF_FAIL(assertMinCol(11));
256 :
257 12 : pszAptICAO = papszTokens[8];
258 12 : pszRwyNum = papszTokens[9];
259 12 : pszSubType = papszTokens[10];
260 :
261 12 : 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 12 : if (poILSLayer)
271 : poILSLayer->AddFeature(pszNavaidId, pszAptICAO, pszRwyNum, pszSubType,
272 : dfLat, dfLon,
273 12 : 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 22 : else if (nType == NAVAID_GS)
283 : {
284 : const char* pszAptICAO, * pszRwyNum, * pszSubType;
285 :
286 2 : RET_IF_FAIL(readDouble(&dfVal, 6, "slope & heading"));
287 2 : dfSlope = (int)(dfVal / 1000) / 100.;
288 2 : dfTrueHeading = dfVal - dfSlope * 100000;
289 2 : 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 2 : RET_IF_FAIL(assertMinCol(11));
297 :
298 2 : pszAptICAO = papszTokens[8];
299 2 : pszRwyNum = papszTokens[9];
300 2 : pszSubType = papszTokens[10];
301 :
302 2 : if (EQUAL(pszSubType, "GS") )
303 : {
304 2 : if (poGSLayer)
305 : poGSLayer->AddFeature(pszNavaidId, pszAptICAO, pszRwyNum,
306 : dfLat, dfLon,
307 2 : 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 26 : else if (nType == NAVAID_OM || nType == NAVAID_MM || nType == NAVAID_IM)
317 : {
318 : const char* pszAptICAO, * pszRwyNum, * pszSubType;
319 :
320 6 : RET_IF_FAIL(readDoubleWithBounds(&dfTrueHeading, 6, "true heading", 0., 360.));
321 :
322 6 : RET_IF_FAIL(assertMinCol(11));
323 :
324 6 : pszAptICAO = papszTokens[8];
325 6 : pszRwyNum = papszTokens[9];
326 6 : pszSubType = papszTokens[10];
327 :
328 6 : if (EQUAL(pszSubType, "OM") ||
329 : EQUAL(pszSubType, "MM") ||
330 : EQUAL(pszSubType, "IM") )
331 : {
332 6 : if (poMarkerLayer)
333 : poMarkerLayer->AddFeature(pszAptICAO, pszRwyNum, pszSubType,
334 : dfLat, dfLon,
335 6 : 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 28 : else if (nType == NAVAID_DME_COLOC || nType == NAVAID_DME_STANDALONE)
345 : {
346 14 : const char* pszSubType = "";
347 14 : CPLString osNavaidName;
348 :
349 14 : RET_IF_FAIL(readDouble(&dfDMEBias, 6, "DME bias"));
350 14 : dfDMEBias *= NM_TO_KM;
351 :
352 14 : if (EQUAL(papszTokens[nTokens-1], "DME-ILS"))
353 : {
354 : char* pszAptICAO, * pszRwyNum, * pszSubType;
355 2 : if (nTokens != 11)
356 : {
357 : CPLDebug("XPlane", "Line %d : not enough columns : %d",
358 0 : nLineNumber, nTokens);
359 : return;
360 : }
361 :
362 2 : pszAptICAO = papszTokens[8];
363 2 : pszRwyNum = papszTokens[9];
364 2 : pszSubType = papszTokens[10];
365 :
366 2 : if (poDMEILSLayer)
367 : poDMEILSLayer->AddFeature(pszNavaidId, pszAptICAO, pszRwyNum,
368 : dfLat, dfLon,
369 2 : dfElevation, dfFrequency, dfRange, dfDMEBias);
370 : }
371 : else
372 : {
373 12 : if (EQUAL(papszTokens[nTokens-1], "DME"))
374 : {
375 12 : nTokens--;
376 34 : if (EQUAL(papszTokens[nTokens-1], "VORTAC") ||
377 10 : EQUAL(papszTokens[nTokens-1], "VOR-DME") ||
378 8 : EQUAL(papszTokens[nTokens-1], "TACAN") ||
379 4 : EQUAL(papszTokens[nTokens-1], "NDB-DME"))
380 : {
381 10 : pszSubType = papszTokens[nTokens-1];
382 10 : nTokens--;
383 : }
384 : }
385 : else
386 : {
387 : CPLDebug("XPlane", "Line %d : Unexpected DME subtype : %s",
388 0 : nLineNumber, papszTokens[nTokens-1]);
389 : }
390 :
391 12 : osNavaidName = readStringUntilEnd(8);
392 :
393 12 : if (poDMELayer)
394 : poDMELayer->AddFeature(pszNavaidId, osNavaidName, pszSubType,
395 : dfLat, dfLon,
396 12 : 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 2 : OGRXPlaneILSLayer::OGRXPlaneILSLayer() : OGRXPlaneLayer("ILS")
412 : {
413 2 : poFeatureDefn->SetGeomType( wkbPoint );
414 :
415 2 : OGRFieldDefn oFieldID("navaid_id", OFTString );
416 2 : oFieldID.SetWidth( 4 );
417 2 : poFeatureDefn->AddFieldDefn( &oFieldID );
418 :
419 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
420 2 : oFieldAptICAO.SetWidth( 4 );
421 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
422 :
423 2 : OGRFieldDefn oFieldRwyNum("rwy_num", OFTString );
424 2 : oFieldRwyNum.SetWidth( 3 );
425 2 : poFeatureDefn->AddFieldDefn( &oFieldRwyNum );
426 :
427 2 : OGRFieldDefn oFieldSubType("subtype", OFTString );
428 2 : oFieldSubType.SetWidth( 10 );
429 2 : poFeatureDefn->AddFieldDefn( &oFieldSubType );
430 :
431 2 : OGRFieldDefn oFieldElev("elevation_m", OFTReal );
432 2 : oFieldElev.SetWidth( 8 );
433 2 : oFieldElev.SetPrecision( 2 );
434 2 : poFeatureDefn->AddFieldDefn( &oFieldElev );
435 :
436 2 : OGRFieldDefn oFieldFreq("freq_mhz", OFTReal );
437 2 : oFieldFreq.SetWidth( 7 );
438 2 : oFieldFreq.SetPrecision( 3 );
439 2 : poFeatureDefn->AddFieldDefn( &oFieldFreq );
440 :
441 2 : OGRFieldDefn oFieldRange("range_km", OFTReal );
442 2 : oFieldRange.SetWidth( 7 );
443 2 : oFieldRange.SetPrecision( 3 );
444 2 : poFeatureDefn->AddFieldDefn( &oFieldRange );
445 :
446 2 : OGRFieldDefn oFieldTrueHeading("true_heading_deg", OFTReal );
447 2 : oFieldTrueHeading.SetWidth( 6 );
448 2 : oFieldTrueHeading.SetPrecision( 2 );
449 2 : poFeatureDefn->AddFieldDefn( &oFieldTrueHeading );
450 2 : }
451 :
452 : /************************************************************************/
453 : /* AddFeature() */
454 : /************************************************************************/
455 :
456 : OGRFeature*
457 12 : 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 12 : int nCount = 0;
469 12 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
470 24 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
471 12 : poFeature->SetField( nCount++, pszNavaidID );
472 12 : poFeature->SetField( nCount++, pszAptICAO );
473 12 : poFeature->SetField( nCount++, pszRwyNum );
474 12 : poFeature->SetField( nCount++, pszSubType );
475 12 : poFeature->SetField( nCount++, dfEle );
476 12 : poFeature->SetField( nCount++, dfFreq );
477 12 : poFeature->SetField( nCount++, dfRange );
478 12 : poFeature->SetField( nCount++, dfTrueHeading );
479 :
480 12 : RegisterFeature(poFeature);
481 :
482 12 : return poFeature;
483 : }
484 :
485 : /************************************************************************/
486 : /* OGRXPlaneVORLayer() */
487 : /************************************************************************/
488 :
489 :
490 2 : OGRXPlaneVORLayer::OGRXPlaneVORLayer() : OGRXPlaneLayer("VOR")
491 : {
492 2 : poFeatureDefn->SetGeomType( wkbPoint );
493 :
494 2 : OGRFieldDefn oFieldID("navaid_id", OFTString );
495 2 : oFieldID.SetWidth( 4 );
496 2 : poFeatureDefn->AddFieldDefn( &oFieldID );
497 :
498 2 : OGRFieldDefn oFieldName("navaid_name", OFTString );
499 2 : poFeatureDefn->AddFieldDefn( &oFieldName );
500 :
501 2 : OGRFieldDefn oFieldSubType("subtype", OFTString );
502 2 : oFieldSubType.SetWidth( 10 );
503 2 : poFeatureDefn->AddFieldDefn( &oFieldSubType );
504 :
505 2 : OGRFieldDefn oFieldElev("elevation_m", OFTReal );
506 2 : oFieldElev.SetWidth( 8 );
507 2 : oFieldElev.SetPrecision( 2 );
508 2 : poFeatureDefn->AddFieldDefn( &oFieldElev );
509 :
510 2 : OGRFieldDefn oFieldFreq("freq_mhz", OFTReal );
511 2 : oFieldFreq.SetWidth( 7 );
512 2 : oFieldFreq.SetPrecision( 3 );
513 2 : poFeatureDefn->AddFieldDefn( &oFieldFreq );
514 :
515 2 : OGRFieldDefn oFieldRange("range_km", OFTReal );
516 2 : oFieldRange.SetWidth( 7 );
517 2 : oFieldRange.SetPrecision( 3 );
518 2 : poFeatureDefn->AddFieldDefn( &oFieldRange );
519 :
520 2 : OGRFieldDefn oFieldSlavedVariation("slaved_variation_deg", OFTReal );
521 2 : oFieldSlavedVariation.SetWidth( 6 );
522 2 : oFieldSlavedVariation.SetPrecision( 2 );
523 2 : poFeatureDefn->AddFieldDefn( &oFieldSlavedVariation );
524 2 : }
525 :
526 : /************************************************************************/
527 : /* AddFeature() */
528 : /************************************************************************/
529 :
530 : OGRFeature*
531 6 : 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 6 : int nCount = 0;
542 6 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
543 12 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
544 6 : poFeature->SetField( nCount++, pszNavaidID );
545 6 : poFeature->SetField( nCount++, pszNavaidName );
546 6 : poFeature->SetField( nCount++, pszSubType );
547 6 : poFeature->SetField( nCount++, dfEle );
548 6 : poFeature->SetField( nCount++, dfFreq );
549 6 : poFeature->SetField( nCount++, dfRange );
550 6 : poFeature->SetField( nCount++, dfSlavedVariation );
551 :
552 6 : RegisterFeature(poFeature);
553 :
554 6 : return poFeature;
555 : }
556 :
557 : /************************************************************************/
558 : /* OGRXPlaneNDBLayer() */
559 : /************************************************************************/
560 :
561 2 : OGRXPlaneNDBLayer::OGRXPlaneNDBLayer() : OGRXPlaneLayer("NDB")
562 : {
563 2 : poFeatureDefn->SetGeomType( wkbPoint );
564 :
565 2 : OGRFieldDefn oFieldID("navaid_id", OFTString );
566 2 : oFieldID.SetWidth( 4 );
567 2 : poFeatureDefn->AddFieldDefn( &oFieldID );
568 :
569 2 : OGRFieldDefn oFieldName("navaid_name", OFTString );
570 2 : poFeatureDefn->AddFieldDefn( &oFieldName );
571 :
572 2 : OGRFieldDefn oFieldSubType("subtype", OFTString );
573 2 : oFieldSubType.SetWidth( 10 );
574 2 : poFeatureDefn->AddFieldDefn( &oFieldSubType );
575 :
576 2 : OGRFieldDefn oFieldElev("elevation_m", OFTReal );
577 2 : oFieldElev.SetWidth( 8 );
578 2 : oFieldElev.SetPrecision( 2 );
579 2 : poFeatureDefn->AddFieldDefn( &oFieldElev );
580 :
581 2 : OGRFieldDefn oFieldFreq("freq_khz", OFTReal );
582 2 : oFieldFreq.SetWidth( 7 );
583 2 : oFieldFreq.SetPrecision( 3 );
584 2 : poFeatureDefn->AddFieldDefn( &oFieldFreq );
585 :
586 2 : OGRFieldDefn oFieldRange("range_km", OFTReal );
587 2 : oFieldRange.SetWidth( 7 );
588 2 : oFieldRange.SetPrecision( 3 );
589 2 : poFeatureDefn->AddFieldDefn( &oFieldRange );
590 2 : }
591 :
592 : /************************************************************************/
593 : /* AddFeature() */
594 : /************************************************************************/
595 :
596 : OGRFeature*
597 8 : 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 8 : int nCount = 0;
607 8 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
608 16 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
609 8 : poFeature->SetField( nCount++, pszNavaidID );
610 8 : poFeature->SetField( nCount++, pszNavaidName );
611 8 : poFeature->SetField( nCount++, pszSubType );
612 8 : poFeature->SetField( nCount++, dfEle );
613 8 : poFeature->SetField( nCount++, dfFreq );
614 8 : poFeature->SetField( nCount++, dfRange );
615 :
616 8 : RegisterFeature(poFeature);
617 :
618 8 : return poFeature;
619 : }
620 :
621 : /************************************************************************/
622 : /* OGRXPlaneGSLayer */
623 : /************************************************************************/
624 :
625 2 : OGRXPlaneGSLayer::OGRXPlaneGSLayer() : OGRXPlaneLayer("GS")
626 : {
627 2 : poFeatureDefn->SetGeomType( wkbPoint );
628 :
629 2 : OGRFieldDefn oFieldID("navaid_id", OFTString );
630 2 : oFieldID.SetWidth( 4 );
631 2 : poFeatureDefn->AddFieldDefn( &oFieldID );
632 :
633 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
634 2 : oFieldAptICAO.SetWidth( 4 );
635 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
636 :
637 2 : OGRFieldDefn oFieldRwyNum("rwy_num", OFTString );
638 2 : oFieldRwyNum.SetWidth( 3 );
639 2 : poFeatureDefn->AddFieldDefn( &oFieldRwyNum );
640 :
641 2 : OGRFieldDefn oFieldElev("elevation_m", OFTReal );
642 2 : oFieldElev.SetWidth( 8 );
643 2 : oFieldElev.SetPrecision( 2 );
644 2 : poFeatureDefn->AddFieldDefn( &oFieldElev );
645 :
646 2 : OGRFieldDefn oFieldFreq("freq_mhz", OFTReal );
647 2 : oFieldFreq.SetWidth( 7 );
648 2 : oFieldFreq.SetPrecision( 3 );
649 2 : poFeatureDefn->AddFieldDefn( &oFieldFreq );
650 :
651 2 : OGRFieldDefn oFieldRange("range_km", OFTReal );
652 2 : oFieldRange.SetWidth( 7 );
653 2 : oFieldRange.SetPrecision( 3 );
654 2 : poFeatureDefn->AddFieldDefn( &oFieldRange );
655 :
656 2 : OGRFieldDefn oFieldTrueHeading("true_heading_deg", OFTReal );
657 2 : oFieldTrueHeading.SetWidth( 6 );
658 2 : oFieldTrueHeading.SetPrecision( 2 );
659 2 : poFeatureDefn->AddFieldDefn( &oFieldTrueHeading );
660 :
661 2 : OGRFieldDefn oFieldGlideSlope("glide_slope", OFTReal );
662 2 : oFieldGlideSlope.SetWidth( 6 );
663 2 : oFieldGlideSlope.SetPrecision( 2 );
664 2 : poFeatureDefn->AddFieldDefn( &oFieldGlideSlope );
665 2 : }
666 :
667 : /************************************************************************/
668 : /* AddFeature() */
669 : /************************************************************************/
670 :
671 : OGRFeature*
672 2 : 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 2 : int nCount = 0;
684 2 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
685 4 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
686 2 : poFeature->SetField( nCount++, pszNavaidID );
687 2 : poFeature->SetField( nCount++, pszAptICAO );
688 2 : poFeature->SetField( nCount++, pszRwyNum );
689 2 : poFeature->SetField( nCount++, dfEle );
690 2 : poFeature->SetField( nCount++, dfFreq );
691 2 : poFeature->SetField( nCount++, dfRange );
692 2 : poFeature->SetField( nCount++, dfTrueHeading );
693 2 : poFeature->SetField( nCount++, dfSlope );
694 :
695 2 : RegisterFeature(poFeature);
696 :
697 2 : return poFeature;
698 : }
699 :
700 :
701 : /************************************************************************/
702 : /* OGRXPlaneMarkerLayer */
703 : /************************************************************************/
704 :
705 2 : OGRXPlaneMarkerLayer::OGRXPlaneMarkerLayer() : OGRXPlaneLayer("Marker")
706 : {
707 2 : poFeatureDefn->SetGeomType( wkbPoint );
708 :
709 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
710 2 : oFieldAptICAO.SetWidth( 4 );
711 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
712 :
713 2 : OGRFieldDefn oFieldRwyNum("rwy_num", OFTString );
714 2 : oFieldRwyNum.SetWidth( 3 );
715 2 : poFeatureDefn->AddFieldDefn( &oFieldRwyNum );
716 :
717 2 : OGRFieldDefn oFieldSubType("subtype", OFTString );
718 2 : oFieldSubType.SetWidth( 10 );
719 2 : poFeatureDefn->AddFieldDefn( &oFieldSubType );
720 :
721 2 : OGRFieldDefn oFieldElev("elevation_m", OFTReal );
722 2 : oFieldElev.SetWidth( 8 );
723 2 : oFieldElev.SetPrecision( 2 );
724 2 : poFeatureDefn->AddFieldDefn( &oFieldElev );
725 :
726 2 : OGRFieldDefn oFieldTrueHeading("true_heading_deg", OFTReal );
727 2 : oFieldTrueHeading.SetWidth( 6 );
728 2 : oFieldTrueHeading.SetPrecision( 2 );
729 2 : poFeatureDefn->AddFieldDefn( &oFieldTrueHeading );
730 2 : }
731 :
732 : /************************************************************************/
733 : /* AddFeature() */
734 : /************************************************************************/
735 :
736 : OGRFeature*
737 6 : 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 6 : int nCount = 0;
746 6 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
747 12 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
748 6 : poFeature->SetField( nCount++, pszAptICAO );
749 6 : poFeature->SetField( nCount++, pszRwyNum );
750 6 : poFeature->SetField( nCount++, pszSubType );
751 6 : poFeature->SetField( nCount++, dfEle );
752 6 : poFeature->SetField( nCount++, dfTrueHeading );
753 :
754 6 : RegisterFeature(poFeature);
755 :
756 6 : return poFeature;
757 : }
758 :
759 : /************************************************************************/
760 : /* OGRXPlaneDMEILSLayer */
761 : /************************************************************************/
762 :
763 2 : OGRXPlaneDMEILSLayer::OGRXPlaneDMEILSLayer() : OGRXPlaneLayer("DMEILS")
764 : {
765 2 : poFeatureDefn->SetGeomType( wkbPoint );
766 :
767 2 : OGRFieldDefn oFieldID("navaid_id", OFTString );
768 2 : oFieldID.SetWidth( 4 );
769 2 : poFeatureDefn->AddFieldDefn( &oFieldID );
770 :
771 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
772 2 : oFieldAptICAO.SetWidth( 4 );
773 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
774 :
775 2 : OGRFieldDefn oFieldRwyNum("rwy_num", OFTString );
776 2 : oFieldRwyNum.SetWidth( 3 );
777 2 : poFeatureDefn->AddFieldDefn( &oFieldRwyNum );
778 :
779 2 : OGRFieldDefn oFieldElev("elevation_m", OFTReal );
780 2 : oFieldElev.SetWidth( 8 );
781 2 : oFieldElev.SetPrecision( 2 );
782 2 : poFeatureDefn->AddFieldDefn( &oFieldElev );
783 :
784 2 : OGRFieldDefn oFieldFreq("freq_mhz", OFTReal );
785 2 : oFieldFreq.SetWidth( 7 );
786 2 : oFieldFreq.SetPrecision( 3 );
787 2 : poFeatureDefn->AddFieldDefn( &oFieldFreq );
788 :
789 2 : OGRFieldDefn oFieldRange("range_km", OFTReal );
790 2 : oFieldRange.SetWidth( 7 );
791 2 : oFieldRange.SetPrecision( 3 );
792 2 : poFeatureDefn->AddFieldDefn( &oFieldRange );
793 :
794 2 : OGRFieldDefn oFieldBias("bias_km", OFTReal );
795 2 : oFieldBias.SetWidth( 6 );
796 2 : oFieldBias.SetPrecision( 2 );
797 2 : poFeatureDefn->AddFieldDefn( &oFieldBias );
798 2 : }
799 :
800 : /************************************************************************/
801 : /* AddFeature() */
802 : /************************************************************************/
803 :
804 : OGRFeature*
805 2 : 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 2 : int nCount = 0;
816 2 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
817 4 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
818 2 : poFeature->SetField( nCount++, pszNavaidID );
819 2 : poFeature->SetField( nCount++, pszAptICAO );
820 2 : poFeature->SetField( nCount++, pszRwyNum );
821 2 : poFeature->SetField( nCount++, dfEle );
822 2 : poFeature->SetField( nCount++, dfFreq );
823 2 : poFeature->SetField( nCount++, dfRange );
824 2 : poFeature->SetField( nCount++, dfBias );
825 :
826 2 : RegisterFeature(poFeature);
827 :
828 2 : return poFeature;
829 : }
830 :
831 : /************************************************************************/
832 : /* OGRXPlaneDMELayer */
833 : /************************************************************************/
834 :
835 :
836 2 : OGRXPlaneDMELayer::OGRXPlaneDMELayer() : OGRXPlaneLayer("DME")
837 : {
838 2 : poFeatureDefn->SetGeomType( wkbPoint );
839 :
840 2 : OGRFieldDefn oFieldID("navaid_id", OFTString );
841 2 : oFieldID.SetWidth( 4 );
842 2 : poFeatureDefn->AddFieldDefn( &oFieldID );
843 :
844 2 : OGRFieldDefn oFieldName("navaid_name", OFTString );
845 2 : poFeatureDefn->AddFieldDefn( &oFieldName );
846 :
847 2 : OGRFieldDefn oFieldSubType("subtype", OFTString );
848 2 : oFieldSubType.SetWidth( 10 );
849 2 : poFeatureDefn->AddFieldDefn( &oFieldSubType );
850 :
851 2 : OGRFieldDefn oFieldElev("elevation_m", OFTReal );
852 2 : oFieldElev.SetWidth( 8 );
853 2 : oFieldElev.SetPrecision( 2 );
854 2 : poFeatureDefn->AddFieldDefn( &oFieldElev );
855 :
856 2 : OGRFieldDefn oFieldFreq("freq_mhz", OFTReal );
857 2 : oFieldFreq.SetWidth( 7 );
858 2 : oFieldFreq.SetPrecision( 3 );
859 2 : poFeatureDefn->AddFieldDefn( &oFieldFreq );
860 :
861 2 : OGRFieldDefn oFieldRange("range_km", OFTReal );
862 2 : oFieldRange.SetWidth( 7 );
863 2 : oFieldRange.SetPrecision( 3 );
864 2 : poFeatureDefn->AddFieldDefn( &oFieldRange );
865 :
866 2 : OGRFieldDefn oFieldBias("bias_km", OFTReal );
867 2 : oFieldBias.SetWidth( 6 );
868 2 : oFieldBias.SetPrecision( 2 );
869 2 : poFeatureDefn->AddFieldDefn( &oFieldBias );
870 2 : }
871 :
872 : /************************************************************************/
873 : /* AddFeature() */
874 : /************************************************************************/
875 :
876 : OGRFeature*
877 12 : 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 12 : int nCount = 0;
888 12 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
889 24 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
890 12 : poFeature->SetField( nCount++, pszNavaidID );
891 12 : poFeature->SetField( nCount++, pszNavaidName );
892 12 : poFeature->SetField( nCount++, pszSubType );
893 12 : poFeature->SetField( nCount++, dfEle );
894 12 : poFeature->SetField( nCount++, dfFreq );
895 12 : poFeature->SetField( nCount++, dfRange );
896 12 : poFeature->SetField( nCount++, dfBias );
897 :
898 12 : RegisterFeature(poFeature);
899 :
900 12 : return poFeature;
901 : }
|