1 // airport.hxx -- a really simplistic class to manage airport ID,
2 //                 lat, lon of the center of one of it's runways, and
3 //                 elevation in feet.
4 //
5 // Written by Curtis Olson, started April 1998.
6 // Updated by Durk Talsma, started December 2004.
7 //
8 // Copyright (C) 1998  Curtis L. Olson  - http://www.flightgear.org/~curt
9 //
10 // This program is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU General Public License as
12 // published by the Free Software Foundation; either version 2 of the
13 // License, or (at your option) any later version.
14 //
15 // This program is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 // General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
23 //
24 // $Id$
25 
26 
27 #ifndef _FG_SIMPLE_HXX
28 #define _FG_SIMPLE_HXX
29 
30 #include <simgear/compiler.h>
31 
32 #include <string>
33 #include <vector>
34 #include <map>
35 #include <memory>
36 
37 #include <Navaids/positioned.hxx>
38 #include <Navaids/procedure.hxx>
39 
40 #include "airports_fwd.hxx"
41 #include "runways.hxx"
42 
43 class FGGroundNetwork;
44 
45 /***************************************************************************************
46  *
47  **************************************************************************************/
48 class FGAirport : public FGPositioned
49 {
50   public:
51     FGAirport(PositionedID aGuid, const std::string& id, const SGGeod& location,
52             const std::string& name, bool has_metar, Type aType);
53     ~FGAirport();
54 
isType(FGPositioned::Type ty)55     static bool isType(FGPositioned::Type ty)
56     { return (ty >= FGPositioned::AIRPORT) && (ty <= FGPositioned::SEAPORT); }
57 
getId() const58     const std::string& getId() const { return ident(); }
getName() const59     const std::string& getName() const { return _name; }
toString() const60     std::string toString() const { return "an airport " + ident(); }
61 
getLongitude() const62     double getLongitude() const { return longitude(); }
63     // Returns degrees
getLatitude() const64     double getLatitude()  const { return latitude(); }
65     // Returns ft
getElevation() const66     double getElevation() const { return elevation(); }
getMetar() const67     bool   getMetar()     const { return _has_metar; }
68     bool   isAirport()    const;
69     bool   isSeaport()    const;
70     bool   isHeliport()   const;
71 
72     /// is the airport closed (disused)?
73     /// note at rpesent we look for an [x] in the name, ideally the database
74     /// would explicitly include this
isClosed() const75     bool isClosed() const
76     {
77         return mIsClosed;
78     }
79 
name() const80     virtual const std::string& name() const
81     { return _name; }
82 
83     /**
84      * reload the ILS data from XML if required.
85      */
86     void validateILSData();
87 
88     bool hasTower() const;
89 
90     SGGeod getTowerLocation() const;
91 
setMetar(bool value)92     void setMetar(bool value) { _has_metar = value; }
93 
94     FGRunwayRef getActiveRunwayForUsage() const;
95 
96     FGAirportDynamicsRef getDynamics() const;
97 
98     FGGroundNetwork* groundNetwork() const;
99 
100     unsigned int numRunways() const;
101     unsigned int numHelipads() const;
102     FGRunwayRef getRunwayByIndex(unsigned int aIndex) const;
103     FGHelipadRef getHelipadByIndex(unsigned int aIndex) const;
104     FGRunwayMap getRunwayMap() const;
105     FGHelipadMap getHelipadMap() const;
106 
107     bool hasRunwayWithIdent(const std::string& aIdent) const;
108     bool hasHelipadWithIdent(const std::string& aIdent) const;
109     FGRunwayRef getRunwayByIdent(const std::string& aIdent) const;
110     FGHelipadRef getHelipadByIdent(const std::string& aIdent) const;
111 
112     struct FindBestRunwayForHeadingParams {
FindBestRunwayForHeadingParamsFGAirport::FindBestRunwayForHeadingParams113       FindBestRunwayForHeadingParams() {
114         lengthWeight =  0.01;
115         widthWeight =  0.01;
116         surfaceWeight =  10;
117         deviationWeight =  1;
118         ilsWeight = 0;
119       }
120       double lengthWeight;
121       double widthWeight;
122       double surfaceWeight;
123       double deviationWeight;
124       double ilsWeight;
125     };
126     FGRunwayRef findBestRunwayForHeading(double aHeading, struct FindBestRunwayForHeadingParams * parms = NULL ) const;
127 
128     /**
129      * return the most likely target runway based on a position.
130      * Specifically, return the runway for which the course from aPos
131      * to the runway end, mostly closely matches the runway heading.
132      * This is a good approximation of which runway the position is on or
133      * aiming towards.
134      */
135     FGRunwayRef findBestRunwayForPos(const SGGeod& aPos) const;
136 
137     /**
138      * Retrieve all runways at the airport, but excluding the reciprocal
139      * runways. For example at KSFO this might return 1L, 1R, 28L and 28R,
140      * but would not then include 19L/R or 10L/R.
141      *
142      * Exactly which runways you get, is undefined (i.e, dont assumes it's
143      * runways with heading < 180 degrees) - it depends on order in apt.dat.
144      *
145      * This is useful for code that wants to process each piece of tarmac at
146      * an airport *once*, not *twice* - eg mapping and nav-display code.
147      */
148     FGRunwayList getRunwaysWithoutReciprocals() const;
149 
150     /**
151      * Retrieve all runways at the airport
152      */
153     FGRunwayList getRunways() const;
154 
155      /**
156      * Useful predicate for FMS/GPS/NAV displays and similar - check if this
157      * aiport has a hard-surfaced runway of at least the specified length.
158      */
159     bool hasHardRunwayOfLengthFt(double aLengthFt) const;
160 
161     FGRunwayRef longestRunway() const;
162 
163     unsigned int numTaxiways() const;
164     FGTaxiwayRef getTaxiwayByIndex(unsigned int aIndex) const;
165     FGTaxiwayList getTaxiways() const;
166 
167     unsigned int numPavements() const;
168     FGPavementRef getPavementByIndex(unsigned int aIndex) const;
169     FGPavementList getPavements() const;
170 
171     class AirportFilter : public Filter
172     {
173       public:
pass(FGPositioned * aPos) const174         virtual bool pass(FGPositioned* aPos) const {
175           return passAirport(static_cast<FGAirport*>(aPos));
176         }
177 
minType() const178         virtual Type minType() const {
179           return AIRPORT;
180         }
181 
maxType() const182         virtual Type maxType() const {
183           return AIRPORT;
184         }
185 
passAirport(FGAirport * aApt) const186         virtual bool passAirport(FGAirport* aApt) const {
187           return true;
188         }
189      };
190 
191      /**
192       * Filter which passes heliports and seaports in addition to airports
193       */
194      class PortsFilter : public AirportFilter
195      {
196      public:
maxType() const197        virtual Type maxType() const {
198          return SEAPORT;
199        }
200      };
201 
202      class HardSurfaceFilter : public AirportFilter
203      {
204      public:
205        HardSurfaceFilter(double minLengthFt = -1);
206 
207        virtual bool passAirport(FGAirport* aApt) const;
208 
209      private:
210        double mMinLengthFt;
211      };
212 
213      /**
214       * Filter which passes specified port type and in case of airport checks
215       * if a runway larger the /sim/navdb/min-runway-lenght-ft exists.
216       */
217      class TypeRunwayFilter:
218        public AirportFilter
219      {
220        public:
221          TypeRunwayFilter();
222 
223          /**
224           * Construct from string containing type (airport, seaport or heliport)
225           */
226          bool fromTypeString(const std::string& type);
227 
minType() const228          virtual FGPositioned::Type minType() const { return _type; }
maxType() const229          virtual FGPositioned::Type maxType() const { return _type; }
230          virtual bool pass(FGPositioned* pos) const;
231 
232        protected:
233          FGPositioned::Type _type;
234          double _min_runway_length_ft;
235      };
236 
237 
238      void setProcedures(const std::vector<flightgear::SID*>& aSids,
239       const std::vector<flightgear::STAR*>& aStars,
240       const std::vector<flightgear::Approach*>& aApproaches);
241 
242      void addSID(flightgear::SID* aSid);
243       void addSTAR(flightgear::STAR* aStar);
244       void addApproach(flightgear::Approach* aApp);
245 
246       unsigned int numSIDs() const;
247       flightgear::SID* getSIDByIndex(unsigned int aIndex) const;
248       flightgear::SID* findSIDWithIdent(const std::string& aIdent) const;
249       flightgear::SIDList getSIDs() const;
250 
251       flightgear::Transition* selectSIDByEnrouteTransition(FGPositioned* enroute) const;
252       flightgear::Transition* selectSIDByTransition(const FGRunway* runway, const std::string& aIdent) const;
253 
254       unsigned int numSTARs() const;
255       flightgear::STAR* getSTARByIndex(unsigned int aIndex) const;
256       flightgear::STAR* findSTARWithIdent(const std::string& aIdent) const;
257       flightgear::STARList getSTARs() const;
258 
259       flightgear::Transition* selectSTARByEnrouteTransition(FGPositioned* enroute) const;
260       flightgear::Transition* selectSTARByTransition(const FGRunway* runway, const std::string& aIdent) const;
261 
262       unsigned int numApproaches() const;
263       flightgear::Approach* getApproachByIndex(unsigned int aIndex) const;
264       flightgear::Approach* findApproachWithIdent(const std::string& aIdent) const;
265       flightgear::ApproachList getApproaches
266       (
267         flightgear::ProcedureType type = flightgear::PROCEDURE_INVALID
268       ) const;
269 
270      /**
271       * Syntactic wrapper around FGPositioned::findClosest - find the closest
272       * match for filter, and return it cast to FGAirport. The default filter
273       * passes airports, but not seaports or heliports
274       */
275      static FGAirportRef findClosest(const SGGeod& aPos, double aCuttofNm, Filter* filter = NULL);
276 
277      /**
278       * Helper to look up an FGAirport instance by unique ident. Throws an
279       * exception if the airport could not be found - so callers can assume
280       * the result is non-NULL.
281       */
282      static FGAirportRef getByIdent(const std::string& aIdent);
283 
284      /**
285       * Helper to look up an FGAirport instance by unique ident. Returns NULL
286       * if the airport could not be found.
287       */
288      static FGAirportRef findByIdent(const std::string& aIdent);
289 
290      /**
291       * Specialised helper to implement the AirportList dialog. Performs a
292       * case-insensitive search on airport names and ICAO codes, and returns
293       * matches in a format suitable for use by a puaList.
294       */
295      static char** searchNamesAndIdents(const std::string& aFilter);
296 
297 
298     /**
299      * Sort an FGPositionedList of airports by size (number of runways + length)
300      * this is meant to prioritise more important airports.
301      */
302     static void sortBySize(FGPositionedList&);
303 
304     flightgear::CommStationList commStationsOfType(FGPositioned::Type aTy) const;
305 
306     flightgear::CommStationList commStations() const;
307 
308     static void clearAirportsCache();
309 
310 
311 #if defined(BUILDING_TESTSUITE)
312     // helper to allow testing without needing a full Airports heirarchy
313     void testSuiteInjectGroundnetXML(const SGPath& path);
314 #endif
315 private:
316     static flightgear::AirportCache airportCache;
317 
318     // disable these
319     FGAirport operator=(FGAirport &other);
320     FGAirport(const FGAirport&);
321 
322     /**
323      * helper to read airport data from the scenery XML files.
324      */
325     void loadSceneryDefinitions() const;
326 
327     /**
328      * Helpers to process property data loaded from an ICAO.threshold.xml file
329      */
330     void readThresholdData(SGPropertyNode* aRoot);
331     void processThreshold(SGPropertyNode* aThreshold);
332 
333     void readILSData(SGPropertyNode* aRoot);
334 
335     void validateTowerData() const;
336 
337     /**
338      * Helper to parse property data loaded from an ICAO.twr.xml file
339      */
340     void readTowerData(SGPropertyNode* aRoot);
341 
342     PositionedIDVec itemsOfType(FGPositioned::Type ty) const;
343 
344     std::string _name;
345     bool _has_metar;
346 
347     void loadRunways() const;
348     void loadHelipads() const;
349     void loadTaxiways() const;
350     void loadProcedures() const;
351 
352     mutable bool mTowerDataLoaded;
353     mutable bool mHasTower;
354     mutable SGGeod mTowerPosition;
355 
356     mutable bool mRunwaysLoaded;
357     mutable bool mHelipadsLoaded;
358     mutable bool mTaxiwaysLoaded;
359     mutable bool mProceduresLoaded;
360     bool mIsClosed;
361     mutable bool mThresholdDataLoaded;
362     bool mILSDataLoaded;
363 
364     mutable std::vector<FGRunwayRef> mRunways;
365 
366     mutable PositionedIDVec mHelipads;
367     mutable PositionedIDVec mTaxiways;
368     PositionedIDVec mPavements;
369 
370     typedef SGSharedPtr<flightgear::SID> SIDRef;
371     typedef SGSharedPtr<flightgear::STAR> STARRef;
372     typedef SGSharedPtr<flightgear::Approach> ApproachRef;
373 
374     std::vector<SIDRef> mSIDs;
375     std::vector<STARRef> mSTARs;
376     std::vector<ApproachRef> mApproaches;
377 
378     mutable std::unique_ptr<FGGroundNetwork> _groundNetwork;
379   };
380 
381 // find basic airport location info from airport database
382 const FGAirport *fgFindAirportID( const std::string& id);
383 
384 // get airport elevation
385 double fgGetAirportElev( const std::string& id );
386 
387 #endif // _FG_SIMPLE_HXX
388 
389 
390