| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include "Wm4FoundationPCH.h" |
| | #include "Wm4ContBox3.h" |
| | #include "Wm4ApprGaussPointsFit3.h" |
| | #include "Wm4ContBox2.h" |
| | #include "Wm4ConvexHull3.h" |
| | #include "Wm4EdgeKey.h" |
| | #include "Wm4Quaternion.h" |
| |
|
| | namespace Wm4 |
| | { |
| | |
| | template <class Real> |
| | Box3<Real> ContAlignedBox (int iQuantity, const Vector3<Real>* akPoint) |
| | { |
| | Vector3<Real> kMin, kMax; |
| | Vector3<Real>::ComputeExtremes(iQuantity,akPoint,kMin,kMax); |
| |
|
| | Box3<Real> kBox; |
| | kBox.Center = ((Real)0.5)*(kMin + kMax); |
| | kBox.Axis[0] = Vector3<Real>::UNIT_X; |
| | kBox.Axis[1] = Vector3<Real>::UNIT_Y; |
| | kBox.Axis[2] = Vector3<Real>::UNIT_Z; |
| | Vector3<Real> kHalfDiagonal = ((Real)0.5)*(kMax - kMin); |
| | for (int i = 0; i < 3; i++) |
| | { |
| | kBox.Extent[i] = kHalfDiagonal[i]; |
| | } |
| |
|
| | return kBox; |
| | } |
| | |
| | template <class Real> |
| | Box3<Real> ContOrientedBox (int iQuantity, const Vector3<Real>* akPoint) |
| | { |
| | Box3<Real> kBox = GaussPointsFit3<Real>(iQuantity,akPoint); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | Vector3<Real> kDiff = akPoint[0] - kBox.Center; |
| | Vector3<Real> kMin(kDiff.Dot(kBox.Axis[0]),kDiff.Dot(kBox.Axis[1]), |
| | kDiff.Dot(kBox.Axis[2])); |
| | Vector3<Real> kMax = kMin; |
| | for (int i = 1; i < iQuantity; i++) |
| | { |
| | kDiff = akPoint[i] - kBox.Center; |
| | for (int j = 0; j < 3; j++) |
| | { |
| | Real fDot = kDiff.Dot(kBox.Axis[j]); |
| | if (fDot < kMin[j]) |
| | { |
| | kMin[j] = fDot; |
| | } |
| | else if (fDot > kMax[j]) |
| | { |
| | kMax[j] = fDot; |
| | } |
| | } |
| | } |
| |
|
| | kBox.Center += |
| | (((Real)0.5)*(kMin[0]+kMax[0]))*kBox.Axis[0] + |
| | (((Real)0.5)*(kMin[1]+kMax[1]))*kBox.Axis[1] + |
| | (((Real)0.5)*(kMin[2]+kMax[2]))*kBox.Axis[2]; |
| |
|
| | kBox.Extent[0] = ((Real)0.5)*(kMax[0] - kMin[0]); |
| | kBox.Extent[1] = ((Real)0.5)*(kMax[1] - kMin[1]); |
| | kBox.Extent[2] = ((Real)0.5)*(kMax[2] - kMin[2]); |
| |
|
| | return kBox; |
| | } |
| | |
| | template <class Real> |
| | Box3<Real> ContMinBox (int iQuantity, const Vector3<Real>* akPoint, |
| | Real fEpsilon, Query::Type eQueryType) |
| | { |
| | Box3<Real> kBox; |
| |
|
| | |
| | ConvexHull3<Real> kHull(iQuantity,(Vector3<Real>*)akPoint,fEpsilon,false, |
| | eQueryType); |
| | int iHDim = kHull.GetDimension(); |
| | int iHQuantity; |
| | const int* aiHIndex; |
| |
|
| | if (iHDim == 0) |
| | { |
| | kBox.Center = akPoint[0]; |
| | kBox.Axis[0] = Vector3<Real>::UNIT_X; |
| | kBox.Axis[1] = Vector3<Real>::UNIT_Y; |
| | kBox.Axis[2] = Vector3<Real>::UNIT_Z; |
| | kBox.Extent[0] = (Real)0.0; |
| | kBox.Extent[1] = (Real)0.0; |
| | kBox.Extent[2] = (Real)0.0; |
| | return kBox; |
| | } |
| |
|
| | if (iHDim == 1) |
| | { |
| | ConvexHull1<Real>* pkHull1 = kHull.GetConvexHull1(); |
| | aiHIndex = pkHull1->GetIndices(); |
| |
|
| | kBox.Center = ((Real)0.5)*(akPoint[aiHIndex[0]]+akPoint[aiHIndex[1]]); |
| | Vector3<Real> kDiff = akPoint[aiHIndex[1]] - akPoint[aiHIndex[0]]; |
| | kBox.Extent[0] = ((Real)0.5)*kDiff.Normalize(); |
| | kBox.Extent[1] = (Real)0.0; |
| | kBox.Extent[2] = (Real)0.0; |
| | kBox.Axis[0] = kDiff; |
| | Vector3<Real>::GenerateComplementBasis(kBox.Axis[1],kBox.Axis[2], |
| | kBox.Axis[0]); |
| |
|
| | WM4_DELETE pkHull1; |
| | return kBox; |
| | } |
| |
|
| | int i, j; |
| | Vector3<Real> kOrigin, kDiff, kU, kV, kW; |
| | Vector2<Real>* akPoint2; |
| | Box2<Real> kBox2; |
| |
|
| | if (iHDim == 2) |
| | { |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | kOrigin = kHull.GetPlaneOrigin(); |
| | kW = kHull.GetPlaneDirection(0).Cross(kHull.GetPlaneDirection(1)); |
| | Vector3<Real>::GenerateComplementBasis(kU,kV,kW); |
| |
|
| | |
| | akPoint2 = WM4_NEW Vector2<Real>[iQuantity]; |
| | for (i = 0; i < iQuantity; i++) |
| | { |
| | kDiff = akPoint[i] - kOrigin; |
| | akPoint2[i].X() = kU.Dot(kDiff); |
| | akPoint2[i].Y() = kV.Dot(kDiff); |
| | } |
| |
|
| | |
| | kBox2 = ContMinBox<Real>(iQuantity,akPoint2,fEpsilon,eQueryType, |
| | false); |
| | WM4_DELETE[] akPoint2; |
| |
|
| | |
| | kBox.Center = kOrigin + kBox2.Center.X()*kU + kBox2.Center.Y()*kV; |
| | kBox.Axis[0] = kBox2.Axis[0].X()*kU + kBox2.Axis[0].Y()*kV; |
| | kBox.Axis[1] = kBox2.Axis[1].X()*kU + kBox2.Axis[1].Y()*kV; |
| | kBox.Axis[2] = kW; |
| | kBox.Extent[0] = kBox2.Extent[0]; |
| | kBox.Extent[1] = kBox2.Extent[1]; |
| | kBox.Extent[2] = (Real)0.0; |
| | return kBox; |
| | } |
| |
|
| | iHQuantity = kHull.GetSimplexQuantity(); |
| | aiHIndex = kHull.GetIndices(); |
| | Real fVolume, fMinVolume = Math<Real>::MAX_REAL; |
| |
|
| | |
| | |
| | std::set<int> kUniqueIndices; |
| | for (i = 0; i < 3*iHQuantity; i++) |
| | { |
| | kUniqueIndices.insert(aiHIndex[i]); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | const int* piIndex = aiHIndex; |
| | Real fHeight, fMinHeight, fMaxHeight; |
| | std::set<EdgeKey> kEdges; |
| | akPoint2 = WM4_NEW Vector2<Real>[kUniqueIndices.size()]; |
| | for (i = 0; i < iHQuantity; i++) |
| | { |
| | |
| | int iV0 = *piIndex++; |
| | int iV1 = *piIndex++; |
| | int iV2 = *piIndex++; |
| |
|
| | |
| | kEdges.insert(EdgeKey(iV0,iV1)); |
| | kEdges.insert(EdgeKey(iV1,iV2)); |
| | kEdges.insert(EdgeKey(iV2,iV0)); |
| |
|
| | |
| | kOrigin = (akPoint[iV0] + akPoint[iV1] + akPoint[iV2])/(Real)3.0; |
| | Vector3<Real> kEdge1 = akPoint[iV1] - akPoint[iV0]; |
| | Vector3<Real> kEdge2 = akPoint[iV2] - akPoint[iV0]; |
| | kW = kEdge2.UnitCross(kEdge1); |
| | if (kW == Vector3<Real>::ZERO) |
| | { |
| | |
| | continue; |
| | } |
| | Vector3<Real>::GenerateComplementBasis(kU,kV,kW); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | fMinHeight = (Real)0.0; |
| | fMaxHeight = (Real)0.0; |
| | j = 0; |
| | std::set<int>::const_iterator pkUI = kUniqueIndices.begin(); |
| | while (pkUI != kUniqueIndices.end()) |
| | { |
| | int index = *pkUI++; |
| | kDiff = akPoint[index] - kOrigin; |
| | akPoint2[j].X() = kU.Dot(kDiff); |
| | akPoint2[j].Y() = kV.Dot(kDiff); |
| | fHeight = kW.Dot(kDiff); |
| | if (fHeight > fMaxHeight) |
| | { |
| | fMaxHeight = fHeight; |
| | } |
| | else if (fHeight < fMinHeight) |
| | { |
| | fMinHeight = fHeight; |
| | } |
| |
|
| | j++; |
| | } |
| | if (-fMinHeight > fMaxHeight) |
| | { |
| | fMaxHeight = -fMinHeight; |
| | } |
| |
|
| | |
| | kBox2 = ContMinBox<Real>((int)kUniqueIndices.size(),akPoint2,fEpsilon, |
| | eQueryType,false); |
| |
|
| | |
| | fVolume = fMaxHeight*kBox2.Extent[0]*kBox2.Extent[1]; |
| | if (fVolume < fMinVolume) |
| | { |
| | fMinVolume = fVolume; |
| |
|
| | |
| | kBox.Extent[0] = kBox2.Extent[0]; |
| | kBox.Extent[1] = kBox2.Extent[1]; |
| | kBox.Extent[2] = ((Real)0.5)*fMaxHeight; |
| | kBox.Axis[0] = kBox2.Axis[0].X()*kU + kBox2.Axis[0].Y()*kV; |
| | kBox.Axis[1] = kBox2.Axis[1].X()*kU + kBox2.Axis[1].Y()*kV; |
| | kBox.Axis[2] = kW; |
| | kBox.Center = kOrigin + kBox2.Center.X()*kU + kBox2.Center.Y()*kV |
| | + kBox.Extent[2]*kW; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | std::set<EdgeKey>::const_iterator pkE2; |
| | for (pkE2 = kEdges.begin(); pkE2 != kEdges.end(); pkE2++) |
| | { |
| | kW = akPoint[pkE2->V[1]] - akPoint[pkE2->V[0]]; |
| | kW.Normalize(); |
| |
|
| | std::set<EdgeKey>::const_iterator pkE1 = pkE2; |
| | for (++pkE1; pkE1 != kEdges.end(); pkE1++) |
| | { |
| | kV = akPoint[pkE1->V[1]] - akPoint[pkE1->V[0]]; |
| | kV.Normalize(); |
| | Real fDot = kV.Dot(kW); |
| | if (Math<Real>::FAbs(fDot) > Math<Real>::ZERO_TOLERANCE) |
| | { |
| | continue; |
| | } |
| |
|
| | std::set<EdgeKey>::const_iterator pkE0 = pkE1; |
| | for (++pkE0; pkE0 != kEdges.end(); pkE0++) |
| | { |
| | kU = akPoint[pkE0->V[1]] - akPoint[pkE0->V[0]]; |
| | kU.Normalize(); |
| | fDot = kU.Dot(kV); |
| | if (Math<Real>::FAbs(fDot) > Math<Real>::ZERO_TOLERANCE) |
| | { |
| | continue; |
| | } |
| | fDot = kU.Dot(kW); |
| | if (Math<Real>::FAbs(fDot) > Math<Real>::ZERO_TOLERANCE) |
| | { |
| | continue; |
| | } |
| | |
| | |
| | |
| | |
| | Real fUMin = (Real)0.0, fUMax = (Real)0.0; |
| | Real fVMin = (Real)0.0, fVMax = (Real)0.0; |
| | Real fWMin = (Real)0.0, fWMax = (Real)0.0; |
| | kOrigin = akPoint[aiHIndex[0]]; |
| | std::set<int>::const_iterator pkUI = kUniqueIndices.begin(); |
| | while (pkUI != kUniqueIndices.end()) |
| | { |
| | int index = *pkUI++; |
| | kDiff = akPoint[index] - kOrigin; |
| |
|
| | Real fU = kU.Dot(kDiff); |
| | if (fU < fUMin) |
| | { |
| | fUMin = fU; |
| | } |
| | else if (fU > fUMax) |
| | { |
| | fUMax = fU; |
| | } |
| |
|
| | Real fV = kV.Dot(kDiff); |
| | if (fV < fVMin) |
| | { |
| | fVMin = fV; |
| | } |
| | else if (fV > fVMax) |
| | { |
| | fVMax = fV; |
| | } |
| |
|
| | Real fW = kW.Dot(kDiff); |
| | if (fW < fWMin) |
| | { |
| | fWMin = fW; |
| | } |
| | else if (fW > fWMax) |
| | { |
| | fWMax = fW; |
| | } |
| | } |
| |
|
| | Real fUExtent = ((Real)0.5)*(fUMax - fUMin); |
| | Real fVExtent = ((Real)0.5)*(fVMax - fVMin); |
| | Real fWExtent = ((Real)0.5)*(fWMax - fWMin); |
| |
|
| | |
| | fVolume = fUExtent*fVExtent*fWExtent; |
| | if (fVolume < fMinVolume) |
| | { |
| | fMinVolume = fVolume; |
| |
|
| | kBox.Extent[0] = fUExtent; |
| | kBox.Extent[1] = fVExtent; |
| | kBox.Extent[2] = fWExtent; |
| | kBox.Axis[0] = kU; |
| | kBox.Axis[1] = kV; |
| | kBox.Axis[2] = kW; |
| | kBox.Center = kOrigin + |
| | ((Real)0.5)*(fUMin+fUMax)*kU + |
| | ((Real)0.5)*(fVMin+fVMax)*kV + |
| | ((Real)0.5)*(fWMin+fWMax)*kW; |
| | } |
| | } |
| | } |
| | } |
| |
|
| | WM4_DELETE[] akPoint2; |
| | return kBox; |
| | } |
| | |
| | template <class Real> |
| | bool InBox (const Vector3<Real>& rkPoint, const Box3<Real>& rkBox) |
| | { |
| | Vector3<Real> kDiff = rkPoint - rkBox.Center; |
| | for (int i = 0; i < 3; i++) |
| | { |
| | Real fCoeff = kDiff.Dot(rkBox.Axis[i]); |
| | if (Math<Real>::FAbs(fCoeff) > rkBox.Extent[i]) |
| | { |
| | return false; |
| | } |
| | } |
| | return true; |
| | } |
| | |
| | template <class Real> |
| | Box3<Real> MergeBoxes (const Box3<Real>& rkBox0, const Box3<Real>& rkBox1) |
| | { |
| | |
| | Box3<Real> kBox; |
| |
|
| | |
| | |
| | |
| | kBox.Center = ((Real)0.5)*(rkBox0.Center + rkBox1.Center); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | Quaternion<Real> kQ0, kQ1; |
| | kQ0.FromRotationMatrix(rkBox0.Axis); |
| | kQ1.FromRotationMatrix(rkBox1.Axis); |
| | if (kQ0.Dot(kQ1) < (Real)0.0) |
| | { |
| | kQ1 = -kQ1; |
| | } |
| |
|
| | Quaternion<Real> kQ = kQ0 + kQ1; |
| | Real fInvLength = Math<Real>::InvSqrt(kQ.Dot(kQ)); |
| | kQ = fInvLength*kQ; |
| | kQ.ToRotationMatrix(kBox.Axis); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | int i, j; |
| | Real fDot; |
| | Vector3<Real> akVertex[8], kDiff; |
| | Vector3<Real> kMin = Vector3<Real>::ZERO; |
| | Vector3<Real> kMax = Vector3<Real>::ZERO; |
| |
|
| | rkBox0.ComputeVertices(akVertex); |
| | for (i = 0; i < 8; i++) |
| | { |
| | kDiff = akVertex[i] - kBox.Center; |
| | for (j = 0; j < 3; j++) |
| | { |
| | fDot = kDiff.Dot(kBox.Axis[j]); |
| | if (fDot > kMax[j]) |
| | { |
| | kMax[j] = fDot; |
| | } |
| | else if (fDot < kMin[j]) |
| | { |
| | kMin[j] = fDot; |
| | } |
| | } |
| | } |
| |
|
| | rkBox1.ComputeVertices(akVertex); |
| | for (i = 0; i < 8; i++) |
| | { |
| | kDiff = akVertex[i] - kBox.Center; |
| | for (j = 0; j < 3; j++) |
| | { |
| | fDot = kDiff.Dot(kBox.Axis[j]); |
| | if (fDot > kMax[j]) |
| | { |
| | kMax[j] = fDot; |
| | } |
| | else if (fDot < kMin[j]) |
| | { |
| | kMin[j] = fDot; |
| | } |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | for (j = 0; j < 3; j++) |
| | { |
| | kBox.Center += (((Real)0.5)*(kMax[j]+kMin[j]))*kBox.Axis[j]; |
| | kBox.Extent[j] = ((Real)0.5)*(kMax[j]-kMin[j]); |
| | } |
| |
|
| | return kBox; |
| | } |
| | |
| |
|
| | |
| | |
| | |
| | template WM4_FOUNDATION_ITEM |
| | Box3<float> ContAlignedBox<float> (int, const Vector3<float>*); |
| |
|
| | template WM4_FOUNDATION_ITEM |
| | Box3<float> ContOrientedBox<float> (int, const Vector3<float>*); |
| |
|
| | template WM4_FOUNDATION_ITEM |
| | Box3<float> ContMinBox<float> (int, const Vector3<float>*, float, |
| | Query::Type); |
| |
|
| | template WM4_FOUNDATION_ITEM |
| | bool InBox<float> (const Vector3<float>&, const Box3<float>&); |
| |
|
| | template WM4_FOUNDATION_ITEM |
| | Box3<float> MergeBoxes<float> (const Box3<float>&, const Box3<float>&); |
| |
|
| | template WM4_FOUNDATION_ITEM |
| | Box3<double> ContAlignedBox<double> (int, const Vector3<double>*); |
| |
|
| | template WM4_FOUNDATION_ITEM |
| | Box3<double> ContOrientedBox<double> (int, const Vector3<double>*); |
| |
|
| | template WM4_FOUNDATION_ITEM |
| | Box3<double> ContMinBox<double> (int, const Vector3<double>*, double, |
| | Query::Type); |
| |
|
| | template WM4_FOUNDATION_ITEM |
| | bool InBox<double> (const Vector3<double>&, const Box3<double>&); |
| |
|
| | template WM4_FOUNDATION_ITEM |
| | Box3<double> MergeBoxes<double> (const Box3<double>&, const Box3<double>&); |
| | |
| | } |
| |
|