From ccf0ba50c40918024d0e76b1288deb109a526f39 Mon Sep 17 00:00:00 2001 From: John Denker Date: Sat, 10 Jan 2009 18:16:58 -0700 Subject: [PATCH] Implement vector _projection_ functions. --- simgear/math/SGVec3.hxx | 17 +++++++++++++++-- simgear/math/vector.cxx | 34 ++++++++++++++++++---------------- simgear/math/vector.hxx | 12 +++++++++++- 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/simgear/math/SGVec3.hxx b/simgear/math/SGVec3.hxx index cbdf0fa2..9b81ec57 100644 --- a/simgear/math/SGVec3.hxx +++ b/simgear/math/SGVec3.hxx @@ -352,12 +352,16 @@ perpendicular(const SGVec3& v) } } -/// The euclidean norm of the vector, that is what most people call length +/// Construct a unit vector in the given direction. +/// or the zero vector if the input vector is zero. template inline SGVec3 normalize(const SGVec3& v) -{ return (1/norm(v))*v; } +{ T normv = norm(v); + if (normv > 0.0) return (1/norm(v))*v; + else return v; +} /// Return true if exactly the same template @@ -476,6 +480,15 @@ SGVec3d toVec3d(const SGVec3f& v) { return SGVec3d(v(0), v(1), v(2)); } +// calculate the projection of u along the direction of d. +template +inline SGVec3 SGProjection(const SGVec3& u, const SGVec3& d) +{ + T denom = dot(d, d); + if (denom == 0.) return u; + else return d * (dot(u,d) / denom); +} + #ifndef NO_OPENSCENEGRAPH_INTERFACE inline SGVec3d diff --git a/simgear/math/vector.cxx b/simgear/math/vector.cxx index 8a87fb5d..a5d3ee0a 100644 --- a/simgear/math/vector.cxx +++ b/simgear/math/vector.cxx @@ -29,6 +29,20 @@ #include "vector.hxx" +// calculate the projection, p, of u along the direction of d. +void sgProjection(sgVec3 p, const sgVec3 u, const sgVec3 d){ + double denom = sgScalarProductVec3(d,d); + if (denom == 0.) sgCopyVec3(p, u); + else sgScaleVec3(p, d, sgScalarProductVec3(u,d) / denom); +} + +// Same thing, except using double precision +void sgProjection(sgdVec3 p, const sgdVec3 u, const sgdVec3 d){ + double denom = sgdScalarProductVec3(d,d); + if (denom == 0.) sgdCopyVec3(p, u); + else sgdScaleVec3(p, d, sgdScalarProductVec3(u,d) / denom); +} + // Given a point p, and a line through p0 with direction vector d, // find the closest point (p1) on the line void sgClosestPointToLine( sgVec3 p1, const sgVec3 p, const sgVec3 p0, @@ -40,8 +54,7 @@ void sgClosestPointToLine( sgVec3 p1, const sgVec3 p, const sgVec3 p0, sgSubVec3(u, p, p0); // calculate the projection, u1, of u along d. - // u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d; - sgScaleVec3( u1, d, sgScalarProductVec3(u,d) / sgScalarProductVec3(d,d) ); + sgProjection(u1, u, d); // calculate the point p1 along the line that is closest to p // p0 = p1 + u1 @@ -60,12 +73,7 @@ void sgdClosestPointToLine( sgdVec3 p1, const sgdVec3 p, const sgdVec3 p0, sgdSubVec3(u, p, p0); // calculate the projection, u1, of u along d. - // u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d; - double ud = sgdScalarProductVec3(u, d); - double dd = sgdScalarProductVec3(d, d); - double tmp = ud / dd; - - sgdScaleVec3(u1, d, tmp);; + sgProjection(u1, u, d); // calculate the point p1 along the line that is closest to p // p0 = p1 + u1 @@ -84,8 +92,7 @@ double sgClosestPointToLineDistSquared( const sgVec3 p, const sgVec3 p0, sgSubVec3(u, p, p0); // calculate the projection, u1, of u along d. - // u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d; - sgScaleVec3( u1, d, sgScalarProductVec3(u,d) / sgScalarProductVec3(d,d) ); + sgProjection(u1, u, d); // v = u - u1 = vector from closest point on line, p1, to the // original point, p. @@ -106,12 +113,7 @@ double sgdClosestPointToLineDistSquared( const sgdVec3 p, const sgdVec3 p0, sgdSubVec3(u, p, p0); // calculate the projection, u1, of u along d. - // u1 = ( dot_prod(u, d) / dot_prod(d, d) ) * d; - double ud = sgdScalarProductVec3(u, d); - double dd = sgdScalarProductVec3(d, d); - double tmp = ud / dd; - - sgdScaleVec3(u1, d, tmp);; + sgProjection(u1, u, d); // v = u - u1 = vector from closest point on line, p1, to the // original point, p. diff --git a/simgear/math/vector.hxx b/simgear/math/vector.hxx index cec24236..b4cbb2f3 100644 --- a/simgear/math/vector.hxx +++ b/simgear/math/vector.hxx @@ -38,7 +38,17 @@ /** - * Map a vector onto a plane. + * calculate the projection, p, of u along the direction of d. + * @param p (out) the projection + * @param u (in) the vector to be projected + * @param d (in) the direction onto which we project + */ +void sgProjection(sgVec3 p, const sgVec3 u, const sgVec3 d); +void sgProjection(sgdVec3 p, const sgdVec3 u, const sgdVec3 d); + + +/** + * Map i.e. project a vector onto a plane. * @param normal (in) normal vector for the plane * @param v0 (in) a point on the plane * @param vec (in) the vector to map onto the plane -- 2.39.5