Skip to content

Commit

Permalink
adding helper function _pg_atan2 + docs modification
Browse files Browse the repository at this point in the history
  • Loading branch information
AntoineMamou committed Nov 23, 2024
1 parent 71c12a7 commit 23f426f
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 48 deletions.
6 changes: 4 additions & 2 deletions buildconfig/stubs/pygame/math.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,10 @@ class Vector2(_GenericVector):
xy: Vector2
yx: Vector2
yy: Vector2
angle: float
angle_rad: float
@property
def angle(self) -> float: ...
@property
def angle_rad(self) -> float: ...
@overload
def __init__(
self: _TVec,
Expand Down
12 changes: 6 additions & 6 deletions docs/reST/ref/math.rst
Original file line number Diff line number Diff line change
Expand Up @@ -618,21 +618,21 @@ Multiple coordinates can be set using slices or swizzling

.. attribute:: angle

| :sl:`Gives the angle of the vector in degrees, relative to the X-axis, normalized to the interval (-180, 180].`
| :sl:`Gives the angle of the vector in degrees, relative to the X-axis, normalized to the interval [-180, 180].`
Read-only attribute representing the angle of the vector in degrees relative to the X-axis. This angle is normalized to
the interval (-180, 180].
the interval [-180, 180].

Usage: Accessing `angle` provides the current angle of the vector in degrees within the specified range.
Usage: Accessing `angle` provides the current angle of the vector in degrees within the predefined range of [-180, 180].

.. attribute:: angle_rad

| :sl:`Gives the angle of the vector in radians, relative to the X-axis, normalized to the interval (-π, π].`
| :sl:`Gives the angle of the vector in radians, relative to the X-axis, normalized to the interval [-π, π].`
Read-only attribute representing the angle of the vector in radians relative to the X-axis. This value is equivalent
to the `angle` attribute converted to radians and is normalized to the interval (-π, π].
to the `angle` attribute converted to radians and is normalized to the interval [-π, π].

Usage: Accessing `angle_rad` provides the current angle of the vector in radians within the specified range.
Usage: Accessing `angle_rad` provides the current angle of the vector in radians within the predefined range of [-π, π].

.. ## pygame.math.Vector2 ##
Expand Down
4 changes: 2 additions & 2 deletions src_c/doc/math_doc.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
#define DOC_MATH_VECTOR2_CLAMPMAGNITUDEIP "clamp_magnitude_ip(max_length, /) -> None\nclamp_magnitude_ip(min_length, max_length, /) -> None\nClamps the vector's magnitude between max_length and min_length"
#define DOC_MATH_VECTOR2_UPDATE "update() -> None\nupdate(int) -> None\nupdate(float) -> None\nupdate(Vector2) -> None\nupdate(x, y) -> None\nupdate((x, y)) -> None\nSets the coordinates of the vector."
#define DOC_MATH_VECTOR2_EPSILON "Determines the tolerance of vector calculations."
#define DOC_MATH_VECTOR2_ANGLE "Gives the angle of the vector in degrees, relative to the X-axis, normalized to the interval (-180, 180]."
#define DOC_MATH_VECTOR2_ANGLERAD "Gives the angle of the vector in radians, relative to the X-axis, normalized to the interval (-π, π]."
#define DOC_MATH_VECTOR2_ANGLE "Gives the angle of the vector in degrees, relative to the X-axis, normalized to the interval [-180, 180]."
#define DOC_MATH_VECTOR2_ANGLERAD "Gives the angle of the vector in radians, relative to the X-axis, normalized to the interval [-π, π]."
#define DOC_MATH_VECTOR3 "Vector3() -> Vector3(0, 0, 0)\nVector3(int) -> Vector3\nVector3(float) -> Vector3\nVector3(Vector3) -> Vector3\nVector3(x, y, z) -> Vector3\nVector3((x, y, z)) -> Vector3\na 3-Dimensional Vector"
#define DOC_MATH_VECTOR3_DOT "dot(Vector3, /) -> float\ncalculates the dot- or scalar-product with the other vector"
#define DOC_MATH_VECTOR3_CROSS "cross(Vector3, /) -> Vector3\ncalculates the cross- or vector-product"
Expand Down
82 changes: 44 additions & 38 deletions src_c/math.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ _vector_coords_from_string(PyObject *str, char **delimiter, double *coords,
static void
_vector_move_towards_helper(Py_ssize_t dim, double *origin_coords,
double *target_coords, double max_distance);
static double
_pg_atan2(double y, double x);

/* generic vector functions */
static PyObject *
pgVector_NEW(Py_ssize_t dim);
Expand Down Expand Up @@ -637,6 +640,40 @@ vector_dealloc(pgVector *self)
Py_TYPE(self)->tp_free((PyObject *)self);
}

/*
*Returns rhe arctangent of the quotient y / x, in radians, considering the
*following special cases: atan2((anything), NaN ) is NaN; atan2(NAN ,
*(anything) ) is NaN; atan2(+-0, +(anything but NaN)) is +-0 ; atan2(+-0,
*-(anything but NaN)) is +-pi ; atan2(+-(anything but 0 and NaN), 0) is
*+-pi/2; atan2(+-(anything but INF and NaN), +INF) is +-0 ; atan2(+-(anything
*but INF and NaN), -INF) is +-pi; atan2(+-INF,+INF ) is +-pi/4 ;
* atan2(+-INF,-INF ) is +-3pi/4;
* atan2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2;
*
*/
static double
_pg_atan2(double y, double x)
{
if (Py_IS_NAN(x) || Py_IS_NAN(y)) {
return Py_NAN;
}

if (Py_IS_INFINITY(y)) {
if (Py_IS_INFINITY(x)) {
return copysign((copysign(1., x) == 1.) ? 0.25 * Py_MATH_PI
: 0.75 * Py_MATH_PI,
y);
}
return copysign(0.5 * Py_MATH_PI, y);
}

if (Py_IS_INFINITY(x) || y == 0.) {
return copysign((copysign(1., x) == 1.) ? 0. : Py_MATH_PI, y);
}

return atan2(y, x);
}

/**********************************************
* Generic vector PyNumber emulation routines
**********************************************/
Expand Down Expand Up @@ -1276,51 +1313,20 @@ vector_setz(pgVector *self, PyObject *value, void *closure)
}

