ConvexHull2<Real>::ConvexHull2 ( int numVertices, Vector2<Real>* vertices, Real epsilon, bool owner, Query::Type queryType ) : ConvexHull<Real>( numVertices, epsilon, owner, queryType ), mVertices( vertices ), mSVertices( 0 ), mQuery( 0 ), mLineOrigin( Vector2<Real>::ZERO ), mLineDirection( Vector2<Real>::ZERO ) { typename Vector2<Real>::Information info; Vector2<Real>::GetInformation( mNumVertices, mVertices, mEpsilon, info ); if ( info.mDimension == 0 ) { // The values of mDimension and mIndices were already initialized by // the ConvexHull base class. return; } if ( info.mDimension == 1 ) { // The set is (nearly) collinear. The caller is responsible for // creating a ConvexHull1 object. mDimension = 1; mLineOrigin = info.mOrigin; mLineDirection = info.mDirection[0]; return; } mDimension = 2; int i0 = info.mExtreme[0]; int i1 = info.mExtreme[1]; int i2 = info.mExtreme[2]; mSVertices = new1<Vector2<Real> >( mNumVertices ); int i; if ( queryType != Query::QT_RATIONAL && queryType != Query::QT_FILTERED ) { // Transform the vertices to the square [0,1]^2. Vector2<Real> minValue( info.mMin[0], info.mMin[1] ); Real scale = ( ( Real )1 ) / info.mMaxRange; for ( i = 0; i < mNumVertices; ++i ) { mSVertices[i] = ( mVertices[i] - minValue ) * scale; } Real expand; if ( queryType == Query::QT_INT64 ) { // Scale the vertices to the square [0,2^{20}]^2 to allow use of // 64-bit integers. expand = ( Real )( 1 << 20 ); mQuery = new0 Query2Int64<Real>( mNumVertices, mSVertices ); } else if ( queryType == Query::QT_INTEGER ) { // Scale the vertices to the square [0,2^{24}]^2 to allow use of // Integer. expand = ( Real )( 1 << 24 ); mQuery = new0 Query2Integer<Real>( mNumVertices, mSVertices ); } else // queryType == Query::QT_REAL { // No scaling for floating point. expand = ( Real )1; mQuery = new0 Query2<Real>( mNumVertices, mSVertices ); } for ( i = 0; i < mNumVertices; ++i ) { mSVertices[i] *= expand; } } else { // No transformation needed for exact rational arithmetic or filtered // predicates. memcpy( mSVertices, mVertices, mNumVertices * sizeof( Vector2<Real> ) ); if ( queryType == Query::QT_RATIONAL ) { mQuery = new0 Query2Rational<Real>( mNumVertices, mSVertices ); } else // queryType == Query::QT_FILTERED { mQuery = new0 Query2Filtered<Real>( mNumVertices, mSVertices, mEpsilon ); } } Edge* edge0; Edge* edge1; Edge* edge2; if ( info.mExtremeCCW ) { edge0 = new0 Edge( i0, i1 ); edge1 = new0 Edge( i1, i2 ); edge2 = new0 Edge( i2, i0 ); } else { edge0 = new0 Edge( i0, i2 ); edge1 = new0 Edge( i2, i1 ); edge2 = new0 Edge( i1, i0 ); } edge0->Insert( edge2, edge1 ); edge1->Insert( edge0, edge2 ); edge2->Insert( edge1, edge0 ); Edge* hull = edge0; for ( i = 0; i < mNumVertices; ++i ) { if ( !Update( hull, i ) ) { hull->DeleteAll(); return; } } hull->GetIndices( mNumSimplices, mIndices ); hull->DeleteAll(); }
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); } } 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(); }