有效地找到顺时针排序点列表中新点的插入点(围绕中心点)

时间:2018-03-22 17:02:11

标签: list sorting geometry trigonometry

想象一下,我有一个有序的点列表,围绕一个中心点排列。

我有一个新点,我想在列表中包含,但保持围绕中心点的顺时针顺序。

最明显的解决方案是找到中心和新点之间的角度,循环遍历列表,计算每个点与中心之间的角度以找到插入点,但我相信有更好的方法并不需要使用三角函数(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;
    }
}

另一种可视化问题的方法是想象通过列表循环作为连续的点对,并询问新点是否位于由这两个点和中心点(眼睛)形成的无限截头体的眼线中,但是没有三角法可以做到吗?

1 个答案:

答案 0 :(得分:0)

您可以使用基于跨产品的CCW(逆时针/顺时针方向)功能(您已经拥有det)并实现一种二分搜索。

我认为避免循环问题的最简单方法是引入两个虚拟点P [M] - P [0]对中心的镜像和P [N + 1] - 列表末尾第一个点的副本。插入一次并在需要时更正M索引。

查找第一个和新点的CCW。如果为True,则在范围0..M中进行二进制搜索,并在插入后增加M.如果为False,则在范围M..N+1中进行二进制搜索