From c5781546b970dd710ef8469dc7ba39f339375f15 Mon Sep 17 00:00:00 2001 From: James Turner Date: Wed, 25 Apr 2012 16:54:40 +0100 Subject: [PATCH] Expose greatCircleMove to Nasal, and allow geo.Coord to be passed into methods. --- src/Scripting/NasalPositioned.cxx | 68 +++++++++++++++++++++++++++++-- src/Scripting/NasalPositioned.hxx | 1 + src/Scripting/NasalSys.cxx | 3 ++ 3 files changed, 68 insertions(+), 4 deletions(-) diff --git a/src/Scripting/NasalPositioned.cxx b/src/Scripting/NasalPositioned.cxx index 3714d4369..18f2b1032 100644 --- a/src/Scripting/NasalPositioned.cxx +++ b/src/Scripting/NasalPositioned.cxx @@ -97,6 +97,7 @@ static void wayptGhostDestroy(void* g) static naRef airportPrototype; static naRef routePrototype; static naRef waypointPrototype; +static naRef geoCoordClass; naRef ghostForPositioned(naContext c, const FGPositioned* pos) { @@ -248,6 +249,16 @@ naRef hashForNavRecord(naContext c, const FGNavRecord* nav, const SGGeod& rel) return navdata; } +static bool hashIsCoord(naRef h) +{ + naRef parents = naHash_cget(h, (char*) "parents"); + if (!naIsVector(parents)) { + return false; + } + + return naEqual(naVec_get(parents, 0), geoCoordClass); +} + bool geodFromHash(naRef ref, SGGeod& result) { if (!naIsHash(ref)) { @@ -274,11 +285,18 @@ bool geodFromHash(naRef ref, SGGeod& result) naRef lat = naHash_cget(ref, (char*) "lat"); naRef lon = naHash_cget(ref, (char*) "lon"); if (naIsNum(lat) && naIsNum(lon)) { - result = SGGeod::fromDeg(naNumValue(lat).num, naNumValue(lon).num); + result = SGGeod::fromDeg(naNumValue(lon).num, naNumValue(lat).num); return true; } -// check for geo.Coord type + if (hashIsCoord(ref)) { + naRef lat = naHash_cget(ref, (char*) "_lat"); + naRef lon = naHash_cget(ref, (char*) "_lon"); + if (naIsNum(lat) && naIsNum(lon)) { + result = SGGeod::fromRad(naNumValue(lon).num, naNumValue(lat).num); + return true; + } + } // check for any synonyms? // latitude + longitude? @@ -580,7 +598,6 @@ static naRef f_airport_sids(naContext c, naRef me, int argc, naRef* args) naRef sids = naNewVector(c); - // if we have an explicit type, return a simple vector of frequencies if (argc > 0 && naIsString(args[0])) { if (!apt->hasRunwayWithIdent(naStr_data(args[0]))) { return naNil(); @@ -611,7 +628,6 @@ static naRef f_airport_stars(naContext c, naRef me, int argc, naRef* args) naRef stars = naNewVector(c); - // if we have an explicit type, return a simple vector of frequencies if (argc > 0 && naIsString(args[0])) { if (!apt->hasRunwayWithIdent(naStr_data(args[0]))) { return naNil(); @@ -883,6 +899,37 @@ static naRef f_courseAndDistance(naContext c, naRef me, int argc, naRef* args) return result; } +static naRef f_greatCircleMove(naContext c, naRef me, int argc, naRef* args) +{ + SGGeod from = globals->get_aircraft_position(), to; + int argOffset = 0; + + // complication - don't inerpret two doubles (as the only args) + // as a lat,lon pair - only do so if we have at least three args. + if (argc > 2) { + argOffset = geodFromArgs(args, 0, argc, from); + } + + if ((argOffset + 1) >= argc) { + naRuntimeError(c, "isufficent arguments to greatCircleMove"); + } + + if (!naIsNum(args[argOffset]) || !naIsNum(args[argOffset+1])) { + naRuntimeError(c, "invalid arguments %d and %d to greatCircleMove", + argOffset, argOffset + 1); + } + + double course = args[argOffset].num, course2; + double distanceNm = args[argOffset + 1].num; + SGGeodesy::direct(from, course, distanceNm * SG_NM_TO_METER, to, course2); + + // return geo.Coord + naRef coord = naNewHash(c); + hashset(c, coord, "lat", naNum(to.getLatitudeDeg())); + hashset(c, coord, "lon", naNum(to.getLongitudeDeg())); + return coord; +} + static naRef f_tilePath(naContext c, naRef me, int argc, naRef* args) { SGGeod pos = globals->get_aircraft_position(); @@ -1034,6 +1081,7 @@ static struct { const char* name; naCFunction func; } funcs[] = { { "route", f_route }, { "magvar", f_magvar }, { "courseAndDistance", f_courseAndDistance }, + { "greatCircleMove", f_greatCircleMove }, { "bucketPath", f_tilePath }, { 0, 0 } }; @@ -1073,3 +1121,15 @@ naRef initNasalPositioned(naRef globals, naContext c, naRef gcSave) return naNil(); } +void postinitNasalPositioned(naRef globals, naContext c) +{ + naRef geoModule = naHash_cget(globals, (char*) "geo"); + if (naIsNil(geoModule)) { + SG_LOG(SG_GENERAL, SG_WARN, "postinitNasalPositioned: geo.nas not loaded"); + return; + } + + geoCoordClass = naHash_cget(geoModule, (char*) "Coord"); +} + + diff --git a/src/Scripting/NasalPositioned.hxx b/src/Scripting/NasalPositioned.hxx index 96cb87918..5fbec2650 100644 --- a/src/Scripting/NasalPositioned.hxx +++ b/src/Scripting/NasalPositioned.hxx @@ -36,5 +36,6 @@ naRef hashForNavRecord(naContext c, const FGNavRecord* nav, const SGGeod& rel); bool geodFromHash(naRef ref, SGGeod& result); naRef initNasalPositioned(naRef globals, naContext c, naRef gcSave); +void postinitNasalPositioned(naRef globals, naContext c); #endif // of SCRIPTING_NASAL_POSITIONED_HXX diff --git a/src/Scripting/NasalSys.cxx b/src/Scripting/NasalSys.cxx index 3be65c325..73bb2e25a 100644 --- a/src/Scripting/NasalSys.cxx +++ b/src/Scripting/NasalSys.cxx @@ -564,6 +564,9 @@ void FGNasalSys::init() // Pull scripts out of the property tree, too loadPropertyScripts(); + + // now Nasal modules are loaded, we can do some delayed work + postinitNasalPositioned(_globals, _context); } void FGNasalSys::update(double) -- 2.39.5