1 : /******************************************************************************
2 : * $Id: ogr_xplane_apt_reader.cpp
3 : *
4 : * Project: X-Plane apt.dat file reader
5 : * Purpose: Implements OGRXPlaneAptReader 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_apt_reader.h"
31 : #include "ogr_xplane_geo_utils.h"
32 :
33 : CPL_CVSID("$Id: ogr_xplane_apt_reader.cpp 18548 2010-01-14 22:01:35Z rouault $");
34 :
35 : /************************************************************************/
36 : /* OGRXPlaneCreateAptFileReader */
37 : /************************************************************************/
38 :
39 2 : OGRXPlaneReader* OGRXPlaneCreateAptFileReader( OGRXPlaneDataSource* poDataSource )
40 : {
41 2 : OGRXPlaneReader* poReader = new OGRXPlaneAptReader(poDataSource);
42 2 : return poReader;
43 : }
44 :
45 : /************************************************************************/
46 : /* OGRXPlaneAptReader() */
47 : /************************************************************************/
48 0 : OGRXPlaneAptReader::OGRXPlaneAptReader()
49 : {
50 0 : poAPTLayer = NULL;
51 0 : poRunwayLayer = NULL;
52 0 : poRunwayThresholdLayer = NULL;
53 0 : poStopwayLayer = NULL;
54 0 : poWaterRunwayLayer = NULL;
55 0 : poWaterRunwayThresholdLayer = NULL;
56 0 : poHelipadLayer = NULL;
57 0 : poHelipadPolygonLayer = NULL;
58 0 : poTaxiwayRectangleLayer =NULL;
59 0 : poPavementLayer = NULL;
60 0 : poAPTBoundaryLayer = NULL;
61 0 : poAPTLinearFeatureLayer = NULL;
62 0 : poATCFreqLayer = NULL;
63 0 : poStartupLocationLayer = NULL;
64 0 : poAPTLightBeaconLayer = NULL;
65 0 : poAPTWindsockLayer = NULL;
66 0 : poTaxiwaySignLayer = NULL;
67 0 : poVASI_PAPI_WIGWAG_Layer = NULL;
68 :
69 0 : Rewind();
70 0 : }
71 :
72 : /************************************************************************/
73 : /* OGRXPlaneAptReader() */
74 : /************************************************************************/
75 :
76 2 : OGRXPlaneAptReader::OGRXPlaneAptReader( OGRXPlaneDataSource* poDataSource )
77 : {
78 2 : poAPTLayer = new OGRXPlaneAPTLayer();
79 4 : poRunwayLayer = new OGRXPlaneRunwayLayer();
80 4 : poRunwayThresholdLayer = new OGRXPlaneRunwayThresholdLayer();
81 4 : poStopwayLayer = new OGRXPlaneStopwayLayer();
82 4 : poWaterRunwayLayer = new OGRXPlaneWaterRunwayLayer();
83 4 : poWaterRunwayThresholdLayer = new OGRXPlaneWaterRunwayThresholdLayer();
84 4 : poHelipadLayer = new OGRXPlaneHelipadLayer();
85 4 : poHelipadPolygonLayer = new OGRXPlaneHelipadPolygonLayer();
86 4 : poTaxiwayRectangleLayer = new OGRXPlaneTaxiwayRectangleLayer();
87 4 : poPavementLayer = new OGRXPlanePavementLayer();
88 4 : poAPTBoundaryLayer = new OGRXPlaneAPTBoundaryLayer();
89 4 : poAPTLinearFeatureLayer = new OGRXPlaneAPTLinearFeatureLayer();
90 4 : poATCFreqLayer = new OGRXPlaneATCFreqLayer();
91 4 : poStartupLocationLayer = new OGRXPlaneStartupLocationLayer();
92 4 : poAPTLightBeaconLayer = new OGRXPlaneAPTLightBeaconLayer();
93 4 : poAPTWindsockLayer = new OGRXPlaneAPTWindsockLayer();
94 4 : poTaxiwaySignLayer = new OGRXPlaneTaxiwaySignLayer();
95 4 : poVASI_PAPI_WIGWAG_Layer = new OGRXPlane_VASI_PAPI_WIGWAG_Layer();
96 :
97 2 : poDataSource->RegisterLayer(poAPTLayer);
98 2 : poDataSource->RegisterLayer(poRunwayLayer);
99 2 : poDataSource->RegisterLayer(poRunwayThresholdLayer);
100 2 : poDataSource->RegisterLayer(poStopwayLayer);
101 2 : poDataSource->RegisterLayer(poWaterRunwayLayer);
102 2 : poDataSource->RegisterLayer(poWaterRunwayThresholdLayer);
103 2 : poDataSource->RegisterLayer(poHelipadLayer);
104 2 : poDataSource->RegisterLayer(poHelipadPolygonLayer);
105 2 : poDataSource->RegisterLayer(poTaxiwayRectangleLayer);
106 2 : poDataSource->RegisterLayer(poPavementLayer);
107 2 : poDataSource->RegisterLayer(poAPTBoundaryLayer);
108 2 : poDataSource->RegisterLayer(poAPTLinearFeatureLayer);
109 2 : poDataSource->RegisterLayer(poATCFreqLayer);
110 2 : poDataSource->RegisterLayer(poStartupLocationLayer);
111 2 : poDataSource->RegisterLayer(poAPTLightBeaconLayer);
112 2 : poDataSource->RegisterLayer(poAPTWindsockLayer);
113 2 : poDataSource->RegisterLayer(poTaxiwaySignLayer);
114 2 : poDataSource->RegisterLayer(poVASI_PAPI_WIGWAG_Layer);
115 :
116 2 : Rewind();
117 2 : }
118 :
119 : /************************************************************************/
120 : /* CloneForLayer() */
121 : /************************************************************************/
122 :
123 0 : OGRXPlaneReader* OGRXPlaneAptReader::CloneForLayer(OGRXPlaneLayer* poLayer)
124 : {
125 0 : OGRXPlaneAptReader* poReader = new OGRXPlaneAptReader();
126 :
127 0 : poReader->poInterestLayer = poLayer;
128 0 : SET_IF_INTEREST_LAYER(poAPTLayer);
129 0 : SET_IF_INTEREST_LAYER(poRunwayLayer);
130 0 : SET_IF_INTEREST_LAYER(poRunwayThresholdLayer);
131 0 : SET_IF_INTEREST_LAYER(poStopwayLayer);
132 0 : SET_IF_INTEREST_LAYER(poWaterRunwayLayer);
133 0 : SET_IF_INTEREST_LAYER(poWaterRunwayThresholdLayer);
134 0 : SET_IF_INTEREST_LAYER(poHelipadLayer);
135 0 : SET_IF_INTEREST_LAYER(poHelipadPolygonLayer);
136 0 : SET_IF_INTEREST_LAYER(poTaxiwayRectangleLayer);
137 0 : SET_IF_INTEREST_LAYER(poPavementLayer);
138 0 : SET_IF_INTEREST_LAYER(poAPTBoundaryLayer);
139 0 : SET_IF_INTEREST_LAYER(poAPTLinearFeatureLayer);
140 0 : SET_IF_INTEREST_LAYER(poATCFreqLayer);
141 0 : SET_IF_INTEREST_LAYER(poStartupLocationLayer);
142 0 : SET_IF_INTEREST_LAYER(poAPTLightBeaconLayer);
143 0 : SET_IF_INTEREST_LAYER(poAPTWindsockLayer);
144 0 : SET_IF_INTEREST_LAYER(poTaxiwaySignLayer);
145 0 : SET_IF_INTEREST_LAYER(poVASI_PAPI_WIGWAG_Layer);
146 :
147 0 : if (pszFilename)
148 : {
149 0 : poReader->pszFilename = CPLStrdup(pszFilename);
150 0 : poReader->fp = VSIFOpen( pszFilename, "rt" );
151 : }
152 :
153 0 : return poReader;
154 : }
155 :
156 : /************************************************************************/
157 : /* Rewind() */
158 : /************************************************************************/
159 :
160 4 : void OGRXPlaneAptReader::Rewind()
161 : {
162 4 : bAptHeaderFound = FALSE;
163 4 : bTowerFound = FALSE;
164 4 : dfLatTower = 0;
165 4 : dfLonTower = 0;
166 4 : dfHeightTower = 0;
167 4 : bRunwayFound = FALSE;
168 4 : dfLatFirstRwy = 0;
169 4 : dfLonFirstRwy = 0;
170 4 : nAPTType = -1;
171 :
172 4 : bResumeLine = FALSE;
173 :
174 4 : OGRXPlaneReader::Rewind();
175 4 : }
176 :
177 :
178 : /************************************************************************/
179 : /* IsRecognizedVersion() */
180 : /************************************************************************/
181 :
182 2 : int OGRXPlaneAptReader::IsRecognizedVersion( const char* pszVersionString)
183 : {
184 : return EQUALN(pszVersionString, "850 Version", 11) ||
185 2 : EQUALN(pszVersionString, "810 Version", 11);
186 : }
187 :
188 : /************************************************************************/
189 : /* Read() */
190 : /************************************************************************/
191 :
192 2 : void OGRXPlaneAptReader::Read()
193 : {
194 : const char* pszLine;
195 :
196 2 : if (!bResumeLine)
197 : {
198 2 : CPLAssert(papszTokens == NULL);
199 : }
200 :
201 805 : while(bResumeLine || (pszLine = CPLReadLine(fp)) != NULL)
202 : {
203 : int nType;
204 803 : if (!bResumeLine)
205 : {
206 803 : papszTokens = CSLTokenizeString(pszLine);
207 803 : nTokens = CSLCount(papszTokens);
208 803 : nLineNumber ++;
209 803 : bResumeLine = FALSE;
210 : }
211 :
212 841 : do
213 : {
214 860 : bResumeLine = FALSE;
215 :
216 860 : if (nTokens == 1 && strcmp(papszTokens[0], "99") == 0)
217 : {
218 2 : CSLDestroy(papszTokens);
219 2 : papszTokens = NULL;
220 2 : bEOF = TRUE;
221 2 : if (bAptHeaderFound)
222 : {
223 2 : if (poAPTLayer)
224 : {
225 : poAPTLayer->AddFeature(osAptICAO, osAptName, nAPTType, dfElevation,
226 : bTowerFound || bRunwayFound,
227 : (bTowerFound) ? dfLatTower : dfLatFirstRwy,
228 : (bTowerFound) ? dfLonTower : dfLonFirstRwy,
229 2 : bTowerFound, dfHeightTower, osTowerName);
230 : }
231 : }
232 2 : return;
233 : }
234 858 : else if (nTokens == 0 || assertMinCol(2) == FALSE)
235 : {
236 17 : break;
237 : }
238 :
239 841 : nType = atoi(papszTokens[0]);
240 841 : switch(nType)
241 : {
242 : case APT_AIRPORT_HEADER:
243 : case APT_SEAPLANE_HEADER:
244 : case APT_HELIPORT_HEADER:
245 14 : if (bAptHeaderFound)
246 : {
247 12 : bAptHeaderFound = FALSE;
248 12 : if (poAPTLayer)
249 : {
250 : poAPTLayer->AddFeature(osAptICAO, osAptName, nAPTType, dfElevation,
251 : bTowerFound || bRunwayFound,
252 : (bTowerFound) ? dfLatTower : dfLatFirstRwy,
253 : (bTowerFound) ? dfLonTower : dfLonFirstRwy,
254 12 : bTowerFound, dfHeightTower, osTowerName);
255 : }
256 : }
257 14 : ParseAptHeaderRecord();
258 14 : nAPTType = nType;
259 :
260 14 : break;
261 :
262 : case APT_RUNWAY_TAXIWAY_V_810:
263 504 : if (poAPTLayer ||
264 : poRunwayLayer || poRunwayThresholdLayer ||
265 : poStopwayLayer ||
266 : poHelipadLayer || poHelipadPolygonLayer ||
267 : poVASI_PAPI_WIGWAG_Layer || poTaxiwayRectangleLayer)
268 : {
269 504 : ParseRunwayTaxiwayV810Record();
270 : }
271 504 : break;
272 :
273 : case APT_TOWER:
274 6 : if (poAPTLayer)
275 6 : ParseTowerRecord();
276 6 : break;
277 :
278 : case APT_STARTUP_LOCATION:
279 110 : if (poStartupLocationLayer)
280 110 : ParseStartupLocationRecord();
281 110 : break;
282 :
283 : case APT_LIGHT_BEACONS:
284 5 : if (poAPTLightBeaconLayer)
285 5 : ParseLightBeaconRecord();
286 5 : break;
287 :
288 : case APT_WINDSOCKS:
289 34 : if (poAPTWindsockLayer)
290 34 : ParseWindsockRecord();
291 34 : break;
292 :
293 : case APT_TAXIWAY_SIGNS:
294 17 : if (poTaxiwaySignLayer)
295 17 : ParseTaxiwaySignRecord();
296 17 : break;
297 :
298 : case APT_VASI_PAPI_WIGWAG:
299 24 : if (poVASI_PAPI_WIGWAG_Layer)
300 24 : ParseVasiPapiWigWagRecord();
301 24 : break;
302 :
303 : case APT_ATC_AWOS_ASOS_ATIS:
304 : case APT_ATC_CTAF:
305 : case APT_ATC_CLD:
306 : case APT_ATC_GND:
307 : case APT_ATC_TWR:
308 : case APT_ATC_APP:
309 : case APT_ATC_DEP:
310 52 : if (poATCFreqLayer)
311 52 : ParseATCRecord(nType);
312 52 : break;
313 :
314 : case APT_RUNWAY:
315 16 : if (poAPTLayer || poRunwayLayer || poRunwayThresholdLayer || poStopwayLayer)
316 16 : ParseRunwayRecord();
317 16 : break;
318 :
319 : case APT_WATER_RUNWAY:
320 1 : if (poWaterRunwayLayer || poWaterRunwayThresholdLayer)
321 1 : ParseWaterRunwayRecord();
322 1 : break;
323 :
324 : case APT_HELIPAD:
325 1 : if (poHelipadLayer || poHelipadPolygonLayer)
326 1 : ParseHelipadRecord();
327 1 : break;
328 :
329 : case APT_PAVEMENT_HEADER:
330 11 : if (poPavementLayer)
331 11 : ParsePavement();
332 11 : break;
333 :
334 : case APT_LINEAR_HEADER:
335 45 : if (poAPTLinearFeatureLayer)
336 45 : ParseAPTLinearFeature();
337 45 : break;
338 :
339 : case APT_BOUNDARY_HEADER:
340 1 : if (poAPTBoundaryLayer)
341 1 : ParseAPTBoundary();
342 : break;
343 :
344 : default:
345 : break;
346 : }
347 : } while(bResumeLine);
348 :
349 801 : CSLDestroy(papszTokens);
350 801 : papszTokens = NULL;
351 :
352 801 : if (poInterestLayer && poInterestLayer->IsEmpty() == FALSE)
353 0 : return;
354 : }
355 :
356 0 : bEOF = TRUE;
357 : }
358 :
359 :
360 : /************************************************************************/
361 : /* ParseAptHeaderRecord() */
362 : /************************************************************************/
363 :
364 14 : void OGRXPlaneAptReader::ParseAptHeaderRecord()
365 : {
366 14 : bAptHeaderFound = FALSE;
367 14 : bTowerFound = FALSE;
368 14 : bRunwayFound = FALSE;
369 :
370 14 : RET_IF_FAIL(assertMinCol(6));
371 :
372 : /* feet to meter */
373 14 : RET_IF_FAIL(readDoubleWithBoundsAndConversion(&dfElevation, 1, "elevation", FEET_TO_METER, -1000., 10000.));
374 14 : bControlTower = atoi(papszTokens[2]);
375 : // papszTokens[3] ignored
376 14 : osAptICAO = papszTokens[4];
377 28 : osAptName = readStringUntilEnd(5);
378 :
379 14 : bAptHeaderFound = TRUE;
380 : }
381 :
382 : /************************************************************************/
383 : /* ParseRunwayTaxiwayV810Record() */
384 : /************************************************************************/
385 :
386 504 : void OGRXPlaneAptReader::ParseRunwayTaxiwayV810Record()
387 : {
388 : double dfLat, dfLon, dfTrueHeading, dfLength, dfWidth;
389 : double adfDisplacedThresholdLength[2];
390 : double adfStopwayLength[2];
391 : const char* pszRwyNum;
392 : int aeVisualApproachLightingCode[2], aeRunwayLightingCode[2], aeApproachLightingCode[2];
393 : int eSurfaceCode, eShoulderCode, eMarkings;
394 : double dfSmoothness;
395 : double adfVisualGlidePathAngle[2];
396 : int bHasDistanceRemainingSigns;
397 :
398 504 : RET_IF_FAIL(assertMinCol(15));
399 :
400 504 : RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
401 504 : pszRwyNum = papszTokens[3];
402 504 : RET_IF_FAIL(readTrueHeading(&dfTrueHeading, 4));
403 504 : RET_IF_FAIL(readDouble(&dfLength, 5, "length"));
404 504 : dfLength *= FEET_TO_METER;
405 504 : adfDisplacedThresholdLength[0] = atoi(papszTokens[6]) * FEET_TO_METER;
406 504 : if (strchr(papszTokens[6], '.') != NULL)
407 504 : adfDisplacedThresholdLength[1] = atoi(strchr(papszTokens[6], '.') + 1) * FEET_TO_METER;
408 504 : adfStopwayLength[0] = atoi(papszTokens[7]) * FEET_TO_METER;
409 504 : if (strchr(papszTokens[7], '.') != NULL)
410 504 : adfStopwayLength[1] = atoi(strchr(papszTokens[7], '.') + 1) * FEET_TO_METER;
411 504 : RET_IF_FAIL(readDouble(&dfWidth, 8, "width"));
412 504 : dfWidth *= FEET_TO_METER;
413 504 : if (strlen(papszTokens[9]) == 6)
414 : {
415 504 : aeVisualApproachLightingCode[0] = papszTokens[9][0] - '0';
416 504 : aeRunwayLightingCode[0] = papszTokens[9][1] - '0';
417 504 : aeApproachLightingCode[0] = papszTokens[9][2] - '0';
418 504 : aeVisualApproachLightingCode[1] = papszTokens[9][3] - '0';
419 504 : aeRunwayLightingCode[1] = papszTokens[9][4] - '0';
420 504 : aeApproachLightingCode[1] = papszTokens[9][5] - '0';
421 : }
422 504 : eSurfaceCode = atoi(papszTokens[10]);
423 504 : eShoulderCode = atoi(papszTokens[11]);
424 504 : eMarkings = atoi(papszTokens[12]);
425 504 : RET_IF_FAIL(readDoubleWithBounds(&dfSmoothness, 13, "runway smoothness", 0., 1.));
426 504 : bHasDistanceRemainingSigns = atoi(papszTokens[14]);
427 504 : if (nTokens == 16)
428 : {
429 13 : adfVisualGlidePathAngle[0] = atoi(papszTokens[15]) / 100.;
430 13 : if (strchr(papszTokens[15], '.') != NULL)
431 13 : adfVisualGlidePathAngle[1] = atoi(strchr(papszTokens[15], '.') + 1) / 100.;
432 : }
433 :
434 504 : if (strcmp(pszRwyNum, "xxx") == 000)
435 : {
436 : /* Taxiway */
437 491 : if (poTaxiwayRectangleLayer)
438 : poTaxiwayRectangleLayer->AddFeature(osAptICAO, dfLat, dfLon,
439 : dfTrueHeading, dfLength, dfWidth,
440 : RunwaySurfaceEnumeration.GetText(eSurfaceCode),
441 491 : dfSmoothness, aeRunwayLightingCode[0] == 1);
442 : }
443 24 : else if (pszRwyNum[0] >= '0' && pszRwyNum[0] <= '9' && strlen(pszRwyNum) >= 2)
444 : {
445 : /* Runway */
446 : double adfLat[2], adfLon[2];
447 11 : CPLString aosRwyNum[2];
448 : OGRFeature* poFeature;
449 : int abReil[2];
450 :
451 11 : int num1 = atoi(pszRwyNum);
452 11 : int num2 = (num1 > 18) ? num1 - 18 : num1 + 18;
453 19 : if (pszRwyNum[2] == '0' || pszRwyNum[2] == 'x')
454 : {
455 8 : aosRwyNum[0].Printf("%02d", num1);
456 8 : aosRwyNum[1].Printf("%02d", num2);
457 : }
458 : else
459 : {
460 3 : aosRwyNum[0] = pszRwyNum;
461 : aosRwyNum[1].Printf("%02d%c", num2,
462 : (aosRwyNum[0][2] == 'L') ? 'R' :
463 3 : (aosRwyNum[0][2] == 'R') ? 'L' : aosRwyNum[0][2]);
464 : }
465 :
466 11 : OGRXPlane_ExtendPosition(dfLat, dfLon, dfLength / 2, dfTrueHeading + 180, &adfLat[0], &adfLon[0]);
467 11 : OGRXPlane_ExtendPosition(dfLat, dfLon, dfLength / 2, dfTrueHeading, &adfLat[1], &adfLon[1]);
468 :
469 33 : for(int i=0;i<2;i++)
470 22 : abReil[i] = (aeRunwayLightingCode[i] >= 3 && aeRunwayLightingCode[i] <= 5) ;
471 :
472 11 : if (!bRunwayFound)
473 : {
474 6 : dfLatFirstRwy = adfLat[0];
475 6 : dfLonFirstRwy = adfLon[0];
476 6 : bRunwayFound = TRUE;
477 : }
478 :
479 13 : if (nAPTType == APT_SEAPLANE_HEADER || eSurfaceCode == 13)
480 : {
481 : /* Special case for water-runways. No special record in V8.10 */
482 2 : OGRFeature* apoWaterRunwayThreshold[2] = {NULL, NULL};
483 : int bBuoys;
484 : int i;
485 :
486 2 : bBuoys = TRUE;
487 :
488 6 : for(i=0;i<2;i++)
489 : {
490 4 : if (poWaterRunwayThresholdLayer)
491 : {
492 : apoWaterRunwayThreshold[i] =
493 : poWaterRunwayThresholdLayer->AddFeature
494 4 : (osAptICAO, aosRwyNum[i], adfLat[i], adfLon[i], dfWidth, bBuoys);
495 : }
496 :
497 : }
498 :
499 2 : if (poWaterRunwayThresholdLayer)
500 : {
501 : poWaterRunwayThresholdLayer->SetRunwayLengthAndHeading(apoWaterRunwayThreshold[0], dfLength,
502 2 : OGRXPlane_Track(adfLat[0], adfLon[0], adfLat[1], adfLon[1]));
503 : poWaterRunwayThresholdLayer->SetRunwayLengthAndHeading(apoWaterRunwayThreshold[1], dfLength,
504 2 : OGRXPlane_Track(adfLat[1], adfLon[1], adfLat[0], adfLon[0]));
505 : }
506 :
507 2 : if (poWaterRunwayLayer)
508 : {
509 : poWaterRunwayLayer->AddFeature(osAptICAO, aosRwyNum[0], aosRwyNum[1],
510 : adfLat[0], adfLon[0], adfLat[1], adfLon[1],
511 2 : dfWidth, bBuoys);
512 : }
513 : }
514 : else
515 : {
516 9 : if (poRunwayThresholdLayer)
517 : {
518 27 : for(int i=0;i<2;i++)
519 : {
520 : poFeature =
521 : poRunwayThresholdLayer->AddFeature
522 : (osAptICAO, aosRwyNum[i],
523 : adfLat[i], adfLon[i], dfWidth,
524 : RunwaySurfaceEnumeration.GetText(eSurfaceCode),
525 : RunwayShoulderEnumeration.GetText(eShoulderCode),
526 : dfSmoothness,
527 : (aeRunwayLightingCode[i] == 4 || aeRunwayLightingCode[i] == 5) /* bHasCenterLineLights */,
528 : (aeRunwayLightingCode[i] >= 2 && aeRunwayLightingCode[i] <= 5) ? "Yes" : "None" /* pszEdgeLighting */,
529 : bHasDistanceRemainingSigns,
530 : adfDisplacedThresholdLength[i], adfStopwayLength[i],
531 : RunwayMarkingEnumeration.GetText(eMarkings),
532 : RunwayApproachLightingEnumerationV810.GetText(aeApproachLightingCode[i]),
533 : (aeRunwayLightingCode[i] == 5) /* bHasTouchdownLights */,
534 : (abReil[i] && abReil[i]) ? "Omni-directional" :
535 18 : (abReil[i] && !abReil[1-i]) ? "Unidirectional" : "None" /* eReil */);
536 : poRunwayThresholdLayer->SetRunwayLengthAndHeading(poFeature, dfLength,
537 18 : (i == 0) ? dfTrueHeading : (dfTrueHeading < 180) ? dfTrueHeading + 180 : dfTrueHeading - 180);
538 18 : if (adfDisplacedThresholdLength[i] != 0)
539 2 : poRunwayThresholdLayer->AddFeatureFromNonDisplacedThreshold(poFeature);
540 : }
541 : }
542 :
543 9 : if (poRunwayLayer)
544 : {
545 : poRunwayLayer->AddFeature(osAptICAO, aosRwyNum[0], aosRwyNum[1],
546 : adfLat[0], adfLon[0], adfLat[1], adfLon[1],
547 : dfWidth,
548 : RunwaySurfaceEnumeration.GetText(eSurfaceCode),
549 : RunwayShoulderEnumeration.GetText(eShoulderCode),
550 : dfSmoothness,
551 : (aeRunwayLightingCode[0] == 4 || aeRunwayLightingCode[0] == 5),
552 : (aeRunwayLightingCode[0] >= 2 && aeRunwayLightingCode[0] <= 5) ? "Yes" : "None" /* pszEdgeLighting */,
553 9 : bHasDistanceRemainingSigns);
554 : }
555 :
556 9 : if (poStopwayLayer)
557 : {
558 27 : for(int i=0;i<2;i++)
559 : {
560 18 : if (adfStopwayLength[i] != 0)
561 : {
562 : double dfHeading = OGRXPlane_Track(adfLat[i], adfLon[i],
563 4 : adfLat[1-i], adfLon[1-i]);
564 : poStopwayLayer->AddFeature(osAptICAO, aosRwyNum[i],
565 4 : adfLat[i], adfLon[i], dfHeading, dfWidth, adfStopwayLength[i]);
566 : }
567 : }
568 : }
569 :
570 9 : if (poVASI_PAPI_WIGWAG_Layer)
571 : {
572 27 : for(int i=0;i<2;i++)
573 : {
574 18 : if (aeApproachLightingCode[i])
575 : poVASI_PAPI_WIGWAG_Layer->AddFeature(osAptICAO, aosRwyNum[i],
576 : RunwayVisualApproachPathIndicatorEnumerationV810.GetText(aeApproachLightingCode[i]),
577 : adfLat[i], adfLon[i],
578 : (i == 0) ? dfTrueHeading : (dfTrueHeading < 180) ? dfTrueHeading + 180 : dfTrueHeading- 180,
579 18 : adfVisualGlidePathAngle[i]);
580 : }
581 : }
582 11 : }
583 : }
584 2 : else if (pszRwyNum[0] == 'H')
585 : {
586 : /* Helipads can belong to regular airports or heliports */
587 2 : CPLString osHelipadName = pszRwyNum;
588 2 : if (strlen(pszRwyNum) == 3 && pszRwyNum[2] == 'x')
589 2 : osHelipadName[2] = 0;
590 :
591 2 : if (!bRunwayFound)
592 : {
593 1 : dfLatFirstRwy = dfLat;
594 1 : dfLonFirstRwy = dfLon;
595 1 : bRunwayFound = TRUE;
596 : }
597 :
598 2 : if (poHelipadLayer)
599 : {
600 : poHelipadLayer->AddFeature(osAptICAO, osHelipadName, dfLat, dfLon,
601 : dfTrueHeading, dfLength, dfWidth,
602 : RunwaySurfaceEnumeration.GetText(eSurfaceCode),
603 : RunwayMarkingEnumeration.GetText(eMarkings),
604 : RunwayShoulderEnumeration.GetText(eShoulderCode),
605 : dfSmoothness,
606 2 : (aeRunwayLightingCode[0] >= 2 && aeRunwayLightingCode[0] <= 5) ? "Yes" : "None" /* pszEdgeLighting */);
607 : }
608 :
609 2 : if (poHelipadPolygonLayer)
610 : {
611 : poHelipadPolygonLayer->AddFeature(osAptICAO, osHelipadName, dfLat, dfLon,
612 : dfTrueHeading, dfLength, dfWidth,
613 : RunwaySurfaceEnumeration.GetText(eSurfaceCode),
614 : RunwayMarkingEnumeration.GetText(eMarkings),
615 : RunwayShoulderEnumeration.GetText(eShoulderCode),
616 : dfSmoothness,
617 2 : (aeRunwayLightingCode[0] >= 2 && aeRunwayLightingCode[0] <= 5) ? "Yes" : "None" /* pszEdgeLighting */);
618 2 : }
619 : }
620 : else
621 : {
622 : CPLDebug("XPlane", "Line %d : Unexpected runway number : %s",
623 0 : nLineNumber, pszRwyNum);
624 : }
625 :
626 : }
627 :
628 : /************************************************************************/
629 : /* ParseRunwayRecord() */
630 : /************************************************************************/
631 :
632 16 : void OGRXPlaneAptReader::ParseRunwayRecord()
633 : {
634 : double dfWidth;
635 : int eSurfaceCode, eShoulderCode;
636 : double dfSmoothness;
637 : int bHasCenterLineLights, bHasDistanceRemainingSigns;
638 : int eEdgeLighting;
639 : int nCurToken;
640 16 : int nRwy = 0;
641 : double adfLat[2], adfLon[2];
642 16 : OGRFeature* apoRunwayThreshold[2] = { NULL, NULL };
643 : double dfLength;
644 16 : CPLString aosRunwayId[2];
645 : double adfDisplacedThresholdLength[2];
646 : double adfStopwayLength[2];
647 :
648 32 : RET_IF_FAIL(assertMinCol(8 + 9 + 9));
649 :
650 16 : RET_IF_FAIL(readDouble(&dfWidth, 1, "runway width"));
651 16 : eSurfaceCode = atoi(papszTokens[2]);
652 16 : eShoulderCode = atoi(papszTokens[3]);
653 16 : RET_IF_FAIL(readDoubleWithBounds(&dfSmoothness, 4, "runway smoothness", 0., 1.));
654 16 : bHasCenterLineLights = atoi(papszTokens[5]);
655 16 : eEdgeLighting = atoi(papszTokens[6]);
656 16 : bHasDistanceRemainingSigns = atoi(papszTokens[7]);
657 :
658 48 : for( nRwy=0, nCurToken = 8 ; nRwy<=1 ; nRwy++, nCurToken += 9 )
659 : {
660 : double dfLat, dfLon;
661 : int eMarkings, eApproachLightingCode, eREIL;
662 : int bHasTouchdownLights;
663 :
664 32 : aosRunwayId[nRwy] = papszTokens[nCurToken + 0]; /* for example : 08, 24R, or xxx */
665 32 : RET_IF_FAIL(readLatLon(&dfLat, &dfLon, nCurToken + 1));
666 32 : adfLat[nRwy] = dfLat;
667 32 : adfLon[nRwy] = dfLon;
668 32 : RET_IF_FAIL(readDouble(&adfDisplacedThresholdLength[nRwy], nCurToken + 3, "displaced threshold length"));
669 32 : RET_IF_FAIL(readDouble(&adfStopwayLength[nRwy], nCurToken + 4, "stopway/blastpad/over-run length"));
670 32 : eMarkings = atoi(papszTokens[nCurToken + 5]);
671 32 : eApproachLightingCode = atoi(papszTokens[nCurToken + 6]);
672 32 : bHasTouchdownLights = atoi(papszTokens[nCurToken + 7]);
673 32 : eREIL = atoi(papszTokens[nCurToken + 8]);
674 :
675 32 : if (!bRunwayFound)
676 : {
677 7 : dfLatFirstRwy = dfLat;
678 7 : dfLonFirstRwy = dfLon;
679 7 : bRunwayFound = TRUE;
680 : }
681 :
682 32 : if (poRunwayThresholdLayer)
683 : {
684 : apoRunwayThreshold[nRwy] =
685 : poRunwayThresholdLayer->AddFeature
686 : (osAptICAO, aosRunwayId[nRwy],
687 : dfLat, dfLon, dfWidth,
688 : RunwaySurfaceEnumeration.GetText(eSurfaceCode),
689 : RunwayShoulderEnumeration.GetText(eShoulderCode),
690 : dfSmoothness, bHasCenterLineLights,
691 : RunwayEdgeLightingEnumeration.GetText(eEdgeLighting), bHasDistanceRemainingSigns,
692 : adfDisplacedThresholdLength[nRwy], adfStopwayLength[nRwy],
693 : RunwayMarkingEnumeration.GetText(eMarkings),
694 : RunwayApproachLightingEnumeration.GetText(eApproachLightingCode),
695 : bHasTouchdownLights,
696 32 : RunwayREILEnumeration.GetText(eREIL));
697 : }
698 : }
699 :
700 16 : dfLength = OGRXPlane_Distance(adfLat[0], adfLon[0], adfLat[1], adfLon[1]);
701 16 : if (poRunwayThresholdLayer)
702 : {
703 : poRunwayThresholdLayer->SetRunwayLengthAndHeading(apoRunwayThreshold[0], dfLength,
704 16 : OGRXPlane_Track(adfLat[0], adfLon[0], adfLat[1], adfLon[1]));
705 : poRunwayThresholdLayer->SetRunwayLengthAndHeading(apoRunwayThreshold[1], dfLength,
706 16 : OGRXPlane_Track(adfLat[1], adfLon[1], adfLat[0], adfLon[0]));
707 16 : if (adfDisplacedThresholdLength[0] != 0)
708 1 : poRunwayThresholdLayer->AddFeatureFromNonDisplacedThreshold(apoRunwayThreshold[0]);
709 16 : if (adfDisplacedThresholdLength[1] != 0)
710 4 : poRunwayThresholdLayer->AddFeatureFromNonDisplacedThreshold(apoRunwayThreshold[1]);
711 : }
712 :
713 16 : if (poRunwayLayer)
714 : {
715 : poRunwayLayer->AddFeature(osAptICAO, aosRunwayId[0], aosRunwayId[1],
716 : adfLat[0], adfLon[0], adfLat[1], adfLon[1],
717 : dfWidth,
718 : RunwaySurfaceEnumeration.GetText(eSurfaceCode),
719 : RunwayShoulderEnumeration.GetText(eShoulderCode),
720 : dfSmoothness, bHasCenterLineLights,
721 : RunwayEdgeLightingEnumeration.GetText(eEdgeLighting),
722 16 : bHasDistanceRemainingSigns);
723 : }
724 :
725 16 : if (poStopwayLayer)
726 : {
727 48 : for(int i=0;i<2;i++)
728 : {
729 32 : if (adfStopwayLength[i] != 0)
730 : {
731 : double dfHeading = OGRXPlane_Track(adfLat[i], adfLon[i],
732 6 : adfLat[1-i], adfLon[1-i]);
733 : poStopwayLayer->AddFeature(osAptICAO, aosRunwayId[i],
734 6 : adfLat[i], adfLon[i], dfHeading, dfWidth, adfStopwayLength[i]);
735 : }
736 : }
737 0 : }
738 : }
739 :
740 : /************************************************************************/
741 : /* ParseWaterRunwayRecord() */
742 : /************************************************************************/
743 :
744 1 : void OGRXPlaneAptReader::ParseWaterRunwayRecord()
745 : {
746 : double adfLat[2], adfLon[2];
747 1 : OGRFeature* apoWaterRunwayThreshold[2] = {NULL, NULL};
748 : double dfWidth, dfLength;
749 : int bBuoys;
750 1 : CPLString aosRunwayId[2];
751 : int i;
752 :
753 2 : RET_IF_FAIL(assertMinCol(9));
754 :
755 1 : RET_IF_FAIL(readDouble(&dfWidth, 1, "runway width"));
756 1 : bBuoys = atoi(papszTokens[2]);
757 :
758 3 : for(i=0;i<2;i++)
759 : {
760 2 : aosRunwayId[i] = papszTokens[3 + 3*i];
761 2 : RET_IF_FAIL(readLatLon(&adfLat[i], &adfLon[i], 4 + 3*i));
762 :
763 2 : if (poWaterRunwayThresholdLayer)
764 : {
765 : apoWaterRunwayThreshold[i] =
766 : poWaterRunwayThresholdLayer->AddFeature
767 2 : (osAptICAO, aosRunwayId[i], adfLat[i], adfLon[i], dfWidth, bBuoys);
768 : }
769 :
770 : }
771 :
772 1 : dfLength = OGRXPlane_Distance(adfLat[0], adfLon[0], adfLat[1], adfLon[1]);
773 :
774 1 : if (poWaterRunwayThresholdLayer)
775 : {
776 : poWaterRunwayThresholdLayer->SetRunwayLengthAndHeading(apoWaterRunwayThreshold[0], dfLength,
777 1 : OGRXPlane_Track(adfLat[0], adfLon[0], adfLat[1], adfLon[1]));
778 : poWaterRunwayThresholdLayer->SetRunwayLengthAndHeading(apoWaterRunwayThreshold[1], dfLength,
779 1 : OGRXPlane_Track(adfLat[1], adfLon[1], adfLat[0], adfLon[0]));
780 : }
781 :
782 1 : if (poWaterRunwayLayer)
783 : {
784 : poWaterRunwayLayer->AddFeature(osAptICAO, aosRunwayId[0], aosRunwayId[1],
785 : adfLat[0], adfLon[0], adfLat[1], adfLon[1],
786 1 : dfWidth, bBuoys);
787 0 : }
788 : }
789 :
790 : /************************************************************************/
791 : /* ParseHelipadRecord() */
792 : /************************************************************************/
793 :
794 1 : void OGRXPlaneAptReader::ParseHelipadRecord()
795 : {
796 : double dfLat, dfLon, dfTrueHeading, dfLength, dfWidth, dfSmoothness;
797 : int eSurfaceCode, eMarkings, eShoulderCode, eEdgeLighting;
798 : const char* pszHelipadName;
799 :
800 1 : RET_IF_FAIL(assertMinCol(12));
801 :
802 1 : pszHelipadName = papszTokens[1];
803 1 : RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 2));
804 1 : RET_IF_FAIL(readTrueHeading(&dfTrueHeading, 4));
805 1 : RET_IF_FAIL(readDouble(&dfLength, 5, "length"));
806 1 : RET_IF_FAIL(readDouble(&dfWidth, 6, "width"));
807 1 : eSurfaceCode = atoi(papszTokens[7]);
808 1 : eMarkings = atoi(papszTokens[8]);
809 1 : eShoulderCode = atoi(papszTokens[9]);
810 1 : RET_IF_FAIL(readDoubleWithBounds(&dfSmoothness, 10, "helipad smoothness", 0., 1.));
811 1 : eEdgeLighting = atoi(papszTokens[11]);
812 :
813 1 : if (poHelipadLayer)
814 : {
815 : poHelipadLayer->AddFeature(osAptICAO, pszHelipadName, dfLat, dfLon,
816 : dfTrueHeading, dfLength, dfWidth,
817 : RunwaySurfaceEnumeration.GetText(eSurfaceCode),
818 : RunwayMarkingEnumeration.GetText(eMarkings),
819 : RunwayShoulderEnumeration.GetText(eShoulderCode),
820 : dfSmoothness,
821 1 : HelipadEdgeLightingEnumeration.GetText(eEdgeLighting));
822 : }
823 :
824 1 : if (poHelipadPolygonLayer)
825 : {
826 : poHelipadPolygonLayer->AddFeature(osAptICAO, pszHelipadName, dfLat, dfLon,
827 : dfTrueHeading, dfLength, dfWidth,
828 : RunwaySurfaceEnumeration.GetText(eSurfaceCode),
829 : RunwayMarkingEnumeration.GetText(eMarkings),
830 : RunwayShoulderEnumeration.GetText(eShoulderCode),
831 : dfSmoothness,
832 1 : HelipadEdgeLightingEnumeration.GetText(eEdgeLighting));
833 : }
834 : }
835 :
836 :
837 :
838 : /************************************************************************/
839 : /* AddBezierCurve() */
840 : /************************************************************************/
841 :
842 : #define CUBIC_INTERPOL(A, B, C, D) ((A)*(b*b*b) + 3*(B)*(b*b)*a + 3 *(C)*b*(a*a) + (D)*(a*a*a))
843 :
844 : void OGRXPlaneAptReader::AddBezierCurve(OGRLineString& lineString,
845 : double dfLatA, double dfLonA,
846 : double dfCtrPtLatA, double dfCtrPtLonA,
847 : double dfSymCtrlPtLatB, double dfSymCtrlPtLonB,
848 239 : double dfLatB, double dfLonB)
849 : {
850 : int step;
851 2868 : for(step = 0; step <= 10; step++)
852 : {
853 2629 : double a = step / 10.;
854 2629 : double b = 1. - a;
855 2629 : double dfCtrlPtLonB = dfLonB - (dfSymCtrlPtLonB - dfLonB);
856 2629 : double dfCtrlPtLatB = dfLatB - (dfSymCtrlPtLatB - dfLatB);
857 : lineString.addPoint(CUBIC_INTERPOL(dfLonA, dfCtrPtLonA, dfCtrlPtLonB, dfLonB),
858 2629 : CUBIC_INTERPOL(dfLatA, dfCtrPtLatA, dfCtrlPtLatB, dfLatB));
859 : }
860 239 : }
861 :
862 :
863 : #define QUADRATIC_INTERPOL(A, B, C) ((A)*(b*b) + 2*(B)*b*a + (C)*(a*a))
864 :
865 : void OGRXPlaneAptReader::AddBezierCurve(OGRLineString& lineString,
866 : double dfLatA, double dfLonA,
867 : double dfCtrPtLat, double dfCtrPtLon,
868 89 : double dfLatB, double dfLonB)
869 : {
870 : int step;
871 1068 : for(step = 0; step <= 10; step++)
872 : {
873 979 : double a = step / 10.;
874 979 : double b = 1. - a;
875 : lineString.addPoint(QUADRATIC_INTERPOL(dfLonA, dfCtrPtLon, dfLonB),
876 979 : QUADRATIC_INTERPOL(dfLatA, dfCtrPtLat, dfLatB));
877 : }
878 89 : }
879 :
880 2 : static OGRGeometry* OGRXPlaneAptReaderSplitPolygon(OGRPolygon& polygon)
881 : {
882 2 : OGRPolygon** papoPolygons = new OGRPolygon* [1 + polygon.getNumInteriorRings()];
883 :
884 2 : papoPolygons[0] = new OGRPolygon();
885 2 : papoPolygons[0]->addRing(polygon.getExteriorRing());
886 12 : for(int i=0;i<polygon.getNumInteriorRings();i++)
887 : {
888 4 : papoPolygons[i+1] = new OGRPolygon();
889 4 : papoPolygons[i+1]->addRing(polygon.getInteriorRing(i));
890 : }
891 :
892 : int bIsValid;
893 : OGRGeometry* poGeom;
894 : poGeom = OGRGeometryFactory::organizePolygons((OGRGeometry**)papoPolygons,
895 : 1 + polygon.getNumInteriorRings(),
896 2 : &bIsValid, NULL);
897 :
898 2 : delete[] papoPolygons;
899 :
900 2 : return poGeom;
901 : }
902 :
903 : /************************************************************************/
904 : /* FixPolygonTopology() */
905 : /************************************************************************/
906 :
907 : /*
908 : Intended to fix several topological problems, like when a point of an interior ring
909 : is on the edge of the external ring, or other topological anomalies.
910 : */
911 :
912 12 : OGRGeometry* OGRXPlaneAptReader::FixPolygonTopology(OGRPolygon& polygon)
913 : {
914 12 : OGRLinearRing* poExternalRing = polygon.getExteriorRing();
915 12 : if (poExternalRing->getNumPoints() < 4)
916 : {
917 0 : CPLDebug("XPLANE", "Discarded degenerated polygon at line %d", nLineNumber);
918 0 : return NULL;
919 : }
920 :
921 12 : for(int i=0;i<polygon.getNumInteriorRings();i++)
922 : {
923 2 : OGRLinearRing* poInternalRing = polygon.getInteriorRing(i);
924 2 : if (poInternalRing->getNumPoints() < 4)
925 : {
926 0 : CPLDebug("XPLANE", "Discarded degenerated interior ring (%d) at line %d", i, nLineNumber);
927 0 : OGRPolygon polygon2;
928 0 : polygon2.addRing(poExternalRing);
929 0 : for(int j=0;j<polygon.getNumInteriorRings();j++)
930 : {
931 0 : if (i != j)
932 0 : polygon2.addRing(polygon.getInteriorRing(j));
933 : }
934 0 : polygon = * (OGRPolygon*) (polygon2.clone());
935 0 : i --;
936 0 : continue;
937 : }
938 :
939 2 : int nOutside = 0;
940 2 : int jOutside = -1;
941 101 : for(int j=0;j<poInternalRing->getNumPoints();j++)
942 : {
943 99 : OGRPoint pt;
944 99 : poInternalRing->getPoint(j, &pt);
945 99 : if (poExternalRing->isPointInRing(&pt) == FALSE)
946 : {
947 0 : nOutside++;
948 0 : jOutside = j;
949 : }
950 : }
951 :
952 2 : if (nOutside == 1)
953 : {
954 0 : int j = jOutside;
955 0 : OGRPoint pt;
956 0 : poInternalRing->getPoint(j, &pt);
957 0 : OGRPoint newPt;
958 0 : int bSuccess = FALSE;
959 0 : for(int k=-1;k<=1 && !bSuccess;k+=2)
960 : {
961 0 : for(int l=-1;l<=1 && !bSuccess;l+=2)
962 : {
963 0 : newPt.setX(pt.getX() + k * 1e-7);
964 0 : newPt.setY(pt.getY() + l * 1e-7);
965 0 : if (poExternalRing->isPointInRing(&newPt))
966 : {
967 0 : poInternalRing->setPoint(j, newPt.getX(), newPt.getY());
968 0 : bSuccess = TRUE;
969 : }
970 : }
971 : }
972 0 : if (!bSuccess)
973 : {
974 : CPLDebug("XPLANE",
975 0 : "Didn't manage to fix polygon topology at line %d", nLineNumber);
976 :
977 : /* Invalid topology. Will split into several pieces */
978 0 : return OGRXPlaneAptReaderSplitPolygon(polygon);
979 0 : }
980 : }
981 : else
982 : {
983 : /* Two parts. Or other strange cases */
984 2 : return OGRXPlaneAptReaderSplitPolygon(polygon);
985 : }
986 : }
987 :
988 : /* The geometry is right */
989 10 : return polygon.clone();
990 : }
991 :
992 : /************************************************************************/
993 : /* ParsePolygonalGeometry() */
994 : /************************************************************************/
995 :
996 : /* This function will eat records until the end of the polygon */
997 : /* Return TRUE if the main parser must re-scan the current record */
998 :
999 : #define RET_FALSE_IF_FAIL(x) if (!(x)) return FALSE;
1000 :
1001 12 : int OGRXPlaneAptReader::ParsePolygonalGeometry(OGRGeometry** ppoGeom)
1002 : {
1003 : double dfLat, dfLon;
1004 12 : double dfFirstLat = 0., dfFirstLon = 0.;
1005 12 : double dfLastLat = 0., dfLastLon = 0.;
1006 : double dfLatBezier, dfLonBezier;
1007 12 : double dfFirstLatBezier = 0., dfFirstLonBezier = 0.;
1008 12 : double dfLastLatBezier = 0., dfLastLonBezier = 0.;
1009 12 : int bIsFirst = TRUE;
1010 12 : int bFirstIsBezier = TRUE;
1011 12 : int bLastIsValid = FALSE;
1012 12 : int bLastIsBezier = FALSE;
1013 12 : int bLastPartIsClosed = FALSE;
1014 : const char* pszLine;
1015 12 : OGRPolygon polygon;
1016 :
1017 12 : OGRLinearRing linearRing;
1018 :
1019 12 : *ppoGeom = NULL;
1020 :
1021 400 : while((pszLine = CPLReadLine(fp)) != NULL)
1022 : {
1023 388 : int nType = -1;
1024 388 : papszTokens = CSLTokenizeString(pszLine);
1025 388 : nTokens = CSLCount(papszTokens);
1026 :
1027 388 : nLineNumber ++;
1028 :
1029 388 : if (nTokens == 1 && strcmp(papszTokens[0], "99") == 0)
1030 : {
1031 0 : if (bLastPartIsClosed == FALSE)
1032 : {
1033 : CPLDebug("XPlane", "Line %d : Unexpected token when reading a polygon : %d",
1034 0 : nLineNumber, nType);
1035 : }
1036 : else
1037 : {
1038 0 : *ppoGeom = FixPolygonTopology(polygon);
1039 : }
1040 :
1041 0 : return TRUE;
1042 : }
1043 388 : if (nTokens == 0 || assertMinCol(2) == FALSE)
1044 : {
1045 0 : CSLDestroy(papszTokens);
1046 0 : continue;
1047 : }
1048 :
1049 388 : nType = atoi(papszTokens[0]);
1050 388 : if (nType == APT_NODE)
1051 : {
1052 155 : RET_FALSE_IF_FAIL(assertMinCol(3));
1053 155 : RET_FALSE_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
1054 :
1055 198 : if (bLastIsBezier && !bIsFirst &&
1056 : !(dfLastLat == dfLat && dfLastLon == dfLon))
1057 : {
1058 : AddBezierCurve(linearRing,
1059 : dfLastLat, dfLastLon,
1060 : dfLastLatBezier, dfLastLonBezier,
1061 43 : dfLat, dfLon);
1062 : }
1063 : else
1064 112 : linearRing.addPoint(dfLon, dfLat);
1065 :
1066 155 : bLastPartIsClosed = FALSE;
1067 155 : bLastIsBezier = FALSE;
1068 : }
1069 233 : else if (nType == APT_NODE_WITH_BEZIER)
1070 : {
1071 205 : RET_FALSE_IF_FAIL(assertMinCol(5));
1072 205 : RET_FALSE_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
1073 205 : RET_FALSE_IF_FAIL(readLatLon(&dfLatBezier, &dfLonBezier, 3));
1074 :
1075 205 : if (bLastIsBezier)
1076 : {
1077 : AddBezierCurve(linearRing,
1078 : dfLastLat, dfLastLon,
1079 : dfLastLatBezier, dfLastLonBezier,
1080 : dfLatBezier, dfLonBezier,
1081 148 : dfLat, dfLon);
1082 : }
1083 57 : else if (!bIsFirst && !(dfLastLat == dfLat && dfLastLon == dfLon))
1084 : {
1085 42 : double dfCtrLatBezier = dfLat - (dfLatBezier - dfLat);
1086 42 : double dfCtrLonBezier = dfLon - (dfLonBezier - dfLon);
1087 : AddBezierCurve(linearRing,
1088 : dfLastLat, dfLastLon,
1089 : dfCtrLatBezier, dfCtrLonBezier,
1090 42 : dfLat, dfLon);
1091 : }
1092 :
1093 205 : bLastPartIsClosed = FALSE;
1094 205 : bLastIsBezier = TRUE;
1095 205 : dfLastLatBezier = dfLatBezier;
1096 205 : dfLastLonBezier = dfLonBezier;
1097 : }
1098 28 : else if (nType == APT_NODE_CLOSE)
1099 : {
1100 8 : RET_FALSE_IF_FAIL(assertMinCol(3));
1101 8 : RET_FALSE_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
1102 8 : if (bIsFirst)
1103 : {
1104 : CPLDebug("XPlane", "Line %d : Unexpected token when reading a polygon : %d",
1105 0 : nLineNumber, nType);
1106 0 : return TRUE;
1107 : }
1108 :
1109 8 : if (bLastIsBezier && !bIsFirst &&
1110 : !(dfLastLat == dfLat && dfLastLon == dfLon))
1111 : {
1112 : AddBezierCurve(linearRing,
1113 : dfLastLat, dfLastLon,
1114 : dfLastLatBezier, dfLastLonBezier,
1115 0 : dfLat, dfLon);
1116 : }
1117 : else
1118 8 : linearRing.addPoint(dfLon, dfLat);
1119 :
1120 8 : linearRing.closeRings();
1121 :
1122 8 : polygon.addRing(&linearRing);
1123 8 : linearRing.empty();
1124 :
1125 8 : bLastPartIsClosed = TRUE;
1126 8 : bLastIsBezier = FALSE;
1127 : }
1128 20 : else if (nType == APT_NODE_CLOSE_WITH_BEZIER)
1129 : {
1130 8 : RET_FALSE_IF_FAIL(assertMinCol(5));
1131 8 : RET_FALSE_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
1132 8 : RET_FALSE_IF_FAIL(readLatLon(&dfLatBezier, &dfLonBezier, 3));
1133 8 : if (bIsFirst)
1134 : {
1135 : CPLDebug("XPlane", "Line %d : Unexpected token when reading a polygon : %d",
1136 0 : nLineNumber, nType);
1137 0 : return TRUE;
1138 : }
1139 :
1140 8 : if (bLastIsBezier)
1141 : {
1142 : AddBezierCurve(linearRing,
1143 : dfLastLat, dfLastLon,
1144 : dfLastLatBezier, dfLastLonBezier,
1145 : dfLatBezier, dfLonBezier,
1146 6 : dfLat, dfLon);
1147 : }
1148 3 : else if (!bIsFirst && !(dfLastLat == dfLat && dfLastLon == dfLon))
1149 : {
1150 1 : double dfCtrLatBezier = dfLat - (dfLatBezier - dfLat);
1151 1 : double dfCtrLonBezier = dfLon - (dfLonBezier - dfLon);
1152 : AddBezierCurve(linearRing,
1153 : dfLastLat, dfLastLon,
1154 : dfCtrLatBezier, dfCtrLonBezier,
1155 1 : dfLat, dfLon);
1156 : }
1157 : else
1158 : {
1159 1 : linearRing.addPoint(dfLon, dfLat);
1160 : }
1161 :
1162 8 : if (bFirstIsBezier)
1163 : {
1164 : AddBezierCurve(linearRing,
1165 : dfLat, dfLon,
1166 : dfLatBezier, dfLonBezier,
1167 : dfFirstLatBezier, dfFirstLonBezier,
1168 6 : dfFirstLat, dfFirstLon);
1169 : }
1170 : else
1171 : {
1172 2 : linearRing.closeRings();
1173 : }
1174 :
1175 8 : polygon.addRing(&linearRing);
1176 8 : linearRing.empty();
1177 :
1178 8 : bLastPartIsClosed = TRUE;
1179 8 : bLastIsBezier = FALSE; /* we don't want to draw an arc between two parts */
1180 : }
1181 : else
1182 : {
1183 12 : if (nType == APT_NODE_END || nType == APT_NODE_END_WITH_BEZIER ||
1184 : bLastPartIsClosed == FALSE)
1185 : {
1186 : CPLDebug("XPlane", "Line %d : Unexpected token when reading a polygon : %d",
1187 0 : nLineNumber, nType);
1188 : }
1189 : else
1190 : {
1191 12 : *ppoGeom = FixPolygonTopology(polygon);
1192 : }
1193 :
1194 12 : return TRUE;
1195 : }
1196 :
1197 376 : if (bIsFirst)
1198 : {
1199 16 : dfFirstLat = dfLat;
1200 16 : dfFirstLon = dfLon;
1201 16 : dfFirstLatBezier = dfLatBezier;
1202 16 : dfFirstLonBezier = dfLonBezier;
1203 16 : bFirstIsBezier = bLastIsBezier;
1204 : }
1205 376 : bIsFirst = bLastPartIsClosed;
1206 :
1207 376 : dfLastLat = dfLat;
1208 376 : dfLastLon = dfLon;
1209 376 : bLastIsValid = TRUE;
1210 :
1211 376 : CSLDestroy(papszTokens);
1212 : }
1213 :
1214 0 : CPLAssert(0);
1215 :
1216 0 : papszTokens = NULL;
1217 :
1218 0 : return FALSE;
1219 : }
1220 :
1221 :
1222 : /************************************************************************/
1223 : /* ParsePavement() */
1224 : /************************************************************************/
1225 :
1226 11 : void OGRXPlaneAptReader::ParsePavement()
1227 : {
1228 : int eSurfaceCode;
1229 : double dfSmoothness, dfTextureHeading;
1230 11 : CPLString osPavementName;
1231 :
1232 11 : RET_IF_FAIL(assertMinCol(4));
1233 :
1234 11 : eSurfaceCode = atoi(papszTokens[1]);
1235 :
1236 11 : RET_IF_FAIL(readDoubleWithBounds(&dfSmoothness, 2, "pavement smoothness", 0., 1.));
1237 :
1238 11 : RET_IF_FAIL(readTrueHeading(&dfTextureHeading, 3, "texture heading"));
1239 :
1240 11 : osPavementName = readStringUntilEnd(4);
1241 :
1242 11 : CSLDestroy(papszTokens);
1243 11 : papszTokens = NULL;
1244 :
1245 : OGRGeometry* poGeom;
1246 11 : bResumeLine = ParsePolygonalGeometry(&poGeom);
1247 11 : if (poGeom != NULL && poPavementLayer)
1248 : {
1249 11 : if (poGeom->getGeometryType() == wkbPolygon)
1250 : {
1251 : poPavementLayer->AddFeature(osAptICAO, osPavementName,
1252 : RunwaySurfaceEnumeration.GetText(eSurfaceCode),
1253 : dfSmoothness, dfTextureHeading,
1254 11 : (OGRPolygon*)poGeom);
1255 : }
1256 : else
1257 : {
1258 0 : OGRGeometryCollection* poGeomCollection = (OGRGeometryCollection*)poGeom;
1259 0 : for(int i=0;i<poGeomCollection->getNumGeometries();i++)
1260 : {
1261 0 : OGRGeometry* poSubGeom = poGeomCollection->getGeometryRef(i);
1262 0 : if (poSubGeom->getGeometryType() == wkbPolygon &&
1263 : ((OGRPolygon*)poSubGeom)->getExteriorRing()->getNumPoints() >= 4)
1264 : {
1265 : poPavementLayer->AddFeature(osAptICAO, osPavementName,
1266 : RunwaySurfaceEnumeration.GetText(eSurfaceCode),
1267 : dfSmoothness, dfTextureHeading,
1268 0 : (OGRPolygon*)poSubGeom);
1269 : }
1270 : }
1271 : }
1272 : }
1273 11 : if (poGeom != NULL)
1274 11 : delete poGeom;
1275 : }
1276 :
1277 : /************************************************************************/
1278 : /* ParseAPTBoundary() */
1279 : /************************************************************************/
1280 :
1281 : /* This function will eat records until the end of the boundary definition */
1282 : /* Return TRUE if the main parser must re-scan the current record */
1283 :
1284 1 : void OGRXPlaneAptReader::ParseAPTBoundary()
1285 : {
1286 1 : CPLString osBoundaryName;
1287 :
1288 1 : RET_IF_FAIL(assertMinCol(2));
1289 :
1290 1 : osBoundaryName = readStringUntilEnd(2);
1291 :
1292 1 : CSLDestroy(papszTokens);
1293 1 : papszTokens = NULL;
1294 :
1295 : OGRGeometry* poGeom;
1296 1 : bResumeLine = ParsePolygonalGeometry(&poGeom);
1297 1 : if (poGeom != NULL && poAPTBoundaryLayer)
1298 : {
1299 1 : if (poGeom->getGeometryType() == wkbPolygon)
1300 : {
1301 : poAPTBoundaryLayer->AddFeature(osAptICAO, osBoundaryName,
1302 1 : (OGRPolygon*)poGeom);
1303 : }
1304 : else
1305 : {
1306 0 : OGRGeometryCollection* poGeomCollection = (OGRGeometryCollection*)poGeom;
1307 0 : for(int i=0;i<poGeomCollection->getNumGeometries();i++)
1308 : {
1309 0 : OGRGeometry* poSubGeom = poGeomCollection->getGeometryRef(i);
1310 0 : if (poSubGeom->getGeometryType() == wkbPolygon &&
1311 : ((OGRPolygon*)poSubGeom)->getExteriorRing()->getNumPoints() >= 4)
1312 : {
1313 : poAPTBoundaryLayer->AddFeature(osAptICAO, osBoundaryName,
1314 0 : (OGRPolygon*)poSubGeom);
1315 : }
1316 : }
1317 : }
1318 : }
1319 1 : if (poGeom != NULL)
1320 1 : delete poGeom;
1321 : }
1322 :
1323 :
1324 : /************************************************************************/
1325 : /* ParseLinearGeometry() */
1326 : /************************************************************************/
1327 :
1328 : /* This function will eat records until the end of the multilinestring */
1329 : /* Return TRUE if the main parser must re-scan the current record */
1330 :
1331 45 : int OGRXPlaneAptReader::ParseLinearGeometry(OGRMultiLineString& multilinestring, int* pbIsValid)
1332 : {
1333 : double dfLat, dfLon;
1334 45 : double dfFirstLat = 0., dfFirstLon = 0.;
1335 45 : double dfLastLat = 0., dfLastLon = 0.;
1336 : double dfLatBezier, dfLonBezier;
1337 45 : double dfFirstLatBezier = 0., dfFirstLonBezier = 0.;
1338 45 : double dfLastLatBezier = 0., dfLastLonBezier = 0.;
1339 45 : int bIsFirst = TRUE;
1340 45 : int bFirstIsBezier = TRUE;
1341 45 : int bLastIsValid = FALSE;
1342 45 : int bLastIsBezier = FALSE;
1343 45 : int bLastPartIsClosedOrEnded = FALSE;
1344 : const char* pszLine;
1345 :
1346 45 : OGRLineString lineString;
1347 :
1348 234 : while((pszLine = CPLReadLine(fp)) != NULL)
1349 : {
1350 189 : int nType = -1;
1351 189 : papszTokens = CSLTokenizeString(pszLine);
1352 189 : nTokens = CSLCount(papszTokens);
1353 :
1354 189 : nLineNumber ++;
1355 :
1356 189 : if (nTokens == 1 && strcmp(papszTokens[0], "99") == 0)
1357 : {
1358 0 : if (bLastPartIsClosedOrEnded == FALSE)
1359 : {
1360 : CPLDebug("XPlane", "Line %d : Unexpected token when reading a linear feature : %d",
1361 0 : nLineNumber, nType);
1362 : }
1363 0 : else if (multilinestring.getNumGeometries() == 0)
1364 : {
1365 : CPLDebug("XPlane", "Line %d : Linear geometry is invalid or empty",
1366 0 : nLineNumber);
1367 : }
1368 : else
1369 : {
1370 0 : *pbIsValid = TRUE;
1371 : }
1372 0 : return TRUE;
1373 : }
1374 189 : if (nTokens == 0 || assertMinCol(2) == FALSE)
1375 : {
1376 0 : CSLDestroy(papszTokens);
1377 0 : continue;
1378 : }
1379 :
1380 189 : nType = atoi(papszTokens[0]);
1381 189 : if (nType == APT_NODE)
1382 : {
1383 20 : RET_FALSE_IF_FAIL(assertMinCol(3));
1384 20 : RET_FALSE_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
1385 :
1386 20 : if (bLastIsBezier && !bIsFirst &&
1387 : !(dfLastLat == dfLat && dfLastLon == dfLon))
1388 : {
1389 : AddBezierCurve(lineString,
1390 : dfLastLat, dfLastLon,
1391 : dfLastLatBezier, dfLastLonBezier,
1392 0 : dfLat, dfLon);
1393 : }
1394 : else
1395 20 : lineString.addPoint(dfLon, dfLat);
1396 :
1397 20 : bLastPartIsClosedOrEnded = FALSE;
1398 20 : bLastIsBezier = FALSE;
1399 : }
1400 169 : else if (nType == APT_NODE_WITH_BEZIER)
1401 : {
1402 79 : RET_FALSE_IF_FAIL(assertMinCol(5));
1403 79 : RET_FALSE_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
1404 79 : RET_FALSE_IF_FAIL(readLatLon(&dfLatBezier, &dfLonBezier, 3));
1405 :
1406 79 : if (bLastIsBezier)
1407 : {
1408 : AddBezierCurve(lineString,
1409 : dfLastLat, dfLastLon,
1410 : dfLastLatBezier, dfLastLonBezier,
1411 : dfLatBezier, dfLonBezier,
1412 48 : dfLat, dfLon);
1413 : }
1414 31 : else if (!bIsFirst && !(dfLastLat == dfLat && dfLastLon == dfLon))
1415 : {
1416 2 : double dfCtrLatBezier = dfLat - (dfLatBezier - dfLat);
1417 2 : double dfCtrLonBezier = dfLon - (dfLonBezier - dfLon);
1418 : AddBezierCurve(lineString,
1419 : dfLastLat, dfLastLon,
1420 : dfCtrLatBezier, dfCtrLonBezier,
1421 2 : dfLat, dfLon);
1422 : }
1423 :
1424 79 : bLastPartIsClosedOrEnded = FALSE;
1425 79 : bLastIsBezier = TRUE;
1426 79 : dfLastLatBezier = dfLatBezier;
1427 79 : dfLastLonBezier = dfLonBezier;
1428 : }
1429 103 : else if (nType == APT_NODE_CLOSE || nType == APT_NODE_END)
1430 : {
1431 13 : RET_FALSE_IF_FAIL(assertMinCol(3));
1432 13 : RET_FALSE_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
1433 13 : if (bIsFirst)
1434 : {
1435 : CPLDebug("XPlane", "Line %d : Unexpected token when reading a linear feature : %d",
1436 0 : nLineNumber, nType);
1437 0 : return TRUE;
1438 : }
1439 :
1440 13 : if (bLastIsBezier && !(dfLastLat == dfLat && dfLastLon == dfLon))
1441 : {
1442 : AddBezierCurve(lineString,
1443 : dfLastLat, dfLastLon,
1444 : dfLastLatBezier, dfLastLonBezier,
1445 0 : dfLat, dfLon);
1446 : }
1447 : else
1448 13 : lineString.addPoint(dfLon, dfLat);
1449 :
1450 13 : if (nType == APT_NODE_CLOSE )
1451 0 : lineString.closeRings();
1452 :
1453 13 : if (lineString.getNumPoints() < 2)
1454 : {
1455 : CPLDebug("XPlane", "Line %d : A linestring has less than 2 points",
1456 0 : nLineNumber);
1457 : }
1458 : else
1459 : {
1460 13 : multilinestring.addGeometry(&lineString);
1461 : }
1462 13 : lineString.empty();
1463 :
1464 13 : bLastPartIsClosedOrEnded = TRUE;
1465 13 : bLastIsBezier = FALSE;
1466 : }
1467 109 : else if (nType == APT_NODE_CLOSE_WITH_BEZIER || nType == APT_NODE_END_WITH_BEZIER)
1468 : {
1469 32 : RET_FALSE_IF_FAIL(assertMinCol(5));
1470 32 : RET_FALSE_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
1471 32 : RET_FALSE_IF_FAIL(readLatLon(&dfLatBezier, &dfLonBezier, 3));
1472 32 : if (bIsFirst)
1473 : {
1474 : CPLDebug("XPlane", "Line %d : Unexpected token when reading a linear feature : %d",
1475 0 : nLineNumber, nType);
1476 0 : return TRUE;
1477 : }
1478 :
1479 32 : if (bLastIsBezier)
1480 : {
1481 : AddBezierCurve(lineString,
1482 : dfLastLat, dfLastLon,
1483 : dfLastLatBezier, dfLastLonBezier,
1484 : dfLatBezier, dfLonBezier,
1485 31 : dfLat, dfLon);
1486 : }
1487 2 : else if (!bIsFirst && !(dfLastLat == dfLat && dfLastLon == dfLon))
1488 : {
1489 1 : double dfCtrLatBezier = dfLat - (dfLatBezier - dfLat);
1490 1 : double dfCtrLonBezier = dfLon - (dfLonBezier - dfLon);
1491 : AddBezierCurve(lineString,
1492 : dfLastLat, dfLastLon,
1493 : dfCtrLatBezier, dfCtrLonBezier,
1494 1 : dfLat, dfLon);
1495 : }
1496 : else
1497 : {
1498 0 : lineString.addPoint(dfLon, dfLat);
1499 : }
1500 :
1501 32 : if (nType == APT_NODE_CLOSE_WITH_BEZIER)
1502 : {
1503 0 : if (bFirstIsBezier)
1504 : {
1505 : AddBezierCurve(lineString,
1506 : dfLat, dfLon,
1507 : dfLatBezier, dfLonBezier,
1508 : dfFirstLatBezier, dfFirstLonBezier,
1509 0 : dfFirstLat, dfFirstLon);
1510 : }
1511 : else
1512 : {
1513 0 : lineString.closeRings();
1514 : }
1515 : }
1516 :
1517 32 : if (lineString.getNumPoints() < 2)
1518 : {
1519 : CPLDebug("XPlane", "Line %d : A linestring has less than 2 points",
1520 0 : nLineNumber);
1521 : }
1522 : else
1523 : {
1524 32 : multilinestring.addGeometry(&lineString);
1525 : }
1526 32 : lineString.empty();
1527 :
1528 32 : bLastPartIsClosedOrEnded = TRUE;
1529 32 : bLastIsBezier = FALSE; /* we don't want to draw an arc between two parts */
1530 : }
1531 : else
1532 : {
1533 45 : if (bLastPartIsClosedOrEnded == FALSE)
1534 : {
1535 : CPLDebug("XPlane", "Line %d : Unexpected token when reading a linear feature : %d",
1536 0 : nLineNumber, nType);
1537 : }
1538 45 : else if (multilinestring.getNumGeometries() == 0)
1539 : {
1540 : CPLDebug("XPlane", "Line %d : Linear geometry is invalid or empty",
1541 0 : nLineNumber);
1542 : }
1543 : else
1544 : {
1545 45 : *pbIsValid = TRUE;
1546 : }
1547 45 : return TRUE;
1548 : }
1549 :
1550 144 : if (bIsFirst)
1551 : {
1552 45 : dfFirstLat = dfLat;
1553 45 : dfFirstLon = dfLon;
1554 45 : dfFirstLatBezier = dfLatBezier;
1555 45 : dfFirstLonBezier = dfLonBezier;
1556 45 : bFirstIsBezier = bLastIsBezier;
1557 : }
1558 144 : bIsFirst = bLastPartIsClosedOrEnded;
1559 :
1560 144 : dfLastLat = dfLat;
1561 144 : dfLastLon = dfLon;
1562 144 : bLastIsValid = TRUE;
1563 :
1564 144 : CSLDestroy(papszTokens);
1565 : }
1566 :
1567 0 : CPLAssert(0);
1568 :
1569 0 : papszTokens = NULL;
1570 :
1571 0 : return FALSE;
1572 : }
1573 :
1574 : /************************************************************************/
1575 : /* ParseAPTLinearFeature() */
1576 : /************************************************************************/
1577 :
1578 : /* This function will eat records until the end of the linear feature definition */
1579 : /* Return TRUE if the main parser must re-scan the current record */
1580 :
1581 45 : void OGRXPlaneAptReader::ParseAPTLinearFeature()
1582 : {
1583 45 : CPLString osLinearFeatureName;
1584 :
1585 45 : RET_IF_FAIL(assertMinCol(2));
1586 :
1587 45 : osLinearFeatureName = readStringUntilEnd(2);
1588 :
1589 45 : CSLDestroy(papszTokens);
1590 45 : papszTokens = NULL;
1591 :
1592 45 : OGRMultiLineString multilinestring;
1593 45 : int bIsValid = FALSE;
1594 45 : bResumeLine = ParseLinearGeometry(multilinestring, &bIsValid);
1595 45 : if (bIsValid && poAPTLinearFeatureLayer)
1596 : {
1597 : poAPTLinearFeatureLayer->AddFeature(osAptICAO, osLinearFeatureName,
1598 45 : &multilinestring);
1599 45 : }
1600 : }
1601 :
1602 : /************************************************************************/
1603 : /* ParseTowerRecord() */
1604 : /************************************************************************/
1605 :
1606 6 : void OGRXPlaneAptReader::ParseTowerRecord()
1607 : {
1608 6 : RET_IF_FAIL(assertMinCol(6));
1609 :
1610 6 : RET_IF_FAIL(readLatLon(&dfLatTower, &dfLonTower, 1));
1611 :
1612 : /* feet to meter */
1613 6 : RET_IF_FAIL(readDoubleWithBoundsAndConversion(&dfHeightTower, 3, "tower height", FEET_TO_METER, 0., 300.));
1614 :
1615 : // papszTokens[4] ignored
1616 :
1617 6 : osTowerName = readStringUntilEnd(5);
1618 :
1619 6 : bTowerFound = TRUE;
1620 : }
1621 :
1622 :
1623 : /************************************************************************/
1624 : /* ParseATCRecord() */
1625 : /************************************************************************/
1626 :
1627 52 : void OGRXPlaneAptReader::ParseATCRecord(int nType)
1628 : {
1629 : double dfFrequency;
1630 52 : CPLString osFreqName;
1631 :
1632 52 : RET_IF_FAIL(assertMinCol(2));
1633 :
1634 52 : RET_IF_FAIL(readDouble(&dfFrequency, 1, "frequency"));
1635 52 : dfFrequency /= 100.;
1636 :
1637 52 : osFreqName = readStringUntilEnd(2);
1638 :
1639 52 : if (poATCFreqLayer)
1640 : {
1641 : poATCFreqLayer->AddFeature(osAptICAO,
1642 : (nType == APT_ATC_AWOS_ASOS_ATIS) ? "ATIS" :
1643 : (nType == APT_ATC_CTAF) ? "CTAF" :
1644 : (nType == APT_ATC_CLD) ? "CLD" :
1645 : (nType == APT_ATC_GND) ? "GND" :
1646 : (nType == APT_ATC_TWR) ? "TWR" :
1647 : (nType == APT_ATC_APP) ? "APP" :
1648 : (nType == APT_ATC_DEP) ? "DEP" : "UNK",
1649 52 : osFreqName, dfFrequency);
1650 0 : }
1651 : }
1652 :
1653 :
1654 : /************************************************************************/
1655 : /* ParseStartupLocationRecord() */
1656 : /************************************************************************/
1657 :
1658 110 : void OGRXPlaneAptReader::ParseStartupLocationRecord()
1659 : {
1660 : double dfLat, dfLon, dfTrueHeading;
1661 110 : CPLString osName;
1662 :
1663 110 : RET_IF_FAIL(assertMinCol(4));
1664 :
1665 110 : RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
1666 :
1667 110 : RET_IF_FAIL(readTrueHeading(&dfTrueHeading, 3));
1668 :
1669 110 : osName = readStringUntilEnd(4);
1670 :
1671 110 : if (poStartupLocationLayer)
1672 110 : poStartupLocationLayer->AddFeature(osAptICAO, osName, dfLat, dfLon, dfTrueHeading);
1673 : }
1674 :
1675 : /************************************************************************/
1676 : /* ParseLightBeaconRecord() */
1677 : /************************************************************************/
1678 :
1679 5 : void OGRXPlaneAptReader::ParseLightBeaconRecord()
1680 : {
1681 : double dfLat, dfLon;
1682 : int eColor;
1683 5 : CPLString osName;
1684 :
1685 5 : RET_IF_FAIL(assertMinCol(4));
1686 5 : RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
1687 5 : eColor = atoi(papszTokens[3]);
1688 5 : osName = readStringUntilEnd(4);
1689 :
1690 5 : if (poAPTLightBeaconLayer)
1691 : poAPTLightBeaconLayer->AddFeature(osAptICAO, osName, dfLat, dfLon,
1692 5 : APTLightBeaconColorEnumeration.GetText(eColor));
1693 : }
1694 :
1695 : /************************************************************************/
1696 : /* ParseWindsockRecord() */
1697 : /************************************************************************/
1698 :
1699 34 : void OGRXPlaneAptReader::ParseWindsockRecord()
1700 : {
1701 : double dfLat, dfLon;
1702 : int bIsIllumnited;
1703 34 : CPLString osName;
1704 :
1705 34 : RET_IF_FAIL(assertMinCol(4));
1706 :
1707 34 : RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
1708 34 : bIsIllumnited = atoi(papszTokens[3]);
1709 34 : osName = readStringUntilEnd(4);
1710 :
1711 34 : if (poAPTWindsockLayer)
1712 : poAPTWindsockLayer->AddFeature(osAptICAO, osName, dfLat, dfLon,
1713 34 : bIsIllumnited);
1714 : }
1715 :
1716 : /************************************************************************/
1717 : /* ParseTaxiwaySignRecord */
1718 : /************************************************************************/
1719 :
1720 17 : void OGRXPlaneAptReader::ParseTaxiwaySignRecord()
1721 : {
1722 : double dfLat, dfLon;
1723 : double dfTrueHeading;
1724 : int nSize;
1725 17 : CPLString osText;
1726 :
1727 17 : RET_IF_FAIL(assertMinCol(7));
1728 :
1729 17 : RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
1730 17 : RET_IF_FAIL(readTrueHeading(&dfTrueHeading, 3, "heading"));
1731 : /* papszTokens[4] : ignored. Taxiway sign style */
1732 17 : nSize = atoi(papszTokens[5]);
1733 17 : osText = readStringUntilEnd(6);
1734 :
1735 17 : if (poTaxiwaySignLayer)
1736 : poTaxiwaySignLayer->AddFeature(osAptICAO, osText, dfLat, dfLon,
1737 17 : dfTrueHeading, nSize);
1738 : }
1739 :
1740 : /************************************************************************/
1741 : /* ParseVasiPapiWigWagRecord() */
1742 : /************************************************************************/
1743 :
1744 24 : void OGRXPlaneAptReader::ParseVasiPapiWigWagRecord()
1745 : {
1746 : double dfLat, dfLon;
1747 : int eType;
1748 : double dfTrueHeading, dfVisualGlidePathAngle;
1749 : const char* pszRwyNum;
1750 :
1751 24 : RET_IF_FAIL(assertMinCol(7));
1752 :
1753 24 : RET_IF_FAIL(readLatLon(&dfLat, &dfLon, 1));
1754 24 : eType = atoi(papszTokens[3]);
1755 24 : RET_IF_FAIL(readTrueHeading(&dfTrueHeading, 4, "heading"));
1756 24 : RET_IF_FAIL(readDoubleWithBounds(&dfVisualGlidePathAngle, 5, "visual glidepath angle", 0, 90));
1757 24 : pszRwyNum = papszTokens[6];
1758 : /* papszTokens[7] : ignored. Type of lighting object represented */
1759 :
1760 24 : if (poVASI_PAPI_WIGWAG_Layer)
1761 : poVASI_PAPI_WIGWAG_Layer->AddFeature(osAptICAO, pszRwyNum, VASI_PAPI_WIGWAG_Enumeration.GetText(eType),
1762 : dfLat, dfLon,
1763 24 : dfTrueHeading, dfVisualGlidePathAngle);
1764 : }
1765 :
1766 : /************************************************************************/
1767 : /* OGRXPlaneAPTLayer() */
1768 : /************************************************************************/
1769 :
1770 :
1771 2 : OGRXPlaneAPTLayer::OGRXPlaneAPTLayer() : OGRXPlaneLayer("APT")
1772 : {
1773 2 : poFeatureDefn->SetGeomType( wkbPoint );
1774 :
1775 2 : OGRFieldDefn oFieldID("apt_icao", OFTString );
1776 2 : oFieldID.SetWidth( 4 );
1777 2 : poFeatureDefn->AddFieldDefn( &oFieldID );
1778 :
1779 2 : OGRFieldDefn oFieldName("apt_name", OFTString );
1780 2 : poFeatureDefn->AddFieldDefn( &oFieldName );
1781 :
1782 2 : OGRFieldDefn oType("type", OFTInteger );
1783 2 : oType.SetWidth( 1 );
1784 2 : poFeatureDefn->AddFieldDefn( &oType );
1785 :
1786 2 : OGRFieldDefn oFieldElev("elevation_m", OFTReal );
1787 2 : oFieldElev.SetWidth( 8 );
1788 2 : oFieldElev.SetPrecision( 2 );
1789 2 : poFeatureDefn->AddFieldDefn( &oFieldElev );
1790 :
1791 2 : OGRFieldDefn oFieldHasTower("has_tower", OFTInteger );
1792 2 : oFieldHasTower.SetWidth( 1 );
1793 2 : poFeatureDefn->AddFieldDefn( &oFieldHasTower );
1794 :
1795 2 : OGRFieldDefn oFieldHeightTower("hgt_tower_m", OFTReal );
1796 2 : oFieldHeightTower.SetWidth( 8 );
1797 2 : oFieldHeightTower.SetPrecision( 2 );
1798 2 : poFeatureDefn->AddFieldDefn( &oFieldHeightTower );
1799 :
1800 2 : OGRFieldDefn oFieldTowerName("tower_name", OFTString );
1801 2 : poFeatureDefn->AddFieldDefn( &oFieldTowerName );
1802 :
1803 2 : }
1804 :
1805 : /************************************************************************/
1806 : /* AddFeature() */
1807 : /************************************************************************/
1808 :
1809 : OGRFeature*
1810 : OGRXPlaneAPTLayer::AddFeature(const char* pszAptICAO,
1811 : const char* pszAptName,
1812 : int nAPTType,
1813 : double dfElevation,
1814 : int bHasCoordinates,
1815 : double dfLat,
1816 : double dfLon,
1817 : int bHasTower,
1818 : double dfHeightTower,
1819 14 : const char* pszTowerName)
1820 : {
1821 14 : int nCount = 0;
1822 14 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
1823 14 : poFeature->SetField( nCount++, pszAptICAO );
1824 14 : poFeature->SetField( nCount++, pszAptName );
1825 : poFeature->SetField( nCount++, (nAPTType == APT_AIRPORT_HEADER) ? 0 :
1826 : (nAPTType == APT_SEAPLANE_HEADER) ? 1 :
1827 16 : /*(nAPTType == APT_HELIPORT_HEADER)*/ 2 );
1828 14 : poFeature->SetField( nCount++, dfElevation );
1829 14 : poFeature->SetField( nCount++, bHasTower );
1830 14 : if (bHasCoordinates)
1831 : {
1832 14 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
1833 : }
1834 : else
1835 : {
1836 0 : CPLDebug("XPlane", "Airport %s/%s has no coordinates", pszAptICAO, pszAptName);
1837 : }
1838 14 : if (bHasTower)
1839 : {
1840 6 : poFeature->SetField( nCount++, dfHeightTower );
1841 6 : poFeature->SetField( nCount++, pszTowerName );
1842 : }
1843 :
1844 14 : RegisterFeature(poFeature);
1845 :
1846 14 : return poFeature;
1847 : }
1848 :
1849 : /************************************************************************/
1850 : /* OGRXPlaneRunwayThresholdLayer() */
1851 : /************************************************************************/
1852 :
1853 :
1854 2 : OGRXPlaneRunwayThresholdLayer::OGRXPlaneRunwayThresholdLayer() : OGRXPlaneLayer("RunwayThreshold")
1855 : {
1856 2 : poFeatureDefn->SetGeomType( wkbPoint );
1857 :
1858 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
1859 2 : oFieldAptICAO.SetWidth( 4 );
1860 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
1861 :
1862 2 : OGRFieldDefn oFieldRwyNum("rwy_num", OFTString );
1863 2 : oFieldRwyNum.SetWidth( 3 );
1864 2 : poFeatureDefn->AddFieldDefn( &oFieldRwyNum );
1865 :
1866 2 : OGRFieldDefn oFieldWidth("width_m", OFTReal );
1867 2 : oFieldWidth.SetWidth( 3 );
1868 2 : poFeatureDefn->AddFieldDefn( &oFieldWidth );
1869 :
1870 2 : OGRFieldDefn oFieldSurface("surface", OFTString );
1871 2 : poFeatureDefn->AddFieldDefn( &oFieldSurface );
1872 :
1873 2 : OGRFieldDefn oFieldShoulder("shoulder", OFTString );
1874 2 : poFeatureDefn->AddFieldDefn( &oFieldShoulder );
1875 :
1876 2 : OGRFieldDefn oFieldSmoothness("smoothness", OFTReal );
1877 2 : oFieldSmoothness.SetWidth( 4 );
1878 2 : oFieldSmoothness.SetPrecision( 2 );
1879 2 : poFeatureDefn->AddFieldDefn( &oFieldSmoothness );
1880 :
1881 2 : OGRFieldDefn oFieldCenterLineLights("centerline_lights", OFTInteger );
1882 2 : oFieldCenterLineLights.SetWidth( 1 );
1883 2 : poFeatureDefn->AddFieldDefn( &oFieldCenterLineLights );
1884 :
1885 2 : OGRFieldDefn oFieldEdgeLigthing("edge_lighting", OFTString );
1886 2 : poFeatureDefn->AddFieldDefn( &oFieldEdgeLigthing );
1887 :
1888 2 : OGRFieldDefn oFieldDistanceRemainingSigns("distance_remaining_signs", OFTInteger );
1889 2 : oFieldDistanceRemainingSigns.SetWidth( 1 );
1890 2 : poFeatureDefn->AddFieldDefn( &oFieldDistanceRemainingSigns );
1891 :
1892 2 : OGRFieldDefn oFieldDisplacedThreshold("displaced_threshold_m", OFTReal );
1893 2 : oFieldDisplacedThreshold.SetWidth( 3 );
1894 2 : poFeatureDefn->AddFieldDefn( &oFieldDisplacedThreshold );
1895 :
1896 2 : OGRFieldDefn oFieldIsDisplaced("is_displaced", OFTInteger );
1897 2 : oFieldIsDisplaced.SetWidth( 1 );
1898 2 : poFeatureDefn->AddFieldDefn( &oFieldIsDisplaced );
1899 :
1900 2 : OGRFieldDefn oFieldStopwayLength("stopway_length_m", OFTReal );
1901 2 : oFieldStopwayLength.SetWidth( 3 );
1902 2 : poFeatureDefn->AddFieldDefn( &oFieldStopwayLength );
1903 :
1904 2 : OGRFieldDefn oFieldMarkings("markings", OFTString );
1905 2 : poFeatureDefn->AddFieldDefn( &oFieldMarkings );
1906 :
1907 2 : OGRFieldDefn oFieldApproachLighting("approach_lighting", OFTString );
1908 2 : poFeatureDefn->AddFieldDefn( &oFieldApproachLighting );
1909 :
1910 2 : OGRFieldDefn oFieldTouchdownLights("touchdown_lights", OFTInteger );
1911 2 : oFieldTouchdownLights.SetWidth( 1 );
1912 2 : poFeatureDefn->AddFieldDefn( &oFieldTouchdownLights );
1913 :
1914 2 : OGRFieldDefn oFieldREIL("REIL", OFTString );
1915 2 : poFeatureDefn->AddFieldDefn( &oFieldREIL );
1916 :
1917 2 : OGRFieldDefn oFieldLength("length_m", OFTReal );
1918 2 : oFieldLength.SetWidth( 5 );
1919 2 : poFeatureDefn->AddFieldDefn( &oFieldLength );
1920 :
1921 2 : OGRFieldDefn oFieldTrueHeading("true_heading_deg", OFTReal );
1922 2 : oFieldTrueHeading.SetWidth( 6 );
1923 2 : oFieldTrueHeading.SetPrecision( 2 );
1924 2 : poFeatureDefn->AddFieldDefn( &oFieldTrueHeading );
1925 2 : }
1926 :
1927 : /************************************************************************/
1928 : /* AddFeature() */
1929 : /************************************************************************/
1930 :
1931 : OGRFeature*
1932 : OGRXPlaneRunwayThresholdLayer::AddFeature (const char* pszAptICAO,
1933 : const char* pszRwyNum,
1934 : double dfLat,
1935 : double dfLon,
1936 : double dfWidth,
1937 : const char* pszSurfaceType,
1938 : const char* pszShoulderType,
1939 : double dfSmoothness,
1940 : int bHasCenterLineLights,
1941 : const char* pszEdgeLighting,
1942 : int bHasDistanceRemainingSigns,
1943 : double dfDisplacedThresholdLength,
1944 : double dfStopwayLength,
1945 : const char* pszMarkings,
1946 : const char* pszApproachLightingCode,
1947 : int bHasTouchdownLights,
1948 50 : const char* pszREIL)
1949 : {
1950 50 : int nCount = 0;
1951 50 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
1952 50 : poFeature->SetField( nCount++, pszAptICAO );
1953 50 : poFeature->SetField( nCount++, pszRwyNum );
1954 50 : poFeature->SetField( nCount++, dfWidth );
1955 100 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
1956 50 : poFeature->SetField( nCount++, pszSurfaceType );
1957 50 : poFeature->SetField( nCount++, pszShoulderType );
1958 50 : poFeature->SetField( nCount++, dfSmoothness );
1959 50 : poFeature->SetField( nCount++, bHasCenterLineLights );
1960 50 : poFeature->SetField( nCount++, pszEdgeLighting );
1961 50 : poFeature->SetField( nCount++, bHasDistanceRemainingSigns );
1962 50 : poFeature->SetField( nCount++, dfDisplacedThresholdLength );
1963 50 : poFeature->SetField( nCount++, FALSE);
1964 50 : poFeature->SetField( nCount++, dfStopwayLength );
1965 50 : poFeature->SetField( nCount++, pszMarkings );
1966 50 : poFeature->SetField( nCount++, pszApproachLightingCode );
1967 50 : poFeature->SetField( nCount++, bHasTouchdownLights );
1968 50 : poFeature->SetField( nCount++, pszREIL );
1969 :
1970 50 : RegisterFeature(poFeature);
1971 :
1972 50 : return poFeature;
1973 : }
1974 :
1975 : void OGRXPlaneRunwayThresholdLayer::SetRunwayLengthAndHeading(OGRFeature* poFeature,
1976 : double dfLength,
1977 50 : double dfHeading)
1978 : {
1979 50 : int nCount = 16;
1980 50 : poFeature->SetField( nCount++, dfLength );
1981 50 : poFeature->SetField( nCount++, dfHeading );
1982 50 : }
1983 :
1984 : /************************************************************************/
1985 : /* AddFeatureFromNonDisplacedThreshold() */
1986 : /************************************************************************/
1987 :
1988 : OGRFeature* OGRXPlaneRunwayThresholdLayer::
1989 7 : AddFeatureFromNonDisplacedThreshold(OGRFeature* poNonDisplacedThresholdFeature)
1990 : {
1991 7 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
1992 :
1993 7 : poFeature->SetFrom(poNonDisplacedThresholdFeature, FALSE);
1994 :
1995 7 : double dfDisplacedThresholdLength = poFeature->GetFieldAsDouble("displaced_threshold_m");
1996 7 : double dfTrueHeading = poFeature->GetFieldAsDouble("true_heading_deg");
1997 7 : poFeature->SetField("is_displaced", TRUE);
1998 7 : OGRPoint* poPoint = (OGRPoint*)poFeature->GetGeometryRef();
1999 : double dfLatDisplaced, dfLonDisplaced;
2000 : OGRXPlane_ExtendPosition(poPoint->getY(), poPoint->getX(),
2001 : dfDisplacedThresholdLength, dfTrueHeading,
2002 7 : &dfLatDisplaced, &dfLonDisplaced);
2003 7 : poPoint->setX(dfLonDisplaced);
2004 7 : poPoint->setY(dfLatDisplaced);
2005 :
2006 7 : RegisterFeature(poFeature);
2007 :
2008 7 : return poFeature;
2009 : }
2010 :
2011 : /************************************************************************/
2012 : /* OGRXPlaneRunwayLayer() */
2013 : /************************************************************************/
2014 :
2015 :
2016 :
2017 2 : OGRXPlaneRunwayLayer::OGRXPlaneRunwayLayer() : OGRXPlaneLayer("RunwayPolygon")
2018 : {
2019 2 : poFeatureDefn->SetGeomType( wkbPolygon );
2020 :
2021 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
2022 2 : oFieldAptICAO.SetWidth( 4 );
2023 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
2024 :
2025 2 : OGRFieldDefn oFieldRwyNum1("rwy_num1", OFTString );
2026 2 : oFieldRwyNum1.SetWidth( 3 );
2027 2 : poFeatureDefn->AddFieldDefn( &oFieldRwyNum1 );
2028 :
2029 2 : OGRFieldDefn oFieldRwyNum2("rwy_num2", OFTString );
2030 2 : oFieldRwyNum2.SetWidth( 3 );
2031 2 : poFeatureDefn->AddFieldDefn( &oFieldRwyNum2 );
2032 :
2033 2 : OGRFieldDefn oFieldWidth("width_m", OFTReal );
2034 2 : oFieldWidth.SetWidth( 3 );
2035 2 : poFeatureDefn->AddFieldDefn( &oFieldWidth );
2036 :
2037 2 : OGRFieldDefn oFieldSurface("surface", OFTString );
2038 2 : poFeatureDefn->AddFieldDefn( &oFieldSurface );
2039 :
2040 2 : OGRFieldDefn oFieldShoulder("shoulder", OFTString );
2041 2 : poFeatureDefn->AddFieldDefn( &oFieldShoulder );
2042 :
2043 2 : OGRFieldDefn oFieldSmoothness("smoothness", OFTReal );
2044 2 : oFieldSmoothness.SetWidth( 4 );
2045 2 : oFieldSmoothness.SetPrecision( 2 );
2046 2 : poFeatureDefn->AddFieldDefn( &oFieldSmoothness );
2047 :
2048 2 : OGRFieldDefn oFieldCenterLineLights("centerline_lights", OFTInteger );
2049 2 : oFieldCenterLineLights.SetWidth( 1 );
2050 2 : poFeatureDefn->AddFieldDefn( &oFieldCenterLineLights );
2051 :
2052 2 : OGRFieldDefn oFieldEdgeLigthing("edge_lighting", OFTString );
2053 2 : poFeatureDefn->AddFieldDefn( &oFieldEdgeLigthing );
2054 :
2055 2 : OGRFieldDefn oFieldDistanceRemainingSigns("distance_remaining_signs", OFTInteger );
2056 2 : oFieldDistanceRemainingSigns.SetWidth( 1 );
2057 2 : poFeatureDefn->AddFieldDefn( &oFieldDistanceRemainingSigns );
2058 :
2059 2 : OGRFieldDefn oFieldLength("length_m", OFTReal );
2060 2 : oFieldLength.SetWidth( 5 );
2061 2 : poFeatureDefn->AddFieldDefn( &oFieldLength );
2062 :
2063 2 : OGRFieldDefn oFieldTrueHeading("true_heading_deg", OFTReal );
2064 2 : oFieldTrueHeading.SetWidth( 6 );
2065 2 : oFieldTrueHeading.SetPrecision( 2 );
2066 2 : poFeatureDefn->AddFieldDefn( &oFieldTrueHeading );
2067 2 : }
2068 :
2069 : /************************************************************************/
2070 : /* AddFeature() */
2071 : /************************************************************************/
2072 :
2073 :
2074 : OGRFeature*
2075 : OGRXPlaneRunwayLayer::AddFeature (const char* pszAptICAO,
2076 : const char* pszRwyNum1,
2077 : const char* pszRwyNum2,
2078 : double dfLat1,
2079 : double dfLon1,
2080 : double dfLat2,
2081 : double dfLon2,
2082 : double dfWidth,
2083 : const char* pszSurfaceType,
2084 : const char* pszShoulderType,
2085 : double dfSmoothness,
2086 : int bHasCenterLineLights,
2087 : const char* pszEdgeLighting,
2088 25 : int bHasDistanceRemainingSigns)
2089 : {
2090 25 : int nCount = 0;
2091 25 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
2092 :
2093 25 : double dfLength = OGRXPlane_Distance(dfLat1, dfLon1, dfLat2, dfLon2);
2094 25 : double dfTrack12 = OGRXPlane_Track(dfLat1, dfLon1, dfLat2, dfLon2);
2095 25 : double dfTrack21 = OGRXPlane_Track(dfLat2, dfLon2, dfLat1, dfLon1);
2096 : double adfLat[4], adfLon[4];
2097 :
2098 25 : OGRXPlane_ExtendPosition(dfLat1, dfLon1, dfWidth / 2, dfTrack12 - 90, &adfLat[0], &adfLon[0]);
2099 25 : OGRXPlane_ExtendPosition(dfLat2, dfLon2, dfWidth / 2, dfTrack21 + 90, &adfLat[1], &adfLon[1]);
2100 25 : OGRXPlane_ExtendPosition(dfLat2, dfLon2, dfWidth / 2, dfTrack21 - 90, &adfLat[2], &adfLon[2]);
2101 25 : OGRXPlane_ExtendPosition(dfLat1, dfLon1, dfWidth / 2, dfTrack12 + 90, &adfLat[3], &adfLon[3]);
2102 :
2103 50 : OGRLinearRing* linearRing = new OGRLinearRing();
2104 25 : linearRing->setNumPoints(5);
2105 : int i;
2106 125 : for(i=0;i<4;i++)
2107 100 : linearRing->setPoint(i, adfLon[i], adfLat[i]);
2108 25 : linearRing->setPoint(4, adfLon[0], adfLat[0]);
2109 25 : OGRPolygon* polygon = new OGRPolygon();
2110 25 : polygon->addRingDirectly( linearRing );
2111 25 : poFeature->SetGeometryDirectly( polygon );
2112 :
2113 25 : poFeature->SetField( nCount++, pszAptICAO );
2114 25 : poFeature->SetField( nCount++, pszRwyNum1 );
2115 25 : poFeature->SetField( nCount++, pszRwyNum2 );
2116 25 : poFeature->SetField( nCount++, dfWidth );
2117 25 : poFeature->SetField( nCount++, pszSurfaceType );
2118 25 : poFeature->SetField( nCount++, pszShoulderType );
2119 25 : poFeature->SetField( nCount++, dfSmoothness );
2120 25 : poFeature->SetField( nCount++, bHasCenterLineLights );
2121 25 : poFeature->SetField( nCount++, pszEdgeLighting );
2122 25 : poFeature->SetField( nCount++, bHasDistanceRemainingSigns );
2123 25 : poFeature->SetField( nCount++, dfLength );
2124 25 : poFeature->SetField( nCount++, dfTrack12 );
2125 :
2126 25 : RegisterFeature(poFeature);
2127 :
2128 25 : return poFeature;
2129 : }
2130 :
2131 :
2132 : /************************************************************************/
2133 : /* OGRXPlaneStopwayLayer() */
2134 : /************************************************************************/
2135 :
2136 :
2137 :
2138 2 : OGRXPlaneStopwayLayer::OGRXPlaneStopwayLayer() : OGRXPlaneLayer("Stopway")
2139 : {
2140 2 : poFeatureDefn->SetGeomType( wkbPolygon );
2141 :
2142 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
2143 2 : oFieldAptICAO.SetWidth( 4 );
2144 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
2145 :
2146 2 : OGRFieldDefn oFieldRwyNum1("rwy_num", OFTString );
2147 2 : oFieldRwyNum1.SetWidth( 3 );
2148 2 : poFeatureDefn->AddFieldDefn( &oFieldRwyNum1 );
2149 :
2150 2 : OGRFieldDefn oFieldWidth("width_m", OFTReal );
2151 2 : oFieldWidth.SetWidth( 3 );
2152 2 : poFeatureDefn->AddFieldDefn( &oFieldWidth );
2153 :
2154 2 : OGRFieldDefn oFieldLength("length_m", OFTReal );
2155 2 : oFieldLength.SetWidth( 5 );
2156 2 : poFeatureDefn->AddFieldDefn( &oFieldLength );
2157 2 : }
2158 :
2159 : /************************************************************************/
2160 : /* AddFeature() */
2161 : /************************************************************************/
2162 :
2163 :
2164 : OGRFeature*
2165 : OGRXPlaneStopwayLayer::AddFeature(const char* pszAptICAO,
2166 : const char* pszRwyNum,
2167 : double dfLatThreshold,
2168 : double dfLonThreshold,
2169 : double dfRunwayHeading,
2170 : double dfWidth,
2171 10 : double dfStopwayLength)
2172 : {
2173 10 : int nCount = 0;
2174 10 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
2175 :
2176 : double dfLat2, dfLon2;
2177 : double adfLat[4], adfLon[4];
2178 :
2179 10 : OGRXPlane_ExtendPosition(dfLatThreshold, dfLonThreshold, dfStopwayLength, 180 + dfRunwayHeading, &dfLat2, &dfLon2);
2180 :
2181 10 : OGRXPlane_ExtendPosition(dfLatThreshold, dfLonThreshold, dfWidth / 2, dfRunwayHeading - 90, &adfLat[0], &adfLon[0]);
2182 10 : OGRXPlane_ExtendPosition(dfLat2, dfLon2, dfWidth / 2, dfRunwayHeading - 90, &adfLat[1], &adfLon[1]);
2183 10 : OGRXPlane_ExtendPosition(dfLat2, dfLon2, dfWidth / 2, dfRunwayHeading + 90, &adfLat[2], &adfLon[2]);
2184 10 : OGRXPlane_ExtendPosition(dfLatThreshold, dfLonThreshold, dfWidth / 2, dfRunwayHeading + 90, &adfLat[3], &adfLon[3]);
2185 :
2186 20 : OGRLinearRing* linearRing = new OGRLinearRing();
2187 10 : linearRing->setNumPoints(5);
2188 : int i;
2189 50 : for(i=0;i<4;i++)
2190 40 : linearRing->setPoint(i, adfLon[i], adfLat[i]);
2191 10 : linearRing->setPoint(4, adfLon[0], adfLat[0]);
2192 10 : OGRPolygon* polygon = new OGRPolygon();
2193 10 : polygon->addRingDirectly( linearRing );
2194 10 : poFeature->SetGeometryDirectly( polygon );
2195 :
2196 10 : poFeature->SetField( nCount++, pszAptICAO );
2197 10 : poFeature->SetField( nCount++, pszRwyNum );
2198 10 : poFeature->SetField( nCount++, dfWidth );
2199 10 : poFeature->SetField( nCount++, dfStopwayLength );
2200 :
2201 10 : RegisterFeature(poFeature);
2202 :
2203 10 : return poFeature;
2204 : }
2205 :
2206 : /************************************************************************/
2207 : /* OGRXPlaneWaterRunwayThresholdLayer() */
2208 : /************************************************************************/
2209 :
2210 :
2211 2 : OGRXPlaneWaterRunwayThresholdLayer::OGRXPlaneWaterRunwayThresholdLayer() : OGRXPlaneLayer("WaterRunwayThreshold")
2212 : {
2213 2 : poFeatureDefn->SetGeomType( wkbPoint );
2214 :
2215 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
2216 2 : oFieldAptICAO.SetWidth( 4 );
2217 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
2218 :
2219 2 : OGRFieldDefn oFieldRwyNum("rwy_num", OFTString );
2220 2 : oFieldRwyNum.SetWidth( 3 );
2221 2 : poFeatureDefn->AddFieldDefn( &oFieldRwyNum );
2222 :
2223 2 : OGRFieldDefn oFieldWidth("width_m", OFTReal );
2224 2 : oFieldWidth.SetWidth( 3 );
2225 2 : poFeatureDefn->AddFieldDefn( &oFieldWidth );
2226 :
2227 2 : OGRFieldDefn oFieldHasBuoys("has_buoys", OFTInteger );
2228 2 : oFieldHasBuoys.SetWidth( 1 );
2229 2 : poFeatureDefn->AddFieldDefn( &oFieldHasBuoys );
2230 :
2231 2 : OGRFieldDefn oFieldLength("length_m", OFTReal );
2232 2 : oFieldLength.SetWidth( 5 );
2233 2 : poFeatureDefn->AddFieldDefn( &oFieldLength );
2234 :
2235 2 : OGRFieldDefn oFieldTrueHeading("true_heading_deg", OFTReal );
2236 2 : oFieldTrueHeading.SetWidth( 6 );
2237 2 : oFieldTrueHeading.SetPrecision( 2 );
2238 2 : poFeatureDefn->AddFieldDefn( &oFieldTrueHeading );
2239 2 : }
2240 :
2241 : /************************************************************************/
2242 : /* AddFeature() */
2243 : /************************************************************************/
2244 :
2245 : OGRFeature*
2246 : OGRXPlaneWaterRunwayThresholdLayer::AddFeature (const char* pszAptICAO,
2247 : const char* pszRwyNum,
2248 : double dfLat,
2249 : double dfLon,
2250 : double dfWidth,
2251 6 : int bBuoys)
2252 : {
2253 6 : int nCount = 0;
2254 6 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
2255 6 : poFeature->SetField( nCount++, pszAptICAO );
2256 6 : poFeature->SetField( nCount++, pszRwyNum );
2257 6 : poFeature->SetField( nCount++, dfWidth );
2258 12 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
2259 6 : poFeature->SetField( nCount++, bBuoys );
2260 :
2261 6 : RegisterFeature(poFeature);
2262 :
2263 6 : return poFeature;
2264 : }
2265 :
2266 : void OGRXPlaneWaterRunwayThresholdLayer::SetRunwayLengthAndHeading(OGRFeature* poFeature,
2267 : double dfLength,
2268 6 : double dfHeading)
2269 : {
2270 6 : int nCount = 4;
2271 6 : poFeature->SetField( nCount++, dfLength );
2272 6 : poFeature->SetField( nCount++, dfHeading );
2273 6 : }
2274 :
2275 :
2276 : /************************************************************************/
2277 : /* OGRXPlaneWaterRunwayLayer() */
2278 : /************************************************************************/
2279 :
2280 :
2281 :
2282 2 : OGRXPlaneWaterRunwayLayer::OGRXPlaneWaterRunwayLayer() : OGRXPlaneLayer("WaterRunwayPolygon")
2283 : {
2284 2 : poFeatureDefn->SetGeomType( wkbPolygon );
2285 :
2286 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
2287 2 : oFieldAptICAO.SetWidth( 4 );
2288 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
2289 :
2290 2 : OGRFieldDefn oFieldRwyNum1("rwy_num1", OFTString );
2291 2 : oFieldRwyNum1.SetWidth( 3 );
2292 2 : poFeatureDefn->AddFieldDefn( &oFieldRwyNum1 );
2293 :
2294 2 : OGRFieldDefn oFieldRwyNum2("rwy_num2", OFTString );
2295 2 : oFieldRwyNum2.SetWidth( 3 );
2296 2 : poFeatureDefn->AddFieldDefn( &oFieldRwyNum2 );
2297 :
2298 2 : OGRFieldDefn oFieldWidth("width_m", OFTReal );
2299 2 : oFieldWidth.SetWidth( 3 );
2300 2 : poFeatureDefn->AddFieldDefn( &oFieldWidth );
2301 :
2302 2 : OGRFieldDefn oFieldHasBuoys("has_buoys", OFTInteger );
2303 2 : oFieldHasBuoys.SetWidth( 1 );
2304 2 : poFeatureDefn->AddFieldDefn( &oFieldHasBuoys );
2305 :
2306 2 : OGRFieldDefn oFieldLength("length_m", OFTReal );
2307 2 : oFieldLength.SetWidth( 5 );
2308 2 : poFeatureDefn->AddFieldDefn( &oFieldLength );
2309 :
2310 2 : OGRFieldDefn oFieldTrueHeading("true_heading_deg", OFTReal );
2311 2 : oFieldTrueHeading.SetWidth( 6 );
2312 2 : oFieldTrueHeading.SetPrecision( 2 );
2313 2 : poFeatureDefn->AddFieldDefn( &oFieldTrueHeading );
2314 2 : }
2315 :
2316 : /************************************************************************/
2317 : /* AddFeature() */
2318 : /************************************************************************/
2319 :
2320 : OGRFeature*
2321 : OGRXPlaneWaterRunwayLayer::AddFeature (const char* pszAptICAO,
2322 : const char* pszRwyNum1,
2323 : const char* pszRwyNum2,
2324 : double dfLat1,
2325 : double dfLon1,
2326 : double dfLat2,
2327 : double dfLon2,
2328 : double dfWidth,
2329 3 : int bBuoys)
2330 : {
2331 3 : int nCount = 0;
2332 3 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
2333 :
2334 3 : double dfLength = OGRXPlane_Distance(dfLat1, dfLon1, dfLat2, dfLon2);
2335 3 : double dfTrack12 = OGRXPlane_Track(dfLat1, dfLon1, dfLat2, dfLon2);
2336 3 : double dfTrack21 = OGRXPlane_Track(dfLat2, dfLon2, dfLat1, dfLon1);
2337 : double adfLat[4], adfLon[4];
2338 :
2339 3 : OGRXPlane_ExtendPosition(dfLat1, dfLon1, dfWidth / 2, dfTrack12 - 90, &adfLat[0], &adfLon[0]);
2340 3 : OGRXPlane_ExtendPosition(dfLat2, dfLon2, dfWidth / 2, dfTrack21 + 90, &adfLat[1], &adfLon[1]);
2341 3 : OGRXPlane_ExtendPosition(dfLat2, dfLon2, dfWidth / 2, dfTrack21 - 90, &adfLat[2], &adfLon[2]);
2342 3 : OGRXPlane_ExtendPosition(dfLat1, dfLon1, dfWidth / 2, dfTrack12 + 90, &adfLat[3], &adfLon[3]);
2343 :
2344 6 : OGRLinearRing* linearRing = new OGRLinearRing();
2345 3 : linearRing->setNumPoints(5);
2346 : int i;
2347 15 : for(i=0;i<4;i++)
2348 12 : linearRing->setPoint(i, adfLon[i], adfLat[i]);
2349 3 : linearRing->setPoint(4, adfLon[0], adfLat[0]);
2350 3 : OGRPolygon* polygon = new OGRPolygon();
2351 3 : polygon->addRingDirectly( linearRing );
2352 3 : poFeature->SetGeometryDirectly( polygon );
2353 :
2354 3 : poFeature->SetField( nCount++, pszAptICAO );
2355 3 : poFeature->SetField( nCount++, pszRwyNum1 );
2356 3 : poFeature->SetField( nCount++, pszRwyNum2 );
2357 3 : poFeature->SetField( nCount++, dfWidth );
2358 3 : poFeature->SetField( nCount++, bBuoys );
2359 3 : poFeature->SetField( nCount++, dfLength );
2360 3 : poFeature->SetField( nCount++, dfTrack12 );
2361 :
2362 3 : RegisterFeature(poFeature);
2363 :
2364 3 : return poFeature;
2365 : }
2366 :
2367 :
2368 : /************************************************************************/
2369 : /* OGRXPlaneHelipadLayer() */
2370 : /************************************************************************/
2371 :
2372 :
2373 2 : OGRXPlaneHelipadLayer::OGRXPlaneHelipadLayer() : OGRXPlaneLayer("Helipad")
2374 : {
2375 2 : poFeatureDefn->SetGeomType( wkbPoint );
2376 :
2377 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
2378 2 : oFieldAptICAO.SetWidth( 4 );
2379 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
2380 :
2381 2 : OGRFieldDefn oFieldHelipadName("helipad_name", OFTString );
2382 2 : oFieldHelipadName.SetWidth( 5 );
2383 2 : poFeatureDefn->AddFieldDefn( &oFieldHelipadName );
2384 :
2385 2 : OGRFieldDefn oFieldTrueHeading("true_heading_deg", OFTReal );
2386 2 : oFieldTrueHeading.SetWidth( 6 );
2387 2 : oFieldTrueHeading.SetPrecision( 2 );
2388 2 : poFeatureDefn->AddFieldDefn( &oFieldTrueHeading );
2389 :
2390 2 : OGRFieldDefn oFieldLength("length_m", OFTReal );
2391 2 : oFieldLength.SetWidth( 5 );
2392 2 : poFeatureDefn->AddFieldDefn( &oFieldLength );
2393 :
2394 2 : OGRFieldDefn oFieldWidth("width_m", OFTReal );
2395 2 : oFieldWidth.SetWidth( 3 );
2396 2 : poFeatureDefn->AddFieldDefn( &oFieldWidth );
2397 :
2398 2 : OGRFieldDefn oFieldSurface("surface", OFTString );
2399 2 : poFeatureDefn->AddFieldDefn( &oFieldSurface );
2400 :
2401 2 : OGRFieldDefn oFieldMarkings("markings", OFTString );
2402 2 : poFeatureDefn->AddFieldDefn( &oFieldMarkings );
2403 :
2404 2 : OGRFieldDefn oFieldShoulder("shoulder", OFTString );
2405 2 : poFeatureDefn->AddFieldDefn( &oFieldShoulder );
2406 :
2407 2 : OGRFieldDefn oFieldSmoothness("smoothness", OFTReal );
2408 2 : oFieldSmoothness.SetWidth( 4 );
2409 2 : oFieldSmoothness.SetPrecision( 2 );
2410 2 : poFeatureDefn->AddFieldDefn( &oFieldSmoothness );
2411 :
2412 2 : OGRFieldDefn oFieldEdgeLighting("edge_lighting", OFTString );
2413 2 : poFeatureDefn->AddFieldDefn( &oFieldEdgeLighting );
2414 :
2415 2 : }
2416 :
2417 : /************************************************************************/
2418 : /* AddFeature() */
2419 : /************************************************************************/
2420 :
2421 : OGRFeature*
2422 : OGRXPlaneHelipadLayer::AddFeature (const char* pszAptICAO,
2423 : const char* pszHelipadNum,
2424 : double dfLat,
2425 : double dfLon,
2426 : double dfTrueHeading,
2427 : double dfLength,
2428 : double dfWidth,
2429 : const char* pszSurfaceType,
2430 : const char* pszMarkings,
2431 : const char* pszShoulderType,
2432 : double dfSmoothness,
2433 3 : const char* pszEdgeLighting)
2434 : {
2435 3 : int nCount = 0;
2436 3 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
2437 3 : poFeature->SetField( nCount++, pszAptICAO );
2438 3 : poFeature->SetField( nCount++, pszHelipadNum );
2439 6 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
2440 3 : poFeature->SetField( nCount++, dfTrueHeading );
2441 3 : poFeature->SetField( nCount++, dfLength );
2442 3 : poFeature->SetField( nCount++, dfWidth );
2443 3 : poFeature->SetField( nCount++, pszSurfaceType );
2444 3 : poFeature->SetField( nCount++, pszMarkings );
2445 3 : poFeature->SetField( nCount++, pszShoulderType );
2446 3 : poFeature->SetField( nCount++, dfSmoothness );
2447 3 : poFeature->SetField( nCount++, pszEdgeLighting );
2448 :
2449 3 : RegisterFeature(poFeature);
2450 :
2451 3 : return poFeature;
2452 : }
2453 :
2454 : /************************************************************************/
2455 : /* OGRXPlaneHelipadPolygonLayer() */
2456 : /************************************************************************/
2457 :
2458 :
2459 2 : OGRXPlaneHelipadPolygonLayer::OGRXPlaneHelipadPolygonLayer() : OGRXPlaneLayer("HelipadPolygon")
2460 : {
2461 2 : poFeatureDefn->SetGeomType( wkbPolygon );
2462 :
2463 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
2464 2 : oFieldAptICAO.SetWidth( 4 );
2465 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
2466 :
2467 2 : OGRFieldDefn oFieldHelipadName("helipad_name", OFTString );
2468 2 : oFieldHelipadName.SetWidth( 5 );
2469 2 : poFeatureDefn->AddFieldDefn( &oFieldHelipadName );
2470 :
2471 2 : OGRFieldDefn oFieldTrueHeading("true_heading_deg", OFTReal );
2472 2 : oFieldTrueHeading.SetWidth( 6 );
2473 2 : oFieldTrueHeading.SetPrecision( 2 );
2474 2 : poFeatureDefn->AddFieldDefn( &oFieldTrueHeading );
2475 :
2476 2 : OGRFieldDefn oFieldLength("length_m", OFTReal );
2477 2 : oFieldLength.SetWidth( 5 );
2478 2 : poFeatureDefn->AddFieldDefn( &oFieldLength );
2479 :
2480 2 : OGRFieldDefn oFieldWidth("width_m", OFTReal );
2481 2 : oFieldWidth.SetWidth( 3 );
2482 2 : poFeatureDefn->AddFieldDefn( &oFieldWidth );
2483 :
2484 2 : OGRFieldDefn oFieldSurface("surface", OFTString );
2485 2 : poFeatureDefn->AddFieldDefn( &oFieldSurface );
2486 :
2487 2 : OGRFieldDefn oFieldMarkings("markings", OFTString );
2488 2 : poFeatureDefn->AddFieldDefn( &oFieldMarkings );
2489 :
2490 2 : OGRFieldDefn oFieldShoulder("shoulder", OFTString );
2491 2 : poFeatureDefn->AddFieldDefn( &oFieldShoulder );
2492 :
2493 2 : OGRFieldDefn oFieldSmoothness("smoothness", OFTReal );
2494 2 : oFieldSmoothness.SetWidth( 4 );
2495 2 : oFieldSmoothness.SetPrecision( 2 );
2496 2 : poFeatureDefn->AddFieldDefn( &oFieldSmoothness );
2497 :
2498 2 : OGRFieldDefn oFieldEdgeLighting("edge_lighting", OFTString );
2499 2 : poFeatureDefn->AddFieldDefn( &oFieldEdgeLighting );
2500 :
2501 2 : }
2502 :
2503 : /************************************************************************/
2504 : /* AddFeature() */
2505 : /************************************************************************/
2506 :
2507 : OGRFeature*
2508 : OGRXPlaneHelipadPolygonLayer::AddFeature (const char* pszAptICAO,
2509 : const char* pszHelipadNum,
2510 : double dfLat,
2511 : double dfLon,
2512 : double dfTrueHeading,
2513 : double dfLength,
2514 : double dfWidth,
2515 : const char* pszSurfaceType,
2516 : const char* pszMarkings,
2517 : const char* pszShoulderType,
2518 : double dfSmoothness,
2519 3 : const char* pszEdgeLighting)
2520 : {
2521 3 : int nCount = 0;
2522 3 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
2523 :
2524 : double dfBeforeLat, dfBeforeLon;
2525 : double dfAfterLat, dfAfterLon;
2526 : double adfLat[4], adfLon[4];
2527 :
2528 3 : OGRXPlane_ExtendPosition(dfLat, dfLon, dfLength / 2, dfTrueHeading + 180, &dfBeforeLat, &dfBeforeLon);
2529 3 : OGRXPlane_ExtendPosition(dfLat, dfLon, dfLength / 2, dfTrueHeading, &dfAfterLat, &dfAfterLon);
2530 :
2531 3 : OGRXPlane_ExtendPosition(dfBeforeLat, dfBeforeLon, dfWidth / 2, dfTrueHeading - 90, &adfLat[0], &adfLon[0]);
2532 3 : OGRXPlane_ExtendPosition(dfAfterLat, dfAfterLon, dfWidth / 2, dfTrueHeading - 90, &adfLat[1], &adfLon[1]);
2533 3 : OGRXPlane_ExtendPosition(dfAfterLat, dfAfterLon, dfWidth / 2, dfTrueHeading + 90, &adfLat[2], &adfLon[2]);
2534 3 : OGRXPlane_ExtendPosition(dfBeforeLat, dfBeforeLon, dfWidth / 2, dfTrueHeading + 90, &adfLat[3], &adfLon[3]);
2535 :
2536 6 : OGRLinearRing* linearRing = new OGRLinearRing();
2537 3 : linearRing->setNumPoints(5);
2538 : int i;
2539 15 : for(i=0;i<4;i++)
2540 12 : linearRing->setPoint(i, adfLon[i], adfLat[i]);
2541 3 : linearRing->setPoint(4, adfLon[0], adfLat[0]);
2542 3 : OGRPolygon* polygon = new OGRPolygon();
2543 3 : polygon->addRingDirectly( linearRing );
2544 3 : poFeature->SetGeometryDirectly( polygon );
2545 :
2546 3 : poFeature->SetField( nCount++, pszAptICAO );
2547 3 : poFeature->SetField( nCount++, pszHelipadNum );
2548 3 : poFeature->SetField( nCount++, dfTrueHeading );
2549 3 : poFeature->SetField( nCount++, dfLength );
2550 3 : poFeature->SetField( nCount++, dfWidth );
2551 3 : poFeature->SetField( nCount++, pszSurfaceType );
2552 3 : poFeature->SetField( nCount++, pszMarkings );
2553 3 : poFeature->SetField( nCount++, pszShoulderType );
2554 3 : poFeature->SetField( nCount++, dfSmoothness );
2555 3 : poFeature->SetField( nCount++, pszEdgeLighting );
2556 :
2557 3 : RegisterFeature(poFeature);
2558 :
2559 3 : return poFeature;
2560 : }
2561 :
2562 :
2563 : /************************************************************************/
2564 : /* OGRXPlaneTaxiwayRectangleLayer() */
2565 : /************************************************************************/
2566 :
2567 :
2568 2 : OGRXPlaneTaxiwayRectangleLayer::OGRXPlaneTaxiwayRectangleLayer() : OGRXPlaneLayer("TaxiwayRectangle")
2569 : {
2570 2 : poFeatureDefn->SetGeomType( wkbPolygon );
2571 :
2572 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
2573 2 : oFieldAptICAO.SetWidth( 4 );
2574 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
2575 :
2576 2 : OGRFieldDefn oFieldTrueHeading("true_heading_deg", OFTReal );
2577 2 : oFieldTrueHeading.SetWidth( 6 );
2578 2 : oFieldTrueHeading.SetPrecision( 2 );
2579 2 : poFeatureDefn->AddFieldDefn( &oFieldTrueHeading );
2580 :
2581 2 : OGRFieldDefn oFieldLength("length_m", OFTReal );
2582 2 : oFieldLength.SetWidth( 5 );
2583 2 : poFeatureDefn->AddFieldDefn( &oFieldLength );
2584 :
2585 2 : OGRFieldDefn oFieldWidth("width_m", OFTReal );
2586 2 : oFieldWidth.SetWidth( 3 );
2587 2 : poFeatureDefn->AddFieldDefn( &oFieldWidth );
2588 :
2589 2 : OGRFieldDefn oFieldSurface("surface", OFTString );
2590 2 : poFeatureDefn->AddFieldDefn( &oFieldSurface );
2591 :
2592 2 : OGRFieldDefn oFieldSmoothness("smoothness", OFTReal );
2593 2 : oFieldSmoothness.SetWidth( 4 );
2594 2 : oFieldSmoothness.SetPrecision( 2 );
2595 2 : poFeatureDefn->AddFieldDefn( &oFieldSmoothness );
2596 :
2597 2 : OGRFieldDefn oFieldBlueEdgeLighting("edge_lighting", OFTInteger );
2598 2 : oFieldBlueEdgeLighting.SetWidth( 1 );
2599 2 : poFeatureDefn->AddFieldDefn( &oFieldBlueEdgeLighting );
2600 :
2601 2 : }
2602 :
2603 : /************************************************************************/
2604 : /* AddFeature() */
2605 : /************************************************************************/
2606 :
2607 : OGRFeature*
2608 : OGRXPlaneTaxiwayRectangleLayer::AddFeature(const char* pszAptICAO,
2609 : double dfLat,
2610 : double dfLon,
2611 : double dfTrueHeading,
2612 : double dfLength,
2613 : double dfWidth,
2614 : const char* pszSurfaceType,
2615 : double dfSmoothness,
2616 491 : int bBlueEdgeLights)
2617 : {
2618 491 : int nCount = 0;
2619 491 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
2620 :
2621 : double dfBeforeLat, dfBeforeLon;
2622 : double dfAfterLat, dfAfterLon;
2623 : double adfLat[4], adfLon[4];
2624 :
2625 491 : OGRXPlane_ExtendPosition(dfLat, dfLon, dfLength / 2, dfTrueHeading + 180, &dfBeforeLat, &dfBeforeLon);
2626 491 : OGRXPlane_ExtendPosition(dfLat, dfLon, dfLength / 2, dfTrueHeading, &dfAfterLat, &dfAfterLon);
2627 :
2628 491 : OGRXPlane_ExtendPosition(dfBeforeLat, dfBeforeLon, dfWidth / 2, dfTrueHeading - 90, &adfLat[0], &adfLon[0]);
2629 491 : OGRXPlane_ExtendPosition(dfAfterLat, dfAfterLon, dfWidth / 2, dfTrueHeading - 90, &adfLat[1], &adfLon[1]);
2630 491 : OGRXPlane_ExtendPosition(dfAfterLat, dfAfterLon, dfWidth / 2, dfTrueHeading + 90, &adfLat[2], &adfLon[2]);
2631 491 : OGRXPlane_ExtendPosition(dfBeforeLat, dfBeforeLon, dfWidth / 2, dfTrueHeading + 90, &adfLat[3], &adfLon[3]);
2632 :
2633 982 : OGRLinearRing* linearRing = new OGRLinearRing();
2634 491 : linearRing->setNumPoints(5);
2635 : int i;
2636 2455 : for(i=0;i<4;i++)
2637 1964 : linearRing->setPoint(i, adfLon[i], adfLat[i]);
2638 491 : linearRing->setPoint(4, adfLon[0], adfLat[0]);
2639 491 : OGRPolygon* polygon = new OGRPolygon();
2640 491 : polygon->addRingDirectly( linearRing );
2641 491 : poFeature->SetGeometryDirectly( polygon );
2642 :
2643 491 : poFeature->SetField( nCount++, pszAptICAO );
2644 491 : poFeature->SetField( nCount++, dfTrueHeading );
2645 491 : poFeature->SetField( nCount++, dfLength );
2646 491 : poFeature->SetField( nCount++, dfWidth );
2647 491 : poFeature->SetField( nCount++, pszSurfaceType );
2648 491 : poFeature->SetField( nCount++, dfSmoothness );
2649 491 : poFeature->SetField( nCount++, bBlueEdgeLights );
2650 :
2651 491 : RegisterFeature(poFeature);
2652 :
2653 491 : return poFeature;
2654 : }
2655 :
2656 :
2657 : /************************************************************************/
2658 : /* OGRXPlanePavementLayer() */
2659 : /************************************************************************/
2660 :
2661 :
2662 2 : OGRXPlanePavementLayer::OGRXPlanePavementLayer() : OGRXPlaneLayer("Pavement")
2663 : {
2664 2 : poFeatureDefn->SetGeomType( wkbPolygon );
2665 :
2666 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
2667 2 : oFieldAptICAO.SetWidth( 4 );
2668 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
2669 :
2670 2 : OGRFieldDefn oFieldName("name", OFTString );
2671 2 : poFeatureDefn->AddFieldDefn( &oFieldName );
2672 :
2673 2 : OGRFieldDefn oFieldSurface("surface", OFTString );
2674 2 : poFeatureDefn->AddFieldDefn( &oFieldSurface );
2675 :
2676 2 : OGRFieldDefn oFieldSmoothness("smoothness", OFTReal );
2677 2 : oFieldSmoothness.SetWidth( 4 );
2678 2 : oFieldSmoothness.SetPrecision( 2 );
2679 2 : poFeatureDefn->AddFieldDefn( &oFieldSmoothness );
2680 :
2681 2 : OGRFieldDefn oFieldTextureHeading("texture_heading", OFTReal );
2682 2 : oFieldTextureHeading.SetWidth( 6 );
2683 2 : oFieldTextureHeading.SetPrecision( 2 );
2684 2 : poFeatureDefn->AddFieldDefn( &oFieldTextureHeading );
2685 :
2686 2 : }
2687 :
2688 : /************************************************************************/
2689 : /* AddFeature() */
2690 : /************************************************************************/
2691 :
2692 : OGRFeature*
2693 : OGRXPlanePavementLayer::AddFeature(const char* pszAptICAO,
2694 : const char* pszPavementName,
2695 : const char* pszSurfaceType,
2696 : double dfSmoothness,
2697 : double dfTextureHeading,
2698 11 : OGRPolygon* poPolygon)
2699 : {
2700 11 : int nCount = 0;
2701 11 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
2702 :
2703 11 : poFeature->SetGeometry( poPolygon );
2704 :
2705 11 : poFeature->SetField( nCount++, pszAptICAO );
2706 11 : poFeature->SetField( nCount++, pszPavementName );
2707 11 : poFeature->SetField( nCount++, pszSurfaceType );
2708 11 : poFeature->SetField( nCount++, dfSmoothness );
2709 11 : poFeature->SetField( nCount++, dfTextureHeading );
2710 :
2711 11 : RegisterFeature(poFeature);
2712 :
2713 11 : return poFeature;
2714 : }
2715 :
2716 :
2717 :
2718 : /************************************************************************/
2719 : /* OGRXPlaneAPTBoundaryLayer() */
2720 : /************************************************************************/
2721 :
2722 :
2723 2 : OGRXPlaneAPTBoundaryLayer::OGRXPlaneAPTBoundaryLayer() : OGRXPlaneLayer("APTBoundary")
2724 : {
2725 2 : poFeatureDefn->SetGeomType( wkbPolygon );
2726 :
2727 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
2728 2 : oFieldAptICAO.SetWidth( 4 );
2729 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
2730 :
2731 2 : OGRFieldDefn oFieldName("name", OFTString );
2732 2 : poFeatureDefn->AddFieldDefn( &oFieldName );
2733 :
2734 2 : }
2735 :
2736 : /************************************************************************/
2737 : /* AddFeature() */
2738 : /************************************************************************/
2739 :
2740 : OGRFeature*
2741 : OGRXPlaneAPTBoundaryLayer::AddFeature(const char* pszAptICAO,
2742 : const char* pszBoundaryName,
2743 1 : OGRPolygon* poPolygon)
2744 : {
2745 1 : int nCount = 0;
2746 1 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
2747 :
2748 1 : poFeature->SetGeometry( poPolygon );
2749 :
2750 1 : poFeature->SetField( nCount++, pszAptICAO );
2751 1 : poFeature->SetField( nCount++, pszBoundaryName );
2752 :
2753 1 : RegisterFeature(poFeature);
2754 :
2755 1 : return poFeature;
2756 : }
2757 :
2758 : /************************************************************************/
2759 : /* OGRXPlaneAPTLinearFeatureLayer() */
2760 : /************************************************************************/
2761 :
2762 :
2763 2 : OGRXPlaneAPTLinearFeatureLayer::OGRXPlaneAPTLinearFeatureLayer() : OGRXPlaneLayer("APTLinearFeature")
2764 : {
2765 2 : poFeatureDefn->SetGeomType( wkbMultiLineString );
2766 :
2767 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
2768 2 : oFieldAptICAO.SetWidth( 4 );
2769 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
2770 :
2771 2 : OGRFieldDefn oFieldName("name", OFTString );
2772 2 : poFeatureDefn->AddFieldDefn( &oFieldName );
2773 :
2774 2 : }
2775 :
2776 : /************************************************************************/
2777 : /* AddFeature() */
2778 : /************************************************************************/
2779 :
2780 : OGRFeature*
2781 : OGRXPlaneAPTLinearFeatureLayer::AddFeature(const char* pszAptICAO,
2782 : const char* pszLinearFeatureName,
2783 45 : OGRMultiLineString* poMultilineString)
2784 : {
2785 45 : int nCount = 0;
2786 45 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
2787 :
2788 45 : poFeature->SetGeometry( poMultilineString );
2789 :
2790 45 : poFeature->SetField( nCount++, pszAptICAO );
2791 45 : poFeature->SetField( nCount++, pszLinearFeatureName );
2792 :
2793 45 : RegisterFeature(poFeature);
2794 :
2795 45 : return poFeature;
2796 : }
2797 :
2798 : /************************************************************************/
2799 : /* OGRXPlaneATCFreqLayer() */
2800 : /************************************************************************/
2801 :
2802 :
2803 2 : OGRXPlaneATCFreqLayer::OGRXPlaneATCFreqLayer() : OGRXPlaneLayer("ATCFreq")
2804 : {
2805 2 : poFeatureDefn->SetGeomType( wkbNone );
2806 :
2807 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
2808 2 : oFieldAptICAO.SetWidth( 4 );
2809 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
2810 :
2811 2 : OGRFieldDefn oFieldATCFreqType("atc_type", OFTString );
2812 2 : oFieldATCFreqType.SetWidth( 4 );
2813 2 : poFeatureDefn->AddFieldDefn( &oFieldATCFreqType );
2814 :
2815 2 : OGRFieldDefn oFieldATCFreqName("freq_name", OFTString );
2816 2 : poFeatureDefn->AddFieldDefn( &oFieldATCFreqName );
2817 :
2818 2 : OGRFieldDefn oFieldFreq("freq_mhz", OFTReal );
2819 2 : oFieldFreq.SetWidth( 7 );
2820 2 : oFieldFreq.SetPrecision( 3 );
2821 2 : poFeatureDefn->AddFieldDefn( &oFieldFreq );
2822 2 : }
2823 :
2824 : /************************************************************************/
2825 : /* AddFeature() */
2826 : /************************************************************************/
2827 :
2828 : OGRFeature*
2829 : OGRXPlaneATCFreqLayer::AddFeature (const char* pszAptICAO,
2830 : const char* pszATCType,
2831 : const char* pszATCFreqName,
2832 52 : double dfFrequency)
2833 : {
2834 52 : int nCount = 0;
2835 52 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
2836 52 : poFeature->SetField( nCount++, pszAptICAO );
2837 52 : poFeature->SetField( nCount++, pszATCType );
2838 52 : poFeature->SetField( nCount++, pszATCFreqName );
2839 52 : poFeature->SetField( nCount++, dfFrequency );
2840 :
2841 52 : RegisterFeature(poFeature);
2842 :
2843 52 : return poFeature;
2844 : }
2845 :
2846 :
2847 : /************************************************************************/
2848 : /* OGRXPlaneStartupLocationLayer() */
2849 : /************************************************************************/
2850 :
2851 2 : OGRXPlaneStartupLocationLayer::OGRXPlaneStartupLocationLayer() : OGRXPlaneLayer("StartupLocation")
2852 : {
2853 2 : poFeatureDefn->SetGeomType( wkbPoint );
2854 :
2855 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
2856 2 : oFieldAptICAO.SetWidth( 4 );
2857 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
2858 :
2859 2 : OGRFieldDefn oFieldName("name", OFTString );
2860 2 : poFeatureDefn->AddFieldDefn( &oFieldName );
2861 :
2862 2 : OGRFieldDefn oFieldTrueHeading("true_heading_deg", OFTReal );
2863 2 : oFieldTrueHeading.SetWidth( 6 );
2864 2 : oFieldTrueHeading.SetPrecision( 2 );
2865 2 : poFeatureDefn->AddFieldDefn( &oFieldTrueHeading );
2866 2 : }
2867 :
2868 : /************************************************************************/
2869 : /* AddFeature() */
2870 : /************************************************************************/
2871 :
2872 : OGRFeature*
2873 : OGRXPlaneStartupLocationLayer::AddFeature (const char* pszAptICAO,
2874 : const char* pszName,
2875 : double dfLat,
2876 : double dfLon,
2877 110 : double dfTrueHeading)
2878 : {
2879 110 : int nCount = 0;
2880 110 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
2881 110 : poFeature->SetField( nCount++, pszAptICAO );
2882 110 : poFeature->SetField( nCount++, pszName );
2883 220 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
2884 110 : poFeature->SetField( nCount++, dfTrueHeading );
2885 :
2886 110 : RegisterFeature(poFeature);
2887 :
2888 110 : return poFeature;
2889 : }
2890 :
2891 :
2892 : /************************************************************************/
2893 : /* OGRXPlaneAPTLightBeaconLayer() */
2894 : /************************************************************************/
2895 :
2896 2 : OGRXPlaneAPTLightBeaconLayer::OGRXPlaneAPTLightBeaconLayer() : OGRXPlaneLayer("APTLightBeacon")
2897 : {
2898 2 : poFeatureDefn->SetGeomType( wkbPoint );
2899 :
2900 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
2901 2 : oFieldAptICAO.SetWidth( 4 );
2902 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
2903 :
2904 2 : OGRFieldDefn oFieldName("name", OFTString );
2905 2 : poFeatureDefn->AddFieldDefn( &oFieldName );
2906 :
2907 2 : OGRFieldDefn oFieldColor("color", OFTString );
2908 2 : poFeatureDefn->AddFieldDefn( &oFieldColor );
2909 2 : }
2910 :
2911 : /************************************************************************/
2912 : /* AddFeature() */
2913 : /************************************************************************/
2914 :
2915 : OGRFeature*
2916 : OGRXPlaneAPTLightBeaconLayer::AddFeature (const char* pszAptICAO,
2917 : const char* pszName,
2918 : double dfLat,
2919 : double dfLon,
2920 5 : const char* pszColor)
2921 : {
2922 5 : int nCount = 0;
2923 5 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
2924 5 : poFeature->SetField( nCount++, pszAptICAO );
2925 5 : poFeature->SetField( nCount++, pszName );
2926 10 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
2927 5 : poFeature->SetField( nCount++, pszColor );
2928 :
2929 5 : RegisterFeature(poFeature);
2930 :
2931 5 : return poFeature;
2932 : }
2933 :
2934 : /************************************************************************/
2935 : /* OGRXPlaneAPTWindsockLayer() */
2936 : /************************************************************************/
2937 :
2938 2 : OGRXPlaneAPTWindsockLayer::OGRXPlaneAPTWindsockLayer() : OGRXPlaneLayer("APTWindsock")
2939 : {
2940 2 : poFeatureDefn->SetGeomType( wkbPoint );
2941 :
2942 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
2943 2 : oFieldAptICAO.SetWidth( 4 );
2944 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
2945 :
2946 2 : OGRFieldDefn oFieldName("name", OFTString );
2947 2 : poFeatureDefn->AddFieldDefn( &oFieldName );
2948 :
2949 2 : OGRFieldDefn oFieldIsIlluminated("is_illuminated", OFTInteger );
2950 2 : oFieldIsIlluminated.SetWidth( 1 );
2951 2 : poFeatureDefn->AddFieldDefn( &oFieldIsIlluminated );
2952 2 : }
2953 :
2954 : /************************************************************************/
2955 : /* AddFeature() */
2956 : /************************************************************************/
2957 :
2958 : OGRFeature*
2959 : OGRXPlaneAPTWindsockLayer::AddFeature (const char* pszAptICAO,
2960 : const char* pszName,
2961 : double dfLat,
2962 : double dfLon,
2963 34 : int bIsIllumnited)
2964 : {
2965 34 : int nCount = 0;
2966 34 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
2967 34 : poFeature->SetField( nCount++, pszAptICAO );
2968 34 : poFeature->SetField( nCount++, pszName );
2969 68 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
2970 34 : poFeature->SetField( nCount++, bIsIllumnited );
2971 :
2972 34 : RegisterFeature(poFeature);
2973 :
2974 34 : return poFeature;
2975 : }
2976 :
2977 :
2978 : /************************************************************************/
2979 : /* OGRXPlaneTaxiwaySignLayer() */
2980 : /************************************************************************/
2981 :
2982 2 : OGRXPlaneTaxiwaySignLayer::OGRXPlaneTaxiwaySignLayer() : OGRXPlaneLayer("TaxiwaySign")
2983 : {
2984 2 : poFeatureDefn->SetGeomType( wkbPoint );
2985 :
2986 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
2987 2 : oFieldAptICAO.SetWidth( 4 );
2988 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
2989 :
2990 2 : OGRFieldDefn oFieldText("text", OFTString );
2991 2 : poFeatureDefn->AddFieldDefn( &oFieldText );
2992 :
2993 2 : OGRFieldDefn oFieldTrueHeading("true_heading_deg", OFTReal );
2994 2 : oFieldTrueHeading.SetWidth( 6 );
2995 2 : oFieldTrueHeading.SetPrecision( 2 );
2996 2 : poFeatureDefn->AddFieldDefn( &oFieldTrueHeading );
2997 :
2998 2 : OGRFieldDefn oFieldSize("size", OFTInteger );
2999 2 : oFieldSize.SetWidth( 1 );
3000 2 : poFeatureDefn->AddFieldDefn( &oFieldSize );
3001 2 : }
3002 :
3003 : /************************************************************************/
3004 : /* AddFeature() */
3005 : /************************************************************************/
3006 :
3007 : OGRFeature*
3008 : OGRXPlaneTaxiwaySignLayer::AddFeature (const char* pszAptICAO,
3009 : const char* pszText,
3010 : double dfLat,
3011 : double dfLon,
3012 : double dfHeading,
3013 17 : int nSize)
3014 : {
3015 17 : int nCount = 0;
3016 17 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
3017 17 : poFeature->SetField( nCount++, pszAptICAO );
3018 17 : poFeature->SetField( nCount++, pszText );
3019 34 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
3020 17 : poFeature->SetField( nCount++, dfHeading );
3021 17 : poFeature->SetField( nCount++, nSize );
3022 :
3023 17 : RegisterFeature(poFeature);
3024 :
3025 17 : return poFeature;
3026 : }
3027 :
3028 :
3029 : /************************************************************************/
3030 : /* OGRXPlane_VASI_PAPI_WIGWAG_Layer() */
3031 : /************************************************************************/
3032 :
3033 2 : OGRXPlane_VASI_PAPI_WIGWAG_Layer::OGRXPlane_VASI_PAPI_WIGWAG_Layer() : OGRXPlaneLayer("VASI_PAPI_WIGWAG")
3034 : {
3035 2 : poFeatureDefn->SetGeomType( wkbPoint );
3036 :
3037 2 : OGRFieldDefn oFieldAptICAO("apt_icao", OFTString );
3038 2 : oFieldAptICAO.SetWidth( 4 );
3039 2 : poFeatureDefn->AddFieldDefn( &oFieldAptICAO );
3040 :
3041 2 : OGRFieldDefn oFieldRwyNum("rwy_num", OFTString );
3042 2 : oFieldRwyNum.SetWidth( 3 );
3043 2 : poFeatureDefn->AddFieldDefn( &oFieldRwyNum );
3044 :
3045 2 : OGRFieldDefn oFieldType("type", OFTString );
3046 2 : poFeatureDefn->AddFieldDefn( &oFieldType );
3047 :
3048 2 : OGRFieldDefn oFieldTrueHeading("true_heading_deg", OFTReal );
3049 2 : oFieldTrueHeading.SetWidth( 6 );
3050 2 : oFieldTrueHeading.SetPrecision( 2 );
3051 2 : poFeatureDefn->AddFieldDefn( &oFieldTrueHeading );
3052 :
3053 2 : OGRFieldDefn oFieldVisualGlidePathAngle("visual_glide_deg", OFTReal );
3054 2 : oFieldVisualGlidePathAngle.SetWidth( 4 );
3055 2 : oFieldVisualGlidePathAngle.SetPrecision( 2 );
3056 2 : poFeatureDefn->AddFieldDefn( &oFieldVisualGlidePathAngle );
3057 2 : }
3058 :
3059 : /************************************************************************/
3060 : /* AddFeature() */
3061 : /************************************************************************/
3062 :
3063 : OGRFeature*
3064 : OGRXPlane_VASI_PAPI_WIGWAG_Layer::AddFeature (const char* pszAptICAO,
3065 : const char* pszRwyNum,
3066 : const char* pszObjectType,
3067 : double dfLat,
3068 : double dfLon,
3069 : double dfHeading,
3070 42 : double dfVisualGlidePathAngle)
3071 : {
3072 42 : int nCount = 0;
3073 42 : OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
3074 42 : poFeature->SetField( nCount++, pszAptICAO );
3075 42 : poFeature->SetField( nCount++, pszRwyNum );
3076 42 : poFeature->SetField( nCount++, pszObjectType );
3077 84 : poFeature->SetGeometryDirectly( new OGRPoint( dfLon, dfLat ) );
3078 42 : poFeature->SetField( nCount++, dfHeading );
3079 42 : poFeature->SetField( nCount++, dfVisualGlidePathAngle );
3080 :
3081 42 : RegisterFeature(poFeature);
3082 :
3083 42 : return poFeature;
3084 896 : }
|