2

There is a list of polygons List<Polygon> Polygons defined by these classes.

How can I order that list, so that the polygon are ordered first by the X property of their Points and then by the Y property of their Points in an ascending order.

public class Polygon
{
    public List<Point2D> Points;
}

public class Point2D
{
    public double X;
    public double Y;
}

Update: For example consider these polygons:

(A) (0, 0) -> (5, 1) -> (5, -3) -> (0, -3) -> (0, 0)
(B) (0, -10) -> (5, -9) -> (5, -13) -> (0, -13) -> (0, -10)
(C) (10, 0) -> (15, 1) -> (15, -3) -> (10, -3) -> (10, 0)

the sorted output:

(A) (0, -10) -> (5, -9) -> (5, -13) -> (0, -13) -> (0, -10)
(B) (0, 0) -> (5, 1) -> (5, -3) -> (0, -3) -> (0, 0)
(C) (10, 0) -> (15, 1) -> (15, -3) -> (10, -3) -> (10, 0)
Vahid
  • 4,369
  • 10
  • 55
  • 116

3 Answers3

2

You need to add other properties to the polygon class

public class Polygon
{
    public List<Point2D> Points;

    public Point2D MinPoint;
}

This part will depend on the distibution of you points and adept the algorith fitting to you needs. then you need to find the min point of a polygon One representative of the polygon. Might be the center, bottomleft point or center of a convex hull. One representative. (this might be a bit wrong but you need to play with it a bit). This depend on the various scenarios

foreach(var poly in Polygons)
{
    int minx = poly.Points.Min(p=>p.X);
    int minY = poly.Points.Where(p=>p.X==minX).Min(p=>p.Y);
    poly.MinPoint = poly.Points.FirstOrDefault(p=>p.X==minX && p.Y==minY)
}

Then you can sort it.

var sortedPolygons = polygons.OrderBy(p=>p.MinPoint.X).ThenBy(p=>p.MinPoint.Y);
user853710
  • 1,640
  • 1
  • 13
  • 25
  • you can also put the minpoint part into the polygon class itself – user853710 May 26 '16 at 10:04
  • 1
    It would also be suggested to implement in Point2D the IComparable inteface, the you can add the comparisson of two point directly to the method and use standard sorting mechanisms. The same should be applied to the polygon as well. This is actually the "by the book" solution – user853710 May 26 '16 at 10:21
  • OrderBy needs IComparer, not IComparable – Mrinal Kamboj May 26 '16 at 10:38
1

You seem to want to order the polygons based on the smallest X value of their points, and if these are equal, then based on the smallest Y value of their points.

Here is how you can do it with LINQ:

var result =
    Polygons
    //Order by smallest X
    .OrderBy(pl => pl.Points.Min(pn => pn.X)) 
    //Then by smallest Y
    .ThenBy(pl => pl.Points.Min(pn => pn.Y))
    .ToList();
Yacoub Massad
  • 26,006
  • 2
  • 31
  • 56
  • I don't think this is what he does, because otherwise polygon B would end up earlier than polygon C (B and C are names in the original list; OP does not seem to keep them in the sorted list). It looks like you spotted that, too (I mean your comment on the question). – Sergey Kalinichenko May 26 '16 at 10:01
  • This seems to be right answer. I made a mistake preparing the example. But the whole idea is correct. – Vahid May 26 '16 at 10:04
  • 1
    @dasblinkenlight, for Y, I changed it from `Min` to `Max` to make it work for the example OP provided. If OP is mistaken, he can change it back from `Max` to `Min`. – Yacoub Massad May 26 '16 at 10:05
  • @YacoubMassad I did. Thanks. I will try this now. – Vahid May 26 '16 at 10:13
0

You can write a Comparer class for comparing the Points inside a polygon and use that to order the polygons.

class PointsComparer : IComparer<List<Point2D>>
{
    public int Compare(List<Point2D> left, List<Point2D> right)
    {
        for (int i = 0; i < left.Count && i < right.Count; i++) {
            int c = left[i].X.CompareTo(right[i].X);
            if (c != 0) return c;
            c = left[i].Y.CompareTo(right[i].Y);
            if (c != 0) return c;
        }
        return left.Count.CompareTo(right.Count);
    }
}


polygons.OrderBy(poly => poly.Points, new PointsComparer());

Side note: you may want to turn those fields into properties.

Dennis_E
  • 8,332
  • 20
  • 27