50static const char*
legGhostGetMember(naContext c,
void* g, naRef field, naRef* out);
78static void hashset(naContext c, naRef hash,
const char* key, naRef val)
80 naRef s = naNewString(c);
81 naStr_fromdata(s, (
char*)key, strlen(key));
82 naHash_set(hash, s, val);
87 return naStr_fromdata(naNewString(c),
88 const_cast<char*
>(s.c_str()),
94 naRef n = naNumValue(v);
108 if (!strcmp(s,
"missed"))
return WPT_MISS;
126 if (naIsString(na)) {
127 const char* s = naStr_data(na);
138 const int num =
static_cast<int>(na.num);
154 return (
Waypt*)naGhost_ptr(r);
167 if (!Waypt::put(wpt))
174 if (!FlightPlan::Leg::put(leg))
203 return (
Airway*)naGhost_ptr(r);
210 if (!RouteBase::put(r))
235 FlightPlan::Leg::get(leg);
255 FlightPlan::get(proc);
287 pos =
static_cast<FGRunway*
>(pos)->airport();
309 if (!strcmp(fieldName,
"wp_name") || !strcmp(fieldName,
"id"))
311 else if (!strcmp(fieldName,
"wp_type"))
313 else if (!strcmp(fieldName,
"wp_role"))
315 else if (!strcmp(fieldName,
"wp_lat") || !strcmp(fieldName,
"lat"))
316 *out = naNum(wpt->
position().getLatitudeDeg());
317 else if (!strcmp(fieldName,
"wp_lon") || !strcmp(fieldName,
"lon"))
318 *out = naNum(wpt->
position().getLongitudeDeg());
319 else if (!strcmp(fieldName,
"wp_parent_name")) {
325 }
else if (!strcmp(fieldName,
"wp_parent")) {
338 }
else if (!strcmp(fieldName,
"fly_type")) {
339 if (wpt->
type() ==
"hold") {
344 }
else if (!strcmp(fieldName,
"heading_course")) {
346 }
else if (!strcmp(fieldName,
"navaid")) {
348 }
else if (!strcmp(fieldName,
"airport")) {
350 }
else if (!strcmp(fieldName,
"runway")) {
352 }
else if (!strcmp(fieldName,
"airway")) {
353 if (wpt->
type() ==
"via") {
365 }
else if (!strcmp(fieldName,
"hidden")) {
367 }
else if (wpt->
type() ==
"hold") {
369 const auto hold =
static_cast<Hold*
>(wpt);
370 if (!strcmp(fieldName,
"hold_is_left_handed")) {
371 *out = naNum(hold->isLeftHanded());
372 }
else if (!strcmp(fieldName,
"hold_is_distance")) {
373 *out = naNum(hold->isDistance());
374 }
else if (!strcmp(fieldName,
"hold_is_time")) {
375 *out = naNum(!hold->isDistance());
376 }
else if (!strcmp(fieldName,
"hold_inbound_radial")) {
377 *out = naNum(hold->inboundRadial());
378 }
else if (!strcmp(fieldName,
"hold_heading_radial_deg")) {
379 *out = naNum(hold->inboundRadial());
380 }
else if (!strcmp(fieldName,
"hold_time_or_distance")) {
383 *out = naNum(hold->timeOrDistance());
396 if (!strcmp(fieldName,
"wp_role")) {
397 if (!naIsString(value)) naRuntimeError(c,
"wp_role must be a string");
398 if (wpt->
owner() != NULL) naRuntimeError(c,
"cannot override wp_role on waypoint with parent");
401 naRuntimeError(c,
"unrecognized wp_role value %s", naStr_data(value));
405 }
else if (!strcmp(fieldName,
"fly_type")) {
406 if (!naIsString(value)) naRuntimeError(c,
"fly_type must be a string");
407 bool flyOver = (strcmp(naStr_data(value),
"flyOver") == 0);
409 }
else if (!strcmp(fieldName,
"hidden")) {
410 if (!naIsNum(value)) naRuntimeError(c,
"wpt.hidden must be a number");
412 }
else if (wpt->
type() ==
"hold") {
413 const auto hold =
static_cast<Hold*
>(wpt);
414 if (!strcmp(fieldName,
"hold_heading_radial_deg")) {
415 if (!naIsNum(value)) naRuntimeError(c,
"set hold_heading_radial_deg: invalid hold radial");
416 hold->setHoldRadial(value.num);
417 }
else if (!strcmp(
"hold_is_left_handed", fieldName)) {
418 bool leftHanded =
static_cast<int>(value.num) > 0;
420 hold->setLeftHanded();
422 hold->setRightHanded();
435 const char* fieldName = naStr_data(field);
442 if (naIsNil(arg) || !naIsString(arg)) {
446 const std::string u = simgear::strutils::lowercase(naStr_data(arg));
460 if (naIsNil(arg) || !naIsString(arg)) {
464 const auto u = simgear::strutils::lowercase(naStr_data(arg));
465 if ((u ==
"knots") || (u ==
"kt"))
return SPEED_KNOTS;
468 if ((u ==
"ft") || (u ==
"\'") || (u ==
"feet"))
return ALTITUDE_FEET;
469 if ((u ==
"m") || (u ==
"meter") || (u ==
"meters"))
return ALTITUDE_METER;
472 throw sg_format_exception(
"routeUnitsFromArg: unknown units", u);
498 "flightplan-leg.navaid() called, but can't find the "
499 "underlying waypoint for the flightplan-leg object");
511 "flightplan-leg.airport() called, but can't find the "
512 "underlying waypoint for the flightplan-leg object");
524 "flightplan-leg.runway() called, but can't find the "
525 "underlying waypoint for the flightplan-leg object");
533 const char* fieldName = naStr_data(field);
537 naRuntimeError(c,
"leg ghost member fetched, but no associated leg object found");
543 if (!strcmp(fieldName,
"parents")) {
544 *out = naNewVector(c);
546 }
else if (!strcmp(fieldName,
"index")) {
547 *out = naNum(leg->
index());
548 }
else if (!strcmp(fieldName,
"alt_cstr")) {
550 }
else if (!strcmp(fieldName,
"alt_cstr_type")) {
552 }
else if (!strcmp(fieldName,
"speed_cstr")) {
555 }
else if (!strcmp(fieldName,
"speed_cstr_type")) {
557 }
else if (!strcmp(fieldName,
"leg_distance")) {
559 }
else if (!strcmp(fieldName,
"leg_bearing")) {
561 }
else if (!strcmp(fieldName,
"distance_along_route")) {
563 }
else if (!strcmp(fieldName,
"airport")) {
565 }
else if (!strcmp(fieldName,
"navaid")) {
567 }
else if (!strcmp(fieldName,
"runway")) {
569 }
else if (!strcmp(fieldName,
"hold_count")) {
575 naRuntimeError(c,
"leg ghost member fetched, but no underlying waypoint object found");
584 const char* fieldName = naStr_data(field);
591 const char* fieldName = naStr_data(field);
594 bool didChange =
false;
595 if (!strcmp(fieldName,
"hold_count")) {
596 const int count =
static_cast<int>(value.num);
599 naRuntimeError(c,
"unable to set hold on leg waypoint: maybe unsuitable waypt type?");
600 }
else if (!strcmp(fieldName,
"hold_heading_radial_deg")) {
602 naRuntimeError(c,
"couldn't convert leg waypoint into a hold");
617 const char* fieldName = naStr_data(field);
620 if (!strcmp(fieldName,
"parents")) {
621 *out = naNewVector(c);
623 }
else if (!strcmp(fieldName,
"id"))
625 else if (!strcmp(fieldName,
"departure"))
627 else if (!strcmp(fieldName,
"destination"))
629 else if (!strcmp(fieldName,
"departure_runway"))
631 else if (!strcmp(fieldName,
"destination_runway"))
633 else if (!strcmp(fieldName,
"sid"))
635 else if (!strcmp(fieldName,
"sid_trans"))
637 else if (!strcmp(fieldName,
"star"))
639 else if (!strcmp(fieldName,
"star_trans"))
641 else if (!strcmp(fieldName,
"approach"))
643 else if (!strcmp(fieldName,
"approach_trans"))
645 else if (!strcmp(fieldName,
"current"))
647 else if (!strcmp(fieldName,
"aircraftCategory"))
649 else if (!strcmp(fieldName,
"followLegTrackToFix"))
651 else if (!strcmp(fieldName,
"active"))
653 else if (!strcmp(fieldName,
"cruiseAltitudeFt"))
655 else if (!strcmp(fieldName,
"cruiseFlightLevel"))
657 else if (!strcmp(fieldName,
"cruiseAltitudeM"))
659 else if (!strcmp(fieldName,
"cruiseSpeedKt"))
661 else if (!strcmp(fieldName,
"cruiseSpeedMach"))
663 else if (!strcmp(fieldName,
"cruiseSpeedKPH"))
665 else if (!strcmp(fieldName,
"remarks"))
667 else if (!strcmp(fieldName,
"callsign"))
669 else if (!strcmp(fieldName,
"estimatedDurationMins"))
671 else if (!strcmp(fieldName,
"firstNonDepartureLeg"))
673 else if (!strcmp(fieldName,
"firstArrivalLeg"))
675 else if (!strcmp(fieldName,
"firstApproachLeg"))
677 else if (!strcmp(fieldName,
"destination_runway_leg"))
679 else if (!strcmp(fieldName,
"totalDistanceNm"))
681 else if (!strcmp(fieldName,
"isRoute"))
693 const char* fieldName = naStr_data(field);
696 if (!strcmp(fieldName,
"id")) {
697 if (!naIsString(value)) naRuntimeError(c,
"flightplan.id must be a string");
699 }
else if (!strcmp(fieldName,
"current")) {
700 int index =
static_cast<int>(value.num);
701 if ((index < -1) || (index >= fp->
numLegs())) {
702 naRuntimeError(c,
"flightplan.current must be a valid index or -1");
705 }
else if (!strcmp(fieldName,
"departure")) {
718 if (naIsNil(value)) {
723 naRuntimeError(c,
"bad argument type setting departure");
724 }
else if (!strcmp(fieldName,
"destination")) {
737 if (naIsNil(value)) {
742 naRuntimeError(c,
"bad argument type setting destination");
743 }
else if (!strcmp(fieldName,
"departure_runway")) {
750 naRuntimeError(c,
"bad argument type setting departure runway");
751 }
else if (!strcmp(fieldName,
"destination_runway")) {
752 if (naIsNil(value)) {
763 naRuntimeError(c,
"bad argument type setting destination runway");
764 }
else if (!strcmp(fieldName,
"sid")) {
776 if (naIsString(value)) {
777 const std::string s(naStr_data(value));
781 naRuntimeError(c,
"Unknown SID %s at %s", s.c_str(), apt->
ident().c_str());
788 if (naIsNil(value)) {
793 naRuntimeError(c,
"bad argument type setting SID");
794 }
else if (!strcmp(fieldName,
"sid_trans")) {
801 if (naIsNil(value)) {
806 if (naIsString(value)) {
807 const std::string s(naStr_data(value));
813 naRuntimeError(c,
"No such transition %s for SID %s at %s",
821 naRuntimeError(c,
"Couldn't find SID transition to %s at %s",
834 naRuntimeError(c,
"bad argument type setting sid_trans");
835 }
else if (!strcmp(fieldName,
"star")) {
847 if (naIsString(value)) {
848 const std::string s(naStr_data(value));
852 naRuntimeError(c,
"Unknown SID %s at %s", s.c_str(), apt->
ident().c_str());
858 if (naIsNil(value)) {
863 naRuntimeError(c,
"bad argument type setting STAR");
864 }
else if (!strcmp(fieldName,
"star_trans")) {
871 if (naIsNil(value)) {
876 if (naIsString(value)) {
877 const std::string s(naStr_data(value));
883 naRuntimeError(c,
"No such transition %s for STAR %s at %s",
891 naRuntimeError(c,
"Couldn't find STAR transition to %s at %s",
904 naRuntimeError(c,
"bad argument type setting star_trans");
905 }
else if (!strcmp(fieldName,
"approach")) {
917 if (naIsString(value)) {
923 if (naIsNil(value)) {
928 naRuntimeError(c,
"bad argument type setting approach");
929 }
else if (!strcmp(fieldName,
"approach_trans")) {
936 if (naIsNil(value)) {
941 if (naIsString(value)) {
942 const std::string s(naStr_data(value));
948 naRuntimeError(c,
"No such transition %s for approach %s at %s",
954 naRuntimeError(c,
"No approach selected, can't set approach_trans");
964 naRuntimeError(c,
"bad argument type setting approach_trans");
965 }
else if (!strcmp(fieldName,
"aircraftCategory")) {
966 if (!naIsString(value)) naRuntimeError(c,
"aircraftCategory must be a string");
968 }
else if (!strcmp(fieldName,
"followLegTrackToFix")) {
970 }
else if (!strcmp(fieldName,
"cruiseAltitudeFt")) {
972 }
else if (!strcmp(fieldName,
"cruiseAltitudeM")) {
974 }
else if (!strcmp(fieldName,
"cruiseFlightLevel")) {
976 }
else if (!strcmp(fieldName,
"cruiseSpeedKt")) {
978 }
else if (!strcmp(fieldName,
"cruiseSpeedKPH")) {
980 }
else if (!strcmp(fieldName,
"cruiseSpeedMach")) {
982 }
else if (!strcmp(fieldName,
"callsign")) {
983 if (!naIsString(value)) naRuntimeError(c,
"flightplan.callsign must be a string");
985 }
else if (!strcmp(fieldName,
"remarks")) {
986 if (!naIsString(value)) naRuntimeError(c,
"flightplan.remarks must be a string");
988 }
else if (!strcmp(fieldName,
"estimatedDurationMins")) {
1024 const char* fieldName = naStr_data(field);
1027 if (!strcmp(fieldName,
"parents")) {
1028 *out = naNewVector(c);
1030 }
else if (!strcmp(fieldName,
"id"))
1032 else if (!strcmp(fieldName,
"airport"))
1034 else if (!strcmp(fieldName,
"tp_type"))
1036 else if (!strcmp(fieldName,
"radio"))
1038 else if (!strcmp(fieldName,
"runways")) {
1039 *out = naNewVector(c);
1043 }
else if (!strcmp(fieldName,
"transitions")) {
1044 const auto ty = proc->
type();
1047 const auto app =
static_cast<Approach*
>(proc);
1048 idents = app->transitionIdents();
1057 *out = naNewVector(c);
1058 for (std::string
id : idents) {
1070 const char* fieldName = naStr_data(field);
1073 if (!strcmp(fieldName,
"parents")) {
1074 *out = naNewVector(c);
1076 }
else if (!strcmp(fieldName,
"id"))
1078 else if (!strcmp(fieldName,
"level")) {
1081 const auto level = awy->
level();
1086 default: *out = naNil();
1088 }
else if (!strcmp(fieldName,
"level_code")) {
1090 const auto level = awy->
level();
1091 *out = naNum(
static_cast<int>(level));
1101 bool asRoute =
false;
1103 if (naIsNum(args[0])) {
1104 asRoute = args[0].num != 0.0;
1106 }
else if ((argc == 2) && naIsNum(args[1])) {
1108 asRoute = args[1].num != 0.0;
1113 if ((argc > 0) && naIsString(args[0])) {
1114 SGPath path(naStr_data(args[0]));
1115 if (!path.exists()) {
1116 std::string pdata = path.utf8Str();
1117 naRuntimeError(c,
"createFlightplan, no file at path %s", pdata.c_str());
1120 if (!fp->load(path)) {
1121 SG_LOG(SG_NASAL, SG_WARN,
"failed to load flight-plan from " << path);
1136 if ((argc > 0) && naIsString(args[0])) {
1140 naRuntimeError(c,
"bad arguments to flightplan()");
1153 _gcSaveKey = _nasal->gcSave(ins);
1158 _nasal->gcRelease(_gcSaveKey);
1163 callDelegateMethod(
"departureChanged");
1168 callDelegateMethod(
"arrivalChanged");
1173 callDelegateMethod(
"waypointsChanged");
1178 callDelegateMethod(
"currentWaypointChanged");
1183 callDelegateMethod(
"cleared");
1188 callDelegateMethod(
"endOfFlightPlan");
1193 callDelegateMethod(
"activated");
1198 callDelegateMethod(
"sequence");
1203 callDelegateMethod(
"loaded");
1207 void callDelegateMethod(
const char* method)
1210 naContext ctx = naNewContext();
1212 if (naMember_cget(ctx, _instance, method, &f) != 0) {
1215 _nasal->
callMethod(f, _instance, 1, arg, naNil());
1235 _gcSaveKey = _nasal->
gcSave(_func);
1240 _nasal->gcRelease(_gcSaveKey);
1246 naContext ctx = naNewContext();
1248 naRef instance = _nasal->call(_func, 1, args, naNil());
1251 if (!naIsNil(instance)) {
1265 const std::string&
id()
const
1271 const std::string _id;
1289 if ((argc < 1) || !naIsFunc(args[0])) {
1290 naRuntimeError(c,
"non-function argument to registerFlightPlanDelegate");
1293 const std::string delegateId = (argc > 1) ? naStr_data(args[1]) : std::string{};
1294 if (!delegateId.empty()) {
1297 auto nfpd = static_cast<NasalFPDelegateFactory*>(factory.get());
1298 return nfpd->id() == delegateId;
1301 naRuntimeError(c,
"duplicate delegate ID at registerFlightPlanDelegate: %s", delegateId.c_str());
1305 auto factory = std::make_shared<NasalFPDelegateFactory>(args[0], delegateId);
1313 if ((argc < 1) || !naIsString(args[0])) {
1314 naRuntimeError(c,
"non-string argument to unregisterFlightPlanDelegate");
1317 const std::string delegateId = naStr_data(args[0]);
1320 auto nfpd = static_cast<NasalFPDelegateFactory*>(factory.get());
1321 return nfpd->id() == delegateId;
1325 SG_LOG(SG_NASAL, SG_DEV_WARN,
"f_unregisterFPDelegate: no delegate with ID:" << delegateId);
1360 naRef result = naNewVector(c);
1370 naRuntimeError(c,
"airwaysSearch needs at least two arguments");
1376 if (!start || !end) {
1377 SG_LOG(SG_NASAL, SG_WARN,
"airwaysSearch: start or end points are invalid");
1381 bool highLevel =
true;
1382 if ((argc > 2) && naIsString(args[2])) {
1383 if (!strcmp(naStr_data(args[2]),
"lowlevel")) {
1400 if ((argc < 1) || !naIsString(args[0])) {
1401 naRuntimeError(c,
"findAirway needs at least one string arguments");
1404 std::string ident = naStr_data(args[0]);
1408 int posArgIndex = 1;
1413 if (maybeLevel.has_value()) {
1418 if (argc > posArgIndex) {
1425 SG_LOG(SG_NASAL, SG_INFO,
"Pevious navaid for airway():" << pos->ident());
1438static naRef
f_createWP(naContext c, naRef me,
int argc, naRef* args)
1443 if (((argc - argOffset) < 1) || !naIsString(args[argOffset])) {
1444 naRuntimeError(c,
"createWP: no identifier supplied");
1447 std::string ident = naStr_data(args[argOffset++]);
1451 if (argc > argOffset) {
1454 naRuntimeError(c,
"createWP: bad waypoint role");
1466 naRuntimeError(c,
"createWPFrom: need at least one argument");
1471 naRuntimeError(c,
"createWPFrom: couldn't convert arg[0] to FGPositioned");
1485 naRuntimeError(c,
"createWPFrom: bad waypoint role");
1495 if ((argc < 2) || (argc > 3)) {
1496 naRuntimeError(c,
"createViaTo: needs two or three arguments");
1500 naRef toArg = args[1];
1501 if (!airway && naIsString(args[0])) {
1502 std::string airwayName = naStr_data(args[0]);
1509 naRuntimeError(c,
"createViaTo: level argument is not accepted");
1518 naRuntimeError(c,
"createViaTo: couldn't find airway with provided name: %s",
1519 naStr_data(args[0]));
1524 naRuntimeError(c,
"createViaTo: invalid airway");
1528 if (naIsString(toArg)) {
1529 WayptRef enroute = airway->findEnroute(naStr_data(toArg));
1531 naRuntimeError(c,
"unknown waypoint on airway %s: %s",
1532 naStr_data(args[0]), naStr_data(toArg));
1535 nav = enroute->source();
1539 naRuntimeError(c,
"createViaTo: arg[1] is not a navaid");
1543 if (!airway->containsNavaid(nav)) {
1544 naRuntimeError(c,
"createViaTo: navaid not on airway");
1547 Via* via =
new Via(
nullptr, airway, nav);
1553 if ((argc < 3) || (argc > 4)) {
1554 naRuntimeError(c,
"createViaFromTo: needs three or four arguments");
1559 naRuntimeError(c,
"createViaFromTo: from wp not found");
1563 naRef toArg = args[2];
1564 if (!airway && naIsString(args[1])) {
1565 std::string airwayName = naStr_data(args[1]);
1572 naRuntimeError(c,
"createViaFromTo: level argument is not accepted");
1581 naRuntimeError(c,
"createViaFromTo: couldn't find airway with provided name: %s",
1582 naStr_data(args[1]));
1587 naRuntimeError(c,
"createViaFromTo: invalid airway");
1591 if (naIsString(toArg)) {
1592 WayptRef enroute = airway->findEnroute(naStr_data(toArg));
1594 naRuntimeError(c,
"unknown waypoint on airway %s: %s",
1595 naStr_data(args[1]), naStr_data(toArg));
1598 nav = enroute->source();
1602 naRuntimeError(c,
"createViaFromTo: final arg is not a navaid");
1606 if (!airway->containsNavaid(nav)) {
1607 naRuntimeError(c,
"createViaFromTo: navaid not on airway");
1610 Via* via =
new Via(
nullptr, airway, nav);
1623 naRuntimeError(c,
"flightplan.getWP called on non-flightplan object");
1630 index = (int)naNumValue(args[0]).num;
1633 if ((index < 0) || (index >= fp->
numLegs())) {
1644 naRuntimeError(c,
"flightplan.currentWP called on non-flightplan object");
1649 index +=
static_cast<int>(naNumValue(args[0]).num);
1652 if ((index < 0) || (index >= fp->
numLegs())) {
1663 naRuntimeError(c,
"flightplan.nextWP called on non-flightplan object");
1672 naRuntimeError(c,
"flightplan.numWaypoints called on non-flightplan object");
1681 naRuntimeError(c,
"flightplan.f_flightplan_numRemainingWaypoints called on non-flightplan object");
1696 naRuntimeError(c,
"flightplan.appendWP called on non-flightplan object");
1702 return naNum(index);
1709 naRuntimeError(c,
"flightplan.insertWP called on non-flightplan object");
1714 if ((argc > 1) && naIsNum(args[1])) {
1715 index = (int)args[1].num;
1726 naRuntimeError(c,
"flightplan.insertWPAfter called on non-flightplan object");
1731 if ((argc > 1) && naIsNum(args[1])) {
1732 index = (int)args[1].num;
1743 naRuntimeError(c,
"flightplan.insertWaypoints called on non-flightplan object");
1748 if (naIsNil(args[0])) {
1753 if (!naIsVector(args[0])) {
1754 naRuntimeError(c,
"flightplan.insertWaypoints expects vector as first arg");
1757 int count = naVec_size(args[0]);
1758 for (
int i = 0;
i < count; ++
i) {
1766 if ((argc > 1) && naIsNum(args[1])) {
1767 index = (int)args[1].num;
1778 naRuntimeError(c,
"flightplan.deleteWP called on non-flightplan object");
1781 if ((argc < 1) || !naIsNum(args[0])) {
1782 naRuntimeError(c,
"bad argument to flightplan.deleteWP");
1785 int index = (int)args[0].num;
1794 naRuntimeError(c,
"flightplan.clearLegs called on non-flightplan object");
1805 naRuntimeError(c,
"flightplan.clearAll called on non-flightplan object");
1817 naRuntimeError(c,
"flightplan.clearWPType called on non-flightplan object");
1821 naRuntimeError(c,
"insufficent args to flightplan.clearWPType");
1826 naRuntimeError(c,
"clearWPType: bad waypoint role");
1837 naRuntimeError(c,
"flightplan.clone called on non-flightplan object");
1840 const bool convertRouteToFP = (argc > 0) && naIsNum(args[0]) && (args[0].num != 0.0);
1848 naRuntimeError(c,
"flightplan.pathGeod called on non-flightplan object");
1851 if ((argc < 1) || !naIsNum(args[0])) {
1852 naRuntimeError(c,
"bad argument to flightplan.pathGeod");
1855 if ((argc > 1) && !naIsNum(args[1])) {
1856 naRuntimeError(c,
"bad argument to flightplan.pathGeod");
1859 int index = (int)args[0].num;
1860 double offset = (argc > 1) ? args[1].num : 0.0;
1861 naRef result = naNewHash(c);
1863 hashset(c, result,
"lat", naNum(g.getLatitudeDeg()));
1864 hashset(c, result,
"lon", naNum(g.getLongitudeDeg()));
1872 naRuntimeError(c,
"flightplan.finish called on non-flightplan object");
1885 naRuntimeError(c,
"activate called on non-flightplan object");
1889 naRuntimeError(c,
"activate called on isRoute flightplan");
1901 naRuntimeError(c,
"flightplan.indexOfWP called on non-flightplan object");
1911 if (leg->
owner() == fp) {
1912 return naNum(leg->
index());
1915 naRuntimeError(c,
"flightplan.indexOfWP called on leg from different flightplan");
1920 if (argOffset > 0) {
1931 naRuntimeError(c,
"save called on non-flightplan object");
1934 if ((argc < 1) || !naIsString(args[0])) {
1935 naRuntimeError(c,
"flightplan.save, no file path argument");
1938 const SGPath raw_path(naStr_data(args[0]));
1939 const SGPath validated_path = SGPath(raw_path).validate(
true);
1940 if (validated_path.isNull()) {
1941 naRuntimeError(c,
"flightplan.save, writing to path is not permitted");
1944 bool ok = fp->
save(validated_path);
1952 naRuntimeError(c,
"parseICAORoute called on non-flightplan object");
1955 if ((argc < 1) || !naIsString(args[0])) {
1956 naRuntimeError(c,
"flightplan.parseICAORoute, no route argument");
1967 naRuntimeError(c,
"toICAORoute called on non-flightplan object");
1977 naRuntimeError(c,
"computeDuration called on non-flightplan object");
1988 naRuntimeError(c,
"leg.setSpeed called on non-flightplan-leg object");
1996 if (naIsNil(args[0])) {
2000 if ((argc > 1) && naIsString(args[1])) {
2003 naRuntimeError(c,
"bad arguments to setSpeed");
2013 naRuntimeError(c,
"bad arguments to setSpeed");
2023 naRuntimeError(c,
"leg.setAltitude called on non-flightplan-leg object");
2031 if (naIsNil(args[0])) {
2038 naRuntimeError(c,
"bad arguments to leg.setAltitude");
2044 }
else if (naIsVector(args[0])) {
2045 const auto altTuple = args[0];
2047 if ((argc < 2) || (naVec_size(altTuple) != 2)) {
2048 naRuntimeError(c,
"missing/bad arguments to leg.setAltitude");
2053 naRuntimeError(c,
"leg.setAltitude: passed a 2-tuple, but restriction type is not 'between'");
2056 double constraintAltitude;
2057 const auto ok =
convertToNum(naVec_get(altTuple, 0), constraintAltitude)
2060 naRuntimeError(c,
"leg.setAltitude: tuple members not convertible to numeric altitudes");
2072 naRuntimeError(c,
"bad arguments to setleg.setAltitude");
2082 naRuntimeError(c,
"leg.altitude called on non-flightplan-leg object");
2091 naRef result = naNewVector(c);
2093 naVec_append(result, naNum(leg->
altitude(units)));
2097 return naNum(leg->
altitude(units));
2104 naRuntimeError(c,
"leg.speed called on non-flightplan-leg object");
2112 return naNum(leg->
speed(units));
2118 if (!leg || !leg->
owner()) {
2119 naRuntimeError(c,
"leg.courseAndDistanceFrom called on non-flightplan-leg object");
2127 double courseDeg, az2, distanceM;
2128 SGGeodesy::inverse(pos, wpPos, courseDeg, az2, distanceM);
2130 naRef result = naNewVector(c);
2131 naVec_append(result, naNum(courseDeg));
2132 naVec_append(result, naNum(distanceM * SG_METER_TO_NM));
2136static naRef
f_leg_path(naContext c, naRef me,
int argc, naRef* args)
2139 if (!leg || !leg->
owner()) {
2140 naRuntimeError(c,
"leg.setAltitude called on non-flightplan-leg object");
2146 naRef result = naNewVector(c);
2147 for (SGGeod
p : gv) {
2149 naRef coord = naNewHash(c);
2150 hashset(c, coord,
"lat", naNum(
p.getLatitudeDeg()));
2151 hashset(c, coord,
"lon", naNum(
p.getLongitudeDeg()));
2152 naVec_append(result, coord);
2162 naRuntimeError(c,
"procedure.transition called on non-procedure object");
2165 const std::string ident{naStr_data(args[0])};
2166 const auto ty = proc->
type();
2168 const auto app =
static_cast<Approach*
>(proc);
2174 naRuntimeError(c,
"procedure.transition called on non-SID or -STAR");
2187 if (rwy) ++argOffset;
2193 if (argOffset < argc) {
2207 bool ok = app->
route(rwy, iaf, r);
2218 naRuntimeError(c,
"procedure.route called on non-procedure object");
2227 naRuntimeError(c,
"procedure.route called on unsuitable procedure type");
2232 if (rwy) ++argOffset;
2236 if (argOffset < argc) {
2242 if (!ad->
route(rwy, trans, r)) {
2243 SG_LOG(SG_NASAL, SG_WARN,
"procedure.route failed for ArrivalDeparture somehow");
2254 naRuntimeError(c,
"airway.contains called on non-airway object");
2258 naRuntimeError(c,
"missing arg to airway.contains");
2273 naRuntimeError(c,
"airway.viaWaypoints called on non-airway object");
2276 if ((argc < 1) || (argc > 2)) {
2277 naRuntimeError(c,
"Airway.viaWaypoints: needs one ro two arguments");
2283 naRuntimeError(c,
"Airway.viaWaypoints: from wp not found");
2286 naRef toArg = args[1];
2288 if (naIsString(toArg)) {
2291 naRuntimeError(c,
"unknown waypoint on airway %s: %s",
2292 awy->
ident().c_str(), naStr_data(toArg));
2295 nav = enroute->source();
2299 naRuntimeError(c,
"Airway.viaWaypoints: final arg is not a navaid");
2305 naRuntimeError(c,
"Airway.viaWaypoints: navaid not on airway");
2308 auto wps = awy->
via(fromWp, toWaypt);
2328 {
nullptr,
nullptr}};
2398 for (
int i = 0;
funcs[
i].name;
i++) {
std::vector< SGGeod > SGGeodVec
static naRef approachRoute(Approach *app, naContext c, int argc, naRef *args)
static naRef stringToNasal(naContext c, const std::string &s)
naRef ghostForFlightPlan(naContext c, const FlightPlan *fp)
static naGhostType ProcedureGhostType
static naRef f_leg_path(naContext c, naRef me, int argc, naRef *args)
static naRef f_flightplan_toICAORoute(naContext c, naRef me, int, naRef *)
static naRef fpLegPrototype
static naRef f_createDiscontinuity(naContext c, naRef me, int argc, naRef *args)
static naRef f_flightplan_computeDuration(naContext c, naRef me, int, naRef *)
static void waypointGhostSetMember(naContext c, void *g, naRef field, naRef value)
static naRef procedurePrototype
static naRef f_flightplan_parseICAORoute(naContext c, naRef me, int argc, naRef *args)
static Airway * airwayGhost(naRef r)
static void hashset(naContext c, naRef hash, const char *key, naRef val)
static void flightplanGhostSetMember(naContext c, void *g, naRef field, naRef value)
static naRef f_createWP(naContext c, naRef me, int argc, naRef *args)
static naRef f_flightplan_getWP(naContext c, naRef me, int argc, naRef *args)
static naRef f_fpLeg_runway(naContext c, naRef me, int argc, naRef *args)
static naRef f_flightplan(naContext c, naRef me, int argc, naRef *args)
static naRef f_airwaySearch(naContext c, naRef me, int argc, naRef *args)
static naRef f_flightplan_save(naContext c, naRef me, int argc, naRef *args)
static naRef f_procedure_route(naContext c, naRef me, int argc, naRef *args)
static struct @032150236342374176343243244364035346052374146336 funcs[]
static naRef f_leg_speed(naContext c, naRef me, int argc, naRef *args)
naRef ghostForWaypt(naContext c, const Waypt *wpt)
static void wayptGhostDestroy(void *g)
naRef ghostForAirway(naContext c, const Airway *awy)
static naGhostType FlightPlanGhostType
static naRef convertWayptVecToNasal(naContext c, const WayptVec &wps)
static naRef f_flightplan_insertWPAfter(naContext c, naRef me, int argc, naRef *args)
static const char * procedureGhostGetMember(naContext c, void *g, naRef field, naRef *out)
static naRef f_flightplan_clearAll(naContext c, naRef me, int argc, naRef *args)
static RouteUnits routeUnitsFromArg(naRef arg)
static void legGhostSetMember(naContext c, void *g, naRef field, naRef value)
static naRef f_flightplan_numWaypoints(naContext c, naRef me, int argc, naRef *args)
static const char * legGhostGetMember(naContext c, void *g, naRef field, naRef *out)
static naGhostType FPLegGhostType
static naGhostType WayptGhostType
static void legGhostDestroy(void *g)
static void routeBaseGhostDestroy(void *g)
static naRef f_airway_contains(naContext c, naRef me, int argc, naRef *args)
static const char * waypointCommonGetMember(naContext c, Waypt *wpt, const char *fieldName, naRef *out)
static naRef f_flightplan_clearWPType(naContext c, naRef me, int argc, naRef *args)
static naRef procedureTpType(naContext c, ProcedureType ty)
static WayptRef wayptFromArg(naRef arg)
static naRef f_createWPFrom(naContext c, naRef me, int argc, naRef *args)
static WayptFlag wayptFlagFromString(const char *s)
static naRef f_flightplan_deleteWP(naContext c, naRef me, int argc, naRef *args)
static naRef f_flightplan_appendWP(naContext c, naRef me, int argc, naRef *args)
static naRef f_leg_courseAndDistanceFrom(naContext c, naRef me, int argc, naRef *args)
static naRef f_flightplan_insertWaypoints(naContext c, naRef me, int argc, naRef *args)
static const char * wayptGhostGetMember(naContext c, void *g, naRef field, naRef *out)
static bool convertToNum(naRef v, double &result)
FlightPlan::Leg * fpLegGhost(naRef r)
static std::optional< Airway::Level > airwayLevelFromNasal(naRef na)
naRef ghostForLeg(naContext c, const FlightPlan::Leg *leg)
static naRef waypointNavaid(naContext c, Waypt *wpt)
static naRef f_flightplan_indexOfWp(naContext c, naRef me, int argc, naRef *args)
static naRef f_flightplan_nextWP(naContext c, naRef me, int argc, naRef *args)
static naRef f_registerFPDelegate(naContext c, naRef me, int argc, naRef *args)
naRef ghostForProcedure(naContext c, const Procedure *proc)
static naRef f_flightplan_currentWP(naContext c, naRef me, int argc, naRef *args)
static naRef f_leg_setSpeed(naContext c, naRef me, int argc, naRef *args)
static const char * airwayGhostGetMember(naContext c, void *g, naRef field, naRef *out)
static naRef f_flightplan_insertWP(naContext c, naRef me, int argc, naRef *args)
static naRef f_flightplan_clearLegs(naContext c, naRef me, int argc, naRef *args)
static naRef f_leg_setAltitude(naContext c, naRef me, int argc, naRef *args)
static naRef procedureRadioType(naContext c, ProcedureType ty)
static naRef waypointAirport(naContext c, Waypt *wpt)
static naRef flightplanPrototype
static naRef f_createViaFromTo(naContext c, naRef me, int argc, naRef *args)
static naRef f_airway_viaWaypoints(naContext c, naRef me, int argc, naRef *args)
static naRef f_findAirway(naContext c, naRef me, int argc, naRef *args)
naRef initNasalFlightPlan(naRef globals, naContext c)
void shutdownNasalFlightPlan()
static RouteRestriction routeRestrictionFromArg(naRef arg)
static naRef waypointRunway(naContext c, Waypt *wpt)
static naRef f_flightplan_numRemainingWaypoints(naContext c, naRef me, int argc, naRef *args)
static FlightPlan * flightplanGhost(naRef r)
static naRef airwayPrototype
static naRef f_createViaTo(naContext c, naRef me, int argc, naRef *args)
static naGhostType AirwayGhostType
static naRef f_flightplan_clone(naContext c, naRef me, int argc, naRef *args)
static naRef f_leg_altitude(naContext c, naRef me, int argc, naRef *args)
static const char * flightplanGhostGetMember(naContext c, void *g, naRef field, naRef *out)
naRef routeRestrictionToNasal(naContext c, RouteRestriction rr)
static std::vector< FlightPlan::DelegateFactoryRef > static_nasalDelegateFactories
static naRef f_flightplan_activate(naContext c, naRef me, int argc, naRef *args)
static naRef f_fpLeg_airport(naContext c, naRef me, int argc, naRef *args)
static naRef f_flightplan_finish(naContext c, naRef me, int argc, naRef *args)
static naRef f_fpLeg_navaid(naContext c, naRef me, int argc, naRef *args)
static naRef f_procedure_transition(naContext c, naRef me, int argc, naRef *args)
Procedure * procedureGhost(naRef r)
static naRef f_unregisterFPDelegate(naContext c, naRef me, int argc, naRef *args)
static naRef f_createFlightplan(naContext c, naRef me, int argc, naRef *args)
Waypt * wayptGhost(naRef r)
static bool waypointCommonSetMember(naContext c, Waypt *wpt, const char *fieldName, naRef value)
static naRef wayptFlagToNasal(naContext c, unsigned int flags)
static naRef f_flightplan_pathGeod(naContext c, naRef me, int argc, naRef *args)
FGAirport * airportGhost(naRef r)
FGRunway * runwayGhost(naRef r)
naRef ghostForRunway(naContext c, const FGRunway *r)
int geodFromArgs(naRef *args, int offset, int argc, SGGeod &result)
FGPositionedRef positionedFromArg(naRef ref)
naRef ghostForPositioned(naContext c, FGPositionedRef pos)
FGPositioned * positionedGhost(naRef r)
naRef ghostForAirport(naContext c, const FGAirport *apt)
SGSharedPtr< FGRunway > FGRunwayRef
flightgear::STAR * findSTARWithIdent(const std::string &aIdent) const
flightgear::Approach * findApproachWithIdent(const std::string &aIdent) const
flightgear::SID * findSIDWithIdent(const std::string &aIdent) const
naRef callMethod(naRef code, naRef self, int argc, naRef *args, naRef locals)
static bool isRunwayType(FGPositioned *pos)
static bool isAirportType(FGPositioned *pos)
static bool isNavaidType(FGPositioned *pos)
const std::string & ident() const
Top level route manager class.
void destroyFlightPlanDelegate(FlightPlan *fp, FlightPlan::Delegate *d) override
FlightPlan::Delegate * createFlightPlanDelegate(FlightPlan *fp) override
virtual ~NasalFPDelegateFactory()
const std::string & id() const
NasalFPDelegateFactory(naRef code, const std::string &id)
void currentWaypointChanged() override
void arrivalChanged() override
void sequence() override
Invoked when the C++ code determines the active leg is done / next leg should be sequenced.
void activated() override
~NasalFPDelegate() override
void endOfFlightPlan() override
void waypointsChanged() override
void departureChanged() override
NasalFPDelegate(FlightPlan *fp, FGNasalSys *sys, naRef ins)
flightgear::SGGeodVec pathForIndex(int index) const
SGGeod positionForIndex(int index) const
bool route(WayptRef aFrom, WayptRef aTo, WayptVec &aPath)
Principal routing algorithm.
static Network * lowLevel()
WayptVec via(const WayptRef &from, const WayptRef &to) const
@ HighLevel
Victor airways.
bool containsNavaid(const FGPositionedRef &navaid) const
WayptRef findEnroute(const std::string &aIdent) const
static AirwayRef findByIdentAndNavaid(const std::string &aIdent, const FGPositionedRef nav)
Find an airway by ident, and containing a particula rnavaid/fix.
static Network * highLevel()
std::string ident() const override
static AirwayRef findByIdent(const std::string &aIdent, Level level)
Describe an approach procedure, including the missed approach segment.
Transition * findTransitionByName(const std::string &aIdent) const
static bool isApproach(ProcedureType ty)
bool routeWithTransition(FGRunwayRef runway, Transition *trans, WayptVec &aWps)
bool route(FGRunwayRef runway, WayptRef aIAF, WayptVec &aWps)
Build a route from a valid IAF to the runway, including the missed segment.
virtual bool route(FGRunwayRef aWay, Transition *trans, WayptVec &aPath)=0
Find a path between the runway and enroute structure.
string_list transitionIdents() const
Transition * findTransitionByName(const std::string &aIdent) const
Find an enroute transition waypoint by identifier.
Represent a route discontinuity.
abstract interface for creating delegates automatically when a flight-plan is created or loaded
flight-plan leg encapsulation
bool convertWaypointToHold()
double speed(RouteUnits units=DEFAULT_UNITS) const
double distanceAlongRoute() const
RouteRestriction altitudeRestriction() const
void setSpeed(RouteRestriction ty, double speed, RouteUnits units=DEFAULT_UNITS)
RouteRestriction speedRestriction() const
bool setHoldCount(int count)
requesting holding at the waypoint upon reaching it.
double distanceNm() const
void markWaypointDirty()
helper function, if the waypoint is modified in some way, to notify the flightplan owning this leg,...
double altitude(RouteUnits units=DEFAULT_UNITS) const
unsigned int index() const
FlightPlan * owner() const
void setAltitude(RouteRestriction ty, double alt, RouteUnits units=DEFAULT_UNITS)
int cruiseSpeedKnots() const
void setCruiseSpeedMach(double mach)
int cruiseAltitudeM() const
std::string icaoAircraftCategory() const
void deleteIndex(int index)
Approach * approach() const
std::shared_ptr< DelegateFactory > DelegateFactoryRef
FGAirportRef departureAirport() const
int indexOfFirstNonDepartureWaypoint() const
int indexOfFirstApproachWaypoint() const
std::string remarks() const
int clearWayptsWithFlag(WayptFlag flag)
bool parseICAORouteString(const std::string &routeData)
attempt to replace the route waypoints (and potentially the SID and STAR) based on an ICAO standard r...
void setSID(SID *sid, const std::string &transition=std::string())
int indexOfFirstArrivalWaypoint() const
void insertWayptsAtIndex(const WayptVec &wps, int aIndex)
FlightPlanRef clone(const std::string &newIdent={}, bool convertToFlightPlan=false) const
void setCruiseSpeedKPH(int kmh)
static void unregisterDelegateFactory(DelegateFactoryRef df)
void setSTAR(STAR *star, const std::string &transition=std::string())
std::string callsign() const
bool isRoute() const
is this flight-pan a route (for planning) or an active flight-plan (which can be flown?...
static FlightPlanRef create()
create a FlightPlan with isRoute not set
void setEstimatedDurationMinutes(int minutes)
void setCruiseFlightLevel(int flightLevel)
void setDeparture(FGAirport *apt)
double totalDistanceNm() const
FGRunway * destinationRunway() const
std::string asICAORouteString() const
void setCruiseAltitudeFt(int altFt)
double cruiseSpeedMach() const
int cruiseSpeedKPH() const
LegRef insertWayptAtIndex(Waypt *aWpt, int aIndex)
FGRunway * departureRunway() const
void setRemarks(const std::string &remarks)
void setApproach(Approach *app, const std::string &transition={})
note setting an approach will implicitly update the destination airport and runway to match
int estimatedDurationMinutes() const
int cruiseFlightLevel() const
bool followLegTrackToFixes() const
void setDestination(FGAirport *apt)
void setCallsign(const std::string &callsign)
Transition * approachTransition() const
int cruiseAltitudeFt() const
virtual std::string ident() const
int findWayptIndex(const SGGeod &aPos) const
void setIdent(const std::string &s)
void setCurrentIndex(int index)
LegRef legAtIndex(int index) const
void setCruiseSpeedKnots(int kts)
void setFollowLegTrackToFixes(bool tf)
FGAirportRef destinationAirport() const
bool save(const SGPath &p) const
static void registerDelegateFactory(DelegateFactoryRef df)
Transition * sidTransition() const
SGGeod pointAlongRoute(int aIndex, double aOffsetNm) const
given a waypoint index, and an offset in NM, find the geodetic position on the route path.
void setIcaoAircraftCategory(const std::string &cat)
int indexOfDestinationRunwayWaypoint() const
void computeDurationMinutes()
computeDurationMinutes - use performance data and cruise data to estimate enroute time
static FlightPlanRef createRoute()
@factory to create a FlightPlan with isRoute=true
void setCruiseAltitudeM(int altM)
Transition * starTransition() const
Waypoint based upon a navaid.
virtual ProcedureType type() const =0
virtual RunwayVec runways() const
virtual std::string ident() const
virtual FGAirport * airport() const =0
virtual std::string ident() const =0
Waypoint based upon a runway.
Encapsulate a transition segment.
Abstract base class for waypoints (and things that are treated similarly by navigation systems).
virtual unsigned int flags() const
RouteBase * owner() const
virtual FGPositioned * source() const
The Positioned associated with this element, if one exists.
virtual std::string type() const =0
void setFlag(WayptFlag aFlag, bool aV=true)
virtual bool flag(WayptFlag aFlag) const
Test if the specified flag is set for this element.
virtual double headingRadialDeg() const
return the assoicated heading or radial for this waypoint.
virtual std::string ident() const
Identifier assoicated with the waypoint.
virtual SGGeod position() const =0
double constraintAltitude(RouteUnits aUnits=DEFAULT_UNITS) const
std::vector< std::string > string_list
FlightPlan.hxx - defines a full flight-plan object, including departure, cruise, arrival information ...
SGSharedPtr< FlightPlan > FlightPlanRef
SGSharedPtr< FGPositioned > FGPositionedRef
SGSharedPtr< Waypt > WayptRef
SGSharedPtr< Airway > AirwayRef
bool isMachRestrict(RouteRestriction rr)
@ WPT_PSEUDO
waypoint generated by VNAV / speed management profile, for step climbs or top of descent
@ WPT_MISS
segment is part of missed approach
@ WPT_HIDDEN
waypoint should not be shown in UI displays, etc this is used to implement FMSs which delete waypoint...
@ WPT_OVERFLIGHT
must overfly the point directly
std::vector< WayptRef > WayptVec
@ RESTRICT_DELETE
ignore underlying restriction (on a leg)
@ RESTRICT_COMPUTED
data is computed, not a real restriction
@ SPEED_COMPUTED_MACH
variant on above to encode a Mach value
@ SPEED_RESTRICT_MACH
encode an 'AT' restriction in Mach, not IAS
@ PROCEDURE_RUNWAY_TRANSITION
@ PROCEDURE_APPROACH_RNAV
T * fgpositioned_cast(FGPositioned *p)