Trait veloren_voxygen::scene::math::Wrap
source · pub trait Wrap<Bound = Self>: Sized {
// Required methods
fn wrapped(self, upper: Bound) -> Self;
fn wrapped_between(self, lower: Bound, upper: Bound) -> Self;
fn pingpong(self, upper: Bound) -> Self;
// Provided methods
fn wrap(val: Self, upper: Bound) -> Self { ... }
fn wrapped_2pi(self) -> Self
where Bound: FloatConst + Add<Output = Bound> { ... }
fn wrap_2pi(val: Self) -> Self
where Bound: FloatConst + Add<Output = Bound> { ... }
fn wrap_between(val: Self, lower: Bound, upper: Bound) -> Self
where Self: Sub<Output = Self> + Add<Output = Self> + From<Bound>,
Bound: Copy + Sub<Output = Bound> + PartialOrd { ... }
fn delta_angle(self, target: Self) -> Self
where Self: From<Bound> + Sub<Output = Self> + PartialOrd,
Bound: FloatConst + Add<Output = Bound> { ... }
fn delta_angle_degrees(self, target: Self) -> Self
where Self: From<Bound> + Sub<Output = Self> + PartialOrd,
Bound: From<u16> { ... }
}
Expand description
A value that can wrap itself around given bounds.
Required Methods§
sourcefn wrapped(self, upper: Bound) -> Self
fn wrapped(self, upper: Bound) -> Self
Returns this value, wrapped between zero and some upper
bound (both inclusive).
The computation is self - (self/upper).floor() * upper
.
This might look like the remainder (%
) operator, but behaves differently with negative
values.
If you’re familiar with Unity, this is the Mathf.Repeat()
function.
§Panics
Panics if upper <= 0
. Reasons include :
- Some types may implement it as
self.wrapped_between(zero, upper)
. A negativeupper
would violate thelower <= upper
requirement in this case; - On unsigned integers, this just resolves to
self % upper
, and integer division by zero is forbidden. Testing fori==0
incurs unnecessary overhead. - Handling negative
upper
values would double the number of test cases and increases implementation complexity;
use vek::ops::Wrap;
assert_eq!((-5_i32).wrapped(3), 1);
assert_eq!((-4_i32).wrapped(3), 2);
assert_eq!((-3_i32).wrapped(3), 0);
assert_eq!((-2_i32).wrapped(3), 1);
assert_eq!((-1_i32).wrapped(3), 2);
assert_eq!(0_i32.wrapped(3), 0);
assert_eq!(1_i32.wrapped(3), 1);
assert_eq!(2_i32.wrapped(3), 2);
assert_eq!(3_i32.wrapped(3), 0);
assert_eq!(4_i32.wrapped(3), 1);
assert_eq!(5_i32.wrapped(3), 2);
sourcefn wrapped_between(self, lower: Bound, upper: Bound) -> Self
fn wrapped_between(self, lower: Bound, upper: Bound) -> Self
Returns this value, wrapped between lower
(inclusive) and upper
(exclusive).
§Panics
Panics if lower >= upper
. Swap the values yourself if necessary.
Also panics if lower < 0
or upper <= 0
. See wrapped()
for a rationale.
Forcing lower
and upper
to be positive allows implementations to be simpler and faster.
use vek::ops::Wrap;
assert_eq!((-4_i32).wrapped_between(2, 5), 2);
assert_eq!((-3_i32).wrapped_between(2, 5), 3);
assert_eq!((-2_i32).wrapped_between(2, 5), 4);
assert_eq!((-1_i32).wrapped_between(2, 5), 2);
assert_eq!( 0_i32 .wrapped_between(2, 5), 3);
assert_eq!( 1_i32 .wrapped_between(2, 5), 4);
assert_eq!( 2_i32 .wrapped_between(2, 5), 2);
assert_eq!( 3_i32 .wrapped_between(2, 5), 3);
assert_eq!( 4_i32 .wrapped_between(2, 5), 4);
assert_eq!( 5_i32 .wrapped_between(2, 5), 2);
assert_eq!( 6_i32 .wrapped_between(2, 5), 3);
sourcefn pingpong(self, upper: Bound) -> Self
fn pingpong(self, upper: Bound) -> Self
Wraps a value such that it goes back and forth from zero to upper
(inclusive) as it increases.
§Panics
Panics if upper <= 0
. See wrapped()
for a rationale.
use vek::ops::Wrap;
assert_eq!((-4_i32).pingpong(3), 2);
assert_eq!((-3_i32).pingpong(3), 3);
assert_eq!((-2_i32).pingpong(3), 2);
assert_eq!((-1_i32).pingpong(3), 1);
assert_eq!( 0_i32 .pingpong(3), 0);
assert_eq!( 1_i32 .pingpong(3), 1);
assert_eq!( 2_i32 .pingpong(3), 2);
assert_eq!( 3_i32 .pingpong(3), 3);
assert_eq!( 4_i32 .pingpong(3), 2);
assert_eq!( 5_i32 .pingpong(3), 1);
assert_eq!( 6_i32 .pingpong(3), 0);
assert_eq!( 7_i32 .pingpong(3), 1);
Provided Methods§
sourcefn wrap(val: Self, upper: Bound) -> Self
fn wrap(val: Self, upper: Bound) -> Self
Alias to wrapped()
which doesn’t take self
.
§Panics
Panics if upper <= 0
. See wrapped()
for a rationale.
sourcefn wrapped_2pi(self) -> Selfwhere
Bound: FloatConst + Add<Output = Bound>,
fn wrapped_2pi(self) -> Selfwhere
Bound: FloatConst + Add<Output = Bound>,
Returns this value, wrapped between zero and two times 𝛑 (inclusive).
This ought to be named wrapped_tau
, but I assume people are
more familiar with 𝛑, and 2pi
is therefore more evocative.
sourcefn wrap_2pi(val: Self) -> Selfwhere
Bound: FloatConst + Add<Output = Bound>,
fn wrap_2pi(val: Self) -> Selfwhere
Bound: FloatConst + Add<Output = Bound>,
Alias to wrapped_2pi
which doesn’t take self
.
This ought to be named wrap_tau
, but I assume people are
more familiar with 𝛑, and 2pi
is therefore more evocative.
sourcefn wrap_between(val: Self, lower: Bound, upper: Bound) -> Self
fn wrap_between(val: Self, lower: Bound, upper: Bound) -> Self
Alias to wrapped_between
which doesn’t take self
.
§Panics
Panics if lower
is greater than upper
. Swap the values yourself if necessary.
sourcefn delta_angle(self, target: Self) -> Self
fn delta_angle(self, target: Self) -> Self
Calculates the shortest difference between two given angles, in radians.
sourcefn delta_angle_degrees(self, target: Self) -> Self
fn delta_angle_degrees(self, target: Self) -> Self
Calculates the shortest difference between two given angles, in degrees.
This exists because it’s enough for Bound
to implement From<u16>
.