zoukankan      html  css  js  c++  java
  • 圆和射线相交 矩形和射线相交判断 lua

    global_NULL = ""
    --判断射线和圆是否相交,相交的话返回交点
    -- rayBeginVec3射线起点 rayNormalVec3归一化的射线方向 centerVec3圆心 r圆半径
    -- return 0 表示不相交
    --return 1, nearPos(近点)
    function global_ray2Circle(rayBeginVec3, rayNormalVec3, centerVec3, r)
        local center2ray = Vector3.New(rayBeginVec3.x - centerVec3.x, rayBeginVec3.y - centerVec3.y, 0)
        local dotV = Vector3.Dot(center2ray, rayNormalVec3)
        local subLen = Vector3.Dot(center2ray, center2ray) - r ^ 2
        if subLen > 0 and dotV > 0 then
            -- 射线源在圆外,方向相反,不会相交
            return 0, global_NULL
        end
        local discr = dotV * dotV - subLen
        if discr < 0 then
            return 0, global_NULL
        end
        local t = -dotV - discr ^ 0.5
        t = math.max(0, t)
        return 1, Vector3.New(rayBeginVec3.x + rayNormalVec3.x * t, rayBeginVec3.y + rayNormalVec3.y * t, 0)
    end
    
    -- 两条直线的交点
    function global_line2line(k1, b1, k2, b2)
        if k1 == global_NULL and k2 == global_NULL then
            return global_NULL
        end
        if k1 == global_NULL then
            return {["x"] = -b1, ["y"] =(-b1 * k2 + b2)}
        end
        if k2 == global_NULL then
            return {["x"] = -b2, ["y"] =(-b2 * k1 + b1)}
        end
        if math.abs(k1 - k2) < 0.00001 then
            --平行
            return global_NULL
        end
        local x = (b2 - b1) / (k1 - k2)
        return {["x"] = x, ["y"] =(x * k1 + b1)}
    end
    
    --获取一条直线的k和b系数
    function global_lineFactor(vec3, pos)
        if vec3.x == 0 then --垂直的直线 k无效
            return global_NULL, -pos.x
        else
            local k = vec3.y / vec3.x
            return  k, pos.y - k*pos.x
        end
    end
    
    -- 射线和线段的交点
    function global_rayPosLine(rayBeginVec3, rayNormalVec3, lineBegin, lineEnd)
        local lineVec3 = Vector3.New(lineEnd.x - lineBegin.x, lineEnd.y - lineBegin.y, 0)
        local k1, b1 = global_lineFactor(rayNormalVec3, rayBeginVec3)
        local k2, b2 = global_lineFactor(lineVec3, lineBegin)
        local pos = global_line2line(k1, b1, k2, b2)
        if pos ~= global_NULL then
            --判断交点在线段内、在射线内
            if ((pos.x - lineBegin.x) * (pos.x - lineEnd.x) <= 0 and (pos.y - lineBegin.y) * (pos.y - lineEnd.y) <= 0)
                    and (rayNormalVec3.x * (pos.x - rayBeginVec3.x) + rayNormalVec3.y * (pos.y - rayBeginVec3.y)) >= 0
            then
                --print(stringMessage(pos))
                return pos
            end
        end
        --print("无交点")
        return global_NULL
    end
    
    --获取射线和矩形的交点(射线在矩形内,必相交)
    --return pos
    function global_ray2RectInner(rayBeginVec3, rayNormalVec3, LB_X, LB_Y, RT_X, RT_Y)
    
        local posFunc = function(a, b, c, d)
            local rightV = Vector3.New(a - rayBeginVec3.x, b - rayBeginVec3.y, 0)
            local leftV = Vector3.New(c - rayBeginVec3.x, d - rayBeginVec3.y, 0)
            local angleA = Vector3.Angle(rightV, rayNormalVec3)
            local angleB = Vector3.Angle(leftV, rayNormalVec3)
            local angleAll = Vector3.Angle(rightV, leftV)
            if angleAll >= angleA and angleAll >= angleB then
                return global_rayPosLine(rayBeginVec3, rayNormalVec3, Vector3.New(a, b, 0), Vector3.New(c, d, 0))
            end
            return global_NULL
        end
        --  右上 左上
        local pos = posFunc(RT_X,RT_Y,LB_X,RT_Y)
        if pos ~=global_NULL then
            return pos
        end
        -- 左上 左下
        local pos = posFunc(LB_X,RT_Y,LB_X,LB_Y)
        if pos ~=global_NULL then
            return pos
        end
        -- 左下 右下
        local pos = posFunc(LB_X,LB_Y,RT_X,LB_Y)
        if pos ~=global_NULL then
            return pos
        end
        -- 右下 右上
        local pos = posFunc(RT_X,LB_Y,RT_X,RT_Y)
        if pos ~=global_NULL then
            return pos
        end
        print("global_ray2RectInner 有错误! 内部射线和矩形没有交点")
        return global_NULL
    end
    
    
    -- 射线和矩形的交点,射线源在矩形内,矩形和x轴平行
    function global_ray2RectInnerPos(rayBeginVec3, rayNormalVec3, LB_X, LB_Y, RT_X, RT_Y)
        local k = global_NULL
        if math.abs(rayNormalVec3.x) >= 0.00001 then
            k = rayNormalVec3.y / rayNormalVec3.x
            if math.abs(k) < 0.00001 then
                if rayNormalVec3.x > 0 then
                    return { x = RT_X, y = rayBeginVec3.y }
                else
                    return { x = LB_X, y = rayBeginVec3.y }
                end
            end
        else
            if rayNormalVec3.y > 0 then
                return { x = rayBeginVec3.x, y = RT_Y }
            else
                return { x = rayBeginVec3.x, y = LB_Y }
            end
        end
        -- 右上 左上
        local rtVec3 = Vector3.New(RT_X - rayBeginVec3.x, RT_Y - rayBeginVec3.y, 0)
        local ltVec3 = Vector3.New(LB_X - rayBeginVec3.x, RT_Y - rayBeginVec3.y, 0)
        local cossRT = Vector3.Cross(rtVec3, rayNormalVec3)
        local cossLT = Vector3.Cross(rayNormalVec3, ltVec3)
        if Vector3.Dot(cossRT, cossLT) <= 0 then
            return { x = (rayBeginVec3.x + RT_Y / k), y = RT_Y }
        end
        -- 左上 左下
        rtVec3 = Vector3.New(LB_X - rayBeginVec3.x, RT_Y - rayBeginVec3.y, 0)
        ltVec3 = Vector3.New(LB_X - rayBeginVec3.x, LB_Y - rayBeginVec3.y, 0)
        cossRT = Vector3.Cross(rtVec3, rayNormalVec3)
        cossLT = Vector3.Cross(rayNormalVec3, ltVec3)
        if Vector3.Dot(cossRT, cossLT) <= 0 then
            return { x = (rayBeginVec3.x + RT_Y / k), y = RT_Y }
        end
        -- 左下 右下
        rtVec3 = Vector3.New(LB_X - rayBeginVec3.x, LB_Y - rayBeginVec3.y, 0)
        ltVec3 = Vector3.New(RT_X - rayBeginVec3.x, LB_Y - rayBeginVec3.y, 0)
        cossRT = Vector3.Cross(rtVec3, rayNormalVec3)
        cossLT = Vector3.Cross(rayNormalVec3, ltVec3)
        if Vector3.Dot(cossRT, cossLT) <= 0 then
            return { x = (rayBeginVec3.x + RT_Y / k), y = RT_Y }
        end
        -- 右下 右上
        rtVec3 = Vector3.New(RT_X - rayBeginVec3.x, LB_Y - rayBeginVec3.y, 0)
        ltVec3 = Vector3.New(RT_X - rayBeginVec3.x, LB_Y - rayBeginVec3.y, 0)
        cossRT = Vector3.Cross(rtVec3, rayNormalVec3)
        cossLT = Vector3.Cross(rayNormalVec3, ltVec3)
        if Vector3.Dot(cossRT, cossLT) <= 0 then
            return { x = (rayBeginVec3.x + RT_Y / k), y = RT_Y }
        end
        print("global_ray2RectInnerPos 出错 没有找到交点!")
        return global_NULL
    end
    改变自己
  • 相关阅读:
    Windows Svr 2008 Ent R2 性能计数器显示不全
    SQL Server的keepalive
    C语言字符串常见操作-strcpy、strlen、strcat和strcmp实现
    计算机中数据的编码方式
    OC中的排序方法
    关于C语言内存对齐
    C语言内存管理总结-野指针
    Objective-C基础学习笔记(九)-Foundation
    Objective-C基础学习笔记(八)-内存管理-autorelease使用-property创建对象的内存管理-循环引用的内管管理
    Objective-C基础学习笔记(七)-分类-Category-类的本质-load和+initialize方法-SEL数据
  • 原文地址:https://www.cnblogs.com/sun-shadow/p/12928516.html
Copyright © 2011-2022 走看看