-1

I have a list of coordinates that should form a edges of a path which i need to get sorted. I am trying to use Grahams scan and have tried a couple of samples from:

  1. GrhamsScan.cs
  2. ConvexHull.cs
  3. ConvexHull Algo

These codes fails for several test cases that I have and I am not sure whats wrong.

Edit:

These coordinates are supposed to be part of tangent lines. If the coordinates are not in sorted, the tangents go hap hazard instead of a proper path that could be straight or curved as the storm progresses.

I am creating tangents to circles that form a storm's path. An example can be seen here: enter image description here

Edit#02

A correct shape (ignore the semi circle at the end) should look like this if the points forming the tangent lines are in order.

enter image description here

Testcases:

Test case#01

[0]: {X = 11.581625 Y = -110.983437}
[1]: {X = 11.1816254 Y = -108.983437}
[2]: {X = 11.88781 Y = -113.115852}
[3]: {X = 11.587204 Y = -111.015938}
[4]: {X = 12.1884336 Y = -115.215759}
[5]: {X = 11.88781 Y = -113.115845}
[6]: {X = 12.5794077 Y = -116.863365}
[7]: {X = 12.1794081 Y = -115.163368}
[8]: {X = 13.0785418 Y = -118.855026}
[9]: {X = 12.5785418 Y = -116.855026}
[10]: {X = 13.534234 Y = -119.732178}
[11]: {X = 13.034234 Y = -118.732178}

Test case#02

   [0]: {X = 10.4182844 Y = -111.21611}
[1]: {X = 10.0190592 Y = -109.21595}
[2]: {X = 10.712142 Y = -113.283806}
[3]: {X = 10.4127483 Y = -111.183716}
[4]: {X = 11.0115175 Y = -115.383896}
[5]: {X = 10.712141 Y = -113.2838}
[6]: {X = 11.4204569 Y = -117.136063}
[7]: {X = 11.0213022 Y = -115.435867}
[8]: {X = 11.9213 Y = -119.144341}
[9]: {X = 11.4223957 Y = -117.144066}
[10]: {X = 12.4652023 Y = -120.266693}
[11]: {X = 11.9662571 Y = -119.266167}

Testcases#03

   [0]: {X = 10.6 Y = -109.1}
    [1]: {X = 11.0 Y = -111.1}
    [2]: {X = 11.3 Y = -113.2}
    [3]: {X = 11.6 Y = -115.3}
    [4]: {X = 12.0 Y = -117.0}
    [5]: {X = 12.5 Y = -119.0}
    [6]: {X = 13.0 Y = -120.0}

Kindly guide me a resource, algorithm or code where i can find a reliable sorting algorithm for floating point coordinates and does not eliminate points while doing that. Speed is not priority, accuracy is a priority.

I would appreciate all inputs. Thanks

Community
  • 1
  • 1
