为了账号安全,请及时绑定邮箱和手机立即绑定

多边形中的点,包括 c# 中带有边距的边缘情况

多边形中的点,包括 c# 中带有边距的边缘情况

C#
慕村225694 2023-09-16 17:00:35
我正在使用 Unity3D,并且有一个多边形(Vector2 数组)以及要检查的点。在过去的几天里,我一直在寻找包括 pnpoly 和其他算法在内的解决方案。问题是我的误差高达 0.001f,因为我在使用 TransformPoint(以获取网格顶点的世界位置)后立即乘以四元数,将 3D 面投影到 2D 平面上。我对多边形一无所知,因为它们是由许多网格三角形组成的 - 它们可以具有任何形状。我如何处理这种极端的不准确性并找到多边形内部或边界上的所有点?    public static bool IsInsidePolygon(Vector2[] vertices, Vector2 checkPoint)    {        float[] vertX = new float[vertices.Length];        float[] vertY = new float[vertices.Length];        for (int i = 0; i < vertices.Length; i++)        {            vertX[i] = vertices[i].x;            vertY[i] = vertices[i].y;        }        return IsInsidePolygon(vertices.Length, vertX, vertY, checkPoint.x, checkPoint.y);    }    public static bool IsInsidePolygon3(int nvert, float[] vertx, float[] verty, float testx, float testy)    {        int i, j = 0;        bool c = false;        for (i = 0, j = nvert - 1; i < nvert; j = i++)        {            if (((verty[i] > testy) != (verty[j] > testy)) &&         (testx < (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + vertx[i]))                c = !c;        }        return c;    }
查看完整描述

1 回答

?
明月笑刀无情

TA贡献1828条经验 获得超4个赞

解决方案是找到到多边形的最近距离,如果距离在边距内,则返回 true,以下是完整代码:


'''


public static float DistancePointLine2D(Vector2 point, Vector2 lineStart, Vector2 lineEnd)

{

    return (ProjectPointLine2D(point, lineStart, lineEnd) - point).magnitude;

}

public static Vector2 ProjectPointLine2D(Vector2 point, Vector2 lineStart, Vector2 lineEnd)

{

    Vector2 rhs = point - lineStart;

    Vector2 vector2 = lineEnd - lineStart;

    float magnitude = vector2.magnitude;

    Vector2 lhs = vector2;

    if (magnitude > 1E-06f)

    {

        lhs = (Vector2)(lhs / magnitude);

    }

    float num2 = Mathf.Clamp(Vector2.Dot(lhs, rhs), 0f, magnitude);

    return (lineStart + ((Vector2)(lhs * num2)));

}



public static float ClosestDistanceToPolygon(Vector2[] verts, Vector2 point)

{

    int nvert = verts.Length;

    int i, j = 0;

    float minDistance = Mathf.Infinity;

    for (i = 0, j = nvert - 1; i < nvert; j = i++)

    {

        float distance = DistancePointLine2D(point, verts[i], verts[j]);

        minDistance = Mathf.Min(minDistance, distance);

    }


    return minDistance;

}


public static bool IsInsidePolygon(Vector2[] vertices, Vector2 checkPoint, float margin = 0.01f)

{

    if(ClosestDistanceToPolygon(vertices, checkPoint) < margin)

    {

        return true;

    }


    float[] vertX = new float[vertices.Length];

    float[] vertY = new float[vertices.Length];

    for (int i = 0; i < vertices.Length; i++)

    {

        vertX[i] = vertices[i].x;

        vertY[i] = vertices[i].y;

    }


    return IsInsidePolygon(vertices.Length, vertX, vertY, checkPoint.x, checkPoint.y);

}


public static bool IsInsidePolygon(int nvert, float[] vertx, float[] verty, float testx, float testy)

{

    bool c = false;

    int i, j = 0;

    for (i = 0, j = nvert - 1; i < nvert; j = i++)

    {

        if ((((verty[i] <= testy) && (testy < verty[j])) ||


             ((verty[j] <= testy) && (testy < verty[i]))) &&


            (testx < (vertx[j] - vertx[i]) * (testy - verty[i]) / (verty[j] - verty[i]) + vertx[i]))

            c = !c;

    }

    return c;

}

'''


查看完整回答
反对 回复 2023-09-16
  • 1 回答
  • 0 关注
  • 96 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信