¿Cuál es una forma fácil de llenar una patayometría cóncava para ser convexo (encontrando los vértices cóncavos y quitándolos)?

StackOverflow https://stackoverflow.com/questions/3208515

Pregunta

Tengo una patayomeometría (polígono) construida de linesegmentos en una patata y me gustaría asegurarme de que sea convexo.Tengo un método que usa el producto cruzado para determinar si la geometría es convexa, estaba asumiendo que podría simplemente devolver una lista de puntos que lo hacen cóncavo cuando es falso y eliminé los puntos para llenar el polígono, pero no funciona bien.

Aquí está el código que tengo:

    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;
        }

y aquí está donde estoy haciendo el cheque y corrigiendo el polígono:

        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);
        }

En última instancia, me gustaría poder hacer mi geometría cóncava en un convexo como este:

 alt text

¿Fue útil?

Solución

COMPUSTE EL convex Hull (también: nts ) y elimina cualquier vértice en el interiordel polígono convexo convexo resultante (usando un Prueba de punto-in-polígono ).

Otros consejos

Usted recorre cada triplete de vértices adyacentes (ABC, BCD, CDE, etc.).Para cada trimestre, calcule el punto medio del segmento que une el primer y tercer vértice (conecta A-C en ABC, B-D en BCD, etc.).Si el punto medio está dentro del polígono, vas al siguiente triplete.Si está afuera, sustituye los 2 segmentos que vinculan el triplete con el segmento que une los extremos (es decir, elimina el punto central).Usted continúa hasta que no sean más sustituciones.

Si lo intentas en papel, obtienes exactamente el resultado que describe.

Si no me equivoco, puede probar si un punto pertenece a un polígono con Polygon.HitTestCore.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top