C++ 对二维点进行顺时针排序

3
我写了一个程序,以从12点钟方向开始顺时针排列图表上的点,使包含这些点的向量按照该顺序排序。我使用 atan2 来获取相对于 12 点钟方向的角度,然后根据象限进行调整。我正在尝试找出 bug 来源,因为它没有正确地对它们进行排序。因此,给定4个类似照片中的随机点,它应该按照在图片中展示的规则将它们排序为 P1、P2、P3、P4。order 以下是我的代码:
//sort_points.cpp
#include <iostream>
#include <math.h>
#include <algorithm>
#include <vector>

using namespace std;

class Point
{
    public:
        double x;
        double y;
        Point(double xx, double yy) : x(xx), y(yy) {}
        ~Point();   
        inline friend ostream& operator<<(ostream& output, const Point& point)
        {
            output << "[" << point.x << ", " << point.y <<"]";
            return output;
        }
};


Point::~Point() {;}


/* get quadrant from 12 o'clock*/
int get_quadrant (const Point& p)
{
    int result = 4; //origin

    if (p.x > 0 && p.y > 0)
        return 1;
    else if(p.x < 0 && p.y > 0)
        return 2;
    else if(p.x < 0 && p.y < 0)
        return 3;
    //else 4th quadrant
    return result;
}

double get_clockwise_angle(const Point& p)
{   
    double angle = 0.0;
    int quadrant = get_quadrant(p);

    /*making sure the quadrants are correct*/
    cout << "Point: " << p << " is on the " << quadrant << " quadrant" << endl;

    /*add the appropriate pi/2 value based on the quadrant. (one of 0, pi/2, pi, 3pi/2)*/
    switch(quadrant)
    {
        case 1:
            angle = atan2(p.x,p.y) * 180/M_PI;
            break;
        case 2:
            angle = atan2(p.y, p.x)* 180/M_PI;
            angle += M_PI/2;
            break;
        case 3:
            angle = atan2(p.x,p.y)* 180/M_PI;
            angle += M_PI;
            break;
        case 4:
            angle = atan2(p.y, p.x)* 180/M_PI;
            angle += 3*M_PI/2;
            break;
    }
    return angle;
}
bool compare_points(const Point& a, const Point& b)
{
    return (get_clockwise_angle(a) < get_clockwise_angle(b));
}
int main(int argc, char const *argv[])
{
    std::vector <Point> points;
    points.push_back( Point( 1, 3 ) );
    points.push_back( Point( 2, 1 ) );
    points.push_back( Point( -3, 2 ) );
    points.push_back( Point( -1, -1 ) );

    cout << "\nBefore sorting" << endl;
    for (int i = 0; i < points.size(); ++i)
    {
        cout << points.at(i) << endl;
    }

    std::sort(points.begin(), points.end(),compare_points);

    cout << "\nAfter sorting" << endl;
    for (int i = 0; i < points.size(); ++i)
    {
        cout << points.at(i) << endl;
    }
    return 0;
}

1
看起来你正在将弧度转换为角度,然后基于π加上某些数字。这些调整的目的是什么? - MikeCAT
atan2 函数返回从 3 点钟方向开始逆时针旋转的角度。 - qxz
@MikeCAT 这是为了获取相对于12点钟方向的顺时针角度。因为我想按照顺时针的方式对它们进行排序,所以需要比较每个点相对于12点钟方向的角度。 - i_use_the_internet
从文档中看,atan2似乎给出角度[-pi/2, pi/2],因此对于第二象限(atan2的输出为[-pi/2, 0]),您需要添加pi,结果为[pi/2 pi],第三象限为pi,第四象限为2pi。通过这种转换,所有角度都将是正的,并按逆时针顺序递增。 - Some Guy
@SomeGuy 那么按照顺序是+0、+pi、+pi、+2pi吗? - i_use_the_internet
1个回答

6

您无需进行调整。atan2将为您提供从x轴正方向开始的角度,逆时针在-PI到PI范围内。

首先,要使起点为y轴的正方向,请让我将参数传递给atan2,好像y轴的负方向是x轴的正方向,而x轴的正方向是y轴的正方向。

然后,这将使角度逆时针变动,因此需要取反角度以颠倒顺序。

double get_clockwise_angle(const Point& p)
{   
    double angle = 0.0;
    int quadrant = get_quadrant(p);

    /*making sure the quadrants are correct*/
    cout << "Point: " << p << " is on the " << quadrant << " quadrant" << endl;

    /*calculate angle and return it*/
    angle = -atan2(p.x,-p.y);
    return angle;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接