| |
|
|
| |
| |
| |
| |
| |
| |
| |
|
|
| #include "Wm4FoundationPCH.h" |
| #include "Wm4ConvexHull2.h" |
| #include "Wm4Mapper2.h" |
| #include "Wm4Query2Filtered.h" |
| #include "Wm4Query2Int64.h" |
| #include "Wm4Query2TInteger.h" |
| #include "Wm4Query2TRational.h" |
|
|
| namespace Wm4 |
| { |
|
|
| |
| template <class Real> |
| ConvexHull2<Real>::ConvexHull2 (int iVertexQuantity, Vector2<Real>* akVertex, |
| Real fEpsilon, bool bOwner, Query::Type eQueryType) |
| : |
| ConvexHull<Real>(iVertexQuantity,fEpsilon,bOwner,eQueryType), |
| m_kLineOrigin(Vector2<Real>::ZERO), |
| m_kLineDirection(Vector2<Real>::ZERO) |
| { |
| assert(akVertex); |
| m_akVertex = akVertex; |
| m_akSVertex = nullptr; |
| m_pkQuery = nullptr; |
|
|
| Mapper2<Real> kMapper(m_iVertexQuantity,m_akVertex,m_fEpsilon); |
| if (kMapper.GetDimension() == 0) |
| { |
| |
| |
| return; |
| } |
|
|
| if (kMapper.GetDimension() == 1) |
| { |
| |
| |
| m_iDimension = 1; |
| m_kLineOrigin = kMapper.GetOrigin(); |
| m_kLineDirection = kMapper.GetDirection(0); |
| return; |
| } |
|
|
| m_iDimension = 2; |
|
|
| int i0 = kMapper.GetExtremeIndex(0); |
| int i1 = kMapper.GetExtremeIndex(1); |
| int i2 = kMapper.GetExtremeIndex(2); |
|
|
| m_akSVertex = WM4_NEW Vector2<Real>[m_iVertexQuantity]; |
| int i; |
|
|
| if (eQueryType != Query::QT_RATIONAL && eQueryType != Query::QT_FILTERED) |
| { |
| |
| Vector2<Real> kMin = kMapper.GetMin(); |
| Real fScale = ((Real)1.0)/kMapper.GetMaxRange(); |
| for (i = 0; i < m_iVertexQuantity; i++) |
| { |
| m_akSVertex[i] = (m_akVertex[i] - kMin)*fScale; |
| } |
|
|
| Real fExpand; |
| if (eQueryType == Query::QT_INT64) |
| { |
| |
| |
| fExpand = (Real)(1 << 20); |
| m_pkQuery = WM4_NEW Query2Int64<Real>(m_iVertexQuantity, |
| m_akSVertex); |
| } |
| else if (eQueryType == Query::QT_INTEGER) |
| { |
| |
| |
| fExpand = (Real)(1 << 24); |
| m_pkQuery = WM4_NEW Query2TInteger<Real>(m_iVertexQuantity, |
| m_akSVertex); |
| } |
| else |
| { |
| |
| fExpand = (Real)1.0; |
| m_pkQuery = WM4_NEW Query2<Real>(m_iVertexQuantity,m_akSVertex); |
| } |
|
|
| for (i = 0; i < m_iVertexQuantity; i++) |
| { |
| m_akSVertex[i] *= fExpand; |
| } |
| } |
| else |
| { |
| |
| |
| size_t uiSize = m_iVertexQuantity*sizeof(Vector2<Real>); |
| System::Memcpy(m_akSVertex,uiSize,m_akVertex,uiSize); |
|
|
| if (eQueryType == Query::QT_RATIONAL) |
| { |
| m_pkQuery = WM4_NEW Query2TRational<Real>(m_iVertexQuantity, |
| m_akSVertex); |
| } |
| else |
| { |
| m_pkQuery = WM4_NEW Query2Filtered<Real>(m_iVertexQuantity, |
| m_akSVertex,m_fEpsilon); |
| } |
| } |
|
|
| Edge* pkE0; |
| Edge* pkE1; |
| Edge* pkE2; |
|
|
| if (kMapper.GetExtremeCCW()) |
| { |
| pkE0 = WM4_NEW Edge(i0,i1); |
| pkE1 = WM4_NEW Edge(i1,i2); |
| pkE2 = WM4_NEW Edge(i2,i0); |
| } |
| else |
| { |
| pkE0 = WM4_NEW Edge(i0,i2); |
| pkE1 = WM4_NEW Edge(i2,i1); |
| pkE2 = WM4_NEW Edge(i1,i0); |
| } |
|
|
| pkE0->Insert(pkE2,pkE1); |
| pkE1->Insert(pkE0,pkE2); |
| pkE2->Insert(pkE1,pkE0); |
|
|
| Edge* pkHull = pkE0; |
| for (i = 0; i < m_iVertexQuantity; i++) |
| { |
| if (!Update(pkHull,i)) |
| { |
| pkHull->DeleteAll(); |
| return; |
| } |
| } |
|
|
| pkHull->GetIndices(m_iSimplexQuantity,m_aiIndex); |
| pkHull->DeleteAll(); |
| } |
| |
| template <class Real> |
| ConvexHull2<Real>::~ConvexHull2 () |
| { |
| if (m_bOwner) |
| { |
| WM4_DELETE[] m_akVertex; |
| } |
| WM4_DELETE[] m_akSVertex; |
| WM4_DELETE m_pkQuery; |
| } |
| |
| template <class Real> |
| const Vector2<Real>& ConvexHull2<Real>::GetLineOrigin () const |
| { |
| return m_kLineOrigin; |
| } |
| |
| template <class Real> |
| const Vector2<Real>& ConvexHull2<Real>::GetLineDirection () const |
| { |
| return m_kLineDirection; |
| } |
| |
| template <class Real> |
| ConvexHull1<Real>* ConvexHull2<Real>::GetConvexHull1 () const |
| { |
| assert(m_iDimension == 1); |
| if (m_iDimension != 1) |
| { |
| return nullptr; |
| } |
|
|
| Real* afProjection = WM4_NEW Real[m_iVertexQuantity]; |
| for (int i = 0; i < m_iVertexQuantity; i++) |
| { |
| Vector2<Real> kDiff = m_akVertex[i] - m_kLineOrigin; |
| afProjection[i] = m_kLineDirection.Dot(kDiff); |
| } |
|
|
| return WM4_NEW ConvexHull1<Real>(m_iVertexQuantity,afProjection, |
| m_fEpsilon,true,m_eQueryType); |
| } |
| |
| template <class Real> |
| bool ConvexHull2<Real>::Update (Edge*& rpkHull, int i) |
| { |
| |
| Edge* pkVisible = nullptr; |
| Edge* pkCurrent = rpkHull; |
| do |
| { |
| if (pkCurrent->GetSign(i,m_pkQuery) > 0) |
| { |
| pkVisible = pkCurrent; |
| break; |
| } |
|
|
| pkCurrent = pkCurrent->A[1]; |
| } |
| while (pkCurrent != rpkHull); |
|
|
| if (!pkVisible) |
| { |
| |
| return true; |
| } |
|
|
| |
| Edge* pkAdj0 = pkVisible->A[0]; |
| assert(pkAdj0); |
| if (!pkAdj0) |
| { |
| return false; |
| } |
|
|
| Edge* pkAdj1 = pkVisible->A[1]; |
| assert(pkAdj1); |
| if (!pkAdj1) |
| { |
| return false; |
| } |
|
|
| pkVisible->DeleteSelf(); |
|
|
| while (pkAdj0->GetSign(i,m_pkQuery) > 0) |
| { |
| rpkHull = pkAdj0; |
| pkAdj0 = pkAdj0->A[0]; |
| assert(pkAdj0); |
| if (!pkAdj0) |
| { |
| return false; |
| } |
|
|
| pkAdj0->A[1]->DeleteSelf(); |
| } |
|
|
| while (pkAdj1->GetSign(i,m_pkQuery) > 0) |
| { |
| rpkHull = pkAdj1; |
| pkAdj1 = pkAdj1->A[1]; |
| assert(pkAdj1); |
| if (!pkAdj1) |
| { |
| return false; |
| } |
|
|
| pkAdj1->A[0]->DeleteSelf(); |
| } |
|
|
| |
| |
| Edge* pkEdge0 = WM4_NEW Edge(pkAdj0->V[1],i); |
| Edge* pkEdge1 = WM4_NEW Edge(i,pkAdj1->V[0]); |
| pkEdge0->Insert(pkAdj0,pkEdge1); |
| pkEdge1->Insert(pkEdge0,pkAdj1); |
| rpkHull = pkEdge0; |
|
|
| return true; |
| } |
| |
| template <class Real> |
| ConvexHull2<Real>::ConvexHull2 (const char* acFilename) |
| : |
| ConvexHull<Real>(0,(Real)0.0,false,Query::QT_REAL) |
| { |
| m_akVertex = nullptr; |
| m_akSVertex = nullptr; |
| m_pkQuery = nullptr; |
| bool bLoaded = Load(acFilename); |
| assert(bLoaded); |
| (void)bLoaded; |
| } |
| |
| template <class Real> |
| bool ConvexHull2<Real>::Load (const char* acFilename) |
| { |
| FILE* pkIFile = System::Fopen(acFilename,"rb"); |
| if (!pkIFile) |
| { |
| return false; |
| } |
|
|
| ConvexHull<Real>::Load(pkIFile); |
|
|
| WM4_DELETE m_pkQuery; |
| WM4_DELETE[] m_akSVertex; |
| if (m_bOwner) |
| { |
| WM4_DELETE[] m_akVertex; |
| } |
|
|
| m_bOwner = true; |
| m_akVertex = WM4_NEW Vector2<Real>[m_iVertexQuantity]; |
| m_akSVertex = WM4_NEW Vector2<Real>[m_iVertexQuantity]; |
|
|
| size_t uiSize = sizeof(Real); |
| int iVQ = 2*m_iVertexQuantity; |
| if (uiSize == 4) |
| { |
| System::Read4le(pkIFile,iVQ,m_akVertex); |
| System::Read4le(pkIFile,iVQ,m_akSVertex); |
| System::Read4le(pkIFile,2,(Real*)m_kLineOrigin); |
| System::Read4le(pkIFile,2,(Real*)m_kLineDirection); |
| } |
| else |
| { |
| System::Read8le(pkIFile,iVQ,m_akVertex); |
| System::Read8le(pkIFile,iVQ,m_akSVertex); |
| System::Read8le(pkIFile,2,(Real*)m_kLineOrigin); |
| System::Read8le(pkIFile,2,(Real*)m_kLineDirection); |
| } |
|
|
| System::Fclose(pkIFile); |
|
|
| switch (m_eQueryType) |
| { |
| case Query::QT_INT64: |
| m_pkQuery = WM4_NEW Query2Int64<Real>(m_iVertexQuantity,m_akSVertex); |
| break; |
| case Query::QT_INTEGER: |
| m_pkQuery = WM4_NEW Query2TInteger<Real>(m_iVertexQuantity, |
| m_akSVertex); |
| break; |
| case Query::QT_RATIONAL: |
| m_pkQuery = WM4_NEW Query2TRational<Real>(m_iVertexQuantity, |
| m_akSVertex); |
| break; |
| case Query::QT_REAL: |
| m_pkQuery = WM4_NEW Query2<Real>(m_iVertexQuantity,m_akSVertex); |
| break; |
| case Query::QT_FILTERED: |
| m_pkQuery = WM4_NEW Query2Filtered<Real>(m_iVertexQuantity, |
| m_akSVertex,m_fEpsilon); |
| break; |
| } |
|
|
| return true; |
| } |
| |
| template <class Real> |
| bool ConvexHull2<Real>::Save (const char* acFilename) const |
| { |
| FILE* pkOFile = System::Fopen(acFilename,"wb"); |
| if (!pkOFile) |
| { |
| return false; |
| } |
|
|
| ConvexHull<Real>::Save(pkOFile); |
|
|
| size_t uiSize = sizeof(Real); |
| int iVQ = 2*m_iVertexQuantity; |
| if (uiSize == 4) |
| { |
| System::Write4le(pkOFile,iVQ,m_akVertex); |
| System::Write4le(pkOFile,iVQ,m_akSVertex); |
| System::Write4le(pkOFile,2,(const Real*)m_kLineOrigin); |
| System::Write4le(pkOFile,2,(const Real*)m_kLineDirection); |
| } |
| else |
| { |
| System::Write8le(pkOFile,iVQ,m_akVertex); |
| System::Write8le(pkOFile,iVQ,m_akSVertex); |
| System::Write8le(pkOFile,2,(const Real*)m_kLineOrigin); |
| System::Write8le(pkOFile,2,(const Real*)m_kLineDirection); |
| } |
|
|
| System::Fclose(pkOFile); |
| return true; |
| } |
| |
|
|
| |
| |
| |
| template <class Real> |
| ConvexHull2<Real>::Edge::Edge (int iV0, int iV1) |
| { |
| V[0] = iV0; |
| V[1] = iV1; |
| A[0] = nullptr; |
| A[1] = nullptr; |
| Sign = 0; |
| Time = -1; |
| } |
| |
| template <class Real> |
| int ConvexHull2<Real>::Edge::GetSign (int i, const Query2<Real>* pkQuery) |
| { |
| if (i != Time) |
| { |
| Time = i; |
| Sign = pkQuery->ToLine(i,V[0],V[1]); |
| } |
|
|
| return Sign; |
| } |
| |
| template <class Real> |
| void ConvexHull2<Real>::Edge::Insert (Edge* pkAdj0, Edge* pkAdj1) |
| { |
| pkAdj0->A[1] = this; |
| pkAdj1->A[0] = this; |
| A[0] = pkAdj0; |
| A[1] = pkAdj1; |
| } |
| |
| template <class Real> |
| void ConvexHull2<Real>::Edge::DeleteSelf () |
| { |
| if (A[0]) |
| { |
| A[0]->A[1] = nullptr; |
| } |
|
|
| if (A[1]) |
| { |
| A[1]->A[0] = nullptr; |
| } |
|
|
| WM4_DELETE this; |
| } |
| |
| template <class Real> |
| void ConvexHull2<Real>::Edge::DeleteAll () |
| { |
| Edge* pkAdj = A[1]; |
| while (pkAdj && pkAdj != this) |
| { |
| Edge* pkSave = pkAdj->A[1]; |
| WM4_DELETE pkAdj; |
| pkAdj = pkSave; |
| } |
|
|
| assert(pkAdj == this); |
| WM4_DELETE this; |
| } |
| |
| template <class Real> |
| void ConvexHull2<Real>::Edge::GetIndices (int& riHQuantity, int*& raiHIndex) |
| { |
| |
| riHQuantity = 0; |
| Edge* pkCurrent = this; |
| do |
| { |
| riHQuantity++; |
| pkCurrent = pkCurrent->A[1]; |
| } |
| while (pkCurrent != this); |
| raiHIndex = WM4_NEW int[riHQuantity]; |
|
|
| |
| riHQuantity = 0; |
| pkCurrent = this; |
| do |
| { |
| raiHIndex[riHQuantity++] = pkCurrent->V[0]; |
| pkCurrent = pkCurrent->A[1]; |
| } |
| while (pkCurrent != this); |
| } |
| |
|
|
| |
| |
| |
| template WM4_FOUNDATION_ITEM |
| class ConvexHull2<float>; |
|
|
| template WM4_FOUNDATION_ITEM |
| class ConvexHull2<double>; |
| |
| } |
|
|