Real DistTriangle3Rectangle3<Real>::GetSquared () { // Compare edges of triangle to the interior of rectangle. Real sqrDist = Math<Real>::MAX_REAL, sqrDistTmp; Segment3<Real> edge; int i0, i1; for (i0 = 2, i1 = 0; i1 < 3; i0 = i1++) { edge.Center = ((Real)0.5)*(mTriangle->V[i0] + mTriangle->V[i1]); edge.Direction = mTriangle->V[i1] - mTriangle->V[i0]; edge.Extent = ((Real)0.5)*edge.Direction.Normalize(); edge.ComputeEndPoints(); DistSegment3Rectangle3<Real> querySR(edge, *mRectangle); sqrDistTmp = querySR.GetSquared(); if (sqrDistTmp < sqrDist) { // The triangle point is reported in mClosestPoint0 and the // rectangle point is reported in mClosestPoint1. The querySR // calculator is for triangleEdge-rectangle, so GetClosestPoint0() // and GetClosestPoint1() must be called as listed next. mClosestPoint0 = querySR.GetClosestPoint0(); mClosestPoint1 = querySR.GetClosestPoint1(); sqrDist = sqrDistTmp; } } // Compare edges of rectangle to the interior of triangle. for (i1 = 0; i1 < 2; ++i1) { for (i0 = -1; i0 <= 1; i0 += 2) { edge.Center = mRectangle->Center + (i0*mRectangle->Extent[1-i1]) * mRectangle->Axis[1-i1]; edge.Direction = mRectangle->Axis[i1]; edge.Extent = mRectangle->Extent[i1]; edge.ComputeEndPoints(); DistSegment3Triangle3<Real> queryST(edge, *mTriangle); sqrDistTmp = queryST.GetSquared(); if (sqrDistTmp < sqrDist) { // The triangle point is reported in mClosestPoint0 and the // rectangle point is reported in mClosestPoint1. The queryST // calculator is for rectangleEdge-triangle, so // GetClosestPoint1() and GetClosestPoint0() must be called as // listed next. mClosestPoint0 = queryST.GetClosestPoint1(); mClosestPoint1 = queryST.GetClosestPoint0(); sqrDist = sqrDistTmp; } } } return sqrDist; }
Real DistRectangle3Rectangle3<Real>::GetSquared () { // Compare edges of rectangle0 to the interior of rectangle1. Real sqrDist = Math<Real>::MAX_REAL, sqrDistTmp; Segment3<Real> edge; int i0, i1; for (i1 = 0; i1 < 2; ++i1) { for (i0 = -1; i0 <= 1; i0 += 2) { edge.Center = mRectangle0->Center + (i0*mRectangle0->Extent[1-i1]) * mRectangle0->Axis[1-i1]; edge.Direction = mRectangle0->Axis[i1]; edge.Extent = mRectangle0->Extent[i1]; edge.ComputeEndPoints(); DistSegment3Rectangle3<Real> querySR(edge, *mRectangle1); sqrDistTmp = querySR.GetSquared(); if (sqrDistTmp < sqrDist) { mClosestPoint0 = querySR.GetClosestPoint0(); mClosestPoint1 = querySR.GetClosestPoint1(); sqrDist = sqrDistTmp; } } } // Compare edges of rectangle1 to the interior of rectangle0. for (i1 = 0; i1 < 2; ++i1) { for (i0 = -1; i0 <= 1; i0 += 2) { edge.Center = mRectangle1->Center + (i0*mRectangle1->Extent[1-i1]) * mRectangle1->Axis[1-i1]; edge.Direction = mRectangle1->Axis[i1]; edge.Extent = mRectangle1->Extent[i1]; edge.ComputeEndPoints(); DistSegment3Rectangle3<Real> querySR(edge, *mRectangle0); sqrDistTmp = querySR.GetSquared(); if (sqrDistTmp < sqrDist) { mClosestPoint0 = querySR.GetClosestPoint0(); mClosestPoint1 = querySR.GetClosestPoint1(); sqrDist = sqrDistTmp; } } } return sqrDist; }
Real DistTriangle3Triangle3<Real>::GetSquared () { // Compare edges of triangle0 to the interior of triangle1. Real sqrDist = Math<Real>::MAX_REAL, sqrDistTmp; Segment3<Real> edge; Real ratio; int i0, i1; for (i0 = 2, i1 = 0; i1 < 3; i0 = i1++) { edge.Center = ((Real)0.5)*(mTriangle0->V[i0] + mTriangle0->V[i1]); edge.Direction = mTriangle0->V[i1] - mTriangle0->V[i0]; edge.Extent = ((Real)0.5)*edge.Direction.Normalize(); edge.ComputeEndPoints(); DistSegment3Triangle3<Real> queryST(edge, *mTriangle1); sqrDistTmp = queryST.GetSquared(); if (sqrDistTmp < sqrDist) { mClosestPoint0 = queryST.GetClosestPoint0(); mClosestPoint1 = queryST.GetClosestPoint1(); sqrDist = sqrDistTmp; ratio = queryST.GetSegmentParameter()/edge.Extent; mTriangleBary0[i0] = ((Real)0.5)*((Real)1 - ratio); mTriangleBary0[i1] = (Real)1 - mTriangleBary0[i0]; mTriangleBary0[3-i0-i1] = (Real)0; mTriangleBary1[0] = queryST.GetTriangleBary(0); mTriangleBary1[1] = queryST.GetTriangleBary(1); mTriangleBary1[2] = queryST.GetTriangleBary(2); if (sqrDist <= Math<Real>::ZERO_TOLERANCE) { return (Real)0; } } } // Compare edges of triangle1 to the interior of triangle0. for (i0 = 2, i1 = 0; i1 < 3; i0 = i1++) { edge.Center = ((Real)0.5)*(mTriangle1->V[i0] + mTriangle1->V[i1]); edge.Direction = mTriangle1->V[i1] - mTriangle1->V[i0]; edge.Extent = ((Real)0.5)*edge.Direction.Normalize(); edge.ComputeEndPoints(); DistSegment3Triangle3<Real> queryST(edge, *mTriangle0); sqrDistTmp = queryST.GetSquared(); if (sqrDistTmp < sqrDist) { mClosestPoint0 = queryST.GetClosestPoint0(); mClosestPoint1 = queryST.GetClosestPoint1(); sqrDist = sqrDistTmp; ratio = queryST.GetSegmentParameter()/edge.Extent; mTriangleBary1[i0] = ((Real)0.5)*((Real)1 - ratio); mTriangleBary1[i1] = (Real)1 - mTriangleBary1[i0]; mTriangleBary1[3-i0-i1] = (Real)0; mTriangleBary0[0] = queryST.GetTriangleBary(0); mTriangleBary0[1] = queryST.GetTriangleBary(1); mTriangleBary0[2] = queryST.GetTriangleBary(2); if (sqrDist <= Math<Real>::ZERO_TOLERANCE) { return (Real)0; } } } return sqrDist; }
Real DistLine3Rectangle3<Real>::GetSquared () { // Test if line intersects rectangle. If so, the squared distance is // zero. Vector3<Real> N = mRectangle->Axis[0].Cross( mRectangle->Axis[1] ); Real NdD = N.Dot( mLine->Direction ); if ( Math<Real>::FAbs( NdD ) > Math<Real>::ZERO_TOLERANCE ) { // The line and rectangle are not parallel, so the line intersects // the plane of the rectangle. Vector3<Real> diff = mLine->Origin - mRectangle->Center; Vector3<Real> U, V; Vector3<Real>::GenerateComplementBasis( U, V, mLine->Direction ); Real UdD0 = U.Dot( mRectangle->Axis[0] ); Real UdD1 = U.Dot( mRectangle->Axis[1] ); Real UdPmC = U.Dot( diff ); Real VdD0 = V.Dot( mRectangle->Axis[0] ); Real VdD1 = V.Dot( mRectangle->Axis[1] ); Real VdPmC = V.Dot( diff ); Real invDet = ( ( Real )1 ) / ( UdD0 * VdD1 - UdD1 * VdD0 ); // Rectangle coordinates for the point of intersection. Real s0 = ( VdD1 * UdPmC - UdD1 * VdPmC ) * invDet; Real s1 = ( UdD0 * VdPmC - VdD0 * UdPmC ) * invDet; if ( Math<Real>::FAbs( s0 ) <= mRectangle->Extent[0] && Math<Real>::FAbs( s1 ) <= mRectangle->Extent[1] ) { // Line parameter for the point of intersection. Real DdD0 = mLine->Direction.Dot( mRectangle->Axis[0] ); Real DdD1 = mLine->Direction.Dot( mRectangle->Axis[1] ); Real DdDiff = mLine->Direction.Dot( diff ); mLineParameter = s0 * DdD0 + s1 * DdD1 - DdDiff; // Rectangle coordinates for the point of intersection. mRectCoord[0] = s0; mRectCoord[1] = s1; // The intersection point is inside or on the rectangle. mClosestPoint0 = mLine->Origin + mLineParameter * mLine->Direction; mClosestPoint1 = mRectangle->Center + s0 * mRectangle->Axis[0] + s1 * mRectangle->Axis[1]; return ( Real )0; } } // Either (1) the line is not parallel to the rectangle and the point of // intersection of the line and the plane of the rectangle is outside the // rectangle or (2) the line and rectangle are parallel. Regardless, the // closest point on the rectangle is on an edge of the rectangle. Compare // the line to all four edges of the rectangle. Real sqrDist = Math<Real>::MAX_REAL; Vector3<Real> scaledDir[2] = { mRectangle->Extent[0]* mRectangle->Axis[0], mRectangle->Extent[1]* mRectangle->Axis[1] }; for ( int i1 = 0; i1 < 2; ++i1 ) { for ( int i0 = 0; i0 < 2; ++i0 ) { Segment3<Real> segment; segment.Center = mRectangle->Center + ( ( Real )( 2 * i0 - 1 ) ) * scaledDir[i1]; segment.Direction = mRectangle->Axis[1 - i1]; segment.Extent = mRectangle->Extent[1 - i1]; segment.ComputeEndPoints(); DistLine3Segment3<Real> queryLS( *mLine, segment ); Real sqrDistTmp = queryLS.GetSquared(); if ( sqrDistTmp < sqrDist ) { mClosestPoint0 = queryLS.GetClosestPoint0(); mClosestPoint1 = queryLS.GetClosestPoint1(); sqrDist = sqrDistTmp; mLineParameter = queryLS.GetLineParameter(); Real ratio = queryLS.GetSegmentParameter() / segment.Extent; mRectCoord[0] = mRectangle->Extent[0] * ( ( 1 - i1 ) * ( 2 * i0 - 1 ) + i1 * ratio ); mRectCoord[1] = mRectangle->Extent[1] * ( ( 1 - i0 ) * ( 2 * i1 - 1 ) + i0 * ratio ); } } } return sqrDist; }
Real DistLine3Triangle3<Real>::GetSquared () { // Test if line intersects triangle. If so, the squared distance is zero. Vector3<Real> edge0 = mTriangle->V[1] - mTriangle->V[0]; Vector3<Real> edge1 = mTriangle->V[2] - mTriangle->V[0]; Vector3<Real> normal = edge0.UnitCross(edge1); Real NdD = normal.Dot(mLine->Direction); if (Math<Real>::FAbs(NdD) > Math<Real>::ZERO_TOLERANCE) { // The line and triangle are not parallel, so the line intersects // the plane of the triangle. Vector3<Real> diff = mLine->Origin - mTriangle->V[0]; Vector3<Real> U, V; Vector3<Real>::GenerateComplementBasis(U, V, mLine->Direction); Real UdE0 = U.Dot(edge0); Real UdE1 = U.Dot(edge1); Real UdDiff = U.Dot(diff); Real VdE0 = V.Dot(edge0); Real VdE1 = V.Dot(edge1); Real VdDiff = V.Dot(diff); Real invDet = ((Real)1)/(UdE0*VdE1 - UdE1*VdE0); // Barycentric coordinates for the point of intersection. Real b1 = (VdE1*UdDiff - UdE1*VdDiff)*invDet; Real b2 = (UdE0*VdDiff - VdE0*UdDiff)*invDet; Real b0 = (Real)1 - b1 - b2; if (b0 >= (Real)0 && b1 >= (Real)0 && b2 >= (Real)0) { // Line parameter for the point of intersection. Real DdE0 = mLine->Direction.Dot(edge0); Real DdE1 = mLine->Direction.Dot(edge1); Real DdDiff = mLine->Direction.Dot(diff); mLineParameter = b1*DdE0 + b2*DdE1 - DdDiff; // Barycentric coordinates for the point of intersection. mTriangleBary[0] = b0; mTriangleBary[1] = b1; mTriangleBary[2] = b2; // The intersection point is inside or on the triangle. mClosestPoint0 = mLine->Origin + mLineParameter*mLine->Direction; mClosestPoint1 = mTriangle->V[0] + b1*edge0 + b2*edge1; return (Real)0; } } // Either (1) the line is not parallel to the triangle and the point of // intersection of the line and the plane of the triangle is outside the // triangle or (2) the line and triangle are parallel. Regardless, the // closest point on the triangle is on an edge of the triangle. Compare // the line to all three edges of the triangle. Real sqrDist = Math<Real>::MAX_REAL; for (int i0 = 2, i1 = 0; i1 < 3; i0 = i1++) { Segment3<Real> segment; segment.Center = ((Real)0.5)*(mTriangle->V[i0] + mTriangle->V[i1]); segment.Direction = mTriangle->V[i1] - mTriangle->V[i0]; segment.Extent = ((Real)0.5)*segment.Direction.Normalize(); segment.ComputeEndPoints(); DistLine3Segment3<Real> queryLS(*mLine, segment); Real sqrDistTmp = queryLS.GetSquared(); if (sqrDistTmp < sqrDist) { mClosestPoint0 = queryLS.GetClosestPoint0(); mClosestPoint1 = queryLS.GetClosestPoint1(); sqrDist = sqrDistTmp; mLineParameter = queryLS.GetLineParameter(); Real ratio = queryLS.GetSegmentParameter()/segment.Extent; mTriangleBary[i0] = ((Real)0.5)*((Real)1 - ratio); mTriangleBary[i1] = (Real)1 - mTriangleBary[i0]; mTriangleBary[3-i0-i1] = (Real)0; } } return sqrDist; }