1 // Copyright 2013 The Servo Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution.
3 //
4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7 // option. This file may not be copied, modified, or distributed
8 // except according to those terms.
9
10 use super::UnknownUnit;
11 use approxord::{max, min};
12 #[cfg(feature = "mint")]
13 use mint;
14 use length::Length;
15 use scale::Scale;
16 use vector::{Vector2D, vec2, BoolVector2D};
17 use vector::{Vector3D, vec3, BoolVector3D};
18 use num::*;
19
20 use num_traits::{NumCast, Signed};
21 use core::fmt;
22 use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
23 use core::marker::PhantomData;
24 use core::cmp::{Eq, PartialEq};
25 use core::hash::{Hash};
26 #[cfg(feature = "serde")]
27 use serde;
28
29 /// A 2d size tagged with a unit.
30 #[repr(C)]
31 pub struct Size2D<T, U> {
32 /// The extent of the element in the `U` units along the `x` axis (usually horizontal).
33 pub width: T,
34 /// The extent of the element in the `U` units along the `y` axis (usually vertical).
35 pub height: T,
36 #[doc(hidden)]
37 pub _unit: PhantomData<U>,
38 }
39
40 impl<T: Copy, U> Copy for Size2D<T, U> {}
41
42 impl<T: Clone, U> Clone for Size2D<T, U> {
clone(&self) -> Self43 fn clone(&self) -> Self {
44 Size2D {
45 width: self.width.clone(),
46 height: self.height.clone(),
47 _unit: PhantomData,
48 }
49 }
50 }
51
52 #[cfg(feature = "serde")]
53 impl<'de, T, U> serde::Deserialize<'de> for Size2D<T, U>
54 where T: serde::Deserialize<'de>
55 {
56 /// Deserializes 2d size from tuple of width and height.
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de>57 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
58 where D: serde::Deserializer<'de>
59 {
60 let (width, height) = serde::Deserialize::deserialize(deserializer)?;
61 Ok(Size2D { width, height, _unit: PhantomData })
62 }
63 }
64
65 #[cfg(feature = "serde")]
66 impl<T, U> serde::Serialize for Size2D<T, U>
67 where T: serde::Serialize
68 {
69 /// Serializes 2d size to tuple of width and height.
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer70 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
71 where S: serde::Serializer
72 {
73 (&self.width, &self.height).serialize(serializer)
74 }
75 }
76
77 impl<T, U> Eq for Size2D<T, U> where T: Eq {}
78
79 impl<T, U> PartialEq for Size2D<T, U>
80 where T: PartialEq
81 {
eq(&self, other: &Self) -> bool82 fn eq(&self, other: &Self) -> bool {
83 self.width == other.width && self.height == other.height
84 }
85 }
86
87 impl<T, U> Hash for Size2D<T, U>
88 where T: Hash
89 {
hash<H: ::core::hash::Hasher>(&self, h: &mut H)90 fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
91 self.width.hash(h);
92 self.height.hash(h);
93 }
94 }
95
96 impl<T: fmt::Debug, U> fmt::Debug for Size2D<T, U> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result97 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
98 fmt::Debug::fmt(&self.width, f)?;
99 write!(f, "x")?;
100 fmt::Debug::fmt(&self.height, f)
101 }
102 }
103
104 impl<T: fmt::Display, U> fmt::Display for Size2D<T, U> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result105 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
106 write!(f, "(")?;
107 fmt::Display::fmt(&self.width, f)?;
108 write!(f, "x")?;
109 fmt::Display::fmt(&self.height, f)?;
110 write!(f, ")")
111 }
112 }
113
114 impl<T: Default, U> Default for Size2D<T, U> {
default() -> Self115 fn default() -> Self {
116 Size2D::new(Default::default(), Default::default())
117 }
118 }
119
120
121 impl<T, U> Size2D<T, U> {
122 /// The same as [`Zero::zero()`] but available without importing trait.
123 ///
124 /// [`Zero::zero()`]: ./num/trait.Zero.html#tymethod.zero
125 #[inline]
zero() -> Self where T: Zero,126 pub fn zero() -> Self
127 where
128 T: Zero,
129 {
130 Size2D::new(Zero::zero(), Zero::zero())
131 }
132
133 /// Constructor taking scalar values.
134 #[inline]
new(width: T, height: T) -> Self135 pub const fn new(width: T, height: T) -> Self {
136 Size2D {
137 width,
138 height,
139 _unit: PhantomData,
140 }
141 }
142 /// Constructor taking scalar strongly typed lengths.
143 #[inline]
from_lengths(width: Length<T, U>, height: Length<T, U>) -> Self144 pub fn from_lengths(width: Length<T, U>, height: Length<T, U>) -> Self {
145 Size2D::new(width.0, height.0)
146 }
147
148 /// Tag a unitless value with units.
149 #[inline]
from_untyped(p: Size2D<T, UnknownUnit>) -> Self150 pub fn from_untyped(p: Size2D<T, UnknownUnit>) -> Self {
151 Size2D::new(p.width, p.height)
152 }
153 }
154
155 impl<T: Copy, U> Size2D<T, U> {
156 /// Return this size as an array of two elements (width, then height).
157 #[inline]
to_array(&self) -> [T; 2]158 pub fn to_array(&self) -> [T; 2] {
159 [self.width, self.height]
160 }
161
162 /// Return this size as a tuple of two elements (width, then height).
163 #[inline]
to_tuple(&self) -> (T, T)164 pub fn to_tuple(&self) -> (T, T) {
165 (self.width, self.height)
166 }
167
168 /// Return this size as a vector with width and height.
169 #[inline]
to_vector(&self) -> Vector2D<T, U>170 pub fn to_vector(&self) -> Vector2D<T, U> {
171 vec2(self.width, self.height)
172 }
173
174 /// Drop the units, preserving only the numeric value.
175 #[inline]
to_untyped(&self) -> Size2D<T, UnknownUnit>176 pub fn to_untyped(&self) -> Size2D<T, UnknownUnit> {
177 self.cast_unit()
178 }
179
180 /// Cast the unit
181 #[inline]
cast_unit<V>(&self) -> Size2D<T, V>182 pub fn cast_unit<V>(&self) -> Size2D<T, V> {
183 Size2D::new(self.width, self.height)
184 }
185
186 /// Rounds each component to the nearest integer value.
187 ///
188 /// This behavior is preserved for negative values (unlike the basic cast).
189 ///
190 /// ```rust
191 /// # use euclid::size2;
192 /// enum Mm {}
193 ///
194 /// assert_eq!(size2::<_, Mm>(-0.1, -0.8).round(), size2::<_, Mm>(0.0, -1.0))
195 /// ```
196 #[inline]
197 #[must_use]
round(&self) -> Self where T: Round,198 pub fn round(&self) -> Self
199 where
200 T: Round,
201 {
202 Size2D::new(self.width.round(), self.height.round())
203 }
204
205 /// Rounds each component to the smallest integer equal or greater than the original value.
206 ///
207 /// This behavior is preserved for negative values (unlike the basic cast).
208 ///
209 /// ```rust
210 /// # use euclid::size2;
211 /// enum Mm {}
212 ///
213 /// assert_eq!(size2::<_, Mm>(-0.1, -0.8).ceil(), size2::<_, Mm>(0.0, 0.0))
214 /// ```
215 #[inline]
216 #[must_use]
ceil(&self) -> Self where T: Ceil,217 pub fn ceil(&self) -> Self
218 where
219 T: Ceil,
220 {
221 Size2D::new(self.width.ceil(), self.height.ceil())
222 }
223
224 /// Rounds each component to the biggest integer equal or lower than the original value.
225 ///
226 /// This behavior is preserved for negative values (unlike the basic cast).
227 ///
228 /// ```rust
229 /// # use euclid::size2;
230 /// enum Mm {}
231 ///
232 /// assert_eq!(size2::<_, Mm>(-0.1, -0.8).floor(), size2::<_, Mm>(-1.0, -1.0))
233 /// ```
234 #[inline]
235 #[must_use]
floor(&self) -> Self where T: Floor,236 pub fn floor(&self) -> Self
237 where
238 T: Floor,
239 {
240 Size2D::new(self.width.floor(), self.height.floor())
241 }
242
243 /// Returns result of multiplication of both components
area(&self) -> T::Output where T: Mul,244 pub fn area(&self) -> T::Output
245 where
246 T: Mul,
247 {
248 self.width * self.height
249 }
250
251 /// Linearly interpolate each component between this size and another size.
252 ///
253 /// # Example
254 ///
255 /// ```rust
256 /// use euclid::size2;
257 /// use euclid::default::Size2D;
258 ///
259 /// let from: Size2D<_> = size2(0.0, 10.0);
260 /// let to: Size2D<_> = size2(8.0, -4.0);
261 ///
262 /// assert_eq!(from.lerp(to, -1.0), size2(-8.0, 24.0));
263 /// assert_eq!(from.lerp(to, 0.0), size2( 0.0, 10.0));
264 /// assert_eq!(from.lerp(to, 0.5), size2( 4.0, 3.0));
265 /// assert_eq!(from.lerp(to, 1.0), size2( 8.0, -4.0));
266 /// assert_eq!(from.lerp(to, 2.0), size2(16.0, -18.0));
267 /// ```
268 #[inline]
lerp(&self, other: Self, t: T) -> Self where T: One + Sub<Output = T> + Mul<Output = T> + Add<Output = T>,269 pub fn lerp(&self, other: Self, t: T) -> Self
270 where
271 T: One + Sub<Output = T> + Mul<Output = T> + Add<Output = T>,
272 {
273 let one_t = T::one() - t;
274 (*self) * one_t + other * t
275 }
276 }
277
278 impl<T: NumCast + Copy, U> Size2D<T, U> {
279 /// Cast from one numeric representation to another, preserving the units.
280 ///
281 /// When casting from floating point to integer coordinates, the decimals are truncated
282 /// as one would expect from a simple cast, but this behavior does not always make sense
283 /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
284 #[inline]
cast<NewT: NumCast>(&self) -> Size2D<NewT, U>285 pub fn cast<NewT: NumCast>(&self) -> Size2D<NewT, U> {
286 self.try_cast().unwrap()
287 }
288
289 /// Fallible cast from one numeric representation to another, preserving the units.
290 ///
291 /// When casting from floating point to integer coordinates, the decimals are truncated
292 /// as one would expect from a simple cast, but this behavior does not always make sense
293 /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
try_cast<NewT: NumCast>(&self) -> Option<Size2D<NewT, U>>294 pub fn try_cast<NewT: NumCast>(&self) -> Option<Size2D<NewT, U>> {
295 match (NumCast::from(self.width), NumCast::from(self.height)) {
296 (Some(w), Some(h)) => Some(Size2D::new(w, h)),
297 _ => None,
298 }
299 }
300
301 // Convenience functions for common casts
302
303 /// Cast into an `f32` size.
304 #[inline]
to_f32(&self) -> Size2D<f32, U>305 pub fn to_f32(&self) -> Size2D<f32, U> {
306 self.cast()
307 }
308
309 /// Cast into an `f64` size.
310 #[inline]
to_f64(&self) -> Size2D<f64, U>311 pub fn to_f64(&self) -> Size2D<f64, U> {
312 self.cast()
313 }
314
315 /// Cast into an `uint` size, truncating decimals if any.
316 ///
317 /// When casting from floating point sizes, it is worth considering whether
318 /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
319 /// the desired conversion behavior.
320 #[inline]
to_usize(&self) -> Size2D<usize, U>321 pub fn to_usize(&self) -> Size2D<usize, U> {
322 self.cast()
323 }
324
325 /// Cast into an `u32` size, truncating decimals if any.
326 ///
327 /// When casting from floating point sizes, it is worth considering whether
328 /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
329 /// the desired conversion behavior.
330 #[inline]
to_u32(&self) -> Size2D<u32, U>331 pub fn to_u32(&self) -> Size2D<u32, U> {
332 self.cast()
333 }
334
335 /// Cast into an `u64` size, truncating decimals if any.
336 ///
337 /// When casting from floating point sizes, it is worth considering whether
338 /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
339 /// the desired conversion behavior.
340 #[inline]
to_u64(&self) -> Size2D<u64, U>341 pub fn to_u64(&self) -> Size2D<u64, U> {
342 self.cast()
343 }
344
345 /// Cast into an `i32` size, truncating decimals if any.
346 ///
347 /// When casting from floating point sizes, it is worth considering whether
348 /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
349 /// the desired conversion behavior.
350 #[inline]
to_i32(&self) -> Size2D<i32, U>351 pub fn to_i32(&self) -> Size2D<i32, U> {
352 self.cast()
353 }
354
355 /// Cast into an `i64` size, truncating decimals if any.
356 ///
357 /// When casting from floating point sizes, it is worth considering whether
358 /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
359 /// the desired conversion behavior.
360 #[inline]
to_i64(&self) -> Size2D<i64, U>361 pub fn to_i64(&self) -> Size2D<i64, U> {
362 self.cast()
363 }
364 }
365
366 impl<T: Signed, U> Size2D<T, U> {
367 /// Computes the absolute value of each component.
368 ///
369 /// For `f32` and `f64`, `NaN` will be returned for component if the component is `NaN`.
370 ///
371 /// For signed integers, `::MIN` will be returned for component if the component is `::MIN`.
abs(&self) -> Self372 pub fn abs(&self) -> Self {
373 size2(self.width.abs(), self.height.abs())
374 }
375
376 /// Returns `true` if both components is positive and `false` any component is zero or negative.
is_positive(&self) -> bool377 pub fn is_positive(&self) -> bool {
378 self.width.is_positive() && self.height.is_positive()
379 }
380 }
381
382 impl<T: PartialOrd, U> Size2D<T, U> {
383 /// Returns the size each component of which are minimum of this size and another.
384 #[inline]
min(self, other: Self) -> Self385 pub fn min(self, other: Self) -> Self {
386 size2(
387 min(self.width, other.width),
388 min(self.height, other.height),
389 )
390 }
391
392 /// Returns the size each component of which are maximum of this size and another.
393 #[inline]
max(self, other: Self) -> Self394 pub fn max(self, other: Self) -> Self {
395 size2(
396 max(self.width, other.width),
397 max(self.height, other.height),
398 )
399 }
400
401 /// Returns the size each component of which clamped by corresponding
402 /// components of `start` and `end`.
403 ///
404 /// Shortcut for `self.max(start).min(end)`.
405 #[inline]
clamp(&self, start: Self, end: Self) -> Self where T: Copy,406 pub fn clamp(&self, start: Self, end: Self) -> Self
407 where
408 T: Copy,
409 {
410 self.max(start).min(end)
411 }
412
413 /// Returns vector with results of "greater then" operation on each component.
greater_than(&self, other: Self) -> BoolVector2D414 pub fn greater_than(&self, other: Self) -> BoolVector2D {
415 BoolVector2D {
416 x: self.width > other.width,
417 y: self.height > other.height,
418 }
419 }
420
421 /// Returns vector with results of "lower then" operation on each component.
lower_than(&self, other: Self) -> BoolVector2D422 pub fn lower_than(&self, other: Self) -> BoolVector2D {
423 BoolVector2D {
424 x: self.width < other.width,
425 y: self.height < other.height,
426 }
427 }
428
429 /// Returns `true` if any component of size is zero or negative.
is_empty_or_negative(&self) -> bool where T: Zero,430 pub fn is_empty_or_negative(&self) -> bool
431 where
432 T: Zero,
433 {
434 let zero = T::zero();
435 self.width <= zero || self.height <= zero
436 }
437 }
438
439 impl<T: PartialEq, U> Size2D<T, U> {
440 /// Returns vector with results of "equal" operation on each component.
equal(&self, other: Self) -> BoolVector2D441 pub fn equal(&self, other: Self) -> BoolVector2D {
442 BoolVector2D {
443 x: self.width == other.width,
444 y: self.height == other.height,
445 }
446 }
447
448 /// Returns vector with results of "not equal" operation on each component.
not_equal(&self, other: Self) -> BoolVector2D449 pub fn not_equal(&self, other: Self) -> BoolVector2D {
450 BoolVector2D {
451 x: self.width != other.width,
452 y: self.height != other.height,
453 }
454 }
455 }
456
457
458 impl<T: Round, U> Round for Size2D<T, U> {
459 /// See [`Size2D::round()`](#method.round).
460 #[inline]
round(self) -> Self461 fn round(self) -> Self {
462 (&self).round()
463 }
464 }
465
466 impl<T: Ceil, U> Ceil for Size2D<T, U> {
467 /// See [`Size2D::ceil()`](#method.ceil).
468 #[inline]
ceil(self) -> Self469 fn ceil(self) -> Self {
470 (&self).ceil()
471 }
472 }
473
474 impl<T: Floor, U> Floor for Size2D<T, U> {
475 /// See [`Size2D::floor()`](#method.floor).
476 #[inline]
floor(self) -> Self477 fn floor(self) -> Self {
478 (&self).floor()
479 }
480 }
481
482 impl<T: Zero, U> Zero for Size2D<T, U> {
483 #[inline]
zero() -> Self484 fn zero() -> Self {
485 Size2D::new(Zero::zero(), Zero::zero())
486 }
487 }
488
489
490 impl<T: Neg, U> Neg for Size2D<T, U> {
491 type Output = Size2D<T::Output, U>;
492
493 #[inline]
neg(self) -> Self::Output494 fn neg(self) -> Self::Output {
495 Size2D::new(-self.width, -self.height)
496 }
497 }
498
499
500 impl<T: Add, U> Add for Size2D<T, U> {
501 type Output = Size2D<T::Output, U>;
502
503 #[inline]
add(self, other: Self) -> Self::Output504 fn add(self, other: Self) -> Self::Output {
505 Size2D::new(self.width + other.width, self.height + other.height)
506 }
507 }
508
509 impl<T: AddAssign, U> AddAssign for Size2D<T, U> {
510 #[inline]
add_assign(&mut self, other: Self)511 fn add_assign(&mut self, other: Self) {
512 self.width += other.width;
513 self.height += other.height;
514 }
515 }
516
517
518 impl<T: Sub, U> Sub for Size2D<T, U> {
519 type Output = Size2D<T::Output, U>;
520
521 #[inline]
sub(self, other: Self) -> Self::Output522 fn sub(self, other: Self) -> Self::Output {
523 Size2D::new(self.width - other.width, self.height - other.height)
524 }
525 }
526
527 impl<T: SubAssign, U> SubAssign for Size2D<T, U> {
528 #[inline]
sub_assign(&mut self, other: Self)529 fn sub_assign(&mut self, other: Self) {
530 self.width -= other.width;
531 self.height -= other.height;
532 }
533 }
534
535
536 impl<T: Clone + Mul, U> Mul<T> for Size2D<T, U> {
537 type Output = Size2D<T::Output, U>;
538
539 #[inline]
mul(self, scale: T) -> Self::Output540 fn mul(self, scale: T) -> Self::Output {
541 Size2D::new(self.width * scale.clone(), self.height * scale)
542 }
543 }
544
545 impl<T: Clone + MulAssign, U> MulAssign<T> for Size2D<T, U> {
546 #[inline]
mul_assign(&mut self, other: T)547 fn mul_assign(&mut self, other: T) {
548 self.width *= other.clone();
549 self.height *= other;
550 }
551 }
552
553 impl<T: Clone + Mul, U1, U2> Mul<Scale<T, U1, U2>> for Size2D<T, U1> {
554 type Output = Size2D<T::Output, U2>;
555
556 #[inline]
mul(self, scale: Scale<T, U1, U2>) -> Self::Output557 fn mul(self, scale: Scale<T, U1, U2>) -> Self::Output {
558 Size2D::new(self.width * scale.0.clone(), self.height * scale.0)
559 }
560 }
561
562 impl<T: Clone + MulAssign, U> MulAssign<Scale<T, U, U>> for Size2D<T, U> {
563 #[inline]
mul_assign(&mut self, other: Scale<T, U, U>)564 fn mul_assign(&mut self, other: Scale<T, U, U>) {
565 *self *= other.0;
566 }
567 }
568
569
570 impl<T: Clone + Div, U> Div<T> for Size2D<T, U> {
571 type Output = Size2D<T::Output, U>;
572
573 #[inline]
div(self, scale: T) -> Self::Output574 fn div(self, scale: T) -> Self::Output {
575 Size2D::new(self.width / scale.clone(), self.height / scale)
576 }
577 }
578
579 impl<T: Clone + DivAssign, U> DivAssign<T> for Size2D<T, U> {
580 #[inline]
div_assign(&mut self, other: T)581 fn div_assign(&mut self, other: T) {
582 self.width /= other.clone();
583 self.height /= other;
584 }
585 }
586
587 impl<T: Clone + Div, U1, U2> Div<Scale<T, U1, U2>> for Size2D<T, U2> {
588 type Output = Size2D<T::Output, U1>;
589
590 #[inline]
div(self, scale: Scale<T, U1, U2>) -> Self::Output591 fn div(self, scale: Scale<T, U1, U2>) -> Self::Output {
592 Size2D::new(self.width / scale.0.clone(), self.height / scale.0)
593 }
594 }
595
596 impl<T: Clone + DivAssign, U> DivAssign<Scale<T, U, U>> for Size2D<T, U> {
597 #[inline]
div_assign(&mut self, other: Scale<T, U, U>)598 fn div_assign(&mut self, other: Scale<T, U, U>) {
599 *self /= other.0;
600 }
601 }
602
603
604 /// Shorthand for `Size2D::new(w, h)`.
605 #[inline]
size2<T, U>(w: T, h: T) -> Size2D<T, U>606 pub const fn size2<T, U>(w: T, h: T) -> Size2D<T, U> {
607 Size2D::new(w, h)
608 }
609
610 #[cfg(feature = "mint")]
611 impl<T, U> From<mint::Vector2<T>> for Size2D<T, U> {
612 #[inline]
from(v: mint::Vector2<T>) -> Self613 fn from(v: mint::Vector2<T>) -> Self {
614 Size2D {
615 width: v.x,
616 height: v.y,
617 _unit: PhantomData,
618 }
619 }
620 }
621 #[cfg(feature = "mint")]
622 impl<T, U> Into<mint::Vector2<T>> for Size2D<T, U> {
623 #[inline]
into(self) -> mint::Vector2<T>624 fn into(self) -> mint::Vector2<T> {
625 mint::Vector2 {
626 x: self.width,
627 y: self.height,
628 }
629 }
630 }
631
632 impl<T, U> From<Vector2D<T, U>> for Size2D<T, U> {
633 #[inline]
from(v: Vector2D<T, U>) -> Self634 fn from(v: Vector2D<T, U>) -> Self {
635 size2(v.x, v.y)
636 }
637 }
638
639 impl<T, U> Into<[T; 2]> for Size2D<T, U> {
640 #[inline]
into(self) -> [T; 2]641 fn into(self) -> [T; 2] {
642 [self.width, self.height]
643 }
644 }
645
646 impl<T, U> From<[T; 2]> for Size2D<T, U> {
647 #[inline]
from([w, h]: [T; 2]) -> Self648 fn from([w, h]: [T; 2]) -> Self {
649 size2(w, h)
650 }
651 }
652
653 impl<T, U> Into<(T, T)> for Size2D<T, U> {
654 #[inline]
into(self) -> (T, T)655 fn into(self) -> (T, T) {
656 (self.width, self.height)
657 }
658 }
659
660 impl<T, U> From<(T, T)> for Size2D<T, U> {
661 #[inline]
from(tuple: (T, T)) -> Self662 fn from(tuple: (T, T)) -> Self {
663 size2(tuple.0, tuple.1)
664 }
665 }
666
667 #[cfg(test)]
668 mod size2d {
669 use default::Size2D;
670 #[cfg(feature = "mint")]
671 use mint;
672
673 #[test]
test_area()674 pub fn test_area() {
675 let p = Size2D::new(1.5, 2.0);
676 assert_eq!(p.area(), 3.0);
677 }
678
679 #[cfg(feature = "mint")]
680 #[test]
test_mint()681 pub fn test_mint() {
682 let s1 = Size2D::new(1.0, 2.0);
683 let sm: mint::Vector2<_> = s1.into();
684 let s2 = Size2D::from(sm);
685
686 assert_eq!(s1, s2);
687 }
688
689 mod ops {
690 use default::Size2D;
691 use scale::Scale;
692
693 pub enum Mm {}
694 pub enum Cm {}
695
696 pub type Size2DMm<T> = crate::Size2D<T, Mm>;
697 pub type Size2DCm<T> = crate::Size2D<T, Cm>;
698
699 #[test]
test_neg()700 pub fn test_neg() {
701 assert_eq!(-Size2D::new( 1.0, 2.0), Size2D::new(-1.0, -2.0));
702 assert_eq!(-Size2D::new( 0.0, 0.0), Size2D::new(-0.0, -0.0));
703 assert_eq!(-Size2D::new(-1.0, -2.0), Size2D::new( 1.0, 2.0));
704 }
705
706
707 #[test]
test_add()708 pub fn test_add() {
709 let s1 = Size2D::new(1.0, 2.0);
710 let s2 = Size2D::new(3.0, 4.0);
711 assert_eq!(s1 + s2, Size2D::new(4.0, 6.0));
712
713 let s1 = Size2D::new(1.0, 2.0);
714 let s2 = Size2D::new(0.0, 0.0);
715 assert_eq!(s1 + s2, Size2D::new(1.0, 2.0));
716
717 let s1 = Size2D::new(1.0, 2.0);
718 let s2 = Size2D::new(-3.0, -4.0);
719 assert_eq!(s1 + s2, Size2D::new(-2.0, -2.0));
720
721 let s1 = Size2D::new(0.0, 0.0);
722 let s2 = Size2D::new(0.0, 0.0);
723 assert_eq!(s1 + s2, Size2D::new(0.0, 0.0));
724 }
725
726 #[test]
test_add_assign()727 pub fn test_add_assign() {
728 let mut s = Size2D::new(1.0, 2.0);
729 s += Size2D::new(3.0, 4.0);
730 assert_eq!(s, Size2D::new(4.0, 6.0));
731
732 let mut s = Size2D::new(1.0, 2.0);
733 s += Size2D::new(0.0, 0.0);
734 assert_eq!(s, Size2D::new(1.0, 2.0));
735
736 let mut s = Size2D::new(1.0, 2.0);
737 s += Size2D::new(-3.0, -4.0);
738 assert_eq!(s, Size2D::new(-2.0, -2.0));
739
740 let mut s = Size2D::new(0.0, 0.0);
741 s += Size2D::new(0.0, 0.0);
742 assert_eq!(s, Size2D::new(0.0, 0.0));
743 }
744
745 #[test]
test_sub()746 pub fn test_sub() {
747 let s1 = Size2D::new(1.0, 2.0);
748 let s2 = Size2D::new(3.0, 4.0);
749 assert_eq!(s1 - s2, Size2D::new(-2.0, -2.0));
750
751 let s1 = Size2D::new(1.0, 2.0);
752 let s2 = Size2D::new(0.0, 0.0);
753 assert_eq!(s1 - s2, Size2D::new(1.0, 2.0));
754
755 let s1 = Size2D::new(1.0, 2.0);
756 let s2 = Size2D::new(-3.0, -4.0);
757 assert_eq!(s1 - s2, Size2D::new(4.0, 6.0));
758
759 let s1 = Size2D::new(0.0, 0.0);
760 let s2 = Size2D::new(0.0, 0.0);
761 assert_eq!(s1 - s2, Size2D::new(0.0, 0.0));
762 }
763
764 #[test]
test_sub_assign()765 pub fn test_sub_assign() {
766 let mut s = Size2D::new(1.0, 2.0);
767 s -= Size2D::new(3.0, 4.0);
768 assert_eq!(s, Size2D::new(-2.0, -2.0));
769
770 let mut s = Size2D::new(1.0, 2.0);
771 s -= Size2D::new(0.0, 0.0);
772 assert_eq!(s, Size2D::new(1.0, 2.0));
773
774 let mut s = Size2D::new(1.0, 2.0);
775 s -= Size2D::new(-3.0, -4.0);
776 assert_eq!(s, Size2D::new(4.0, 6.0));
777
778 let mut s = Size2D::new(0.0, 0.0);
779 s -= Size2D::new(0.0, 0.0);
780 assert_eq!(s, Size2D::new(0.0, 0.0));
781 }
782
783
784 #[test]
test_mul_scalar()785 pub fn test_mul_scalar() {
786 let s1: Size2D<f32> = Size2D::new(3.0, 5.0);
787
788 let result = s1 * 5.0;
789
790 assert_eq!(result, Size2D::new(15.0, 25.0));
791 }
792
793 #[test]
test_mul_assign_scalar()794 pub fn test_mul_assign_scalar() {
795 let mut s1 = Size2D::new(3.0, 5.0);
796
797 s1 *= 5.0;
798
799 assert_eq!(s1, Size2D::new(15.0, 25.0));
800 }
801
802 #[test]
test_mul_scale()803 pub fn test_mul_scale() {
804 let s1 = Size2DMm::new(1.0, 2.0);
805 let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
806
807 let result = s1 * cm_per_mm;
808
809 assert_eq!(result, Size2DCm::new(0.1, 0.2));
810 }
811
812 #[test]
test_mul_assign_scale()813 pub fn test_mul_assign_scale() {
814 let mut s1 = Size2DMm::new(1.0, 2.0);
815 let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
816
817 s1 *= scale;
818
819 assert_eq!(s1, Size2DMm::new(0.1, 0.2));
820 }
821
822
823 #[test]
test_div_scalar()824 pub fn test_div_scalar() {
825 let s1: Size2D<f32> = Size2D::new(15.0, 25.0);
826
827 let result = s1 / 5.0;
828
829 assert_eq!(result, Size2D::new(3.0, 5.0));
830 }
831
832 #[test]
test_div_assign_scalar()833 pub fn test_div_assign_scalar() {
834 let mut s1: Size2D<f32> = Size2D::new(15.0, 25.0);
835
836 s1 /= 5.0;
837
838 assert_eq!(s1, Size2D::new(3.0, 5.0));
839 }
840
841 #[test]
test_div_scale()842 pub fn test_div_scale() {
843 let s1 = Size2DCm::new(0.1, 0.2);
844 let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
845
846 let result = s1 / cm_per_mm;
847
848 assert_eq!(result, Size2DMm::new(1.0, 2.0));
849 }
850
851 #[test]
test_div_assign_scale()852 pub fn test_div_assign_scale() {
853 let mut s1 = Size2DMm::new(0.1, 0.2);
854 let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
855
856 s1 /= scale;
857
858 assert_eq!(s1, Size2DMm::new(1.0, 2.0));
859 }
860 }
861 }
862
863
864
865 /// A 3d size tagged with a unit.
866 #[repr(C)]
867 pub struct Size3D<T, U> {
868 /// The extent of the element in the `U` units along the `x` axis.
869 pub width: T,
870 /// The extent of the element in the `U` units along the `y` axis.
871 pub height: T,
872 /// The extent of the element in the `U` units along the `z` axis.
873 pub depth: T,
874 #[doc(hidden)]
875 pub _unit: PhantomData<U>,
876 }
877
878 impl<T: Copy, U> Copy for Size3D<T, U> {}
879
880 impl<T: Clone, U> Clone for Size3D<T, U> {
clone(&self) -> Self881 fn clone(&self) -> Self {
882 Size3D {
883 width: self.width.clone(),
884 height: self.height.clone(),
885 depth: self.depth.clone(),
886 _unit: PhantomData,
887 }
888 }
889 }
890
891 #[cfg(feature = "serde")]
892 impl<'de, T, U> serde::Deserialize<'de> for Size3D<T, U>
893 where T: serde::Deserialize<'de>
894 {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de>895 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
896 where D: serde::Deserializer<'de>
897 {
898 let (width, height, depth) = serde::Deserialize::deserialize(deserializer)?;
899 Ok(Size3D { width, height, depth, _unit: PhantomData })
900 }
901 }
902
903 #[cfg(feature = "serde")]
904 impl<T, U> serde::Serialize for Size3D<T, U>
905 where T: serde::Serialize
906 {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer907 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
908 where S: serde::Serializer
909 {
910 (&self.width, &self.height, &self.depth).serialize(serializer)
911 }
912 }
913
914 impl<T, U> Eq for Size3D<T, U> where T: Eq {}
915
916 impl<T, U> PartialEq for Size3D<T, U>
917 where T: PartialEq
918 {
eq(&self, other: &Self) -> bool919 fn eq(&self, other: &Self) -> bool {
920 self.width == other.width && self.height == other.height && self.depth == other.depth
921 }
922 }
923
924 impl<T, U> Hash for Size3D<T, U>
925 where T: Hash
926 {
hash<H: ::core::hash::Hasher>(&self, h: &mut H)927 fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
928 self.width.hash(h);
929 self.height.hash(h);
930 self.depth.hash(h);
931 }
932 }
933
934 impl<T: fmt::Debug, U> fmt::Debug for Size3D<T, U> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result935 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
936 fmt::Debug::fmt(&self.width, f)?;
937 write!(f, "x")?;
938 fmt::Debug::fmt(&self.height, f)?;
939 write!(f, "x")?;
940 fmt::Debug::fmt(&self.depth, f)
941 }
942 }
943
944 impl<T: fmt::Display, U> fmt::Display for Size3D<T, U> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result945 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
946 write!(f, "(")?;
947 fmt::Display::fmt(&self.width, f)?;
948 write!(f, "x")?;
949 fmt::Display::fmt(&self.height, f)?;
950 write!(f, "x")?;
951 fmt::Display::fmt(&self.depth, f)?;
952 write!(f, ")")
953 }
954 }
955
956 impl<T: Default, U> Default for Size3D<T, U> {
default() -> Self957 fn default() -> Self {
958 Size3D::new(Default::default(), Default::default(), Default::default())
959 }
960 }
961
962
963 impl<T, U> Size3D<T, U> {
964 /// The same as [`Zero::zero()`] but available without importing trait.
965 ///
966 /// [`Zero::zero()`]: ./num/trait.Zero.html#tymethod.zero
zero() -> Self where T: Zero,967 pub fn zero() -> Self
968 where
969 T: Zero,
970 {
971 Size3D::new(Zero::zero(), Zero::zero(), Zero::zero())
972 }
973
974 /// Constructor taking scalar values.
975 #[inline]
new(width: T, height: T, depth: T) -> Self976 pub const fn new(width: T, height: T, depth: T) -> Self {
977 Size3D {
978 width,
979 height,
980 depth,
981 _unit: PhantomData,
982 }
983 }
984
985 /// Constructor taking scalar strongly typed lengths.
986 #[inline]
from_lengths(width: Length<T, U>, height: Length<T, U>, depth: Length<T, U>) -> Self987 pub fn from_lengths(width: Length<T, U>, height: Length<T, U>, depth: Length<T, U>) -> Self {
988 Size3D::new(width.0, height.0, depth.0)
989 }
990
991 /// Tag a unitless value with units.
992 #[inline]
from_untyped(p: Size3D<T, UnknownUnit>) -> Self993 pub fn from_untyped(p: Size3D<T, UnknownUnit>) -> Self {
994 Size3D::new(p.width, p.height, p.depth)
995 }
996 }
997
998 impl<T: Copy, U> Size3D<T, U> {
999 /// Return this size as an array of three elements (width, then height, then depth).
1000 #[inline]
to_array(&self) -> [T; 3]1001 pub fn to_array(&self) -> [T; 3] {
1002 [self.width, self.height, self.depth]
1003 }
1004
1005 /// Return this size as an array of three elements (width, then height, then depth).
1006 #[inline]
to_tuple(&self) -> (T, T, T)1007 pub fn to_tuple(&self) -> (T, T, T) {
1008 (self.width, self.height, self.depth)
1009 }
1010
1011 /// Return this size as a vector with width, height and depth.
1012 #[inline]
to_vector(&self) -> Vector3D<T, U>1013 pub fn to_vector(&self) -> Vector3D<T, U> {
1014 vec3(self.width, self.height, self.depth)
1015 }
1016
1017 /// Drop the units, preserving only the numeric value.
1018 #[inline]
to_untyped(&self) -> Size3D<T, UnknownUnit>1019 pub fn to_untyped(&self) -> Size3D<T, UnknownUnit> {
1020 self.cast_unit()
1021 }
1022
1023 /// Cast the unit
1024 #[inline]
cast_unit<V>(&self) -> Size3D<T, V>1025 pub fn cast_unit<V>(&self) -> Size3D<T, V> {
1026 Size3D::new(self.width, self.height, self.depth)
1027 }
1028
1029 /// Rounds each component to the nearest integer value.
1030 ///
1031 /// This behavior is preserved for negative values (unlike the basic cast).
1032 ///
1033 /// ```rust
1034 /// # use euclid::size3;
1035 /// enum Mm {}
1036 ///
1037 /// assert_eq!(size3::<_, Mm>(-0.1, -0.8, 0.4).round(), size3::<_, Mm>(0.0, -1.0, 0.0))
1038 /// ```
1039 #[inline]
1040 #[must_use]
round(&self) -> Self where T: Round,1041 pub fn round(&self) -> Self
1042 where
1043 T: Round,
1044 {
1045 Size3D::new(self.width.round(), self.height.round(), self.depth.round())
1046 }
1047
1048 /// Rounds each component to the smallest integer equal or greater than the original value.
1049 ///
1050 /// This behavior is preserved for negative values (unlike the basic cast).
1051 ///
1052 /// ```rust
1053 /// # use euclid::size3;
1054 /// enum Mm {}
1055 ///
1056 /// assert_eq!(size3::<_, Mm>(-0.1, -0.8, 0.4).ceil(), size3::<_, Mm>(0.0, 0.0, 1.0))
1057 /// ```
1058 #[inline]
1059 #[must_use]
ceil(&self) -> Self where T: Ceil,1060 pub fn ceil(&self) -> Self
1061 where
1062 T: Ceil,
1063 {
1064 Size3D::new(self.width.ceil(), self.height.ceil(), self.depth.ceil())
1065 }
1066
1067 /// Rounds each component to the biggest integer equal or lower than the original value.
1068 ///
1069 /// This behavior is preserved for negative values (unlike the basic cast).
1070 ///
1071 /// ```rust
1072 /// # use euclid::size3;
1073 /// enum Mm {}
1074 ///
1075 /// assert_eq!(size3::<_, Mm>(-0.1, -0.8, 0.4).floor(), size3::<_, Mm>(-1.0, -1.0, 0.0))
1076 /// ```
1077 #[inline]
1078 #[must_use]
floor(&self) -> Self where T: Floor,1079 pub fn floor(&self) -> Self
1080 where
1081 T: Floor,
1082 {
1083 Size3D::new(self.width.floor(), self.height.floor(), self.depth.floor())
1084 }
1085
1086 /// Returns result of multiplication of all components
volume(&self) -> T where T: Mul<Output = T>1087 pub fn volume(&self) -> T
1088 where
1089 T: Mul<Output = T>
1090 {
1091 self.width * self.height * self.depth
1092 }
1093
1094 /// Linearly interpolate between this size and another size.
1095 ///
1096 /// # Example
1097 ///
1098 /// ```rust
1099 /// use euclid::size3;
1100 /// use euclid::default::Size3D;
1101 ///
1102 /// let from: Size3D<_> = size3(0.0, 10.0, -1.0);
1103 /// let to: Size3D<_> = size3(8.0, -4.0, 0.0);
1104 ///
1105 /// assert_eq!(from.lerp(to, -1.0), size3(-8.0, 24.0, -2.0));
1106 /// assert_eq!(from.lerp(to, 0.0), size3( 0.0, 10.0, -1.0));
1107 /// assert_eq!(from.lerp(to, 0.5), size3( 4.0, 3.0, -0.5));
1108 /// assert_eq!(from.lerp(to, 1.0), size3( 8.0, -4.0, 0.0));
1109 /// assert_eq!(from.lerp(to, 2.0), size3(16.0, -18.0, 1.0));
1110 /// ```
1111 #[inline]
lerp(&self, other: Self, t: T) -> Self where T: One + Sub<Output = T> + Mul<Output = T> + Add<Output = T>,1112 pub fn lerp(&self, other: Self, t: T) -> Self
1113 where
1114 T: One + Sub<Output = T> + Mul<Output = T> + Add<Output = T>,
1115 {
1116 let one_t = T::one() - t;
1117 (*self) * one_t + other * t
1118 }
1119 }
1120
1121 impl<T: NumCast + Copy, U> Size3D<T, U> {
1122 /// Cast from one numeric representation to another, preserving the units.
1123 ///
1124 /// When casting from floating point to integer coordinates, the decimals are truncated
1125 /// as one would expect from a simple cast, but this behavior does not always make sense
1126 /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
1127 #[inline]
cast<NewT: NumCast>(&self) -> Size3D<NewT, U>1128 pub fn cast<NewT: NumCast>(&self) -> Size3D<NewT, U> {
1129 self.try_cast().unwrap()
1130 }
1131
1132 /// Fallible cast from one numeric representation to another, preserving the units.
1133 ///
1134 /// When casting from floating point to integer coordinates, the decimals are truncated
1135 /// as one would expect from a simple cast, but this behavior does not always make sense
1136 /// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
try_cast<NewT: NumCast>(&self) -> Option<Size3D<NewT, U>>1137 pub fn try_cast<NewT: NumCast>(&self) -> Option<Size3D<NewT, U>> {
1138 match (NumCast::from(self.width), NumCast::from(self.height), NumCast::from(self.depth)) {
1139 (Some(w), Some(h), Some(d)) => Some(Size3D::new(w, h, d)),
1140 _ => None,
1141 }
1142 }
1143
1144 // Convenience functions for common casts
1145
1146 /// Cast into an `f32` size.
1147 #[inline]
to_f32(&self) -> Size3D<f32, U>1148 pub fn to_f32(&self) -> Size3D<f32, U> {
1149 self.cast()
1150 }
1151
1152 /// Cast into an `f64` size.
1153 #[inline]
to_f64(&self) -> Size3D<f64, U>1154 pub fn to_f64(&self) -> Size3D<f64, U> {
1155 self.cast()
1156 }
1157
1158 /// Cast into an `uint` size, truncating decimals if any.
1159 ///
1160 /// When casting from floating point sizes, it is worth considering whether
1161 /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
1162 /// the desired conversion behavior.
1163 #[inline]
to_usize(&self) -> Size3D<usize, U>1164 pub fn to_usize(&self) -> Size3D<usize, U> {
1165 self.cast()
1166 }
1167
1168 /// Cast into an `u32` size, truncating decimals if any.
1169 ///
1170 /// When casting from floating point sizes, it is worth considering whether
1171 /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
1172 /// the desired conversion behavior.
1173 #[inline]
to_u32(&self) -> Size3D<u32, U>1174 pub fn to_u32(&self) -> Size3D<u32, U> {
1175 self.cast()
1176 }
1177
1178 /// Cast into an `i32` size, truncating decimals if any.
1179 ///
1180 /// When casting from floating point sizes, it is worth considering whether
1181 /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
1182 /// the desired conversion behavior.
1183 #[inline]
to_i32(&self) -> Size3D<i32, U>1184 pub fn to_i32(&self) -> Size3D<i32, U> {
1185 self.cast()
1186 }
1187
1188 /// Cast into an `i64` size, truncating decimals if any.
1189 ///
1190 /// When casting from floating point sizes, it is worth considering whether
1191 /// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
1192 /// the desired conversion behavior.
1193 #[inline]
to_i64(&self) -> Size3D<i64, U>1194 pub fn to_i64(&self) -> Size3D<i64, U> {
1195 self.cast()
1196 }
1197 }
1198
1199 impl<T: Signed, U> Size3D<T, U> {
1200 /// Computes the absolute value of each component.
1201 ///
1202 /// For `f32` and `f64`, `NaN` will be returned for component if the component is `NaN`.
1203 ///
1204 /// For signed integers, `::MIN` will be returned for component if the component is `::MIN`.
abs(&self) -> Self1205 pub fn abs(&self) -> Self {
1206 size3(self.width.abs(), self.height.abs(), self.depth.abs())
1207 }
1208
1209 /// Returns `true` if all components is positive and `false` any component is zero or negative.
is_positive(&self) -> bool1210 pub fn is_positive(&self) -> bool {
1211 self.width.is_positive() && self.height.is_positive() && self.depth.is_positive()
1212 }
1213 }
1214
1215 impl<T: PartialOrd, U> Size3D<T, U> {
1216 /// Returns the size each component of which are minimum of this size and another.
1217 #[inline]
min(self, other: Self) -> Self1218 pub fn min(self, other: Self) -> Self {
1219 size3(
1220 min(self.width, other.width),
1221 min(self.height, other.height),
1222 min(self.depth, other.depth),
1223 )
1224 }
1225
1226 /// Returns the size each component of which are maximum of this size and another.
1227 #[inline]
max(self, other: Self) -> Self1228 pub fn max(self, other: Self) -> Self {
1229 size3(
1230 max(self.width, other.width),
1231 max(self.height, other.height),
1232 max(self.depth, other.depth),
1233 )
1234 }
1235
1236 /// Returns the size each component of which clamped by corresponding
1237 /// components of `start` and `end`.
1238 ///
1239 /// Shortcut for `self.max(start).min(end)`.
1240 #[inline]
clamp(&self, start: Self, end: Self) -> Self where T: Copy,1241 pub fn clamp(&self, start: Self, end: Self) -> Self
1242 where
1243 T: Copy,
1244 {
1245 self.max(start).min(end)
1246 }
1247
1248 /// Returns vector with results of "greater than" operation on each component.
greater_than(&self, other: Self) -> BoolVector3D1249 pub fn greater_than(&self, other: Self) -> BoolVector3D {
1250 BoolVector3D {
1251 x: self.width > other.width,
1252 y: self.height > other.height,
1253 z: self.depth > other.depth,
1254 }
1255 }
1256
1257 /// Returns vector with results of "lower than" operation on each component.
lower_than(&self, other: Self) -> BoolVector3D1258 pub fn lower_than(&self, other: Self) -> BoolVector3D {
1259 BoolVector3D {
1260 x: self.width < other.width,
1261 y: self.height < other.height,
1262 z: self.depth < other.depth,
1263 }
1264 }
1265
1266 /// Returns `true` if any component of size is zero or negative.
is_empty_or_negative(&self) -> bool where T: Zero,1267 pub fn is_empty_or_negative(&self) -> bool
1268 where
1269 T: Zero,
1270 {
1271 let zero = T::zero();
1272 self.width <= zero || self.height <= zero || self.depth <= zero
1273 }
1274 }
1275
1276 impl<T: PartialEq, U> Size3D<T, U> {
1277 /// Returns vector with results of "equal" operation on each component.
equal(&self, other: Self) -> BoolVector3D1278 pub fn equal(&self, other: Self) -> BoolVector3D {
1279 BoolVector3D {
1280 x: self.width == other.width,
1281 y: self.height == other.height,
1282 z: self.depth == other.depth,
1283 }
1284 }
1285
1286 /// Returns vector with results of "not equal" operation on each component.
not_equal(&self, other: Self) -> BoolVector3D1287 pub fn not_equal(&self, other: Self) -> BoolVector3D {
1288 BoolVector3D {
1289 x: self.width != other.width,
1290 y: self.height != other.height,
1291 z: self.depth != other.depth,
1292 }
1293 }
1294 }
1295
1296
1297 impl<T: Round, U> Round for Size3D<T, U> {
1298 /// See [`Size3D::round()`](#method.round).
1299 #[inline]
round(self) -> Self1300 fn round(self) -> Self {
1301 (&self).round()
1302 }
1303 }
1304
1305 impl<T: Ceil, U> Ceil for Size3D<T, U> {
1306 /// See [`Size3D::ceil()`](#method.ceil).
1307 #[inline]
ceil(self) -> Self1308 fn ceil(self) -> Self {
1309 (&self).ceil()
1310 }
1311 }
1312
1313 impl<T: Floor, U> Floor for Size3D<T, U> {
1314 /// See [`Size3D::floor()`](#method.floor).
1315 #[inline]
floor(self) -> Self1316 fn floor(self) -> Self {
1317 (&self).floor()
1318 }
1319 }
1320
1321 impl<T: Zero, U> Zero for Size3D<T, U> {
1322 #[inline]
zero() -> Self1323 fn zero() -> Self {
1324 Size3D::new(Zero::zero(), Zero::zero(), Zero::zero())
1325 }
1326 }
1327
1328
1329 impl<T: Neg, U> Neg for Size3D<T, U> {
1330 type Output = Size3D<T::Output, U>;
1331
1332 #[inline]
neg(self) -> Self::Output1333 fn neg(self) -> Self::Output {
1334 Size3D::new(-self.width, -self.height, -self.depth)
1335 }
1336 }
1337
1338
1339 impl<T: Add, U> Add for Size3D<T, U> {
1340 type Output = Size3D<T::Output, U>;
1341
1342 #[inline]
add(self, other: Self) -> Self::Output1343 fn add(self, other: Self) -> Self::Output {
1344 Size3D::new(self.width + other.width, self.height + other.height, self.depth + other.depth)
1345 }
1346 }
1347
1348 impl<T: AddAssign, U> AddAssign for Size3D<T, U> {
1349 #[inline]
add_assign(&mut self, other: Self)1350 fn add_assign(&mut self, other: Self) {
1351 self.width += other.width;
1352 self.height += other.height;
1353 self.depth += other.depth;
1354 }
1355 }
1356
1357
1358 impl<T: Sub, U> Sub for Size3D<T, U> {
1359 type Output = Size3D<T::Output, U>;
1360
1361 #[inline]
sub(self, other: Self) -> Self::Output1362 fn sub(self, other: Self) -> Self::Output {
1363 Size3D::new(self.width - other.width, self.height - other.height, self.depth - other.depth)
1364 }
1365 }
1366
1367 impl<T: SubAssign, U> SubAssign for Size3D<T, U> {
1368 #[inline]
sub_assign(&mut self, other: Self)1369 fn sub_assign(&mut self, other: Self) {
1370 self.width -= other.width;
1371 self.height -= other.height;
1372 self.depth -= other.depth;
1373 }
1374 }
1375
1376
1377 impl<T: Clone + Mul, U> Mul<T> for Size3D<T, U> {
1378 type Output = Size3D<T::Output, U>;
1379
1380 #[inline]
mul(self, scale: T) -> Self::Output1381 fn mul(self, scale: T) -> Self::Output {
1382 Size3D::new(
1383 self.width * scale.clone(),
1384 self.height * scale.clone(),
1385 self.depth * scale
1386 )
1387 }
1388 }
1389
1390 impl<T: Clone + MulAssign, U> MulAssign<T> for Size3D<T, U> {
1391 #[inline]
mul_assign(&mut self, other: T)1392 fn mul_assign(&mut self, other: T) {
1393 self.width *= other.clone();
1394 self.height *= other.clone();
1395 self.depth *= other;
1396 }
1397 }
1398
1399 impl<T: Clone + Mul, U1, U2> Mul<Scale<T, U1, U2>> for Size3D<T, U1> {
1400 type Output = Size3D<T::Output, U2>;
1401
1402 #[inline]
mul(self, scale: Scale<T, U1, U2>) -> Self::Output1403 fn mul(self, scale: Scale<T, U1, U2>) -> Self::Output {
1404 Size3D::new(
1405 self.width * scale.0.clone(),
1406 self.height * scale.0.clone(),
1407 self.depth * scale.0
1408 )
1409 }
1410 }
1411
1412 impl<T: Clone + MulAssign, U> MulAssign<Scale<T, U, U>> for Size3D<T, U> {
1413 #[inline]
mul_assign(&mut self, other: Scale<T, U, U>)1414 fn mul_assign(&mut self, other: Scale<T, U, U>) {
1415 *self *= other.0;
1416 }
1417 }
1418
1419
1420 impl<T: Clone + Div, U> Div<T> for Size3D<T, U> {
1421 type Output = Size3D<T::Output, U>;
1422
1423 #[inline]
div(self, scale: T) -> Self::Output1424 fn div(self, scale: T) -> Self::Output {
1425 Size3D::new(
1426 self.width / scale.clone(),
1427 self.height / scale.clone(),
1428 self.depth / scale
1429 )
1430 }
1431 }
1432
1433 impl<T: Clone + DivAssign, U> DivAssign<T> for Size3D<T, U> {
1434 #[inline]
div_assign(&mut self, other: T)1435 fn div_assign(&mut self, other: T) {
1436 self.width /= other.clone();
1437 self.height /= other.clone();
1438 self.depth /= other;
1439 }
1440 }
1441
1442 impl<T: Clone + Div, U1, U2> Div<Scale<T, U1, U2>> for Size3D<T, U2> {
1443 type Output = Size3D<T::Output, U1>;
1444
1445 #[inline]
div(self, scale: Scale<T, U1, U2>) -> Self::Output1446 fn div(self, scale: Scale<T, U1, U2>) -> Self::Output {
1447 Size3D::new(
1448 self.width / scale.0.clone(),
1449 self.height / scale.0.clone(),
1450 self.depth / scale.0
1451 )
1452 }
1453 }
1454
1455 impl<T: Clone + DivAssign, U> DivAssign<Scale<T, U, U>> for Size3D<T, U> {
1456 #[inline]
div_assign(&mut self, other: Scale<T, U, U>)1457 fn div_assign(&mut self, other: Scale<T, U, U>) {
1458 *self /= other.0;
1459 }
1460 }
1461
1462
1463 #[cfg(feature = "mint")]
1464 impl<T, U> From<mint::Vector3<T>> for Size3D<T, U> {
1465 #[inline]
from(v: mint::Vector3<T>) -> Self1466 fn from(v: mint::Vector3<T>) -> Self {
1467 size3(v.x, v.y, v.z)
1468 }
1469 }
1470 #[cfg(feature = "mint")]
1471 impl<T, U> Into<mint::Vector3<T>> for Size3D<T, U> {
1472 #[inline]
into(self) -> mint::Vector3<T>1473 fn into(self) -> mint::Vector3<T> {
1474 mint::Vector3 {
1475 x: self.width,
1476 y: self.height,
1477 z: self.depth,
1478 }
1479 }
1480 }
1481
1482 impl<T, U> From<Vector3D<T, U>> for Size3D<T, U> {
1483 #[inline]
from(v: Vector3D<T, U>) -> Self1484 fn from(v: Vector3D<T, U>) -> Self {
1485 size3(v.x, v.y, v.z)
1486 }
1487 }
1488
1489 impl<T, U> Into<[T; 3]> for Size3D<T, U> {
1490 #[inline]
into(self) -> [T; 3]1491 fn into(self) -> [T; 3] {
1492 [self.width, self.height, self.depth]
1493 }
1494 }
1495
1496 impl<T, U> From<[T; 3]> for Size3D<T, U> {
1497 #[inline]
from([w, h, d]: [T; 3]) -> Self1498 fn from([w, h, d]: [T; 3]) -> Self {
1499 size3(w, h, d)
1500 }
1501 }
1502
1503 impl<T, U> Into<(T, T, T)> for Size3D<T, U> {
1504 #[inline]
into(self) -> (T, T, T)1505 fn into(self) -> (T, T, T) {
1506 (self.width, self.height, self.depth)
1507 }
1508 }
1509
1510 impl<T, U> From<(T, T, T)> for Size3D<T, U> {
1511 #[inline]
from(tuple: (T, T, T)) -> Self1512 fn from(tuple: (T, T, T)) -> Self {
1513 size3(tuple.0, tuple.1, tuple.2)
1514 }
1515 }
1516
1517
1518 /// Shorthand for `Size3D::new(w, h, d)`.
1519 #[inline]
size3<T, U>(w: T, h: T, d: T) -> Size3D<T, U>1520 pub const fn size3<T, U>(w: T, h: T, d: T) -> Size3D<T, U> {
1521 Size3D::new(w, h, d)
1522 }
1523
1524 #[cfg(test)]
1525 mod size3d {
1526 mod ops {
1527 use default::Size3D;
1528 use scale::Scale;
1529
1530 pub enum Mm {}
1531 pub enum Cm {}
1532
1533 pub type Size3DMm<T> = crate::Size3D<T, Mm>;
1534 pub type Size3DCm<T> = crate::Size3D<T, Cm>;
1535
1536 #[test]
test_neg()1537 pub fn test_neg() {
1538 assert_eq!(-Size3D::new( 1.0, 2.0, 3.0), Size3D::new(-1.0, -2.0, -3.0));
1539 assert_eq!(-Size3D::new( 0.0, 0.0, 0.0), Size3D::new(-0.0, -0.0, -0.0));
1540 assert_eq!(-Size3D::new(-1.0, -2.0, -3.0), Size3D::new( 1.0, 2.0, 3.0));
1541 }
1542
1543
1544 #[test]
test_add()1545 pub fn test_add() {
1546 let s1 = Size3D::new(1.0, 2.0, 3.0);
1547 let s2 = Size3D::new(4.0, 5.0, 6.0);
1548 assert_eq!(s1 + s2, Size3D::new(5.0, 7.0, 9.0));
1549
1550 let s1 = Size3D::new(1.0, 2.0, 3.0);
1551 let s2 = Size3D::new(0.0, 0.0, 0.0);
1552 assert_eq!(s1 + s2, Size3D::new(1.0, 2.0, 3.0));
1553
1554 let s1 = Size3D::new( 1.0, 2.0, 3.0);
1555 let s2 = Size3D::new(-4.0, -5.0, -6.0);
1556 assert_eq!(s1 + s2, Size3D::new(-3.0, -3.0, -3.0));
1557
1558 let s1 = Size3D::new(0.0, 0.0, 0.0);
1559 let s2 = Size3D::new(0.0, 0.0, 0.0);
1560 assert_eq!(s1 + s2, Size3D::new(0.0, 0.0, 0.0));
1561 }
1562
1563 #[test]
test_add_assign()1564 pub fn test_add_assign() {
1565 let mut s = Size3D::new(1.0, 2.0, 3.0);
1566 s += Size3D::new(4.0, 5.0, 6.0);
1567 assert_eq!(s, Size3D::new(5.0, 7.0, 9.0));
1568
1569 let mut s = Size3D::new(1.0, 2.0, 3.0);
1570 s += Size3D::new(0.0, 0.0, 0.0);
1571 assert_eq!(s, Size3D::new(1.0, 2.0, 3.0));
1572
1573 let mut s = Size3D::new( 1.0, 2.0, 3.0);
1574 s += Size3D::new(-4.0, -5.0, -6.0);
1575 assert_eq!(s, Size3D::new(-3.0, -3.0, -3.0));
1576
1577 let mut s = Size3D::new(0.0, 0.0, 0.0);
1578 s += Size3D::new(0.0, 0.0, 0.0);
1579 assert_eq!(s, Size3D::new(0.0, 0.0, 0.0));
1580 }
1581
1582 #[test]
test_sub()1583 pub fn test_sub() {
1584 let s1 = Size3D::new(1.0, 2.0, 3.0);
1585 let s2 = Size3D::new(4.0, 5.0, 6.0);
1586 assert_eq!(s1 - s2, Size3D::new(-3.0, -3.0, -3.0));
1587
1588 let s1 = Size3D::new(1.0, 2.0, 3.0);
1589 let s2 = Size3D::new(0.0, 0.0, 0.0);
1590 assert_eq!(s1 - s2, Size3D::new(1.0, 2.0, 3.0));
1591
1592 let s1 = Size3D::new( 1.0, 2.0, 3.0);
1593 let s2 = Size3D::new(-4.0, -5.0, -6.0);
1594 assert_eq!(s1 - s2, Size3D::new(5.0, 7.0, 9.0));
1595
1596 let s1 = Size3D::new(0.0, 0.0, 0.0);
1597 let s2 = Size3D::new(0.0, 0.0, 0.0);
1598 assert_eq!(s1 - s2, Size3D::new(0.0, 0.0, 0.0));
1599 }
1600
1601 #[test]
test_sub_assign()1602 pub fn test_sub_assign() {
1603 let mut s = Size3D::new(1.0, 2.0, 3.0);
1604 s -= Size3D::new(4.0, 5.0, 6.0);
1605 assert_eq!(s, Size3D::new(-3.0, -3.0, -3.0));
1606
1607 let mut s = Size3D::new(1.0, 2.0, 3.0);
1608 s -= Size3D::new(0.0, 0.0, 0.0);
1609 assert_eq!(s, Size3D::new(1.0, 2.0, 3.0));
1610
1611 let mut s = Size3D::new( 1.0, 2.0, 3.0);
1612 s -= Size3D::new(-4.0, -5.0, -6.0);
1613 assert_eq!(s, Size3D::new(5.0, 7.0, 9.0));
1614
1615 let mut s = Size3D::new(0.0, 0.0, 0.0);
1616 s -= Size3D::new(0.0, 0.0, 0.0);
1617 assert_eq!(s, Size3D::new(0.0, 0.0, 0.0));
1618 }
1619
1620
1621 #[test]
test_mul_scalar()1622 pub fn test_mul_scalar() {
1623 let s1: Size3D<f32> = Size3D::new(3.0, 5.0, 7.0);
1624
1625 let result = s1 * 5.0;
1626
1627 assert_eq!(result, Size3D::new(15.0, 25.0, 35.0));
1628 }
1629
1630 #[test]
test_mul_assign_scalar()1631 pub fn test_mul_assign_scalar() {
1632 let mut s1: Size3D<f32> = Size3D::new(3.0, 5.0, 7.0);
1633
1634 s1 *= 5.0;
1635
1636 assert_eq!(s1, Size3D::new(15.0, 25.0, 35.0));
1637 }
1638
1639 #[test]
test_mul_scale()1640 pub fn test_mul_scale() {
1641 let s1 = Size3DMm::new(1.0, 2.0, 3.0);
1642 let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
1643
1644 let result = s1 * cm_per_mm;
1645
1646 assert_eq!(result, Size3DCm::new(0.1, 0.2, 0.3));
1647 }
1648
1649 #[test]
test_mul_assign_scale()1650 pub fn test_mul_assign_scale() {
1651 let mut s1 = Size3DMm::new(1.0, 2.0, 3.0);
1652 let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
1653
1654 s1 *= scale;
1655
1656 assert_eq!(s1, Size3DMm::new(0.1, 0.2, 0.3));
1657 }
1658
1659
1660 #[test]
test_div_scalar()1661 pub fn test_div_scalar() {
1662 let s1: Size3D<f32> = Size3D::new(15.0, 25.0, 35.0);
1663
1664 let result = s1 / 5.0;
1665
1666 assert_eq!(result, Size3D::new(3.0, 5.0, 7.0));
1667 }
1668
1669 #[test]
test_div_assign_scalar()1670 pub fn test_div_assign_scalar() {
1671 let mut s1: Size3D<f32> = Size3D::new(15.0, 25.0, 35.0);
1672
1673 s1 /= 5.0;
1674
1675 assert_eq!(s1, Size3D::new(3.0, 5.0, 7.0));
1676 }
1677
1678 #[test]
test_div_scale()1679 pub fn test_div_scale() {
1680 let s1 = Size3DCm::new(0.1, 0.2, 0.3);
1681 let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
1682
1683 let result = s1 / cm_per_mm;
1684
1685 assert_eq!(result, Size3DMm::new(1.0, 2.0, 3.0));
1686 }
1687
1688 #[test]
test_div_assign_scale()1689 pub fn test_div_assign_scale() {
1690 let mut s1 = Size3DMm::new(0.1, 0.2, 0.3);
1691 let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
1692
1693 s1 /= scale;
1694
1695 assert_eq!(s1, Size3DMm::new(1.0, 2.0, 3.0));
1696 }
1697 }
1698 }