From b06049219ec443de65b4b67c592a3d551b772a5f Mon Sep 17 00:00:00 2001 From: curt Date: Wed, 9 Nov 2005 17:08:04 +0000 Subject: [PATCH] =?utf8?q?Mathias=20Fr=C3=B6hlich:?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Take any arbitrary vector (not necessarily vertical) and intersect it with the current set of loaded terrain tiles. Returns lon, lat, elev. This could have a multitude of useful applications such as testing line of sight between two objects, faking a terrain following lookahead radar system, virtual georeferencing, etc. --- src/Scenery/scenery.cxx | 71 +++++++++++++++++++++++++++++++++++++++++ src/Scenery/scenery.hxx | 8 +++++ 2 files changed, 79 insertions(+) diff --git a/src/Scenery/scenery.cxx b/src/Scenery/scenery.cxx index 183826b27..2b97835d2 100644 --- a/src/Scenery/scenery.cxx +++ b/src/Scenery/scenery.cxx @@ -186,3 +186,74 @@ FGScenery::get_cart_elevation_m(const sgdVec3& pos, double max_altoff, return hit; } + + +bool +FGScenery::get_cart_ground_intersection(const sgdVec3& pos, + const sgdVec3& dir, + sgdVec3& nearestHit, bool exact) +{ + // We assume that starting positions in the center of the earth are invalid + if ( fabs(pos[0]) < 1.0 && fabs(pos[1]) < 1.0 && fabs(pos[2]) < 1.0 ) + return false; + + // Well that 'exactness' is somehow problematic, but makes at least sure + // that we don't compute that with a cenery center at the other side of + // the world ... + Point3D saved_center = center; + bool replaced_center = false; + if (exact) { + Point3D ppos(pos[0], pos[1], pos[2]); + if (30.0*30.0 < ppos.distance3Dsquared(center)) { + set_center( ppos ); + replaced_center = true; + } + } + + // Not yet found any hit ... + bool result = false; + + // Make really sure the direction is normalized, is really cheap compared to + // computation of ground intersection. + sgdVec3 normalizedDir; + sgdCopyVec3(normalizedDir, dir); + sgdNormaliseVec3(normalizedDir); + + sgdVec3 sceneryCenter; + sgdSetVec3(sceneryCenter, center[0], center[1], center[2]); + sgdVec3 relativePos; + sgdSubVec3(relativePos, pos, sceneryCenter); + + // At the moment only intersection with the terrain? + FGHitList hit_list; + hit_list.Intersect(globals->get_scenery()->get_terrain_branch(), + relativePos, normalizedDir); + + double dist = DBL_MAX; + int hitcount = hit_list.num_hits(); + for (int i = 0; i < hitcount; ++i) { + // Check for the nearest hit + sgdVec3 diff; + sgdSubVec3(diff, hit_list.get_point(i), relativePos); + + // We only want hits in front of us ... + if (sgdScalarProductVec3(normalizedDir, diff) < 0) + continue; + + // find the nearest hit + double nDist = sgdScalarProductVec3(diff, diff); + if (dist < nDist) + continue; + + // Store the hit point + dist = nDist; + sgdAddVec3(nearestHit, hit_list.get_point(i), sceneryCenter); + result = true; + } + + if (replaced_center) + set_center( saved_center ); + + return result; +} + diff --git a/src/Scenery/scenery.hxx b/src/Scenery/scenery.hxx index eed0e67a0..996eb8ddc 100644 --- a/src/Scenery/scenery.hxx +++ b/src/Scenery/scenery.hxx @@ -108,6 +108,14 @@ public: bool get_cart_elevation_m(const sgdVec3& pos, double max_altoff, double& radius, bool exact = false); + /// Compute the nearest intersection point of the line starting from + /// start going in direction dir with the terrain. + /// The input and output values should be in cartesian coordinates in the + /// usual earth centered wgs84 coordiante system. Units are meters. + /// On success, true is returned. + bool get_cart_ground_intersection(const sgdVec3& start, const sgdVec3& dir, + sgdVec3& nearestHit, bool exact = false); + inline const Point3D& get_center() const { return center; } void set_center( const Point3D& p ); -- 2.39.5