Beispiel #1
0
    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();
}