Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new_and_length method to Direction2d and Direction3d #11172

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 18 additions & 14 deletions crates/bevy_math/src/primitives/dim2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@ impl Direction2d {
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
/// of the given vector is zero (or very close to zero), infinite, or `NaN`.
pub fn new(value: Vec2) -> Result<Self, InvalidDirectionError> {
value.try_normalize().map(Self).map_or_else(
|| {
if value.is_nan() {
Err(InvalidDirectionError::NaN)
} else if !value.is_finite() {
// If the direction is non-finite but also not NaN, it must be infinite
Err(InvalidDirectionError::Infinite)
} else {
// If the direction is invalid but neither NaN nor infinite, it must be zero
Err(InvalidDirectionError::Zero)
}
},
Ok,
)
Self::new_and_length(value).map(|(dir, _)| dir)
}

/// Create a direction from a finite, nonzero [`Vec2`], also returning its original length.
///
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
/// of the given vector is zero (or very close to zero), infinite, or `NaN`.
pub fn new_and_length(value: Vec2) -> Result<(Self, f32), InvalidDirectionError> {
let length = value.length();
let direction = (length.is_finite() && length > 0.0).then_some(value / length);

direction
.map(|dir| (Self(dir), length))
.map_or(Err(InvalidDirectionError::from_length(length)), Ok)
}

/// Create a direction from its `x` and `y` components.
Expand Down Expand Up @@ -391,6 +391,10 @@ mod tests {
Direction2d::new(Vec2::new(f32::NAN, 0.0)),
Err(InvalidDirectionError::NaN)
);
assert_eq!(
Direction2d::new_and_length(Vec2::X * 6.5),
Ok((Direction2d::from_normalized(Vec2::X), 6.5))
);
}

#[test]
Expand Down
32 changes: 18 additions & 14 deletions crates/bevy_math/src/primitives/dim3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@ impl Direction3d {
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
/// of the given vector is zero (or very close to zero), infinite, or `NaN`.
pub fn new(value: Vec3) -> Result<Self, InvalidDirectionError> {
value.try_normalize().map(Self).map_or_else(
|| {
if value.is_nan() {
Err(InvalidDirectionError::NaN)
} else if !value.is_finite() {
// If the direction is non-finite but also not NaN, it must be infinite
Err(InvalidDirectionError::Infinite)
} else {
// If the direction is invalid but neither NaN nor infinite, it must be zero
Err(InvalidDirectionError::Zero)
}
},
Ok,
)
Self::new_and_length(value).map(|(dir, _)| dir)
}

/// Create a direction from a finite, nonzero [`Vec3`], also returning its original length.
///
/// Returns [`Err(InvalidDirectionError)`](InvalidDirectionError) if the length
/// of the given vector is zero (or very close to zero), infinite, or `NaN`.
pub fn new_and_length(value: Vec3) -> Result<(Self, f32), InvalidDirectionError> {
let length = value.length();
let direction = (length.is_finite() && length > 0.0).then_some(value / length);

direction
.map(|dir| (Self(dir), length))
.map_or(Err(InvalidDirectionError::from_length(length)), Ok)
}

/// Create a direction from its `x`, `y`, and `z` components.
Expand Down Expand Up @@ -404,5 +404,9 @@ mod test {
Direction3d::new(Vec3::new(f32::NAN, 0.0, 0.0)),
Err(InvalidDirectionError::NaN)
);
assert_eq!(
Direction3d::new_and_length(Vec3::X * 6.5),
Ok((Direction3d::from_normalized(Vec3::X), 6.5))
);
}
}
15 changes: 15 additions & 0 deletions crates/bevy_math/src/primitives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,21 @@ pub enum InvalidDirectionError {
NaN,
}

impl InvalidDirectionError {
/// Creates an [`InvalidDirectionError`] from the length of an invalid direction vector.
pub fn from_length(length: f32) -> Self {
if length.is_nan() {
InvalidDirectionError::NaN
} else if !length.is_finite() {
// If the direction is non-finite but also not NaN, it must be infinite
InvalidDirectionError::Infinite
} else {
// If the direction is invalid but neither NaN nor infinite, it must be zero
InvalidDirectionError::Zero
}
}
}

impl std::fmt::Display for InvalidDirectionError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
Expand Down