//---------------------------------------------------------------------------- bool Mgc::FindIntersection (const Segment3& rkSegment, const Box3& rkBox, int& riQuantity, Vector3 akPoint[2]) { // convert segment to box coordinates Vector3 kDiff = rkSegment.Origin() - rkBox.Center(); Vector3 kOrigin( kDiff.Dot(rkBox.Axis(0)), kDiff.Dot(rkBox.Axis(1)), kDiff.Dot(rkBox.Axis(2)) ); Vector3 kDirection( rkSegment.Direction().Dot(rkBox.Axis(0)), rkSegment.Direction().Dot(rkBox.Axis(1)), rkSegment.Direction().Dot(rkBox.Axis(2)) ); Real fT0 = 0.0f, fT1 = 1.0f; bool bIntersects = FindIntersection(kOrigin,kDirection,rkBox.Extents(), fT0,fT1); if ( bIntersects ) { if ( fT0 > 0.0f ) { if ( fT1 < 1.0f ) { riQuantity = 2; akPoint[0] = rkSegment.Origin() + fT0*rkSegment.Direction(); akPoint[1] = rkSegment.Origin() + fT1*rkSegment.Direction(); } else { riQuantity = 1; akPoint[0] = rkSegment.Origin() + fT0*rkSegment.Direction(); } } else // fT0 == 0 { if ( fT1 < 1.0f ) { riQuantity = 1; akPoint[0] = rkSegment.Origin() + fT1*rkSegment.Direction(); } else // fT1 == 1 { // segment entirely in box riQuantity = 0; } } } else { riQuantity = 0; } return bIntersects; }
Box3<Real> Wml::ContOrientedBox (int iQuantity, const Vector3<Real>* akPoint) { Box3<Real> kBox; GaussPointsFit(iQuantity,akPoint,kBox.Center(),kBox.Axes(), kBox.Extents()); // Let C be the box center and let U0, U1, and U2 be the box axes. Each // input point is of the form X = C + y0*U0 + y1*U1 + y2*U2. The // following code computes min(y0), max(y0), min(y1), max(y1), min(y2), // and max(y2). The box center is then adjusted to be // C' = C + 0.5*(min(y0)+max(y0))*U0 + 0.5*(min(y1)+max(y1))*U1 + // 0.5*(min(y2)+max(y2))*U2 Vector3<Real> kDiff = akPoint[0] - kBox.Center(); Real fY0Min = kDiff.Dot(kBox.Axis(0)), fY0Max = fY0Min; Real fY1Min = kDiff.Dot(kBox.Axis(1)), fY1Max = fY1Min; Real fY2Min = kDiff.Dot(kBox.Axis(2)), fY2Max = fY2Min; for (int i = 1; i < iQuantity; i++) { kDiff = akPoint[i] - kBox.Center(); Real fY0 = kDiff.Dot(kBox.Axis(0)); if ( fY0 < fY0Min ) fY0Min = fY0; else if ( fY0 > fY0Max ) fY0Max = fY0; Real fY1 = kDiff.Dot(kBox.Axis(1)); if ( fY1 < fY1Min ) fY1Min = fY1; else if ( fY1 > fY1Max ) fY1Max = fY1; Real fY2 = kDiff.Dot(kBox.Axis(2)); if ( fY2 < fY2Min ) fY2Min = fY2; else if ( fY2 > fY2Max ) fY2Max = fY2; } kBox.Center() += (((Real)0.5)*(fY0Min+fY0Max))*kBox.Axis(0) + (((Real)0.5)*(fY1Min+fY1Max))*kBox.Axis(1) + (((Real)0.5)*(fY2Min+fY2Max))*kBox.Axis(2); kBox.Extent(0) = ((Real)0.5)*(fY0Max - fY0Min); kBox.Extent(1) = ((Real)0.5)*(fY1Max - fY1Min); kBox.Extent(2) = ((Real)0.5)*(fY2Max - fY2Min); return kBox; }
//---------------------------------------------------------------------------- bool Mgc::FindIntersection (const Line3& rkLine, const Box3& rkBox, int& riQuantity, Vector3 akPoint[2]) { // convert line to box coordinates Vector3 kDiff = rkLine.Origin() - rkBox.Center(); Vector3 kOrigin( kDiff.Dot(rkBox.Axis(0)), kDiff.Dot(rkBox.Axis(1)), kDiff.Dot(rkBox.Axis(2)) ); Vector3 kDirection( rkLine.Direction().Dot(rkBox.Axis(0)), rkLine.Direction().Dot(rkBox.Axis(1)), rkLine.Direction().Dot(rkBox.Axis(2)) ); Real fT0 = -Math::MAX_REAL, fT1 = Math::MAX_REAL; bool bIntersects = FindIntersection(kOrigin,kDirection,rkBox.Extents(), fT0,fT1); if ( bIntersects ) { if ( fT0 != fT1 ) { riQuantity = 2; akPoint[0] = rkLine.Origin() + fT0*rkLine.Direction(); akPoint[1] = rkLine.Origin() + fT1*rkLine.Direction(); } else { riQuantity = 1; akPoint[0] = rkLine.Origin() + fT0*rkLine.Direction(); } } else { riQuantity = 0; } return bIntersects; }
bool Wml::ContOrientedBox (int iQuantity, const Vector3<Real>* akPoint, const bool* abValid, Box3<Real>& rkBox) { if ( !GaussPointsFit(iQuantity,akPoint,abValid,rkBox.Center(), rkBox.Axes(),rkBox.Extents()) ) { return false; } // Let C be the box center and let U0, U1, and U2 be the box axes. Each // input point is of the form X = C + y0*U0 + y1*U1 + y2*U2. The // following code computes min(y0), max(y0), min(y1), max(y1), min(y2), // and max(y2). The box center is then adjusted to be // C' = C + 0.5*(min(y0)+max(y0))*U0 + 0.5*(min(y1)+max(y1))*U1 + // 0.5*(min(y2)+max(y2))*U2 // get first valid vertex Vector3<Real> kDiff; Real fY0Min = (Real)0.0, fY0Max = (Real)0.0; Real fY1Min = (Real)0.0, fY1Max = (Real)0.0; Real fY2Min = (Real)0.0, fY2Max = (Real)0.0; int i; for (i = 0; i < iQuantity; i++) { if ( abValid[i] ) { kDiff = akPoint[i] - rkBox.Center(); fY0Min = kDiff.Dot(rkBox.Axis(0)); fY0Max = fY0Min; fY1Min = kDiff.Dot(rkBox.Axis(1)); fY1Max = fY1Min; fY2Min = kDiff.Dot(rkBox.Axis(2)); fY2Max = fY2Min; break; } } for (i++; i < iQuantity; i++) { if ( abValid[i] ) { kDiff = akPoint[i] - rkBox.Center(); Real fY0 = kDiff.Dot(rkBox.Axis(0)); if ( fY0 < fY0Min ) fY0Min = fY0; else if ( fY0 > fY0Max ) fY0Max = fY0; Real fY1 = kDiff.Dot(rkBox.Axis(1)); if ( fY1 < fY1Min ) fY1Min = fY1; else if ( fY1 > fY1Max ) fY1Max = fY1; Real fY2 = kDiff.Dot(rkBox.Axis(2)); if ( fY2 < fY2Min ) fY2Min = fY2; else if ( fY2 > fY2Max ) fY2Max = fY2; } } rkBox.Center() += (0.5f*(fY0Min+fY0Max))*rkBox.Axis(0) + (0.5f*(fY1Min+fY1Max))*rkBox.Axis(1) + (0.5f*(fY2Min+fY2Max))*rkBox.Axis(2); rkBox.Extent(0) = 0.5f*(fY0Max - fY0Min); rkBox.Extent(1) = 0.5f*(fY1Max - fY1Min); rkBox.Extent(2) = 0.5f*(fY2Max - fY2Min); return true; }