9

我正在使用格雷厄姆扫描算法来查找点集的凸包我试图通过它们的极角对点进行排序,但我不知道该怎么做(我已经通过它们对点集进行了排序Y 坐标)。

我已经写的是这样的:

public double angle(Coord o, Coord a)
{
    return Math.atan((double)(a.y - o.y) / (double)(a.x - o.x));
}

Coord我有 X 和 Y 坐标的类在哪里double

我还查看了 Stack Overflow 中的一篇类似帖子,其中有人试图用 C++ 实现这个角度,但我不明白qsqrt。我们在 Java 中有类似的东西吗?

qreal Interpolation::dp(QPointF pt1, QPointF pt2)
{
    return (pt2.x()-pt1.x())/qSqrt((pt2.x()-pt1.x())*(pt2.x()-pt1.x()) + (pt2.y()-pt1.y())*(pt2.y()-pt1.y()));
}

如果有人可以帮助我,我会很高兴。

4

3 回答 3

17

您无需计算极角即可对其进行排序。由于三角函数在一个象限内是单调的(总是增加或总是减少),只需按函数本身排序,例如您的案例中的棕褐色。如果您从最底点开始实施格雷厄姆扫描,您只需要查看前两个象限,因此最容易按 cotan 排序,因为它在两个象限上都是单调的。

换句话说,您可以按- (x - x1) / (y - y1)(其中 (x1, y1) 是起点的坐标)进行排序,这样计算起来会更快。首先,您y == y1当然需要将位置分隔开,然后根据 (x - x1)` 的符号将它们添加到列表的顶部或底部,但它们很容易识别,因为您已经排序通过 y 找到您的起点。

于 2013-05-12T16:36:53.817 回答
7

如上所述,计算极角本身是一种非常草率的处理方式。您可以定义一个简单的比较器并使用叉积按极角排序。这是 C++ 中的代码(我将其用于我自己的 Graham 扫描):

struct Point {
    int x, y;
}

int operator^(Point p1, Point p2) {
    return p1.x * p2.y - p1.y * p2.x;
}

bool operator<(Point p1, Point p2) 
{
    if(p1.y == 0 && p1.x > 0) 
        return true; //angle of p1 is 0, thus p2 > p1

    if(p2.y == 0 && p2.x > 0) 
        return false; //angle of p2 is 0 , thus p1 > p2

    if(p1.y > 0 && p2.y < 0) 
        return true; //p1 is between 0 and 180, p2 between 180 and 360

    if(p1.y <0 && p2.y > 0) 
         return false;

    return (p1 ^ p2) > 0; //return true if p1 is clockwise from p2
}

Point您可以通过定义一个类在 Java 中实现相同的功能。基本上我已经重载了^运算符以返回叉积。其余的很明显,希望这有帮助!

于 2013-06-11T16:29:30.453 回答
0

Math.atan()返回 -pi/2 到 pi/2 之间的角度。您必须调整其他两个坐标的结果。

如果您想要与凸包中心的角度,则必须首先平移坐标,以使质心为原点。

于 2013-05-12T15:58:45.873 回答