X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FScripting%2FNasalPositioned_cppbind.cxx;h=cc3568c4b67f8ee16984e675774f12ea3b15da28;hb=881df711ba5be8a8c0bc65f2126a0dcb63865df9;hp=aeede726b87a8ebc5194890e2b3b303b4e6a5797;hpb=22a1c9b2af9fd6c4c2758d095c3004da28e83b85;p=flightgear.git diff --git a/src/Scripting/NasalPositioned_cppbind.cxx b/src/Scripting/NasalPositioned_cppbind.cxx index aeede726b..cc3568c4b 100644 --- a/src/Scripting/NasalPositioned_cppbind.cxx +++ b/src/Scripting/NasalPositioned_cppbind.cxx @@ -38,39 +38,22 @@ #include #include +#include #include #include
#include +#include +#include +#include typedef nasal::Ghost NasalPositioned; typedef nasal::Ghost NasalRunway; typedef nasal::Ghost NasalParking; typedef nasal::Ghost NasalAirport; typedef nasal::Ghost NasalCommStation; - -//------------------------------------------------------------------------------ -naRef to_nasal_helper(naContext c, FGPositioned* positioned) -{ - return NasalPositioned::create(c, positioned); -} - -//------------------------------------------------------------------------------ -naRef to_nasal_helper(naContext c, FGPavement* rwy) -{ - return NasalPositioned::create(c, (FGPositioned*)rwy); -} - -//------------------------------------------------------------------------------ -naRef to_nasal_helper(naContext c, FGRunwayBase* rwy) -{ - return NasalPositioned::create(c, (FGPositioned*)rwy); -} - -//------------------------------------------------------------------------------ -naRef to_nasal_helper(naContext c, FGParking* parking) -{ - return NasalParking::create(c, parking); -} +typedef nasal::Ghost NasalNavRecord; +typedef nasal::Ghost NasalRunway; +typedef nasal::Ghost NasalFix; //------------------------------------------------------------------------------ naRef to_nasal_helper(naContext c, flightgear::SID* sid) @@ -94,23 +77,19 @@ naRef to_nasal_helper(naContext c, flightgear::Approach* iap) } //------------------------------------------------------------------------------ -naRef to_nasal_helper(naContext c, FGAirport* apt) +static naRef f_navaid_course(naContext, FGNavRecord& nav) { - return NasalAirport::create(c, apt); -} + if( !( nav.type() == FGPositioned::ILS + || nav.type() == FGPositioned::LOC + ) ) + return naNil(); -//------------------------------------------------------------------------------ -naRef to_nasal_helper(naContext c, const SGGeod& pos) -{ - nasal::Hash hash(c); - hash.set("lat", pos.getLatitudeDeg()); - hash.set("lon", pos.getLongitudeDeg()); - hash.set("elevation", pos.getElevationM()); - return hash.get_naRef(); + double radial = nav.get_multiuse(); + return naNum(SGMiscd::normalizePeriodic(0.5, 360.5, radial)); } //------------------------------------------------------------------------------ -static FGRunwayBase* f_airport_runway(FGAirport& apt, std::string ident) +static FGRunwayBaseRef f_airport_runway(FGAirport& apt, std::string ident) { boost::to_upper(ident); @@ -124,7 +103,7 @@ static FGRunwayBase* f_airport_runway(FGAirport& apt, std::string ident) //------------------------------------------------------------------------------ template -std::vector extract( const std::vector& in, +std::vector extract( const std::vector& in, T (C2::*getter)() const ) { std::vector ret(in.size()); @@ -224,7 +203,7 @@ static naRef f_airport_approaches(FGAirport& apt, const nasal::CallContext& ctx) //------------------------------------------------------------------------------ static FGParkingList -f_airport_parking(FGAirport& apt, const nasal::CallContext& ctx) +f_airport_parking(FGAirport& apt, nasal::CallContext ctx) { std::string type = ctx.getArg(0); bool only_available = ctx.getArg(1); @@ -251,6 +230,81 @@ f_airport_parking(FGAirport& apt, const nasal::CallContext& ctx) return ret; } +/** + * Extract a SGGeod from a nasal function argument list. + * + * , + * {"lat": , "lon": } + * geo.Coord.new() (aka. {"_lat": , "_lon": }) + */ +static bool extractGeod(nasal::CallContext& ctx, SGGeod& result) +{ + if( !ctx.argc ) + return false; + + if( ctx.isGhost(0) ) + { + FGPositioned* pos = + NasalPositioned::fromNasal(ctx.c, ctx.requireArg(0)); + + if( pos ) + { + result = pos->geod(); + ctx.popFront(); + return true; + } + } + else if( ctx.isHash(0) ) + { + nasal::Hash pos_hash = ctx.requireArg(0); + + // check for manual latitude / longitude names + naRef lat = pos_hash.get("lat"), + lon = pos_hash.get("lon"); + if( naIsNum(lat) && naIsNum(lon) ) + { + result = SGGeod::fromDeg( ctx.from_nasal(lon), + ctx.from_nasal(lat) ); + ctx.popFront(); + return true; + } + + // geo.Coord uses _lat/_lon in radians + // TODO should we check if its really a geo.Coord? + lat = pos_hash.get("_lat"); + lon = pos_hash.get("_lon"); + if( naIsNum(lat) && naIsNum(lon) ) + { + result = SGGeod::fromRad( ctx.from_nasal(lon), + ctx.from_nasal(lat) ); + ctx.popFront(); + return true; + } + } + else if( ctx.isNumeric(0) && ctx.isNumeric(1) ) + { + // lat, lon + result = SGGeod::fromDeg( ctx.requireArg(1), + ctx.requireArg(0) ); + ctx.popFront(2); + return true; + } + + return false; +} + +/** + * Extract position from ctx or return current aircraft position if not given. + */ +static SGGeod getPosition(nasal::CallContext& ctx) +{ + SGGeod pos; + if( !extractGeod(ctx, pos) ) + pos = globals->get_aircraft_position(); + + return pos; +} + //------------------------------------------------------------------------------ // Returns Nasal ghost for particular or nearest airport of a , or nil // on error. @@ -259,31 +313,17 @@ f_airport_parking(FGAirport& apt, const nasal::CallContext& ctx) // airportinfo(); type := ("airport"|"seaport"|"heliport") // airportinfo() same as airportinfo("airport") // airportinfo(, [, ]); -static naRef f_airportinfo(naContext c, naRef me, int argc, naRef* args) +static naRef f_airportinfo(nasal::CallContext ctx) { - nasal::CallContext ctx(c, argc, args); - // TODO think of something comfortable to overload functions or use variable - // number/types of arguments. + SGGeod pos = getPosition(ctx); - std::string ident = "airport"; - SGGeod pos = globals->get_aircraft_position(); + if( ctx.argc > 1 ) + naRuntimeError(ctx.c, "airportinfo() with invalid function arguments"); - if( ctx.argc == 1 ) - { + // optional type/ident + std::string ident("airport"); + if( ctx.isString(0) ) ident = ctx.requireArg(0); - } - else if( ctx.argc >= 2 ) - { - // Why are lat/lon swapped? - pos = SGGeod::fromDeg( ctx.requireArg(1), - ctx.requireArg(0) ); - - if( ctx.argc >= 3 ) - ident = ctx.requireArg(2); - - if( ctx.argc > 3 ) - naRuntimeError(ctx.c, "airportinfo() with invalid function arguments"); - } FGAirport::TypeRunwayFilter filter; if( !filter.fromTypeString(ident) ) @@ -294,23 +334,157 @@ static naRef f_airportinfo(naContext c, naRef me, int argc, naRef* args) return ctx.to_nasal( FGAirport::findClosest(pos, maxRange, &filter) ); } +/** + * findAirportsWithinRange([,] [, type]) + */ +static naRef f_findAirportsWithinRange(nasal::CallContext ctx) +{ + SGGeod pos = getPosition(ctx); + double range_nm = ctx.requireArg(0); + + FGAirport::TypeRunwayFilter filter; // defaults to airports only + filter.fromTypeString( ctx.getArg(1) ); + + FGPositionedList apts = FGPositioned::findWithinRange(pos, range_nm, &filter); + FGPositioned::sortByRange(apts, pos); + + return ctx.to_nasal(apts); +} + +/** + * findAirportsByICAO( [, type]) + */ +static naRef f_findAirportsByICAO(nasal::CallContext ctx) +{ + std::string prefix = ctx.requireArg(0); + + FGAirport::TypeRunwayFilter filter; // defaults to airports only + filter.fromTypeString( ctx.getArg(1) ); + + return ctx.to_nasal( FGPositioned::findAllWithIdent(prefix, &filter, false) ); +} + +// Returns vector of data hash for navaid of a , nil on error +// navaids sorted by ascending distance +// navinfo([,],[],[]) +// lat/lon (numeric): use latitude/longitude instead of ac position +// type: ("fix"|"vor"|"ndb"|"ils"|"dme"|"tacan"|"any") +// id: (partial) id of the fix +// examples: +// navinfo("vor") returns all vors +// navinfo("HAM") return all navaids who's name start with "HAM" +// navinfo("vor", "HAM") return all vor who's name start with "HAM" +//navinfo(34,48,"vor","HAM") return all vor who's name start with "HAM" +// sorted by distance relative to lat=34, lon=48 +static naRef f_navinfo(nasal::CallContext ctx) +{ + SGGeod pos = getPosition(ctx); + std::string id = ctx.getArg(0); + + FGNavList::TypeFilter filter; + if( filter.fromTypeString(id) ) + id = ctx.getArg(1); + else if( ctx.argc > 1 ) + naRuntimeError(ctx.c, "navinfo() already got an ident"); + + return ctx.to_nasal( FGNavList::findByIdentAndFreq(pos, id, 0.0, &filter) ); +} + +//------------------------------------------------------------------------------ +static naRef f_findWithinRange(nasal::CallContext ctx) +{ + SGGeod pos = getPosition(ctx); + double range_nm = ctx.requireArg(0); + + std::string typeSpec = ctx.getArg(1); + FGPositioned::TypeFilter filter(FGPositioned::TypeFilter::fromString(typeSpec)); + + FGPositionedList items = FGPositioned::findWithinRange(pos, range_nm, &filter); + FGPositioned::sortByRange(items, pos); + return ctx.to_nasal(items); +} + +static naRef f_findByIdent(nasal::CallContext ctx) +{ + std::string prefix = ctx.requireArg(0); + std::string typeSpec = ctx.getArg(1); + FGPositioned::TypeFilter filter(FGPositioned::TypeFilter::fromString(typeSpec)); + bool exact = ctx.getArg(2, false); + + return ctx.to_nasal( FGPositioned::findAllWithIdent(prefix, &filter, exact) ); +} + +static naRef f_findByName(nasal::CallContext ctx) +{ + std::string prefix = ctx.requireArg(0); + std::string typeSpec = ctx.getArg(1); + FGPositioned::TypeFilter filter(FGPositioned::TypeFilter::fromString(typeSpec)); + + return ctx.to_nasal( FGPositioned::findAllWithName(prefix, &filter, false) ); +} + //------------------------------------------------------------------------------ -naRef initNasalPositioned_cppbind(naRef globalsRef, naContext c, naRef gcSave) + +static naRef f_courseAndDistance(nasal::CallContext ctx) { - NasalPositioned::init("FGPositioned") + SGGeod from = globals->get_aircraft_position(), to, pos; + bool ok = extractGeod(ctx, pos); + if (!ok) { + naRuntimeError(ctx.c, "invalid arguments to courseAndDistance"); + } + + if (extractGeod(ctx, to)) { + from = pos; // we parsed both FROM and TO args, so first was FROM + } else { + to = pos; // only parsed one arg, so FROM is current + } + + double course, course2, d; + SGGeodesy::inverse(from, to, course, course2, d); + + naRef result = naNewVector(ctx.c); + naVec_append(result, naNum(course)); + naVec_append(result, naNum(d * SG_METER_TO_NM)); + return result; +} + +static naRef f_sortByRange(nasal::CallContext ctx) +{ + FGPositionedList items = ctx.requireArg(0); + ctx.popFront(); + FGPositioned::sortByRange(items, getPosition(ctx)); + return ctx.to_nasal(items); +} + +//------------------------------------------------------------------------------ +naRef initNasalPositioned_cppbind(naRef globalsRef, naContext c) +{ + if (!NasalPositioned::isInit()) { + + NasalPositioned::init("Positioned") .member("id", &FGPositioned::ident) .member("ident", &FGPositioned::ident) // TODO to we really need id and ident? .member("name", &FGPositioned::name) + .member("type", &FGPositioned::typeString) .member("lat", &FGPositioned::latitude) .member("lon", &FGPositioned::longitude) .member("elevation", &FGPositioned::elevationM); - NasalRunway::init("FGRunway") + NasalRunway::init("Runway") .bases(); - NasalParking::init("FGParking") + NasalParking::init("Parking") .bases(); NasalCommStation::init("CommStation") .bases() .member("frequency", &flightgear::CommStation::freqMHz); + NasalNavRecord::init("Navaid") + .bases() + .member("frequency", &FGNavRecord::get_freq) + .member("range_nm", &FGNavRecord::get_range) + .member("course", &f_navaid_course); + + NasalFix::init("Fix") + .bases(); + NasalAirport::init("FGAirport") .bases() .member("has_metar", &FGAirport::getMetar) @@ -330,11 +504,21 @@ naRef initNasalPositioned_cppbind(naRef globalsRef, naContext c, naRef gcSave) .method("getStar", &FGAirport::findSTARWithIdent) .method("getIAP", &FGAirport::findApproachWithIdent) .method("tostring", &FGAirport::toString); - + } + nasal::Hash globals(globalsRef, c), positioned( globals.createHash("positioned") ); positioned.set("airportinfo", &f_airportinfo); - + positioned.set("findAirportsWithinRange", f_findAirportsWithinRange); + positioned.set("findAirportsByICAO", &f_findAirportsByICAO); + positioned.set("navinfo", &f_navinfo); + + positioned.set("findWithinRange", &f_findWithinRange); + positioned.set("findByIdent", &f_findByIdent); + positioned.set("findByName", &f_findByName); + positioned.set("courseAndDistance", &f_courseAndDistance); + positioned.set("sortByRange", &f_sortByRange); + return naNil(); }