28#include <simgear/sg_inlines.h>
29#include <simgear/scene/material/mat.hxx>
30#include <simgear/magvar/magvar.hxx>
31#include <simgear/timing/sg_time.hxx>
32#include <simgear/bucket/newbucket.hxx>
69static const char*
fixGhostGetMember(naContext c,
void* g, naRef field, naRef* out);
75static const char*
poiGhostGetMember(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()),
137 return (
FGFix*) naGhost_ptr(r);
153 return (
POI*)naGhost_ptr(r);
161 if (!FGPositioned::put(pos))
176 FGPositioned::get(apt);
186 FGPositioned::get(n);
196 FGPositioned::get(r);
206 FGPositioned::get(r);
216 FGPositioned::get(r);
226 FGPositioned::get(r);
236 FGPositioned::get(comm);
246 FGPositioned::get(r);
256 switch (pos->type()) {
288 SG_LOG(SG_NASAL, SG_DEV_ALERT,
"Type lacks Nasal ghost mapping:" << pos->typeString());
295 const char* fieldName = naStr_data(field);
298 if (!strcmp(fieldName,
"parents")) {
299 *out = naNewVector(c);
303 else if (!strcmp(fieldName,
"lat")) *out = naNum(apt->
getLatitude());
304 else if (!strcmp(fieldName,
"lon")) *out = naNum(apt->
getLongitude());
305 else if (!strcmp(fieldName,
"elevation")) {
307 }
else if (!strcmp(fieldName,
"has_metar")) {
309 }
else if (!strcmp(fieldName,
"runways")) {
311 double minLengthFt =
fgGetDouble(
"/sim/navdb/min-runway-length-ft");
312 for(
unsigned int r=0; r<apt->
numRunways(); ++r) {
315 if (rwy->
lengthFt() < minLengthFt) {
320 naHash_set(*out, rwyid, rwydata);
322 }
else if (!strcmp(fieldName,
"helipads")) {
330 naHash_set(*out, rwyid, rwydata);
333 }
else if (!strcmp(fieldName,
"taxiways")) {
334 *out = naNewVector(c);
338 naVec_append(*out, taxidata);
350 const char* fieldName = naStr_data(field);
354 else if (!strcmp(fieldName,
"lat")) *out = naNum(base->
latitude());
355 else if (!strcmp(fieldName,
"lon")) *out = naNum(base->
longitude());
356 else if (!strcmp(fieldName,
"heading")) *out = naNum(base->
headingDeg());
357 else if (!strcmp(fieldName,
"length")) *out = naNum(base->
lengthM());
358 else if (!strcmp(fieldName,
"width")) *out = naNum(base->
widthM());
359 else if (!strcmp(fieldName,
"surface")) *out = naNum(base->
surface());
360 else if (!strcmp(fieldName,
"airport"))
365 else if (!strcmp(fieldName,
"stopway")) *out = naNum(rwy->
stopwayM());
366 else if (!strcmp(fieldName,
"reciprocal")) {
368 }
else if (!strcmp(fieldName,
"ils_frequency_mhz")) {
369 *out = rwy->
ILS() ? naNum(rwy->
ILS()->
get_freq() / 100.0) : naNil();
370 }
else if (!strcmp(fieldName,
"ils")) {
384 const char* fieldName = naStr_data(field);
389 else if (!strcmp(fieldName,
"lat")) *out = naNum(nav->
get_lat());
390 else if (!strcmp(fieldName,
"lon")) *out = naNum(nav->
get_lon());
391 else if (!strcmp(fieldName,
"elevation")) {
392 *out = naNum(nav->
get_elev_ft() * SG_FEET_TO_METER);
393 }
else if (!strcmp(fieldName,
"type")) {
395 }
else if (!strcmp(fieldName,
"frequency")) {
397 }
else if (!strcmp(fieldName,
"range_nm")) {
399 }
else if (!strcmp(fieldName,
"magvar")) {
403 SG_NORMALIZE_RANGE(variation, 0.0, 360.0);
404 *out = naNum(variation);
408 }
else if (!strcmp(fieldName,
"colocated_dme")) {
415 }
else if (!strcmp(fieldName,
"dme")) {
416 *out = naNum(nav->
hasDME());
417 }
else if (!strcmp(fieldName,
"vortac")) {
419 }
else if (!strcmp(fieldName,
"course")) {
422 SG_NORMALIZE_RANGE(radial, 0.0, 360.0);
423 *out = naNum(radial);
427 }
else if (!strcmp(fieldName,
"guid")) {
428 *out = naNum(nav->
guid());
429 }
else if (!strcmp(fieldName,
"runway")) {
431 }
else if (!strcmp(fieldName,
"airport")) {
446 const char* fieldName = naStr_data(field);
450 else if (!strcmp(fieldName,
"lat")) *out = naNum(fix->
get_lat());
451 else if (!strcmp(fieldName,
"lon")) *out = naNum(fix->
get_lon());
453 else if (!strcmp(fieldName,
"type")) *out =
stringToNasal(c,
"fix");
455 else if (!strcmp(fieldName,
"guid"))
456 *out = naNum(fix->
guid());
466 const char* fieldName = naStr_data(field);
469 if (!strcmp(fieldName,
"id"))
471 else if (!strcmp(fieldName,
"lat"))
472 *out = naNum(comm->latitude());
473 else if (!strcmp(fieldName,
"lon"))
474 *out = naNum(comm->longitude());
475 else if (!strcmp(fieldName,
"airport"))
477 else if (!strcmp(fieldName,
"range_nm"))
478 *out = naNum(comm->rangeNm());
479 else if (!strcmp(fieldName,
"type")) {
481 }
else if (!strcmp(fieldName,
"name"))
483 else if (!strcmp(fieldName,
"frequency")) {
484 *out = naNum(comm->freqMHz());
485 }
else if (!strcmp(fieldName,
"guid")) {
486 *out = naNum(comm->guid());
496 const char* fieldName = naStr_data(field);
499 if (!strcmp(fieldName,
"parents")) {
500 *out = naNewVector(c);
502 }
else if (!strcmp(fieldName,
"id"))
504 else if (!strcmp(fieldName,
"lat"))
506 else if (!strcmp(fieldName,
"lon"))
508 else if (!strcmp(fieldName,
"type"))
510 else if (!strcmp(fieldName,
"name"))
512 else if (!strcmp(fieldName,
"guid"))
513 *out = naNum(wpt->
guid());
524 naRef parents = naHash_cget(h, (
char*)
"parents");
525 if (!naIsVector(parents)) {
534 if (!naIsHash(ref)) {
540 naRef lat = naHash_cget(ref, (
char*)
"lat");
541 naRef lon = naHash_cget(ref, (
char*)
"lon");
542 if (naIsNum(lat) && naIsNum(lon)) {
543 result = SGGeod::fromDeg(naNumValue(lon).num, naNumValue(lat).num);
549 naRef polarDirtyFlag = naHash_cget(ref, (
char*)
"_pdirty");
550 naRef cartesianDirtyFlag = naHash_cget(ref, (
char*)
"_cdirty");
552 if (naNumValue(polarDirtyFlag).num == 0) {
554 naRef lat = naHash_cget(ref, (
char*)
"_lat");
555 naRef lon = naHash_cget(ref, (
char*)
"_lon");
556 naRef alt_feet = naHash_cget(ref, (
char*)
"_alt");
558 if (naIsNum(lat) && naIsNum(lon) && naIsNil(alt_feet)) {
559 result = SGGeod::fromRad(naNumValue(lon).num, naNumValue(lat).num);
563 if (naIsNum(lat) && naIsNum(lon) && naIsNum(alt_feet)) {
564 result = SGGeod::fromRadFt(naNumValue(lon).num, naNumValue(lat).num, naNumValue(alt_feet).num);
567 }
else if (naNumValue(cartesianDirtyFlag).num == 0) {
569 naRef x = naHash_cget(ref, (
char*)
"_x");
570 naRef y = naHash_cget(ref, (
char*)
"_y");
571 naRef z = naHash_cget(ref, (
char*)
"_z");
573 if (naIsNum(x) && naIsNum(y) && naIsNum(z)) {
574 result = SGGeod::fromCart(SGVec3d{naNumValue(x).num,
575 naNumValue(y).num, naNumValue(z).num});
579 SG_LOG(SG_NASAL, SG_DEV_ALERT,
"geo.Coord() instance has invalid coordinates");
590 if (offset >= argc || !args) {
594 if (naIsGhost(args[offset])) {
595 naGhostType* gt = naGhost_type(args[offset]);
628 result = wp->position();
634 result = leg->waypoint()->position();
643 if (((argc - offset) >= 2) && naIsNum(args[offset]) && naIsNum(args[offset + 1])) {
644 double lat = naNumValue(args[0]).num,
645 lon = naNumValue(args[1]).num;
646 result = SGGeod::fromDeg(lon, lat);
655 if (!naIsHash(ref)) {
660 naRef x = naHash_cget(ref, (
char*)
"x");
661 naRef y = naHash_cget(ref, (
char*)
"y");
662 naRef z = naHash_cget(ref, (
char*)
"z");
663 if (naIsNum(x) && naIsNum(y) && naIsNum(z)) {
664 result = SGVec3d(naNumValue(x).num, naNumValue(y).num, naNumValue(z).num);
673 double lat, lon, alt, xyz[3];
674 if(argc != 3) naRuntimeError(c,
"carttogeod() expects 3 arguments");
675 for(
int i=0;
i<3;
i++)
676 xyz[
i] = naNumValue(args[
i]).num;
677 sgCartToGeod(xyz, &lat, &lon, &alt);
678 lat *= SG_RADIANS_TO_DEGREES;
679 lon *= SG_RADIANS_TO_DEGREES;
680 naRef vec = naNewVector(c);
681 naVec_append(vec, naNum(lat));
682 naVec_append(vec, naNum(lon));
683 naVec_append(vec, naNum(alt));
690 if(argc != 3) naRuntimeError(c,
"geodtocart() expects 3 arguments");
691 double lat = naNumValue(args[0]).num * SG_DEGREES_TO_RADIANS;
692 double lon = naNumValue(args[1]).num * SG_DEGREES_TO_RADIANS;
693 double alt = naNumValue(args[2]).num;
695 sgGeodToCart(lat, lon, alt, xyz);
696 naRef vec = naNewVector(c);
697 naVec_append(vec, naNum(xyz[0]));
698 naVec_append(vec, naNum(xyz[1]));
699 naVec_append(vec, naNum(xyz[2]));
746 naRuntimeError(c,
"geod_hash get_cart_ground_intersection(position: hash{x,y,z}, direction:hash{x,y,z}) expects 2 arguments");
749 naRuntimeError(c,
"geod_hash get_cart_ground_intersection(position:hash{x,y,z}, direction:hash{x,y,z}) expects argument(0) to be hash of position containing x,y,z");
752 naRuntimeError(c,
"geod_hash get_cart_ground_intersection(position: hash{x,y,z}, direction:hash{x,y,z}) expects argument(1) to be hash of direction containing x,y,z");
755 if (!
globals->get_scenery()->get_cart_ground_intersection(pos, dir, nearestHit))
758 const SGGeod geodHit = SGGeod::fromCart(nearestHit);
761 naRef intersection_h = naNewHash(c);
762 hashset(c, intersection_h,
"lat", naNum(geodHit.getLatitudeDeg()));
763 hashset(c, intersection_h,
"lon", naNum(geodHit.getLongitudeDeg()));
764 hashset(c, intersection_h,
"elevation", naNum(geodHit.getElevationM()));
765 return intersection_h;
772 naRuntimeError(c,
"hash{x,y,z} aircraftToCart(position: hash{x,y,z}) expects one argument");
776 naRuntimeError(c,
"aircraftToCart expects argument(0) to be a hash containing x,y,z");
778 double heading, pitch, roll;
779 globals->get_aircraft_orientation(heading, pitch, roll);
782 SGQuatd hlTrans = SGQuatd::fromLonLat(
globals->get_aircraft_position());
785 hlTrans *= SGQuatd::fromYawPitchRollDeg(heading, pitch, roll);
789 offset = hlTrans.backTransform(offset);
791 SGVec3d v =
globals->get_aircraft_position_cart() + offset;
794 naRef pos_h = naNewHash(c);
795 hashset(c, pos_h,
"x", naNum(v.x()));
796 hashset(c, pos_h,
"y", naNum(v.y()));
797 hashset(c, pos_h,
"z", naNum(v.z()));
805static naRef
f_geodinfo(naContext c, naRef me,
int argc, naRef* args)
807#define HASHSET(s,l,n) naHash_set(matdata, naStr_fromdata(naNewString(c),s,l),n)
808 if(argc < 2 || argc > 3)
809 naRuntimeError(c,
"geodinfo() expects 2 or 3 arguments: lat, lon [, maxalt]");
810 double lat = naNumValue(args[0]).num;
811 double lon = naNumValue(args[1]).num;
812 double elev = argc == 3 ? naNumValue(args[2]).num : 10000;
813 const simgear::BVHMaterial *material;
814 SGGeod geod = SGGeod::fromDegM(lon, lat, elev);
819 const auto scenery =
globals->get_scenery();
820 if (scenery ==
nullptr)
823 if(!scenery->get_elevation_m(geod, elev, &material)) {
827 naRef vec = naNewVector(c);
828 naVec_append(vec, naNum(elev));
830 naRef matdata = naNil();
832 const SGMaterial *mat =
dynamic_cast<const SGMaterial *
>(material);
834 matdata = naNewHash(c);
835 naRef names = naNewVector(c);
836 for (
const std::string& n : mat->get_names())
841 HASHSET(
"solid", 5, naNum(mat->get_solid()));
842 HASHSET(
"friction_factor", 15, naNum(mat->get_friction_factor()));
843 HASHSET(
"rolling_friction", 16, naNum(mat->get_rolling_friction()));
844 HASHSET(
"load_resistance", 15, naNum(mat->get_load_resistance()));
845 HASHSET(
"bumpiness", 9, naNum(mat->get_bumpiness()));
846 HASHSET(
"light_coverage", 14, naNum(mat->get_light_coverage()));
847 }
else if (material) {
848 matdata = naNewHash(c);
849 naRef names = naNewVector(c);
854 HASHSET(
"solid", 5, naNum(material->get_solid()));
855 HASHSET(
"friction_factor", 15, naNum(material->get_friction_factor()));
856 HASHSET(
"rolling_friction", 16, naNum(material->get_rolling_friction()));
857 HASHSET(
"load_resistance", 15, naNum(material->get_load_resistance()));
858 HASHSET(
"bumpiness", 9, naNum(material->get_bumpiness()));
861 naVec_append(vec, matdata);
876 SGGeod pos =
globals->get_aircraft_position();
879 if(argc >= 2 && naIsNum(args[0]) && naIsNum(args[1])) {
880 pos = SGGeod::fromDeg(args[1].num, args[0].num);
885 double maxRange = 10000.0;
891 }
else if(argc == 1 && naIsString(args[0])) {
905 naRuntimeError(c,
"airportinfo() with invalid function arguments");
911 if(!apt)
return naNil();
920 SGGeod pos =
globals->get_aircraft_position();
923 if (!naIsNum(args[argOffset])) {
924 naRuntimeError(c,
"findAirportsWithinRange expected range (in nm) as arg %d", argOffset);
928 double rangeNm = args[argOffset++].num;
929 if (argOffset < argc) {
933 naRef r = naNewVector(c);
947 if (!naIsString(args[0])) {
948 naRuntimeError(c,
"findAirportsByICAO expects string as arg 0");
952 std::string prefix(naStr_data(args[argOffset++]));
954 if (argOffset < argc) {
958 naRef r = naNewVector(c);
972 naRuntimeError(c,
"airport.tower called on non-airport object");
977 naRef tower = naNewHash(c);
978 hashset(c, tower,
"lat", naNum(towerLoc.getLatitudeDeg()));
979 hashset(c, tower,
"lon", naNum(towerLoc.getLongitudeDeg()));
980 hashset(c, tower,
"elevation", naNum(towerLoc.getElevationM()));
988 naRuntimeError(c,
"airport.comms called on non-airport object");
990 naRef comms = naNewVector(c);
993 if (argc > 0 && !naIsString(args[0])) {
994 naRuntimeError(c,
"airport.comms argument must be a frequency type name");
998 std::string commName = naStr_data(args[0]);
1002 naVec_append(comms, naNum(comm->freqMHz()));
1007 naRef commHash = naNewHash(c);
1008 hashset(c, commHash,
"frequency", naNum(comm->freqMHz()));
1010 naVec_append(comms, commHash);
1021 naRuntimeError(c,
"airport.runway called on non-airport object");
1024 if ((argc < 1) || !naIsString(args[0])) {
1025 naRuntimeError(c,
"airport.runway expects a runway ident argument");
1028 std::string ident = simgear::strutils::uppercase(naStr_data(args[0]));
1042 naRuntimeError(c,
"airport.runwaysWithoutReciprocals called on non-airport object");
1046 naRef runways = naNewVector(c);
1047 for (
unsigned int r=0; r<rwylist.size(); ++r) {
1058 naRuntimeError(c,
"airport.sids called on non-airport object");
1061 naRef sids = naNewVector(c);
1064 if (argc > 0 && naIsString(args[0])) {
1070 }
else if (argc > 0) {
1075 for (
auto sid : rwy->
getSIDs()) {
1077 naVec_append(sids, procId);
1080 for (
unsigned int s=0; s<apt->
numSIDs(); ++s) {
1083 naVec_append(sids, procId);
1094 naRuntimeError(c,
"airport.stars called on non-airport object");
1097 naRef stars = naNewVector(c);
1100 if (argc > 0 && naIsString(args[0])) {
1106 }
else if (argc > 0) {
1113 naVec_append(stars, procId);
1116 for (
unsigned int s=0; s<apt->
numSTARs(); ++s) {
1119 naVec_append(stars, procId);
1130 naRuntimeError(c,
"airport.getApproachList called on non-airport object");
1133 naRef approaches = naNewVector(c);
1136 if ((argc > 1) && naIsString(args[1])) {
1137 std::string u = simgear::strutils::uppercase(naStr_data(args[1]));
1145 STAR* star =
nullptr;
1152 star =
static_cast<STAR*
>(proc);
1153 }
else if (argc > 0 && naIsString(args[0])) {
1168 naVec_append(approaches, procId);
1171 std::set<std::string> appIds;
1172 for (
auto rwy : star->
runways()) {
1174 appIds.insert(app->ident());
1178 for (
auto s : appIds) {
1194 naVec_append(approaches, procId);
1205 naRuntimeError(c,
"airport.parking called on non-airport object");
1208 naRef r = naNewVector(c);
1210 bool onlyAvailable =
false;
1212 if (argc > 0 && naIsString(args[0])) {
1213 type = naStr_data(args[0]);
1216 if ((argc > 1) && naIsNum(args[1])) {
1217 onlyAvailable = (args[1].num != 0.0);
1221 FGParkingList parkings = dynamics->getParkings(onlyAvailable, type);
1222 FGParkingList::const_iterator it;
1223 for (it = parkings.begin(); it != parkings.end(); ++it) {
1225 const SGGeod& parkLoc = park->geod();
1226 naRef ph = naNewHash(c);
1228 hashset(c, ph,
"lat", naNum(parkLoc.getLatitudeDeg()));
1229 hashset(c, ph,
"lon", naNum(parkLoc.getLongitudeDeg()));
1230 hashset(c, ph,
"elevation", naNum(parkLoc.getElevationM()));
1231 naVec_append(r, ph);
1241 naRuntimeError(c,
"airport.getSid called on non-airport object");
1244 if ((argc != 1) || !naIsString(args[0])) {
1245 naRuntimeError(c,
"airport.getSid passed invalid argument");
1248 std::string ident = naStr_data(args[0]);
1256 naRuntimeError(c,
"airport.getStar called on non-airport object");
1259 if ((argc != 1) || !naIsString(args[0])) {
1260 naRuntimeError(c,
"airport.getStar passed invalid argument");
1263 std::string ident = naStr_data(args[0]);
1271 naRuntimeError(c,
"airport.getIAP called on non-airport object");
1274 if ((argc != 1) || !naIsString(args[0])) {
1275 naRuntimeError(c,
"airport.getIAP passed invalid argument");
1278 std::string ident = naStr_data(args[0]);
1286 naRuntimeError(c,
"findBestRunway called on non-airport object");
1291 naRuntimeError(c,
"findBestRunway must be passed a position");
1301 naRuntimeError(c,
"airport.tostring called on non-airport object");
1319static naRef
f_navinfo(naContext c, naRef me,
int argc, naRef* args)
1323 if(argc >= 2 && naIsNum(args[0]) && naIsNum(args[1])) {
1324 pos = SGGeod::fromDeg(args[1].num, args[0].num);
1328 pos =
globals->get_aircraft_position();
1333 const char *
id =
"";
1335 if(argc > 0 && naIsString(args[0])) {
1336 const char *s = naStr_data(args[0]);
1349 if(argc > 0 && naIsString(args[0])) {
1351 naRuntimeError(c,
"navinfo() called with navaid id");
1354 id = naStr_data(args[0]);
1360 naRuntimeError(c,
"navinfo() called with too many arguments");
1367 naRef reply = naNewVector(c);
1368 for( nav_list_type::const_iterator it = navlist.begin(); it != navlist.end(); ++it ) {
1377 SGGeod pos =
globals->get_aircraft_position();
1380 if (!naIsNum(args[argOffset])) {
1381 naRuntimeError(c,
"findNavaidsWithinRange expected range (in nm) as arg %d", argOffset);
1385 double rangeNm = args[argOffset++].num;
1386 if (argOffset < argc) {
1390 naRef r = naNewVector(c);
1406 SGGeod pos =
globals->get_aircraft_position();
1409 if (!naIsNum(args[argOffset])) {
1410 naRuntimeError(c,
"findNDBByFrquency expectes frequency (in kHz) as arg %d", argOffset);
1413 double dbFreq = args[argOffset++].num;
1426 SGGeod pos =
globals->get_aircraft_position();
1429 if (!naIsNum(args[argOffset])) {
1430 naRuntimeError(c,
"findNDBsByFrquency expectes frequency (in kHz) as arg %d", argOffset);
1433 double dbFreq = args[argOffset++].num;
1440 naRef r = naNewVector(c);
1450 SGGeod pos =
globals->get_aircraft_position();
1453 if (!naIsNum(args[argOffset])) {
1454 naRuntimeError(c,
"findNavaidByFrequency expectes frequency (in Mhz) as arg %d", argOffset);
1458 double freqMhz = args[argOffset++].num;
1459 if (argOffset < argc) {
1462 naRuntimeError(c,
"Use findNDBByFrquency to seach NDBs");
1478 SGGeod pos =
globals->get_aircraft_position();
1481 if (!naIsNum(args[argOffset])) {
1482 naRuntimeError(c,
"findNavaidsByFrequency expectes frequency (in Mhz) as arg %d", argOffset);
1486 double freqMhz = args[argOffset++].num;
1487 if (argOffset < argc) {
1490 naRuntimeError(c,
"Use findNDBsByFrquency to seach NDBs");
1494 naRef r = naNewVector(c);
1497 for (
auto a : navs) {
1507 SGGeod pos =
globals->get_aircraft_position();
1510 if (!naIsNum(args[argOffset])) {
1511 naRuntimeError(c,
"findCommByFrequencyMhz expectes frequency (in Mhz) as arg %d", argOffset);
1516 double freqMhz = args[argOffset++].num;
1517 if (argOffset < argc) {
1534 SGGeod pos =
globals->get_aircraft_position();
1537 if (!naIsNum(args[argOffset])) {
1538 naRuntimeError(c,
"f_findCommsByFrequency expectes frequency (in Mhz) as arg %d", argOffset);
1542 double freqMhz = args[argOffset++].num;
1543 if (argOffset < argc) {
1548 naRef r = naNewVector(c);
1550 for (
auto id : stations) {
1561 SGGeod pos =
globals->get_aircraft_position();
1564 if (!naIsString(args[argOffset])) {
1565 naRuntimeError(c,
"findNavaidsByIdent expectes ident string as arg %d", argOffset);
1569 std::string ident = naStr_data(args[argOffset++]);
1570 if (argOffset < argc) {
1575 naRef r = naNewVector(c);
1588 SGGeod pos =
globals->get_aircraft_position();
1591 if (!naIsString(args[argOffset])) {
1592 naRuntimeError(c,
"findFixesByIdent expectes ident string as arg %d", argOffset);
1595 std::string ident(naStr_data(args[argOffset]));
1596 naRef r = naNewVector(c);
1611 if ((argc < 2) || !naIsString(args[0]) || !naIsString(args[1]) ) {
1612 naRuntimeError(c,
"finxByIdent: expects ident and type as first two args");
1615 std::string ident(naStr_data(args[0]));
1616 std::string typeSpec(naStr_data(args[1]));
1619 SGGeod pos =
globals->get_aircraft_position();
1623 naRef r = naNewVector(c);
1628 for (
auto f : matches) {
1637static naRef
f_magvar(naContext c, naRef me,
int argc, naRef* args)
1639 SGGeod pos =
globals->get_aircraft_position();
1645 naRuntimeError(c,
"magvar() expects no arguments, a positioned hash or lat,lon pair");
1648 double jd =
globals->get_time_params()->getJD();
1649 double magvarDeg = sgGetMagVar(pos, jd) * SG_RADIANS_TO_DEGREES;
1650 return naNum(magvarDeg);
1655 SGGeod from =
globals->get_aircraft_position(), to,
p;
1663 if (argOffset == 0) {
1664 naRuntimeError(c,
"invalid arguments to courseAndDistance");
1667 double course, course2, d;
1668 SGGeodesy::inverse(from, to, course, course2, d);
1670 naRef result = naNewVector(c);
1671 naVec_append(result, naNum(course));
1672 naVec_append(result, naNum(d * SG_METER_TO_NM));
1680 if (argOffset == 0) {
1681 naRuntimeError(c,
"invalid arguments to formatLatLon, expect a geod or lat,lon");
1684 simgear::strutils::LatLonFormat format =
1685 static_cast<simgear::strutils::LatLonFormat
>(
fgGetInt(
"/sim/lon-lat-format"));
1686 if (argOffset < argc && naIsNum(args[argOffset])) {
1687 format =
static_cast<simgear::strutils::LatLonFormat
>((int) args[argOffset].num);
1688 if (format > simgear::strutils::LatLonFormat::DECIMAL_DEGREES_SYMBOL) {
1689 naRuntimeError(c,
"invalid lat-lon format requested");
1693 const auto s = simgear::strutils::formatGeodAsString(
p, format);
1699 if ((argc < 1) || !naIsString(args[0])) {
1700 naRuntimeError(c,
"Missing / bad argument to parseStringAsLatLonValue");
1704 bool ok = simgear::strutils::parseStringAsLatLonValue(naStr_data(args[0]), value);
1709 return naNum(value);
1715 SGGeod from =
globals->get_aircraft_position(), to;
1724 if ((argOffset + 1) >= argc) {
1725 naRuntimeError(c,
"isufficent arguments to greatCircleMove");
1728 if (!naIsNum(args[argOffset]) || !naIsNum(args[argOffset+1])) {
1729 naRuntimeError(c,
"invalid arguments %d and %d to greatCircleMove",
1730 argOffset, argOffset + 1);
1733 double course = args[argOffset].num, course2;
1734 double distanceNm = args[argOffset + 1].num;
1735 SGGeodesy::direct(from, course, distanceNm * SG_NM_TO_METER, to, course2);
1738 naRef coord = naNewHash(c);
1739 hashset(c, coord,
"lat", naNum(to.getLatitudeDeg()));
1740 hashset(c, coord,
"lon", naNum(to.getLongitudeDeg()));
1744static naRef
f_tilePath(naContext c, naRef me,
int argc, naRef* args)
1746 SGGeod pos =
globals->get_aircraft_position();
1754 SGGeod pos =
globals->get_aircraft_position();
1757 return naNum(b.gen_index());
1762 if ((argc < 3) || !naIsString(args[0]) || !naIsString(args[1])) {
1763 naRuntimeError(c,
"createWaypoint: expects type and ident as first two args");
1766 std::string typeSpec(naStr_data(args[0]));
1767 std::string ident(naStr_data(args[1]));
1774 if ((argc > argOffset) && naIsString(args[argOffset])) {
1775 name = naStr_data(args[argOffset]);
1779 bool isTemporary =
false;
1780 if ((argc > argOffset) && naIsNum(args[argOffset])) {
1781 isTemporary = (args[argOffset].num > 0);
1792 }
catch (std::exception& e) {
1793 naRuntimeError(c,
"Failed to create waypoint: %s", e.what());
1803 naRuntimeError(c,
"deleteWaypoint: missing argument");
1807 if (!wpt && naIsNum(args[0])) {
1811 naRuntimeError(c,
"deleteWaypoint: only waypoints can be deleted for now");
1824 naRuntimeError(c,
"waypoint.move called on non-POI object");
1840 if (!naIsGhost(ref))
1843 naGhostType* gt = naGhost_type(ref);
1861 return wpg->source();
1942 naRef geoModule = naHash_cget(
globals, (
char*)
"geo");
1943 if (naIsNil(geoModule)) {
1944 SG_LOG(SG_GENERAL, SG_WARN,
"postinitNasalPositioned: geo.nas not loaded");
static struct @032150236342374176343243244364035346052374146336 funcs[]
FlightPlan::Leg * fpLegGhost(naRef r)
naRef ghostForProcedure(naContext c, const Procedure *proc)
Procedure * procedureGhost(naRef r)
Waypt * wayptGhost(naRef r)
static naRef f_findNavaidsByIdent(naContext c, naRef me, int argc, naRef *args)
static const char * poiGhostGetMember(naContext c, void *g, naRef field, naRef *out)
static naRef f_airport_getStar(naContext c, naRef me, int argc, naRef *args)
bool vec3dFromHash(naRef ref, SGVec3d &result)
naRef ghostForNavaid(naContext c, const FGNavRecord *n)
static naRef stringToNasal(naContext c, const std::string &s)
bool geodFromHash(naRef ref, SGGeod &result)
static naRef f_airport_parking(naContext c, naRef me, int argc, naRef *args)
static const char * navaidGhostGetMember(naContext c, void *g, naRef field, naRef *out)
static naRef f_parseStringAsLatLonValue(naContext c, naRef me, int argc, naRef *args)
static naRef f_airport_runway(naContext c, naRef me, int argc, naRef *args)
static naRef f_airport_runwaysWithoutReciprocals(naContext c, naRef me, int argc, naRef *args)
static naRef f_airport_sids(naContext c, naRef me, int argc, naRef *args)
static naGhostType TaxiwayGhostType
static naGhostType CommGhostType
static void hashset(naContext c, naRef hash, const char *key, naRef val)
static naGhostType FixGhostType
static naRef f_navinfo(naContext c, naRef me, int argc, naRef *args)
FGAirport * airportGhost(naRef r)
static FGFix * fixGhost(naRef r)
static naRef f_findNDBByFrequency(naContext c, naRef me, int argc, naRef *args)
static naGhostType RunwayGhostType
static POI * poiGhost(naRef r)
static naRef f_greatCircleMove(naContext c, naRef me, int argc, naRef *args)
static const char * airportGhostGetMember(naContext c, void *g, naRef field, naRef *out)
static naGhostType PositionedGhostType = { positionedGhostDestroy, "positioned", nullptr,...
naRef ghostForPOI(naContext c, const POI *r)
static naRef f_findNDBsByFrequency(naContext c, naRef me, int argc, naRef *args)
static naRef f_geodinfo(naContext c, naRef me, int argc, naRef *args)
static naRef f_airport_stars(naContext c, naRef me, int argc, naRef *args)
static naRef airportPrototype
static naRef f_findNavaidByFrequency(naContext c, naRef me, int argc, naRef *args)
static naRef f_get_cart_ground_intersection(naContext c, naRef me, int argc, naRef *args)
static naRef f_magvar(naContext c, naRef me, int argc, naRef *args)
static naRef f_tileIndex(naContext c, naRef me, int argc, naRef *args)
naRef ghostForHelipad(naContext c, const FGHelipad *r)
static naGhostType POIGhostType
static void positionedGhostDestroy(void *g)
static naRef f_formatLatLon(naContext c, naRef me, int argc, naRef *args)
static naRef f_findAirportsWithinRange(naContext c, naRef me, int argc, naRef *args)
FGRunway * runwayGhost(naRef r)
static naRef f_findNavaidsByFrequency(naContext c, naRef me, int argc, naRef *args)
static naRef f_airport_getApproach(naContext c, naRef me, int argc, naRef *args)
static naGhostType HelipadGhostType
static FGTaxiway * taxiwayGhost(naRef r)
static const char * fixGhostGetMember(naContext c, void *g, naRef field, naRef *out)
naRef ghostForRunway(naContext c, const FGRunway *r)
int geodFromArgs(naRef *args, int offset, int argc, SGGeod &result)
naRef ghostForFix(naContext c, const FGFix *r)
static naRef f_courseAndDistance(naContext c, naRef me, int argc, naRef *args)
static const char * commGhostGetMember(naContext c, void *g, naRef field, naRef *out)
static bool hashIsCoord(naRef h)
naRef ghostForComm(naContext c, const flightgear::CommStation *comm)
static naRef f_findNavaidsWithinRange(naContext c, naRef me, int argc, naRef *args)
static naRef f_waypoint_move(naContext c, naRef me, int argc, naRef *args)
static naRef f_createWaypoint(naContext c, naRef me, int argc, naRef *args)
static naRef f_airport_comms(naContext c, naRef me, int argc, naRef *args)
static naRef f_findCommsByFrequency(naContext c, naRef me, int argc, naRef *args)
static naRef f_airport_findBestRunway(naContext c, naRef me, int argc, naRef *args)
static naRef f_airport_toString(naContext c, naRef me, int argc, naRef *args)
static naRef f_findAirportsByICAO(naContext c, naRef me, int argc, naRef *args)
static naRef f_carttogeod(naContext c, naRef me, int argc, naRef *args)
static naRef f_findByIdent(naContext c, naRef me, int argc, naRef *args)
static naGhostType AirportGhostType
FGPositionedRef positionedFromArg(naRef ref)
static naRef f_airport_getSid(naContext c, naRef me, int argc, naRef *args)
naRef ghostForPositioned(naContext c, FGPositionedRef pos)
static naGhostType NavaidGhostType
static naRef waypointPrototype
static naRef f_tilePath(naContext c, naRef me, int argc, naRef *args)
void shutdownNasalPositioned()
FGPositioned * positionedGhost(naRef r)
static naRef f_aircraftToCart(naContext c, naRef me, int argc, naRef *args)
static naRef f_airportinfo(naContext c, naRef me, int argc, naRef *args)
static naRef f_findFixesByIdent(naContext c, naRef me, int argc, naRef *args)
static naRef f_deleteWaypoint(naContext c, naRef me, int argc, naRef *args)
static naRef geoCoordClass
static naRef f_airport_tower(naContext c, naRef me, int argc, naRef *args)
static naRef f_geodtocart(naContext c, naRef me, int argc, naRef *args)
static naRef f_airport_approaches(naContext c, naRef me, int argc, naRef *args)
naRef ghostForTaxiway(naContext c, const FGTaxiway *r)
static const char * runwayGhostGetMember(naContext c, void *g, naRef field, naRef *out)
naRef initNasalPositioned(naRef globals, naContext c)
static naRef f_findCommByFrequency(naContext c, naRef me, int argc, naRef *args)
naRef ghostForAirport(naContext c, const FGAirport *apt)
static FGNavRecord * navaidGhost(naRef r)
void postinitNasalPositioned(naRef globals, naContext c)
SGSharedPtr< FGAirportDynamics > FGAirportDynamicsRef
std::vector< FGRunwayRef > FGRunwayList
std::vector< FGParkingRef > FGParkingList
SGSharedPtr< FGParking > FGParkingRef
Filter which passes specified port type and in case of airport checks if a runway larger the /sim/nav...
bool fromTypeString(const std::string &type)
Construct from string containing type (airport, seaport or heliport)
FGAirportDynamicsRef getDynamics() const
unsigned int numRunways() const
flightgear::STAR * getSTARByIndex(unsigned int aIndex) const
FGHelipadRef getHelipadByIndex(unsigned int aIndex) const
FGRunwayRef findBestRunwayForPos(const SGGeod &aPos) const
return the most likely target runway based on a position.
unsigned int numApproaches() const
unsigned int numSIDs() const
unsigned int numTaxiways() const
FGRunwayRef getRunwayByIndex(unsigned int aIndex) const
FGRunwayList getRunwaysWithoutReciprocals() const
Retrieve all runways at the airport, but excluding the reciprocal runways.
double getElevation() const
double getLatitude() const
double getLongitude() const
FGRunwayRef getRunwayByIdent(const std::string &aIdent) const
flightgear::CommStationList commStationsOfType(FGPositioned::Type aTy) const
static FGAirportRef findClosest(const SGGeod &aPos, double aCuttofNm, Filter *filter=NULL)
Syntactic wrapper around FGPositioned::findClosest - find the closest match for filter,...
flightgear::Approach * getApproachByIndex(unsigned int aIndex) const
unsigned int numHelipads() const
static FGAirportRef findByIdent(const std::string &aIdent)
Helper to look up an FGAirport instance by unique ident.
flightgear::STAR * findSTARWithIdent(const std::string &aIdent) const
bool hasHelipadWithIdent(const std::string &aIdent) const
virtual const std::string & name() const
Return the name of this positioned.
bool hasRunwayWithIdent(const std::string &aIdent) const
FGTaxiwayRef getTaxiwayByIndex(unsigned int aIndex) const
flightgear::CommStationList commStations() const
SGGeod getTowerLocation() const
flightgear::Approach * findApproachWithIdent(const std::string &aIdent) const
flightgear::SID * findSIDWithIdent(const std::string &aIdent) const
FGHelipadRef getHelipadByIdent(const std::string &aIdent) const
unsigned int numSTARs() const
flightgear::SID * getSIDByIndex(unsigned int aIndex) const
static nav_list_type findAllByFreq(double freq, const SGGeod &position, TypeFilter *filter=NULL)
static nav_list_type findByIdentAndFreq(const std::string &ident, const double freq, TypeFilter *filter=NULL)
double get_elev_ft() const
virtual const std::string & name() const
Return the name of this positioned.
double get_multiuse() const
PositionedID colocatedDME() const
FGRunwayRef runway() const
Retrieve the runway this navaid is associated with (for ILS/LOC/GS)
static TypeFilter fromString(const std::string &aFilterSpec)
static Type typeFromName(const std::string &aName)
Map a candidate type string to a real type.
static FGPositionedRef createWaypoint(FGPositioned::Type aType, const std::string &aIdent, const SGGeod &aPos, bool isTemporary=false, const std::string &aName={})
PositionedID guid() const
static FGPositionedList findWithinRange(const SGGeod &aPos, double aRangeNm, Filter *aFilter)
virtual const SGGeod & geod() const
static void sortByRange(FGPositionedList &, const SGGeod &aPos)
Sort an FGPositionedList by distance from a position.
static SGSharedPtr< T > loadById(PositionedID id)
@ DME
important that DME & TACAN are adjacent to keep the TacanFilter efficient - DMEs are proxies for TACA...
static FGPositionedList findAllWithIdent(const std::string &aIdent, Filter *aFilter=NULL, bool aExact=true)
Find all items with the specified ident.
static const char * nameForType(Type aTy)
Map a type to a human-readable string.
const std::string & ident() const
static bool deleteWaypoint(FGPositionedRef aWpt)
double headingDeg() const
Runway heading in degrees.
int surface() const
Retrieve runway surface code, as define in Robin Peel's data.
FGAirportRef airport() const
flightgear::STARList getSTARs() const
Get STARs associared with this runway.
FGNavRecord * ILS() const
FGRunway * reciprocalRunway() const
flightgear::SIDList getSIDs() const
Get SIDs (DPs) associated with this runway.
flightgear::ApproachList getApproaches(flightgear::ProcedureType type=flightgear::PROCEDURE_INVALID) const
double displacedThresholdM() const
static bool isType(FGPositioned::Type ty)
const std::string & name() const override
Return the name of this positioned.
Describe an approach procedure, including the missed approach segment.
virtual ProcedureType type() const
virtual RunwayVec runways() const
FGPositionedRef findCommByFreq(int freqKhz, const SGGeod &pos, FGPositioned::Filter *filt)
Find the closest matching comm-station on a frequency, to a position.
PositionedIDVec findCommsByFreq(int freqKhz, const SGGeod &pos, FGPositioned::Filter *filt)
Find all on a frequency, sorted by distance from a position The filter with be used for both type ran...
void updatePosition(PositionedID item, const SGGeod &pos)
Modify the position of an existing item.
FGPositionedRef loadById(PositionedID guid)
retrieve an FGPositioned from the cache.
static NavDataCache * instance()
virtual ProcedureType type() const =0
virtual std::string ident() const
std::vector< FGRunwayRef > RunwayVec
int fgGetInt(const char *name, int defaultValue)
Get an int value for a property.
FlightPlan.hxx - defines a full flight-plan object, including departure, cruise, arrival information ...
SGSharedPtr< FGPositioned > FGPositionedRef
@ PROCEDURE_APPROACH_RNAV
SGSharedPtr< FGNavRecord > FGNavRecordRef
std::vector< nav_rec_ptr > nav_list_type
SGSharedPtr< FGNavRecord > nav_rec_ptr
T * fgpositioned_cast(FGPositioned *p)
std::vector< FGPositionedRef > FGPositionedList
double fgGetDouble(const char *name, double defaultValue)
Get a double value for a property.