Skip to content

Commit

Permalink
Merge pull request #2432 from hannobraun/bivector
Browse files Browse the repository at this point in the history
Add `Bivector`
  • Loading branch information
hannobraun committed Jul 29, 2024
2 parents b7f6620 + 914bf84 commit 1b01055
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 0 deletions.
38 changes: 38 additions & 0 deletions crates/fj-math/src/bivector.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use crate::{Scalar, Vector};

/// # An n-dimensional bivector
///
/// The dimensionality of the vector is defined by the generic `D` parameter.
///
/// ## Implementation Note
///
/// The bivector representation chosen here, two vectors whose outer product
/// forms the bivector, is not the only one, and it might not be the best one
/// for our needs.
///
/// I considered using a coordinate-based representation, as that would be
/// unique and require less memory, but since we need 3 coordinates for 3D, but
/// just 1 coordinate for 2D, this would require type shenanigans or the (at the
/// time of writing) unstable `generic_const_exprs` feature.
///
/// I've decided that two vectors is good enough, and anything else not worth
/// the trouble. But we might want to reconsider, once `generic_const_exprs` is
/// stable.
#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)]
#[repr(C)]
pub struct Bivector<const D: usize> {
/// The first of the vectors whose outer product defines this bivector
pub a: Vector<D>,

/// The second of the vectors whose outer product defines this bivector
pub b: Vector<D>,
}

impl<const D: usize> Bivector<D> {
/// Compute the magnitude of the bivector
pub fn magnitude(&self) -> Scalar {
self.a.angle_to(&self.b).sin().abs()
* self.a.magnitude()
* self.b.magnitude()
}
}
2 changes: 2 additions & 0 deletions crates/fj-math/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

mod aabb;
mod arc;
mod bivector;
mod circle;
mod coordinates;
mod line;
Expand All @@ -47,6 +48,7 @@ mod vector;
pub use self::{
aabb::Aabb,
arc::Arc,
bivector::Bivector,
circle::Circle,
coordinates::{Uv, Xyz, T},
line::Line,
Expand Down
5 changes: 5 additions & 0 deletions crates/fj-math/src/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ impl Scalar {
self.0.round().into()
}

/// Compute the sine
pub fn sin(self) -> Self {
self.0.sin().into()
}

/// Compute the cosine
pub fn cos(self) -> Self {
self.0.cos().into()
Expand Down
15 changes: 15 additions & 0 deletions crates/fj-math/src/vector.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::{fmt, ops};

use crate::Bivector;

use super::{
coordinates::{Uv, Xyz, T},
Scalar,
Expand Down Expand Up @@ -85,11 +87,24 @@ impl<const D: usize> Vector<D> {
self.to_na().normalize().into()
}

/// Compute the angle between this vector and another
pub fn angle_to(&self, other: &Self) -> Scalar {
(self.dot(other) / (self.magnitude() * other.magnitude())).acos()
}

/// Compute the dot product with another vector
pub fn dot(&self, other: &Self) -> Scalar {
self.to_na().dot(&other.to_na()).into()
}

/// Compute the outer with another vector
pub fn outer(&self, other: &Self) -> Bivector<D> {
Bivector {
a: *self,
b: *other,
}
}

/// Compute the scalar projection of this vector onto another
pub fn scalar_projection_onto(&self, other: &Self) -> Scalar {
if other.magnitude() == Scalar::ZERO {
Expand Down

0 comments on commit 1b01055

Please sign in to comment.