Skip to content

Commit 4813d2c

Browse files
authored
math.vec: swap u and v in the .project() method of Vec2,Vec3,Vec4 (#25841)
1 parent 1a91193 commit 4813d2c

File tree

6 files changed

+60
-62
lines changed

6 files changed

+60
-62
lines changed

vlib/math/vec/vec2.v

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -264,22 +264,22 @@ pub fn (v Vec2[T]) perpendicular(u Vec2[T]) Vec2[T] {
264264
}
265265

266266
// project returns the projected vector.
267-
// The projection of vector `u` onto vector `v` is the orthogonal projection
268-
// of `u` onto a straight line parallel to `v` that passes through the origin.
269-
// This is equivalent to the vector projection of `u` onto the unit vector in the direction of `v`.
270-
// and is given by the formula: proj_v(u) = (u · v / |v|^2) * v
271-
// where "·" denotes the dot product and |v| is the magnitude of vector `v`.
272-
// If `u` is a zero vector, the result will also be a zero vector.
267+
// The projection of vector `v` onto vector `u` is the orthogonal projection
268+
// of `v` onto a straight line parallel to `u` that passes through the origin.
269+
// This is equivalent to the vector projection of `v` onto the unit vector in the direction of `u`.
270+
// and is given by the formula: proj_v(u) = (v · u / |u|^2) * u
271+
// where "·" denotes the dot product and |u| is the magnitude of vector `u`.
272+
// If `v` is a zero vector, the result will also be a zero vector.
273273
// example:
274274
// ```v
275275
// v := vec2[f32](3, 4)
276276
// u := vec2[f32](5, 6)
277277
// proj := v.project(u)
278-
// println(proj) // Output: vec2[f32](3.61, 4.81)
278+
// println(proj) // Output: vec2[f32](3.1967213, 3.8360658)
279279
// ```
280280
pub fn (v Vec2[T]) project(u Vec2[T]) Vec2[T] {
281-
scale := u.dot(v) / v.dot(v)
282-
return v.mul_scalar(scale)
281+
scale := T(v.dot(u) / u.dot(u))
282+
return u.mul_scalar(scale)
283283
}
284284

285285
// rotate_around_cw returns the vector `v` rotated *clockwise* `radians` around an origin vector `o` in Cartesian space.

vlib/math/vec/vec2_test.v

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -232,24 +232,24 @@ fn test_vec2_rotate_around_ccw_2() {
232232
// Test for Vec2 projection
233233
//
234234
fn test_vec2_project_onto_basic() {
235-
u := vec.vec2(3.0, 4.0) // magnitude 5 vector
236235
v := vec.vec2(5.0, 6.0) // magnitude ~7.81 vector
236+
u := vec.vec2(3.0, 4.0) // magnitude 5 vector
237237
// hand-computed:
238-
// u·v = 5*3 + 6*4 = 39
239-
// |v|^2 = 3^2 + 4^2 = 25
238+
// v·u = 5*3 + 6*4 = 39
239+
// |u|^2 = 3^2 + 4^2 = 25
240240
// scale = 39/25 = 1.56
241-
// proj = scale * v = (1.56*3, 1.56*4) = (4.68, 6.24)
242-
proj := u.project(v)
241+
// proj = scale * u = (1.56*3, 1.56*4) = (4.68, 6.24)
242+
proj := v.project(u)
243243
assert tolerance(proj.x, 4.68, vec.vec_epsilon)
244244
assert tolerance(proj.y, 6.24, vec.vec_epsilon)
245245
}
246246

247247
// Test for Vec2 projection onto zero vector
248248
// project v into the null vector
249249
fn test_vec2_project_onto_zero() {
250-
u := vec.vec2(0.0, 0.0)
251250
v := vec.vec2(5.0, 6.0)
252-
proj := u.project(v)
251+
u := vec.vec2(0.0, 0.0)
252+
proj := v.project(u)
253253
// must be nan
254254
assert is_nan(proj.x)
255255
assert is_nan(proj.y)
@@ -258,9 +258,9 @@ fn test_vec2_project_onto_zero() {
258258
// Test for Vec2 projection of zero vector
259259
// project a null vector
260260
fn test_vec2_project_zero_vector() {
261-
u := vec.vec2(3.0, 4.0)
262261
v := vec.vec2(0.0, 0.0)
263-
proj := u.project(v)
262+
u := vec.vec2(3.0, 4.0)
263+
proj := v.project(u)
264264
assert proj.x == 0.0
265265
assert proj.y == 0.0
266266
}
@@ -277,8 +277,8 @@ fn test_vec2_project_onto_self() {
277277
// Test for Vec2 projection onto orthogonal vector
278278
//
279279
fn test_vec2_project_onto_orthogonal() {
280-
u := vec.vec2(1.0, 0.0)
281280
v := vec.vec2(0.0, 1.0)
281+
u := vec.vec2(1.0, 0.0)
282282
proj := u.project(v)
283283
// more sensitive to floating point errors so i think close is better here
284284
assert close(proj.x, 0.0)
@@ -288,14 +288,14 @@ fn test_vec2_project_onto_orthogonal() {
288288
// Test for Vec2 projection with negative components
289289
//
290290
fn test_vec2_project_negative_components() {
291-
u := vec.vec2(-3.0, 4.0)
292291
v := vec.vec2(5.0, -6.0)
292+
u := vec.vec2(-3.0, 4.0)
293293
// hand-computed:
294-
// u·v = 5*-3 + -6*4 = -15 - 24 = -39
295-
// |v|^2 = -3^2 + 4^2 = 9 + 16 = 25
294+
// v·u = 5*-3 + -6*4 = -15 - 24 = -39
295+
// |u|^2 = -3^2 + 4^2 = 9 + 16 = 25
296296
// scale = -39/25 = -1.56
297-
// proj = scale * v = (-1.56*-3, -1.56*4) = (4.68, -6.24)
298-
proj := u.project(v)
297+
// proj = scale * u = (-1.56*-3, -1.56*4) = (4.68, -6.24)
298+
proj := v.project(u)
299299
assert tolerance(proj.x, 4.68, vec.vec_epsilon)
300300
assert tolerance(proj.y, -6.24, vec.vec_epsilon)
301301
}

vlib/math/vec/vec3.v

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -260,18 +260,17 @@ pub fn (v Vec3[T]) perpendicular(u Vec3[T]) Vec3[T] {
260260
}
261261

262262
// project returns the projected vector.
263-
// The projection of vector `u` onto vector `v` is the orthogonal projection
264-
// of `u` onto a straight line parallel to `v` that passes through the origin.
265-
// This is equivalent to the vector projection of `u` onto the unit vector in the direction of `v`.
266-
// and is given by the formula: proj_v(u) = (u · v / |v|^2) * v
267-
// where "·" denotes the dot product and |v| is the magnitude of vector `v`.
268-
// If `u` is a zero vector, the result will also be a zero vector.
263+
// The projection of vector `v` onto vector `u` is the orthogonal projection
264+
// of `v` onto a straight line parallel to `u` that passes through the origin.
265+
// This is equivalent to the vector projection of `v` onto the unit vector in the direction of `u`.
266+
// and is given by the formula: proj_v(u) = (v · u / |u|^2) * u
267+
// where "·" denotes the dot product and |u| is the magnitude of vector `u`.
268+
// If `v` is a zero vector, the result will also be a zero vector.
269269
// example:
270270
// TODO: add examples
271-
// ```
272271
pub fn (v Vec3[T]) project(u Vec3[T]) Vec3[T] {
273-
scale := T(u.dot(v) / v.dot(v))
274-
return v.mul_scalar(scale)
272+
scale := T(v.dot(u) / u.dot(u))
273+
return u.mul_scalar(scale)
275274
}
276275

277276
// eq returns a bool indicating if the two vectors are equal.

vlib/math/vec/vec3_test.v

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,14 @@ fn test_vec3_f64_utils_2() {
9292

9393
// sample tests for vec3 projection
9494
fn test_vec3_project_onto_basic() {
95-
u := vec.vec3(3.0, 4.0, 0.0) // magnitude 5 vector
9695
v := vec.vec3(5.0, 6.0, 0.0) // magnitude ~7.81 vector
96+
u := vec.vec3(3.0, 4.0, 0.0) // magnitude 5 vector
9797
// hand-computed:
98-
// u·v = 5*3 + 6*4 + 0*0 = 39
99-
// |v|^2 = 3^2 + 4^2 +0^2 = 25
98+
// v·u = 5*3 + 6*4 + 0*0 = 39
99+
// |u|^2 = 3^2 + 4^2 +0^2 = 25
100100
// scale = 39/25 = 1.56
101-
// proj = scale * v = (1.56*3, 1.56*4, 1.56*0) = (4.68, 6.24, 0)
102-
proj := u.project(v)
101+
// proj = scale * u = (1.56*3, 1.56*4, 1.56*0) = (4.68, 6.24, 0)
102+
proj := v.project(u)
103103
assert veryclose(proj.x, 4.68)
104104
assert veryclose(proj.y, 6.24)
105105
assert veryclose(proj.z, 0.0)
@@ -108,9 +108,9 @@ fn test_vec3_project_onto_basic() {
108108
// Test for Vec3 projection onto zero vector
109109
//
110110
fn test_vec3_project_onto_zero() {
111-
u := vec.vec3(3.0, 4.0, 0.0)
112111
v := vec.vec3(0.0, 0.0, 0.0)
113-
proj := u.project(v)
112+
u := vec.vec3(3.0, 4.0, 0.0)
113+
proj := v.project(u)
114114
assert proj.x == 0.0
115115
assert proj.y == 0.0
116116
assert proj.z == 0.0
@@ -119,14 +119,14 @@ fn test_vec3_project_onto_zero() {
119119
// Test for vec3 projection at an angle
120120
//
121121
fn test_vec3_project_onto_angle() {
122-
u := vec.vec3(1.0, 0.0, 0.0) // magnitude 1 vector
123122
v := vec.vec3(1.0, 1.0, 0.0) // magnitude sqrt(2) vector
123+
u := vec.vec3(1.0, 0.0, 0.0) // magnitude 1 vector
124124
// hand-computed:
125-
// u·v = 1*1 + 0*1 + 0*0 = 1
126-
// |v|^2 = 1^2 + 0^2 +0^2 = 1
125+
// v·u = 1*1 + 1*0 + 0*0 = 1
126+
// |u|^2 = 1^2 + 0^2 +0^2 = 1
127127
// scale = 1/1 = 1
128-
// proj = scale * v = (1*1, 1*0, 1*0) = (1, 0, 0)
129-
proj := u.project(v)
128+
// proj = scale * u = (1*1, 1*0, 1*0) = (1, 0, 0)
129+
proj := v.project(u)
130130
assert veryclose(proj.x, 1.0)
131131
assert veryclose(proj.y, 0.0)
132132
assert veryclose(proj.z, 0.0)

vlib/math/vec/vec4.v

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -276,18 +276,17 @@ pub fn (v Vec4[T]) perpendicular(u Vec4[T]) Vec4[T] {
276276
}
277277

278278
// project returns the projected vector.
279-
// The projection of vector `u` onto vector `v` is the orthogonal projection
280-
// of `u` onto a straight line parallel to `v` that passes through the origin.
281-
// This is equivalent to the vector projection of `u` onto the unit vector in the direction of `v`.
282-
// and is given by the formula: proj_v(u) = (u · v / |v|^2) * v
283-
// where "·" denotes the dot product and |v| is the magnitude of vector `v`.
284-
// If `u` is a zero vector, the result will also be a zero vector.
279+
// The projection of vector `v` onto vector `u` is the orthogonal projection
280+
// of `v` onto a straight line parallel to `u` that passes through the origin.
281+
// This is equivalent to the vector projection of `v` onto the unit vector in the direction of `u`.
282+
// and is given by the formula: proj_v(u) = (v · u / |u|^2) * u
283+
// where "·" denotes the dot product and |u| is the magnitude of vector `u`.
284+
// If `v` is a zero vector, the result will also be a zero vector.
285285
// example:
286286
// TODO: add examples
287-
// ```
288287
pub fn (v Vec4[T]) project(u Vec4[T]) Vec4[T] {
289-
scale := u.dot(v) / v.dot(v)
290-
return v.mul_scalar(scale)
288+
scale := T(v.dot(u) / u.dot(u))
289+
return u.mul_scalar(scale)
291290
}
292291

293292
// eq returns a bool indicating if the two vectors are equal.

vlib/math/vec/vec4_test.v

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,24 +100,24 @@ fn test_vec4_f64_utils_2() {
100100

101101
// sample tests for vec4 projection
102102
fn test_vec4_project_onto_basic() {
103-
u := vec.vec4(3.0, 4.0, 0.0, 0.0) // magnitude 5 vector
104103
v := vec.vec4(5.0, 6.0, 0.0, 0.0) // magnitude ~7.81 vector
104+
u := vec.vec4(3.0, 4.0, 0.0, 0.0) // magnitude 5 vector
105105
// hand-computed:
106-
// u·v = 5*3 + 6*4 + 0*0 + 0*0 = 39
107-
// |v|^2 = 3^2 + 4^2 +0^2 +0^2 = 25
108-
proj := u.project(v)
109-
assert proj.x == 3.0
110-
assert proj.y == 4.0
106+
// v·u = 5*3 + 6*4 + 0*0 + 0*0 = 39
107+
// |u|^2 = 3^2 + 4^2 +0^2 +0^2 = 25
108+
proj := v.project(u)
109+
assert proj.x == 4.68
110+
assert proj.y == 6.24
111111
assert proj.z == 0.0
112112
assert proj.w == 0.0
113113
}
114114

115115
// Test for Vec4 projection onto zero vector
116116
//
117117
fn test_vec4_project_onto_zero() {
118-
u := vec.vec4(3.0, 4.0, 0.0, 0.0)
119118
v := vec.vec4(0.0, 0.0, 0.0, 0.0)
120-
proj := u.project(v)
119+
u := vec.vec4(3.0, 4.0, 0.0, 0.0)
120+
proj := v.project(u)
121121
assert proj.x == 0.0
122122
assert proj.y == 0.0
123123
assert proj.z == 0.0

0 commit comments

Comments
 (0)