From 807e4c153aacf973d9d5b68d943e6bea72d1f431 Mon Sep 17 00:00:00 2001 From: Owen Brooks Date: Wed, 15 Jun 2022 13:47:55 +1000 Subject: [PATCH] Simplify and standardise formatting of geometry types --- src/base/matrix.rs | 15 +++++++++++ src/geometry/dual_quaternion.rs | 25 +++++------------ src/geometry/isometry.rs | 12 ++++----- src/geometry/point.rs | 33 +++++++++-------------- src/geometry/quaternion.rs | 48 ++++++++++++++++++++------------- src/geometry/scale.rs | 18 +++++-------- src/geometry/similarity.rs | 14 +++++----- src/geometry/translation.rs | 18 +++++-------- 8 files changed, 89 insertions(+), 94 deletions(-) diff --git a/src/base/matrix.rs b/src/base/matrix.rs index 9afd8a14..fc3ff857 100644 --- a/src/base/matrix.rs +++ b/src/base/matrix.rs @@ -1968,6 +1968,21 @@ impl_fmt!(fmt::UpperHex, "{:X}", "{:1$X}"); impl_fmt!(fmt::Binary, "{:b}", "{:.1$b}"); impl_fmt!(fmt::Pointer, "{:p}", "{:.1$p}"); +/// Displays a vector using commas as the delimiter +pub fn display_column_vec_as_row(vector: &OVector, f: &mut fmt::Formatter<'_>) -> fmt::Result +where + DefaultAllocator: Allocator, +{ + write!(f, "[")?; + let mut it = vector.iter(); + std::fmt::Display::fmt(it.next().unwrap(), f)?; + for comp in it { + write!(f, ", ")?; + std::fmt::Display::fmt(comp, f)?; + } + write!(f, "]") +} + #[cfg(test)] mod tests { #[test] diff --git a/src/geometry/dual_quaternion.rs b/src/geometry/dual_quaternion.rs index 6f1b7053..46666863 100644 --- a/src/geometry/dual_quaternion.rs +++ b/src/geometry/dual_quaternion.rs @@ -951,25 +951,12 @@ impl Default for UnitDualQuaternion { impl fmt::Display for UnitDualQuaternion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Some(axis) = self.rotation().axis() { - let axis = axis.into_inner(); - write!( - f, - "UnitDualQuaternion translation: {} − angle: {} − axis: ({}, {}, {})", - self.translation().vector, - self.rotation().angle(), - axis[0], - axis[1], - axis[2] - ) - } else { - write!( - f, - "UnitDualQuaternion translation: {} − angle: {} − axis: (undefined)", - self.translation().vector, - self.rotation().angle() - ) - } + write!(f, "{{ translation: ")?; + crate::display_column_vec_as_row(&self.translation().vector, f)?; + write!(f, ", ")?; + write!(f, "rotation: ")?; + std::fmt::Display::fmt(&self.rotation(), f)?; + write!(f, " }}") } } diff --git a/src/geometry/isometry.rs b/src/geometry/isometry.rs index 92169742..6f375d45 100755 --- a/src/geometry/isometry.rs +++ b/src/geometry/isometry.rs @@ -548,11 +548,11 @@ where R: fmt::Display, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let precision = f.precision().unwrap_or(3); - - writeln!(f, "Isometry {{")?; - write!(f, "{:.*}", precision, self.translation)?; - write!(f, "{:.*}", precision, self.rotation)?; - writeln!(f, "}}") + write!(f, "{{ translation: ")?; + crate::display_column_vec_as_row(&self.translation.vector, f)?; + write!(f, ", ")?; + write!(f, "rotation: ")?; + std::fmt::Display::fmt(&self.rotation, f)?; + write!(f, " }}") } } diff --git a/src/geometry/point.rs b/src/geometry/point.rs index 306c18e5..d639a04a 100644 --- a/src/geometry/point.rs +++ b/src/geometry/point.rs @@ -35,7 +35,7 @@ use std::mem::MaybeUninit; /// may have some other methods, e.g., `isometry.inverse_transform_point(&point)`. See the documentation /// of said transformations for details. #[repr(C)] -#[derive(Clone)] +#[derive(Clone, Debug)] #[cfg_attr( feature = "rkyv-serialize-no-std", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) @@ -49,15 +49,6 @@ where pub coords: OVector, } -impl fmt::Debug for OPoint -where - DefaultAllocator: Allocator, -{ - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - self.coords.as_slice().fmt(formatter) - } -} - impl hash::Hash for OPoint where DefaultAllocator: Allocator, @@ -457,17 +448,19 @@ impl fmt::Display for OPoint where DefaultAllocator: Allocator, { + /// ```rust + /// # use nalgebra::Point3; + /// let point = Point3::new(1.12345678, 2.12345678, 3.12345678); + /// let rounded = format!("{:#.4}", point); // print point in compact representation + /// assert_eq!(rounded, "[1.1235, 2.1235, 3.1235]"); + /// let vertical = format!("{}", point); // print point as a column + /// assert_eq!(vertical, "\n ┌ ┐\n │ 1.12345678 │\n │ 2.12345678 │\n │ 3.12345678 │\n └ ┘"); + /// ``` fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{{")?; - - let mut it = self.coords.iter(); - - write!(f, "{}", *it.next().unwrap())?; - - for comp in it { - write!(f, ", {}", *comp)?; + if f.alternate() { + crate::display_column_vec_as_row(&self.coords, f) + } else { + std::fmt::Display::fmt(&self.coords, f) // pretty-prints vector } - - write!(f, "}}") } } diff --git a/src/geometry/quaternion.rs b/src/geometry/quaternion.rs index f38dca6f..5d02988a 100755 --- a/src/geometry/quaternion.rs +++ b/src/geometry/quaternion.rs @@ -36,7 +36,13 @@ pub struct Quaternion { impl fmt::Debug for Quaternion { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - self.coords.as_slice().fmt(formatter) + formatter + .debug_struct("Quaternion") + .field("x", &self.coords[0]) + .field("y", &self.coords[1]) + .field("z", &self.coords[2]) + .field("w", &self.coords[3]) + .finish() } } @@ -995,11 +1001,16 @@ impl> UlpsEq for Quaternion { impl fmt::Display for Quaternion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "Quaternion {} − ({}, {}, {})", - self[3], self[0], self[1], self[2] - ) + // Formatting of each item is forwarded to standard fmt display so that formatting + // flags are followed correctly. + std::fmt::Display::fmt(&self[0], f)?; + write!(f, " + ")?; + std::fmt::Display::fmt(&self[1], f)?; + write!(f, "i + ")?; + std::fmt::Display::fmt(&self[2], f)?; + write!(f, "j + ")?; + std::fmt::Display::fmt(&self[3], f)?; + write!(f, "k") } } @@ -1636,23 +1647,22 @@ impl Default for UnitQuaternion { impl fmt::Display for UnitQuaternion { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Formatting of each item is forwarded to standard fmt Display so that formatting + // flags are followed correctly. + write!(f, "{{ angle: ")?; + std::fmt::Display::fmt(&self.angle(), f)?; + write!(f, ", axis: (")?; if let Some(axis) = self.axis() { let axis = axis.into_inner(); - write!( - f, - "UnitQuaternion angle: {} − axis: ({}, {}, {})", - self.angle(), - axis[0], - axis[1], - axis[2] - ) + std::fmt::Display::fmt(&axis[0], f)?; + write!(f, ", ")?; + std::fmt::Display::fmt(&axis[1], f)?; + write!(f, ", ")?; + std::fmt::Display::fmt(&axis[2], f)?; } else { - write!( - f, - "UnitQuaternion angle: {} − axis: (undefined)", - self.angle() - ) + write!(f, "undefined")?; } + write!(f, ") }}") } } diff --git a/src/geometry/scale.rs b/src/geometry/scale.rs index 37da1ef0..ad09cca5 100755 --- a/src/geometry/scale.rs +++ b/src/geometry/scale.rs @@ -23,19 +23,13 @@ use crate::geometry::Point; derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) )] #[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))] -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct Scale { /// The scale coordinates, i.e., how much is multiplied to a point's coordinates when it is /// scaled. pub vector: SVector, } -impl fmt::Debug for Scale { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - self.vector.as_slice().fmt(formatter) - } -} - impl hash::Hash for Scale where Owned>: hash::Hash, @@ -369,10 +363,10 @@ where */ impl fmt::Display for Scale { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let precision = f.precision().unwrap_or(3); - - writeln!(f, "Scale {{")?; - write!(f, "{:.*}", precision, self.vector)?; - writeln!(f, "}}") + if f.alternate() { + crate::display_column_vec_as_row(&self.vector, f) + } else { + std::fmt::Display::fmt(&self.vector, f) // pretty-prints vector + } } } diff --git a/src/geometry/similarity.rs b/src/geometry/similarity.rs index 8c38ff1e..0a6060ac 100755 --- a/src/geometry/similarity.rs +++ b/src/geometry/similarity.rs @@ -397,11 +397,13 @@ where R: AbstractRotation + fmt::Display, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let precision = f.precision().unwrap_or(3); - - writeln!(f, "Similarity {{")?; - write!(f, "{:.*}", precision, self.isometry)?; - write!(f, "Scaling: {:.*}", precision, self.scaling)?; - writeln!(f, "}}") + write!(f, "{{ translation: ")?; + crate::display_column_vec_as_row(&self.isometry.translation.vector, f)?; + write!(f, ", ")?; + write!(f, "rotation: ")?; + std::fmt::Display::fmt(&self.isometry.rotation, f)?; + write!(f, ", scaling: ")?; + std::fmt::Display::fmt(&self.scaling, f)?; + write!(f, " }}") } } diff --git a/src/geometry/translation.rs b/src/geometry/translation.rs index bef66f68..b910d88b 100755 --- a/src/geometry/translation.rs +++ b/src/geometry/translation.rs @@ -23,19 +23,13 @@ use crate::geometry::Point; derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize) )] #[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))] -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Debug)] pub struct Translation { /// The translation coordinates, i.e., how much is added to a point's coordinates when it is /// translated. pub vector: SVector, } -impl fmt::Debug for Translation { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { - self.vector.as_slice().fmt(formatter) - } -} - impl hash::Hash for Translation where Owned>: hash::Hash, @@ -284,10 +278,10 @@ where */ impl fmt::Display for Translation { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let precision = f.precision().unwrap_or(3); - - writeln!(f, "Translation {{")?; - write!(f, "{:.*}", precision, self.vector)?; - writeln!(f, "}}") + if f.alternate() { + crate::display_column_vec_as_row(&self.vector, f) + } else { + std::fmt::Display::fmt(&self.vector, f) // pretty-prints vector + } } }