mirror of
https://github.com/vlang/v.git
synced 2025-08-03 09:47:15 -04:00
math: add remap/5, smoothstep/3 and smootherstep/3 implementations + tests
This commit is contained in:
parent
35b1cff2d3
commit
e32283fd1c
@ -24,3 +24,38 @@ pub fn clip[T](x T, min_value T, max_value T) T {
|
||||
x
|
||||
}
|
||||
}
|
||||
|
||||
// remap the input `x`, from the range [`a`,`b`] to [`c`,`d`] .
|
||||
// Example: math.remap(20, 1, 100, 50, 5000) == 1000
|
||||
// Note: `a` should be != `b`.
|
||||
@[inline]
|
||||
pub fn remap[T](x T, a T, b T, c T, d T) T {
|
||||
return c + (d - c) * (x - a) / (b - a)
|
||||
}
|
||||
|
||||
// smoothstep smoothly maps a value between `edge0` and `edge1`. It returns:
|
||||
// 0 if `x` is less than or equal to the left `edge0`,
|
||||
// 1 if `x` is greater than or equal to the right `edge`,
|
||||
// and smoothly interpolates, using a Hermite polynomial, between 0 and 1 otherwise.
|
||||
// The gradient of the smoothstep function is zero at both edges. This is convenient
|
||||
// for creating a sequence of transitions using smoothstep to interpolate each segment
|
||||
// as an alternative to using more sophisticated or expensive interpolation techniques.
|
||||
// `smoothstep` is a 1st order smoothing function, using a 3rd order polynomial.
|
||||
// See also `smootherstep`, which is slower, but nicer looking.
|
||||
// See also https://en.wikipedia.org/wiki/Smoothstep
|
||||
@[inline]
|
||||
pub fn smoothstep[T](edge0 T, edge1 T, x T) T {
|
||||
v := clip((x - edge0) / (edge1 - edge0), 0, 1)
|
||||
return v * v * (3 - 2 * v)
|
||||
}
|
||||
|
||||
// smootherstep smoothly maps a value between `edge0` and `edge1`.
|
||||
// smootherstep is a 2nd order smoothing function, using a 5th order polynomial.
|
||||
// The 1st and 2nd order derivatives of the smootherstep function are 0 at both edges.
|
||||
// See also `smoothstep`, which is faster, but has just its gradient being 0 at both edges.
|
||||
// See also https://en.wikipedia.org/wiki/Smoothstep
|
||||
@[inline]
|
||||
pub fn smootherstep[T](edge0 T, edge1 T, x T) T {
|
||||
v := clip((x - edge0) / (edge1 - edge0), 0, 1)
|
||||
return v * v * v * (x * (6 * x - 15) + 10)
|
||||
}
|
||||
|
@ -65,3 +65,40 @@ fn test_cubic_bezier_fa() {
|
||||
assert math.cubic_bezier_fa(0.5, bx_fa, by_fa) == math.BezierPoint{0.35375, 0.5375}
|
||||
assert math.cubic_bezier_fa(1.0, bx_fa, by_fa) == math.BezierPoint{bx_fa[3], by_fa[3]}
|
||||
}
|
||||
|
||||
fn test_remap() {
|
||||
assert math.remap(20, 1, 100, 50, 5000) == 1000
|
||||
assert math.remap(20.0, 1, 100, 50, 5000) == 1000.0
|
||||
|
||||
assert math.remap(55, 1, 100, 52, 5000) == 2750
|
||||
assert math.remap(55.0, 1, 100, 52, 5000) == 2750.909090909091
|
||||
|
||||
assert math.remap(25, 1, 100, 50, 5000) == 1250
|
||||
assert math.remap(25, 1, 100, -50, -5000) == -1250
|
||||
assert math.remap(25, 1, 100, 5000, 50) == 3800
|
||||
assert math.remap(25, 1, 100, -5000, -50) == -3800
|
||||
assert math.remap(25, 100, 1, 50, 5000) == 3800
|
||||
assert math.remap(25, 100, 1, -50, -5000) == -3800
|
||||
assert math.remap(25, 100, 1, 5000, 50) == 1250
|
||||
assert math.remap(25, 100, 1, -5000, -50) == -1250
|
||||
}
|
||||
|
||||
fn test_smoothstep() {
|
||||
assert math.smoothstep(0.0, 1, 0) == 0
|
||||
assert math.close(math.smoothstep(0.0, 1, 0.05), 0.00725)
|
||||
assert math.close(math.smoothstep(0.0, 1, 0.1), 0.028)
|
||||
assert math.smoothstep(0.0, 1, 0.5) == 0.5
|
||||
assert math.close(math.smoothstep(0.0, 1, 0.9), 0.972)
|
||||
assert math.close(math.smoothstep(0.0, 1, 0.95), 0.99275)
|
||||
assert math.smoothstep(0.0, 1, 1) == 1
|
||||
}
|
||||
|
||||
fn test_smootherstep() {
|
||||
assert math.smootherstep(0.0, 1, 0) == 0
|
||||
assert math.close(math.smootherstep(0.0, 1, 0.05), 0.001158125)
|
||||
assert math.close(math.smootherstep(0.0, 1, 0.1), 0.00856)
|
||||
assert math.smootherstep(0.0, 1, 0.5) == 0.5
|
||||
assert math.close(math.smootherstep(0.0, 1, 0.9), 0.99144)
|
||||
assert math.close(math.smootherstep(0.0, 1, 0.95), 0.998841875)
|
||||
assert math.smootherstep(0.0, 1, 1) == 1
|
||||
}
|
||||
|
@ -42,6 +42,12 @@ pub fn degrees(radians f64) f64 {
|
||||
return radians * (180.0 / pi)
|
||||
}
|
||||
|
||||
// radians converts an angle in degrees to a corresponding angle in radians.
|
||||
@[inline]
|
||||
pub fn radians(degrees f64) f64 {
|
||||
return degrees * (pi / 180.0)
|
||||
}
|
||||
|
||||
// angle_diff calculates the difference between angles in radians
|
||||
@[inline]
|
||||
pub fn angle_diff(radian_a f64, radian_b f64) f64 {
|
||||
@ -154,12 +160,6 @@ pub fn signi(n f64) int {
|
||||
return int(copysign(1.0, n))
|
||||
}
|
||||
|
||||
// radians converts an angle in degrees to a corresponding angle in radians.
|
||||
@[inline]
|
||||
pub fn radians(degrees f64) f64 {
|
||||
return degrees * (pi / 180.0)
|
||||
}
|
||||
|
||||
// signbit returns a value with the boolean representation of the sign for x
|
||||
@[inline]
|
||||
pub fn signbit(x f64) bool {
|
||||
|
Loading…
x
Reference in New Issue
Block a user