【问题标题】:sort list of points by distance in .NET在.NET中按距离排序点列表
【发布时间】:2014-06-26 22:27:53
【问题描述】:

我需要按距离对点列表进行排序。

所以例如

input : [[1,2],[5,10],[2,4]...]
output : [[1,2],[2,4],[5,10]...]  

(假设在几何上 [1,2] 和 [2,4] 是最近的,而 [2,4] 和 [5,10] 是最近的。

我需要它们对其进行排序,以便它们按距离排序,即在几何图上,点 a 最接近点 b ,点 b 最接近 c 等等。

有什么想法吗?

编辑:代码示例

public class Point
{
   public double X {get;set;}
   public double Y {get;set;}
}


List<Point> points = new List<Point>();

假设我的积分列表是按随机顺序填充的(不是按几何距离)。 所以积分看起来像......

点~[[1,2],[5,10],[2,4]...]

现在我的图表控件只取第一个和第二个点并在它们之间画一条线。这意味着它不关心它的几何顺序。 如果我只是提供上面的“点”列表,它会在每个点之间画线,从图表的角度来看,它看起来不正确,因为它们是“之字形”。

为了确保图表控件绘制一条直线(& 而不是之字形),我必须以正确的顺序传递点,这看起来像 ...

destination points ~ [[1,2],[2,4],[5,10]...]  

所以我的问题是如何实现这一点。

注意:此处不能更改图表控件。

谢谢

【问题讨论】:

  • 能否请您发布一个带有输入和输出的明确示例?提前谢谢你。
  • 哪一个会指向a?
  • 对于投票否决,请告诉我我在这里错过了哪些研究工作。以便我纠正它们!
  • 创建一个返回距离的方法(here),然后将该方法用于List.SortArray.Sort
  • @user25018 这不是排序。这是一个旅行推销员问题。

标签: c# .net geometry points


【解决方案1】:

代码首先在 '0' 索引处获取最接近 (0, 0) 的点,然后开始按与最后发现点的距离对点进行排序..

C#:

    List<Point> SortByDistance(List<Point> lst)
    {
        List<Point> output = new List<Point>();
        output.Add(lst[NearestPoint(new Point(0, 0), lst)]);
        lst.Remove(output[0]);
        int x = 0;
        for (int i = 0; i < lst.Count + x; i++)
        {
            output.Add(lst[NearestPoint(output[output.Count - 1], lst)]);
            lst.Remove(output[output.Count - 1]);
            x++;
        }
        return output;
    }

    int NearestPoint(Point srcPt, List<Point> lookIn)
    {
        KeyValuePair<double, int> smallestDistance = new KeyValuePair<double, int>();
        for (int i = 0; i < lookIn.Count; i++)
        {
            double distance = Math.Sqrt(Math.Pow(srcPt.X - lookIn[i].X, 2) + Math.Pow(srcPt.Y - lookIn[i].Y, 2));
            if (i == 0)
            {
                smallestDistance = new KeyValuePair<double, int>(distance, i);
            }
            else
            {
                if (distance < smallestDistance.Key)
                {
                    smallestDistance = new KeyValuePair<double, int>(distance, i);
                }
            }
        }
        return smallestDistance.Value;
    }

VB.Net:

Function SortByDistance(ByVal lst As List(Of Point)) As List(Of Point)
    Dim out As New List(Of Point)
    out.Add(lst(NearestPoint(New Point(0, 0), lst)))
    lst.Remove(out(0))
    Dim x As Integer = 0
    For i As Integer = 0 To lst.Count - 1 + x
        out.Add(lst(NearestPoint(out(out.Count - 1), lst)))
        lst.Remove(out(out.Count - 1))
        x += 1
    Next
    Return out
End Function

Function NearestPoint(ByVal srcPt As Point, ByVal lookIn As List(Of Point)) As Integer
    Dim smallestDistance As KeyValuePair(Of Double, Integer)
    For i As Integer = 0 To lookIn.Count - 1
        Dim distance As Double = Math.Sqrt(Math.Pow(srcPt.X - lookIn(i).X, 2) + Math.Pow(srcPt.Y - lookIn(i).Y, 2))
        If i = 0 Then
            smallestDistance = New KeyValuePair(Of Double, Integer)(distance, i)
        Else
            If distance < smallestDistance.Key Then
                smallestDistance = New KeyValuePair(Of Double, Integer)(distance, i)
            End If
        End If
    Next
    Return smallestDistance.Value
End Function

【讨论】:

  • @Tarec 是的,我知道,提问者使用了“vb.net”标签,现在他编辑了帖子并删除了标签...
  • 感谢您的建设性回复。
【解决方案2】:

我想你想要这个,Dijkstra's algorithm。有一个c#项目here

以下是该链接中未修改的代码

class Dijkstra
    {        
        private int rank = 0;
        private int[,] L;
        private int[] C; 
        public int[] D;
        private int trank = 0;
        public Dijkstra(int paramRank,int [,]paramArray)
        {
            L = new int[paramRank, paramRank];
            C = new int[paramRank];
            D = new int[paramRank];
            rank = paramRank;
            for (int i = 0; i < rank; i++)
            {
                for (int j = 0; j < rank; j++) {
                    L[i, j] = paramArray[i, j];
                }
            }

            for (int i = 0; i < rank; i++)
            {
                C[i] = i;
            }
            C[0] = -1;          
            for (int i = 1; i < rank; i++)
                D[i] = L[0, i];
        }
        public void DijkstraSolving()
        {            
            int minValue = Int32.MaxValue;
            int minNode = 0;
            for (int i = 0; i < rank; i++)
            {
                if (C[i] == -1)
                    continue;
                if (D[i] > 0 && D[i] < minValue)
                {
                    minValue = D[i];
                    minNode = i;
                }
            }
            C[minNode] = -1;
            for (int i = 0; i < rank; i++)
            { 
                if (L[minNode, i] < 0)
                    continue;
                if (D[i] < 0) {
                    D[i] = minValue + L[minNode, i];
                    continue;
                }
                if ((D[minNode] + L[minNode, i]) < D[i])
                    D[i] = minValue+ L[minNode, i];
            }
        }
        public void Run()
        {
            for (trank = 1; trank >rank; trank++)
            {
                DijkstraSolving();
                Console.WriteLine("iteration" + trank);
                for (int i = 0; i < rank; i++)
                    Console.Write(D[i] + " ");
                Console.WriteLine("");
                for (int i = 0; i < rank; i++)
                    Console.Write(C[i] + " ");
                Console.WriteLine("");                
            }
        }
 }

【讨论】:

    【解决方案3】:

    在图表中,一组点(x1,y1), (x2,y2), (x3,y3)...(xn,yn) 应该按任意一个坐标的值排序,因为它不是应该按顺序排列的最近的点,而是与 x 或 y (无论哪个轴)最近的点作为参考)坐标值。因此,要传递给图表的数组应该是:

    var orderedPoints=points.OrderBy(p=>p.X);
    

    在上图中,线 L1 的长度大于 L2。但是点 P2 而不是 P3 应该在 P1 之后,因为P2.X&lt;P3.X

    【讨论】:

    • 投反对票的人能否建议这个答案有什么问题?
    • 我带着我的救援投票来了!解决一个问题有点困难,实际上还没有正确建立。