C# 将凹形路径几何体填充为凸形(查找凹形顶点并移除它们)的简单方法是什么?

C# 将凹形路径几何体填充为凸形(查找凹形顶点并移除它们)的简单方法是什么?,c#,wpf,geometry,pathgeometry,concave,C#,Wpf,Geometry,Pathgeometry,Concave,我有一个由一个PathFigure上的线段组成的PathGeometry(多边形),我想确保它是凸的。我有一种方法,使用叉积来确定几何体是否是凸的,我假设我可以返回一个点列表,当它为假时,这些点使它成为凹的,然后移除这些点来填充多边形,但它的工作方式不太正确 以下是我得到的代码: public static bool IsConvexPolygon(this IList<Point> polygon, out List<Point> concavePoints)

我有一个由一个PathFigure上的线段组成的PathGeometry(多边形),我想确保它是凸的。我有一种方法,使用叉积来确定几何体是否是凸的,我假设我可以返回一个点列表,当它为假时,这些点使它成为凹的,然后移除这些点来填充多边形,但它的工作方式不太正确

以下是我得到的代码:

    public static bool IsConvexPolygon(this IList<Point> polygon, out List<Point> concavePoints)
    {
        int n = polygon.Count;
        List<double> result = new List<double>();
        concavePoints = new List<Point>();
        for (int i = 0; i < n; i++)
        {
            result.Add(polygon[i].CrossProduct(polygon[i.RotateNext(n)]));
            if (result.Last() < 0.0)
            {
                concavePoints.Add(polygon[i.RotateNext(n)]);
            }
        }
        return (result.All(d => d >= 0.0));
    }

    public static double CrossProduct(this Point p1, Point p2)
        {
            return (p1.X * p2.Y) - (p1.Y * p2.X);
        }

    public static int RotateNext(this int index, int count)
        {
            return (index + 1) % count;
        }

    public static PointCollection ExtractPoints(this Geometry geometry)
        {
            PointCollection pc = new PointCollection();
            if (geometry is LineGeometry)
            {
                var lg = (LineGeometry)geometry;
                pc.Add(lg.StartPoint);
                pc.Add(lg.EndPoint);
                return pc;
            }
            else if (geometry is PathGeometry)
            {
                var pg = (PathGeometry)geometry;
                if (pg.Figures.Count > 0)
                {
                    List<Point> points;
                    if ((pg.Figures[0].Segments.Count > 0) && (pg.Figures[0].Segments[0] is PolyLineSegment))
                        points = ((PolyLineSegment)pg.Figures[0].Segments[0]).Points.ToList();
                    else
                        points = pg.Figures[0].Segments.Select(seg => (seg as LineSegment).Point).ToList();

                    pc.Add(pg.Figures[0].StartPoint);
                    foreach (Point p in points)
                        pc.Add(p);
                    return pc;
                }
            }
            else if (geometry is RectangleGeometry)
            {
                var rg = (RectangleGeometry)geometry;
                var rect = rg.Rect;
                pc.Add(rect.TopLeft);
                pc.Add(rect.TopRight);
                pc.Add(rect.BottomRight);
                pc.Add(rect.BottomLeft);
                return pc;
            }
            return pc;
        }

public static Geometry CreateGeometryFromPoints(this List<Point> pts)
{
    if (pts.Count < 2)
        return null;

    PathFigure pFig = new PathFigure() { StartPoint = pts[0] };
    for (int i = 1; i < pts.Count; i++)
    {
        pFig.Segments.Add(new LineSegment(pts[i], true));
    }
    pFig.IsClosed = true;

    PathGeometry pg = new PathGeometry(new List<PathFigure>() { pFig });
    return pg;
}
public static Path CreatePolygonFromGeometry(this Geometry geo, Brush fillBrush)
        {
            Path path = new Path() { Stroke = Brushes.Black, StrokeThickness = 1, Fill = fillBrush };
            path.Data = geo;
            return path;
        }
public static bool IsConvexPolygon(此IList多边形,列表外凹点)
{
int n=多边形计数;
列表结果=新列表();
concavePoints=新列表();
对于(int i=0;id>=0.0));
}
公共静态双叉积(此点p1,点p2)
{
返回(p1.X*p2.Y)-(p1.Y*p2.X);
}
公共静态int RotateNext(此int索引,int计数)
{
返回(索引+1)%count;
}
公共静态点集合提取点(此几何体)
{
PointCollection pc=新的PointCollection();
如果(几何图形是线几何图形)
{
var lg=(线性几何体)几何体;
pc.Add(lg.StartPoint);
pc.Add(lg.EndPoint);
返回pc;
}
else if(几何体是路径几何体)
{
var pg=(路径几何体)几何体;
如果(pg.Figures.Count>0)
{
列出要点;
如果((pg.Figures[0].Segments.Count>0)和&(pg.Figures[0].Segments[0]是多段线线段))
点=((多段线线段)pg.Figures[0]。线段[0])。点。ToList();
其他的
points=pg.Figures[0]。Segments.Select(seg=>(seg as LineSegment).Point.ToList();
pc.Add(pg.Figures[0].StartPoint);
foreach(点中的点p)
pc.Add(p);
返回pc;
}
}
else if(几何体为矩形几何体)
{
var rg=(矩形几何体)几何体;
var rect=rg.rect;
pc.Add(右上左);
pc.Add(右上角);
pc.Add(右下角矩形);
pc.Add(右下角左下角);
返回pc;
}
返回pc;
}
公共静态几何体CreateGeometryFromPoints(此列表)
{
如果(pts.Count<2)
返回null;
PathFigure pFig=new PathFigure(){StartPoint=pts[0]};
for(int i=1;i
这里是我检查和修正多边形的地方:

        List<Point> outstuff;
        if (geo1.ExtractPoints().IsConvexPolygon(out outstuff) == false)
        {
            // Got to fill it in if it's concave
            var newpts = geo1.ExtractPoints().Except(outstuff).ToList();
            var z = newpts.CreateGeometryFromPoints().CreatePolygonFromGeometry(Brushes.Purple);
            z.MouseRightButtonDown += delegate { canvas.Children.Remove(z); };
            canvas.Children.Add(z);
        }
List-outpuff;
if(geo1.ExtractPoints().IsConvexPolygon(out-outsuff)==false)
{
//如果是凹面,就得填进去
var newpts=geo1.ExtractPoints().Except(outsuff.ToList();
var z=newpts.CreateGeometryFromPoints().CreatePolygonFromGeometry(画笔.Purple);
z、 MouseRightButtonDown+=委托{canvas.Children.Remove(z);};
canvas.Children.Add(z);
}
最终,我希望能够将我的凹面几何体变成凸面几何体,如下所示:


您可以循环遍历每个相邻顶点的三元组(ABC、BCD、CDE等)。对于每个三元组,计算连接第一个和第三个顶点的线段的中点(在ABC中连接A-C,在BCD中连接B-D,等等)。如果中点位于多边形内部,则转到下一个三元组。如果它在外部,则将链接三元组的两条线段替换为链接极端的一条线段(即,删除中间点)。你继续,直到没有更多的替代品

如果你在纸上试一下,你会得到你描述的结果


如果我没有弄错的话,您可以使用
polygon.HitTestCore

来测试一个点是否属于多边形。我会计算(也:)并删除生成的凸包多边形内部的所有顶点(使用测试)。

那么,有什么不起作用呢?你得到了什么结果?啊!谢谢你提到凸面外壳。我接受了这个想法,我在这里发现了它的实现: