简体   繁体   中英

C# Sort List of X,Y Coordinates Clockwise

I am using .NET 2.0 so I don't have access to the nifty Linq; however, I have worked up some code that sorts a list of points clockwise/counterclockwise.

My problem is that the sort works perfectly fine if the list is not already sorted, but if for some reason the list is already sorted the sort function fails miserably.

I was wandering if someone could help point me in the right direction as to why this may be the cause.

Here is my call to the sort:

positions.Sort(new Comparison<Position>(MapUtils.SortCornersClockwise));

And here is the SortCornersClockwise function:

public static int SortCornersClockwise( Position A, Position B)
    {
        //  Variables to Store the atans
        double aTanA, aTanB;

        //  Reference Point
        Pixels reference = Program.main.reference;

        //  Fetch the atans
        aTanA = Math.Atan2(A.Pixel.Y - reference.Y, A.Pixel.X - reference.X);
        aTanB = Math.Atan2(B.Pixel.Y - reference.Y, B.Pixel.X - reference.X);

        //  Determine next point in Clockwise rotation
        if (aTanA < aTanB) return -1;
        else if (aTanB > aTanA) return 1;
        return 0;
    }

Where my reference is the point from which I determine the respective angle to each point in my list of points.

Now say I have a list of points:

15778066, 27738237
15778169, 27738296
15778185, 27738269
15778082, 27738210 

These are already sorted in the correct order but calling the sort function yields:

15778082, 27738210
15778066, 27738237
15778185, 27738269
15778169, 27738296

Now take another set of sample points:

15778180, 27738255
15778081, 27738192
15778064, 27738219
15778163, 27738282 

This list is not already in the correct order and calling the sort function yields:

15778064, 27738219
15778081, 27738192
15778180, 27738255
15778163, 27738282

Which is sorted correctly. This pattern repeats it self for each set of coordinates that are already sorted and for those that aren't. Any ideas?

if (aTanA < aTanB) return -1;
else if (aTanB > aTanA) return 1;

These two conditions are the same! Either swap the variables or turn around the inequality sign, but not both.

In addition to the excellent observation that Henning made, you may also be surprised by the output once you fix that problem.

The circular symmetry makes this a somewhat unusual sorting algorithm when compared with normal sorts on totally ordered domains. Since there is circular symmetry, there are n valid clockwise orderings, given n points and it may matter to you which of those orderings you prefer.

As it stands, use of atan2 unmodified will result in a cut-line with coordinates (x,0) where x<0.

Consider coordinates A = (-10, 1) and B = (-10, -1), measured relative to the reference. You probably imagine that A should appear before B in the result, but in fact it will be the other way around since atan2 returns just less than π for A, but just more than -π for B.

If you want a cut-line with coordinates (x,0) where x>0 simply add 2π to any negative values returned from atan2.

Shouldn't that be:

else if(aTanA > aTanB) return 1;

Not sure if that would cause your issue though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM