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