⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wmlconvexhull2.cpp

📁 3D Game Engine Design Source Code非常棒
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    GetTangent(rkLHull,rkRHull,iLLIndex,iLRIndex);

    // get upper tangent to hulls (UL = upper left, UR = upper right)
    int iULIndex = iLMax, iURIndex = iRMin;
    GetTangent(rkRHull,rkLHull,iURIndex,iULIndex);

    // Construct the counterclockwise-ordered merged-hull vertices.
    // TO DO.  If the hull is stored using linked lists, this block can be
    // improved by an O(1) detach, attach, and delete of the appropriate
    // sublists.
    i = iLRIndex;
    while ( true )
    {
        rkHull.push_back(rkRHull[i]);
        if ( i == iURIndex )
            break;

        if ( ++i == iRSize )
            i = 0;
    }

    i = iULIndex;
    while ( true )
    {
        rkHull.push_back(rkLHull[i]);
        if ( i == iLLIndex )
            break;

        if ( ++i == iLSize )
            i = 0;
    }
}
//----------------------------------------------------------------------------
template <class Real>
void ConvexHull2<Real>::MergeLinear (const SortedVertex& rkP, SVArray& rkHull)
{
    // hull = <Q0,Q1>

    switch ( CollinearTest(rkP.m_kV,rkHull[0].m_kV,rkHull[1].m_kV) )
    {
    case ORDER_POSITIVE:
        // merged hull is triangle <Q0,Q1,P>
        m_iHullType = HULL_PLANAR;
        rkHull.push_back(rkP);
        break;
    case ORDER_NEGATIVE:
    {
        // merged hull is triangle <Q1,Q0,P>
        m_iHullType = HULL_PLANAR;
        SortedVertex kSave = rkHull[0];
        rkHull[0] = rkHull[1];
        rkHull[1] = kSave;
        rkHull.push_back(rkP);
        break;
    }
    case ORDER_COLLINEAR_LEFT:
        // collinear order is <P,Q0,Q1>, merged hull is <P,Q1>
        rkHull[0] = rkP;
        break;
    case ORDER_COLLINEAR_RIGHT:
        // collinear order is <Q0,Q1,P>, merged hull is <Q0,P>
        rkHull[1] = rkP;
        break;
    //case ORDER_COLLINEAR_CONTAIN:
        // collinear order is <Q0,P,Q1>, merged hull is <Q0,Q1> (no change)
    }
}
//----------------------------------------------------------------------------
template <class Real>
void ConvexHull2<Real>::GetTangent (const SVArray& rkLHull,
    const SVArray& rkRHull, int& riL, int& riR)
{
    // In theory the loop terminates in a finite number of steps, but the
    // upper bound for the loop variable is used to trap problems caused by
    // floating point round-off errors that might lead to an infinite loop.

    int iLSize = (int)rkLHull.size(), iRSize = (int)rkRHull.size();
    int iLSizeM1 = iLSize-1, iRSizeM1 = iRSize-1;
    int i;
    for (i = 0; i < iLSize+iRSize; i++)
    {
        // end points of potential tangent
        const Vector2<Real>& rkL1 = rkLHull[riL].m_kV;
        const Vector2<Real>& rkR0 = rkRHull[riR].m_kV;

        // walk along left hull to find tangency
        int iLm1 = ( riL > 0 ? riL-1 : iLSizeM1 );
        const Vector2<Real>& rkL0 = rkLHull[iLm1].m_kV;
        int iCT = CollinearTest(rkR0,rkL0,rkL1);
        if ( iCT == ORDER_NEGATIVE || iCT == ORDER_COLLINEAR_LEFT )
        {
            riL = iLm1;
            continue;
        }

        // walk along right hull to find tangency
        int iRp1 = ( riR < iRSizeM1 ? riR+1 : 0 );
        const Vector2<Real>& rkR1 = rkRHull[iRp1].m_kV;
        iCT = CollinearTest(rkL1,rkR0,rkR1);
        if ( iCT == ORDER_NEGATIVE || iCT == ORDER_COLLINEAR_RIGHT )
        {
            riR = iRp1;
            continue;
        }

        // tangent segment has been found
        break;
    }

    // detect "infinite loop" caused by floating point round-off errors
    assert( i < iLSize+iRSize );
}
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
// incremental hull
//----------------------------------------------------------------------------
template <class Real>
void ConvexHull2<Real>::ByIncremental ()
{
    // Sort by x-component and store in contiguous array.  The sort is
    // O(N log N).
    SVArray kSVArray(m_iVQuantity);
    int i;
    for (i = 0; i < m_iVQuantity; i++)
    {
        kSVArray[i].m_kV = m_akVertex[i];
        kSVArray[i].m_iIndex = i;
    }
    sort(kSVArray.begin(),kSVArray.end());

    // remove duplicate points
    typename SVArray::iterator pkEnd =
        unique(kSVArray.begin(),kSVArray.end());
    kSVArray.erase(pkEnd,kSVArray.end());

    // Compute convex hull incrementally.  The first and second vertices in
    // the hull are managed separately until at least one triangle is formed.
    // At that time an array is used to store the hull in counterclockwise
    // order.
    m_iHullType = HULL_POINT;
    m_kHull.push_back(kSVArray[0]);
    for (i = 1; i < (int)kSVArray.size(); i++)
    {
        switch ( m_iHullType )
        {
        case HULL_POINT:
            m_iHullType = HULL_LINEAR;
            m_kHull.push_back(kSVArray[i]);
            break;
        case HULL_LINEAR:
            MergeLinear(kSVArray[i]);
            break;
        case HULL_PLANAR:
            MergePlanar(kSVArray[i]);
            break;
        }
    }

    // construct index array for ordered vertices of convex hull
    m_iHQuantity = (int)m_kHull.size();
    m_aiHIndex = new int[m_iHQuantity];
    for (i = 0; i < m_iHQuantity; i++)
        m_aiHIndex[i] = m_kHull[i].m_iIndex;
}
//----------------------------------------------------------------------------
template <class Real>
void ConvexHull2<Real>::MergeLinear (const SortedVertex& rkP)
{
    switch ( CollinearTest(rkP.m_kV,m_kHull[0].m_kV,m_kHull[1].m_kV) )
    {
    case ORDER_POSITIVE:
    {
        // merged hull is <P,Q0,Q1>
        m_iHullType = HULL_PLANAR;
        SortedVertex kCopy = m_kHull[1];
        m_kHull.push_back(kCopy);
        m_kHull[1] = m_kHull[0];
        m_kHull[0] = rkP;
        break;
    }
    case ORDER_NEGATIVE:
    {
        // merged hull is <P,Q1,Q0>
        m_iHullType = HULL_PLANAR;
        SortedVertex kCopy = m_kHull[0];
        m_kHull.push_back(kCopy);
        m_kHull[0] = rkP;
        break;
    }
    case ORDER_COLLINEAR_LEFT:
        // linear order is <P,Q0,Q1>, merged hull is <P,Q1>
        m_kHull[0] = rkP;
        break;
    case ORDER_COLLINEAR_RIGHT:
        // linear order is <Q0,Q1,P>, merged hull is <Q0,P>
        m_kHull[1] = rkP;
        break;
    // case ORDER_COLLINEAR_CONTAIN:  linear order is <Q0,P,Q1>, no change
    }
}
//----------------------------------------------------------------------------
template <class Real>
void ConvexHull2<Real>::MergePlanar (const SortedVertex& rkP)
{
    int iSize = (int)m_kHull.size();
    int i, iU, iL, iCT;

    // search counterclockwise for last visible vertex
    for (iU = 0, i = 1; iU < iSize; iU = i++)
    {
        if ( i == iSize )
            i = 0;

        iCT = CollinearTest(rkP.m_kV,m_kHull[iU].m_kV,m_kHull[i].m_kV);
        if ( iCT == ORDER_NEGATIVE )
            continue;
        if ( iCT == ORDER_POSITIVE || iCT == ORDER_COLLINEAR_LEFT )
            break;

        // iCT == ORDER_COLLINEAR_CONTAIN || iCT == ORDER_COLLINEAR_RIGHT
        return;
    }
    assert( iU < iSize );

    // search clockwise for last visible vertex
    for (iL = 0, i = iSize-1; i >= 0; iL = i--)
    {
        iCT = CollinearTest(rkP.m_kV,m_kHull[i].m_kV,m_kHull[iL].m_kV);
        if ( iCT == ORDER_NEGATIVE )
            continue;
        if ( iCT == ORDER_POSITIVE || iCT == ORDER_COLLINEAR_RIGHT )
            break;

        // iCT == ORDER_COLLINEAR_CONTAIN || iCT == ORDER_COLLINEAR_LEFT
        return;
    }
    assert( i >= 0 );

    if ( iU == iL )
    {
        // This probably occurs when CollinearTest should report collinearity,
        // but does not.  If it does occur, and you care about this code
        // block not occurring, try increasing the size of the collinear
        // epsilon.  When this block does occur, the conclusion is that the
        // input point is collinear with an edge of the hull, so just return.
        return;
    }

    // construct the counterclockwise-ordered merged-hull vertices
    SVArray kTmpHull;
    kTmpHull.push_back(rkP);
    while ( true )
    {
        kTmpHull.push_back(m_kHull[iU]);
        if ( iU == iL )
            break;

        if ( ++iU == iSize )
            iU = 0;
    }
    assert( kTmpHull.size() > 2 );

    m_kHull = kTmpHull;
}
//----------------------------------------------------------------------------

//----------------------------------------------------------------------------
// explicit instantiation
//----------------------------------------------------------------------------
namespace Wml
{
template class WML_ITEM ConvexHull2<float>;
float ConvexHull2f::COLLINEAR_EPSILON = 1e-06f;

template class WML_ITEM ConvexHull2<double>;
double ConvexHull2d::COLLINEAR_EPSILON = 1e-06;
}
//----------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -