зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1711648 - Update euclid to 0.22.6. r=gfx-reviewers,jrmuizel
Differential Revision: https://phabricator.services.mozilla.com/D116266
This commit is contained in:
Родитель
6c020067b9
Коммит
be0eb5fbfc
|
@ -1332,9 +1332,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "euclid"
|
||||
version = "0.22.0"
|
||||
version = "0.22.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ab0e07e345fb061928646949fdf5fb888e5d75a57385e7f5856e45be289e745"
|
||||
checksum = "da96828553a086d7b18dcebfc579bd9628b016f86590d7453c115e490fa74b80"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"serde",
|
||||
|
|
|
@ -9,7 +9,7 @@ dirs = "2"
|
|||
rayon = "1"
|
||||
num_cpus = "1.7.0"
|
||||
tracy-rs = "0.1"
|
||||
euclid = { version = "0.22.0", features = ["serde"] }
|
||||
euclid = { version = "0.22.5", features = ["serde"] }
|
||||
app_units = "0.7"
|
||||
gleam = "0.13.1"
|
||||
log = "0.4"
|
||||
|
|
|
@ -529,9 +529,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "euclid"
|
||||
version = "0.22.0"
|
||||
version = "0.22.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ab0e07e345fb061928646949fdf5fb888e5d75a57385e7f5856e45be289e745"
|
||||
checksum = "da96828553a086d7b18dcebfc579bd9628b016f86590d7453c115e490fa74b80"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"serde",
|
||||
|
|
|
@ -18,7 +18,7 @@ app_units = "0.7"
|
|||
bitflags = "1.2"
|
||||
byteorder = "1.2.1"
|
||||
derive_more = "0.99"
|
||||
euclid = { version = "0.22.0", features = ["serde"] }
|
||||
euclid = { version = "0.22.6", features = ["serde"] }
|
||||
malloc_size_of_derive = "0.1"
|
||||
serde = { version = "1.0", features = ["rc"] }
|
||||
serde_derive = "1.0"
|
||||
|
|
Двоичные данные
gfx/wr/wrench/reftests/transforms/prim-suite.png
Двоичные данные
gfx/wr/wrench/reftests/transforms/prim-suite.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 48 KiB После Ширина: | Высота: | Размер: 50 KiB |
|
@ -1 +1 @@
|
|||
{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"a86dfb641b12e15efe3e2b40a2061c27b9347b38a315700773d7af2c6acccc96","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"625bec69c76ce5423fdd05cfe46922b2680ec517f97c5854ce34798d1d8a9541","src/angle.rs":"b4b17c16bd135914a6e2ebad54b9cbb8ea475d5992bcb75c397b7813b6f7b8dd","src/approxeq.rs":"8ad9ab7336e1924b0543eb46f975367f4388a4dda91839b7cda7d21eec8991fb","src/approxord.rs":"f1b11ea7603b3dddb0002c7ded934816f5a8bb108e150028b49595b8e3382ac1","src/box2d.rs":"2566d13d8823c13eaab68bbeabe371fa507497d07b3638e5c501cd73cb2a5251","src/box3d.rs":"a96e6b4cbae217095fcbc997db9f7dfafe813d84856bc0a02abbbb6bc881eac7","src/homogen.rs":"57c08e6e5d0bf87c724eb074c624a6557170f9d695ef1ed1a4b2677069dbbaa4","src/length.rs":"6972f49203c0256287dbf5119124ad64e2cf001574995bfaed8cd21e4a19f17c","src/lib.rs":"ebf2023c1e1bd397a4ae135a14657d00757c9ad4094d32d65848a1d5e061df7a","src/macros.rs":"3b475e84d00cceee6c7e96e9f2c97ba15d8dc7f4094efb82c5ed10bd60d86a64","src/num.rs":"27ef5975c2149f4c1a4659ae1dd9fc86618579ec985361130ea9fdc891fcfae3","src/point.rs":"db1beb1e581261a8077669c0a69973c35100163e1b98e6b720b0af331a951345","src/rect.rs":"83ce34da75dc570d8f62700d283adfda419a98ea2d0fc691dedc4389c574dd46","src/rigid.rs":"e9b39039df2882d5b8d5a28305ddb40f7c59a9401af615b842f485a62af12217","src/rotation.rs":"6ed0b5793fdd3d557e98e9523e506786c337c98ae61a3f7773bbd934922803a9","src/scale.rs":"c26ad154ace1647196eb1a19c0c26c22c461322c643c22b9b260392443688299","src/side_offsets.rs":"b795816fe6cc027692bbb5704eebe48d8556619f837ce75de34ca6acf8502ef9","src/size.rs":"17002e23cc424c04d288f65e5f6493759ea7bfb2b0a749131c1a3561d2e3def4","src/transform2d.rs":"505f47b58a96a64804d027d21ebf28c75c80c7d2975760d6d2cadbefb7c4605c","src/transform3d.rs":"e8221391475208af1430ad3a432e972fe45cec68e10103a57af7197f11e034f8","src/translation.rs":"8500a10ed37447fbc41a4a1f554c08095f055c36b4e0a637d7c07505fe2570a2","src/trig.rs":"ab09a8503d04ac1d0d6848d074ac18a22d324184e5bb186bbd4287c977894886","src/vector.rs":"2f573f1587c8f119c45c8822c81d3fe5aa6113cad51be4d19eea73d8058b91dd"},"package":"7ab0e07e345fb061928646949fdf5fb888e5d75a57385e7f5856e45be289e745"}
|
||||
{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"744f48a8bf5a6c7459ba64ed48031ea29cb0d11cce36637a4adc57e0bc85b73b","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"625bec69c76ce5423fdd05cfe46922b2680ec517f97c5854ce34798d1d8a9541","src/angle.rs":"02331fcc1f22af951f4da3aa80f1f8f9708d20200716ab5547952db01f5c0e6e","src/approxeq.rs":"8ad9ab7336e1924b0543eb46f975367f4388a4dda91839b7cda7d21eec8991fb","src/approxord.rs":"f1b11ea7603b3dddb0002c7ded934816f5a8bb108e150028b49595b8e3382ac1","src/box2d.rs":"1cb8456138c96fcbc1c2d88f58d45157b95f6d5a7cffb133decc3f2e44d52710","src/box3d.rs":"d1144b284f6907b8dfefa00b1373ea904f0b50a5d8683019d13b07d4d96c2c8e","src/homogen.rs":"57c08e6e5d0bf87c724eb074c624a6557170f9d695ef1ed1a4b2677069dbbaa4","src/length.rs":"37a6a1683867ccec6247726f66054bb4210bca41f40e8ef69f6fe5dcc4c60169","src/lib.rs":"ebf2023c1e1bd397a4ae135a14657d00757c9ad4094d32d65848a1d5e061df7a","src/macros.rs":"3b475e84d00cceee6c7e96e9f2c97ba15d8dc7f4094efb82c5ed10bd60d86a64","src/num.rs":"9c8d4564549646e68eeb2f004239626369cce3d752002497f8dda8a91d833ec1","src/point.rs":"766dd28709ad101ca304314a2ed0bcba28bfa17e1984d592a55eb0d9beb0287d","src/rect.rs":"de0e9bbb7a732a939c133b7eabbc5c604f5e14948e7773f864683ebe50f8bfe5","src/rigid.rs":"e9b39039df2882d5b8d5a28305ddb40f7c59a9401af615b842f485a62af12217","src/rotation.rs":"6ed0b5793fdd3d557e98e9523e506786c337c98ae61a3f7773bbd934922803a9","src/scale.rs":"c26ad154ace1647196eb1a19c0c26c22c461322c643c22b9b260392443688299","src/side_offsets.rs":"dcb2016d2e558eb79126a534f76ecf81eecf5ff5c5e18329d5347728c3a52f6d","src/size.rs":"684d02a037a130da8d61e962945ecde19fad5018494e7777e90bbc6b168fae56","src/transform2d.rs":"8123a3b05c9661a0029f6c435eb065075215d90001e1d2e66a7fb06327e206b9","src/transform3d.rs":"549dd3fa686c05adb8252665c4ebc1189834cef197c58b03a1abddc2c7fe1793","src/translation.rs":"5b56395f7403e89cd2f0396b99ab20ae3d18135067d19d4dfb68a0164eeed06d","src/trig.rs":"ab09a8503d04ac1d0d6848d074ac18a22d324184e5bb186bbd4287c977894886","src/vector.rs":"b56b4f0f95fb7e701d1642f941d1b52a6b88fd6b051cba12b8b204e128b647a0"},"package":"da96828553a086d7b18dcebfc579bd9628b016f86590d7453c115e490fa74b80"}
|
|
@ -13,7 +13,7 @@
|
|||
[package]
|
||||
edition = "2018"
|
||||
name = "euclid"
|
||||
version = "0.22.0"
|
||||
version = "0.22.6"
|
||||
authors = ["The Servo Project Developers"]
|
||||
description = "Geometry primitives"
|
||||
documentation = "https://docs.rs/euclid/"
|
||||
|
@ -21,6 +21,11 @@ keywords = ["matrix", "vector", "linear-algebra", "geometry"]
|
|||
categories = ["science"]
|
||||
license = "MIT / Apache-2.0"
|
||||
repository = "https://github.com/servo/euclid"
|
||||
[dependencies.arbitrary]
|
||||
version = "1"
|
||||
features = ["derive"]
|
||||
optional = true
|
||||
|
||||
[dependencies.mint]
|
||||
version = "0.5.1"
|
||||
optional = true
|
||||
|
|
|
@ -11,6 +11,7 @@ use crate::approxeq::ApproxEq;
|
|||
use crate::trig::Trig;
|
||||
use core::cmp::{Eq, PartialEq};
|
||||
use core::hash::Hash;
|
||||
use core::iter::Sum;
|
||||
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign};
|
||||
use num_traits::{Float, FloatConst, NumCast, One, Zero};
|
||||
#[cfg(feature = "serde")]
|
||||
|
@ -19,6 +20,7 @@ use serde::{Deserialize, Serialize};
|
|||
/// An angle in radians
|
||||
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
|
||||
pub struct Angle<T> {
|
||||
pub radians: T,
|
||||
}
|
||||
|
@ -107,6 +109,12 @@ where
|
|||
pub fn sin_cos(self) -> (T, T) {
|
||||
self.radians.sin_cos()
|
||||
}
|
||||
|
||||
/// Returns true if the angle is a finite number.
|
||||
#[inline]
|
||||
pub fn is_finite(self) -> bool {
|
||||
self.radians.is_finite()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Angle<T>
|
||||
|
@ -174,9 +182,28 @@ where
|
|||
}
|
||||
|
||||
impl<T: Add<T, Output = T>> Add for Angle<T> {
|
||||
type Output = Angle<T>;
|
||||
fn add(self, other: Angle<T>) -> Angle<T> {
|
||||
Angle::radians(self.radians + other.radians)
|
||||
type Output = Self;
|
||||
fn add(self, other: Self) -> Self {
|
||||
Self::radians(self.radians + other.radians)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Add<T, Output = T>> Add<&Self> for Angle<T> {
|
||||
type Output = Self;
|
||||
fn add(self, other: &Self) -> Self {
|
||||
Self::radians(self.radians + other.radians)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Add + Zero> Sum for Angle<T> {
|
||||
fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::zero(), Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: 'a + Add + Copy + Zero> Sum<&'a Self> for Angle<T> {
|
||||
fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::zero(), Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -314,3 +341,11 @@ fn lerp() {
|
|||
.lerp(b + A::two_pi() * 5.0, 0.75)
|
||||
.approx_eq(&Angle::radians(1.75)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sum() {
|
||||
type A = Angle<f32>;
|
||||
let angles = [A::radians(1.0), A::radians(2.0), A::radians(3.0)];
|
||||
let sum = A::radians(6.0);
|
||||
assert_eq!(angles.iter().sum::<A>(), sum);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ use crate::side_offsets::SideOffsets2D;
|
|||
use crate::size::Size2D;
|
||||
use crate::vector::{vec2, Vector2D};
|
||||
|
||||
use num_traits::NumCast;
|
||||
use num_traits::{NumCast, Float};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
@ -25,7 +25,7 @@ use core::borrow::Borrow;
|
|||
use core::cmp::PartialOrd;
|
||||
use core::fmt;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::ops::{Add, Div, DivAssign, Mul, MulAssign, Sub};
|
||||
use core::ops::{Add, Div, DivAssign, Mul, MulAssign, Sub, Range};
|
||||
|
||||
/// A 2d axis aligned rectangle represented by its minimum and maximum coordinates.
|
||||
///
|
||||
|
@ -105,6 +105,27 @@ impl<T, U> Box2D<T, U> {
|
|||
pub const fn new(min: Point2D<T, U>, max: Point2D<T, U>) -> Self {
|
||||
Box2D { min, max }
|
||||
}
|
||||
|
||||
/// Constructor.
|
||||
#[inline]
|
||||
pub fn from_origin_and_size(origin: Point2D<T, U>, size: Size2D<T, U>) -> Self
|
||||
where
|
||||
T: Copy + Add<T, Output = T>
|
||||
{
|
||||
Box2D {
|
||||
min: origin,
|
||||
max: point2(origin.x + size.width, origin.y + size.height),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a Box2D of the given size, at offset zero.
|
||||
#[inline]
|
||||
pub fn from_size(size: Size2D<T, U>) -> Self where T: Zero {
|
||||
Box2D {
|
||||
min: Point2D::zero(),
|
||||
max: point2(size.width, size.height),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Box2D<T, U>
|
||||
|
@ -195,8 +216,18 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Computes the union of two boxes.
|
||||
///
|
||||
/// If either of the boxes is empty, the other one is returned.
|
||||
#[inline]
|
||||
pub fn union(&self, other: &Self) -> Self {
|
||||
if other.is_empty() {
|
||||
return *self;
|
||||
}
|
||||
if self.is_empty() {
|
||||
return *other;
|
||||
}
|
||||
|
||||
Box2D {
|
||||
min: point2(min(self.min.x, other.min.x), min(self.min.y, other.min.y)),
|
||||
max: point2(max(self.max.x, other.max.x), max(self.max.y, other.max.y)),
|
||||
|
@ -227,6 +258,14 @@ where
|
|||
(self.max - self.min).to_size()
|
||||
}
|
||||
|
||||
/// Change the size of the box by adjusting the max endpoint
|
||||
/// without modifying the min endpoint.
|
||||
#[inline]
|
||||
pub fn set_size(&mut self, size: Size2D<T, U>) {
|
||||
let diff = (self.size() - size).to_vector();
|
||||
self.max -= diff;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn width(&self) -> T {
|
||||
self.max.x - self.min.x
|
||||
|
@ -286,14 +325,6 @@ impl<T, U> Box2D<T, U>
|
|||
where
|
||||
T: Copy + Zero + PartialOrd,
|
||||
{
|
||||
/// Creates a Box2D of the given size, at offset zero.
|
||||
#[inline]
|
||||
pub fn from_size(size: Size2D<T, U>) -> Self {
|
||||
let zero = Point2D::zero();
|
||||
let point = size.to_vector().to_point();
|
||||
Box2D::from_points(&[zero, point])
|
||||
}
|
||||
|
||||
/// Returns the smallest box containing all of the provided points.
|
||||
pub fn from_points<I>(points: I) -> Self
|
||||
where
|
||||
|
@ -443,6 +474,16 @@ impl<T, U> Box2D<T, U>
|
|||
where
|
||||
T: Copy,
|
||||
{
|
||||
#[inline]
|
||||
pub fn x_range(&self) -> Range<T> {
|
||||
self.min.x..self.max.x
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn y_range(&self) -> Range<T> {
|
||||
self.min.y..self.max.y
|
||||
}
|
||||
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> Box2D<T, UnknownUnit> {
|
||||
|
@ -551,6 +592,14 @@ impl<T: NumCast + Copy, U> Box2D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Float, U> Box2D<T, U> {
|
||||
/// Returns true if all members are finite.
|
||||
#[inline]
|
||||
pub fn is_finite(self) -> bool {
|
||||
self.min.is_finite() && self.max.is_finite()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Round,
|
||||
|
@ -602,6 +651,15 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Default, U> Default for Box2D<T, U> {
|
||||
fn default() -> Self {
|
||||
Box2D {
|
||||
min: Default::default(),
|
||||
max: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::default::Box2D;
|
||||
|
@ -815,4 +873,23 @@ mod tests {
|
|||
assert!(Box2D { min: point2(1.0, -2.0), max: point2(NAN, 2.0) }.is_empty());
|
||||
assert!(Box2D { min: point2(1.0, -2.0), max: point2(0.0, NAN) }.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_origin_and_size() {
|
||||
let b = Box2D::from_origin_and_size(point2(1.0, 2.0), size2(3.0, 4.0));
|
||||
assert_eq!(b.min, point2(1.0, 2.0));
|
||||
assert_eq!(b.size(), size2(3.0, 4.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_size() {
|
||||
let mut b = Box2D {
|
||||
min: point2(1.0, 2.0),
|
||||
max: point2(3.0, 4.0),
|
||||
};
|
||||
b.set_size(size2(5.0, 6.0));
|
||||
|
||||
assert_eq!(b.min, point2(1.0, 2.0));
|
||||
assert_eq!(b.size(), size2(5.0, 6.0));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ use crate::scale::Scale;
|
|||
use crate::size::Size3D;
|
||||
use crate::vector::Vector3D;
|
||||
|
||||
use num_traits::NumCast;
|
||||
use num_traits::{NumCast, Float};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
@ -23,7 +23,7 @@ use core::borrow::Borrow;
|
|||
use core::cmp::PartialOrd;
|
||||
use core::fmt;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::ops::{Add, Div, DivAssign, Mul, MulAssign, Sub};
|
||||
use core::ops::{Add, Div, DivAssign, Mul, MulAssign, Sub, Range};
|
||||
|
||||
/// An axis aligned 3D box represented by its minimum and maximum coordinates.
|
||||
#[repr(C)]
|
||||
|
@ -75,6 +75,15 @@ impl<T, U> Box3D<T, U> {
|
|||
pub const fn new(min: Point3D<T, U>, max: Point3D<T, U>) -> Self {
|
||||
Box3D { min, max }
|
||||
}
|
||||
|
||||
/// Creates a Box3D of the given size, at offset zero.
|
||||
#[inline]
|
||||
pub fn from_size(size: Size3D<T, U>) -> Self where T: Zero {
|
||||
Box3D {
|
||||
min: Point3D::zero(),
|
||||
max: point3(size.width, size.height, size.depth),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Box3D<T, U>
|
||||
|
@ -174,9 +183,18 @@ where
|
|||
Box3D::new(intersection_min, intersection_max)
|
||||
}
|
||||
|
||||
/// Returns the smallest box containing both of the provided boxes.
|
||||
/// Computes the union of two boxes.
|
||||
///
|
||||
/// If either of the boxes is empty, the other one is returned.
|
||||
#[inline]
|
||||
pub fn union(&self, other: &Self) -> Self {
|
||||
if other.is_empty() {
|
||||
return *self;
|
||||
}
|
||||
if self.is_empty() {
|
||||
return *other;
|
||||
}
|
||||
|
||||
Box3D::new(
|
||||
Point3D::new(
|
||||
min(self.min.x, other.min.x),
|
||||
|
@ -255,14 +273,6 @@ impl<T, U> Box3D<T, U>
|
|||
where
|
||||
T: Copy + Zero + PartialOrd,
|
||||
{
|
||||
/// Creates a Box3D of the given size, at offset zero.
|
||||
#[inline]
|
||||
pub fn from_size(size: Size3D<T, U>) -> Self {
|
||||
let zero = Point3D::zero();
|
||||
let point = size.to_vector().to_point();
|
||||
Box3D::from_points(&[zero, point])
|
||||
}
|
||||
|
||||
/// Returns the smallest box containing all of the provided points.
|
||||
pub fn from_points<I>(points: I) -> Self
|
||||
where
|
||||
|
@ -438,6 +448,21 @@ impl<T, U> Box3D<T, U>
|
|||
where
|
||||
T: Copy,
|
||||
{
|
||||
#[inline]
|
||||
pub fn x_range(&self) -> Range<T> {
|
||||
self.min.x..self.max.x
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn y_range(&self) -> Range<T> {
|
||||
self.min.y..self.max.y
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn z_range(&self) -> Range<T> {
|
||||
self.min.z..self.max.z
|
||||
}
|
||||
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> Box3D<T, UnknownUnit> {
|
||||
|
@ -552,6 +577,14 @@ impl<T: NumCast + Copy, U> Box3D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Float, U> Box3D<T, U> {
|
||||
/// Returns true if all members are finite.
|
||||
#[inline]
|
||||
pub fn is_finite(self) -> bool {
|
||||
self.min.is_finite() && self.max.is_finite()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Round,
|
||||
|
@ -605,6 +638,15 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Default, U> Default for Box3D<T, U> {
|
||||
fn default() -> Self {
|
||||
Box3D {
|
||||
min: Default::default(),
|
||||
max: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Shorthand for `Box3D::new(Point3D::new(x1, y1, z1), Point3D::new(x2, y2, z2))`.
|
||||
pub fn box3d<T: Copy, U>(
|
||||
min_x: T,
|
||||
|
|
|
@ -17,6 +17,7 @@ use crate::num::One;
|
|||
use core::cmp::Ordering;
|
||||
use core::fmt;
|
||||
use core::hash::{Hash, Hasher};
|
||||
use core::iter::Sum;
|
||||
use core::marker::PhantomData;
|
||||
use core::ops::{Add, Div, Mul, Neg, Sub};
|
||||
use core::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
|
||||
|
@ -175,6 +176,29 @@ impl<T: Add, U> Add for Length<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
// length + &length
|
||||
impl<T: Add + Copy, U> Add<&Self> for Length<T, U> {
|
||||
type Output = Length<T::Output, U>;
|
||||
|
||||
fn add(self, other: &Self) -> Self::Output {
|
||||
Length::new(self.0 + other.0)
|
||||
}
|
||||
}
|
||||
|
||||
// length_iter.copied().sum()
|
||||
impl<T: Add<Output = T> + Zero, U> Sum for Length<T, U> {
|
||||
fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::zero(), Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
// length_iter.sum()
|
||||
impl<'a, T: 'a + Add<Output = T> + Copy + Zero, U: 'a> Sum<&'a Self> for Length<T, U> {
|
||||
fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::zero(), Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
// length += length
|
||||
impl<T: AddAssign, U> AddAssign for Length<T, U> {
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
|
@ -372,9 +396,16 @@ mod tests {
|
|||
let length1: Length<u8, Mm> = Length::new(250);
|
||||
let length2: Length<u8, Mm> = Length::new(5);
|
||||
|
||||
let result = length1 + length2;
|
||||
assert_eq!((length1 + length2).get(), 255);
|
||||
assert_eq!((length1 + &length2).get(), 255);
|
||||
}
|
||||
|
||||
assert_eq!(result.get(), 255);
|
||||
#[test]
|
||||
fn test_sum() {
|
||||
type L = Length<f32, Mm>;
|
||||
let lengths = [L::new(1.0), L::new(2.0), L::new(3.0)];
|
||||
|
||||
assert_eq!(lengths.iter().sum::<L>(), L::new(6.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -70,6 +70,29 @@ pub trait Ceil: Copy {
|
|||
fn ceil(self) -> Self;
|
||||
}
|
||||
|
||||
macro_rules! num_int {
|
||||
($ty:ty) => {
|
||||
impl Round for $ty {
|
||||
#[inline]
|
||||
fn round(self) -> $ty {
|
||||
self
|
||||
}
|
||||
}
|
||||
impl Floor for $ty {
|
||||
#[inline]
|
||||
fn floor(self) -> $ty {
|
||||
self
|
||||
}
|
||||
}
|
||||
impl Ceil for $ty {
|
||||
#[inline]
|
||||
fn ceil(self) -> $ty {
|
||||
self
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! num_float {
|
||||
($ty:ty) => {
|
||||
impl Round for $ty {
|
||||
|
@ -92,5 +115,14 @@ macro_rules! num_float {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
num_int!(i16);
|
||||
num_int!(u16);
|
||||
num_int!(i32);
|
||||
num_int!(u32);
|
||||
num_int!(i64);
|
||||
num_int!(u64);
|
||||
num_int!(isize);
|
||||
num_int!(usize);
|
||||
num_float!(f32);
|
||||
num_float!(f64);
|
||||
|
|
|
@ -78,6 +78,21 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary")]
|
||||
impl<'a, T, U> arbitrary::Arbitrary<'a> for Point2D<T, U>
|
||||
where
|
||||
T: arbitrary::Arbitrary<'a>,
|
||||
{
|
||||
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self>
|
||||
{
|
||||
let (x, y) = arbitrary::Arbitrary::arbitrary(u)?;
|
||||
Ok(Point2D {
|
||||
x,
|
||||
y,
|
||||
_unit: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl<T, U> Eq for Point2D<T, U> where T: Eq {}
|
||||
|
||||
impl<T, U> PartialEq for Point2D<T, U>
|
||||
|
@ -148,6 +163,19 @@ impl<T, U> Point2D<T, U> {
|
|||
point2(x.0, y.0)
|
||||
}
|
||||
|
||||
/// Constructor setting all components to the same value.
|
||||
#[inline]
|
||||
pub fn splat(v: T) -> Self
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
Point2D {
|
||||
x: v.clone(),
|
||||
y: v,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
#[inline]
|
||||
pub fn from_untyped(p: Point2D<T, UnknownUnit>) -> Self {
|
||||
|
@ -457,6 +485,14 @@ impl<T: NumCast + Copy, U> Point2D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Float, U> Point2D<T, U> {
|
||||
/// Returns true if all members are finite.
|
||||
#[inline]
|
||||
pub fn is_finite(self) -> bool {
|
||||
self.x.is_finite() && self.y.is_finite()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Add<T, Output = T>, U> Point2D<T, U> {
|
||||
#[inline]
|
||||
pub fn add_size(self, other: &Size2D<T, U>) -> Self {
|
||||
|
@ -819,6 +855,20 @@ impl<T, U> Point3D<T, U> {
|
|||
point3(x.0, y.0, z.0)
|
||||
}
|
||||
|
||||
/// Constructor setting all components to the same value.
|
||||
#[inline]
|
||||
pub fn splat(v: T) -> Self
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
Point3D {
|
||||
x: v.clone(),
|
||||
y: v.clone(),
|
||||
z: v,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
#[inline]
|
||||
pub fn from_untyped(p: Point3D<T, UnknownUnit>) -> Self {
|
||||
|
@ -1155,6 +1205,14 @@ impl<T: NumCast + Copy, U> Point3D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Float, U> Point3D<T, U> {
|
||||
/// Returns true if all members are finite.
|
||||
#[inline]
|
||||
pub fn is_finite(self) -> bool {
|
||||
self.x.is_finite() && self.y.is_finite() && self.z.is_finite()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Add<T, Output = T>, U> Point3D<T, U> {
|
||||
#[inline]
|
||||
pub fn add_size(self, other: Size3D<T, U>) -> Self {
|
||||
|
|
|
@ -16,7 +16,7 @@ use crate::side_offsets::SideOffsets2D;
|
|||
use crate::size::Size2D;
|
||||
use crate::vector::Vector2D;
|
||||
|
||||
use num_traits::NumCast;
|
||||
use num_traits::{NumCast, Float};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
@ -32,7 +32,7 @@ use core::ops::{Add, Div, DivAssign, Mul, MulAssign, Range, Sub};
|
|||
///
|
||||
/// `Rect` is represented by an origin point and a size.
|
||||
///
|
||||
/// See [`Rect`] for a rectangle represented by two endpoints.
|
||||
/// See [`Box2D`] for a rectangle represented by two endpoints.
|
||||
///
|
||||
/// # Empty rectangle
|
||||
///
|
||||
|
@ -54,6 +54,21 @@ pub struct Rect<T, U> {
|
|||
pub size: Size2D<T, U>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary")]
|
||||
impl<'a, T, U> arbitrary::Arbitrary<'a> for Rect<T, U>
|
||||
where
|
||||
T: arbitrary::Arbitrary<'a>,
|
||||
{
|
||||
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self>
|
||||
{
|
||||
let (origin, size) = arbitrary::Arbitrary::arbitrary(u)?;
|
||||
Ok(Rect {
|
||||
origin,
|
||||
size,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Hash, U> Hash for Rect<T, U> {
|
||||
fn hash<H: Hasher>(&self, h: &mut H) {
|
||||
self.origin.hash(h);
|
||||
|
@ -353,13 +368,6 @@ where
|
|||
{
|
||||
#[inline]
|
||||
pub fn union(&self, other: &Self) -> Self {
|
||||
if self.size == Zero::zero() {
|
||||
return *other;
|
||||
}
|
||||
if other.size == Zero::zero() {
|
||||
return *self;
|
||||
}
|
||||
|
||||
self.to_box2d().union(&other.to_box2d()).to_rect()
|
||||
}
|
||||
}
|
||||
|
@ -579,6 +587,14 @@ impl<T: NumCast + Copy, U> Rect<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Float, U> Rect<T, U> {
|
||||
/// Returns true if all members are finite.
|
||||
#[inline]
|
||||
pub fn is_finite(self) -> bool {
|
||||
self.origin.is_finite() && self.size.is_finite()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Floor + Ceil + Round + Add<T, Output = T> + Sub<T, Output = T>, U> Rect<T, U> {
|
||||
/// Return a rectangle with edges rounded to integer coordinates, such that
|
||||
/// the returned rectangle has the same set of pixel centers as the original
|
||||
|
|
|
@ -39,6 +39,24 @@ pub struct SideOffsets2D<T, U> {
|
|||
pub _unit: PhantomData<U>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary")]
|
||||
impl<'a, T, U> arbitrary::Arbitrary<'a> for SideOffsets2D<T, U>
|
||||
where
|
||||
T: arbitrary::Arbitrary<'a>,
|
||||
{
|
||||
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self>
|
||||
{
|
||||
let (top, right, bottom, left) = arbitrary::Arbitrary::arbitrary(u)?;
|
||||
Ok(SideOffsets2D {
|
||||
top,
|
||||
right,
|
||||
bottom,
|
||||
left,
|
||||
_unit: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Copy for SideOffsets2D<T, U> {}
|
||||
|
||||
impl<T: Clone, U> Clone for SideOffsets2D<T, U> {
|
||||
|
|
|
@ -20,9 +20,10 @@ use mint;
|
|||
use core::cmp::{Eq, PartialEq};
|
||||
use core::fmt;
|
||||
use core::hash::Hash;
|
||||
use core::iter::Sum;
|
||||
use core::marker::PhantomData;
|
||||
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||
use num_traits::{NumCast, Signed};
|
||||
use num_traits::{NumCast, Signed, Float};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde;
|
||||
|
||||
|
@ -82,6 +83,22 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary")]
|
||||
impl<'a, T, U> arbitrary::Arbitrary<'a> for Size2D<T, U>
|
||||
where
|
||||
T: arbitrary::Arbitrary<'a>,
|
||||
{
|
||||
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self>
|
||||
{
|
||||
let (width, height) = arbitrary::Arbitrary::arbitrary(u)?;
|
||||
Ok(Size2D {
|
||||
width,
|
||||
height,
|
||||
_unit: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Eq for Size2D<T, U> where T: Eq {}
|
||||
|
||||
impl<T, U> PartialEq for Size2D<T, U>
|
||||
|
@ -144,6 +161,19 @@ impl<T, U> Size2D<T, U> {
|
|||
Size2D::new(width.0, height.0)
|
||||
}
|
||||
|
||||
/// Constructor setting all components to the same value.
|
||||
#[inline]
|
||||
pub fn splat(v: T) -> Self
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
Size2D {
|
||||
width: v.clone(),
|
||||
height: v,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
#[inline]
|
||||
pub fn from_untyped(p: Size2D<T, UnknownUnit>) -> Self {
|
||||
|
@ -362,6 +392,14 @@ impl<T: NumCast + Copy, U> Size2D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Float, U> Size2D<T, U> {
|
||||
/// Returns true if all members are finite.
|
||||
#[inline]
|
||||
pub fn is_finite(self) -> bool {
|
||||
self.width.is_finite() && self.height.is_finite()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Signed, U> Size2D<T, U> {
|
||||
/// Computes the absolute value of each component.
|
||||
///
|
||||
|
@ -403,6 +441,12 @@ impl<T: PartialOrd, U> Size2D<T, U> {
|
|||
self.max(start).min(end)
|
||||
}
|
||||
|
||||
// Returns true if this size is larger or equal to the other size in all dimensions.
|
||||
#[inline]
|
||||
pub fn contains(self, other: Self) -> bool {
|
||||
self.width >= other.width && self.height >= other.height
|
||||
}
|
||||
|
||||
/// Returns vector with results of "greater then" operation on each component.
|
||||
pub fn greater_than(self, other: Self) -> BoolVector2D {
|
||||
BoolVector2D {
|
||||
|
@ -498,6 +542,25 @@ impl<T: Add, U> Add for Size2D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Add<T, Output = T>, U> Add<&Self> for Size2D<T, U> {
|
||||
type Output = Self;
|
||||
fn add(self, other: &Self) -> Self {
|
||||
Size2D::new(self.width + other.width, self.height + other.height)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Add<Output = T> + Zero, U> Sum for Size2D<T, U> {
|
||||
fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::zero(), Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: 'a + Add<Output = T> + Copy + Zero, U: 'a> Sum<&'a Self> for Size2D<T, U> {
|
||||
fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::zero(), Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AddAssign, U> AddAssign for Size2D<T, U> {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
|
@ -696,18 +759,22 @@ mod size2d {
|
|||
let s1 = Size2D::new(1.0, 2.0);
|
||||
let s2 = Size2D::new(3.0, 4.0);
|
||||
assert_eq!(s1 + s2, Size2D::new(4.0, 6.0));
|
||||
assert_eq!(s1 + &s2, Size2D::new(4.0, 6.0));
|
||||
|
||||
let s1 = Size2D::new(1.0, 2.0);
|
||||
let s2 = Size2D::new(0.0, 0.0);
|
||||
assert_eq!(s1 + s2, Size2D::new(1.0, 2.0));
|
||||
assert_eq!(s1 + &s2, Size2D::new(1.0, 2.0));
|
||||
|
||||
let s1 = Size2D::new(1.0, 2.0);
|
||||
let s2 = Size2D::new(-3.0, -4.0);
|
||||
assert_eq!(s1 + s2, Size2D::new(-2.0, -2.0));
|
||||
assert_eq!(s1 + &s2, Size2D::new(-2.0, -2.0));
|
||||
|
||||
let s1 = Size2D::new(0.0, 0.0);
|
||||
let s2 = Size2D::new(0.0, 0.0);
|
||||
assert_eq!(s1 + s2, Size2D::new(0.0, 0.0));
|
||||
assert_eq!(s1 + &s2, Size2D::new(0.0, 0.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -729,6 +796,17 @@ mod size2d {
|
|||
assert_eq!(s, Size2D::new(0.0, 0.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_sum() {
|
||||
let sizes = [
|
||||
Size2D::new(0.0, 1.0),
|
||||
Size2D::new(1.0, 2.0),
|
||||
Size2D::new(2.0, 3.0)
|
||||
];
|
||||
let sum = Size2D::new(3.0, 6.0);
|
||||
assert_eq!(sizes.iter().sum::<Size2D<_>>(), sum);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_sub() {
|
||||
let s1 = Size2D::new(1.0, 2.0);
|
||||
|
@ -970,13 +1048,26 @@ impl<T, U> Size3D<T, U> {
|
|||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructor taking scalar strongly typed lengths.
|
||||
#[inline]
|
||||
pub fn from_lengths(width: Length<T, U>, height: Length<T, U>, depth: Length<T, U>) -> Self {
|
||||
Size3D::new(width.0, height.0, depth.0)
|
||||
}
|
||||
|
||||
/// Constructor setting all components to the same value.
|
||||
#[inline]
|
||||
pub fn splat(v: T) -> Self
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
Size3D {
|
||||
width: v.clone(),
|
||||
height: v.clone(),
|
||||
depth: v,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
#[inline]
|
||||
pub fn from_untyped(p: Size3D<T, UnknownUnit>) -> Self {
|
||||
|
@ -1189,6 +1280,14 @@ impl<T: NumCast + Copy, U> Size3D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Float, U> Size3D<T, U> {
|
||||
/// Returns true if all members are finite.
|
||||
#[inline]
|
||||
pub fn is_finite(self) -> bool {
|
||||
self.width.is_finite() && self.height.is_finite() && self.depth.is_finite()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Signed, U> Size3D<T, U> {
|
||||
/// Computes the absolute value of each component.
|
||||
///
|
||||
|
@ -1238,6 +1337,13 @@ impl<T: PartialOrd, U> Size3D<T, U> {
|
|||
self.max(start).min(end)
|
||||
}
|
||||
|
||||
// Returns true if this size is larger or equal to the other size in all dimensions.
|
||||
#[inline]
|
||||
pub fn contains(self, other: Self) -> bool {
|
||||
self.width >= other.width && self.height >= other.height && self.depth >= other.depth
|
||||
}
|
||||
|
||||
|
||||
/// Returns vector with results of "greater than" operation on each component.
|
||||
pub fn greater_than(self, other: Self) -> BoolVector3D {
|
||||
BoolVector3D {
|
||||
|
@ -1339,6 +1445,29 @@ impl<T: Add, U> Add for Size3D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Add<T, Output = T>, U> Add<&Self> for Size3D<T, U> {
|
||||
type Output = Self;
|
||||
fn add(self, other: &Self) -> Self {
|
||||
Size3D::new(
|
||||
self.width + other.width,
|
||||
self.height + other.height,
|
||||
self.depth + other.depth,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Add<Output = T> + Zero, U> Sum for Size3D<T, U> {
|
||||
fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::zero(), Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: 'a + Add<Output = T> + Copy + Zero, U: 'a> Sum<&'a Self> for Size3D<T, U> {
|
||||
fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::zero(), Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AddAssign, U> AddAssign for Size3D<T, U> {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
|
@ -1538,18 +1667,33 @@ mod size3d {
|
|||
let s1 = Size3D::new(1.0, 2.0, 3.0);
|
||||
let s2 = Size3D::new(4.0, 5.0, 6.0);
|
||||
assert_eq!(s1 + s2, Size3D::new(5.0, 7.0, 9.0));
|
||||
assert_eq!(s1 + &s2, Size3D::new(5.0, 7.0, 9.0));
|
||||
|
||||
let s1 = Size3D::new(1.0, 2.0, 3.0);
|
||||
let s2 = Size3D::new(0.0, 0.0, 0.0);
|
||||
assert_eq!(s1 + s2, Size3D::new(1.0, 2.0, 3.0));
|
||||
assert_eq!(s1 + &s2, Size3D::new(1.0, 2.0, 3.0));
|
||||
|
||||
let s1 = Size3D::new(1.0, 2.0, 3.0);
|
||||
let s2 = Size3D::new(-4.0, -5.0, -6.0);
|
||||
assert_eq!(s1 + s2, Size3D::new(-3.0, -3.0, -3.0));
|
||||
assert_eq!(s1 + &s2, Size3D::new(-3.0, -3.0, -3.0));
|
||||
|
||||
let s1 = Size3D::new(0.0, 0.0, 0.0);
|
||||
let s2 = Size3D::new(0.0, 0.0, 0.0);
|
||||
assert_eq!(s1 + s2, Size3D::new(0.0, 0.0, 0.0));
|
||||
assert_eq!(s1 + &s2, Size3D::new(0.0, 0.0, 0.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_sum() {
|
||||
let sizes = [
|
||||
Size3D::new(0.0, 1.0, 2.0),
|
||||
Size3D::new(1.0, 2.0, 3.0),
|
||||
Size3D::new(2.0, 3.0, 4.0)
|
||||
];
|
||||
let sum = Size3D::new(3.0, 6.0, 9.0);
|
||||
assert_eq!(sizes.iter().sum::<Size3D<_>>(), sum);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -69,6 +69,21 @@ pub struct Transform2D<T, Src, Dst> {
|
|||
pub _unit: PhantomData<(Src, Dst)>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary")]
|
||||
impl<'a, T, Src, Dst> arbitrary::Arbitrary<'a> for Transform2D<T, Src, Dst>
|
||||
where
|
||||
T: arbitrary::Arbitrary<'a>,
|
||||
{
|
||||
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self>
|
||||
{
|
||||
let (m11, m12, m21, m22, m31, m32) = arbitrary::Arbitrary::arbitrary(u)?;
|
||||
Ok(Transform2D {
|
||||
m11, m12, m21, m22, m31, m32,
|
||||
_unit: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, Src, Dst> Copy for Transform2D<T, Src, Dst> {}
|
||||
|
||||
impl<T: Clone, Src, Dst> Clone for Transform2D<T, Src, Dst> {
|
||||
|
|
|
@ -70,6 +70,41 @@ pub struct Transform3D<T, Src, Dst> {
|
|||
pub _unit: PhantomData<(Src, Dst)>,
|
||||
}
|
||||
|
||||
|
||||
#[cfg(feature = "arbitrary")]
|
||||
impl<'a, T, Src, Dst> arbitrary::Arbitrary<'a> for Transform3D<T, Src, Dst>
|
||||
where
|
||||
T: arbitrary::Arbitrary<'a>,
|
||||
{
|
||||
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self>
|
||||
{
|
||||
let (m11, m12, m13, m14) = arbitrary::Arbitrary::arbitrary(u)?;
|
||||
let (m21, m22, m23, m24) = arbitrary::Arbitrary::arbitrary(u)?;
|
||||
let (m31, m32, m33, m34) = arbitrary::Arbitrary::arbitrary(u)?;
|
||||
let (m41, m42, m43, m44) = arbitrary::Arbitrary::arbitrary(u)?;
|
||||
|
||||
Ok(Transform3D {
|
||||
m11,
|
||||
m12,
|
||||
m13,
|
||||
m14,
|
||||
m21,
|
||||
m22,
|
||||
m23,
|
||||
m24,
|
||||
m31,
|
||||
m32,
|
||||
m33,
|
||||
m34,
|
||||
m41,
|
||||
m42,
|
||||
m43,
|
||||
m44,
|
||||
_unit: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, Src, Dst> Copy for Transform3D<T, Src, Dst> {}
|
||||
|
||||
impl<T: Clone, Src, Dst> Clone for Transform3D<T, Src, Dst> {
|
||||
|
@ -425,7 +460,7 @@ where
|
|||
)
|
||||
}
|
||||
|
||||
/// Create a simple perspective projection transform:
|
||||
/// Create a simple perspective transform, projecting to the plane `z = -d`.
|
||||
///
|
||||
/// ```text
|
||||
/// 1 0 0 0
|
||||
|
@ -433,6 +468,8 @@ where
|
|||
/// 0 0 1 -1/d
|
||||
/// 0 0 0 1
|
||||
/// ```
|
||||
///
|
||||
/// See <https://drafts.csswg.org/css-transforms-2/#PerspectiveDefined>.
|
||||
pub fn perspective(d: T) -> Self
|
||||
where
|
||||
T: Neg<Output = T> + Div<Output = T>,
|
||||
|
|
|
@ -55,6 +55,22 @@ pub struct Translation2D<T, Src, Dst> {
|
|||
pub _unit: PhantomData<(Src, Dst)>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary")]
|
||||
impl<'a, T, Src, Dst> arbitrary::Arbitrary<'a> for Translation2D<T, Src, Dst>
|
||||
where
|
||||
T: arbitrary::Arbitrary<'a>,
|
||||
{
|
||||
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self>
|
||||
{
|
||||
let (x, y) = arbitrary::Arbitrary::arbitrary(u)?;
|
||||
Ok(Translation2D {
|
||||
x,
|
||||
y,
|
||||
_unit: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, Src, Dst> Copy for Translation2D<T, Src, Dst> {}
|
||||
|
||||
impl<T: Clone, Src, Dst> Clone for Translation2D<T, Src, Dst> {
|
||||
|
@ -98,6 +114,18 @@ impl<T, Src, Dst> Translation2D<T, Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn splat(v: T) -> Self
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
Translation2D {
|
||||
x: v.clone(),
|
||||
y: v,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates no-op translation (both `x` and `y` is `zero()`).
|
||||
#[inline]
|
||||
pub fn identity() -> Self
|
||||
|
@ -381,6 +409,19 @@ impl<T, Src, Dst> Translation3D<T, Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn splat(v: T) -> Self
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
Translation3D {
|
||||
x: v.clone(),
|
||||
y: v.clone(),
|
||||
z: v,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates no-op translation (`x`, `y` and `z` is `zero()`).
|
||||
#[inline]
|
||||
pub fn identity() -> Self
|
||||
|
|
|
@ -22,6 +22,7 @@ use crate::Angle;
|
|||
use core::cmp::{Eq, PartialEq};
|
||||
use core::fmt;
|
||||
use core::hash::Hash;
|
||||
use core::iter::Sum;
|
||||
use core::marker::PhantomData;
|
||||
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
|
||||
#[cfg(feature = "mint")]
|
||||
|
@ -86,6 +87,22 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "arbitrary")]
|
||||
impl<'a, T, U> arbitrary::Arbitrary<'a> for Vector2D<T, U>
|
||||
where
|
||||
T: arbitrary::Arbitrary<'a>,
|
||||
{
|
||||
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self>
|
||||
{
|
||||
let (x, y) = arbitrary::Arbitrary::arbitrary(u)?;
|
||||
Ok(Vector2D {
|
||||
x,
|
||||
y,
|
||||
_unit: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Eq, U> Eq for Vector2D<T, U> {}
|
||||
|
||||
impl<T: PartialEq, U> PartialEq for Vector2D<T, U> {
|
||||
|
@ -131,6 +148,15 @@ impl<T, U> Vector2D<T, U> {
|
|||
Vector2D::new(Zero::zero(), Zero::zero())
|
||||
}
|
||||
|
||||
/// Constructor, setting all components to one.
|
||||
#[inline]
|
||||
pub fn one() -> Self
|
||||
where
|
||||
T: One,
|
||||
{
|
||||
Vector2D::new(One::one(), One::one())
|
||||
}
|
||||
|
||||
/// Constructor taking scalar values directly.
|
||||
#[inline]
|
||||
pub const fn new(x: T, y: T) -> Self {
|
||||
|
@ -141,6 +167,19 @@ impl<T, U> Vector2D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Constructor setting all components to the same value.
|
||||
#[inline]
|
||||
pub fn splat(v: T) -> Self
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
Vector2D {
|
||||
x: v.clone(),
|
||||
y: v,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructor taking angle and length
|
||||
pub fn from_angle_and_length(angle: Angle<T>, length: T) -> Self
|
||||
where
|
||||
|
@ -205,6 +244,24 @@ impl<T, U> Vector2D<T, U> {
|
|||
{
|
||||
self.x * other.y - self.y * other.x
|
||||
}
|
||||
|
||||
/// Returns the component-wise multiplication of the two vectors.
|
||||
#[inline]
|
||||
pub fn component_mul(self, other: Self) -> Self
|
||||
where
|
||||
T: Mul<Output = T>,
|
||||
{
|
||||
vec2(self.x * other.x, self.y * other.y)
|
||||
}
|
||||
|
||||
/// Returns the component-wise division of the two vectors.
|
||||
#[inline]
|
||||
pub fn component_div(self, other: Self) -> Self
|
||||
where
|
||||
T: Div<Output = T>,
|
||||
{
|
||||
vec2(self.x / other.x, self.y / other.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Vector2D<T, U> {
|
||||
|
@ -452,6 +509,12 @@ impl<T: Float, U> Vector2D<T, U> {
|
|||
debug_assert!(min <= max);
|
||||
self.with_min_length(min).with_max_length(max)
|
||||
}
|
||||
|
||||
/// Returns true if all members are finite.
|
||||
#[inline]
|
||||
pub fn is_finite(self) -> bool {
|
||||
self.x.is_finite() && self.y.is_finite()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Vector2D<T, U>
|
||||
|
@ -649,6 +712,27 @@ impl<T: Add, U> Add for Vector2D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Add + Copy, U> Add<&Self> for Vector2D<T, U> {
|
||||
type Output = Vector2D<T::Output, U>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, other: &Self) -> Self::Output {
|
||||
Vector2D::new(self.x + other.x, self.y + other.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Add<Output = T> + Zero, U> Sum for Vector2D<T, U> {
|
||||
fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::zero(), Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: 'a + Add<Output = T> + Copy + Zero, U: 'a> Sum<&'a Self> for Vector2D<T, U> {
|
||||
fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::zero(), Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Add<T, Output = T>, U> AddAssign for Vector2D<T, U> {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
|
@ -914,6 +998,15 @@ impl<T, U> Vector3D<T, U> {
|
|||
vec3(Zero::zero(), Zero::zero(), Zero::zero())
|
||||
}
|
||||
|
||||
/// Constructor, setting all components to one.
|
||||
#[inline]
|
||||
pub fn one() -> Self
|
||||
where
|
||||
T: One,
|
||||
{
|
||||
vec3(One::one(), One::one(), One::one())
|
||||
}
|
||||
|
||||
/// Constructor taking scalar values directly.
|
||||
#[inline]
|
||||
pub const fn new(x: T, y: T, z: T) -> Self {
|
||||
|
@ -924,6 +1017,19 @@ impl<T, U> Vector3D<T, U> {
|
|||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
/// Constructor setting all components to the same value.
|
||||
#[inline]
|
||||
pub fn splat(v: T) -> Self
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
Vector3D {
|
||||
x: v.clone(),
|
||||
y: v.clone(),
|
||||
z: v,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructor taking properly Lengths instead of scalar values.
|
||||
#[inline]
|
||||
|
@ -989,6 +1095,24 @@ impl<T: Copy, U> Vector3D<T, U> {
|
|||
)
|
||||
}
|
||||
|
||||
/// Returns the component-wise multiplication of the two vectors.
|
||||
#[inline]
|
||||
pub fn component_mul(self, other: Self) -> Self
|
||||
where
|
||||
T: Mul<Output = T>,
|
||||
{
|
||||
vec3(self.x * other.x, self.y * other.y, self.z * other.z)
|
||||
}
|
||||
|
||||
/// Returns the component-wise division of the two vectors.
|
||||
#[inline]
|
||||
pub fn component_div(self, other: Self) -> Self
|
||||
where
|
||||
T: Div<Output = T>,
|
||||
{
|
||||
vec3(self.x / other.x, self.y / other.y, self.z / other.z)
|
||||
}
|
||||
|
||||
/// Cast this vector into a point.
|
||||
///
|
||||
/// Equivalent to adding this vector to the origin.
|
||||
|
@ -1235,6 +1359,12 @@ impl<T: Float, U> Vector3D<T, U> {
|
|||
debug_assert!(min <= max);
|
||||
self.with_min_length(min).with_max_length(max)
|
||||
}
|
||||
|
||||
/// Returns true if all members are finite.
|
||||
#[inline]
|
||||
pub fn is_finite(self) -> bool {
|
||||
self.x.is_finite() && self.y.is_finite() && self.z.is_finite()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Vector3D<T, U>
|
||||
|
@ -1448,6 +1578,27 @@ impl<T: Add, U> Add for Vector3D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: 'a + Add + Copy, U: 'a> Add<&Self> for Vector3D<T, U> {
|
||||
type Output = Vector3D<T::Output, U>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, other: &Self) -> Self::Output {
|
||||
vec3(self.x + other.x, self.y + other.y, self.z + other.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Add<Output = T> + Zero, U> Sum for Vector3D<T, U> {
|
||||
fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::zero(), Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: 'a + Add<Output = T> + Copy + Zero, U: 'a> Sum<&'a Self> for Vector3D<T, U> {
|
||||
fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
|
||||
iter.fold(Self::zero(), Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Add<T, Output = T>, U> AddAssign for Vector3D<T, U> {
|
||||
#[inline]
|
||||
fn add_assign(&mut self, other: Self) {
|
||||
|
@ -1826,7 +1977,7 @@ impl BoolVector3D {
|
|||
|
||||
/// Convenience constructor.
|
||||
#[inline]
|
||||
pub fn vec2<T, U>(x: T, y: T) -> Vector2D<T, U> {
|
||||
pub const fn vec2<T, U>(x: T, y: T) -> Vector2D<T, U> {
|
||||
Vector2D {
|
||||
x,
|
||||
y,
|
||||
|
@ -1836,7 +1987,7 @@ pub fn vec2<T, U>(x: T, y: T) -> Vector2D<T, U> {
|
|||
|
||||
/// Convenience constructor.
|
||||
#[inline]
|
||||
pub fn vec3<T, U>(x: T, y: T, z: T) -> Vector3D<T, U> {
|
||||
pub const fn vec3<T, U>(x: T, y: T, z: T) -> Vector3D<T, U> {
|
||||
Vector3D {
|
||||
x,
|
||||
y,
|
||||
|
@ -1847,13 +1998,13 @@ pub fn vec3<T, U>(x: T, y: T, z: T) -> Vector3D<T, U> {
|
|||
|
||||
/// Shorthand for `BoolVector2D { x, y }`.
|
||||
#[inline]
|
||||
pub fn bvec2(x: bool, y: bool) -> BoolVector2D {
|
||||
pub const fn bvec2(x: bool, y: bool) -> BoolVector2D {
|
||||
BoolVector2D { x, y }
|
||||
}
|
||||
|
||||
/// Shorthand for `BoolVector3D { x, y, z }`.
|
||||
#[inline]
|
||||
pub fn bvec3(x: bool, y: bool, z: bool) -> BoolVector3D {
|
||||
pub const fn bvec3(x: bool, y: bool, z: bool) -> BoolVector3D {
|
||||
BoolVector3D { x, y, z }
|
||||
}
|
||||
|
||||
|
@ -2043,9 +2194,19 @@ mod vector2d {
|
|||
let p1 = Vector2DMm::new(1.0, 2.0);
|
||||
let p2 = Vector2DMm::new(3.0, 4.0);
|
||||
|
||||
let result = p1 + p2;
|
||||
assert_eq!(p1 + p2, vec2(4.0, 6.0));
|
||||
assert_eq!(p1 + &p2, vec2(4.0, 6.0));
|
||||
}
|
||||
|
||||
assert_eq!(result, vec2(4.0, 6.0));
|
||||
#[test]
|
||||
pub fn test_sum() {
|
||||
let vecs = [
|
||||
Vector2DMm::new(1.0, 2.0),
|
||||
Vector2DMm::new(3.0, 4.0),
|
||||
Vector2DMm::new(5.0, 6.0)
|
||||
];
|
||||
let sum = Vector2DMm::new(9.0, 12.0);
|
||||
assert_eq!(vecs.iter().sum::<Vector2DMm<_>>(), sum);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -2093,6 +2254,26 @@ mod vector3d {
|
|||
|
||||
type Vec3 = default::Vector3D<f32>;
|
||||
|
||||
#[test]
|
||||
pub fn test_add() {
|
||||
let p1 = Vec3::new(1.0, 2.0, 3.0);
|
||||
let p2 = Vec3::new(4.0, 5.0, 6.0);
|
||||
|
||||
assert_eq!(p1 + p2, vec3(5.0, 7.0, 9.0));
|
||||
assert_eq!(p1 + &p2, vec3(5.0, 7.0, 9.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_sum() {
|
||||
let vecs = [
|
||||
Vec3::new(1.0, 2.0, 3.0),
|
||||
Vec3::new(4.0, 5.0, 6.0),
|
||||
Vec3::new(7.0, 8.0, 9.0)
|
||||
];
|
||||
let sum = Vec3::new(12.0, 15.0, 18.0);
|
||||
assert_eq!(vecs.iter().sum::<Vec3>(), sum);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_dot() {
|
||||
let p1: Vec3 = vec3(7.0, 21.0, 32.0);
|
||||
|
|
Загрузка…
Ссылка в новой задаче