utilities3D.cpp

00001 
00016 #include <sstream>
00017 #include <dlrCommon/exception.h>
00018 #include <dlrCommon/types.h>
00019 #include <dlrGeometry/utilities3D.h>
00020 #include <dlrLinearAlgebra/linearAlgebra.h>
00021 #include <dlrNumeric/array2D.h>
00022 
00023 namespace dlr {
00024 
00025   namespace geometry {
00026 
00027 
00028     bool
00029     checkIntersect(const Ray3D& ray, const Triangle3D& triangle)
00030     {
00031       double dummy0;
00032       Vector3D dummy1;
00033       return checkIntersect(ray, triangle, dummy1, dummy0);
00034     }
00035 
00036 
00037     bool
00038     checkIntersect(const Ray3D& ray, const Triangle3D& triangle,
00039                    numeric::Vector3D& intersect)
00040     {
00041       double dummy;
00042       return checkIntersect(ray, triangle, intersect, dummy);
00043     }
00044     
00045 
00046     bool
00047     checkIntersect(const Ray3D& ray, const Triangle3D& triangle,
00048                    double& lambda)
00049     {
00050       Vector3D dummy;
00051       return checkIntersect(ray, triangle, dummy, lambda);
00052     }
00053 
00054 
00055     bool
00056     checkIntersect(const Ray3D& ray, const Triangle3D& triangle,
00057                    numeric::Vector3D& intersect, double& lambda)
00058     {
00059       // The point at which the ray intersects the plane of the
00060       // triangle satisfies this equation:
00061       //
00062       //   v_0 + alpha_0 * e_0 + alpha_1 * e_1 = o + beta * d,
00063       //
00064       // where:
00065       //
00066       //    v_0, v_1, and v_2 are the three vertices of the triangle.
00067       //
00068       //    e_0 = v_1 - v_0 is the first leg of the triangle.
00069       //
00070       //    e_1 = v_2 - v_0 is the second leg of the triangle.
00071       //
00072       //    o and d are the origin and direction of the ray, respectively.
00073       //
00074       //    alpha_0, alpha_1, and beta are scalars.
00075       //
00076       // We rearrange this equation and solve for alpha_0, alpha_1, and beta.
00077       Float64 bufferA[9];
00078       Float64 bufferB[3];
00079       
00080       Array2D<Float64> AMatrix(3, 3, bufferA);
00081       Array1D<Float64> bVector(3, bufferB);
00082 
00083       Vector3D e_0 = triangle.getVertex1() - triangle.getVertex0();
00084       Vector3D e_1 = triangle.getVertex2() - triangle.getVertex0();
00085       
00086       AMatrix[0] = e_0.x();
00087       AMatrix[3] = e_0.y();
00088       AMatrix[6] = e_0.z();
00089       AMatrix[1] = e_1.x();
00090       AMatrix[4] = e_1.y();
00091       AMatrix[7] = e_1.z();
00092       AMatrix[2] = -ray.getDirectionVector().x();
00093       AMatrix[5] = -ray.getDirectionVector().y();
00094       AMatrix[8] = -ray.getDirectionVector().z();
00095 
00096       bVector[0] = ray.getOrigin().x() - triangle.getVertex0().x();
00097       bVector[1] = ray.getOrigin().y() - triangle.getVertex0().y();
00098       bVector[2] = ray.getOrigin().z() - triangle.getVertex0().z();
00099 
00100       try {
00101         linearSolveInPlace(AMatrix, bVector);
00102       } catch(const ValueException&) {
00103         // Singular matrix indicates degenerate triangle, or ray
00104         // parallel to the plane of the triangle.
00105         return false;
00106       }
00107 
00108       if(bVector[0] < 0.0 || bVector[1] < 0.0) {
00109         // Negative values for alpha_0 or alpha_1 indicate that the
00110         // intersection point is outside the triangle.
00111         return false;
00112       }
00113 
00114       // At this point we know that the intersection lies between
00115       // sides e_0 and e_1.  We need to make sure that this point also
00116       // lies within the bounds of the third side.  We do this by
00117       // requiring that the cross products with two adjacent sides be
00118       // antiparallel.
00119       Vector3D intersectionPoint =
00120         ray.getOrigin() + bVector[2] * ray.getDirectionVector();
00121       Vector3D offsetFromVertex1 = triangle.getVertex1() - intersectionPoint;
00122       Vector3D e_2 = triangle.getVertex2() - triangle.getVertex1();
00123 
00124       Vector3D crossProduct0 = cross(offsetFromVertex1, -e_0);
00125       Vector3D crossProduct1 = cross(offsetFromVertex1, e_2);
00126       double dotProduct = dot(crossProduct0, crossProduct1);
00127       
00128       if(dotProduct >= 0.0) {
00129         return false;
00130       }
00131 
00132       lambda = bVector[2];
00133       intersect = intersectionPoint;
00134       return true;
00135     }
00136 
00137     
00138     Vector3D
00139     findIntersect(const Ray3D& ray, const Plane3D& plane)
00140     {
00141       double dummy;
00142       return findIntersect(ray, plane, dummy);
00143     }
00144 
00145     
00146     Vector3D
00147     findIntersect(const Ray3D& ray, const Plane3D& plane, double& distance)
00148     {
00149       Float64 bufferA[9];
00150       Float64 bufferB[3];
00151       
00152       Array2D<double> AMatrix(3, 3, bufferA);
00153       Array1D<double> bVector(3, bufferB);
00154 
00155       AMatrix[0] = ray.getDirectionVector().x();
00156       AMatrix[3] = ray.getDirectionVector().y();
00157       AMatrix[6] = ray.getDirectionVector().z();
00158       AMatrix[1] = plane.getDirectionVector0().x();
00159       AMatrix[4] = plane.getDirectionVector0().y();
00160       AMatrix[7] = plane.getDirectionVector0().z();
00161       AMatrix[2] = plane.getDirectionVector1().x();
00162       AMatrix[5] = plane.getDirectionVector1().y();
00163       AMatrix[8] = plane.getDirectionVector1().z();
00164 
00165       bVector[0] = plane.getOrigin().x() - ray.getOrigin().x();
00166       bVector[1] = plane.getOrigin().y() - ray.getOrigin().y();
00167       bVector[2] = plane.getOrigin().z() - ray.getOrigin().z();
00168 
00169       try {
00170         linearSolveInPlace(AMatrix, bVector);
00171       } catch(const ValueException&) {
00172         std::ostringstream message;
00173         message << "Unable to find intersection of " << ray << " with "
00174                 << plane << ".  Perhaps the ray is parallel to the plane.";
00175         DLR_THROW(ValueException, "findIntersect()", message.str().c_str());
00176       }
00177       
00178       distance = bVector[0];
00179       return ray.getOrigin() + distance * ray.getDirectionVector();
00180     }
00181      
00182 
00183     numeric::Vector3D
00184     findIntersect(const Ray3D& ray0, const Ray3D& ray1,
00185                   double& distance0, double& distance1, double& residual)
00186     {
00187       Array2D<double> AMatrix(3, 2);
00188       AMatrix(0, 0) = ray0.getDirectionVector().x();
00189       AMatrix(1, 0) = ray0.getDirectionVector().y();
00190       AMatrix(2, 0) = ray0.getDirectionVector().z();
00191       AMatrix(0, 1) = -ray1.getDirectionVector().x();
00192       AMatrix(1, 1) = -ray1.getDirectionVector().y();
00193       AMatrix(2, 1) = -ray1.getDirectionVector().z();
00194 
00195       Array1D<double> bVector(3);
00196       bVector[0] = ray1.getOrigin().x() - ray0.getOrigin().x();
00197       bVector[1] = ray1.getOrigin().y() - ray0.getOrigin().y();
00198       bVector[2] = ray1.getOrigin().z() - ray0.getOrigin().z();
00199 
00200       Array2D<double> APinv;
00201       try {
00202         APinv = linearAlgebra::pseudoinverse(AMatrix);
00203       } catch(ValueException const&) {
00204         DLR_THROW(ValueException, "findIntersect()",
00205                   "Trouble inverting matrix.  "
00206                   "Input rays must not be parallel. ");
00207       }
00208       Array1D<double> parameters = matrixMultiply(APinv, bVector);
00209 
00210       distance0 = parameters[0];
00211       distance1 = parameters[1];
00212       Vector3D point0 =
00213         ray0.getOrigin() + distance0 * ray0.getDirectionVector();
00214       Vector3D point1 =
00215         ray1.getOrigin() + distance1 * ray1.getDirectionVector();
00216       residual = magnitude(point1 - point0) / 2.0;
00217       return 0.5 * (point0 + point1);
00218     }
00219     
00220 
00221     Plane3D
00222     operator*(const numeric::Transform3D& transform,
00223               const Plane3D& inputPlane)
00224     {
00225       Vector3D newOrigin = transform * inputPlane.getOrigin();
00226       Vector3D newEndPoint0 =
00227         transform * (inputPlane.getOrigin() + inputPlane.getDirectionVector0());
00228       Vector3D newEndPoint1 =
00229         transform * (inputPlane.getOrigin() + inputPlane.getDirectionVector1());
00230       return Plane3D(newOrigin, newEndPoint0, newEndPoint1);
00231     }
00232 
00233 
00234     Ray3D
00235     operator*(const numeric::Transform3D& transform,
00236               const Ray3D& inputRay)
00237     {
00238       Vector3D newOrigin = transform * inputRay.getOrigin();
00239       Vector3D newEndpoint =
00240         transform * (inputRay.getOrigin() + inputRay.getDirectionVector());
00241       return Ray3D(newOrigin, newEndpoint - newOrigin, false);
00242     }
00243     
00244     
00245     Triangle3D
00246     operator*(const numeric::Transform3D& transform,
00247               const Triangle3D& inputTriangle)
00248     {
00249       Vector3D newVertex0 = transform * inputTriangle.getVertex0();
00250       Vector3D newVertex1 = transform * inputTriangle.getVertex1();
00251       Vector3D newVertex2 = transform * inputTriangle.getVertex2();
00252       return Triangle3D(newVertex0, newVertex1, newVertex2);
00253     }
00254 
00255 
00256   } // namespace utilities
00257     
00258 } // namespace dlr

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