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

如何判断二维线段是否处于多边形内部?

问题

我有多边形顶点数据,格式示例如下:
-5.0000,-1.0000;-5.0000,-4.0000;5.0000,-4.0000;5.0000,0.0000;2.0000,-3.0000;1.0000,-1.0000
顶点间用;分隔,坐标用,分隔,数据构成闭合图形。

另有一条线段坐标示例:
-5.5380,-1.7205;-6.3484,-3.1333
格式与多边形顶点一致,我需要判断这条线段是否完全处于多边形内部(完全在内部的线段返回true,穿出或在外部的返回false)。

目前我有一个基于射线投射算法的函数,仅能判断单个点是否在多边形内部,代码如下:

type Point struct {
    X float64
    Y float64
}

func intersect(vertexes []Point, testx float64, testy float64) bool {
    // 射线投射算法实现:统计测试点向右发射的射线与多边形边的交点数
    var c = false
    polygonVertexCount := len(vertexes)
    for index := range vertexes {
        currentVertex := vertexes[index]
        nextVertex := vertexes[(index+1)%polygonVertexCount]
        if ((currentVertex.Y > testy) != (nextVertex.Y > testy)) &&
            (testx < (nextVertex.X-currentVertex.X)*(testy-currentVertex.Y)/(nextVertex.Y-currentVertex.Y)+currentVertex.X) {
            c = !c
        }
    }
    return c
}

请问如何修改该算法,使其能够判断线段是否处于多边形内部?


解决方案

要判断线段是否完全在多边形内部,需要满足两个核心条件:

  • 线段的两个端点都在多边形内部(含边界)
  • 线段本身不与多边形的任何边相交(避免线段穿出多边形)

步骤1:实现线段相交判断函数

新增函数用于判断两条线段是否相交(排除端点接触、共线重叠的情况):

// 判断两条线段是否相交(非端点接触的跨立相交)
func segmentsIntersect(a1, a2, b1, b2 Point) bool {
    // 计算叉积,用于判断点的相对位置
    cross := func(p1, p2, p3 Point) float64 {
        return (p2.X-p1.X)*(p3.Y-p1.Y) - (p2.Y-p1.Y)*(p3.X-p1.X)
    }

    d1 := cross(b1, b2, a1)
    d2 := cross(b1, b2, a2)
    d3 := cross(a1, a2, b1)
    d4 := cross(a1, a2, b2)

    // 两条线段互相跨立,判定为相交
    if ((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) && 
       ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0)) {
        return true
    }

    // 排除端点在另一条线段上的场景(若需支持边界贴合,可调整此处逻辑)
    return false
}

步骤2:实现线段在多边形内的判断函数

结合现有点-in-多边形函数与线段相交判断,实现最终逻辑:

func IsSegmentInsidePolygon(polygon []Point, segStart, segEnd Point) bool {
    // 1. 检查线段两个端点是否都在多边形内部
    if !intersect(polygon, segStart.X, segStart.Y) || !intersect(polygon, segEnd.X, segEnd.Y) {
        return false
    }

    // 2. 检查线段是否与多边形的任意边相交
    polyCount := len(polygon)
    for i := 0; i < polyCount; i++ {
        curr := polygon[i]
        next := polygon[(i+1)%polyCount]
        if segmentsIntersect(segStart, segEnd, curr, next) {
            return false
        }
    }

    // 满足所有条件,线段在多边形内部
    return true
}

补充说明

  • 若需支持线段端点在多边形边界上的场景,需给intersect函数补充边界判断逻辑(比如检查点是否落在多边形的某条边上)
  • 浮点数计算存在精度误差,实际使用时建议添加极小阈值(如1e-8),避免因精度问题导致判断错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 21:12:09