utilities2D.cpp

00001 
00016 #include <dlrGeometry/utilities2D.h>
00017 #include <dlrNumeric/utilities.h>
00018 
00019 namespace num = dlr::numeric;
00020 
00021 // Anonymous namespace for local symbols.
00022 namespace {
00023 
00024   bool
00025   solve2By2LinearSystem(double a00, double a01, double a10, double a11,
00026                         double b0, double b1,
00027                         double& x0, double& x1) {
00028     // Use cofactor inversion.
00029     double determinant = a00 * a11 - a01 * a10;
00030     if(determinant == 0.0) {
00031       return false;
00032     }
00033     x0 = (a11 * b0 - a01 * b1) / determinant;
00034     x1 = (a00 * b1 - a10 * b0) / determinant;
00035     return true;
00036   }
00037 
00038 } // namespace
00039 
00040 
00041 namespace dlr {
00042 
00043   namespace geometry {
00044 
00045     bool
00046     checkIntersect(const LineSegment2D& lineSegment0,
00047                    const LineSegment2D& lineSegment1)
00048     {
00049       Vector2D dummy;
00050       return checkIntersect(lineSegment0, lineSegment1, dummy);
00051     }
00052 
00053 
00054     bool
00055     checkIntersect(const LineSegment2D& lineSegment0,
00056                    const LineSegment2D& lineSegment1,
00057                    numeric::Vector2D& intersect)
00058     {
00059       // The point at which lineSegment0 intersects the line of
00060       // lineSegment1 satisfies this equation:
00061       //
00062       //    v_0 + alpha * (v_1 - v_0) = w_0 + beta * (w_1 - w_0)
00063       //
00064       // where:
00065       //
00066       //    v_0 and v_1 are the vertices of the first line segment.
00067       //
00068       //    w_0 and w_1 are the vertices of the second line segment.
00069       //
00070       //    o and d are the origin and direction of the ray, respectively.
00071       //
00072       //    alpha and beta are scalar free parameters.
00073       //
00074       // We rearrange this equation:
00075       //
00076       //   A * [alpha] = b
00077       //       [ beta]
00078       //
00079       // where A is the 2x2 matrix [(v_0 - v_1), (w_1 - w_0)], and b is the 2
00080       // element vector [v_0 - w_0].
00081       
00082       // First find matrix A.
00083       Vector2D lineDirection0 =
00084         lineSegment0.getVertex0() - lineSegment0.getVertex1();
00085       Vector2D lineDirection1 =
00086         lineSegment1.getVertex0() - lineSegment1.getVertex1();
00087       double const& A_00 = lineDirection0.x();
00088       double const& A_01 = -lineDirection1.x();
00089       double const& A_10 = lineDirection0.y();
00090       double const& A_11 = -lineDirection1.y();
00091 
00092       // Now find b.  We'll call it bb.
00093       Vector2D bb = lineSegment0.getVertex0() - lineSegment1.getVertex0();
00094 
00095       // Solve for alpha and beta.
00096       double alpha;
00097       double beta;
00098       if(!solve2By2LinearSystem(A_00, A_01, A_10, A_11, bb.x(), bb.y(),
00099                                 alpha, beta)) {
00100         return false;
00101       }
00102       
00103       // The line segment runs from alpha = 0 to alpha = 1 and from
00104       // beta = 0 to beta = 1.  Check this here.
00105       if((alpha < 0.0) || (alpha >= 1.0) || (beta < 0.0) || (beta >= 1.0)) {
00106         return false;
00107       }
00108 
00109       // All done.  Now fill in the return parameters.
00110       intersect = lineSegment0.getVertex0() - alpha * lineDirection0;
00111       return true;
00112     }
00113 
00114     
00115     bool
00116     checkIntersect(const Ray2D& ray, const LineSegment2D& lineSegment)
00117     {
00118       double dummy0;
00119       Vector2D dummy1;
00120       return checkIntersect(ray, lineSegment, dummy1, dummy0);
00121     }
00122 
00123 
00124     bool
00125     checkIntersect(const Ray2D& ray, const LineSegment2D& lineSegment,
00126                    numeric::Vector2D& intersect)
00127     {
00128       double dummy;
00129       return checkIntersect(ray, lineSegment, intersect, dummy);
00130     }
00131     
00132 
00133     bool
00134     checkIntersect(const Ray2D& ray, const LineSegment2D& lineSegment,
00135                    double& lambda)
00136     {
00137       Vector2D dummy;
00138       return checkIntersect(ray, lineSegment, dummy, lambda);
00139     }
00140 
00141 
00142     bool
00143     checkIntersect(const Ray2D& ray, const LineSegment2D& lineSegment,
00144                    numeric::Vector2D& intersect, double& lambda)
00145     {
00146       // The point at which the ray intersects the line of the
00147       // line segment satisfies this equation:
00148       //
00149       //    v_0 + alpha * (v_1 - v_0) = o + beta * d
00150       //
00151       // where:
00152       //
00153       //    v_0 and v_1 are the vertices of the line segment.
00154       //
00155       //    o and d are the origin and direction of the ray, respectively.
00156       //
00157       //    alpha and beta are scalar free parameters.
00158       //
00159       // We rearrange this equation:
00160       //
00161       //   A * [alpha] = b
00162       //       [ beta]
00163       //
00164       // where A is the 2x2 matrix [(v_0 - v_1), d], and b is the 2
00165       // element vector [v_0 - o].
00166       
00167       // First find matrix A.
00168       Vector2D lineDirection =
00169         lineSegment.getVertex0() - lineSegment.getVertex1();
00170       Vector2D const& rayDirection = ray.getDirectionVector();
00171       double const& A_00 = lineDirection.x();
00172       double const& A_01 = rayDirection.x();
00173       double const& A_10 = lineDirection.y();
00174       double const& A_11 = rayDirection.y();
00175 
00176       // Now find b.  We'll call it bb.
00177       Vector2D bb = lineSegment.getVertex0() - ray.getOrigin();
00178 
00179       // Solve for alpha and beta.
00180       double alpha;
00181       double beta;
00182       if(!solve2By2LinearSystem(A_00, A_01, A_10, A_11, bb.x(), bb.y(),
00183                                 alpha, beta)) {
00184         return false;
00185       }
00186 
00187       // The line segment runs from alpha = 0 to alpha = 1.  Check
00188       // this here.
00189       if((alpha < 0.0) || (alpha >= 1.0)) {
00190         return false;
00191       }
00192 
00193       // Check that the intersection is with the ray, not with the
00194       // fictional part of the ray that extends back past the ray
00195       // origin.
00196       if(beta < 0.0) {
00197         return false;
00198       }
00199       
00200       // All done.  Now fill in the return parameters.
00201       lambda = beta;
00202       intersect = ray.getOrigin() + beta * ray.getDirectionVector();
00203       return true;
00204     }
00205 
00206     
00207     numeric::Vector2D
00208     findClosestPoint(numeric::Vector2D const& point,
00209                      Ray2D const& ray)
00210     {
00211       num::Vector2D v1 = point - ray.getOrigin();
00212       double kk = dot(v1, ray.getDirectionVector());
00213       return ray.getOrigin() + kk * ray.getDirectionVector();
00214     }
00215 
00216 
00217     LineSegment2D
00218     operator*(const numeric::Transform2D& transform,
00219               const LineSegment2D& inputSegment)
00220     {
00221       Vector2D newVertex0 = transform * inputSegment.getVertex0();
00222       Vector2D newVertex1 = transform * inputSegment.getVertex1();
00223       return LineSegment2D(newVertex0, newVertex1);
00224     }
00225     
00226     
00227     Ray2D
00228     operator*(const numeric::Transform2D& transform,
00229               const Ray2D& inputRay)
00230     {
00231       Vector2D newOrigin = transform * inputRay.getOrigin();
00232       Vector2D newEndpoint =
00233         transform * (inputRay.getOrigin() + inputRay.getDirectionVector());
00234       return Ray2D(newOrigin, newEndpoint - newOrigin, false);
00235     }
00236     
00237     
00238   } // namespace utilities
00239     
00240 } // namespace dlr

Generated on Wed Nov 25 11:45:25 2009 for dlrGeometry Utility Library by  doxygen 1.5.8