| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include "Wm4FoundationPCH.h" |
| | #include "Wm4ContBox2.h" |
| | #include "Wm4ApprGaussPointsFit2.h" |
| | #include "Wm4ConvexHull2.h" |
| |
|
| | namespace Wm4 |
| | { |
| | |
| | template <class Real> |
| | Box2<Real> ContAlignedBox (int iQuantity, const Vector2<Real>* akPoint) |
| | { |
| | Vector2<Real> kMin, kMax; |
| | Vector2<Real>::ComputeExtremes(iQuantity,akPoint,kMin,kMax); |
| |
|
| | Box2<Real> kBox; |
| | kBox.Center = ((Real)0.5)*(kMin + kMax); |
| | kBox.Axis[0] = Vector2<Real>::UNIT_X; |
| | kBox.Axis[1] = Vector2<Real>::UNIT_Y; |
| | Vector2<Real> kHalfDiagonal = ((Real)0.5)*(kMax - kMin); |
| | for (int i = 0; i < 2; i++) |
| | { |
| | kBox.Extent[i] = kHalfDiagonal[i]; |
| | } |
| |
|
| | return kBox; |
| | } |
| | |
| | template <class Real> |
| | Box2<Real> ContOrientedBox (int iQuantity, const Vector2<Real>* akPoint) |
| | { |
| | Box2<Real> kBox = GaussPointsFit2<Real>(iQuantity,akPoint); |
| |
|
| | |
| | |
| | |
| | |
| | |
| |
|
| | Vector2<Real> kDiff = akPoint[0] - kBox.Center; |
| | Vector2<Real> kMin(kDiff.Dot(kBox.Axis[0]),kDiff.Dot(kBox.Axis[1])); |
| | Vector2<Real> kMax = kMin; |
| | for (int i = 1; i < iQuantity; i++) |
| | { |
| | kDiff = akPoint[i] - kBox.Center; |
| | for (int j = 0; j < 2; 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]; |
| |
|
| | kBox.Extent[0] = ((Real)0.5)*(kMax[0] - kMin[0]); |
| | kBox.Extent[1] = ((Real)0.5)*(kMax[1] - kMin[1]); |
| |
|
| | return kBox; |
| | } |
| | |
| | template <class Real> |
| | static void UpdateBox (const Vector2<Real>& rkLPoint, |
| | const Vector2<Real>& rkRPoint, const Vector2<Real>& rkBPoint, |
| | const Vector2<Real>& rkTPoint, const Vector2<Real>& rkU, |
| | const Vector2<Real>& rkV, Real& rfMinAreaDiv4, Box2<Real>& rkBox) |
| | { |
| | Vector2<Real> kRLDiff = rkRPoint - rkLPoint; |
| | Vector2<Real> kTBDiff = rkTPoint - rkBPoint; |
| | Real fExtent0 = ((Real)0.5)*(rkU.Dot(kRLDiff)); |
| | Real fExtent1 = ((Real)0.5)*(rkV.Dot(kTBDiff)); |
| | Real fAreaDiv4 = fExtent0*fExtent1; |
| | if (fAreaDiv4 < rfMinAreaDiv4) |
| | { |
| | rfMinAreaDiv4 = fAreaDiv4; |
| | rkBox.Axis[0] = rkU; |
| | rkBox.Axis[1] = rkV; |
| | rkBox.Extent[0] = fExtent0; |
| | rkBox.Extent[1] = fExtent1; |
| | Vector2<Real> kLBDiff = rkLPoint - rkBPoint; |
| | rkBox.Center = rkLPoint + rkU*fExtent0 + |
| | rkV*(fExtent1 - rkV.Dot(kLBDiff)); |
| | } |
| | } |
| | |
| | template <class Real> |
| | Box2<Real> ContMinBox (int iQuantity, const Vector2<Real>* akPoint, |
| | Real fEpsilon, Query::Type eQueryType, bool bIsConvexPolygon) |
| | { |
| | Box2<Real> kBox; |
| |
|
| | |
| | Vector2<Real>* akHPoint = nullptr; |
| | if (bIsConvexPolygon) |
| | { |
| | akHPoint = (Vector2<Real>*)akPoint; |
| | } |
| | else |
| | { |
| | ConvexHull2<Real> kHull(iQuantity,(Vector2<Real>*)akPoint,fEpsilon, |
| | false,eQueryType); |
| | int iHDim = kHull.GetDimension(); |
| | int iHQuantity = kHull.GetSimplexQuantity(); |
| | const int* aiHIndex = kHull.GetIndices(); |
| |
|
| | if (iHDim == 0) |
| | { |
| | kBox.Center = akPoint[0]; |
| | kBox.Axis[0] = Vector2<Real>::UNIT_X; |
| | kBox.Axis[1] = Vector2<Real>::UNIT_Y; |
| | kBox.Extent[0] = (Real)0.0; |
| | kBox.Extent[1] = (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]]); |
| | Vector2<Real> kDiff = akPoint[aiHIndex[1]] - akPoint[aiHIndex[0]]; |
| | kBox.Extent[0] = ((Real)0.5)*kDiff.Normalize(); |
| | kBox.Extent[1] = (Real)0.0; |
| | kBox.Axis[0] = kDiff; |
| | kBox.Axis[1] = -kBox.Axis[0].Perp(); |
| |
|
| | WM4_DELETE pkHull1; |
| | return kBox; |
| | } |
| |
|
| | iQuantity = iHQuantity; |
| | akHPoint = WM4_NEW Vector2<Real>[iQuantity]; |
| | for (int i = 0; i < iQuantity; i++) |
| | { |
| | akHPoint[i] = akPoint[aiHIndex[i]]; |
| | } |
| | } |
| | |
| | |
| | |
| | |
| |
|
| | |
| | |
| | int iQuantityM1 = iQuantity -1; |
| | Vector2<Real>* akEdge = WM4_NEW Vector2<Real>[iQuantity]; |
| | bool* abVisited = WM4_NEW bool[iQuantity]; |
| | int i; |
| | for (i = 0; i < iQuantityM1; i++) |
| | { |
| | akEdge[i] = akHPoint[i+1] - akHPoint[i]; |
| | akEdge[i].Normalize(); |
| | abVisited[i] = false; |
| | } |
| | akEdge[iQuantityM1] = akHPoint[0] - akHPoint[iQuantityM1]; |
| | akEdge[iQuantityM1].Normalize(); |
| | abVisited[iQuantityM1] = false; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | Real fXMin = akHPoint[0].X(), fXMax = fXMin; |
| | Real fYMin = akHPoint[0].Y(), fYMax = fYMin; |
| | int iLIndex = 0, iRIndex = 0, iBIndex = 0, iTIndex = 0; |
| | for (i = 1; i < iQuantity; i++) |
| | { |
| | if (akHPoint[i].X() <= fXMin) |
| | { |
| | fXMin = akHPoint[i].X(); |
| | iLIndex = i; |
| | } |
| | if (akHPoint[i].X() >= fXMax) |
| | { |
| | fXMax = akHPoint[i].X(); |
| | iRIndex = i; |
| | } |
| |
|
| | if (akHPoint[i].Y() <= fYMin) |
| | { |
| | fYMin = akHPoint[i].Y(); |
| | iBIndex = i; |
| | } |
| | if (akHPoint[i].Y() >= fYMax) |
| | { |
| | fYMax = akHPoint[i].Y(); |
| | iTIndex = i; |
| | } |
| | } |
| |
|
| | |
| | if (iLIndex == iQuantityM1) |
| | { |
| | if (akHPoint[0].X() <= fXMin) |
| | { |
| | fXMin = akHPoint[0].X(); |
| | iLIndex = 0; |
| | } |
| | } |
| |
|
| | if (iRIndex == iQuantityM1) |
| | { |
| | if (akHPoint[0].X() >= fXMax) |
| | { |
| | fXMax = akHPoint[0].X(); |
| | iRIndex = 0; |
| | } |
| | } |
| |
|
| | if (iBIndex == iQuantityM1) |
| | { |
| | if (akHPoint[0].Y() <= fYMin) |
| | { |
| | fYMin = akHPoint[0].Y(); |
| | iBIndex = 0; |
| | } |
| | } |
| |
|
| | if (iTIndex == iQuantityM1) |
| | { |
| | if (akHPoint[0].Y() >= fYMax) |
| | { |
| | fYMax = akHPoint[0].Y(); |
| | iTIndex = 0; |
| | } |
| | } |
| |
|
| | |
| | kBox.Center.X() = ((Real)0.5)*(fXMin + fXMax); |
| | kBox.Center.Y() = ((Real)0.5)*(fYMin + fYMax); |
| | kBox.Axis[0] = Vector2<Real>::UNIT_X; |
| | kBox.Axis[1] = Vector2<Real>::UNIT_Y; |
| | kBox.Extent[0] = ((Real)0.5)*(fXMax - fXMin); |
| | kBox.Extent[1] = ((Real)0.5)*(fYMax - fYMin); |
| | Real fMinAreaDiv4 = kBox.Extent[0]*kBox.Extent[1]; |
| |
|
| | |
| | enum { F_NONE, F_LEFT, F_RIGHT, F_BOTTOM, F_TOP }; |
| | Vector2<Real> kU = Vector2<Real>::UNIT_X, kV = Vector2<Real>::UNIT_Y; |
| |
|
| | bool bDone = false; |
| | while (!bDone) |
| | { |
| | |
| | int iFlag = F_NONE; |
| | Real fMaxDot = (Real)0.0; |
| |
|
| | Real fDot = kU.Dot(akEdge[iBIndex]); |
| | if (fDot > fMaxDot) |
| | { |
| | fMaxDot = fDot; |
| | iFlag = F_BOTTOM; |
| | } |
| |
|
| | fDot = kV.Dot(akEdge[iRIndex]); |
| | if (fDot > fMaxDot) |
| | { |
| | fMaxDot = fDot; |
| | iFlag = F_RIGHT; |
| | } |
| |
|
| | fDot = -kU.Dot(akEdge[iTIndex]); |
| | if (fDot > fMaxDot) |
| | { |
| | fMaxDot = fDot; |
| | iFlag = F_TOP; |
| | } |
| |
|
| | fDot = -kV.Dot(akEdge[iLIndex]); |
| | if (fDot > fMaxDot) |
| | { |
| | fMaxDot = fDot; |
| | iFlag = F_LEFT; |
| | } |
| |
|
| | switch (iFlag) |
| | { |
| | case F_BOTTOM: |
| | if (abVisited[iBIndex]) |
| | { |
| | bDone = true; |
| | } |
| | else |
| | { |
| | |
| | kU = akEdge[iBIndex]; |
| | kV = -kU.Perp(); |
| | UpdateBox(akHPoint[iLIndex],akHPoint[iRIndex], |
| | akHPoint[iBIndex],akHPoint[iTIndex],kU,kV,fMinAreaDiv4, |
| | kBox); |
| |
|
| | |
| | abVisited[iBIndex] = true; |
| | if (++iBIndex == iQuantity) |
| | { |
| | iBIndex = 0; |
| | } |
| | } |
| | break; |
| | case F_RIGHT: |
| | if (abVisited[iRIndex]) |
| | { |
| | bDone = true; |
| | } |
| | else |
| | { |
| | |
| | kV = akEdge[iRIndex]; |
| | kU = kV.Perp(); |
| | UpdateBox(akHPoint[iLIndex],akHPoint[iRIndex], |
| | akHPoint[iBIndex],akHPoint[iTIndex],kU,kV,fMinAreaDiv4, |
| | kBox); |
| |
|
| | |
| | abVisited[iRIndex] = true; |
| | if (++iRIndex == iQuantity) |
| | { |
| | iRIndex = 0; |
| | } |
| | } |
| | break; |
| | case F_TOP: |
| | if (abVisited[iTIndex]) |
| | { |
| | bDone = true; |
| | } |
| | else |
| | { |
| | |
| | kU = -akEdge[iTIndex]; |
| | kV = -kU.Perp(); |
| | UpdateBox(akHPoint[iLIndex],akHPoint[iRIndex], |
| | akHPoint[iBIndex],akHPoint[iTIndex],kU,kV,fMinAreaDiv4, |
| | kBox); |
| |
|
| | |
| | abVisited[iTIndex] = true; |
| | if (++iTIndex == iQuantity) |
| | { |
| | iTIndex = 0; |
| | } |
| | } |
| | break; |
| | case F_LEFT: |
| | if (abVisited[iLIndex]) |
| | { |
| | bDone = true; |
| | } |
| | else |
| | { |
| | |
| | kV = -akEdge[iLIndex]; |
| | kU = kV.Perp(); |
| | UpdateBox(akHPoint[iLIndex],akHPoint[iRIndex], |
| | akHPoint[iBIndex],akHPoint[iTIndex],kU,kV,fMinAreaDiv4, |
| | kBox); |
| |
|
| | |
| | abVisited[iLIndex] = true; |
| | if (++iLIndex == iQuantity) |
| | { |
| | iLIndex = 0; |
| | } |
| | } |
| | break; |
| | case F_NONE: |
| | |
| | bDone = true; |
| | break; |
| | } |
| | } |
| |
|
| | WM4_DELETE[] abVisited; |
| | WM4_DELETE[] akEdge; |
| | if (!bIsConvexPolygon) |
| | { |
| | WM4_DELETE[] akHPoint; |
| | } |
| |
|
| | return kBox; |
| | } |
| | |
| | template <class Real> |
| | bool InBox (const Vector2<Real>& rkPoint, const Box2<Real>& rkBox) |
| | { |
| | Vector2<Real> kDiff = rkPoint - rkBox.Center; |
| | for (int i = 0; i < 2; i++) |
| | { |
| | Real fCoeff = kDiff.Dot(rkBox.Axis[i]); |
| | if (Math<Real>::FAbs(fCoeff) > rkBox.Extent[i]) |
| | { |
| | return false; |
| | } |
| | } |
| | return true; |
| | } |
| | |
| | template <class Real> |
| | Box2<Real> MergeBoxes (const Box2<Real>& rkBox0, const Box2<Real>& rkBox1) |
| | { |
| | |
| | Box2<Real> kBox; |
| |
|
| | |
| | |
| | |
| | kBox.Center = ((Real)0.5)*(rkBox0.Center + rkBox1.Center); |
| |
|
| | |
| | |
| | |
| | if (rkBox0.Axis[0].Dot(rkBox1.Axis[0]) >= (Real)0.0) |
| | { |
| | kBox.Axis[0] = ((Real)0.5)*(rkBox0.Axis[0] + rkBox1.Axis[0]); |
| | kBox.Axis[0].Normalize(); |
| | } |
| | else |
| | { |
| | kBox.Axis[0] = ((Real)0.5)*(rkBox0.Axis[0] - rkBox1.Axis[0]); |
| | kBox.Axis[0].Normalize(); |
| | } |
| | kBox.Axis[1] = -kBox.Axis[0].Perp(); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | int i, j; |
| | Real fDot; |
| | Vector2<Real> akVertex[4], kDiff; |
| | Vector2<Real> kMin = Vector2<Real>::ZERO; |
| | Vector2<Real> kMax = Vector2<Real>::ZERO; |
| |
|
| | rkBox0.ComputeVertices(akVertex); |
| | for (i = 0; i < 4; i++) |
| | { |
| | kDiff = akVertex[i] - kBox.Center; |
| | for (j = 0; j < 2; 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 < 4; i++) |
| | { |
| | kDiff = akVertex[i] - kBox.Center; |
| | for (j = 0; j < 2; 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 < 2; j++) |
| | { |
| | kBox.Center += kBox.Axis[j]*(((Real)0.5)*(kMax[j]+kMin[j])); |
| | kBox.Extent[j] = ((Real)0.5)*(kMax[j]-kMin[j]); |
| | } |
| |
|
| | return kBox; |
| | } |
| | |
| |
|
| | |
| | |
| | |
| | template WM4_FOUNDATION_ITEM |
| | Box2<float> ContAlignedBox<float> (int, const Vector2<float>*); |
| |
|
| | template WM4_FOUNDATION_ITEM |
| | Box2<float> ContOrientedBox<float> (int, const Vector2<float>*); |
| |
|
| | template WM4_FOUNDATION_ITEM |
| | Box2<float> ContMinBox<float> (int, const Vector2<float>*, float, |
| | Query::Type, bool); |
| |
|
| | template WM4_FOUNDATION_ITEM |
| | bool InBox<float> (const Vector2<float>&, const Box2<float>&); |
| |
|
| | template WM4_FOUNDATION_ITEM |
| | Box2<float> MergeBoxes<float> (const Box2<float>&, const Box2<float>&); |
| |
|
| | template WM4_FOUNDATION_ITEM |
| | Box2<double> ContAlignedBox<double> (int, const Vector2<double>*); |
| |
|
| | template WM4_FOUNDATION_ITEM |
| | Box2<double> ContOrientedBox<double> (int, const Vector2<double>*); |
| |
|
| | template WM4_FOUNDATION_ITEM |
| | Box2<double> ContMinBox<double> (int, const Vector2<double>*, double, |
| | Query::Type, bool); |
| |
|
| | template WM4_FOUNDATION_ITEM |
| | bool InBox<double> (const Vector2<double>&, const Box2<double>&); |
| |
|
| | template WM4_FOUNDATION_ITEM |
| | Box2<double> MergeBoxes<double> (const Box2<double>&, const Box2<double>&); |
| | |
| | } |
| |
|