|
51 | 51 |
|
52 | 52 | #define TWO_PI (2. * M_PI) |
53 | 53 |
|
| 54 | +#define RAD_TO_DEG (180.0 / M_PI) |
| 55 | +#define DEG_TO_RAD (M_PI / 180.0) |
| 56 | + |
54 | 57 | #ifndef M_PI_2 |
55 | 58 | #define M_PI_2 (M_PI / 2.0) |
56 | 59 | #endif /* M_PI_2 */ |
@@ -142,6 +145,8 @@ _vector_coords_from_string(PyObject *str, char **delimiter, double *coords, |
142 | 145 | static void |
143 | 146 | _vector_move_towards_helper(Py_ssize_t dim, double *origin_coords, |
144 | 147 | double *target_coords, double max_distance); |
| 148 | +static double |
| 149 | +_pg_atan2(double y, double x); |
145 | 150 |
|
146 | 151 | /* generic vector functions */ |
147 | 152 | static PyObject * |
@@ -202,6 +207,10 @@ vector_sety(pgVector *self, PyObject *value, void *closure); |
202 | 207 | static int |
203 | 208 | vector_setz(pgVector *self, PyObject *value, void *closure); |
204 | 209 | static PyObject * |
| 210 | +vector_get_angle(pgVector *self, void *closure); |
| 211 | +static PyObject * |
| 212 | +vector_get_angle_rad(pgVector *self, void *closure); |
| 213 | +static PyObject * |
205 | 214 | vector_richcompare(PyObject *o1, PyObject *o2, int op); |
206 | 215 | static PyObject * |
207 | 216 | vector_length(pgVector *self, PyObject *args); |
@@ -635,6 +644,40 @@ vector_dealloc(pgVector *self) |
635 | 644 | Py_TYPE(self)->tp_free((PyObject *)self); |
636 | 645 | } |
637 | 646 |
|
| 647 | +/* |
| 648 | + *Returns rhe arctangent of the quotient y / x, in radians, considering the |
| 649 | + *following special cases: atan2((anything), NaN ) is NaN; atan2(NAN , |
| 650 | + *(anything) ) is NaN; atan2(+-0, +(anything but NaN)) is +-0 ; atan2(+-0, |
| 651 | + *-(anything but NaN)) is +-pi ; atan2(+-(anything but 0 and NaN), 0) is |
| 652 | + *+-pi/2; atan2(+-(anything but INF and NaN), +INF) is +-0 ; atan2(+-(anything |
| 653 | + *but INF and NaN), -INF) is +-pi; atan2(+-INF,+INF ) is +-pi/4 ; |
| 654 | + * atan2(+-INF,-INF ) is +-3pi/4; |
| 655 | + * atan2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2; |
| 656 | + * |
| 657 | + */ |
| 658 | +static double |
| 659 | +_pg_atan2(double y, double x) |
| 660 | +{ |
| 661 | + if (Py_IS_NAN(x) || Py_IS_NAN(y)) { |
| 662 | + return Py_NAN; |
| 663 | + } |
| 664 | + |
| 665 | + if (Py_IS_INFINITY(y)) { |
| 666 | + if (Py_IS_INFINITY(x)) { |
| 667 | + return copysign((copysign(1., x) == 1.) ? 0.25 * Py_MATH_PI |
| 668 | + : 0.75 * Py_MATH_PI, |
| 669 | + y); |
| 670 | + } |
| 671 | + return copysign(0.5 * Py_MATH_PI, y); |
| 672 | + } |
| 673 | + |
| 674 | + if (Py_IS_INFINITY(x) || y == 0.) { |
| 675 | + return copysign((copysign(1., x) == 1.) ? 0. : Py_MATH_PI, y); |
| 676 | + } |
| 677 | + |
| 678 | + return atan2(y, x); |
| 679 | +} |
| 680 | + |
638 | 681 | /********************************************** |
639 | 682 | * Generic vector PyNumber emulation routines |
640 | 683 | **********************************************/ |
@@ -1303,6 +1346,23 @@ vector_setz(pgVector *self, PyObject *value, void *closure) |
1303 | 1346 | return vector_set_component(self, value, 2); |
1304 | 1347 | } |
1305 | 1348 |
|
| 1349 | +static PyObject * |
| 1350 | +vector_get_angle_rad(pgVector *self, void *closure) |
| 1351 | +{ |
| 1352 | + double angle_rad = _pg_atan2(self->coords[1], self->coords[0]); |
| 1353 | + |
| 1354 | + return PyFloat_FromDouble(angle_rad); |
| 1355 | +} |
| 1356 | + |
| 1357 | +static PyObject * |
| 1358 | +vector_get_angle(pgVector *self, void *closure) |
| 1359 | +{ |
| 1360 | + double angle_rad = _pg_atan2(self->coords[1], self->coords[0]); |
| 1361 | + double angle_deg = angle_rad * RAD_TO_DEG; |
| 1362 | + |
| 1363 | + return PyFloat_FromDouble(angle_deg); |
| 1364 | +} |
| 1365 | + |
1306 | 1366 | static PyObject * |
1307 | 1367 | vector_richcompare(PyObject *o1, PyObject *o2, int op) |
1308 | 1368 | { |
@@ -2675,6 +2735,9 @@ static PyMethodDef vector2_methods[] = { |
2675 | 2735 | static PyGetSetDef vector2_getsets[] = { |
2676 | 2736 | {"x", (getter)vector_getx, (setter)vector_setx, NULL, NULL}, |
2677 | 2737 | {"y", (getter)vector_gety, (setter)vector_sety, NULL, NULL}, |
| 2738 | + {"angle", (getter)vector_get_angle, NULL, DOC_MATH_VECTOR2_ANGLE, NULL}, |
| 2739 | + {"angle_rad", (getter)vector_get_angle_rad, NULL, |
| 2740 | + DOC_MATH_VECTOR2_ANGLERAD, NULL}, |
2678 | 2741 | {NULL, 0, NULL, NULL, NULL} /* Sentinel */ |
2679 | 2742 | }; |
2680 | 2743 |
|
|
0 commit comments