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