1 // runways.cxx -- a simple class to manage airport runway info
2 //
3 // Written by Curtis Olson, started August 2000.
4 //
5 // Copyright (C) 2000 Curtis L. Olson - http://www.flightgear.org/~curt
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 //
21 // $Id$
22
23
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
27
28 #include <cstdio> // sprintf()
29 #include <cstdlib> // atoi()
30 #include <cassert>
31
32 #include <simgear/compiler.h>
33
34 #include <simgear/props/props.hxx>
35
36 #include <string>
37
38 #include "runways.hxx"
39
40 #include <Airports/airport.hxx>
41 #include <Navaids/procedure.hxx>
42 #include <Navaids/navrecord.hxx>
43 #include <Navaids/NavDataCache.hxx>
44
45 using std::string;
46
FGRunway(PositionedID aGuid,PositionedID aAirport,const string & aIdent,const SGGeod & aGeod,const double heading,const double length,const double width,const double displ_thresh,const double stopway,const int surface_code)47 FGRunway::FGRunway(PositionedID aGuid,
48 PositionedID aAirport, const string& aIdent,
49 const SGGeod& aGeod,
50 const double heading, const double length,
51 const double width,
52 const double displ_thresh,
53 const double stopway,
54 const int surface_code) :
55 FGRunwayBase(aGuid, RUNWAY, aIdent, aGeod,
56 heading, length, width, surface_code),
57 _airport(aAirport),
58 _reciprocal(0),
59 _displ_thresh(displ_thresh),
60 _stopway(stopway),
61 _ils(0)
62 {
63 }
64
reverseIdent(const string & aRunwayIdent)65 string FGRunway::reverseIdent(const string& aRunwayIdent)
66 {
67 // Helipads don't have a seperate number per end
68 if (aRunwayIdent.size() && (aRunwayIdent[0] == 'H' || aRunwayIdent[0] == 'h' || aRunwayIdent[0] == 'x')) {
69 return aRunwayIdent;
70 }
71
72 std::string ident(aRunwayIdent);
73
74 char buf[4];
75 int rn = atoi(ident.substr(0,2).c_str());
76 rn += 18;
77 while(rn > 36) {
78 rn -= 36;
79 }
80
81 sprintf(buf, "%02i", rn);
82 if(ident.size() == 3) {
83 char suffix = toupper(ident[2]);
84 if(suffix == 'L') {
85 buf[2] = 'R';
86 } else if (suffix == 'R') {
87 buf[2] = 'L';
88 } else {
89 // something else, just copy
90 buf[2] = suffix;
91 }
92
93 buf[3] = 0;
94 }
95
96 return buf;
97 }
98
score(double aLengthWt,double aWidthWt,double aSurfaceWt,double aIlsWt) const99 double FGRunway::score(double aLengthWt, double aWidthWt, double aSurfaceWt, double aIlsWt) const
100 {
101 int surface = 1;
102 if (_surface_code == 12 || _surface_code == 5) // dry lakebed & gravel
103 surface = 2;
104 else if (_surface_code == 1 || _surface_code == 2) // asphalt & concrete
105 surface = 3;
106
107 int ils = (_ils != 0);
108
109 return _length * aLengthWt + _width * aWidthWt + surface * aSurfaceWt + ils * aIlsWt + 1e-20;
110 }
111
begin() const112 SGGeod FGRunway::begin() const
113 {
114 return pointOnCenterline(0.0);
115 }
116
end() const117 SGGeod FGRunway::end() const
118 {
119 return pointOnCenterline(lengthM());
120 }
121
threshold() const122 SGGeod FGRunway::threshold() const
123 {
124 return pointOnCenterline(_displ_thresh);
125 }
126
setReciprocalRunway(PositionedID other)127 void FGRunway::setReciprocalRunway(PositionedID other)
128 {
129 assert(_reciprocal==0);
130 _reciprocal = other;
131 }
132
airport() const133 FGAirport* FGRunway::airport() const
134 {
135 return loadById<FGAirport>(_airport);
136 }
137
reciprocalRunway() const138 FGRunway* FGRunway::reciprocalRunway() const
139 {
140 return loadById<FGRunway>(_reciprocal);
141 }
142
ILS() const143 FGNavRecord* FGRunway::ILS() const
144 {
145 if (_ils == 0) {
146 return NULL;
147 }
148
149 return loadById<FGNavRecord>(_ils);
150 }
151
glideslope() const152 FGNavRecord* FGRunway::glideslope() const
153 {
154 flightgear::NavDataCache* cache = flightgear::NavDataCache::instance();
155 PositionedID gsId = cache->findNavaidForRunway(guid(), FGPositioned::GS);
156 if (gsId == 0) {
157 return NULL;
158 }
159
160 return loadById<FGNavRecord>(gsId);
161 }
162
getSIDs() const163 flightgear::SIDList FGRunway::getSIDs() const
164 {
165 FGAirport* apt = airport();
166 flightgear::SIDList result;
167 for (unsigned int i=0; i<apt->numSIDs(); ++i) {
168 flightgear::SID* s = apt->getSIDByIndex(i);
169 if (s->isForRunway(this)) {
170 result.push_back(s);
171 }
172 } // of SIDs at the airport iteration
173
174 return result;
175 }
176
getSTARs() const177 flightgear::STARList FGRunway::getSTARs() const
178 {
179 FGAirport* apt = airport();
180 flightgear::STARList result;
181 for (unsigned int i=0; i<apt->numSTARs(); ++i) {
182 flightgear::STAR* s = apt->getSTARByIndex(i);
183 if (s->isForRunway(this)) {
184 result.push_back(s);
185 }
186 } // of STARs at the airport iteration
187
188 return result;
189 }
190
191 flightgear::ApproachList
getApproaches(flightgear::ProcedureType type) const192 FGRunway::getApproaches(flightgear::ProcedureType type) const
193 {
194 FGAirport* apt = airport();
195 flightgear::ApproachList result;
196 for (unsigned int i=0; i<apt->numApproaches(); ++i)
197 {
198 flightgear::Approach* s = apt->getApproachByIndex(i);
199 if( s->runway() == this
200 && (type == flightgear::PROCEDURE_INVALID || type == s->type()) )
201 {
202 result.push_back(s);
203 }
204 } // of approaches at the airport iteration
205
206 return result;
207 }
208
updateThreshold(const SGGeod & newThreshold,double newHeading,double newDisplacedThreshold,double newStopway)209 void FGRunway::updateThreshold(const SGGeod& newThreshold, double newHeading,
210 double newDisplacedThreshold,
211 double newStopway)
212 {
213 modifyPosition(newThreshold);
214 _heading = newHeading;
215 _stopway = newStopway;
216 _displ_thresh = newDisplacedThreshold;
217 }
218
FGHelipad(PositionedID aGuid,PositionedID aAirport,const string & aIdent,const SGGeod & aGeod,const double heading,const double length,const double width,const int surface_code)219 FGHelipad::FGHelipad(PositionedID aGuid,
220 PositionedID aAirport, const string& aIdent,
221 const SGGeod& aGeod,
222 const double heading, const double length,
223 const double width,
224 const int surface_code) :
225 FGRunwayBase(aGuid, HELIPAD, aIdent, aGeod,
226 heading, length, width, surface_code)
227 {
228 }
229