C#点在多边形多边形

2023-09-10 22:30:29 作者:尔虞我诈...

我试图确定一个点是一个多边形内。多边形是由点对象的数组定义。我可以很容易地计算出,如果该点内的多边形的有界框,但我不知道如何判断它内部的实际多边形与否。如果可能的话,我想只能用C#和WinForms。我宁愿不上的OpenGL或致电东西做这个简单的任务。

这里的code我到目前为止有:

 私人无效CalculateOuterBounds()
{
    // m_aptVertices是一个点[]保持该多边形的顶点。
    //和X / Y最小/最大只是整数
    在Xmin = Xmax的= m_aptVertices [0] .X;
    YMIN = YMAX = m_aptVertices [0] .Y;

    的foreach(点PT在m_aptVertices)
    {
        如果(在Xmin> pt.X)
            在Xmin = pt.X;

        如果(Xmax的< pt.X)
            XMAX = pt.X;

        如果(YMIN> pt.Y)
            YMIN = pt.Y;

        如果(YMAX< pt.Y)
            YMAX = pt.Y;
    }
}

公共BOOL包含(点PT)
{
    布尔bContains = TRUE; //显然是错误的时刻:)

    如果(pt.X<在Xmin || pt.X>的Xmax || pt.Y< YMIN || pt.Y> YMAX)
        bContains = FALSE;
    其他
    {
        //计算出,如果该点是在所述多边形
    }

    返回bContains;
}
 

解决方案

见的这个的它在C ++中,可以在C#中同样的方式进行。

有关凸多边形是太容易了:

  点是否在多边形内部的判断 代码

如果多边形是凸的那么就可以   考虑多边形从路径   第一个顶点。有一点是对的   这个多边形内部,如果它是   总是在所有的同一侧   线段构成的路径。

     

鉴于P0之间的线段   (X0,Y0)和P1(X1,Y1),另一点   P(X,Y)具有以下关系   线段。计算(Y - Y0)   (X1 - X0) - (X - X0)(Y1 - Y0)

     

如果它小于0,那么P是至   线段的权利,如果更大   于0,是向左,如果等于   0则位于线段

这是在C#code吧,可能是有错误:

 公共静态布尔IsInPolygon(点[]聚,点对点)
        {
           VAR系数= poly.Skip(1)。选择((P,I)=>
                                           (point.Y  - 聚[I] .Y)*(p.X  - 聚[I] .X)
                                          - (point.X  - 聚[I] .X)*(p.Y  - 聚[I] .Y))
                                   .ToList();

            如果(coef.Any(p值=指p == 0))
                返回true;

            的for(int i = 1; I< coef.Count();我++)
            {
                如果(系数[I] *系数[I  -  1]; 0)
                    返回false;
            }
            返回true;
        }
 

我用简单的长方形测试它工作正常:

 点[] PTS =新点[] {新点{X = 1,Y = 1},
                                        新的点{X = 1,Y = 3},
                                        新的点{X = 3,Y = 3},
                                        新的点{X = 3,Y = 1}};
            IsInPolygon(点,新点{X = 2,Y = 2}); ==>真正
            IsInPolygon(点,新点{X = 1,Y = 2}); ==>真正
            IsInPolygon(份,新点{X = 0,Y = 2}); ==>假
 

在LINQ查询说明:

poly.Skip(1) ==>创建一个新的列表,从位置 1 的聚列表,然后通过 (point.Y - 聚[I] .Y)*(PX - 聚[I] .X) - (point.X - 聚[I] .X)*(PY - 聚[I] .Y)我们要计算的方向(在引用段落中提到)。 类似的例子(与其他操作):

  LST = 2,4,8,12,7,19
lst.Skip(1)==> 4,8,12,7,19
lst.Skip(1)。选择((P,I)=指p-LST [I])==> 2,4,4,-5,12
 

I'm trying to determine if a point is inside a polygon. the Polygon is defined by an array of Point objects. I can easily figure out if the point is inside the bounded box of the polygon, but I'm not sure how to tell if it's inside the actual polygon or not. If possible, I'd like to only use C# and WinForms. I'd rather not call on OpenGL or something to do this simple task.

Here's the code I have so far:

private void CalculateOuterBounds()
{
    //m_aptVertices is a Point[] which holds the vertices of the polygon.
    // and X/Y min/max are just ints
    Xmin = Xmax = m_aptVertices[0].X;
    Ymin = Ymax = m_aptVertices[0].Y;

    foreach(Point pt in m_aptVertices)
    {
        if(Xmin > pt.X)
            Xmin = pt.X;

        if(Xmax < pt.X)
            Xmax = pt.X;

        if(Ymin > pt.Y)
            Ymin = pt.Y;

        if(Ymax < pt.Y)
            Ymax = pt.Y;
    }
}

public bool Contains(Point pt)
{
    bool bContains = true; //obviously wrong at the moment :)

    if(pt.X < Xmin || pt.X > Xmax || pt.Y < Ymin || pt.Y > Ymax)
        bContains = false;
    else
    {
        //figure out if the point is in the polygon
    }

    return bContains;
}

解决方案

See this it's in c++ and can be done in c# in a same way.

for convex polygon is too easy:

If the polygon is convex then one can consider the polygon as a "path" from the first vertex. A point is on the interior of this polygons if it is always on the same side of all the line segments making up the path.

Given a line segment between P0 (x0,y0) and P1 (x1,y1), another point P (x,y) has the following relationship to the line segment. Compute (y - y0) (x1 - x0) - (x - x0) (y1 - y0)

if it is less than 0 then P is to the right of the line segment, if greater than 0 it is to the left, if equal to 0 then it lies on the line segment.

And this is a code for it in c#, may be is buggy:

        public static bool IsInPolygon(Point[] poly, Point point)
        {
           var coef = poly.Skip(1).Select((p, i) => 
                                           (point.Y - poly[i].Y)*(p.X - poly[i].X) 
                                         - (point.X - poly[i].X) * (p.Y - poly[i].Y))
                                   .ToList();

            if (coef.Any(p => p == 0))
                return true;

            for (int i = 1; i < coef.Count(); i++)
            {
                if (coef[i] * coef[i - 1] < 0)
                    return false;
            }
            return true;
        }

I test it with simple rectangle works fine:

            Point[] pts = new Point[] { new Point { X = 1, Y = 1 }, 
                                        new Point { X = 1, Y = 3 }, 
                                        new Point { X = 3, Y = 3 }, 
                                        new Point { X = 3, Y = 1 } };
            IsInPolygon(pts, new Point { X = 2, Y = 2 }); ==> true
            IsInPolygon(pts, new Point { X = 1, Y = 2 }); ==> true
            IsInPolygon(pts, new Point { X = 0, Y = 2 }); ==> false

Explanation on the linq query:

poly.Skip(1) ==> creates a new list started from position 1 of the poly list and then by (point.Y - poly[i].Y)*(p.X - poly[i].X) - (point.X - poly[i].X) * (p.Y - poly[i].Y) we'll going to calculate the direction (which mentioned in referenced paragraph). similar example (with another operation):

lst = 2,4,8,12,7,19
lst.Skip(1) ==> 4,8,12,7,19
lst.Skip(1).Select((p,i)=>p-lst[i]) ==> 2,4,4,-5,12