9#include <simgear/structure/exception.hxx>
10#include <simgear/misc/sg_path.hxx>
11#include <simgear/misc/strutils.hxx>
46 if (tag ==
"Airport") {
47 string icao(atts.getValue(
"ICAOcode"));
48 if (_airport->ident() != icao) {
49 throw sg_format_exception(
"Airport and ICAO mismatch", icao, _path.utf8Str());
51 }
else if (tag ==
"Sid") {
52 string ident(atts.getValue(
"Name"));
53 _sid =
new SID(ident, _airport);
56 processRunways(_sid, atts);
57 }
else if (tag ==
"Star") {
58 string ident(atts.getValue(
"Name"));
59 _star =
new STAR(ident, _airport);
62 processRunways(_star, atts);
63 }
else if ((tag ==
"Sid_Waypoint") ||
64 (tag ==
"App_Waypoint") ||
65 (tag ==
"Star_Waypoint") ||
66 (tag ==
"AppTr_Waypoint") ||
67 (tag ==
"SidTr_Waypoint") ||
68 (tag ==
"RwyTr_Waypoint"))
74 _overflightWaypt =
false;
76 }
else if (tag ==
"Approach") {
77 _ident = atts.getValue(
"Name");
82 if (_ident.find(
"ILS") == 0) {
84 }
else if (_ident.find(
"VOR") == 0 || _ident.find(
"VDM") == 0) {
86 }
else if (_ident.find(
"NDB") == 0 || _ident.find(
"NDM") == 0) {
90 _approach =
new Approach(_ident, ty);
91 _procedure = _approach;
92 }
else if ((tag ==
"Sid_Transition") ||
93 (tag ==
"App_Transition") ||
94 (tag ==
"Star_Transition")) {
95 _transIdent = atts.getValue(
"Name");
98 }
else if (tag ==
"RunwayTransition") {
99 _transIdent = atts.getValue(
"Runway");
100 if (!_airport->hasRunwayWithIdent(_transIdent)) {
102 _transition =
nullptr;
105 _transWaypts.clear();
112void NavdataVisitor::processRunways(
ArrivalDeparture* aProc,
const XMLAttributes &atts)
115 if (atts.hasAttribute(
"Runways")) {
116 v = atts.getValue(
"Runways");
120 for (
unsigned int r=0; r<_airport->
numRunways(); ++r) {
126 auto rwys = simgear::strutils::split_on_any_of(v,
" ,");
127 for (
auto rwy : rwys) {
128 if (!_airport->hasRunwayWithIdent(rwy)) {
129 const auto renamed = _airport->findAPTRunwayForNewName(rwy);
130 if (!renamed.empty()) {
133 SG_LOG(SG_NAVAID, SG_DEV_WARN,
"Procedure file " << _path <<
" references unknown airport runway:" << rwy);
138 aProc->
addRunway(_airport->getRunwayByIdent(rwy));
145 if ((tag ==
"Sid_Waypoint") ||
146 (tag ==
"App_Waypoint") ||
147 (tag ==
"Star_Waypoint"))
149 _waypoints.push_back(buildWaypoint(_procedure));
150 }
else if ((tag ==
"AppTr_Waypoint") ||
151 (tag ==
"SidTr_Waypoint") ||
152 (tag ==
"RwyTr_Waypoint") ||
153 (tag ==
"StarTr_Waypoint"))
155 _transWaypts.push_back(buildWaypoint(_transition));
156 }
else if (tag ==
"Sid_Transition") {
159 std::reverse(_transWaypts.begin(), _transWaypts.end());
160 _transition->setPrimary(_transWaypts);
161 _sid->addTransition(_transition);
162 }
else if (tag ==
"Star_Transition") {
164 _transition->setPrimary(_transWaypts);
165 _star->addTransition(_transition);
166 }
else if (tag ==
"App_Transition") {
168 _transition->setPrimary(_transWaypts);
169 _approach->addTransition(_transition);
170 }
else if (tag ==
"RunwayTransition") {
179 std::reverse(_transWaypts.begin(), _transWaypts.end());
185 _transition->setPrimary(_transWaypts);
186 FGRunwayRef rwy = _airport->getRunwayByIdent(_transIdent);
187 ad->addRunwayTransition(rwy, _transition);
188 }
else if (tag ==
"Approach") {
190 }
else if (tag ==
"Sid") {
192 }
else if (tag ==
"Star") {
194 }
else if (tag ==
"Longitude") {
195 _longitude =
atof(_text.c_str());
196 }
else if (tag ==
"Latitude") {
197 _latitude =
atof(_text.c_str());
198 }
else if (tag ==
"Name") {
200 }
else if (tag ==
"Type") {
202 }
else if (tag ==
"Speed") {
203 _speed =
atoi(_text.c_str());
204 }
else if (tag ==
"Altitude") {
205 _altitude =
atof(_text.c_str());
206 }
else if (tag ==
"AltitudeRestriction") {
208 }
else if (tag ==
"Hld_Rad_or_Inbd") {
209 if (_text ==
"Inbd") {
212 }
else if (tag ==
"Hld_Time_or_Dist") {
213 _holdDistance = (_text ==
"Dist");
214 }
else if (tag ==
"Hld_Rad_value") {
215 _holdRadial =
atof(_text.c_str());
216 }
else if (tag ==
"Hld_Turn") {
217 _holdRighthanded = (_text ==
"Right");
218 }
else if (tag ==
"Hld_td_value") {
219 _holdTD =
atof(_text.c_str());
220 }
else if (tag ==
"Hdg_Crs") {
221 _courseFlag =
atoi(_text.c_str());
222 }
else if (tag ==
"Hdg_Crs_value") {
223 _courseOrHeading =
atof(_text.c_str());
224 }
else if (tag ==
"DMEtoIntercept") {
225 _dmeDistance =
atof(_text.c_str());
226 }
else if (tag ==
"RadialtoIntercept") {
227 _radial =
atof(_text.c_str());
228 }
else if (tag ==
"Flytype") {
230 _overflightWaypt = (_text ==
"Fly-over");
231 }
else if ((tag ==
"AltitudeCons") ||
232 (tag ==
"BankLimit") ||
233 (tag ==
"Sp_Turn") ||
234 (tag ==
"Airport") ||
235 (tag ==
"ProceduresDB"))
239 SG_LOG(SG_IO, SG_INFO,
"unrecognized Level-D XML element:" << tag);
246 if (_wayptType ==
"Normal") {
248 SGGeod pos(SGGeod::fromDeg(_longitude, _latitude));
250 }
else if (_wayptType ==
"Runway") {
251 string ident = _wayptName.substr(2);
254 if (renamed.empty()) {
255 SG_LOG(SG_NAVAID, SG_DEV_WARN,
"Missing runway " << ident <<
" reading " << _path);
256 SGGeod pos(SGGeod::fromDeg(_longitude, _latitude));
258 wp =
new BasicWaypt(pos, _wayptName, owner);
265 if (!ident.empty()) {
266 FGRunwayRef rwy = _airport->getRunwayByIdent(ident);
267 wp =
new RunwayWaypt(rwy, owner);
269 }
else if (_wayptType ==
"Hold") {
270 SGGeod pos(SGGeod::fromDeg(_longitude, _latitude));
271 Hold* h =
new Hold(pos, _wayptName, owner);
273 if (_holdRighthanded) {
280 h->setHoldDistance(_holdTD);
282 h->setHoldTime(_holdTD * 60.0);
285 if (_holdRadial >= 0.0) {
286 h->setHoldRadial(_holdRadial);
288 }
else if (_wayptType ==
"Vectors") {
289 wp =
new ATCVectors(owner, _airport);
290 }
else if ((_wayptType ==
"Intc") || (_wayptType ==
"VorRadialIntc")) {
291 SGGeod pos(SGGeod::fromDeg(_longitude, _latitude));
292 wp =
new RadialIntercept(owner, _wayptName, pos, _courseOrHeading, _radial);
293 }
else if (_wayptType ==
"DmeIntc") {
294 SGGeod pos(SGGeod::fromDeg(_longitude, _latitude));
295 wp =
new DMEIntercept(owner, _wayptName, pos, _courseOrHeading, _dmeDistance);
296 }
else if (_wayptType ==
"ConstHdgtoAlt") {
297 wp =
new HeadingToAltitude(owner, _wayptName, _courseOrHeading);
298 }
else if (_wayptType ==
"PBD") {
299 SGGeod pos(SGGeod::fromDeg(_longitude, _latitude)), pos2;
301 SGGeodesy::direct(pos, _courseOrHeading, _dmeDistance, pos2, az2);
302 wp =
new BasicWaypt(pos2, _wayptName, owner);
304 SG_LOG(SG_NAVAID, SG_ALERT,
"implement waypoint type:" << _wayptType);
305 throw sg_format_exception(
"Unrecognized waypt type", _wayptType);
317 if (_overflightWaypt) {
324void NavdataVisitor::finishApproach()
326 WayptVec::iterator it;
330 for (it = _waypoints.begin(); it != _waypoints.end(); ++it) {
337 rwy = (FGRunway*) navid.get();
343 SG_LOG(SG_NAVAID, SG_DEV_WARN,
"Parsing:" << _path <<
" found approach without a runway:" << _ident);
349 WayptVec primary(_waypoints.begin(), it);
352 _waypoints.erase(_waypoints.begin(), ++it);
354 _approach->setRunway(rwy);
355 _approach->setPrimaryAndMissed(primary, _waypoints);
356 _airport->addApproach(_approach);
360void NavdataVisitor::finishSid()
364 std::reverse(_waypoints.begin(), _waypoints.end());
365 _sid->setCommon(_waypoints);
366 _airport->addSID(_sid);
370void NavdataVisitor::finishStar()
372 _star->setCommon(_waypoints);
373 _airport->addSTAR(_star);
379 _text += string(s, len);
388 SG_LOG(SG_NAVAID, SG_WARN,
"Warning: " << message <<
" (" << line <<
',' << column <<
')');
392 SG_LOG(SG_NAVAID, SG_ALERT,
"Error: " << message <<
" (" << line <<
',' << column <<
')');
SGSharedPtr< FGRunway > FGRunwayRef
unsigned int numRunways() const
std::string findAPTRunwayForNewName(const std::string &newIdent) const
FGRunwayRef getRunwayByIndex(unsigned int aIndex) const
bool hasRunwayWithIdent(const std::string &aIdent) const
Describe an approach procedure, including the missed approach segment.
void addRunway(FGRunwayRef aRwy)
NavdataVisitor(FGAirport *aApt, const SGPath &aPath)
virtual void warning(const char *message, int line, int column)
virtual void startElement(const char *name, const XMLAttributes &atts)
virtual void pi(const char *target, const char *data)
virtual void data(const char *s, int len)
virtual void error(const char *message, int line, int column)
virtual void endElement(const char *name)
Encapsulate a transition segment.
Abstract base class for waypoints (and things that are treated similarly by navigation systems).
void setAltitude(double aAlt, RouteRestriction aRestrict, RouteUnits aUnits=DEFAULT_UNITS)
void setFlag(WayptFlag aFlag, bool aV=true)
void setSpeed(double aSpeed, RouteRestriction aRestrict, RouteUnits aUnits=DEFAULT_UNITS)
FlightPlan.hxx - defines a full flight-plan object, including departure, cruise, arrival information ...
RouteRestriction restrictionFromString(const std::string &aStr)
SGSharedPtr< FGPositioned > FGPositionedRef
@ WPT_OVERFLIGHT
must overfly the point directly
std::vector< WayptRef > WayptVec
@ PROCEDURE_RUNWAY_TRANSITION
@ PROCEDURE_APPROACH_RNAV
static double atof(const string &str)
static int atoi(const string &str)