Download src/Mod/Mesh/App/WildMagic4/Wm4ConvexHull3.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 18.3 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Mesh/App/WildMagic4/Wm4ConvexHull3.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/Mesh/App/WildMagic4/Wm4ConvexHull3.cpp
-
curl -L -o Wm4ConvexHull3.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Mesh/App/WildMagic4/Wm4ConvexHull3.cpp
18.3 kB
| // SPDX-License-Identifier: BSL-1.0 | |
| // Geometric Tools, LLC | |
| // Copyright (c) 1998-2010 | |
| // Distributed under the Boost Software License, Version 1.0. | |
| // http://www.boost.org/LICENSE_1_0.txt | |
| // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt | |
| // | |
| // File Version: 4.10.0 (2009/11/18) | |
| namespace Wm4 | |
| { | |
| //---------------------------------------------------------------------------- | |
| template <class Real> | |
| ConvexHull3<Real>::ConvexHull3 (int iVertexQuantity, Vector3<Real>* akVertex, | |
| Real fEpsilon, bool bOwner, Query::Type eQueryType) | |
| : | |
| ConvexHull<Real>(iVertexQuantity,fEpsilon,bOwner,eQueryType), | |
| m_kLineOrigin(Vector3<Real>::ZERO), | |
| m_kLineDirection(Vector3<Real>::ZERO), | |
| m_kPlaneOrigin(Vector3<Real>::ZERO) | |
| { | |
| assert(akVertex); | |
| m_akVertex = akVertex; | |
| m_akPlaneDirection[0] = Vector3<Real>::ZERO; | |
| m_akPlaneDirection[1] = Vector3<Real>::ZERO; | |
| m_akSVertex = nullptr; | |
| m_pkQuery = nullptr; | |
| Mapper3<Real> kMapper(m_iVertexQuantity,m_akVertex,m_fEpsilon); | |
| if (kMapper.GetDimension() == 0) | |
| { | |
| // The values of m_iDimension, m_aiIndex, and m_aiAdjacent were | |
| // already initialized by the ConvexHull base class. | |
| return; | |
| } | |
| if (kMapper.GetDimension() == 1) | |
| { | |
| // The set is (nearly) collinear. The caller is responsible for | |
| // creating a ConvexHull1 object. | |
| m_iDimension = 1; | |
| m_kLineOrigin = kMapper.GetOrigin(); | |
| m_kLineDirection = kMapper.GetDirection(0); | |
| return; | |
| } | |
| if (kMapper.GetDimension() == 2) | |
| { | |
| // The set is (nearly) coplanar. The caller is responsible for | |
| // creating a ConvexHull2 object. | |
| m_iDimension = 2; | |
| m_kPlaneOrigin = kMapper.GetOrigin(); | |
| m_akPlaneDirection[0] = kMapper.GetDirection(0); | |
| m_akPlaneDirection[1] = kMapper.GetDirection(1); | |
| return; | |
| } | |
| m_iDimension = 3; | |
| int i0 = kMapper.GetExtremeIndex(0); | |
| int i1 = kMapper.GetExtremeIndex(1); | |
| int i2 = kMapper.GetExtremeIndex(2); | |
| int i3 = kMapper.GetExtremeIndex(3); | |
| m_akSVertex = WM4_NEW Vector3<Real>[m_iVertexQuantity]; | |
| int i; | |
| if (eQueryType != Query::QT_RATIONAL && eQueryType != Query::QT_FILTERED) | |
| { | |
| // Transform the vertices to the cube [0,1]^3. | |
| Vector3<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) | |
| { | |
| // Scale the vertices to the square [0,2^{20}]^2 to allow use of | |
| // 64-bit integers. | |
| fExpand = (Real)(1 << 20); | |
| m_pkQuery = WM4_NEW Query3Int64<Real>(m_iVertexQuantity, | |
| m_akSVertex); | |
| } | |
| else if (eQueryType == Query::QT_INTEGER) | |
| { | |
| // Scale the vertices to the square [0,2^{24}]^2 to allow use of | |
| // TInteger. | |
| fExpand = (Real)(1 << 24); | |
| m_pkQuery = WM4_NEW Query3TInteger<Real>(m_iVertexQuantity, | |
| m_akSVertex); | |
| } | |
| else // eQueryType == Query::QT_REAL | |
| { | |
| // No scaling for floating point. | |
| fExpand = (Real)1.0; | |
| m_pkQuery = WM4_NEW Query3<Real>(m_iVertexQuantity,m_akSVertex); | |
| } | |
| for (i = 0; i < m_iVertexQuantity; i++) | |
| { | |
| m_akSVertex[i] *= fExpand; | |
| } | |
| } | |
| else | |
| { | |
| // No transformation needed for exact rational arithmetic or filtered | |
| // predicates. | |
| size_t uiSize = m_iVertexQuantity*sizeof(Vector3<Real>); | |
| System::Memcpy(m_akSVertex,uiSize,m_akVertex,uiSize); | |
| if (eQueryType == Query::QT_RATIONAL) | |
| { | |
| m_pkQuery = WM4_NEW Query3TRational<Real>(m_iVertexQuantity, | |
| m_akSVertex); | |
| } | |
| else // eQueryType == Query::QT_FILTERED | |
| { | |
| m_pkQuery = WM4_NEW Query3Filtered<Real>(m_iVertexQuantity, | |
| m_akSVertex,m_fEpsilon); | |
| } | |
| } | |
| Triangle* pkT0; | |
| Triangle* pkT1; | |
| Triangle* pkT2; | |
| Triangle* pkT3; | |
| if (kMapper.GetExtremeCCW()) | |
| { | |
| pkT0 = WM4_NEW Triangle(i0,i1,i3); | |
| pkT1 = WM4_NEW Triangle(i0,i2,i1); | |
| pkT2 = WM4_NEW Triangle(i0,i3,i2); | |
| pkT3 = WM4_NEW Triangle(i1,i2,i3); | |
| pkT0->AttachTo(pkT1,pkT3,pkT2); | |
| pkT1->AttachTo(pkT2,pkT3,pkT0); | |
| pkT2->AttachTo(pkT0,pkT3,pkT1); | |
| pkT3->AttachTo(pkT1,pkT2,pkT0); | |
| } | |
| else | |
| { | |
| pkT0 = WM4_NEW Triangle(i0,i3,i1); | |
| pkT1 = WM4_NEW Triangle(i0,i1,i2); | |
| pkT2 = WM4_NEW Triangle(i0,i2,i3); | |
| pkT3 = WM4_NEW Triangle(i1,i3,i2); | |
| pkT0->AttachTo(pkT2,pkT3,pkT1); | |
| pkT1->AttachTo(pkT0,pkT3,pkT2); | |
| pkT2->AttachTo(pkT1,pkT3,pkT0); | |
| pkT3->AttachTo(pkT0,pkT2,pkT1); | |
| } | |
| m_kHull.clear(); | |
| m_kHull.insert(pkT0); | |
| m_kHull.insert(pkT1); | |
| m_kHull.insert(pkT2); | |
| m_kHull.insert(pkT3); | |
| for (i = 0; i < m_iVertexQuantity; i++) | |
| { | |
| if (!Update(i)) | |
| { | |
| DeleteHull(); | |
| return; | |
| } | |
| } | |
| ExtractIndices(); | |
| } | |
| //---------------------------------------------------------------------------- | |
| template <class Real> | |
| ConvexHull3<Real>::~ConvexHull3 () | |
| { | |
| if (m_bOwner) | |
| { | |
| WM4_DELETE[] m_akVertex; | |
| } | |
| WM4_DELETE[] m_akSVertex; | |
| WM4_DELETE m_pkQuery; | |
| } | |
| //---------------------------------------------------------------------------- | |
| template <class Real> | |
| const Vector3<Real>& ConvexHull3<Real>::GetLineOrigin () const | |
| { | |
| return m_kLineOrigin; | |
| } | |
| //---------------------------------------------------------------------------- | |
| template <class Real> | |
| const Vector3<Real>& ConvexHull3<Real>::GetLineDirection () const | |
| { | |
| return m_kLineDirection; | |
| } | |
| //---------------------------------------------------------------------------- | |
| template <class Real> | |
| const Vector3<Real>& ConvexHull3<Real>::GetPlaneOrigin () const | |
| { | |
| return m_kPlaneOrigin; | |
| } | |
| //---------------------------------------------------------------------------- | |
| template <class Real> | |
| const Vector3<Real>& ConvexHull3<Real>::GetPlaneDirection (int i) const | |
| { | |
| assert(0 <= i && i < 2); | |
| return m_akPlaneDirection[i]; | |
| } | |
| //---------------------------------------------------------------------------- | |
| template <class Real> | |
| ConvexHull1<Real>* ConvexHull3<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++) | |
| { | |
| Vector3<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> | |
| ConvexHull2<Real>* ConvexHull3<Real>::GetConvexHull2 () const | |
| { | |
| assert(m_iDimension == 2); | |
| if (m_iDimension != 2) | |
| { | |
| return nullptr; | |
| } | |
| Vector2<Real>* akProjection = WM4_NEW Vector2<Real>[m_iVertexQuantity]; | |
| for (int i = 0; i < m_iVertexQuantity; i++) | |
| { | |
| Vector3<Real> kDiff = m_akVertex[i] - m_kPlaneOrigin; | |
| akProjection[i][0] = m_akPlaneDirection[0].Dot(kDiff); | |
| akProjection[i][1] = m_akPlaneDirection[1].Dot(kDiff); | |
| } | |
| return WM4_NEW ConvexHull2<Real>(m_iVertexQuantity,akProjection, | |
| m_fEpsilon,true,m_eQueryType); | |
| } | |
| //---------------------------------------------------------------------------- | |
| template <class Real> | |
| bool ConvexHull3<Real>::Update (int i) | |
| { | |
| // Locate a triangle visible to the input point (if possible). | |
| Triangle* pkVisible = nullptr; | |
| Triangle* pkTri; | |
| typename std::set<Triangle*>::iterator pkIter; | |
| for (pkIter = m_kHull.begin(); pkIter != m_kHull.end(); pkIter++) | |
| { | |
| pkTri = *pkIter; | |
| if (pkTri->GetSign(i,m_pkQuery) > 0) | |
| { | |
| pkVisible = pkTri; | |
| break; | |
| } | |
| } | |
| if (!pkVisible) | |
| { | |
| // The point is inside the current hull; nothing to do. | |
| return true; | |
| } | |
| // Locate and remove the visible triangles. | |
| std::stack<Triangle*> kVisible; | |
| std::map<int,TerminatorData> kTerminator; | |
| kVisible.push(pkVisible); | |
| pkVisible->OnStack = true; | |
| int j, iV0, iV1; | |
| while (!kVisible.empty()) | |
| { | |
| pkTri = kVisible.top(); | |
| kVisible.pop(); | |
| pkTri->OnStack = false; | |
| for (j = 0; j < 3; j++) | |
| { | |
| Triangle* pkAdj = pkTri->A[j]; | |
| if (pkAdj) | |
| { | |
| // Detach triangle and adjacent triangle from each other. | |
| int iNullIndex = pkTri->DetachFrom(j,pkAdj); | |
| if (pkAdj->GetSign(i,m_pkQuery) > 0) | |
| { | |
| if (!pkAdj->OnStack) | |
| { | |
| // Adjacent triangle is visible. | |
| kVisible.push(pkAdj); | |
| pkAdj->OnStack = true; | |
| } | |
| } | |
| else | |
| { | |
| // Adjacent triangle is invisible. | |
| iV0 = pkTri->V[j]; | |
| iV1 = pkTri->V[(j+1)%3]; | |
| kTerminator[iV0] = TerminatorData(iV0,iV1,iNullIndex, | |
| pkAdj); | |
| } | |
| } | |
| } | |
| m_kHull.erase(pkTri); | |
| WM4_DELETE pkTri; | |
| } | |
| // Insert the new edges formed by the input point and the terminator | |
| // between visible and invisible triangles. | |
| int iSize = (int)kTerminator.size(); | |
| assert(iSize >= 3); | |
| typename std::map<int,TerminatorData>::iterator pkEdge = | |
| kTerminator.begin(); | |
| iV0 = pkEdge->second.V[0]; | |
| iV1 = pkEdge->second.V[1]; | |
| pkTri = WM4_NEW Triangle(i,iV0,iV1); | |
| m_kHull.insert(pkTri); | |
| // save information for linking first/last inserted new triangles | |
| int iSaveV0 = pkEdge->second.V[0]; | |
| Triangle* pkSaveTri = pkTri; | |
| // establish adjacency links across terminator edge | |
| pkTri->A[1] = pkEdge->second.Tri; | |
| pkEdge->second.Tri->A[pkEdge->second.NullIndex] = pkTri; | |
| for (j = 1; j < iSize; j++) | |
| { | |
| pkEdge = kTerminator.find(iV1); | |
| assert(pkEdge != kTerminator.end()); | |
| iV0 = iV1; | |
| iV1 = pkEdge->second.V[1]; | |
| Triangle* pkNext = WM4_NEW Triangle(i,iV0,iV1); | |
| m_kHull.insert(pkNext); | |
| // establish adjacency links across terminator edge | |
| pkNext->A[1] = pkEdge->second.Tri; | |
| pkEdge->second.Tri->A[pkEdge->second.NullIndex] = pkNext; | |
| // establish adjacency links with previously inserted triangle | |
| pkNext->A[0] = pkTri; | |
| pkTri->A[2] = pkNext; | |
| pkTri = pkNext; | |
| } | |
| assert(iV1 == iSaveV0); | |
| (void)iSaveV0; // avoid warning in Release build | |
| // establish adjacency links between first/last triangles | |
| pkSaveTri->A[0] = pkTri; | |
| pkTri->A[2] = pkSaveTri; | |
| return true; | |
| } | |
| //---------------------------------------------------------------------------- | |
| template <class Real> | |
| void ConvexHull3<Real>::ExtractIndices () | |
| { | |
| int iTQuantity = (int)m_kHull.size(); | |
| m_iSimplexQuantity = iTQuantity; | |
| m_aiIndex = WM4_NEW int[3*m_iSimplexQuantity]; | |
| typename std::set<Triangle*>::iterator pkIter; | |
| int i = 0; | |
| for (pkIter = m_kHull.begin(); pkIter != m_kHull.end(); pkIter++) | |
| { | |
| Triangle* pkTri = *pkIter; | |
| for (int j = 0; j < 3; j++) | |
| { | |
| m_aiIndex[i++] = pkTri->V[j]; | |
| } | |
| WM4_DELETE pkTri; | |
| } | |
| m_kHull.clear(); | |
| } | |
| //---------------------------------------------------------------------------- | |
| template <class Real> | |
| void ConvexHull3<Real>::DeleteHull () | |
| { | |
| typename std::set<Triangle*>::iterator pkIter; | |
| for (pkIter = m_kHull.begin(); pkIter != m_kHull.end(); pkIter++) | |
| { | |
| Triangle* pkTri = *pkIter; | |
| WM4_DELETE pkTri; | |
| } | |
| m_kHull.clear(); | |
| } | |
| //---------------------------------------------------------------------------- | |
| template <class Real> | |
| ConvexHull3<Real>::ConvexHull3 (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; // avoid warning in Release build | |
| } | |
| //---------------------------------------------------------------------------- | |
| template <class Real> | |
| bool ConvexHull3<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 Vector3<Real>[m_iVertexQuantity]; | |
| m_akSVertex = WM4_NEW Vector3<Real>[m_iVertexQuantity+4]; | |
| size_t uiSize = sizeof(Real); | |
| int iVQ = 3*m_iVertexQuantity; | |
| if (uiSize == 4) | |
| { | |
| System::Read4le(pkIFile,iVQ,m_akVertex); | |
| System::Read4le(pkIFile,iVQ,m_akSVertex); | |
| System::Read4le(pkIFile,3,(Real*)m_kLineOrigin); | |
| System::Read4le(pkIFile,3,(Real*)m_kLineDirection); | |
| System::Read4le(pkIFile,3,(Real*)m_kPlaneOrigin); | |
| System::Read4le(pkIFile,3,(Real*)m_akPlaneDirection[0]); | |
| System::Read4le(pkIFile,3,(Real*)m_akPlaneDirection[1]); | |
| } | |
| else // iSize == 8 | |
| { | |
| System::Read8le(pkIFile,iVQ,m_akVertex); | |
| System::Read8le(pkIFile,iVQ,m_akSVertex); | |
| System::Read8le(pkIFile,3,(Real*)m_kLineOrigin); | |
| System::Read8le(pkIFile,3,(Real*)m_kLineDirection); | |
| System::Read8le(pkIFile,3,(Real*)m_kPlaneOrigin); | |
| System::Read8le(pkIFile,3,(Real*)m_akPlaneDirection[0]); | |
| System::Read8le(pkIFile,3,(Real*)m_akPlaneDirection[1]); | |
| } | |
| System::Fclose(pkIFile); | |
| switch (m_eQueryType) | |
| { | |
| case Query::QT_INT64: | |
| m_pkQuery = WM4_NEW Query3Int64<Real>(m_iVertexQuantity,m_akSVertex); | |
| break; | |
| case Query::QT_INTEGER: | |
| m_pkQuery = WM4_NEW Query3TInteger<Real>(m_iVertexQuantity, | |
| m_akSVertex); | |
| break; | |
| case Query::QT_RATIONAL: | |
| m_pkQuery = WM4_NEW Query3TRational<Real>(m_iVertexQuantity, | |
| m_akSVertex); | |
| break; | |
| case Query::QT_REAL: | |
| m_pkQuery = WM4_NEW Query3<Real>(m_iVertexQuantity,m_akSVertex); | |
| break; | |
| case Query::QT_FILTERED: | |
| m_pkQuery = WM4_NEW Query3Filtered<Real>(m_iVertexQuantity, | |
| m_akSVertex,m_fEpsilon); | |
| break; | |
| } | |
| return true; | |
| } | |
| //---------------------------------------------------------------------------- | |
| template <class Real> | |
| bool ConvexHull3<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 = 3*m_iVertexQuantity; | |
| if (uiSize == 4) | |
| { | |
| System::Write4le(pkOFile,iVQ,m_akVertex); | |
| System::Write4le(pkOFile,iVQ,m_akSVertex); | |
| System::Write4le(pkOFile,3,(const Real*)m_kLineOrigin); | |
| System::Write4le(pkOFile,3,(const Real*)m_kLineDirection); | |
| System::Write4le(pkOFile,3,(const Real*)m_kPlaneOrigin); | |
| System::Write4le(pkOFile,3,(const Real*)m_akPlaneDirection[0]); | |
| System::Write4le(pkOFile,3,(const Real*)m_akPlaneDirection[1]); | |
| } | |
| else // iSize == 8 | |
| { | |
| System::Write8le(pkOFile,iVQ,m_akVertex); | |
| System::Write8le(pkOFile,iVQ,m_akSVertex); | |
| System::Write8le(pkOFile,3,(const Real*)m_kLineOrigin); | |
| System::Write8le(pkOFile,3,(const Real*)m_kLineDirection); | |
| System::Write8le(pkOFile,3,(const Real*)m_kPlaneOrigin); | |
| System::Write8le(pkOFile,3,(const Real*)m_akPlaneDirection[0]); | |
| System::Write8le(pkOFile,3,(const Real*)m_akPlaneDirection[1]); | |
| } | |
| System::Fclose(pkOFile); | |
| return true; | |
| } | |
| //---------------------------------------------------------------------------- | |
| //---------------------------------------------------------------------------- | |
| // ConvexHull3::Triangle | |
| //---------------------------------------------------------------------------- | |
| template <class Real> | |
| ConvexHull3<Real>::Triangle::Triangle (int iV0, int iV1, int iV2) | |
| { | |
| V[0] = iV0; | |
| V[1] = iV1; | |
| V[2] = iV2; | |
| A[0] = nullptr; | |
| A[1] = nullptr; | |
| A[2] = nullptr; | |
| Sign = 0; | |
| Time = -1; | |
| OnStack = false; | |
| } | |
| //---------------------------------------------------------------------------- | |
| template <class Real> | |
| int ConvexHull3<Real>::Triangle::GetSign (int i, const Query3<Real>* pkQuery) | |
| { | |
| if (i != Time) | |
| { | |
| Time = i; | |
| Sign = pkQuery->ToPlane(i,V[0],V[1],V[2]); | |
| } | |
| return Sign; | |
| } | |
| //---------------------------------------------------------------------------- | |
| template <class Real> | |
| void ConvexHull3<Real>::Triangle::AttachTo (Triangle* pkAdj0, | |
| Triangle* pkAdj1, Triangle* pkAdj2) | |
| { | |
| // assert: The input adjacent triangles are correctly ordered. | |
| A[0] = pkAdj0; | |
| A[1] = pkAdj1; | |
| A[2] = pkAdj2; | |
| } | |
| //---------------------------------------------------------------------------- | |
| template <class Real> | |
| int ConvexHull3<Real>::Triangle::DetachFrom (int iAdj, Triangle* pkAdj) | |
| { | |
| assert(0 <= iAdj && iAdj < 3 && A[iAdj] == pkAdj); | |
| A[iAdj] = nullptr; | |
| for (int i = 0; i < 3; i++) | |
| { | |
| if (pkAdj->A[i] == this) | |
| { | |
| pkAdj->A[i] = nullptr; | |
| return i; | |
| } | |
| } | |
| return -1; | |
| } | |
| //---------------------------------------------------------------------------- | |
| //---------------------------------------------------------------------------- | |
| // explicit instantiation | |
| //---------------------------------------------------------------------------- | |
| template WM4_FOUNDATION_ITEM | |
| class ConvexHull3<float>; | |
| template WM4_FOUNDATION_ITEM | |
| class ConvexHull3<double>; | |
| //---------------------------------------------------------------------------- | |
| } | |