Re-add all the alga trait impls behind a feature.
This commit is contained in:
parent
4103da4bc1
commit
c5dad7f960
|
@ -40,7 +40,7 @@ num-complex = { version = "0.2", default-features = false }
|
||||||
num-rational = { version = "0.2", default-features = false }
|
num-rational = { version = "0.2", default-features = false }
|
||||||
approx = { version = "0.3", default-features = false }
|
approx = { version = "0.3", default-features = false }
|
||||||
simba = { version = "0.1", default-features = false }
|
simba = { version = "0.1", default-features = false }
|
||||||
#alga = { version = "0.9", default-features = false }
|
alga = { version = "0.9", default-features = false, optional = true }
|
||||||
rand_distr = { version = "0.2", optional = true }
|
rand_distr = { version = "0.2", optional = true }
|
||||||
matrixmultiply = { version = "0.2", optional = true }
|
matrixmultiply = { version = "0.2", optional = true }
|
||||||
serde = { version = "1.0", optional = true }
|
serde = { version = "1.0", optional = true }
|
||||||
|
@ -73,4 +73,4 @@ path = "benches/lib.rs"
|
||||||
lto = true
|
lto = true
|
||||||
|
|
||||||
#[patch.crates-io]
|
#[patch.crates-io]
|
||||||
#alga = { path = "../alga/alga" }
|
#simba = { path = "../simba" }
|
|
@ -0,0 +1,452 @@
|
||||||
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
|
use num::{One, Zero};
|
||||||
|
|
||||||
|
use alga::general::{
|
||||||
|
AbstractGroup, AbstractGroupAbelian, AbstractLoop, AbstractMagma, AbstractModule,
|
||||||
|
AbstractMonoid, AbstractQuasigroup, AbstractSemigroup, Additive, ClosedAdd, ClosedMul,
|
||||||
|
ClosedNeg, ComplexField, Field, Identity, JoinSemilattice, Lattice, MeetSemilattice, Module,
|
||||||
|
Multiplicative, RingCommutative, TwoSidedInverse,
|
||||||
|
};
|
||||||
|
use alga::linear::{
|
||||||
|
FiniteDimInnerSpace, FiniteDimVectorSpace, InnerSpace, NormedSpace, VectorSpace,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::base::allocator::Allocator;
|
||||||
|
use crate::base::dimension::{Dim, DimName};
|
||||||
|
use crate::base::storage::{Storage, StorageMut};
|
||||||
|
use crate::base::{DefaultAllocator, MatrixMN, MatrixN, Scalar};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Additive structures.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
impl<N, R: DimName, C: DimName> Identity<Additive> for MatrixMN<N, R, C>
|
||||||
|
where
|
||||||
|
N: Scalar + Zero,
|
||||||
|
DefaultAllocator: Allocator<N, R, C>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn identity() -> Self {
|
||||||
|
Self::from_element(N::zero())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N, R: DimName, C: DimName> AbstractMagma<Additive> for MatrixMN<N, R, C>
|
||||||
|
where
|
||||||
|
N: Scalar + ClosedAdd,
|
||||||
|
DefaultAllocator: Allocator<N, R, C>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn operate(&self, other: &Self) -> Self {
|
||||||
|
self + other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N, R: DimName, C: DimName> TwoSidedInverse<Additive> for MatrixMN<N, R, C>
|
||||||
|
where
|
||||||
|
N: Scalar + ClosedNeg,
|
||||||
|
DefaultAllocator: Allocator<N, R, C>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
#[must_use = "Did you mean to use two_sided_inverse_mut()?"]
|
||||||
|
fn two_sided_inverse(&self) -> Self {
|
||||||
|
-self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn two_sided_inverse_mut(&mut self) {
|
||||||
|
*self = -self.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! inherit_additive_structure(
|
||||||
|
($($marker: ident<$operator: ident> $(+ $bounds: ident)*),* $(,)*) => {$(
|
||||||
|
impl<N, R: DimName, C: DimName> $marker<$operator> for MatrixMN<N, R, C>
|
||||||
|
where N: Scalar + $marker<$operator> $(+ $bounds)*,
|
||||||
|
DefaultAllocator: Allocator<N, R, C> { }
|
||||||
|
)*}
|
||||||
|
);
|
||||||
|
|
||||||
|
inherit_additive_structure!(
|
||||||
|
AbstractSemigroup<Additive> + ClosedAdd,
|
||||||
|
AbstractMonoid<Additive> + Zero + ClosedAdd,
|
||||||
|
AbstractQuasigroup<Additive> + ClosedAdd + ClosedNeg,
|
||||||
|
AbstractLoop<Additive> + Zero + ClosedAdd + ClosedNeg,
|
||||||
|
AbstractGroup<Additive> + Zero + ClosedAdd + ClosedNeg,
|
||||||
|
AbstractGroupAbelian<Additive> + Zero + ClosedAdd + ClosedNeg
|
||||||
|
);
|
||||||
|
|
||||||
|
impl<N, R: DimName, C: DimName> AbstractModule for MatrixMN<N, R, C>
|
||||||
|
where
|
||||||
|
N: Scalar + RingCommutative,
|
||||||
|
DefaultAllocator: Allocator<N, R, C>,
|
||||||
|
{
|
||||||
|
type AbstractRing = N;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn multiply_by(&self, n: N) -> Self {
|
||||||
|
self * n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N, R: DimName, C: DimName> Module for MatrixMN<N, R, C>
|
||||||
|
where
|
||||||
|
N: Scalar + RingCommutative,
|
||||||
|
DefaultAllocator: Allocator<N, R, C>,
|
||||||
|
{
|
||||||
|
type Ring = N;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N, R: DimName, C: DimName> VectorSpace for MatrixMN<N, R, C>
|
||||||
|
where
|
||||||
|
N: Scalar + Field,
|
||||||
|
DefaultAllocator: Allocator<N, R, C>,
|
||||||
|
{
|
||||||
|
type Field = N;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N, R: DimName, C: DimName> FiniteDimVectorSpace for MatrixMN<N, R, C>
|
||||||
|
where
|
||||||
|
N: Scalar + Field,
|
||||||
|
DefaultAllocator: Allocator<N, R, C>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn dimension() -> usize {
|
||||||
|
R::dim() * C::dim()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn canonical_basis_element(i: usize) -> Self {
|
||||||
|
assert!(i < Self::dimension(), "Index out of bound.");
|
||||||
|
|
||||||
|
let mut res = Self::zero();
|
||||||
|
unsafe {
|
||||||
|
*res.data.get_unchecked_linear_mut(i) = N::one();
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn dot(&self, other: &Self) -> N {
|
||||||
|
self.dot(other)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn component_unchecked(&self, i: usize) -> &N {
|
||||||
|
self.data.get_unchecked_linear(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn component_unchecked_mut(&mut self, i: usize) -> &mut N {
|
||||||
|
self.data.get_unchecked_linear_mut(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
N: ComplexField + simba::scalar::ComplexField<RealField = <N as ComplexField>::RealField>,
|
||||||
|
R: DimName,
|
||||||
|
C: DimName,
|
||||||
|
> NormedSpace for MatrixMN<N, R, C>
|
||||||
|
where
|
||||||
|
<N as ComplexField>::RealField: simba::scalar::RealField,
|
||||||
|
DefaultAllocator: Allocator<N, R, C>,
|
||||||
|
{
|
||||||
|
type RealField = <N as ComplexField>::RealField;
|
||||||
|
type ComplexField = N;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn norm_squared(&self) -> <N as ComplexField>::RealField {
|
||||||
|
self.norm_squared()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn norm(&self) -> <N as ComplexField>::RealField {
|
||||||
|
self.norm()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[must_use = "Did you mean to use normalize_mut()?"]
|
||||||
|
fn normalize(&self) -> Self {
|
||||||
|
self.normalize()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn normalize_mut(&mut self) -> <N as ComplexField>::RealField {
|
||||||
|
self.normalize_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
#[must_use = "Did you mean to use try_normalize_mut()?"]
|
||||||
|
fn try_normalize(&self, min_norm: <N as ComplexField>::RealField) -> Option<Self> {
|
||||||
|
self.try_normalize(min_norm)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn try_normalize_mut(
|
||||||
|
&mut self,
|
||||||
|
min_norm: <N as ComplexField>::RealField,
|
||||||
|
) -> Option<<N as ComplexField>::RealField> {
|
||||||
|
self.try_normalize_mut(min_norm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
N: ComplexField + simba::scalar::ComplexField<RealField = <N as ComplexField>::RealField>,
|
||||||
|
R: DimName,
|
||||||
|
C: DimName,
|
||||||
|
> InnerSpace for MatrixMN<N, R, C>
|
||||||
|
where
|
||||||
|
<N as ComplexField>::RealField: simba::scalar::RealField,
|
||||||
|
DefaultAllocator: Allocator<N, R, C>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn angle(&self, other: &Self) -> <N as ComplexField>::RealField {
|
||||||
|
self.angle(other)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inner_product(&self, other: &Self) -> N {
|
||||||
|
self.dotc(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: specialization will greatly simplify this implementation in the future.
|
||||||
|
// In particular:
|
||||||
|
// − use `x()` instead of `::canonical_basis_element`
|
||||||
|
// − use `::new(x, y, z)` instead of `::from_slice`
|
||||||
|
impl<
|
||||||
|
N: ComplexField + simba::scalar::ComplexField<RealField = <N as ComplexField>::RealField>,
|
||||||
|
R: DimName,
|
||||||
|
C: DimName,
|
||||||
|
> FiniteDimInnerSpace for MatrixMN<N, R, C>
|
||||||
|
where
|
||||||
|
<N as ComplexField>::RealField: simba::scalar::RealField,
|
||||||
|
DefaultAllocator: Allocator<N, R, C>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn orthonormalize(vs: &mut [Self]) -> usize {
|
||||||
|
let mut nbasis_elements = 0;
|
||||||
|
|
||||||
|
for i in 0..vs.len() {
|
||||||
|
{
|
||||||
|
let (elt, basis) = vs[..i + 1].split_last_mut().unwrap();
|
||||||
|
|
||||||
|
for basis_element in &basis[..nbasis_elements] {
|
||||||
|
*elt -= &*basis_element * elt.dot(basis_element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if vs[i]
|
||||||
|
.try_normalize_mut(<N as ComplexField>::RealField::zero())
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
// FIXME: this will be efficient on dynamically-allocated vectors but for
|
||||||
|
// statically-allocated ones, `.clone_from` would be better.
|
||||||
|
vs.swap(nbasis_elements, i);
|
||||||
|
nbasis_elements += 1;
|
||||||
|
|
||||||
|
// All the other vectors will be dependent.
|
||||||
|
if nbasis_elements == Self::dimension() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nbasis_elements
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn orthonormal_subspace_basis<F>(vs: &[Self], mut f: F)
|
||||||
|
where
|
||||||
|
F: FnMut(&Self) -> bool,
|
||||||
|
{
|
||||||
|
// FIXME: is this necessary?
|
||||||
|
assert!(
|
||||||
|
vs.len() <= Self::dimension(),
|
||||||
|
"The given set of vectors has no chance of being a free family."
|
||||||
|
);
|
||||||
|
|
||||||
|
match Self::dimension() {
|
||||||
|
1 => {
|
||||||
|
if vs.len() == 0 {
|
||||||
|
let _ = f(&Self::canonical_basis_element(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2 => {
|
||||||
|
if vs.len() == 0 {
|
||||||
|
let _ = f(&Self::canonical_basis_element(0))
|
||||||
|
&& f(&Self::canonical_basis_element(1));
|
||||||
|
} else if vs.len() == 1 {
|
||||||
|
let v = &vs[0];
|
||||||
|
let res = Self::from_column_slice(&[-v[1], v[0]]);
|
||||||
|
|
||||||
|
let _ = f(&res.normalize());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, nothing.
|
||||||
|
}
|
||||||
|
3 => {
|
||||||
|
if vs.len() == 0 {
|
||||||
|
let _ = f(&Self::canonical_basis_element(0))
|
||||||
|
&& f(&Self::canonical_basis_element(1))
|
||||||
|
&& f(&Self::canonical_basis_element(2));
|
||||||
|
} else if vs.len() == 1 {
|
||||||
|
let v = &vs[0];
|
||||||
|
let mut a;
|
||||||
|
|
||||||
|
if ComplexField::norm1(v[0]) > ComplexField::norm1(v[1]) {
|
||||||
|
a = Self::from_column_slice(&[v[2], N::zero(), -v[0]]);
|
||||||
|
} else {
|
||||||
|
a = Self::from_column_slice(&[N::zero(), -v[2], v[1]]);
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = a.normalize_mut();
|
||||||
|
|
||||||
|
if f(&a.cross(v)) {
|
||||||
|
let _ = f(&a);
|
||||||
|
}
|
||||||
|
} else if vs.len() == 2 {
|
||||||
|
let _ = f(&vs[0].cross(&vs[1]).normalize());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
{
|
||||||
|
// XXX: use a GenericArray instead.
|
||||||
|
let mut known_basis = Vec::new();
|
||||||
|
|
||||||
|
for v in vs.iter() {
|
||||||
|
known_basis.push(v.normalize())
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..Self::dimension() - vs.len() {
|
||||||
|
let mut elt = Self::canonical_basis_element(i);
|
||||||
|
|
||||||
|
for v in &known_basis {
|
||||||
|
elt -= v * elt.dot(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(subsp_elt) =
|
||||||
|
elt.try_normalize(<N as ComplexField>::RealField::zero())
|
||||||
|
{
|
||||||
|
if !f(&subsp_elt) {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
known_basis.push(subsp_elt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(all(not(feature = "std"), not(feature = "alloc")))]
|
||||||
|
{
|
||||||
|
panic!("Cannot compute the orthogonal subspace basis of a vector with a dimension greater than 3 \
|
||||||
|
if #![no_std] is enabled and the 'alloc' feature is not enabled.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Multiplicative structures.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
impl<N, D: DimName> Identity<Multiplicative> for MatrixN<N, D>
|
||||||
|
where
|
||||||
|
N: Scalar + Zero + One,
|
||||||
|
DefaultAllocator: Allocator<N, D, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn identity() -> Self {
|
||||||
|
Self::identity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N, D: DimName> AbstractMagma<Multiplicative> for MatrixN<N, D>
|
||||||
|
where
|
||||||
|
N: Scalar + Zero + One + ClosedAdd + ClosedMul,
|
||||||
|
DefaultAllocator: Allocator<N, D, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn operate(&self, other: &Self) -> Self {
|
||||||
|
self * other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_multiplicative_structure(
|
||||||
|
($($marker: ident<$operator: ident> $(+ $bounds: ident)*),* $(,)*) => {$(
|
||||||
|
impl<N, D: DimName> $marker<$operator> for MatrixN<N, D>
|
||||||
|
where N: Scalar + Zero + One + ClosedAdd + ClosedMul + $marker<$operator> $(+ $bounds)*,
|
||||||
|
DefaultAllocator: Allocator<N, D, D> { }
|
||||||
|
)*}
|
||||||
|
);
|
||||||
|
|
||||||
|
impl_multiplicative_structure!(
|
||||||
|
AbstractSemigroup<Multiplicative>,
|
||||||
|
AbstractMonoid<Multiplicative> + One
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Ordering
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
impl<N, R: Dim, C: Dim> MeetSemilattice for MatrixMN<N, R, C>
|
||||||
|
where
|
||||||
|
N: Scalar + MeetSemilattice,
|
||||||
|
DefaultAllocator: Allocator<N, R, C>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn meet(&self, other: &Self) -> Self {
|
||||||
|
self.zip_map(other, |a, b| a.meet(&b))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N, R: Dim, C: Dim> JoinSemilattice for MatrixMN<N, R, C>
|
||||||
|
where
|
||||||
|
N: Scalar + JoinSemilattice,
|
||||||
|
DefaultAllocator: Allocator<N, R, C>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn join(&self, other: &Self) -> Self {
|
||||||
|
self.zip_map(other, |a, b| a.join(&b))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N, R: Dim, C: Dim> Lattice for MatrixMN<N, R, C>
|
||||||
|
where
|
||||||
|
N: Scalar + Lattice,
|
||||||
|
DefaultAllocator: Allocator<N, R, C>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn meet_join(&self, other: &Self) -> (Self, Self) {
|
||||||
|
let shape = self.data.shape();
|
||||||
|
assert!(
|
||||||
|
shape == other.data.shape(),
|
||||||
|
"Matrix meet/join error: mismatched dimensions."
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut mres = unsafe { Self::new_uninitialized_generic(shape.0, shape.1) };
|
||||||
|
let mut jres = unsafe { Self::new_uninitialized_generic(shape.0, shape.1) };
|
||||||
|
|
||||||
|
for i in 0..shape.0.value() * shape.1.value() {
|
||||||
|
unsafe {
|
||||||
|
let mj = self
|
||||||
|
.data
|
||||||
|
.get_unchecked_linear(i)
|
||||||
|
.meet_join(other.data.get_unchecked_linear(i));
|
||||||
|
*mres.data.get_unchecked_linear_mut(i) = mj.0;
|
||||||
|
*jres.data.get_unchecked_linear_mut(i) = mj.1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
(mres, jres)
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,8 @@ mod conversion;
|
||||||
mod edition;
|
mod edition;
|
||||||
pub mod indexing;
|
pub mod indexing;
|
||||||
mod matrix;
|
mod matrix;
|
||||||
|
#[cfg(feature = "alga")]
|
||||||
|
mod matrix_alga;
|
||||||
mod matrix_simba;
|
mod matrix_simba;
|
||||||
mod matrix_slice;
|
mod matrix_slice;
|
||||||
mod norm;
|
mod norm;
|
||||||
|
|
|
@ -0,0 +1,210 @@
|
||||||
|
use alga::general::{
|
||||||
|
AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup,
|
||||||
|
AbstractSemigroup, Id, Identity, Multiplicative, RealField, TwoSidedInverse,
|
||||||
|
};
|
||||||
|
use alga::linear::Isometry as AlgaIsometry;
|
||||||
|
use alga::linear::{
|
||||||
|
AffineTransformation, DirectIsometry, ProjectiveTransformation, Rotation, Similarity,
|
||||||
|
Transformation,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::base::allocator::Allocator;
|
||||||
|
use crate::base::dimension::DimName;
|
||||||
|
use crate::base::{DefaultAllocator, VectorN};
|
||||||
|
|
||||||
|
use crate::geometry::{AbstractRotation, Isometry, Point, Translation};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Algebraic structures.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName, R> Identity<Multiplicative>
|
||||||
|
for Isometry<N, D, R>
|
||||||
|
where
|
||||||
|
R: Rotation<Point<N, D>> + AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn identity() -> Self {
|
||||||
|
Self::identity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName, R> TwoSidedInverse<Multiplicative>
|
||||||
|
for Isometry<N, D, R>
|
||||||
|
where
|
||||||
|
R: Rotation<Point<N, D>> + AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
#[must_use = "Did you mean to use two_sided_inverse_mut()?"]
|
||||||
|
fn two_sided_inverse(&self) -> Self {
|
||||||
|
self.inverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn two_sided_inverse_mut(&mut self) {
|
||||||
|
self.inverse_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName, R> AbstractMagma<Multiplicative>
|
||||||
|
for Isometry<N, D, R>
|
||||||
|
where
|
||||||
|
R: Rotation<Point<N, D>> + AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn operate(&self, rhs: &Self) -> Self {
|
||||||
|
self * rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_multiplicative_structures(
|
||||||
|
($($marker: ident<$operator: ident>),* $(,)*) => {$(
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName, R> $marker<$operator> for Isometry<N, D, R>
|
||||||
|
where R: Rotation<Point<N, D>> + AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D> { }
|
||||||
|
)*}
|
||||||
|
);
|
||||||
|
|
||||||
|
impl_multiplicative_structures!(
|
||||||
|
AbstractSemigroup<Multiplicative>,
|
||||||
|
AbstractMonoid<Multiplicative>,
|
||||||
|
AbstractQuasigroup<Multiplicative>,
|
||||||
|
AbstractLoop<Multiplicative>,
|
||||||
|
AbstractGroup<Multiplicative>
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Transformation groups.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName, R> Transformation<Point<N, D>>
|
||||||
|
for Isometry<N, D, R>
|
||||||
|
where
|
||||||
|
R: Rotation<Point<N, D>> + AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
||||||
|
self.transform_point(pt)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
||||||
|
self.transform_vector(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName, R> ProjectiveTransformation<Point<N, D>>
|
||||||
|
for Isometry<N, D, R>
|
||||||
|
where
|
||||||
|
R: Rotation<Point<N, D>> + AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
||||||
|
self.inverse_transform_point(pt)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
||||||
|
self.inverse_transform_vector(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName, R> AffineTransformation<Point<N, D>>
|
||||||
|
for Isometry<N, D, R>
|
||||||
|
where
|
||||||
|
R: Rotation<Point<N, D>> + AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
type Rotation = R;
|
||||||
|
type NonUniformScaling = Id;
|
||||||
|
type Translation = Translation<N, D>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn decompose(&self) -> (Self::Translation, R, Id, R) {
|
||||||
|
(
|
||||||
|
self.translation.clone(),
|
||||||
|
self.rotation.clone(),
|
||||||
|
Id::new(),
|
||||||
|
<R as AbstractRotation<N, D>>::identity(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_translation(&self, t: &Self::Translation) -> Self {
|
||||||
|
t * self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn prepend_translation(&self, t: &Self::Translation) -> Self {
|
||||||
|
self * t
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_rotation(&self, r: &Self::Rotation) -> Self {
|
||||||
|
let shift = Transformation::transform_vector(r, &self.translation.vector);
|
||||||
|
Isometry::from_parts(Translation::from(shift), r.clone() * self.rotation.clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn prepend_rotation(&self, r: &Self::Rotation) -> Self {
|
||||||
|
Isometry::from_parts(self.translation.clone(), self.rotation.prepend_rotation(r))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_rotation_wrt_point(&self, r: &Self::Rotation, p: &Point<N, D>) -> Option<Self> {
|
||||||
|
let mut res = self.clone();
|
||||||
|
res.append_rotation_wrt_point_mut(r, p);
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName, R> Similarity<Point<N, D>>
|
||||||
|
for Isometry<N, D, R>
|
||||||
|
where
|
||||||
|
R: Rotation<Point<N, D>> + AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
type Scaling = Id;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn translation(&self) -> Translation<N, D> {
|
||||||
|
self.translation.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rotation(&self) -> R {
|
||||||
|
self.rotation.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn scaling(&self) -> Id {
|
||||||
|
Id::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! marker_impl(
|
||||||
|
($($Trait: ident),*) => {$(
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName, R> $Trait<Point<N, D>> for Isometry<N, D, R>
|
||||||
|
where R: Rotation<Point<N, D>> + AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D> { }
|
||||||
|
)*}
|
||||||
|
);
|
||||||
|
|
||||||
|
marker_impl!(AlgaIsometry, DirectIsometry);
|
|
@ -6,6 +6,8 @@ mod op_macros;
|
||||||
mod abstract_rotation;
|
mod abstract_rotation;
|
||||||
|
|
||||||
mod point;
|
mod point;
|
||||||
|
#[cfg(feature = "alga")]
|
||||||
|
mod point_alga;
|
||||||
mod point_alias;
|
mod point_alias;
|
||||||
mod point_construction;
|
mod point_construction;
|
||||||
mod point_conversion;
|
mod point_conversion;
|
||||||
|
@ -14,6 +16,8 @@ mod point_ops;
|
||||||
mod point_simba;
|
mod point_simba;
|
||||||
|
|
||||||
mod rotation;
|
mod rotation;
|
||||||
|
#[cfg(feature = "alga")]
|
||||||
|
mod rotation_alga;
|
||||||
mod rotation_alias;
|
mod rotation_alias;
|
||||||
mod rotation_construction;
|
mod rotation_construction;
|
||||||
mod rotation_conversion;
|
mod rotation_conversion;
|
||||||
|
@ -22,6 +26,8 @@ mod rotation_simba; // FIXME: implement Rotation methods.
|
||||||
mod rotation_specialization;
|
mod rotation_specialization;
|
||||||
|
|
||||||
mod quaternion;
|
mod quaternion;
|
||||||
|
#[cfg(feature = "alga")]
|
||||||
|
mod quaternion_alga;
|
||||||
mod quaternion_construction;
|
mod quaternion_construction;
|
||||||
mod quaternion_conversion;
|
mod quaternion_conversion;
|
||||||
mod quaternion_coordinates;
|
mod quaternion_coordinates;
|
||||||
|
@ -29,12 +35,16 @@ mod quaternion_ops;
|
||||||
mod quaternion_simba;
|
mod quaternion_simba;
|
||||||
|
|
||||||
mod unit_complex;
|
mod unit_complex;
|
||||||
|
#[cfg(feature = "alga")]
|
||||||
|
mod unit_complex_alga;
|
||||||
mod unit_complex_construction;
|
mod unit_complex_construction;
|
||||||
mod unit_complex_conversion;
|
mod unit_complex_conversion;
|
||||||
mod unit_complex_ops;
|
mod unit_complex_ops;
|
||||||
mod unit_complex_simba;
|
mod unit_complex_simba;
|
||||||
|
|
||||||
mod translation;
|
mod translation;
|
||||||
|
#[cfg(feature = "alga")]
|
||||||
|
mod translation_alga;
|
||||||
mod translation_alias;
|
mod translation_alias;
|
||||||
mod translation_construction;
|
mod translation_construction;
|
||||||
mod translation_conversion;
|
mod translation_conversion;
|
||||||
|
@ -43,6 +53,8 @@ mod translation_ops;
|
||||||
mod translation_simba;
|
mod translation_simba;
|
||||||
|
|
||||||
mod isometry;
|
mod isometry;
|
||||||
|
#[cfg(feature = "alga")]
|
||||||
|
mod isometry_alga;
|
||||||
mod isometry_alias;
|
mod isometry_alias;
|
||||||
mod isometry_construction;
|
mod isometry_construction;
|
||||||
mod isometry_conversion;
|
mod isometry_conversion;
|
||||||
|
@ -50,6 +62,8 @@ mod isometry_ops;
|
||||||
mod isometry_simba;
|
mod isometry_simba;
|
||||||
|
|
||||||
mod similarity;
|
mod similarity;
|
||||||
|
#[cfg(feature = "alga")]
|
||||||
|
mod similarity_alga;
|
||||||
mod similarity_alias;
|
mod similarity_alias;
|
||||||
mod similarity_construction;
|
mod similarity_construction;
|
||||||
mod similarity_conversion;
|
mod similarity_conversion;
|
||||||
|
@ -59,6 +73,8 @@ mod similarity_simba;
|
||||||
mod swizzle;
|
mod swizzle;
|
||||||
|
|
||||||
mod transform;
|
mod transform;
|
||||||
|
#[cfg(feature = "alga")]
|
||||||
|
mod transform_alga;
|
||||||
mod transform_alias;
|
mod transform_alias;
|
||||||
mod transform_construction;
|
mod transform_construction;
|
||||||
mod transform_conversion;
|
mod transform_conversion;
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
use alga::general::{Field, JoinSemilattice, Lattice, MeetSemilattice, RealField};
|
||||||
|
use alga::linear::{AffineSpace, EuclideanSpace};
|
||||||
|
|
||||||
|
use crate::base::allocator::Allocator;
|
||||||
|
use crate::base::dimension::DimName;
|
||||||
|
use crate::base::{DefaultAllocator, Scalar, VectorN};
|
||||||
|
|
||||||
|
use crate::geometry::Point;
|
||||||
|
|
||||||
|
impl<N: Scalar + Field, D: DimName> AffineSpace for Point<N, D>
|
||||||
|
where
|
||||||
|
N: Scalar + Field,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
type Translation = VectorN<N, D>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> EuclideanSpace for Point<N, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
type Coordinates = VectorN<N, D>;
|
||||||
|
type RealField = N;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn origin() -> Self {
|
||||||
|
Self::origin()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn coordinates(&self) -> Self::Coordinates {
|
||||||
|
self.coords.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn from_coordinates(coords: Self::Coordinates) -> Self {
|
||||||
|
Self::from(coords)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn scale_by(&self, n: N) -> Self {
|
||||||
|
self * n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Ordering
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
impl<N, D: DimName> MeetSemilattice for Point<N, D>
|
||||||
|
where
|
||||||
|
N: Scalar + MeetSemilattice,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn meet(&self, other: &Self) -> Self {
|
||||||
|
Self::from(self.coords.meet(&other.coords))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N, D: DimName> JoinSemilattice for Point<N, D>
|
||||||
|
where
|
||||||
|
N: Scalar + JoinSemilattice,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn join(&self, other: &Self) -> Self {
|
||||||
|
Self::from(self.coords.join(&other.coords))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N, D: DimName> Lattice for Point<N, D>
|
||||||
|
where
|
||||||
|
N: Scalar + Lattice,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn meet_join(&self, other: &Self) -> (Self, Self) {
|
||||||
|
let (meet, join) = self.coords.meet_join(&other.coords);
|
||||||
|
|
||||||
|
(Self::from(meet), Self::from(join))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,313 @@
|
||||||
|
use num::Zero;
|
||||||
|
|
||||||
|
use alga::general::{
|
||||||
|
AbstractGroup, AbstractGroupAbelian, AbstractLoop, AbstractMagma, AbstractModule,
|
||||||
|
AbstractMonoid, AbstractQuasigroup, AbstractSemigroup, Additive, Id, Identity, Module,
|
||||||
|
Multiplicative, RealField, TwoSidedInverse,
|
||||||
|
};
|
||||||
|
use alga::linear::{
|
||||||
|
AffineTransformation, DirectIsometry, FiniteDimVectorSpace, Isometry, NormedSpace,
|
||||||
|
OrthogonalTransformation, ProjectiveTransformation, Rotation, Similarity, Transformation,
|
||||||
|
VectorSpace,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::base::{Vector3, Vector4};
|
||||||
|
use crate::geometry::{Point3, Quaternion, UnitQuaternion};
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> Identity<Multiplicative> for Quaternion<N> {
|
||||||
|
#[inline]
|
||||||
|
fn identity() -> Self {
|
||||||
|
Self::identity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> Identity<Additive> for Quaternion<N> {
|
||||||
|
#[inline]
|
||||||
|
fn identity() -> Self {
|
||||||
|
Self::zero()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> AbstractMagma<Multiplicative> for Quaternion<N> {
|
||||||
|
#[inline]
|
||||||
|
fn operate(&self, rhs: &Self) -> Self {
|
||||||
|
self * rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> AbstractMagma<Additive> for Quaternion<N> {
|
||||||
|
#[inline]
|
||||||
|
fn operate(&self, rhs: &Self) -> Self {
|
||||||
|
self + rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> TwoSidedInverse<Additive> for Quaternion<N> {
|
||||||
|
#[inline]
|
||||||
|
fn two_sided_inverse(&self) -> Self {
|
||||||
|
-self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_structures(
|
||||||
|
($Quaternion: ident; $($marker: ident<$operator: ident>),* $(,)*) => {$(
|
||||||
|
impl<N: RealField + simba::scalar::RealField> $marker<$operator> for $Quaternion<N> { }
|
||||||
|
)*}
|
||||||
|
);
|
||||||
|
|
||||||
|
impl_structures!(
|
||||||
|
Quaternion;
|
||||||
|
AbstractSemigroup<Multiplicative>,
|
||||||
|
AbstractMonoid<Multiplicative>,
|
||||||
|
|
||||||
|
AbstractSemigroup<Additive>,
|
||||||
|
AbstractQuasigroup<Additive>,
|
||||||
|
AbstractMonoid<Additive>,
|
||||||
|
AbstractLoop<Additive>,
|
||||||
|
AbstractGroup<Additive>,
|
||||||
|
AbstractGroupAbelian<Additive>
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Vector space.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
impl<N: RealField + simba::scalar::RealField> AbstractModule for Quaternion<N> {
|
||||||
|
type AbstractRing = N;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn multiply_by(&self, n: N) -> Self {
|
||||||
|
self * n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> Module for Quaternion<N> {
|
||||||
|
type Ring = N;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> VectorSpace for Quaternion<N> {
|
||||||
|
type Field = N;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> FiniteDimVectorSpace for Quaternion<N> {
|
||||||
|
#[inline]
|
||||||
|
fn dimension() -> usize {
|
||||||
|
4
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn canonical_basis_element(i: usize) -> Self {
|
||||||
|
Self::from(Vector4::canonical_basis_element(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn dot(&self, other: &Self) -> N {
|
||||||
|
self.coords.dot(&other.coords)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn component_unchecked(&self, i: usize) -> &N {
|
||||||
|
self.coords.component_unchecked(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn component_unchecked_mut(&mut self, i: usize) -> &mut N {
|
||||||
|
self.coords.component_unchecked_mut(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> NormedSpace for Quaternion<N> {
|
||||||
|
type RealField = N;
|
||||||
|
type ComplexField = N;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn norm_squared(&self) -> N {
|
||||||
|
self.coords.norm_squared()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn norm(&self) -> N {
|
||||||
|
self.as_vector().norm()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn normalize(&self) -> Self {
|
||||||
|
let v = self.coords.normalize();
|
||||||
|
Self::from(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn normalize_mut(&mut self) -> N {
|
||||||
|
self.coords.normalize_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn try_normalize(&self, min_norm: N) -> Option<Self> {
|
||||||
|
if let Some(v) = self.coords.try_normalize(min_norm) {
|
||||||
|
Some(Self::from(v))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn try_normalize_mut(&mut self, min_norm: N) -> Option<N> {
|
||||||
|
self.coords.try_normalize_mut(min_norm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Implementations for UnitQuaternion.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
impl<N: RealField + simba::scalar::RealField> Identity<Multiplicative> for UnitQuaternion<N> {
|
||||||
|
#[inline]
|
||||||
|
fn identity() -> Self {
|
||||||
|
Self::identity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> AbstractMagma<Multiplicative> for UnitQuaternion<N> {
|
||||||
|
#[inline]
|
||||||
|
fn operate(&self, rhs: &Self) -> Self {
|
||||||
|
self * rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> TwoSidedInverse<Multiplicative>
|
||||||
|
for UnitQuaternion<N>
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn two_sided_inverse(&self) -> Self {
|
||||||
|
self.inverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn two_sided_inverse_mut(&mut self) {
|
||||||
|
self.inverse_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_structures!(
|
||||||
|
UnitQuaternion;
|
||||||
|
AbstractSemigroup<Multiplicative>,
|
||||||
|
AbstractQuasigroup<Multiplicative>,
|
||||||
|
AbstractMonoid<Multiplicative>,
|
||||||
|
AbstractLoop<Multiplicative>,
|
||||||
|
AbstractGroup<Multiplicative>
|
||||||
|
);
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> Transformation<Point3<N>> for UnitQuaternion<N> {
|
||||||
|
#[inline]
|
||||||
|
fn transform_point(&self, pt: &Point3<N>) -> Point3<N> {
|
||||||
|
self.transform_point(pt)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn transform_vector(&self, v: &Vector3<N>) -> Vector3<N> {
|
||||||
|
self.transform_vector(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> ProjectiveTransformation<Point3<N>>
|
||||||
|
for UnitQuaternion<N>
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_point(&self, pt: &Point3<N>) -> Point3<N> {
|
||||||
|
self.inverse_transform_point(pt)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_vector(&self, v: &Vector3<N>) -> Vector3<N> {
|
||||||
|
self.inverse_transform_vector(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> AffineTransformation<Point3<N>>
|
||||||
|
for UnitQuaternion<N>
|
||||||
|
{
|
||||||
|
type Rotation = Self;
|
||||||
|
type NonUniformScaling = Id;
|
||||||
|
type Translation = Id;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn decompose(&self) -> (Id, Self, Id, Self) {
|
||||||
|
(Id::new(), self.clone(), Id::new(), Self::identity())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_translation(&self, _: &Self::Translation) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn prepend_translation(&self, _: &Self::Translation) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_rotation(&self, r: &Self::Rotation) -> Self {
|
||||||
|
r * self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn prepend_rotation(&self, r: &Self::Rotation) -> Self {
|
||||||
|
self * r
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> Similarity<Point3<N>> for UnitQuaternion<N> {
|
||||||
|
type Scaling = Id;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn translation(&self) -> Id {
|
||||||
|
Id::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rotation(&self) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn scaling(&self) -> Id {
|
||||||
|
Id::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! marker_impl(
|
||||||
|
($($Trait: ident),*) => {$(
|
||||||
|
impl<N: RealField + simba::scalar::RealField> $Trait<Point3<N>> for UnitQuaternion<N> { }
|
||||||
|
)*}
|
||||||
|
);
|
||||||
|
|
||||||
|
marker_impl!(Isometry, DirectIsometry, OrthogonalTransformation);
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> Rotation<Point3<N>> for UnitQuaternion<N> {
|
||||||
|
#[inline]
|
||||||
|
fn powf(&self, n: N) -> Option<Self> {
|
||||||
|
Some(self.powf(n))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rotation_between(a: &Vector3<N>, b: &Vector3<N>) -> Option<Self> {
|
||||||
|
Self::rotation_between(a, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn scaled_rotation_between(a: &Vector3<N>, b: &Vector3<N>, s: N) -> Option<Self> {
|
||||||
|
Self::scaled_rotation_between(a, b, s)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,291 @@
|
||||||
|
use alga::general::{
|
||||||
|
AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup,
|
||||||
|
AbstractSemigroup, Id, Identity, Multiplicative, RealField, TwoSidedInverse,
|
||||||
|
};
|
||||||
|
use alga::linear::{
|
||||||
|
self, AffineTransformation, DirectIsometry, Isometry, OrthogonalTransformation,
|
||||||
|
ProjectiveTransformation, Similarity, Transformation,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::base::allocator::Allocator;
|
||||||
|
use crate::base::dimension::DimName;
|
||||||
|
use crate::base::{DefaultAllocator, VectorN};
|
||||||
|
|
||||||
|
use crate::geometry::{Point, Rotation};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Algebraic structures.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> Identity<Multiplicative>
|
||||||
|
for Rotation<N, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn identity() -> Self {
|
||||||
|
Self::identity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> TwoSidedInverse<Multiplicative>
|
||||||
|
for Rotation<N, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
#[must_use = "Did you mean to use two_sided_inverse_mut()?"]
|
||||||
|
fn two_sided_inverse(&self) -> Self {
|
||||||
|
self.transpose()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn two_sided_inverse_mut(&mut self) {
|
||||||
|
self.transpose_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> AbstractMagma<Multiplicative>
|
||||||
|
for Rotation<N, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn operate(&self, rhs: &Self) -> Self {
|
||||||
|
self * rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_multiplicative_structures(
|
||||||
|
($($marker: ident<$operator: ident>),* $(,)*) => {$(
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> $marker<$operator> for Rotation<N, D>
|
||||||
|
where DefaultAllocator: Allocator<N, D, D> { }
|
||||||
|
)*}
|
||||||
|
);
|
||||||
|
|
||||||
|
impl_multiplicative_structures!(
|
||||||
|
AbstractSemigroup<Multiplicative>,
|
||||||
|
AbstractMonoid<Multiplicative>,
|
||||||
|
AbstractQuasigroup<Multiplicative>,
|
||||||
|
AbstractLoop<Multiplicative>,
|
||||||
|
AbstractGroup<Multiplicative>
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Transformation groups.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> Transformation<Point<N, D>>
|
||||||
|
for Rotation<N, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
||||||
|
self.transform_point(pt)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
||||||
|
self.transform_vector(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> ProjectiveTransformation<Point<N, D>>
|
||||||
|
for Rotation<N, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
||||||
|
self.inverse_transform_point(pt)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
||||||
|
self.inverse_transform_vector(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> AffineTransformation<Point<N, D>>
|
||||||
|
for Rotation<N, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
|
||||||
|
{
|
||||||
|
type Rotation = Self;
|
||||||
|
type NonUniformScaling = Id;
|
||||||
|
type Translation = Id;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn decompose(&self) -> (Id, Self, Id, Self) {
|
||||||
|
(Id::new(), self.clone(), Id::new(), Self::identity())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_translation(&self, _: &Self::Translation) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn prepend_translation(&self, _: &Self::Translation) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_rotation(&self, r: &Self::Rotation) -> Self {
|
||||||
|
r * self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn prepend_rotation(&self, r: &Self::Rotation) -> Self {
|
||||||
|
self * r
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> Similarity<Point<N, D>> for Rotation<N, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
|
||||||
|
{
|
||||||
|
type Scaling = Id;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn translation(&self) -> Id {
|
||||||
|
Id::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rotation(&self) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn scaling(&self) -> Id {
|
||||||
|
Id::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! marker_impl(
|
||||||
|
($($Trait: ident),*) => {$(
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> $Trait<Point<N, D>> for Rotation<N, D>
|
||||||
|
where DefaultAllocator: Allocator<N, D, D> +
|
||||||
|
Allocator<N, D> { }
|
||||||
|
)*}
|
||||||
|
);
|
||||||
|
|
||||||
|
marker_impl!(Isometry, DirectIsometry, OrthogonalTransformation);
|
||||||
|
|
||||||
|
/// Subgroups of the n-dimensional rotation group `SO(n)`.
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> linear::Rotation<Point<N, D>>
|
||||||
|
for Rotation<N, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D, D> + Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn powf(&self, _: N) -> Option<Self> {
|
||||||
|
// XXX: Add the general case.
|
||||||
|
// XXX: Use specialization for 2D and 3D.
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rotation_between(_: &VectorN<N, D>, _: &VectorN<N, D>) -> Option<Self> {
|
||||||
|
// XXX: Add the general case.
|
||||||
|
// XXX: Use specialization for 2D and 3D.
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn scaled_rotation_between(_: &VectorN<N, D>, _: &VectorN<N, D>, _: N) -> Option<Self> {
|
||||||
|
// XXX: Add the general case.
|
||||||
|
// XXX: Use specialization for 2D and 3D.
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
impl<N: RealField + simba::scalar::RealField> Matrix for Rotation<N> {
|
||||||
|
type Field = N;
|
||||||
|
type Row = Matrix<N>;
|
||||||
|
type Column = Matrix<N>;
|
||||||
|
type Transpose = Self;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn nrows(&self) -> usize {
|
||||||
|
self.submatrix.nrows()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn ncolumns(&self) -> usize {
|
||||||
|
self.submatrix.ncolumns()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn row(&self, i: usize) -> Self::Row {
|
||||||
|
self.submatrix.row(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn column(&self, i: usize) -> Self::Column {
|
||||||
|
self.submatrix.column(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get(&self, i: usize, j: usize) -> Self::Field {
|
||||||
|
self.submatrix[(i, j)]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn get_unchecked(&self, i: usize, j: usize) -> Self::Field {
|
||||||
|
self.submatrix.at_fast(i, j)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn transpose(&self) -> Self::Transpose {
|
||||||
|
Rotation::from_matrix_unchecked(self.submatrix.transpose())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> SquareMatrix for Rotation<N> {
|
||||||
|
type Vector = Matrix<N>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn diagonal(&self) -> Self::Coordinates {
|
||||||
|
self.submatrix.diagonal()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn determinant(&self) -> Self::Field {
|
||||||
|
crate::one()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn try_inverse(&self) -> Option<Self> {
|
||||||
|
Some(::transpose(self))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn try_inverse_mut(&mut self) -> bool {
|
||||||
|
self.transpose_mut();
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn transpose_mut(&mut self) {
|
||||||
|
self.submatrix.transpose_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> InversibleSquareMatrix for Rotation<N> { }
|
||||||
|
*/
|
|
@ -0,0 +1,196 @@
|
||||||
|
use alga::general::{
|
||||||
|
AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup,
|
||||||
|
AbstractSemigroup, Identity, Multiplicative, RealField, TwoSidedInverse,
|
||||||
|
};
|
||||||
|
use alga::linear::Similarity as AlgaSimilarity;
|
||||||
|
use alga::linear::{AffineTransformation, ProjectiveTransformation, Rotation, Transformation};
|
||||||
|
|
||||||
|
use crate::base::allocator::Allocator;
|
||||||
|
use crate::base::dimension::DimName;
|
||||||
|
use crate::base::{DefaultAllocator, VectorN};
|
||||||
|
|
||||||
|
use crate::geometry::{AbstractRotation, Point, Similarity, Translation};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Algebraic structures.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName, R> Identity<Multiplicative>
|
||||||
|
for Similarity<N, D, R>
|
||||||
|
where
|
||||||
|
R: Rotation<Point<N, D>> + AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn identity() -> Self {
|
||||||
|
Self::identity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName, R> TwoSidedInverse<Multiplicative>
|
||||||
|
for Similarity<N, D, R>
|
||||||
|
where
|
||||||
|
R: Rotation<Point<N, D>> + AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
#[must_use = "Did you mean to use two_sided_inverse_mut()?"]
|
||||||
|
fn two_sided_inverse(&self) -> Self {
|
||||||
|
self.inverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn two_sided_inverse_mut(&mut self) {
|
||||||
|
self.inverse_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName, R> AbstractMagma<Multiplicative>
|
||||||
|
for Similarity<N, D, R>
|
||||||
|
where
|
||||||
|
R: Rotation<Point<N, D>> + AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn operate(&self, rhs: &Self) -> Self {
|
||||||
|
self * rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_multiplicative_structures(
|
||||||
|
($($marker: ident<$operator: ident>),* $(,)*) => {$(
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName, R> $marker<$operator> for Similarity<N, D, R>
|
||||||
|
where R: Rotation<Point<N, D>> + AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D> { }
|
||||||
|
)*}
|
||||||
|
);
|
||||||
|
|
||||||
|
impl_multiplicative_structures!(
|
||||||
|
AbstractSemigroup<Multiplicative>,
|
||||||
|
AbstractMonoid<Multiplicative>,
|
||||||
|
AbstractQuasigroup<Multiplicative>,
|
||||||
|
AbstractLoop<Multiplicative>,
|
||||||
|
AbstractGroup<Multiplicative>
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Transformation groups.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName, R> Transformation<Point<N, D>>
|
||||||
|
for Similarity<N, D, R>
|
||||||
|
where
|
||||||
|
R: Rotation<Point<N, D>> + AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
||||||
|
self.transform_point(pt)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
||||||
|
self.transform_vector(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName, R> ProjectiveTransformation<Point<N, D>>
|
||||||
|
for Similarity<N, D, R>
|
||||||
|
where
|
||||||
|
R: Rotation<Point<N, D>> + AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
||||||
|
self.inverse_transform_point(pt)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
||||||
|
self.inverse_transform_vector(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName, R> AffineTransformation<Point<N, D>>
|
||||||
|
for Similarity<N, D, R>
|
||||||
|
where
|
||||||
|
R: Rotation<Point<N, D>> + AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
type NonUniformScaling = N;
|
||||||
|
type Rotation = R;
|
||||||
|
type Translation = Translation<N, D>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn decompose(&self) -> (Translation<N, D>, R, N, R) {
|
||||||
|
(
|
||||||
|
self.isometry.translation.clone(),
|
||||||
|
self.isometry.rotation.clone(),
|
||||||
|
self.scaling(),
|
||||||
|
<R as AbstractRotation<N, D>>::identity(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_translation(&self, t: &Self::Translation) -> Self {
|
||||||
|
t * self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn prepend_translation(&self, t: &Self::Translation) -> Self {
|
||||||
|
self * t
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_rotation(&self, r: &Self::Rotation) -> Self {
|
||||||
|
Similarity::from_isometry(self.isometry.append_rotation(r), self.scaling())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn prepend_rotation(&self, r: &Self::Rotation) -> Self {
|
||||||
|
Similarity::from_isometry(self.isometry.prepend_rotation(r), self.scaling())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_scaling(&self, s: &Self::NonUniformScaling) -> Self {
|
||||||
|
self.append_scaling(*s)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn prepend_scaling(&self, s: &Self::NonUniformScaling) -> Self {
|
||||||
|
self.prepend_scaling(*s)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_rotation_wrt_point(&self, r: &Self::Rotation, p: &Point<N, D>) -> Option<Self> {
|
||||||
|
let mut res = self.clone();
|
||||||
|
res.append_rotation_wrt_point_mut(r, p);
|
||||||
|
Some(res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName, R> AlgaSimilarity<Point<N, D>>
|
||||||
|
for Similarity<N, D, R>
|
||||||
|
where
|
||||||
|
R: Rotation<Point<N, D>> + AbstractRotation<N, D>,
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
type Scaling = N;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn translation(&self) -> Translation<N, D> {
|
||||||
|
self.isometry.translation()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rotation(&self) -> R {
|
||||||
|
self.isometry.rotation()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn scaling(&self) -> N {
|
||||||
|
self.scaling()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,149 @@
|
||||||
|
use alga::general::{
|
||||||
|
AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup,
|
||||||
|
AbstractSemigroup, Identity, Multiplicative, RealField, TwoSidedInverse,
|
||||||
|
};
|
||||||
|
use alga::linear::{ProjectiveTransformation, Transformation};
|
||||||
|
|
||||||
|
use crate::base::allocator::Allocator;
|
||||||
|
use crate::base::dimension::{DimNameAdd, DimNameSum, U1};
|
||||||
|
use crate::base::{DefaultAllocator, VectorN};
|
||||||
|
|
||||||
|
use crate::geometry::{Point, SubTCategoryOf, TCategory, TProjective, Transform};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Algebraic structures.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimNameAdd<U1>, C> Identity<Multiplicative>
|
||||||
|
for Transform<N, D, C>
|
||||||
|
where
|
||||||
|
C: TCategory,
|
||||||
|
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn identity() -> Self {
|
||||||
|
Self::identity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimNameAdd<U1>, C> TwoSidedInverse<Multiplicative>
|
||||||
|
for Transform<N, D, C>
|
||||||
|
where
|
||||||
|
C: SubTCategoryOf<TProjective>,
|
||||||
|
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
#[must_use = "Did you mean to use two_sided_inverse_mut()?"]
|
||||||
|
fn two_sided_inverse(&self) -> Self {
|
||||||
|
self.clone().inverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn two_sided_inverse_mut(&mut self) {
|
||||||
|
self.inverse_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimNameAdd<U1>, C> AbstractMagma<Multiplicative>
|
||||||
|
for Transform<N, D, C>
|
||||||
|
where
|
||||||
|
C: TCategory,
|
||||||
|
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn operate(&self, rhs: &Self) -> Self {
|
||||||
|
self * rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_multiplicative_structures(
|
||||||
|
($($marker: ident<$operator: ident>),* $(,)*) => {$(
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimNameAdd<U1>, C> $marker<$operator> for Transform<N, D, C>
|
||||||
|
where C: TCategory,
|
||||||
|
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>> { }
|
||||||
|
)*}
|
||||||
|
);
|
||||||
|
|
||||||
|
macro_rules! impl_inversible_multiplicative_structures(
|
||||||
|
($($marker: ident<$operator: ident>),* $(,)*) => {$(
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimNameAdd<U1>, C> $marker<$operator> for Transform<N, D, C>
|
||||||
|
where C: SubTCategoryOf<TProjective>,
|
||||||
|
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>> { }
|
||||||
|
)*}
|
||||||
|
);
|
||||||
|
|
||||||
|
impl_multiplicative_structures!(
|
||||||
|
AbstractSemigroup<Multiplicative>,
|
||||||
|
AbstractMonoid<Multiplicative>,
|
||||||
|
);
|
||||||
|
|
||||||
|
impl_inversible_multiplicative_structures!(
|
||||||
|
AbstractQuasigroup<Multiplicative>,
|
||||||
|
AbstractLoop<Multiplicative>,
|
||||||
|
AbstractGroup<Multiplicative>
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Transformation groups.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
impl<N, D: DimNameAdd<U1>, C> Transformation<Point<N, D>> for Transform<N, D, C>
|
||||||
|
where
|
||||||
|
N: RealField + simba::scalar::RealField,
|
||||||
|
C: TCategory,
|
||||||
|
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>
|
||||||
|
+ Allocator<N, DimNameSum<D, U1>>
|
||||||
|
+ Allocator<N, D, D>
|
||||||
|
+ Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
||||||
|
self.transform_point(pt)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
||||||
|
self.transform_vector(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N, D: DimNameAdd<U1>, C> ProjectiveTransformation<Point<N, D>> for Transform<N, D, C>
|
||||||
|
where
|
||||||
|
N: RealField + simba::scalar::RealField,
|
||||||
|
C: SubTCategoryOf<TProjective>,
|
||||||
|
DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>>
|
||||||
|
+ Allocator<N, DimNameSum<D, U1>>
|
||||||
|
+ Allocator<N, D, D>
|
||||||
|
+ Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
||||||
|
self.inverse_transform_point(pt)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
||||||
|
self.inverse_transform_vector(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: we need to implement an SVD for this.
|
||||||
|
//
|
||||||
|
// impl<N, D: DimNameAdd<U1>, C> AffineTransformation<Point<N, D>> for Transform<N, D, C>
|
||||||
|
// where N: RealField,
|
||||||
|
// C: SubTCategoryOf<TAffine>,
|
||||||
|
// DefaultAllocator: Allocator<N, DimNameSum<D, U1>, DimNameSum<D, U1>> +
|
||||||
|
// Allocator<N, D, D> +
|
||||||
|
// Allocator<N, D> {
|
||||||
|
// type PreRotation = Rotation<N, D>;
|
||||||
|
// type NonUniformScaling = VectorN<N, D>;
|
||||||
|
// type PostRotation = Rotation<N, D>;
|
||||||
|
// type Translation = Translation<N, D>;
|
||||||
|
//
|
||||||
|
// #[inline]
|
||||||
|
// fn decompose(&self) -> (Self::Translation, Self::PostRotation, Self::NonUniformScaling, Self::PreRotation) {
|
||||||
|
// unimplemented!()
|
||||||
|
// }
|
||||||
|
// }
|
|
@ -0,0 +1,215 @@
|
||||||
|
use alga::general::{
|
||||||
|
AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup,
|
||||||
|
AbstractSemigroup, Id, Identity, Multiplicative, RealField, TwoSidedInverse,
|
||||||
|
};
|
||||||
|
use alga::linear::Translation as AlgaTranslation;
|
||||||
|
use alga::linear::{
|
||||||
|
AffineTransformation, DirectIsometry, Isometry, ProjectiveTransformation, Similarity,
|
||||||
|
Transformation,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::base::allocator::Allocator;
|
||||||
|
use crate::base::dimension::DimName;
|
||||||
|
use crate::base::{DefaultAllocator, VectorN};
|
||||||
|
|
||||||
|
use crate::geometry::{Point, Translation};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Algebraic structures.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> Identity<Multiplicative>
|
||||||
|
for Translation<N, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn identity() -> Self {
|
||||||
|
Self::identity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> TwoSidedInverse<Multiplicative>
|
||||||
|
for Translation<N, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
#[must_use = "Did you mean to use two_sided_inverse_mut()?"]
|
||||||
|
fn two_sided_inverse(&self) -> Self {
|
||||||
|
self.inverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn two_sided_inverse_mut(&mut self) {
|
||||||
|
self.inverse_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> AbstractMagma<Multiplicative>
|
||||||
|
for Translation<N, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn operate(&self, rhs: &Self) -> Self {
|
||||||
|
self * rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_multiplicative_structures(
|
||||||
|
($($marker: ident<$operator: ident>),* $(,)*) => {$(
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> $marker<$operator> for Translation<N, D>
|
||||||
|
where DefaultAllocator: Allocator<N, D> { }
|
||||||
|
)*}
|
||||||
|
);
|
||||||
|
|
||||||
|
impl_multiplicative_structures!(
|
||||||
|
AbstractSemigroup<Multiplicative>,
|
||||||
|
AbstractMonoid<Multiplicative>,
|
||||||
|
AbstractQuasigroup<Multiplicative>,
|
||||||
|
AbstractLoop<Multiplicative>,
|
||||||
|
AbstractGroup<Multiplicative>
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Transformation groups.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> Transformation<Point<N, D>>
|
||||||
|
for Translation<N, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
||||||
|
self.transform_point(pt)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
||||||
|
v.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> ProjectiveTransformation<Point<N, D>>
|
||||||
|
for Translation<N, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_point(&self, pt: &Point<N, D>) -> Point<N, D> {
|
||||||
|
self.inverse_transform_point(pt)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_vector(&self, v: &VectorN<N, D>) -> VectorN<N, D> {
|
||||||
|
v.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> AffineTransformation<Point<N, D>>
|
||||||
|
for Translation<N, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
type Rotation = Id;
|
||||||
|
type NonUniformScaling = Id;
|
||||||
|
type Translation = Self;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn decompose(&self) -> (Self, Id, Id, Id) {
|
||||||
|
(self.clone(), Id::new(), Id::new(), Id::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_translation(&self, t: &Self::Translation) -> Self {
|
||||||
|
t * self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn prepend_translation(&self, t: &Self::Translation) -> Self {
|
||||||
|
self * t
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_rotation(&self, _: &Self::Rotation) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn prepend_rotation(&self, _: &Self::Rotation) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> Similarity<Point<N, D>>
|
||||||
|
for Translation<N, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
type Scaling = Id;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn translation(&self) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rotation(&self) -> Id {
|
||||||
|
Id::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn scaling(&self) -> Id {
|
||||||
|
Id::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! marker_impl(
|
||||||
|
($($Trait: ident),*) => {$(
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> $Trait<Point<N, D>> for Translation<N, D>
|
||||||
|
where DefaultAllocator: Allocator<N, D> { }
|
||||||
|
)*}
|
||||||
|
);
|
||||||
|
|
||||||
|
marker_impl!(Isometry, DirectIsometry);
|
||||||
|
|
||||||
|
/// Subgroups of the n-dimensional translation group `T(n)`.
|
||||||
|
impl<N: RealField + simba::scalar::RealField, D: DimName> AlgaTranslation<Point<N, D>>
|
||||||
|
for Translation<N, D>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, D>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn to_vector(&self) -> VectorN<N, D> {
|
||||||
|
self.vector.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn from_vector(v: VectorN<N, D>) -> Option<Self> {
|
||||||
|
Some(Self::from(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn powf(&self, n: N) -> Option<Self> {
|
||||||
|
Some(Self::from(&self.vector * n))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn translation_between(a: &Point<N, D>, b: &Point<N, D>) -> Option<Self> {
|
||||||
|
Some(Self::from(b - a))
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,185 @@
|
||||||
|
use alga::general::{
|
||||||
|
AbstractGroup, AbstractLoop, AbstractMagma, AbstractMonoid, AbstractQuasigroup,
|
||||||
|
AbstractSemigroup, Id, Identity, Multiplicative, RealField, TwoSidedInverse,
|
||||||
|
};
|
||||||
|
use alga::linear::{
|
||||||
|
AffineTransformation, DirectIsometry, Isometry, OrthogonalTransformation,
|
||||||
|
ProjectiveTransformation, Rotation, Similarity, Transformation,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::base::allocator::Allocator;
|
||||||
|
use crate::base::dimension::U2;
|
||||||
|
use crate::base::{DefaultAllocator, Vector2};
|
||||||
|
use crate::geometry::{Point2, UnitComplex};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Implementations for UnitComplex.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
impl<N: RealField + simba::scalar::RealField> Identity<Multiplicative> for UnitComplex<N> {
|
||||||
|
#[inline]
|
||||||
|
fn identity() -> Self {
|
||||||
|
Self::identity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> AbstractMagma<Multiplicative> for UnitComplex<N> {
|
||||||
|
#[inline]
|
||||||
|
fn operate(&self, rhs: &Self) -> Self {
|
||||||
|
self * rhs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> TwoSidedInverse<Multiplicative> for UnitComplex<N> {
|
||||||
|
#[inline]
|
||||||
|
#[must_use = "Did you mean to use two_sided_inverse_mut()?"]
|
||||||
|
fn two_sided_inverse(&self) -> Self {
|
||||||
|
self.inverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn two_sided_inverse_mut(&mut self) {
|
||||||
|
self.inverse_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_structures(
|
||||||
|
($($marker: ident<$operator: ident>),* $(,)*) => {$(
|
||||||
|
impl<N: RealField + simba::scalar::RealField> $marker<$operator> for UnitComplex<N> {
|
||||||
|
}
|
||||||
|
)*}
|
||||||
|
);
|
||||||
|
|
||||||
|
impl_structures!(
|
||||||
|
AbstractSemigroup<Multiplicative>,
|
||||||
|
AbstractQuasigroup<Multiplicative>,
|
||||||
|
AbstractMonoid<Multiplicative>,
|
||||||
|
AbstractLoop<Multiplicative>,
|
||||||
|
AbstractGroup<Multiplicative>
|
||||||
|
);
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> Transformation<Point2<N>> for UnitComplex<N>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, U2>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn transform_point(&self, pt: &Point2<N>) -> Point2<N> {
|
||||||
|
self.transform_point(pt)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn transform_vector(&self, v: &Vector2<N>) -> Vector2<N> {
|
||||||
|
self.transform_vector(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> ProjectiveTransformation<Point2<N>> for UnitComplex<N>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, U2>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_point(&self, pt: &Point2<N>) -> Point2<N> {
|
||||||
|
self.inverse_transform_point(pt)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn inverse_transform_vector(&self, v: &Vector2<N>) -> Vector2<N> {
|
||||||
|
self.inverse_transform_vector(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> AffineTransformation<Point2<N>> for UnitComplex<N>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, U2>,
|
||||||
|
{
|
||||||
|
type Rotation = Self;
|
||||||
|
type NonUniformScaling = Id;
|
||||||
|
type Translation = Id;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn decompose(&self) -> (Id, Self, Id, Self) {
|
||||||
|
(Id::new(), self.clone(), Id::new(), Self::identity())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_translation(&self, _: &Self::Translation) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn prepend_translation(&self, _: &Self::Translation) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_rotation(&self, r: &Self::Rotation) -> Self {
|
||||||
|
r * self
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn prepend_rotation(&self, r: &Self::Rotation) -> Self {
|
||||||
|
self * r
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn append_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn prepend_scaling(&self, _: &Self::NonUniformScaling) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> Similarity<Point2<N>> for UnitComplex<N>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, U2>,
|
||||||
|
{
|
||||||
|
type Scaling = Id;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn translation(&self) -> Id {
|
||||||
|
Id::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rotation(&self) -> Self {
|
||||||
|
self.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn scaling(&self) -> Id {
|
||||||
|
Id::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! marker_impl(
|
||||||
|
($($Trait: ident),*) => {$(
|
||||||
|
impl<N: RealField + simba::scalar::RealField> $Trait<Point2<N>> for UnitComplex<N>
|
||||||
|
where DefaultAllocator: Allocator<N, U2> { }
|
||||||
|
)*}
|
||||||
|
);
|
||||||
|
|
||||||
|
marker_impl!(Isometry, DirectIsometry, OrthogonalTransformation);
|
||||||
|
|
||||||
|
impl<N: RealField + simba::scalar::RealField> Rotation<Point2<N>> for UnitComplex<N>
|
||||||
|
where
|
||||||
|
DefaultAllocator: Allocator<N, U2>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn powf(&self, n: N) -> Option<Self> {
|
||||||
|
Some(self.powf(n))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn rotation_between(a: &Vector2<N>, b: &Vector2<N>) -> Option<Self> {
|
||||||
|
Some(Self::rotation_between(a, b))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn scaled_rotation_between(a: &Vector2<N>, b: &Vector2<N>, s: N) -> Option<Self> {
|
||||||
|
Some(Self::scaled_rotation_between(a, b, s))
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,7 +55,6 @@ pub trait CsStorageIter<'a, N, R, C = U1> {
|
||||||
|
|
||||||
/// Iterates through all the row indices of the j-th column.
|
/// Iterates through all the row indices of the j-th column.
|
||||||
fn column_row_indices(&'a self, j: usize) -> Self::ColumnRowIndices;
|
fn column_row_indices(&'a self, j: usize) -> Self::ColumnRowIndices;
|
||||||
#[inline(always)]
|
|
||||||
/// Iterates through all the entries of the j-th column.
|
/// Iterates through all the entries of the j-th column.
|
||||||
fn column_entries(&'a self, j: usize) -> Self::ColumnEntries;
|
fn column_entries(&'a self, j: usize) -> Self::ColumnEntries;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +105,8 @@ pub trait CsStorageMut<N, R, C = U1>:
|
||||||
/// A storage of column-compressed sparse matrix based on a Vec.
|
/// A storage of column-compressed sparse matrix based on a Vec.
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct CsVecStorage<N: Scalar, R: Dim, C: Dim>
|
pub struct CsVecStorage<N: Scalar, R: Dim, C: Dim>
|
||||||
where DefaultAllocator: Allocator<usize, C>
|
where
|
||||||
|
DefaultAllocator: Allocator<usize, C>,
|
||||||
{
|
{
|
||||||
pub(crate) shape: (R, C),
|
pub(crate) shape: (R, C),
|
||||||
pub(crate) p: VectorN<usize, C>,
|
pub(crate) p: VectorN<usize, C>,
|
||||||
|
@ -115,7 +115,8 @@ where DefaultAllocator: Allocator<usize, C>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Scalar, R: Dim, C: Dim> CsVecStorage<N, R, C>
|
impl<N: Scalar, R: Dim, C: Dim> CsVecStorage<N, R, C>
|
||||||
where DefaultAllocator: Allocator<usize, C>
|
where
|
||||||
|
DefaultAllocator: Allocator<usize, C>,
|
||||||
{
|
{
|
||||||
/// The value buffer of this storage.
|
/// The value buffer of this storage.
|
||||||
pub fn values(&self) -> &[N] {
|
pub fn values(&self) -> &[N] {
|
||||||
|
@ -136,7 +137,8 @@ where DefaultAllocator: Allocator<usize, C>
|
||||||
impl<N: Scalar, R: Dim, C: Dim> CsVecStorage<N, R, C> where DefaultAllocator: Allocator<usize, C> {}
|
impl<N: Scalar, R: Dim, C: Dim> CsVecStorage<N, R, C> where DefaultAllocator: Allocator<usize, C> {}
|
||||||
|
|
||||||
impl<'a, N: Scalar, R: Dim, C: Dim> CsStorageIter<'a, N, R, C> for CsVecStorage<N, R, C>
|
impl<'a, N: Scalar, R: Dim, C: Dim> CsStorageIter<'a, N, R, C> for CsVecStorage<N, R, C>
|
||||||
where DefaultAllocator: Allocator<usize, C>
|
where
|
||||||
|
DefaultAllocator: Allocator<usize, C>,
|
||||||
{
|
{
|
||||||
type ColumnEntries = ColumnEntries<'a, N>;
|
type ColumnEntries = ColumnEntries<'a, N>;
|
||||||
type ColumnRowIndices = iter::Cloned<slice::Iter<'a, usize>>;
|
type ColumnRowIndices = iter::Cloned<slice::Iter<'a, usize>>;
|
||||||
|
@ -155,7 +157,8 @@ where DefaultAllocator: Allocator<usize, C>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Scalar, R: Dim, C: Dim> CsStorage<N, R, C> for CsVecStorage<N, R, C>
|
impl<N: Scalar, R: Dim, C: Dim> CsStorage<N, R, C> for CsVecStorage<N, R, C>
|
||||||
where DefaultAllocator: Allocator<usize, C>
|
where
|
||||||
|
DefaultAllocator: Allocator<usize, C>,
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn shape(&self) -> (R, C) {
|
fn shape(&self) -> (R, C) {
|
||||||
|
@ -200,7 +203,8 @@ where DefaultAllocator: Allocator<usize, C>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, N: Scalar, R: Dim, C: Dim> CsStorageIterMut<'a, N, R, C> for CsVecStorage<N, R, C>
|
impl<'a, N: Scalar, R: Dim, C: Dim> CsStorageIterMut<'a, N, R, C> for CsVecStorage<N, R, C>
|
||||||
where DefaultAllocator: Allocator<usize, C>
|
where
|
||||||
|
DefaultAllocator: Allocator<usize, C>,
|
||||||
{
|
{
|
||||||
type ValuesMut = slice::IterMut<'a, N>;
|
type ValuesMut = slice::IterMut<'a, N>;
|
||||||
type ColumnEntriesMut = iter::Zip<iter::Cloned<slice::Iter<'a, usize>>, slice::IterMut<'a, N>>;
|
type ColumnEntriesMut = iter::Zip<iter::Cloned<slice::Iter<'a, usize>>, slice::IterMut<'a, N>>;
|
||||||
|
@ -220,8 +224,10 @@ where DefaultAllocator: Allocator<usize, C>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Scalar, R: Dim, C: Dim> CsStorageMut<N, R, C> for CsVecStorage<N, R, C> where DefaultAllocator: Allocator<usize, C>
|
impl<N: Scalar, R: Dim, C: Dim> CsStorageMut<N, R, C> for CsVecStorage<N, R, C> where
|
||||||
{}
|
DefaultAllocator: Allocator<usize, C>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pub struct CsSliceStorage<'a, N: Scalar, R: Dim, C: DimAdd<U1>> {
|
pub struct CsSliceStorage<'a, N: Scalar, R: Dim, C: DimAdd<U1>> {
|
||||||
|
@ -247,7 +253,8 @@ pub struct CsMatrix<
|
||||||
pub type CsVector<N, R = Dynamic, S = CsVecStorage<N, R, U1>> = CsMatrix<N, R, U1, S>;
|
pub type CsVector<N, R = Dynamic, S = CsVecStorage<N, R, U1>> = CsMatrix<N, R, U1, S>;
|
||||||
|
|
||||||
impl<N: Scalar, R: Dim, C: Dim> CsMatrix<N, R, C>
|
impl<N: Scalar, R: Dim, C: Dim> CsMatrix<N, R, C>
|
||||||
where DefaultAllocator: Allocator<usize, C>
|
where
|
||||||
|
DefaultAllocator: Allocator<usize, C>,
|
||||||
{
|
{
|
||||||
/// Creates a new compressed sparse column matrix with the specified dimension and
|
/// Creates a new compressed sparse column matrix with the specified dimension and
|
||||||
/// `nvals` possible non-zero values.
|
/// `nvals` possible non-zero values.
|
||||||
|
@ -403,7 +410,9 @@ impl<N: Scalar, R: Dim, C: Dim, S: CsStorage<N, R, C>> CsMatrix<N, R, C, S> {
|
||||||
|
|
||||||
/// Computes the transpose of this sparse matrix.
|
/// Computes the transpose of this sparse matrix.
|
||||||
pub fn transpose(&self) -> CsMatrix<N, C, R>
|
pub fn transpose(&self) -> CsMatrix<N, C, R>
|
||||||
where DefaultAllocator: Allocator<usize, R> {
|
where
|
||||||
|
DefaultAllocator: Allocator<usize, R>,
|
||||||
|
{
|
||||||
let (nrows, ncols) = self.data.shape();
|
let (nrows, ncols) = self.data.shape();
|
||||||
|
|
||||||
let nvals = self.len();
|
let nvals = self.len();
|
||||||
|
@ -442,10 +451,13 @@ impl<N: Scalar, R: Dim, C: Dim, S: CsStorageMut<N, R, C>> CsMatrix<N, R, C, S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Scalar, R: Dim, C: Dim> CsMatrix<N, R, C>
|
impl<N: Scalar, R: Dim, C: Dim> CsMatrix<N, R, C>
|
||||||
where DefaultAllocator: Allocator<usize, C>
|
where
|
||||||
|
DefaultAllocator: Allocator<usize, C>,
|
||||||
{
|
{
|
||||||
pub(crate) fn sort(&mut self)
|
pub(crate) fn sort(&mut self)
|
||||||
where DefaultAllocator: Allocator<N, R> {
|
where
|
||||||
|
DefaultAllocator: Allocator<N, R>,
|
||||||
|
{
|
||||||
// Size = R
|
// Size = R
|
||||||
let nrows = self.data.shape().0;
|
let nrows = self.data.shape().0;
|
||||||
let mut workspace = unsafe { VectorN::new_uninitialized_generic(nrows, U1) };
|
let mut workspace = unsafe { VectorN::new_uninitialized_generic(nrows, U1) };
|
||||||
|
@ -477,7 +489,9 @@ where DefaultAllocator: Allocator<usize, C>
|
||||||
|
|
||||||
// Remove dupliate entries on a sorted CsMatrix.
|
// Remove dupliate entries on a sorted CsMatrix.
|
||||||
pub(crate) fn dedup(&mut self)
|
pub(crate) fn dedup(&mut self)
|
||||||
where N: Zero + ClosedAdd {
|
where
|
||||||
|
N: Zero + ClosedAdd,
|
||||||
|
{
|
||||||
let mut curr_i = 0;
|
let mut curr_i = 0;
|
||||||
|
|
||||||
for j in 0..self.ncols() {
|
for j in 0..self.ncols() {
|
||||||
|
|
Loading…
Reference in New Issue