线段 矩形 碰撞检测

2015-11-13 admin 数学算法

template <class Real>
bool IntrLine2Box2<Real>::Clip (Real fDenom, Real fNumer, Real& rfT0,
    Real& rfT1)
{
    // Return value is 'true' if line segment intersects the current test
    // plane.  Otherwise 'false' is returned in which case the line segment
    // is entirely clipped.
    if (fDenom > (Real)0.0)
    {
        if (fNumer > fDenom*rfT1)
        {
            return false;
        }
        if (fNumer > fDenom*rfT0)
        {
            rfT0 = fNumer/fDenom;
        }
        return true;
    }
    else if (fDenom < (Real)0.0)
    {
        if (fNumer > fDenom*rfT0)
        {
            return false;
        }
        if (fNumer > fDenom*rfT1)
        {
            rfT1 = fNumer/fDenom;
        }
        return true;
    }
    else
    {
        return fNumer <= (Real)0.0;
    }
}
//////////////////////////////////////////////////////////////////
template <class Real>
bool IntrLine2Box2<Real>::DoClipping (Real fT0, Real fT1,
    const Vector2<Real>& rkOrigin, const Vector2<Real>& rkDirection,
    const Box2<Real>& rkBox, bool bSolid, int& riQuantity,
    Vector2<Real> akPoint[2], int& riIntrType)
{
    assert(fT0 < fT1);
    // convert linear component to box coordinates
    Vector2<Real> kDiff = rkOrigin - rkBox.Center;
    Vector2<Real> kBOrigin(
        kDiff.Dot(rkBox.Axis[0]),
        kDiff.Dot(rkBox.Axis[1])
    );
    Vector2<Real> kBDirection(
        rkDirection.Dot(rkBox.Axis[0]),
        rkDirection.Dot(rkBox.Axis[1])
    );
    Real fSaveT0 = fT0, fSaveT1 = fT1;
    bool bNotAllClipped =
        Clip(+kBDirection.X(),-kBOrigin.X()-rkBox.Extent[0],fT0,fT1) &&
        Clip(-kBDirection.X(),+kBOrigin.X()-rkBox.Extent[0],fT0,fT1) &&
        Clip(+kBDirection.Y(),-kBOrigin.Y()-rkBox.Extent[1],fT0,fT1) &&
        Clip(-kBDirection.Y(),+kBOrigin.Y()-rkBox.Extent[1],fT0,fT1);
    if (bNotAllClipped && (bSolid || fT0 != fSaveT0 || fT1 != fSaveT1))
    {
        if (fT1 > fT0)
        {
            riIntrType = IT_SEGMENT;
            riQuantity = 2;
            akPoint[0] = rkOrigin + fT0*rkDirection;
            akPoint[1] = rkOrigin + fT1*rkDirection;
        }
        else
        {
            riIntrType = IT_POINT;
            riQuantity = 1;
            akPoint[0] = rkOrigin + fT0*rkDirection;
        }
    }
    else
    {
        riIntrType = IT_EMPTY;
        riQuantity = 0;
    }
    return riIntrType != IT_EMPTY;
}



调用DoClipping()即可获得交点坐标

代码来自开源引擎WildMagic4p9\GeometricTools\WildMagic4\LibFoundation\Intersection\Wm4IntrLine2Box2.cpp

标签: 游戏开发 算法 C++ 学习

Powered by emlog

浙ICP备17021512号 |浙公网安备 33010602008237号