Steve Johnson
  • 3,054
  • 7
  • 46
  • 71
  • Could you show us a plot of what that data looks like? Also, is the shape convex? – Chris Jan 13 '15 at 19:08
  • Added the screenshot and some relevant detail. – Steve Johnson Jan 13 '15 at 19:11
  • Are there one or two tracks in each data set? – Chris Jan 13 '15 at 19:18
  • Each of the data set (testcases) above is a separate track. If you consider circles moving from left to right, there would upper tangents to those circles represented by testcases#1, lower tangents to those circles represented by testcases#2 and coordinates for the center of the circles represented by test cases#3 – Steve Johnson Jan 13 '15 at 19:27
  • 2
    In that case, assuming the tracks don't loop back on themselves, I would imagine just going from point to point by picking the nearest one would do the trick. – Chris Jan 13 '15 at 19:42
  • I really didnt think of that, lolz.. I should have tried that first. Thanks for the input! – Steve Johnson Jan 13 '15 at 19:47
  • 1
    I do not understand what the problem you're solving has to do with convex hulls. – tmyklebu Jan 13 '15 at 22:33
  • I just wanted to sort the coordinates and this was what i found when i tried to google the probem. If the points are not sorted, the tangents in turn appear as shown in the first diagram. If there is any algorithm out there that can help me sort the points in the correct order so the formed path is correct. – Steve Johnson Jan 13 '15 at 22:38
  • Where is gone this third coordinate named time which could have dramatically helped you sorting the two others? – aka.nice Jan 13 '15 at 23:08
  • This is a good suggestion, I just tried that and created a 3rd data structure with Created datetime property set to DateTime.Now. But the points generation procedure probably adds points in a manner that Created date no longer remains a proper candidate for sorting the points. :( Working on a custom sort as @Chris suggested. – Steve Johnson Jan 13 '15 at 23:29

2 Answers2

1

You unfortunately lost the time graduations that once existed in the meteorological data, and the points arrive to you out of order
So you want to reconstruct a path from a set of points. Once this is done, this answer is considering that constructing the envelope shall not be a problem.

If you have N points, there are N! possible orderings.

Among these orderings, you'll have to choose the one which maximize the likelihood to represent a storm trajectory.

A naive criterion could be to minimize the path length. A more advanced one could take into account that storm velocity cannot change instantly, so more or less penalize the acceleration. Or the derivative of acceleration... But this might require additional hypothesis concerning the regularity of time sampling.

In all cases you'll have to inject a model of what a storm trajectory is supposed to look like, and associate some kind of score (probability) to the various hypothesis (possible trajectories).

Unless your set of points is really tiny, you are not going to iterate on the whole combinatorial. Instead you will reconstruct the trajectory starting with one arbitrary point. You will then try to extend the trajectory at one side or the other by iteratively adding a point. You will select a priori a reduced set of most probables candidates (like nearset point to last points of reconstructed trajectory so far, or nearest to the extrapolation of already reconstructed trajectory with constant velocity or constant acceleration hypothesis...).

A trivial algorithm will select the most probable candidate locally at each step.

A more serious algorithm will reconstruct several possible trajectories in parallel, and eliminate the least probables ones according to some probabilistic selection rules.

I see this category of problems closely related to tracking of targets with a RADAR, so you might have a look at such literature, and notably be interested in bayesian ensemble probability. I hope you love maths.

aka.nice
  • 9,100
  • 1
  • 28
  • 40
0

This is what i wrote and it worked for all the cases finally. Let me admit it can be improved for performance and this might be a quick and dirty way but this what i am using at the moment.

P.S: I also admit that "Convex Hull" or "Graham Scan" was never what i needed and has nothing to do with what was required. So technically it was a fault on my side. I needed to sort points with the closest point first as @Chris had suggested.

public class ConvexHull6
{

    public class PointDistance
    {
        public double X { get; set; }
        public double Y { get; set; }
        public double distance { get; set; }
        public int index { get; set; }
    }
    public class StormPointsDistance
    {
        public StormPoints stormPoints { get; set; }
        public Double distance { get; set; }
    }
    public static List<PointD> ReOrderPointsByClosestPointFirst(List<PointD> points, bool islower = false)
    {
        var minX = points.Min(p => p.X);
        var maxX = points.Max(p => p.X);
        var minP = points.First(p => p.X == minX);
        var maxP = points.First(p => p.X == maxX);

        minP = points.First(p => p.X == minX);
        maxP = points.First(p => p.X == maxX);

        var pB = points.ToList();
        var len = pB.Count();
        //Temporary lists to hold data structures and points when performing the points sorting..
        var pDist = new List<PointDistance>();
        var distances = new List<Double>();
        int index = 0;
        //Sorted list to hold final points...
        var sorted = new List<PointD>();
        for (int i = 0; i < len; i++)
        {
            if (i > 0)
            {
                //Minimum point or "Point of Reference for comparison" is now the last point in the sorted list.
                minP = sorted[sorted.Count() - 1];
                //Clear the temporary lists used...
                pDist.Clear(); distances.Clear();
            }
            for (int j = 0; j < len - i; j++)
            {
                var distance = Math.Sqrt(Math.Pow(pB[j].X - minP.X, 2) + Math.Pow(pB[j].Y - minP.Y, 2));
                pDist.Add(new PointDistance() { X = pB[j].X, Y = pB[j].Y, distance = distance, index = index });
                distances.Add(distance);
            }
            //Order the data structure
            pDist = pDist.OrderBy(m => m.distance).ToList();
            //Convert to points list for use
            pB = pDist.Select(m => new PointD(m.X, m.Y)).ToList();
            //Get the first point and put it in the sorted list
            sorted.Add(pB[0]);
            //Remove the point from the pb list so that it is not considered again
            pB.RemoveAt(0);

            index++;
        }
        pDist = pDist.OrderBy(m => m.distance).ToList();
        distances = pDist.Select(m => m.distance).ToList();

        //The new code...
        points = sorted.ToList();

        //Get the minimum Point again as minP has been overwritten during the loop
        minX = points.Min(p => p.X);
        maxX = points.Max(p => p.X);
        minP = points.First(p => p.X == minX);
        maxP = points.First(p => p.X == maxX);
        //Check if minp does nott match the first point
        if ((minP != points[0] && maxP == points[0]) || (maxP != points[len - 1] && minP == points[len - 1]))
        {
            //Reverse only if the first point of array is not the minimum point
            points.Reverse();
        }
        return points;
    }

}
Community
  • 1
  • 1
Steve Johnson
  • 3,054
  • 7
  • 46
  • 71