Add Vector2.angle
and Vector2.angle_rad
propertiesย #3195
Description
Proposal:
Add properties angle
and angle_rad
to pygame.Vector2
with getter and possibly a setter.
vec.angle_rad == math.atan2(vec.y, vec.x) == vec.as_polar()[1] # note: no vec.angle_rad_to() method
vec.angle == -vec.angle_to([1, 0]) == degrees(vec.angle_rad)
(These angles are normalized: degrees within interval (-180, 180], even if set to an angle outside this range.)
The zero vector has an angle of 0.
Reasons:
In math, the angle of a vector is often relative to the positive x-axis (increasing angle from 0 goes towards positive y-axis).
For example, polar coordinates and trigonometry functions are connected to vectors through their angle to positive x-axis.
vec == Vector2(r * cos(theta), r * sin(theta))
The current ways to get these angles are indirect and less readable, for such an (IMO) important aspect of vectors. See above. In as_polar()
result, the length is available via vec.length
, but the angle is not directly available.
In a codebase, it's convenient to only have to store one float (angle to +x axis) to mark the direction of something, rather than another vector (especially when the distance between two points is unnecessary/inapplicable). Many physics libraries or engines use angles like this heavily, usually using radians. Even if angles are technically only relative, to store them conveniently there has to be 'absolute' angles.
Example uses:
Calculate the angle of one position to another position, in degrees.
# Before
self.angle = (vec2 - vec1).angle_to([1, 0])
# After
self.angle = (vec2 - vec1).angle
Find the angle between two vectors, in radians.
# Before
self.angle_rad = math.radians(vec1.angle_to(vec2))
self.angle_rad = vec2.as_polar()[1] - vec1.as_polar()[1]
# After
self.angle_rad = vec2.angle_rad - vec1.angle_rad
Rotate a vector in-place at the direction of a given angle (from +x axis), in degrees.
# Before
vec.rotate_ip(angle - vec.angle_to([1, 0]))
# After
vec.angle = angle