【问题标题】:2D polygon vertex normal facing inward/outward?2D多边形顶点法线朝内/朝外?
【发布时间】:2014-12-20 12:33:22
【问题描述】:

我想测试一个向量(实际上是一个多边形顶点法线)是朝外还是朝内。多边形顺时针缠绕,边缘从 A(实心圆)到 B(描边圆)。我有这些法线是初步计算的结果,现在我想测试它们的朝向。

像这样。灰色法线应该是无效的,而绿色法线应该被验证。也许我可以通过计算角度来做到这一点,然后简单地比较它们,但我真的想在这里省去三角函数的调用。

是否有任何便宜的方法可以以某种方式仅比较“坡度”? http://bryceboe.com/2006/10/23/line-segment-intersection-algorithm/ 中的 Bryce Boe CCW 算法之类的东西

【问题讨论】:

    标签: algorithm 2d polygon segment


    【解决方案1】:

    如果您将法线向量与线段的两个点形成的向量(尾到头是顺时针方向)一起取,那么要从线段向量到法线,您必须逆时针移动。调用法线N和线段向量S,逆时针检查变为:

    if(cross(S, N) > 0)
       // Bad
    else
       // Good
    

    叉积是这样计算的:

    int cross(Vector p, Vector q)
    {   return (p.x*q.y - p.y*q.x);
    }
    

    因此,如果法线是 N = (0, 1) 和 S = (1, 0),则叉积会给出 1*1​​ - 0*0 = 1 > 0,这告诉您法线在指出。

    【讨论】:

    【解决方案2】:

    边缘向量与法线向量的叉积的符号将告诉您法线向量指向边缘的哪一侧。

    计算(Xb - Xa).Ny - (Yb - Ya).Nx

    这适用于凸多边形。

    对于一般多边形,您必须将法线的支撑线与多边形轮廓相交;你会发现偶数个交叉点(有些可能是两倍);通过将它们连接到奇数,您将知道线的哪些部分在内部或外部。

    【讨论】:

    • 谢谢。光线投射将是一个巨大的开销。我想测试两个相邻边缘的法线,所以它可以用于凹面的东西,不是吗?
    • @YvesDaoust:难道不能利用顶点的缠绕方向已知这一事实吗?
    • @rici 这也是我的猜测。
    【解决方案3】:

    其他人建议的跨产品签名测试是解决方案。

    public static bool PointIsLeftOfSegment(Vector2 point, Vector2 a, Vector2 b)
    {
        float crossProduct = (b.x - a.x) * (point.y - a.y) - (b.y - a.y) * (point.x - a.x);
        return (crossProduct > 0.0f);
    }
    

    对于最初的问题,我为这两个部分编写了测试(也考虑了锐角)。

    bool acute = segmentA.IsPointLeft(segmentB.b);
    bool leftA = segmentA.IsPointLeft(point);
    bool leftB = segmentB.IsPointLeft(point);
    bool outward = (acute) ? leftA && leftB : leftA || leftB;
    bool inward = !outward;
    

    测试台就好了:https://vine.co/u/1137617915458592768

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-25
      • 2021-05-28
      • 2016-11-02
      • 1970-01-01
      相关资源
      最近更新 更多