X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FScripting%2FNasalPositioned_cppbind.cxx;h=cc3568c4b67f8ee16984e675774f12ea3b15da28;hb=881df711ba5be8a8c0bc65f2126a0dcb63865df9;hp=b2ae98c4d3390875b775dfbe127ed736227dbe18;hpb=4b573ebd13bbf301795f57293a0e190d0993ea47;p=flightgear.git diff --git a/src/Scripting/NasalPositioned_cppbind.cxx b/src/Scripting/NasalPositioned_cppbind.cxx index b2ae98c4d..cc3568c4b 100644 --- a/src/Scripting/NasalPositioned_cppbind.cxx +++ b/src/Scripting/NasalPositioned_cppbind.cxx @@ -38,38 +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) @@ -93,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); @@ -123,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()); @@ -223,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); @@ -250,39 +230,261 @@ 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. (Currently only airportinfo() is implemented) +// on error. // // airportinfo(); e.g. "KSFO" // 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. - return ctx.to_nasal(FGAirport::findByIdent( ctx.requireArg(0) )); + SGGeod pos = getPosition(ctx); + + if( ctx.argc > 1 ) + naRuntimeError(ctx.c, "airportinfo() with invalid function arguments"); + + // optional type/ident + std::string ident("airport"); + if( ctx.isString(0) ) + ident = ctx.requireArg(0); + + FGAirport::TypeRunwayFilter filter; + if( !filter.fromTypeString(ident) ) + // user provided an , hopefully + return ctx.to_nasal(FGAirport::findByIdent(ident)); + + double maxRange = 10000.0; // expose this? or pick a smaller value? + 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) ); } //------------------------------------------------------------------------------ -naRef initNasalPositioned_cppbind(naRef globalsRef, naContext c, naRef gcSave) +static naRef f_findWithinRange(nasal::CallContext ctx) { - NasalPositioned::init("FGPositioned") + 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) ); +} + +//------------------------------------------------------------------------------ + +static naRef f_courseAndDistance(nasal::CallContext ctx) +{ + 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) @@ -302,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(); }