如何在不消除坐标的情况下对浮点坐标进行排序?

时间:2015-01-13 19:00:07

标签: c# sorting floating-point coordinates grahams-scan

我有一个坐标列表,应该形成我需要排序的路径边缘。我正在尝试使用Grahams扫描并尝试了几个样本:

  1. GrhamsScan.cs
  2. ConvexHull.cs
  3. ConvexHull Algo
  4. 这些代码对于我所拥有的几个测试用例都失败了,我不确定是什么问题。

    编辑:

    这些坐标应该是切线的一部分。如果坐标没有排序,那么切线就会发生危险,而不是在风暴进展时可能是直的或弯曲的正确路径。

    我正在创建形成风暴路径的圆圈的切线。这里可以看到一个例子: enter image description here

    编辑#02

    如果形成切线的点是有序的,那么正确的形状(忽略末尾的半圆)应如下所示。

    enter image description here

    测试用例:

    测试用例#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}
    

    测试案例#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}
    

    测试用例#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}
    

    请指导我一个资源,算法或代码,我可以找到一个可靠的浮点坐标排序算法,并且在这样做时不会消除点。速度不是优先事项,准确性是优先考虑的事情。

    我很感激所有的投入。感谢

2 个答案:

答案 0 :(得分:1)

您遗憾地失去了曾经存在于气象数据中的时间毕业,并且这些点数无法到达您的身份 因此,您希望从一组点重建路径。一旦完成,这个答案正在考虑构建信封不应该是一个问题。

如果你有N分,那就有N分!可能的排序。

在这些排序中,您必须选择最大化代表风暴轨迹的可能性。

一个天真的标准可能是最小化路径长度。更先进的一个可以考虑到风暴速度不能立即改变,因此或多或少地惩罚加速度。或加速度的导数......但这可能需要关于时间采样规律性的其他假设。

在所有情况下,您都必须注入风暴轨迹应该是什么样的模型,并将某种分数(概率)与各种假设(可能的轨迹)联系起来。

除非你的点数非常小,否则你不会在整个组合上进行迭代。相反,您将从一个任意点开始重建轨迹。然后,您将尝试通过迭代添加点来扩展一侧或另一侧的轨迹。您将先验地选择一组最可能的候选者(如同目前为止的重建轨迹的最近点,或者最接近已经重建的轨迹的外推,具有恒定速度或恒定加速度假设......)。

一个简单的算法将在每一步选择最可能的候选者。

更严肃的算法将并行重建几个可能的轨迹,并根据一些概率选择规则消除最不可能的轨迹。

我发现这类问题与使用RADAR跟踪目标密切相关,所以你可能会看一下这些文献,特别是对贝叶斯集合概率感兴趣。我希望你喜欢数学。

答案 1 :(得分:0)

这是我写的,最终适用于所有案例。我承认它可以改进性能,这可能是一种快速而肮脏的方式,但这正是我目前正在使用的。

P.S:我也承认" Convex Hull"或者" Graham Scan"从来没有我需要的东西,与所需要的东西无关。所以从技术上讲,这是我的错。我需要先按@ Chris建议的最近点对点进行排序。

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

}