我可以使用什么线多边形裁剪算法来确保结果端点始终在多边形内?

时间:2013-08-05 17:56:03

标签: floating-point geometry numerical-methods clipping point-in-polygon

我有一个2D平面,分为n边,凸多边形。我正在使用WRF's PNPOLY algorithm来包含多边形,以确保一个点属于一个且只有一个多边形。

我是否可以使用一种算法将线段 PO 剪切到平面中的给定多边形,假设为pnpoly(O) == true,这样 pnpoly(P')< / strong>永远都是真的吗?

polygon-segment clipping diagram

我目前对clipToPoly的实现与段和多边形的每个边缘进行了线 - 线交叉测试,然后使用交点(详见this SO answer),但这并不总是产生一个点满足PNPOLY。

function clipPointToPoly(p, o, poly) {
    var i, j, n = poly.length,
        q, r = {}, s = {}, pq = {},
        rxs, t, u;

    function cross2(v, w) {
        return v.x * w.y - v.y * w.x;
    }

    for (i = 0, j = n - 1; i < n; j = i++) {
        q = poly[i];
        s.x = poly[j].x - q.x;
        s.y = poly[j].y - q.y;

        r.x = o.x - p.x;
        r.y = o.y - p.y;

        rxs = cross2(r, s);
        if (rxs !== 0) {
            pq.x = q.x - p.x;
            pq.y = q.y - p.y;

            t = cross2(pq, s) / rxs;
            u = cross2(pq, r) / rxs;
            if (0 < u && u < 1 && 0 < t && t < 1) {
                p.x = p.x + t * r.x;
                p.y = p.y + t * r.y;
                return true;
            }
        }
    }
    return false;
};

这是我对PNPOLY的实现:

function pnpoly(p, poly) {
    var i, j, e0, e1,
        n = polygon.length,
        inside = false;
    for (i = 0, j = n - 1; i < n; j = i++) {
        e0 = poly[i];
        e1 = poly[j];
        if ( ((p0.y > p.y) !== (p1.y > p.y)) &&
             ((p.x < (p1.x - p0.x) * (p.y - p0.y) / (p1.y - p0.y) + p0.x)) ) {
            inside = !inside;
        }
    }
    return inside;
};

我认为我不太了解简单模拟,或者在使用浮点数来正确处理边缘情况时如何处理PNPOLY的半开集。

例如:

poly: [(1,1), (-1,1), (-1,-1), (1,-1)]
p: (5,5)
o: (0,0)
p' = (1,1)

这是失败的,因为根据PNPOLY(它在集合的开放侧)不包括(1,1),但是clipToPoly没有考虑到这一点。我想如果我知道它是在一个开放的一端,我可以用一个epsilon轻推它,但我更喜欢一个更稳定的解决方案。

另一个例子:

poly: [-995.9592341908675, -88.48705014724577
       -1040.5031753180106, -176.53192722405026
       -549.9211095905894, -330.8462151682281
       -653.7143990581328, -211.59193148034612]
p: -1032.3773586525654, -208.3586379393678
o: -957.4172402148379, -202.6668958854324

在这种情况下,clipToPoly失败,因为 O 非常靠近多边形的边缘,它甚至不会因浮点不精确而检测到交叉点。

t: 1.0000000000000002 u: 0.8306380503739466

有没有办法让clipToPoly的浮点不精确以匹配PNPOLY,这样两者都是一致的?

1 个答案:

答案 0 :(得分:0)

您可以针对所有计算尝试精确算术:example

另一个选项(如果适用) - 制作新的多边形ABCDEP',并且将始终包含点。