static PyObject *
vector_get_angle(pgVector *self, void *closure)
vector_get_angle_rad(pgVector *self, void *closure)
{
PyObject *angle_obj = vector_get_angle_rad(self, closure);
double angle_rad = PyFloat_AsDouble(angle_obj);
double angle_deg = angle_rad * RAD_TO_DEG;

if (angle_deg > 180.0) {
angle_deg -= 360.0;
}
else if (angle_deg <= -180.0) {
angle_deg += 360.0;
}
double angle_rad = _pg_atan2(self->coords[1], self->coords[0]);

return PyFloat_FromDouble(angle_deg);
return PyFloat_FromDouble(angle_rad);
}

static PyObject *
vector_get_angle_rad(pgVector *self, void *closure)
vector_get_angle(pgVector *self, void *closure)
{
pgVector *vec = self;
double x = vec->coords[0];
double y = vec->coords[1];

if (Py_IS_NAN(x) || Py_IS_NAN(y)) {
return PyFloat_FromDouble(Py_NAN);
}

if (Py_IS_INFINITY(y)) {
if (Py_IS_INFINITY(x)) {
if (copysign(1., x) == 1.)
return PyFloat_FromDouble(copysign(0.25 * Py_MATH_PI, y));
else
return PyFloat_FromDouble(copysign(0.75 * Py_MATH_PI, y));
}
return PyFloat_FromDouble(copysign(0.5 * Py_MATH_PI, y));
}

if (Py_IS_INFINITY(x) || y == 0.) {
if (copysign(1., x) == 1.)
return PyFloat_FromDouble(copysign(0., y));
else
return PyFloat_FromDouble(copysign(Py_MATH_PI, y));
}
double angle_rad = _pg_atan2(self->coords[1], self->coords[0]);
double angle_deg = angle_rad * RAD_TO_DEG;

return PyFloat_FromDouble(atan2(y, x));
return PyFloat_FromDouble(angle_deg);
}

static PyObject *
Expand Down

0 comments on commit 23f426f

Please sign in to comment.