]> git.mxchange.org Git - flightgear.git/commitdiff
Mathias Fröhlich:
authorcurt <curt>
Wed, 9 Nov 2005 17:08:04 +0000 (17:08 +0000)
committercurt <curt>
Wed, 9 Nov 2005 17:08:04 +0000 (17:08 +0000)
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
src/Scenery/scenery.hxx

index 183826b27b32073488faebe702deef9342566a1c..2b97835d23ae37810b1fcff3ed15158224e26250 100644 (file)
@@ -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;
+}
+
index eed0e67a022d363d67bb171456fa2a763877824b..996eb8ddcfed7e8fd60a5e044711135450eaa3f4 100644 (file)
@@ -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 );