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 = 0; m_pkQuery = 0; 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(); }
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 = 0; m_pkQuery = 0; Mapper2<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; } 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) { // Transform the vertices to the square [0,1]^2. 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) { // 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 Query2Int64<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 Query2TInteger<Real>(m_iVertexQuantity, m_akSVertex); } else // eQueryType == Query::QT_REAL { // No scaling for floating point. 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 { // No transformation needed for exact rational arithmetic or filtered // predicates. 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 // eQueryType == Query::QT_FILTERED { m_pkQuery = WM4_NEW Query2Filtered<Real>(m_iVertexQuantity, m_akSVertex,m_fEpsilon); } } HullEdge2<Real>* pkE0; HullEdge2<Real>* pkE1; HullEdge2<Real>* pkE2; if (kMapper.GetExtremeCCW()) { pkE0 = WM4_NEW HullEdge2<Real>(i0,i1); pkE1 = WM4_NEW HullEdge2<Real>(i1,i2); pkE2 = WM4_NEW HullEdge2<Real>(i2,i0); } else { pkE0 = WM4_NEW HullEdge2<Real>(i0,i2); pkE1 = WM4_NEW HullEdge2<Real>(i2,i1); pkE2 = WM4_NEW HullEdge2<Real>(i1,i0); } pkE0->Insert(pkE2,pkE1); pkE1->Insert(pkE0,pkE2); pkE2->Insert(pkE1,pkE0); HullEdge2<Real>* pkHull = pkE0; for (i = 0; i < m_iVertexQuantity; i++) { if (!Update(pkHull,i)) { pkHull->DeleteAll(); return; } } pkHull->GetIndices(m_iSimplexQuantity,m_aiIndex); pkHull->DeleteAll(); }
Delaunay2<Real>::Delaunay2 (int iVertexQuantity, Vector2<Real>* akVertex, Real fEpsilon, bool bOwner, Query::Type eQueryType) : Delaunay<Real>(iVertexQuantity,fEpsilon,bOwner,eQueryType), m_kLineOrigin(Vector2<Real>::ZERO), m_kLineDirection(Vector2<Real>::ZERO) { assert(akVertex); m_akVertex = akVertex; m_iUniqueVertexQuantity = 0; m_akSVertex = 0; m_pkQuery = 0; m_iPathLast = -1; m_aiPath = 0; m_iLastEdgeV0 = -1; m_iLastEdgeV1 = -1; m_iLastEdgeOpposite = -1; m_iLastEdgeOppositeIndex = -1; Mapper2<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 Delaunay base class. return; } if (kMapper.GetDimension() == 1) { // The set is (nearly) collinear. The caller is responsible for // creating a Delaunay1 object. m_iDimension = 1; m_kLineOrigin = kMapper.GetOrigin(); m_kLineDirection = kMapper.GetDirection(0); return; } m_iDimension = 2; // Allocate storage for the input vertices and the supertriangle // vertices. m_akSVertex = WM4_NEW Vector2<Real>[m_iVertexQuantity+3]; int i; if (eQueryType != Query::QT_RATIONAL && eQueryType != Query::QT_FILTERED) { // Transform the vertices to the square [0,1]^2. m_kMin = kMapper.GetMin(); m_fScale = ((Real)1.0)/kMapper.GetMaxRange(); for (i = 0; i < m_iVertexQuantity; i++) { m_akSVertex[i] = (m_akVertex[i] - m_kMin)*m_fScale; } // Construct the supertriangle to contain [0,1]^2. m_aiSV[0] = m_iVertexQuantity++; m_aiSV[1] = m_iVertexQuantity++; m_aiSV[2] = m_iVertexQuantity++; m_akSVertex[m_aiSV[0]] = Vector2<Real>((Real)-1.0,(Real)-1.0); m_akSVertex[m_aiSV[1]] = Vector2<Real>((Real)+4.0,(Real)-1.0); m_akSVertex[m_aiSV[2]] = Vector2<Real>((Real)-1.0,(Real)+4.0); Real fExpand; if (eQueryType == Query::QT_INT64) { // Scale the vertices to the square [0,2^{16}]^2 to allow use of // 64-bit integers for triangulation. fExpand = (Real)(1 << 16); m_pkQuery = WM4_NEW Query2Int64<Real>(m_iVertexQuantity, m_akSVertex); } else if (eQueryType == Query::QT_INTEGER) { // Scale the vertices to the square [0,2^{20}]^2 to get more // precision for TInteger than for 64-bit integers for // triangulation. fExpand = (Real)(1 << 20); m_pkQuery = WM4_NEW Query2TInteger<Real>(m_iVertexQuantity, m_akSVertex); } else // eQueryType == Query::QT_REAL { // No scaling for floating point. fExpand = (Real)1.0; m_pkQuery = WM4_NEW Query2<Real>(m_iVertexQuantity,m_akSVertex); } m_fScale *= fExpand; for (i = 0; i < m_iVertexQuantity; i++) { m_akSVertex[i] *= fExpand; } } else { // No transformation needed for exact rational arithmetic. m_kMin = Vector2<Real>::ZERO; m_fScale = (Real)1.0; size_t uiSize = m_iVertexQuantity*sizeof(Vector2<Real>); System::Memcpy(m_akSVertex,uiSize,m_akVertex,uiSize); // Construct the supertriangle to contain [min,max]. Vector2<Real> kMin = kMapper.GetMin(); Vector2<Real> kMax = kMapper.GetMax(); Vector2<Real> kDelta = kMax - kMin; Vector2<Real> kSMin = kMin - kDelta; Vector2<Real> kSMax = kMax + kDelta*((Real)3.0); m_aiSV[0] = m_iVertexQuantity++; m_aiSV[1] = m_iVertexQuantity++; m_aiSV[2] = m_iVertexQuantity++; m_akSVertex[m_aiSV[0]] = kSMin; m_akSVertex[m_aiSV[1]] = Vector2<Real>(kSMax[0],kSMin[1]); m_akSVertex[m_aiSV[2]] = Vector2<Real>(kSMin[0],kSMax[1]); if (eQueryType == Query::QT_RATIONAL) { m_pkQuery = WM4_NEW Query2TRational<Real>(m_iVertexQuantity, m_akSVertex); } else // eQueryType == Query::QT_FILTERED { m_pkQuery = WM4_NEW Query2Filtered<Real>(m_iVertexQuantity, m_akSVertex,m_fEpsilon); } } DelTriangle<Real>* pkTri = WM4_NEW DelTriangle<Real>(m_aiSV[0],m_aiSV[1], m_aiSV[2]); m_kTriangle.insert(pkTri); // Incrementally update the triangulation. The set of processed points // is maintained to eliminate duplicates, either in the original input // points or in the points obtained by snap rounding. std::set<Vector2<Real> > kProcessed; for (i = 0; i < m_iVertexQuantity-3; i++) { if (kProcessed.find(m_akSVertex[i]) == kProcessed.end()) { Update(i); kProcessed.insert(m_akSVertex[i]); } } m_iUniqueVertexQuantity = (int)kProcessed.size(); // Remove triangles sharing a vertex of the supertriangle. RemoveTriangles(); // Assign integer values to the triangles for use by the caller. std::map<DelTriangle<Real>*,int> kPermute; typename std::set<DelTriangle<Real>*>::iterator pkTIter = m_kTriangle.begin(); for (i = 0; pkTIter != m_kTriangle.end(); pkTIter++) { pkTri = *pkTIter; kPermute[pkTri] = i++; } kPermute[0] = -1; // Put Delaunay triangles into an array (vertices and adjacency info). m_iSimplexQuantity = (int)m_kTriangle.size(); if (m_iSimplexQuantity > 0) { m_aiIndex = WM4_NEW int[3*m_iSimplexQuantity]; m_aiAdjacent = WM4_NEW int[3*m_iSimplexQuantity]; i = 0; pkTIter = m_kTriangle.begin(); for (/**/; pkTIter != m_kTriangle.end(); pkTIter++) { pkTri = *pkTIter; m_aiIndex[i] = pkTri->V[0]; m_aiAdjacent[i++] = kPermute[pkTri->A[0]]; m_aiIndex[i] = pkTri->V[1]; m_aiAdjacent[i++] = kPermute[pkTri->A[1]]; m_aiIndex[i] = pkTri->V[2]; m_aiAdjacent[i++] = kPermute[pkTri->A[2]]; } assert(i == 3*m_iSimplexQuantity); m_iPathLast = -1; m_aiPath = WM4_NEW int[m_iSimplexQuantity+1]; }