Merge pull request #2432 from hannobraun/bivector

Add `Bivector`
This commit is contained in:
Hanno Braun 2024-07-29 19:12:19 +02:00 committed by GitHub
commit 1b01055a17
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 60 additions and 0 deletions

View File

@ -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()
}
}

View File

@ -33,6 +33,7 @@
mod aabb;
mod arc;
mod bivector;
mod circle;
mod coordinates;
mod line;
@ -47,6 +48,7 @@ mod vector;
pub use self::{
aabb::Aabb,
arc::Arc,
bivector::Bivector,
circle::Circle,
coordinates::{Uv, Xyz, T},
line::Line,

View File

@ -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()

View File

@ -1,5 +1,7 @@
use std::{fmt, ops};
use crate::Bivector;
use super::{
coordinates::{Uv, Xyz, T},
Scalar,
@ -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 {