简体   繁体   English

如何从2个列表中获取最近的2个点<Point>

[英]How to get the closest 2 Points from 2 List<Point>

I have 2 Lists of Points: 我有2个要点列表:

        var listA = new List<Point>();
        listA.Add(new Point(10, 1));
        listA.Add(new Point(5, 5));
        listA.Add(new Point(15, 35));

        var listB = new List<Point>();
        listB.Add(new Point(1, 1));
        listB.Add(new Point(5, 4));
        listB.Add(new Point(35, 15));

Now I would like to do something like: 现在我想做些类似的事情:

        getClosesPoints(listA,listB, Out pointA, Out pointB);

I'm currently at the point where i'm able to check a List again 1 Point 我目前处于可以再次检查列表的位置1点

        private int NearestPoint(Point srcPt, List<Point> lookIn)
        {
            if (lookIn.Count == 1)
                return 0;

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

            Console.WriteLine("smallest Distance:" + smallestDistance.Key);
            return smallestDistance.Value;
        }

But I'm not sure how to expand this code to check 2 Lists. 但是我不确定如何扩展此代码以检查2个列表。

I'm assuming that you want the find the closest two points in two lists, where one of the points is in one list and the other point is in the other list. 我假设您想在两个列表中找到最接近的两个点,其中一个点在一个列表中,另一个点在另一个列表中。

You can solve this by using an inner and an outer loop. 您可以通过使用内部和外部循环来解决此问题。 The outer loop iterates through all the points from the first list; 外循环遍历第一个列表中的所有点。 for each of those points you use an inner loop to compare it with all the points from the second list. 对于每个点,您都可以使用内部循环将其与第二个列表中的所有点进行比较。

You then don't need to remember all the distances; 然后,您无需记住所有距离; you just need to remember the distance between the two closest points that you have found so far, and the closest points so far themselves. 您只需要记住到目前为止找到的两个最接近点之间的距离,以及到目前为止它们本身最接近的点。

You can also create a simple little class just to return the closest two points rather than returning the results via out parameters. 您还可以创建一个简单的小类,仅返回最接近的两个点,而不是通过out参数返回结果。 For convenience you can add a Distance() function to this class so you don't need to store the actual distance. 为了方便起见,您可以向该类添加Distance()函数,因此无需存储实际距离。 (However if you were using this value frequently then you might want to cache the distance in a local field rather than calculating it each time.) (但是,如果您经常使用此值,那么您可能希望将距离缓存在本地字段中,而不是每次都进行计算。)

Finally, the parameters to the FindClosestPoints() method can be IEnumerable<Point> rather than List<Point> which allows you to use it with many more collection types. 最后, FindClosestPoints()方法的参数可以是IEnumerable<Point>而不是List<Point> ,这使您可以将其用于更多收集类型。

Putting that all together gives something like this (a compilable console app): 将所有内容放在一起可以得到以下内容(可编译的控制台应用程序):

using System;
using System.Collections.Generic;
using System.Drawing;

namespace Demo
{
    // Class just used to return the result from FindClosestPoints()

    public sealed class ClosestPoints
    {
        public ClosestPoints(Point p1, Point p2)
        {
            _p1 = p1;
            _p2 = p2;
        }

        public Point P1 { get { return _p1; } }
        public Point P2 { get { return _p2; } }

        public double Distance()
        {
            double dx = P1.X - P2.X;
            double dy = P1.Y - P2.Y;

            return Math.Sqrt(dx*dx + dy*dy);
        }

        private readonly Point _p1;
        private readonly Point _p2;
    }

    public static class Program
    {
        public static void Main()
        {
            var listA = new List<Point>();
            listA.Add(new Point(10, 1));
            listA.Add(new Point(5, 5));
            listA.Add(new Point(15, 35));

            var listB = new List<Point>();
            listB.Add(new Point(1, 1));
            listB.Add(new Point(5, 4));
            listB.Add(new Point(35, 15));

            var answer = FindClosestPoints(listA, listB);

            Console.WriteLine("Closest points are {0} and {1}", answer.P1, answer.P2);
        }

        public static ClosestPoints FindClosestPoints(IEnumerable<Point> seq1, IEnumerable<Point> seq2)
        {
            double closest = double.MaxValue;
            ClosestPoints result = null;

            foreach (var p1 in seq1)
            {
                foreach (var p2 in seq2)
                {
                    double dx = p1.X - p2.X;
                    double dy = p1.Y - p2.Y;

                    double distance = dx*dx + dy*dy;

                    if (distance >= closest)
                        continue;

                    result = new ClosestPoints(p1, p2);
                    closest = distance;
                }
            }

            return result;
        }
    }
}

If you return the entire Key-Value-Pair from your method, you would be able to expand from one point to the whole list using a simple loop: 如果您从方法中返回整个键值对,则可以使用一个简单的循环从一个点扩展到整个列表:

KeyValuePoint<double,int> best = new KeyValuePair<double,int>(double.MaxValue, -1);
int best2 = -1;
for (int i = 0 ; i != list2.Count ; i++) {
    Point pt = list2[i];
    KeyValuePoint<double,int> current = NearestPoint(pt, list1);
    if (current.Key < best.Key) {
        best = current;
        best2 = i;
    }
}

At the end, best.Key has the shortest distance, best.Value has the index of the point in list1 , and best2 has the index of the point in list2 . 最后, best.Key具有最短的距离, best.Value具有list1中的点的索引,而best2具有list2中的点的索引。

Let us call the two sets of points as S1 and S2. 让我们将两组点称为S1和S2。 Let p1 be the iterator for S1 and p2 the iterator for S2. 令p1为S1的迭代器,而p2为S2的迭代器。 Let valueAt be a function which tells the value at iterator position (like p1 or p2). 令valueAt为一个告诉迭代器位置的值的函数(如p1或p2)。 Let dist be a function which computes the distance between two points. 令dist为计算两点之间距离的函数。 And, let dmin be the variable which will hold the distance between two points. 并且,使dmin为将保持两点之间距离的变量。

Assuming that these two sets can contain negative values as well, I propose the following logic : 假设这两个集合也可以包含负值,我提出以下逻辑:

  • sort S1 and S2 排序S1和S2
  • if valueAt (p1) < valueAt (p2) 如果valueAt(p1)<valueAt(p2)
    { d = dist (p1, p2 ); if ( dmin > dist ( p1, p2 ) ) { dmin = dist (p1, p2); record p1 and p2 as closest; }

     increment p1; 

    }

  • if valueAt (p1) > valueAt (p2) 如果valueAt(p1)> valueAt(p2)
    { d = dist (p1, p2 ); if ( dmin > dist ( p1, p2 ) ) { dmin = dist (p1, p2); record p1 and p2 as closest; }

     increment p2; 

    }

  • if valueAt (p1) == valueAt (p2) 如果valueAt(p1)== valueAt(p2)
    { record p1 and p2 as closest; }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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