碰撞算法13 --多边形与圆形的碰撞

--多边形与圆形碰撞
function PolygonToCircle(polygon,circlePos,radius)
    local vectorNum = polygon:VectorNumber();
    local next = 0

    for current = 0 , vectorNum do
        if (current == vectorNum - 1) then
            next = 0
        else
            next = current + 1
        end

        local vc = polygon:GetVector(current)
        local vn = polygon:GetVector(next)
        --线是否与圆碰撞
        if LineToCircle(vc,vn,circlePos,radius) then
            return true
        end
    end
    --多边形是否与圆点碰撞
    PolygonToPoint(polygon,circlePos)
end

--线与圆的碰撞
function LineToCircle(linePoint1,linePoint2,circlePos,radius)
    --这里需要分成两种情况,一种是线段两边的点是否在圆内
    --如果点到半径的距离
    if PointToCircle(linePoint1,circlePos,radius) then
        return true
    end

    if PointToCircle(linePoint2,circlePos,radius) then
        return true
    end

    --寻找圆心最近的点
    local lineVec = {x= (linePoint2.x - linePoint1.x) , y = (linePoint2.y - linePoint1.y)}
    local pointToLinePoint1 = {x= (circlePos.x - linePoint1.x) , y = (circlePos.y - linePoint1.y)}

    local lineLength = math.sqrt(lineVec.x * lineVec.x  + lineVec.y * lineVec.y)
    --点乘向量公式 相当于 lineLength * pointLinePoint1Length * cos角度
    local dot = lineVec.x  * pointToLinePoint1.x +  lineVec.y * pointToLinePoint1.y
    --这里就是pointLinePoint1Length * cos角度 及为lineVec 的投影长度,温馨提示pointLinePoint1ToLine可能为正负值 取决于向量的夹角的cos值
    --相当于到线段的投影比例
    local pointLinePoint1ToLine =  dot / lineLength
    local closestX = linePoint1.x + pointLinePoint1ToLine * (linePoint2.x - linePoint1.x)
    local closestY = linePoint1.y + pointLinePoint1ToLine * (linePoint2.y - linePoint1.y)

    local isInLine = PointToLine({ x = closestX,y =  closestY} , linePoint1, linePoint2)
    --如果点不在线上面(就是相当于他是在延长线 ) 直接returnfalse
    if not isInLine then
        return false;
    end
    --点跟圆的碰撞
    local result = PointToCircle({ x = closestX,y =  closestY},circlePos,radius)
    return result
end

--点与直线的碰撞
function PointToLine(point , linePoint1, linePoint2)
    --思想点与线两边线段的距离跟线的距离的判断,相等就是在同一直线
    local line1 = math.sqrt((linePoint1.x - point.x) * (linePoint1.x - point.x) + (linePoint1.y - point.y)* (linePoint1.y - point.y))
    local line2 = math.sqrt((linePoint2.x - point.x) * (linePoint2.x - point.x) + (linePoint2.y - point.y)* (linePoint2.y - point.y))
    local line = math.sqrt((linePoint2.x - linePoint1.x) * (linePoint2.x - linePoint1.x) + (linePoint2.y - linePoint1.y)* (linePoint2.y - linePoint1.y))
    return (line1 + line2) == line
end

--圆跟圆是否碰撞
function CircleToCircle (circlePos1,radius1,circlePos2,radius2)
    local sqr2  = (circlePos1.x - circlePos2.x) * (circlePos1.x - circlePos2.x) + (circlePos1.y - circlePos2.y)*(circlePos1.y - circlePos2.y)
    return (radius1+radius2)  * (radius1+radius2) >= sqr2
end

--多边形与点的碰撞
function PolygonToPoint(polygon,point)
    local vectorNum = polygon:VectorNumber();

    local collision = false
    local next = 0

    for current = 0 , vectorNum do
        if (current == vectorNum - 1) then
            next = 0
        else
            next = current + 1
        end

        local vc = polygon:GetVector(current)
        local vn = polygon:GetVector(next)
        if PointToLine(point,vc, vn) then
            return true
        end
        --若尔当曲线定理 需要的同学可以去学习一下
        if (((vc.y >= py and vn.y < py) or (vc.y < py and vn.y >= py)) and
            (px < (vn.x - vc.x) * (py - vc.y) / (vn.y - vc.y) + vc.x)) then
            collision = not collision
        end
    end
    return collision
end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值