0

My question is related to this one: c++ Sorting 2D Points clockwise, but somehow that solution doesn't work for me. I am trying to sort 4 2d points counter clockwise.

This is my code:

typedef struct p {
float x,y;
} Point;

double getClockwiseAngle(Point p) {
double angle = 0.0;

angle = atan2(p.x, -p.y);
return angle;
}

bool comparePoints(Point p1, Point p2) {
     return getClockwiseAngle(p1) < getClockwiseAngle(p2);
}

int main() {
    ...
    sort(givenPoints.begin(), givenPoints.end(), comparePoints);
    ...
}

Example: Input (-4, 2), (1, 4), (0,1), (-1, 4)

Output (-4, 2), (-1, 4), (1, 4), (0,1)

Cosmin Stoian
  • 19
  • 1
  • 8
  • The answer is using `-atan2`. You are using `atan2`. See the difference? – NathanOliver Oct 30 '18 at 21:14
  • Yup, you're right, but the output it's still wrong, it's just that now the points are incorrectly sorted clockwise, instead of counter clockwise. – Cosmin Stoian Oct 30 '18 at 21:17
  • Well, that is what you copied. If you don't change anything it wont sort differently. You probably need to change `getClockwiseAngle(p1) < getClockwiseAngle(p2)` to `getClockwiseAngle(p1) > getClockwiseAngle(p2)` – NathanOliver Oct 30 '18 at 21:18
  • Changing what you told me just brings me to my original output. You're basically moving a '-' from one place to another. – Cosmin Stoian Oct 30 '18 at 21:23
  • [Looks like it works here](http://coliru.stacked-crooked.com/a/7e3088b71ae0c861) – NathanOliver Oct 30 '18 at 21:27
  • @NathanOliver If you add `(0,1)` it will probably not work. – zdf Oct 31 '18 at 00:14

2 Answers2

0

I believe there were 2 negative signs that needed to be fixed as indicated in the comment. This seems to work:

#include <iostream>
#include <vector>
#include <cmath>

typedef struct p {
    float x,y;
} Point;

double getClockwiseAngle(Point p) {
    double angle = 0.0;

    angle = -1 * atan2(p.x, -1 * p.y);
    return angle;
}

bool comparePoints(Point p1, Point p2) {
    return getClockwiseAngle(p1) < getClockwiseAngle(p2);
}

int main() {
    std::vector<Point> givenPoints{{-4,2}, {1,4}, {0,1}, {-1,4}};
    sort(givenPoints.begin(), givenPoints.end(), comparePoints);
    std::cout << "Sorted Points: ";

    for(auto it = givenPoints.begin(); it != givenPoints.end(); it++) {
        std::cout << "(" << it->x << ", " << it->y << ")" ;
    }
    std::cout << std::endl;

}

Output:

Sorted Points: (0, 1)(1, 4)(-4, 2)(-1, 4)

Process finished with exit code 0
Gardener
  • 2,591
  • 1
  • 13
  • 22
  • This is exactly how I ended up implementing it, but it's still not outputing the wright answer. The correct is (0, 1), (1, 4), (-1, 4), (-4, 2). Neither, your program, nor mine outputs this result. – Cosmin Stoian Oct 30 '18 at 22:54
  • Moving clockwise around the circle, (-4,2) comes before (-1,4). Draw it out on a piece of graph paper. The program is working correctly. – Gardener Oct 30 '18 at 23:22
0
  • To sort the points starting from 12 o’clock, counterclockwise, you first have to rotate them -90degrees (12 o’clock becomes 3 o’clock):

    x’ = y
    y’ = -x
    
  • atan2 is using arguments signs to compute the quadrant. The following lines are not equivalent:

    bool b = atan2(0.0, 1.0) < atan2(0.0, -1.0); // true
    bool b = atan2(-0.0, 1.0) < atan2(-0.0, -1.0); // false
    

    Therefore you cannot use atan2 to sort the points.

Instead of atan2( -x, y) try atan2( x == .0f ? .0f : -x, y ) - not tested.

zdf
  • 4,382
  • 3
  • 18
  • 29
  • atan() or atan2() seem to be way too expensive. A simple y/x should do the trick. Different cases for positive, zero and negative x must be implemented though. – Karl Zeilhofer Oct 31 '18 at 00:50