mirror of
https://github.com/hannobraun/Fornjot
synced 2025-11-24 08:22:10 +00:00
commit
1b01055a17
38
crates/fj-math/src/bivector.rs
Normal file
38
crates/fj-math/src/bivector.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
@ -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,
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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 {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user