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