【发布时间】:2018-03-22 17:02:10
【问题描述】:
假设我有一个有序的点列表,围绕一个中心点排列。
我有一个新点要包含在列表中,但保持围绕中心点的顺时针顺序。
最明显的解决方案是找到中心与新点之间的角度,循环遍历列表,计算每个点与中心之间的角度以找到插入点,但我相信有更好的方法不需要使用三角函数 (Math.atan2)。
我遇到了一个有用的排序算法,它可以使用叉积对中心点周围的点数组进行完美排序,但我不知道如何针对我的问题重新设计:
public class Vector2ClockwiseComparer : IComparer<Vector2>
{
public Vector2 center;
public Vector2ClockwiseComparer(Vector2 center)
{
this.center = center;
}
public int Compare(Vector2 v0, Vector2 v1)
{
if (v0.x - center.x >= 0 && v1.x - center.x < 0)
return 1;
if (v0.x - center.x < 0 && v1.x - center.x >= 0)
return -1;
if (v0.x - center.x == 0 && v1.x - center.x == 0) {
if (v0.y - center.y >= 0 || v1.y - center.y >= 0)
if (v0.y > v1.y)
return 1;
else return -1;
if (v1.y > v0.y)
return 1;
else return -1;
}
// compute the cross product of vectors (CenterPoint -> a) x (CenterPoint -> b)
var det = (v0.x - center.x) * (v1.y - center.y) -
(v1.x - center.x) * (v0.y - center.y);
if (det < 0)
return 1;
if (det > 0)
return -1;
// points a and b are on the same line from the CenterPoint
// check which point is closer to the CenterPoint
var d1 = (v0.x - center.x) * (v0.x - center.x) +
(v0.y - center.y) * (v0.y - center.y);
var d2 = (v1.x - center.x) * (v1.x - center.x) +
(v1.y - center.y) * (v1.y - center.y);
if (d1 > d2)
return 1;
else return -1;
}
}
另一种可视化问题的方法是将列表中的循环想象为连续的点对,并询问新点是否位于由这两个点和中心点(眼睛)形成的无限平截头体的视线中,但是没有三角函数可以做到吗?
【问题讨论】:
-
您可以使用此比较器通过二分搜索查找插入索引,就像通常使用标量一样。
Atan对于这个问题来说绝对是矫枉过正。
标签: list sorting geometry trigonometry