You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断两条2D线段是否相交?附旧实现脚本参考

线段相交判断与多边形穿侧问题解决

我之前见过类似问题,但看不懂别人的解答。现在有四个Vector2点:P1和P2组成线段1,P3和P4组成线段2。我已经实现了计算交点坐标的代码,但不知道怎么判断这两条线段是否相交;更具体地说,我需要判断一条假想线穿过多边形的哪一侧。之前在旧测试脚本里实现过类似功能,但没加注释,现在没法适配当前需求,下面是旧脚本代码:


旧脚本代码1:角度区间判断

if rotation_angle > PI/2 && rotation_angle < 3*PI/2:
    if rad_overflow(($Position2D.position-position).angle()-PI/2) < rad_overflow(rotation_angle-PI/2) or rad_overflow(($Position2D.position-position).angle()-PI/2) > rad_overflow(rotation_angle+PI/2):
        actives.x = 1
    else:
        actives.x = 0
    
    if rad_overflow(($Position2D2.position-position).angle()-PI/2) < rad_overflow(rotation_angle-PI/2) or rad_overflow(($Position2D2.position-position).angle()-PI/2) > rad_overflow(rotation_angle+PI/2):
        actives.y = 1
    else:
        actives.y = 0
else:
    if rad_overflow(($Position2D.position-position).angle()-PI/2) < rad_overflow(rotation_angle-PI/2) && rad_overflow(($Position2D.position-position).angle()-PI/2) > rad_overflow(rotation_angle+PI/2):
        actives.x = 1
    else:
        actives.x = 0
    
    if rad_overflow(($Position2D2.position-position).angle()-PI/2) < rad_overflow(rotation_angle-PI/2) && rad_overflow(($Position2D2.position-position).angle()-PI/2) > rad_overflow(rotation_angle+PI/2):
        actives.y = 1
    else:
        actives.y = 0

代码逻辑解析:

  • 核心是通过角度范围判断两个点($Position2D和$Position2D2)的位置
  • rad_overflow是处理角度溢出的工具函数(作用是把角度限制在02π或-ππ的有效范围内)
  • 当旋转角在π/2到3π/2之间时,判断点的角度是否在rotation_angle±π/2区间之外,满足则标记actives对应位为1
  • 其他情况判断点的角度是否在该区间之内,满足则标记为1
  • 本质是用角度区间区分点的位置,为后续判断线段是否穿过区间边界做准备

旧脚本代码2:直线交点计算

var point1 = $Position2D.position
var point2 = $Position2D2.position

var limit3 = Vector2(0,1).rotated(rotation_angle+PI/2)
var limit4 = Vector2(0,1).rotated(rotation_angle-PI/2)

var det = (point1.x - point2.x)*(limit3.y - limit4.y) - (point1.y - point2.y)*(limit3.x - limit4.x)

var new_position = Vector2(
((point1.x*point2.y - point1.y*point2.x) * (limit3.x-limit4.x)  -  (point1.x-point2.x) * (limit3.x*limit4.y - limit3.y*limit4.x))/det,
((point1.x*point2.y - point1.y*point2.x) * (limit3.y-limit4.y)  -  (point1.y-point2.y) * (limit3.x*limit4.y - limit3.y*limit4.x))/det)

代码逻辑解析:

  • 计算线段(point1到point2)与角度区间边界线的交点
  • limit3和limit4是沿rotation_angle±π/2方向的单位向量,代表角度区间的两条边界直线
  • 行列式det用于判断两条直线是否平行(det为0时直线平行,无交点)
  • 后续公式是直线相交坐标的通用计算方法,最终得到线段与边界线的交点new_position

旧脚本代码3:相交结果判断

if actives.x != actives.y:
    print("hit")
else:
    print("miss")

代码逻辑解析:

  • 当两个点的标记(actives.x和actives.y)不同时,说明线段穿过了角度区间的边界,输出"hit";否则输出"miss"
  • 本质是判断线段是否与角度区间的边界相交,即线段是否穿过了假想的角度分割线

一、通用线段相交判断方法

判断两条线段(P1-P2和P3-P4)是否相交,用跨立实验结合方向叉乘即可实现:

  1. 先定义叉乘工具函数:
func cross(v1: Vector2, v2: Vector2) -> float:
    return v1.x * v2.y - v1.y * v2.x
  1. 完整相交判断逻辑:
func segments_intersect(p1: Vector2, p2: Vector2, p3: Vector2, p4: Vector2) -> bool:
    var d1 = cross(p2 - p1, p3 - p1)
    var d2 = cross(p2 - p1, p4 - p1)
    var d3 = cross(p4 - p3, p1 - p3)
    var d4 = cross(p4 - p3, p2 - p3)
    
    # 跨立实验:两点分别在对方线段两侧
    if ((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0)):
        return true
    
    # 处理点在线段上的特殊情况
    if d1 == 0 && point_on_segment(p1, p2, p3):
        return true
    if d2 == 0 && point_on_segment(p1, p2, p4):
        return true
    if d3 == 0 && point_on_segment(p3, p4, p1):
        return true
    if d4 == 0 && point_on_segment(p3, p4, p2):
        return true
    
    return false

func point_on_segment(a: Vector2, b: Vector2, p: Vector2) -> bool:
    # 判断点p是否在a-b线段上(包含端点)
    return min(a.x, b.x) <= p.x <= max(a.x, b.x) && min(a.y, b.y) <= p.y <= max(a.y, b.y)

二、判断假想线穿过多边形的哪一侧

假设假想线是无限长直线,判断它穿过多边形的方向可以按以下步骤操作:

  1. 用叉乘区分顶点位置:
    假设假想线由点O和方向向量D定义,对多边形的每个顶点V,计算cross(D, V-O):

    • 结果为正:顶点在直线的一侧
    • 结果为负:顶点在直线的另一侧
    • 结果为0:顶点在直线上
  2. 统计两侧顶点数或跟踪交点顺序:

    • 若正侧顶点数远多于负侧,说明直线从负侧穿入正侧;反之则相反
    • 若需要更精确的穿侧方向,可以跟踪假想线与多边形边的交点顺序,结合多边形法线方向判断穿入/穿出方向

如果是类似旧脚本的角度区间穿侧判断,可简化为:对多边形的每条边,用旧脚本的逻辑判断边是否穿过角度区间边界,统计穿过的方向(内到外/外到内)即可确定整体穿侧方向。


内容的提问来源于stack exchange,提问作者weg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 10:45:34