From 435d874e35d98e9153eabdaca7c41e009f1b5f8c Mon Sep 17 00:00:00 2001 From: mfranz <mfranz> Date: Sun, 4 Dec 2005 10:43:49 +0000 Subject: [PATCH] Mathias FROEHLICH: remove a hack and do it properly: if the requested elevation is for some reason below the surface and the intersection test fails (as it appears to be the case in EGLL), try again from 10000m ASL mf: typos --- src/FDM/flight.cxx | 48 ++++++++++++++++++++++++++++++++--------- src/FDM/groundcache.cxx | 16 +++++++------- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/FDM/flight.cxx b/src/FDM/flight.cxx index 43b5aa03b..695497190 100644 --- a/src/FDM/flight.cxx +++ b/src/FDM/flight.cxx @@ -196,6 +196,10 @@ FGInterface::common_init () double alt_m = alt_ft * SG_FEET_TO_METER; set_Longitude( lon ); set_Latitude( lat ); + SG_LOG( SG_FLIGHT, SG_INFO, "Checking for lon = " + << lon*SGD_RADIANS_TO_DEGREES << "deg, lat = " + << lat*SGD_RADIANS_TO_DEGREES << "deg, alt = " + << alt_ft << "ft"); double ground_elev_m = get_groundlevel_m(lat, lon, alt_m); double ground_elev_ft = ground_elev_m * SG_METER_TO_FEET; @@ -894,26 +898,50 @@ FGInterface::get_agl_ft(double t, const double pt[3], double max_altoff, double FGInterface::get_groundlevel_m(double lat, double lon, double alt) { - // First compute the sea level radius, sgdVec3 pos, cpos; - sgGeodToCart(lat, lon, 0, pos); - double slr = sgdLengthVec3(pos); - // .. then the cartesian position of the given lat/lon/alt. + // Compute the cartesian position of the given lat/lon/alt. sgGeodToCart(lat, lon, alt, pos); // FIXME: how to handle t - ref_time differences ??? double ref_time, radius; // Prepare the ground cache for that position. - if (!is_valid_m(&ref_time, cpos, &radius)) - prepare_ground_cache_m(ref_time, pos, 10); - else if (radius*radius <= sgdDistanceSquaredVec3(pos, cpos)) - prepare_ground_cache_m(ref_time, pos, radius); + if (!is_valid_m(&ref_time, cpos, &radius)) { + bool ok = prepare_ground_cache_m(ref_time, pos, 10); + /// This is most likely the case when the given altitude is + /// too low, try with a new altitude of 10000m, that should be + /// sufficient to find a ground level below everywhere on our planet + if (!ok) { + sgGeodToCart(lat, lon, 10000, pos); + /// If there is still no ground, return sea level radius + if (!prepare_ground_cache_m(ref_time, pos, 10)) + return 0; + } + } else if (radius*radius <= sgdDistanceSquaredVec3(pos, cpos)) { + /// We reuse the old radius value, but only if it is at least 10 Meters .. + if (!(10 < radius)) // Well this strange compare is nan safe + radius = 10; + + bool ok = prepare_ground_cache_m(ref_time, pos, radius); + /// This is most likely the case when the given altitude is + /// too low, try with a new altitude of 10000m, that should be + /// sufficient to find a ground level below everywhere on our planet + if (!ok) { + sgGeodToCart(lat, lon, 10000, pos); + /// If there is still no ground, return sea level radius + if (!prepare_ground_cache_m(ref_time, pos, radius)) + return 0; + } + } double contact[3], normal[3], vel[3], lc, ff, agl; int type; + // Ignore the return value here, since it just tells us if + // the returns stem from the groundcache or from the coarse + // computations below the groundcache. The contact point is still something + // valid, the normals and the other returns just contain some defaults. get_agl_m(ref_time, pos, 2.0, contact, normal, vel, &type, &lc, &ff, &agl); - - return sgdLengthVec3(contact) - slr; + Point3D geodPos = sgCartToGeod(Point3D(contact[0], contact[1], contact[2])); + return geodPos.elev(); } bool diff --git a/src/FDM/groundcache.cxx b/src/FDM/groundcache.cxx index edabbf0de..04b5af06e 100644 --- a/src/FDM/groundcache.cxx +++ b/src/FDM/groundcache.cxx @@ -202,7 +202,7 @@ FGGroundCache::extractGroundProperty( ssgLeaf* l ) { // FIXME: Do more ... // Idea: have a get_globals() function which knows about that stuff. - // Or most propably read that from a configuration file, + // Or most probably read that from a configuration file, // from property tree or whatever ... // Get ground dependent data. @@ -361,7 +361,7 @@ FGGroundCache::putSurfaceLeafIntoCache(const sgdSphere *sp, sgdSubVec3(off, isectpoint, tmp); // Only accept the altitude if the intersection point is below the // ground cache midpoint - if (0 < sgdScalarProductVec3( off, down ) || !found_ground) { + if (0 < sgdScalarProductVec3( off, down )) { found_ground = true; sgdAddVec3(isectpoint, cache_center); double this_radius = sgdLengthVec3(isectpoint); @@ -441,7 +441,7 @@ FGGroundCache::cache_fill(ssgBranch *branch, sgdMat4 xform, if ( e->isAKindOf( ssgTypeBranch() ) ) { ssgBranch *b = (ssgBranch *)e; if ( b->isAKindOf( ssgTypeTransform() ) ) { - // Collect up the transfors required to reach that part of + // Collect up the transforms required to reach that part of // the branch. sgMat4 xform2; sgMakeIdentMat4( xform2 ); @@ -458,9 +458,9 @@ FGGroundCache::cache_fill(ssgBranch *branch, sgdMat4 xform, // This will minimize the number of vertices/triangles in the cache. else if (e->isAKindOf(ssgTypeLeaf())) { // Since we reach that leaf if we have an intersection with the - // most propably bigger wire/catapult cache sphere, we need to check + // most probably bigger wire/catapult cache sphere, we need to check // that here, if the smaller cache for the surface has a chance for hits. - // Also, if the spheres do not intersect compute a croase agl value + // Also, if the spheres do not intersect compute a coarse agl value // by following the line downwards originating at the aircraft. bool spIsec = sp->intersects(&esphere); putSurfaceLeafIntoCache(sp, xform, spIsec, down, (ssgLeaf *)e); @@ -493,7 +493,7 @@ FGGroundCache::prepare_ground_cache(double ref_time, const double pt[3], // Decide where we put the scenery center. Point3D old_cntr = globals->get_scenery()->get_center(); Point3D cntr(pt[0], pt[1], pt[2]); - // Only move the cache center if it is unaccaptable far away. + // Only move the cache center if it is unacceptable far away. if (40*40 < old_cntr.distance3Dsquared(cntr)) globals->get_scenery()->set_center(cntr); else @@ -523,7 +523,7 @@ FGGroundCache::prepare_ground_cache(double ref_time, const double pt[3], sgdSetVec3(down, -pt[0], -pt[1], -pt[2]); sgdNormalizeVec3(down); - // We collaps all transforms we need to reach a particular leaf. + // We collapse all transforms we need to reach a particular leaf. // The leafs itself will be then transformed later. // So our cache is just flat. // For leafs which are moving (carriers surface, etc ...) @@ -736,7 +736,7 @@ bool FGGroundCache::caught_wire(double t, const double pt[4][3]) sgdCopyVec3( tri[1][2], pt[3] ); // Intersect the wire lines with each of these triangles. - // You have cautght a wire if they intersect. + // You have caught a wire if they intersect. for (size_t i = 0; i < sz; ++i) { sgdVec3 le[2]; for (int k = 0; k < 2; ++k) {