Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add new angle and angle_rad property for vector2 #3221

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions src_c/math.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,10 @@ static int
vector_sety(pgVector *self, PyObject *value, void *closure);
static int
vector_setz(pgVector *self, PyObject *value, void *closure);
static PyObject *static PyObject *
vector_get_angle(pgVector *self, void *closure);
static PyObject *
vector_get_angle_rad(pgVector *self, void *closure);
vector_richcompare(PyObject *o1, PyObject *o2, int op);
static PyObject *
vector_length(pgVector *self, PyObject *args);
Expand Down Expand Up @@ -1269,6 +1272,48 @@ vector_setz(pgVector *self, PyObject *value, void *closure)
return vector_set_component(self, value, 2);
}

static PyObject *
vector_get_angle(pgVector *self, void *closure)
{
pgVector *vec = (pgVector *)self;

if (vec->coords[0] == 0.0 && vec->coords[1] == 0.0) {
return PyFloat_FromDouble(0.0);
}

double angle = atan2(vec->coords[1], vec->coords[0]) * 180.0 / M_PI;

if (angle > 180.0) {
angle -= 360.0;
}
else if (angle <= -180.0) {
angle += 360.0;
}

return PyFloat_FromDouble(angle);
}

static PyObject *
vector_get_angle_rad(pgVector *self, void *closure)
{
pgVector *vec = (pgVector *)self;

if (vec->coords[0] == 0.0 && vec->coords[1] == 0.0) {
return PyFloat_FromDouble(0.0);
}

double angle_rad = atan2(vec->coords[1], vec->coords[0]);

if (angle_rad > M_PI) {
angle_rad -= 2 * M_PI;
}
else if (angle_rad <= -M_PI) {
angle_rad += 2 * M_PI;
}

return PyFloat_FromDouble(angle_rad);
}

static PyObject *
vector_richcompare(PyObject *o1, PyObject *o2, int op)
{
Expand Down Expand Up @@ -2585,6 +2630,8 @@ static PyMethodDef vector2_methods[] = {
static PyGetSetDef vector2_getsets[] = {
{"x", (getter)vector_getx, (setter)vector_setx, NULL, NULL},
{"y", (getter)vector_gety, (setter)vector_sety, NULL, NULL},
{"angle", (getter)vector_get_angle, NULL, NULL, NULL},
{"angle_rad", (getter)vector_get_angle_rad, NULL, NULL, NULL},
{NULL, 0, NULL, NULL, NULL} /* Sentinel */
};

Expand Down
60 changes: 60 additions & 0 deletions test/math_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1363,6 +1363,66 @@ def test_del_y(self):
exception = ctx.exception
self.assertEqual(str(exception), "Cannot delete the y attribute")

def test_vector_get_angle_zero_vector(self):
vec = Vector2(0, 0)
self.assertEqual(vec.angle, 0.0)

def test_vector_get_angle_rad_zero_vector(self):
vec = Vector2(0, 0)
self.assertEqual(vec.angle_rad, 0.0)

def test_vector_get_angle_on_axes(self):
vec1 = Vector2(1, 0)
self.assertEqual(vec1.angle, 0.0)

vec2 = Vector2(0, 1)
self.assertEqual(vec2.angle, 90.0)

vec3 = Vector2(-1, 0)
self.assertEqual(vec3.angle, 180.0)

vec4 = Vector2(0, -1)
self.assertEqual(vec4.angle, -90.0)

def test_vector_get_angle_rad_on_axes(self):
vec1 = Vector2(1, 0)
self.assertEqual(vec1.angle_rad, 0.0)

vec2 = Vector2(0, 1)
self.assertEqual(vec2.angle_rad, math.pi / 2)

vec3 = Vector2(-1, 0)
self.assertEqual(vec3.angle_rad, math.pi)

vec4 = Vector2(0, -1)
self.assertEqual(vec4.angle_rad, -math.pi / 2)

def test_vector_get_angle_in_quadrants(self):
vec1 = Vector2(1, 1)
self.assertEqual(vec1.angle, 45.0)

vec2 = Vector2(-1, 1)
self.assertEqual(vec2.angle, 135.0)

vec3 = Vector2(-1, -1)
self.assertEqual(vec3.angle, -135.0)

vec4 = Vector2(1, -1)
self.assertEqual(vec4.angle, -45.0)

def test_vector_get_angle_rad_in_quadrants(self):
vec1 = Vector2(1, 1)
self.assertEqual(vec1.angle_rad, math.pi / 4)

vec2 = Vector2(-1, 1)
self.assertEqual(vec2.angle_rad, 3 * math.pi / 4)

vec3 = Vector2(-1, -1)
self.assertEqual(vec3.angle_rad, -3 * math.pi / 4)

vec4 = Vector2(1, -1)
self.assertEqual(vec4.angle_rad, -math.pi / 4)


class Vector3TypeTest(unittest.TestCase):
def setUp(self):
Expand Down