【问题标题】:C# Sort List of X,Y Coordinates ClockwiseC#顺时针排序X,Y坐标列表
【发布时间】:2011-10-23 05:46:52
【问题描述】:

我使用的是 .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 

这些已按正确顺序排序,但调用排序函数会产生:

15778082, 27738210
15778066, 27738237
15778185, 27738269
15778169, 27738296

现在取另一组样本点:

15778180, 27738255
15778081, 27738192
15778064, 27738219
15778163, 27738282 

此列表的顺序不正确,调用排序函数会产生:

15778064, 27738219
15778081, 27738192
15778180, 27738255
15778163, 27738282

排序正确。对于已经排序的每组坐标和未排序的坐标,这种模式都会自我重复。有什么想法吗?

【问题讨论】:

  • 你真的应该将你的参考点传递给方法,而不是参考(没有双关语)一个“全局”变量。

标签: c# sorting coordinates


【解决方案1】:
if (aTanA < aTanB) return -1;
else if (aTanB > aTanA) return 1;

这两个条件是一样的! 要么交换变量将不等号转过来,但不能同时进行。

【讨论】:

  • 现在我觉得自己很愚蠢,我在玩那个函数,然后把那行打错了。谢谢。
【解决方案2】:

除了 Henning 的出色观察之外,一旦您解决了该问题,您可能还会对输出感到惊讶。

与完全有序域上的正常排序相比,圆形对称性使其成为一种有点不寻常的排序算法。由于存在圆形对称,因此有 n 个有效的顺时针排序,给定 n 个点,您可能更喜欢这些排序中的哪一个。

就目前而言,使用未修改的 atan2 将导致切割线的坐标为 (x,0),其中 x

考虑相对于参考测量的坐标 A = (-10, 1) 和 B = (-10, -1)。您可能会认为 A 应该在结果中出现在 B 之前,但实际上情况正好相反,因为 atan2 返回的 A 仅小于 π,但 B 仅大于 -π。

如果您想要一条坐标为 (x,0) 且 x>0 的切割线,只需将 2π 添加到从 atan2 返回的任何负值。

【讨论】:

  • 出色的观察力。我注意到在 -X 平面上有 2 个(或更多)点的情况相同。关于解决方案的好建议...如果 (X == ref.X),我正要着手做一些更困难的事情。
【解决方案3】:

不应该是这样的:

else if(aTanA > aTanB) return 1;

不确定这是否会导致您的问题。

【讨论】:

    猜你喜欢
    • 2018-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-29
    • 1970-01-01
    • 2012-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多