kas_core/geom/
vector.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License in the LICENSE-APACHE file or at:
4//     https://www.apache.org/licenses/LICENSE-2.0
5
6//! Vector types
7//!
8//! For drawing operations, all dimensions use the `f32` type.
9
10use crate::cast::*;
11use crate::dir::Directional;
12use crate::geom::{Coord, Offset, Rect, Size};
13use std::cmp::{Ordering, PartialOrd};
14use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
15
16/// Axis-aligned 2D cuboid, specified via two corners `a` and `b`
17///
18/// Typically it is expected that `a <= b`, although this is not required.
19#[repr(C)]
20#[derive(Clone, Copy, Debug, Default, PartialEq)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
22pub struct Quad {
23    pub a: Vec2,
24    pub b: Vec2,
25}
26
27impl Quad {
28    /// Zero
29    pub const ZERO: Quad = Quad::from_coords(Vec2::ZERO, Vec2::ZERO);
30
31    /// Negative infinity to positive infinity (everything)
32    pub const INFINITY: Quad = Quad::from_coords(Vec2::NEG_INFINITY, Vec2::INFINITY);
33
34    /// Not a Number (NaN)
35    pub const NAN: Quad = Quad::from_coords(Vec2::NAN, Vec2::NAN);
36
37    /// Construct with two coords
38    #[inline]
39    pub const fn from_coords(a: Vec2, b: Vec2) -> Self {
40        Quad { a, b }
41    }
42
43    /// Construct with position and size
44    #[inline]
45    pub fn from_pos_and_size(pos: Vec2, size: Vec2) -> Self {
46        Quad {
47            a: pos,
48            b: pos + size,
49        }
50    }
51
52    /// Construct with center and radius
53    #[inline]
54    pub fn from_center(pos: Vec2, r: f32) -> Self {
55        let v = Vec2::splat(r);
56        Quad {
57            a: pos - v,
58            b: pos + v,
59        }
60    }
61
62    /// Get the size
63    #[inline]
64    pub fn size(&self) -> Vec2 {
65        self.b - self.a
66    }
67
68    /// Swizzle coordinates: x from first, y from second point
69    #[inline]
70    pub fn ab(&self) -> Vec2 {
71        Vec2(self.a.0, self.b.1)
72    }
73
74    /// Swizzle coordinates: x from second, y from first point
75    #[inline]
76    pub fn ba(&self) -> Vec2 {
77        Vec2(self.b.0, self.a.1)
78    }
79
80    /// Shrink self in all directions by the given `value`
81    #[inline]
82    #[must_use = "method does not modify self but returns a new value"]
83    pub fn shrink(&self, value: f32) -> Quad {
84        let a = self.a + value;
85        let b = self.b - value;
86        Quad { a, b }
87    }
88
89    /// Grow self in all directions by the given `value`
90    #[inline]
91    #[must_use = "method does not modify self but returns a new value"]
92    pub fn grow(&self, value: f32) -> Quad {
93        let a = self.a - value;
94        let b = self.b + value;
95        Quad { a, b }
96    }
97
98    /// Shrink self in all directions by the given `value`
99    #[inline]
100    #[must_use = "method does not modify self but returns a new value"]
101    pub fn shrink_vec(&self, value: Vec2) -> Quad {
102        let a = self.a + value;
103        let b = self.b - value;
104        Quad { a, b }
105    }
106
107    /// Calculate the intersection of two quads
108    pub fn intersection(&self, rhs: &Quad) -> Option<Quad> {
109        let a = Vec2(self.a.0.max(rhs.a.0), self.a.1.max(rhs.a.1));
110        let b = Vec2(self.b.0.min(rhs.b.0), self.b.1.min(rhs.b.1));
111        if a <= b { Some(Quad::from_coords(a, b)) } else { None }
112    }
113}
114
115impl AddAssign<Vec2> for Quad {
116    #[inline]
117    fn add_assign(&mut self, rhs: Vec2) {
118        self.a += rhs;
119        self.b += rhs;
120    }
121}
122
123impl SubAssign<Vec2> for Quad {
124    #[inline]
125    fn sub_assign(&mut self, rhs: Vec2) {
126        self.a -= rhs;
127        self.b -= rhs;
128    }
129}
130
131impl Add<Vec2> for Quad {
132    type Output = Quad;
133    #[inline]
134    fn add(mut self, rhs: Vec2) -> Self::Output {
135        self += rhs;
136        self
137    }
138}
139
140impl Sub<Vec2> for Quad {
141    type Output = Quad;
142    #[inline]
143    fn sub(mut self, rhs: Vec2) -> Self::Output {
144        self -= rhs;
145        self
146    }
147}
148
149impl Conv<Rect> for Quad {
150    #[inline]
151    fn try_conv(rect: Rect) -> Result<Self> {
152        let a = Vec2::try_conv(rect.pos)?;
153        let b = a + Vec2::try_conv(rect.size)?;
154        Ok(Quad { a, b })
155    }
156}
157
158/// 2D vector
159///
160/// Usually used as either a coordinate or a difference of coordinates, but
161/// may have some other uses.
162///
163/// `Vec2` implements [`PartialOrd`] such that the comparison must be true of
164/// all components: for example `a < b == a.0 < b.0 && a.1 < b.1`.
165/// If `c == Vec2(0, 1)` and `d == Vec2(1, 0)` then
166/// `c != d && !(c < d) && !(c > d)`. `Vec2` does not implement [`Ord`].
167#[repr(C)]
168#[derive(Clone, Copy, Debug, Default, PartialEq)]
169#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
170pub struct Vec2(pub f32, pub f32);
171
172/// 2D vector (double precision)
173///
174/// Usually used as either a coordinate or a difference of coordinates, but
175/// may have some other uses.
176///
177/// `DVec2` implements [`PartialOrd`] such that the comparison must be true of
178/// all components: for example `a < b == a.0 < b.0 && a.1 < b.1`.
179/// If `c == DVec2(0, 1)` and `d == DVec2(1, 0)` then
180/// `c != d && !(c < d) && !(c > d)`. `DVec2` does not implement [`Ord`].
181#[repr(C)]
182#[derive(Clone, Copy, Debug, Default, PartialEq)]
183#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
184pub struct DVec2(pub f64, pub f64);
185
186macro_rules! impl_vec2 {
187    ($T:ident, $f:ty) => {
188        impl $T {
189            /// Zero
190            pub const ZERO: $T = $T::splat(0.0);
191
192            /// One
193            pub const ONE: $T = $T::splat(1.0);
194
195            /// Negative infinity
196            pub const NEG_INFINITY: $T = $T::splat(<$f>::NEG_INFINITY);
197
198            /// Positive infinity
199            pub const INFINITY: $T = $T::splat(<$f>::INFINITY);
200
201            /// Not a Number (NaN)
202            pub const NAN: $T = $T::splat(<$f>::NAN);
203
204            /// Constructs a new instance with each element initialized to `value`.
205            #[inline]
206            pub const fn splat(value: $f) -> Self {
207                $T(value, value)
208            }
209
210            /// Take the minimum component
211            #[inline]
212            pub fn min_comp(self) -> $f {
213                self.0.min(self.1)
214            }
215
216            /// Take the maximum component
217            #[inline]
218            pub fn max_comp(self) -> $f {
219                self.0.max(self.1)
220            }
221
222            /// Return the minimum, componentwise
223            #[inline]
224            #[must_use = "method does not modify self but returns a new value"]
225            pub fn min(self, other: Self) -> Self {
226                $T(self.0.min(other.0), self.1.min(other.1))
227            }
228
229            /// Return the maximum, componentwise
230            #[inline]
231            #[must_use = "method does not modify self but returns a new value"]
232            pub fn max(self, other: Self) -> Self {
233                $T(self.0.max(other.0), self.1.max(other.1))
234            }
235
236            /// Restrict a value to a certain interval unless it is NaN
237            ///
238            /// Returns `max` if `self` is greater than `max`, and `min` if
239            /// `self` is less than `min`. Otherwise this returns `self`.
240            ///
241            /// Note that this function returns NaN if the initial value was NaN
242            /// as well.
243            ///
244            /// # Panics
245            ///
246            /// Panics if `min > max`, `min` is NaN, or `max` is NaN.
247            #[inline]
248            #[must_use = "method does not modify self but returns a new value"]
249            pub fn clamp(mut self, min: Self, max: Self) -> Self {
250                assert!(min <= max);
251                if self < min {
252                    self = min;
253                }
254                if self > max {
255                    self = max;
256                }
257                self
258            }
259
260            /// Take the absolute value of each component
261            #[inline]
262            #[must_use = "method does not modify self but returns a new value"]
263            pub fn abs(self) -> Self {
264                $T(self.0.abs(), self.1.abs())
265            }
266
267            /// Take the floor of each component
268            #[inline]
269            #[must_use = "method does not modify self but returns a new value"]
270            pub fn floor(self) -> Self {
271                $T(self.0.floor(), self.1.floor())
272            }
273
274            /// Take the ceiling of each component
275            #[inline]
276            #[must_use = "method does not modify self but returns a new value"]
277            pub fn ceil(self) -> Self {
278                $T(self.0.ceil(), self.1.ceil())
279            }
280
281            /// Round each component to the nearest integer
282            #[inline]
283            #[must_use = "method does not modify self but returns a new value"]
284            pub fn round(self) -> Self {
285                $T(self.0.round(), self.1.round())
286            }
287
288            /// Take the trunc of each component
289            #[inline]
290            #[must_use = "method does not modify self but returns a new value"]
291            pub fn trunc(self) -> Self {
292                $T(self.0.trunc(), self.1.trunc())
293            }
294
295            /// Take the fract of each component
296            #[inline]
297            #[must_use = "method does not modify self but returns a new value"]
298            pub fn fract(self) -> Self {
299                $T(self.0.fract(), self.1.fract())
300            }
301
302            /// For each component, return `±1` with the same sign as `self`.
303            #[inline]
304            #[must_use = "method does not modify self but returns a new value"]
305            pub fn sign(self) -> Self {
306                let one: $f = 1.0;
307                $T(one.copysign(self.0), one.copysign(self.1))
308            }
309            /// Multiply two vectors as if they are complex numbers
310            #[inline]
311            #[must_use = "method does not modify self but returns a new value"]
312            pub fn complex_mul(self, rhs: Self) -> Self {
313                $T(
314                    self.0 * rhs.0 - self.1 * rhs.1,
315                    self.0 * rhs.1 + self.1 * rhs.0,
316                )
317            }
318
319            /// Divide by a second vector as if they are complex numbers
320            #[inline]
321            #[must_use = "method does not modify self but returns a new value"]
322            pub fn complex_div(self, rhs: Self) -> Self {
323                self.complex_mul(rhs.complex_inv())
324            }
325
326            /// Take the complex reciprocal
327            ///
328            /// If both components are zero then the result will not be finite.
329            #[inline]
330            #[must_use = "method does not modify self but returns a new value"]
331            pub fn complex_inv(self) -> Self {
332                let ssi = 1.0 / self.sum_square();
333                $T(self.0 * ssi, -self.1 * ssi)
334            }
335
336            /// Return the sum of the terms
337            #[inline]
338            pub fn sum(self) -> $f {
339                self.0 + self.1
340            }
341
342            /// Return the sum of the square of the terms
343            #[inline]
344            pub fn sum_square(self) -> $f {
345                self.0 * self.0 + self.1 * self.1
346            }
347
348            /// Return the L1 (rectilinear / taxicab) distance
349            #[inline]
350            pub fn distance_l1(self) -> $f {
351                self.0.abs() + self.1.abs()
352            }
353
354            /// Return the L-inf (max) distance
355            #[inline]
356            pub fn distance_l_inf(self) -> $f {
357                self.0.abs().max(self.1.abs())
358            }
359
360            /// Extract one component, based on a direction
361            ///
362            /// This merely extracts the horizontal or vertical component.
363            /// It never negates it, even if the axis is reversed.
364            #[inline]
365            pub fn extract<D: Directional>(self, dir: D) -> $f {
366                match dir.is_vertical() {
367                    false => self.0,
368                    true => self.1,
369                }
370            }
371
372            /// Returns `true` if all components are neither infinite nor NaN
373            #[inline]
374            pub fn is_finite(self) -> bool {
375                self.0.is_finite() && self.1.is_finite()
376            }
377
378            /// Returns `true` if no components are zero, infinite, submormal or NaN
379            #[inline]
380            pub fn is_normal(self) -> bool {
381                self.0.is_normal() && self.1.is_normal()
382            }
383        }
384
385        impl Neg for $T {
386            type Output = $T;
387            #[inline]
388            fn neg(self) -> Self::Output {
389                $T(-self.0, -self.1)
390            }
391        }
392
393        impl Add<$T> for $T {
394            type Output = $T;
395            #[inline]
396            fn add(self, rhs: $T) -> Self::Output {
397                $T(self.0 + rhs.0, self.1 + rhs.1)
398            }
399        }
400
401        impl Add<$f> for $T {
402            type Output = $T;
403            #[inline]
404            fn add(self, rhs: $f) -> Self::Output {
405                $T(self.0 + rhs, self.1 + rhs)
406            }
407        }
408
409        impl AddAssign<$T> for $T {
410            #[inline]
411            fn add_assign(&mut self, rhs: $T) {
412                self.0 += rhs.0;
413                self.1 += rhs.1;
414            }
415        }
416
417        impl AddAssign<$f> for $T {
418            #[inline]
419            fn add_assign(&mut self, rhs: $f) {
420                self.0 += rhs;
421                self.1 += rhs;
422            }
423        }
424
425        impl Sub<$T> for $T {
426            type Output = $T;
427            #[inline]
428            fn sub(self, rhs: $T) -> Self::Output {
429                $T(self.0 - rhs.0, self.1 - rhs.1)
430            }
431        }
432
433        impl Sub<$f> for $T {
434            type Output = $T;
435            #[inline]
436            fn sub(self, rhs: $f) -> Self::Output {
437                $T(self.0 - rhs, self.1 - rhs)
438            }
439        }
440
441        impl SubAssign<$T> for $T {
442            #[inline]
443            fn sub_assign(&mut self, rhs: $T) {
444                self.0 -= rhs.0;
445                self.1 -= rhs.1;
446            }
447        }
448
449        impl SubAssign<$f> for $T {
450            #[inline]
451            fn sub_assign(&mut self, rhs: $f) {
452                self.0 -= rhs;
453                self.1 -= rhs;
454            }
455        }
456
457        impl Mul<$T> for $T {
458            type Output = $T;
459            #[inline]
460            fn mul(self, rhs: $T) -> Self::Output {
461                $T(self.0 * rhs.0, self.1 * rhs.1)
462            }
463        }
464
465        impl MulAssign<$T> for $T {
466            #[inline]
467            fn mul_assign(&mut self, rhs: $T) {
468                self.0 *= rhs.0;
469                self.1 *= rhs.1;
470            }
471        }
472
473        impl Mul<$f> for $T {
474            type Output = $T;
475            #[inline]
476            fn mul(self, rhs: $f) -> Self::Output {
477                $T(self.0 * rhs, self.1 * rhs)
478            }
479        }
480
481        impl MulAssign<$f> for $T {
482            #[inline]
483            fn mul_assign(&mut self, rhs: $f) {
484                self.0 *= rhs;
485                self.1 *= rhs;
486            }
487        }
488
489        impl Div<$T> for $T {
490            type Output = $T;
491            #[inline]
492            fn div(self, rhs: $T) -> Self::Output {
493                $T(self.0 / rhs.0, self.1 / rhs.1)
494            }
495        }
496
497        impl Div<$f> for $T {
498            type Output = $T;
499            #[inline]
500            fn div(self, rhs: $f) -> Self::Output {
501                $T(self.0 / rhs, self.1 / rhs)
502            }
503        }
504
505        impl DivAssign<$f> for $T {
506            #[inline]
507            fn div_assign(&mut self, rhs: $f) {
508                self.0 /= rhs;
509                self.1 /= rhs;
510            }
511        }
512
513        impl PartialOrd for $T {
514            fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
515                if self == rhs {
516                    Some(Ordering::Equal)
517                } else if self.0 < rhs.0 && self.1 < rhs.1 {
518                    Some(Ordering::Less)
519                } else if self.0 > rhs.0 && self.1 > rhs.1 {
520                    Some(Ordering::Greater)
521                } else {
522                    None
523                }
524            }
525
526            #[inline]
527            fn lt(&self, rhs: &Self) -> bool {
528                self.0 < rhs.0 && self.1 < rhs.1
529            }
530
531            #[inline]
532            fn le(&self, rhs: &Self) -> bool {
533                self.0 <= rhs.0 && self.1 <= rhs.1
534            }
535
536            #[inline]
537            fn ge(&self, rhs: &Self) -> bool {
538                self.0 >= rhs.0 && self.1 >= rhs.1
539            }
540
541            #[inline]
542            fn gt(&self, rhs: &Self) -> bool {
543                self.0 > rhs.0 && self.1 > rhs.1
544            }
545        }
546
547        impl PartialEq<Coord> for $T {
548            fn eq(&self, rhs: &Coord) -> bool {
549                DVec2::from(*self) == DVec2::conv(*rhs)
550            }
551        }
552
553        impl PartialOrd<Coord> for $T {
554            fn partial_cmp(&self, rhs: &Coord) -> Option<Ordering> {
555                DVec2::from(*self).partial_cmp(&DVec2::conv(*rhs))
556            }
557
558            #[inline]
559            fn lt(&self, rhs: &Coord) -> bool {
560                DVec2::from(*self) < DVec2::conv(*rhs)
561            }
562
563            #[inline]
564            fn le(&self, rhs: &Coord) -> bool {
565                DVec2::from(*self) <= DVec2::conv(*rhs)
566            }
567
568            #[inline]
569            fn ge(&self, rhs: &Coord) -> bool {
570                DVec2::from(*self) >= DVec2::conv(*rhs)
571            }
572
573            #[inline]
574            fn gt(&self, rhs: &Coord) -> bool {
575                DVec2::from(*self) > DVec2::conv(*rhs)
576            }
577        }
578
579        impl From<($f, $f)> for $T {
580            #[inline]
581            fn from(arg: ($f, $f)) -> Self {
582                $T(arg.0, arg.1)
583            }
584        }
585        impl Conv<($f, $f)> for $T {
586            #[inline]
587            fn conv(arg: ($f, $f)) -> Self {
588                $T(arg.0, arg.1)
589            }
590            #[inline]
591            fn try_conv(v: ($f, $f)) -> Result<Self> {
592                Ok(Self::conv(v))
593            }
594        }
595
596        impl From<$T> for ($f, $f) {
597            #[inline]
598            fn from(v: $T) -> Self {
599                (v.0, v.1)
600            }
601        }
602        impl Conv<$T> for ($f, $f) {
603            #[inline]
604            fn conv(v: $T) -> Self {
605                (v.0, v.1)
606            }
607            #[inline]
608            fn try_conv(v: $T) -> Result<Self> {
609                Ok(Self::conv(v))
610            }
611        }
612
613        impl From<winit::dpi::PhysicalPosition<$f>> for $T {
614            #[inline]
615            fn from(pos: winit::dpi::PhysicalPosition<$f>) -> Self {
616                $T(pos.x, pos.y)
617            }
618        }
619
620        impl From<winit::dpi::PhysicalSize<$f>> for $T {
621            #[inline]
622            fn from(size: winit::dpi::PhysicalSize<$f>) -> Self {
623                $T(size.width, size.height)
624            }
625        }
626    };
627}
628
629impl From<kas_text::Vec2> for Vec2 {
630    #[inline]
631    fn from(size: kas_text::Vec2) -> Self {
632        Vec2(size.0, size.1)
633    }
634}
635impl Conv<kas_text::Vec2> for Vec2 {
636    #[inline]
637    fn conv(size: kas_text::Vec2) -> Self {
638        Vec2(size.0, size.1)
639    }
640    #[inline]
641    fn try_conv(v: kas_text::Vec2) -> Result<Self> {
642        Ok(Self::conv(v))
643    }
644}
645
646impl From<Vec2> for kas_text::Vec2 {
647    #[inline]
648    fn from(size: Vec2) -> kas_text::Vec2 {
649        kas_text::Vec2(size.0, size.1)
650    }
651}
652impl Conv<Vec2> for kas_text::Vec2 {
653    #[inline]
654    fn conv(size: Vec2) -> kas_text::Vec2 {
655        kas_text::Vec2(size.0, size.1)
656    }
657    #[inline]
658    fn try_conv(v: Vec2) -> Result<Self> {
659        Ok(Self::conv(v))
660    }
661}
662
663impl From<Vec2> for DVec2 {
664    #[inline]
665    fn from(v: Vec2) -> DVec2 {
666        DVec2(v.0.into(), v.1.into())
667    }
668}
669impl Conv<Vec2> for DVec2 {
670    #[inline]
671    fn try_conv(v: Vec2) -> Result<DVec2> {
672        Ok(DVec2(v.0.into(), v.1.into()))
673    }
674}
675impl ConvApprox<DVec2> for Vec2 {
676    fn try_conv_approx(size: DVec2) -> Result<Vec2> {
677        Ok(Vec2(size.0.try_cast_approx()?, size.1.try_cast_approx()?))
678    }
679}
680
681impl_vec2!(Vec2, f32);
682impl_vec2!(DVec2, f64);
683
684macro_rules! impl_conv_vec2 {
685    ($S:ty, $T:ty) => {
686        impl Conv<$S> for $T {
687            #[inline]
688            fn try_conv(arg: $S) -> Result<Self> {
689                Ok(Self(arg.0.try_cast()?, arg.1.try_cast()?))
690            }
691        }
692
693        impl ConvApprox<$T> for $S {
694            #[inline]
695            fn try_conv_approx(arg: $T) -> Result<Self> {
696                Ok(Self(arg.0.try_cast_approx()?, arg.1.try_cast_approx()?))
697            }
698        }
699
700        impl ConvFloat<$T> for $S {
701            #[inline]
702            fn try_conv_trunc(x: $T) -> Result<Self> {
703                Ok(Self(i32::try_conv_trunc(x.0)?, i32::try_conv_trunc(x.1)?))
704            }
705            #[inline]
706            fn try_conv_nearest(x: $T) -> Result<Self> {
707                Ok(Self(
708                    i32::try_conv_nearest(x.0)?,
709                    i32::try_conv_nearest(x.1)?,
710                ))
711            }
712            #[inline]
713            fn try_conv_floor(x: $T) -> Result<Self> {
714                Ok(Self(i32::try_conv_floor(x.0)?, i32::try_conv_floor(x.1)?))
715            }
716            #[inline]
717            fn try_conv_ceil(x: $T) -> Result<Self> {
718                Ok(Self(i32::try_conv_ceil(x.0)?, i32::try_conv_ceil(x.1)?))
719            }
720        }
721    };
722}
723
724impl_conv_vec2!(Coord, Vec2);
725impl_conv_vec2!(Size, Vec2);
726impl_conv_vec2!(Offset, Vec2);
727impl_conv_vec2!(Coord, DVec2);
728impl_conv_vec2!(Size, DVec2);
729impl_conv_vec2!(Offset, DVec2);
730
731/// 3D vector
732///
733/// Usually used for a 2D coordinate with a depth value.
734#[repr(C)]
735#[derive(Clone, Copy, Debug, Default, PartialEq)]
736#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
737pub struct Vec3(pub f32, pub f32, pub f32);
738
739impl Vec3 {
740    /// Construct from a [`Vec2`] and third value
741    #[inline]
742    pub fn from2(v: Vec2, z: f32) -> Self {
743        Vec3(v.0, v.1, z)
744    }
745}