【问题标题】:Find minimum distance between 2 points in 2 arrays查找 2 个数组中 2 个点之间的最小距离
【发布时间】:2014-01-21 04:09:03
【问题描述】:

我有 2 个包含点(x、y 和 z)的列表,并希望找到最近的点。

我认为我需要做这样的事情:

for (int i = 0; i < myarray1.Count; i++)
{
  for (int j = 0; j < myarray2.Count; j++)
  {
    // Calculate the quadratic distance between 2 points (point in index i and j)
    // Then store the minimum distance I guess?   
  }
}

【问题讨论】:

  • 您遇到的具体问题是什么?将高级想法转换为实际代码?你有任何特定的部分有问题吗?您是否有一些无法运行的实际代码,我们可以为您提供帮助?
  • 如果您关心效率,kd 树是您的最佳选择。

标签: c# algorithm distance min points


【解决方案1】:

计算距离:

double sqr(double x) {return x*x;}

double distance(MyPoint a, MyPoint b) {
  return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)+sqr(a.z-b.z);
}

然后在第二个循环中存储到目前为止找到的最小距离:

double d = distance(myarray1[i],myarray2[j]);
if (d<min_d) min_d = d;

其中 min_d 是在开头定义的:

double min_d = Float.MAX_VALUE;

【讨论】:

  • 如果pow 的基数是负数,你的方法就不起作用,所以你应该说pow(fabs(...), 2)Math.Pow(Math.Abs(...), 2)。更好的是,跳过pow 函数并实现平方xx*x。 (另外,如果您只是比较 距离以找到最短距离,那么比较 squaresm 就足够了,这消除了sqrt,但不可否认,这是在挑剔。)
  • @MOehm 当基数为 a.x-b.x 为负数且指数为正整数时,您确定 pow(a.x-b.x,2) 不起作用吗?
  • @chux:我很确定,因为我有pow(a, b) == exp(log(a) * b) 的概念,但事实证明我错了。我看过这个 MSDN 页面 (msdn.microsoft.com/de-de/library/…),但错过了关于非整数指数的部分。我不使用 C# 并且有 C 背景,但事实证明 C 的 pow 也可以处理具有整数指数的负基数。尽管如此,我还是更喜欢平方的简单乘法,并且打赌它会更快,即使只是略微。
  • 我很失望Java的Math库没有sqr函数……怎么会这样?
【解决方案2】:
  double min_dist = DOUBLE_MAX;
  for (i = 0; i < myarray1.Count; i++)
   {
     for (j = 0; j < myarray2.Count; j++)
     {
       curr_dist = dist(a[i],a[j]);  
       if( min_dist > curr_dist)
         {
              min_dist = curr_dist;
         }
     }
   }

在哪里

double dist(Point a, Point b) {
  return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2)+pow(a.z-b.z,2);
}

【讨论】:

  • 以 myarray2 为 900,000 个元素和 myarray1 250 为例,最后一个的性能如何?有更快的方法吗?
【解决方案3】:

另一种选择是使用Kd-tree
使用Nearest neighbour search 将为您提供O(log n) 复杂性来找到与给定点集最近的点,并且您的代码将具有O( n log n),而不是O (n^2)

请参阅here 了解如何使用它的实现和示例。

【讨论】:

    【解决方案4】:

    在 C# 中,我会使用 Linq 来做到这一点。

    首先,我将定义计算两点之间距离的函数,如 Emanuelle Paolini 的回答:

    public double Distance(Point p1, Point p2)
    {
       return Math.Sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p1.y) * (p1.y - p1.y) + (p1.z - p1.z) * (p1.z - p1.z));
    }
    

    然后我会查询这两个列表如下:

    var distanceQuery = from p1 in myarray1
                        from p2 in myarray2
                        select Dist(p1, p2);
    

    最后我会检索最小距离:

    var minimumDistance = distanceQuery.Min();
    

    【讨论】:

    • Linq 比执行 2 个 for 循环快吗?
    • 实际上,根据我运行的快速测试,Linq 在这里可能要慢得多。
    【解决方案5】:

    公式是

    Math.sqrt(Math.pow(Math.abs(x1-x2),2) + Math.pow(Math.abs(y1-y2),2)+ Math.pow(Math.abs(z1-z2),2))

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-10
      • 2018-03-01
      相关资源
      最近更新 更多