我正在使用.NET 2.0,因此我无法访问漂亮的Linq;但是,我编写了一些代码,用于顺时针/逆时针对点列表进行排序。
我的问题是,如果列表尚未排序,排序可以正常运行,但如果由于某种原因列表已经排序,则排序功能会失败。
如果有人可以帮我指出正确的方向,那我就是在徘徊。为什么这可能是原因。
以下是我对此类的调用:
positions.Sort(new Comparison<Position>(MapUtils.SortCornersClockwise));
这是SortCornersClockwise函数:
public static int SortCornersClockwise( Position A, Position B)
{
// Variables to Store the atans
double aTanA, aTanB;
// Reference Point
Pixels reference = Program.main.reference;
// Fetch the atans
aTanA = Math.Atan2(A.Pixel.Y - reference.Y, A.Pixel.X - reference.X);
aTanB = Math.Atan2(B.Pixel.Y - reference.Y, B.Pixel.X - reference.X);
// Determine next point in Clockwise rotation
if (aTanA < aTanB) return -1;
else if (aTanB > aTanA) return 1;
return 0;
}
我的参考位置是我确定点列表中每个点的相应角度的点。
现在说我有一个点列表:
15778066, 27738237
15778169, 27738296
15778185, 27738269
15778082, 27738210
这些已按正确的顺序排序,但调用sort函数会产生:
15778082, 27738210
15778066, 27738237
15778185, 27738269
15778169, 27738296
现在采取另一组样本点:
15778180, 27738255
15778081, 27738192
15778064, 27738219
15778163, 27738282
此列表的顺序不正确,调用sort函数会产生:
15778064, 27738219
15778081, 27738192
15778180, 27738255
15778163, 27738282
哪个是正确排序的。对于已经排序的每组坐标以及那些没有排序的坐标,这种模式会重复自我。有什么想法吗?
答案 0 :(得分:8)
if (aTanA < aTanB) return -1;
else if (aTanB > aTanA) return 1;
这两个条件是一样的! 交换变量或转换不等号,但不能同时转换。
答案 1 :(得分:3)
除了Henning所做的出色观察之外,一旦你解决了这个问题,你也可能对输出感到惊讶。
与完全有序域上的正常排序相比,圆对称使得这种排序算法有点不寻常。由于存在圆对称性,因此有n个有效的顺时针顺序,给定n个点,并且您可能对您喜欢哪些顺序很重要。
按照目前的情况,使用atan2未修改将导致带有坐标(x,0)的切割线,其中x <0。
考虑相对于参考测量的坐标A =( - 10,1)和B =( - 10,-1)。你可能想象A应该在结果中出现在B之前,但事实上它将是另一种方式,因为atan2对于A只返回小于π,但对于B只返回-π。
如果你想要一个坐标为(x,0)的切割线,其中x> 0,只需将2π加到atan2返回的任何负值上。
答案 2 :(得分:1)
不应该是:
else if(aTanA > aTanB) return 1;
不确定这是否会导致您的问题。