From 2aa4a82499d4becd2284cdb482213d541b8804dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 16:29:10 +0200 Subject: Adding upstream version 86.0.1. Signed-off-by: Daniel Baumann --- third_party/rust/euclid/src/homogen.rs | 215 +++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 third_party/rust/euclid/src/homogen.rs (limited to 'third_party/rust/euclid/src/homogen.rs') diff --git a/third_party/rust/euclid/src/homogen.rs b/third_party/rust/euclid/src/homogen.rs new file mode 100644 index 0000000000..850726bb2f --- /dev/null +++ b/third_party/rust/euclid/src/homogen.rs @@ -0,0 +1,215 @@ +// Copyright 2018 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::point::{Point2D, Point3D}; +use crate::vector::{Vector2D, Vector3D}; + +use crate::num::{One, Zero}; + +use core::cmp::{Eq, PartialEq}; +use core::fmt; +use core::hash::Hash; +use core::marker::PhantomData; +use core::ops::Div; +#[cfg(feature = "serde")] +use serde; + +/// Homogeneous vector in 3D space. +#[repr(C)] +pub struct HomogeneousVector { + pub x: T, + pub y: T, + pub z: T, + pub w: T, + #[doc(hidden)] + pub _unit: PhantomData, +} + +impl Copy for HomogeneousVector {} + +impl Clone for HomogeneousVector { + fn clone(&self) -> Self { + HomogeneousVector { + x: self.x.clone(), + y: self.y.clone(), + z: self.z.clone(), + w: self.w.clone(), + _unit: PhantomData, + } + } +} + +#[cfg(feature = "serde")] +impl<'de, T, U> serde::Deserialize<'de> for HomogeneousVector +where + T: serde::Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let (x, y, z, w) = serde::Deserialize::deserialize(deserializer)?; + Ok(HomogeneousVector { + x, + y, + z, + w, + _unit: PhantomData, + }) + } +} + +#[cfg(feature = "serde")] +impl serde::Serialize for HomogeneousVector +where + T: serde::Serialize, +{ + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + (&self.x, &self.y, &self.z, &self.w).serialize(serializer) + } +} + +impl Eq for HomogeneousVector where T: Eq {} + +impl PartialEq for HomogeneousVector +where + T: PartialEq, +{ + fn eq(&self, other: &Self) -> bool { + self.x == other.x && self.y == other.y && self.z == other.z && self.w == other.w + } +} + +impl Hash for HomogeneousVector +where + T: Hash, +{ + fn hash(&self, h: &mut H) { + self.x.hash(h); + self.y.hash(h); + self.z.hash(h); + self.w.hash(h); + } +} + +impl HomogeneousVector { + /// Constructor taking scalar values directly. + #[inline] + pub const fn new(x: T, y: T, z: T, w: T) -> Self { + HomogeneousVector { + x, + y, + z, + w, + _unit: PhantomData, + } + } +} + +impl + Zero + PartialOrd, U> HomogeneousVector { + /// Convert into Cartesian 2D point. + /// + /// Returns None if the point is on or behind the W=0 hemisphere. + #[inline] + pub fn to_point2d(self) -> Option> { + if self.w > T::zero() { + Some(Point2D::new(self.x / self.w, self.y / self.w)) + } else { + None + } + } + + /// Convert into Cartesian 3D point. + /// + /// Returns None if the point is on or behind the W=0 hemisphere. + #[inline] + pub fn to_point3d(self) -> Option> { + if self.w > T::zero() { + Some(Point3D::new( + self.x / self.w, + self.y / self.w, + self.z / self.w, + )) + } else { + None + } + } +} + +impl From> for HomogeneousVector { + #[inline] + fn from(v: Vector2D) -> Self { + HomogeneousVector::new(v.x, v.y, T::zero(), T::zero()) + } +} + +impl From> for HomogeneousVector { + #[inline] + fn from(v: Vector3D) -> Self { + HomogeneousVector::new(v.x, v.y, v.z, T::zero()) + } +} + +impl From> for HomogeneousVector { + #[inline] + fn from(p: Point2D) -> Self { + HomogeneousVector::new(p.x, p.y, T::zero(), T::one()) + } +} + +impl From> for HomogeneousVector { + #[inline] + fn from(p: Point3D) -> Self { + HomogeneousVector::new(p.x, p.y, p.z, T::one()) + } +} + +impl fmt::Debug for HomogeneousVector { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("") + .field(&self.x) + .field(&self.y) + .field(&self.z) + .field(&self.w) + .finish() + } +} + +#[cfg(test)] +mod homogeneous { + use super::HomogeneousVector; + use crate::default::{Point2D, Point3D}; + + #[test] + fn roundtrip() { + assert_eq!( + Some(Point2D::new(1.0, 2.0)), + HomogeneousVector::from(Point2D::new(1.0, 2.0)).to_point2d() + ); + assert_eq!( + Some(Point3D::new(1.0, -2.0, 0.1)), + HomogeneousVector::from(Point3D::new(1.0, -2.0, 0.1)).to_point3d() + ); + } + + #[test] + fn negative() { + assert_eq!( + None, + HomogeneousVector::::new(1.0, 2.0, 3.0, 0.0).to_point2d() + ); + assert_eq!( + None, + HomogeneousVector::::new(1.0, -2.0, -3.0, -2.0).to_point3d() + ); + } +} -- cgit v1.2.3