Skip to content

Commit 4f98fe9

Browse files
authored
math.vec: add rotate_around_* (cw/ccw) functions to vec.Vec2[T] (#23807)
1 parent 537605a commit 4f98fe9

2 files changed

Lines changed: 86 additions & 1 deletion

File tree

‎vlib/math/vec/vec2.v‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,23 @@ pub fn (v Vec2[T]) project(u Vec2[T]) Vec2[T] {
258258
return u.mul_scalar(percent)
259259
}
260260

261+
// rotate_around_cw returns the vector `v` rotated *clockwise* `radians` around an origin vector `o` in Cartesian space.
262+
pub fn (v Vec2[T]) rotate_around_cw(o Vec2[T], radians f64) Vec2[T] {
263+
return v.rotate_around_ccw(o, -radians)
264+
}
265+
266+
// rotate_around_ccw returns the vector `v` rotated *counter-clockwise* `radians` around an origin vector `o` in Cartesian space.
267+
pub fn (v Vec2[T]) rotate_around_ccw(o Vec2[T], radians f64) Vec2[T] {
268+
s := math.sin(radians)
269+
c := math.cos(radians)
270+
dx := v.x - o.x
271+
dy := v.y - o.y
272+
return Vec2[T]{
273+
x: T(c * dx - s * dy + o.x)
274+
y: T(s * dx + c * dy + o.y)
275+
}
276+
}
277+
261278
// eq returns a bool indicating if the two vectors are equal.
262279
@[inline]
263280
pub fn (v Vec2[T]) eq(u Vec2[T]) bool {

‎vlib/math/vec/vec2_test.v‎

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import math { close, veryclose }
1+
import math { close, radians, veryclose }
22
import math.vec
33

44
fn test_vec2_int() {
@@ -160,3 +160,71 @@ fn test_vec2_angle_towards() {
160160
}
161161
}
162162
}
163+
164+
fn test_vec2_rotate_around_cw() {
165+
origin := vec.vec2(0.0, 0.0)
166+
mut v := vec.vec2(0.0, 1.0)
167+
v = v.rotate_around_cw(origin, radians(90))
168+
assert close(v.x, 1.0)
169+
assert close(v.y, 0.0)
170+
v = v.rotate_around_cw(origin, radians(90))
171+
assert close(v.x, 0.0)
172+
assert close(v.y, -1.0)
173+
v = v.rotate_around_cw(origin, radians(90))
174+
assert close(v.x, -1.0)
175+
assert close(v.y, 0.0)
176+
v = v.rotate_around_cw(origin, radians(90))
177+
assert close(v.x, 0.0)
178+
assert close(v.y, 1.0)
179+
}
180+
181+
fn test_vec2_rotate_around_ccw() {
182+
origin := vec.vec2(0.0, 0.0)
183+
mut v := vec.vec2(0.0, 1.0)
184+
v = v.rotate_around_ccw(origin, radians(90))
185+
assert close(v.x, -1.0)
186+
assert close(v.y, 0.0)
187+
v = v.rotate_around_ccw(origin, radians(90))
188+
assert close(v.x, 0.0)
189+
assert close(v.y, -1.0)
190+
v = v.rotate_around_ccw(origin, radians(90))
191+
assert close(v.x, 1.0)
192+
assert close(v.y, 0.0)
193+
v = v.rotate_around_ccw(origin, radians(90))
194+
assert close(v.x, 0.0)
195+
assert close(v.y, 1.0)
196+
}
197+
198+
fn test_vec2_rotate_around_cw_2() {
199+
origin := vec.vec2(1.0, 1.0)
200+
mut v := vec.vec2(1.0, 2.0)
201+
v = v.rotate_around_cw(origin, radians(90))
202+
assert close(v.x, 2.0)
203+
assert close(v.y, 1.0)
204+
v = v.rotate_around_cw(origin, radians(90))
205+
assert close(v.x, 1.0)
206+
assert close(v.y, 0.0)
207+
v = v.rotate_around_cw(origin, radians(90))
208+
assert close(v.x, 0.0)
209+
assert close(v.y, 1.0)
210+
v = v.rotate_around_cw(origin, radians(90))
211+
assert close(v.x, 1.0)
212+
assert close(v.y, 2.0)
213+
}
214+
215+
fn test_vec2_rotate_around_ccw_2() {
216+
origin := vec.vec2(-1.0, 1.0)
217+
mut v := vec.vec2(-1.0, -1.0)
218+
v = v.rotate_around_ccw(origin, radians(90))
219+
assert close(v.x, 1.0)
220+
assert close(v.y, 1.0)
221+
v = v.rotate_around_ccw(origin, radians(90))
222+
assert close(v.x, -1.0)
223+
assert close(v.y, 3.0)
224+
v = v.rotate_around_ccw(origin, radians(90))
225+
assert close(v.x, -3.0)
226+
assert close(v.y, 1.0)
227+
v = v.rotate_around_ccw(origin, radians(90))
228+
assert close(v.x, -1.0)
229+
assert close(v.y, -1.0)
230+
}

0 commit comments

Comments
 (0)