cadmus_core/
geom.rs

1use crate::color::Color;
2use serde::{Deserialize, Serialize};
3use std::cmp::Ordering;
4use std::f32::consts;
5use std::fmt;
6use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
7
8#[derive(Debug, Copy, Clone, Eq, PartialEq)]
9pub enum Dir {
10    North,
11    East,
12    South,
13    West,
14}
15
16impl Dir {
17    pub fn opposite(self) -> Dir {
18        match self {
19            Dir::North => Dir::South,
20            Dir::South => Dir::North,
21            Dir::East => Dir::West,
22            Dir::West => Dir::East,
23        }
24    }
25
26    pub fn axis(self) -> Axis {
27        match self {
28            Dir::North | Dir::South => Axis::Vertical,
29            Dir::East | Dir::West => Axis::Horizontal,
30        }
31    }
32}
33
34impl fmt::Display for Dir {
35    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36        match self {
37            Dir::North => write!(f, "north"),
38            Dir::East => write!(f, "east"),
39            Dir::South => write!(f, "south"),
40            Dir::West => write!(f, "west"),
41        }
42    }
43}
44
45#[derive(Debug, Copy, Clone, Eq, PartialEq)]
46pub enum DiagDir {
47    NorthWest,
48    NorthEast,
49    SouthEast,
50    SouthWest,
51}
52
53impl DiagDir {
54    pub fn opposite(self) -> DiagDir {
55        match self {
56            DiagDir::NorthWest => DiagDir::SouthEast,
57            DiagDir::NorthEast => DiagDir::SouthWest,
58            DiagDir::SouthEast => DiagDir::NorthWest,
59            DiagDir::SouthWest => DiagDir::NorthEast,
60        }
61    }
62}
63
64impl fmt::Display for DiagDir {
65    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
66        match self {
67            DiagDir::NorthWest => write!(f, "northwest"),
68            DiagDir::NorthEast => write!(f, "northeast"),
69            DiagDir::SouthEast => write!(f, "southeast"),
70            DiagDir::SouthWest => write!(f, "southwest"),
71        }
72    }
73}
74
75#[derive(Debug, Copy, Clone, Eq, PartialEq)]
76pub enum Axis {
77    Horizontal,
78    Vertical,
79    Diagonal,
80}
81
82impl fmt::Display for Axis {
83    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
84        match self {
85            Axis::Horizontal => write!(f, "horizontal"),
86            Axis::Vertical => write!(f, "vertical"),
87            Axis::Diagonal => write!(f, "diagonal"),
88        }
89    }
90}
91
92#[derive(Debug, Copy, Clone, Eq, PartialEq)]
93pub enum CycleDir {
94    Next,
95    Previous,
96}
97
98#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
99pub enum LinearDir {
100    Backward,
101    Forward,
102}
103
104impl LinearDir {
105    pub fn opposite(self) -> LinearDir {
106        match self {
107            LinearDir::Backward => LinearDir::Forward,
108            LinearDir::Forward => LinearDir::Backward,
109        }
110    }
111}
112
113#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
114pub struct Point {
115    pub x: i32,
116    pub y: i32,
117}
118
119#[macro_export]
120macro_rules! pt {
121    ($x:expr, $y:expr $(,)* ) => {
122        $crate::geom::Point::new($x, $y)
123    };
124    ($a:expr) => {
125        $crate::geom::Point::new($a, $a)
126    };
127}
128
129impl fmt::Display for Point {
130    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
131        write!(f, "({}, {})", self.x, self.y)
132    }
133}
134
135#[derive(Debug, Copy, Clone)]
136pub struct Edge {
137    pub top: i32,
138    pub right: i32,
139    pub bottom: i32,
140    pub left: i32,
141}
142
143impl Edge {
144    pub fn uniform(value: i32) -> Edge {
145        Edge {
146            top: value,
147            right: value,
148            bottom: value,
149            left: value,
150        }
151    }
152}
153
154impl Default for Edge {
155    fn default() -> Self {
156        Edge {
157            top: 0,
158            right: 0,
159            bottom: 0,
160            left: 0,
161        }
162    }
163}
164
165impl Add for Edge {
166    type Output = Edge;
167    fn add(self, rhs: Edge) -> Edge {
168        Edge {
169            top: self.top + rhs.top,
170            right: self.right + rhs.right,
171            bottom: self.bottom + rhs.bottom,
172            left: self.left + rhs.left,
173        }
174    }
175}
176
177impl AddAssign for Edge {
178    fn add_assign(&mut self, rhs: Edge) {
179        self.top += rhs.top;
180        self.right += rhs.right;
181        self.bottom += rhs.bottom;
182        self.left += rhs.left;
183    }
184}
185
186impl Sub for Edge {
187    type Output = Edge;
188    fn sub(self, rhs: Edge) -> Edge {
189        Edge {
190            top: self.top - rhs.top,
191            right: self.right - rhs.right,
192            bottom: self.bottom - rhs.bottom,
193            left: self.left - rhs.left,
194        }
195    }
196}
197
198impl SubAssign for Edge {
199    fn sub_assign(&mut self, rhs: Edge) {
200        self.top -= rhs.top;
201        self.right -= rhs.right;
202        self.bottom -= rhs.bottom;
203        self.left -= rhs.left;
204    }
205}
206
207#[derive(Debug, Copy, Clone)]
208pub enum CornerSpec {
209    Uniform(i32),
210    North(i32),
211    East(i32),
212    South(i32),
213    West(i32),
214    Detailed {
215        north_west: i32,
216        north_east: i32,
217        south_east: i32,
218        south_west: i32,
219    },
220}
221
222pub trait ColorSource {
223    fn color(&self, x: i32, y: i32) -> Color;
224}
225
226impl<F> ColorSource for F
227where
228    F: Fn(i32, i32) -> Color,
229{
230    #[inline]
231    fn color(&self, x: i32, y: i32) -> Color {
232        (self)(x, y)
233    }
234}
235
236impl ColorSource for Color {
237    #[inline]
238    fn color(&self, _: i32, _: i32) -> Color {
239        *self
240    }
241}
242
243#[derive(Debug, Copy, Clone)]
244pub struct BorderSpec {
245    pub thickness: u16,
246    pub color: Color,
247}
248
249const HALF_PIXEL_DIAGONAL: f32 = consts::SQRT_2 / 2.0;
250
251// Takes the (signed) distance and angle from the center of a pixel to the closest point on a
252// shape's boundary and returns the approximate shape area contained within that pixel (the
253// boundary is considered flat at the pixel level).
254pub fn surface_area(dist: f32, angle: f32) -> f32 {
255    // Clearly {in,out}side of the shape.
256    if dist.abs() > HALF_PIXEL_DIAGONAL {
257        if dist.is_sign_positive() {
258            return 0.0;
259        } else {
260            return 1.0;
261        }
262    }
263    // If the boundary is parallel to the pixel's diagonals then the area is proportional to `dist²`.
264    // If the boundary is parallel to the pixel's sides then the area is proportional to `dist`.
265    // Hence we compute an interpolated exponent `expo` (`1 <= expo <= 2`) based on `angle`.
266    let expo = 0.5 * (3.0 - (4.0 * angle).cos());
267    // The *radius* of the pixel for the given *angle*
268    let radius = 0.5 * expo.sqrt();
269    if dist.is_sign_positive() {
270        (radius - dist).max(0.0).powf(expo)
271    } else {
272        1.0 - (radius + dist).max(0.0).powf(expo)
273    }
274}
275
276// Returns the nearest point to p on segment ab
277pub fn nearest_segment_point(p: Vec2, a: Vec2, b: Vec2) -> (Vec2, f32) {
278    let ab = b - a;
279    let ap = p - a;
280    let l2 = ab.dot(ab);
281
282    // Will not happen in practice
283    if l2 < ::std::f32::EPSILON {
284        return (a, 0.0);
285    }
286
287    let t = (ap.dot(ab) / l2).clamp(0.0, 1.0);
288    (a + t * ab, t)
289}
290
291pub fn elbow(sp: &[Point]) -> usize {
292    let len = sp.len();
293    let a: Vec2 = sp[0].into();
294    let b: Vec2 = sp[len - 1].into();
295    let i1 = len / 3;
296    let i2 = 2 * len / 3;
297    let p1: Vec2 = sp[i1].into();
298    let p2: Vec2 = sp[i2].into();
299    let (n1, _) = nearest_segment_point(p1, a, b);
300    let (n2, _) = nearest_segment_point(p2, a, b);
301    let d1 = (p1 - n1).length();
302    let d2 = (p2 - n2).length();
303    if d1 > f32::EPSILON || d2 > f32::EPSILON {
304        ((d1 * i1 as f32 + d2 * i2 as f32) / (d1 + d2)) as usize
305    } else {
306        len / 2
307    }
308}
309
310#[inline]
311pub fn halves(n: i32) -> (i32, i32) {
312    let small_half = n / 2;
313    let big_half = n - small_half;
314    (small_half, big_half)
315}
316
317#[inline]
318pub fn small_half(n: i32) -> i32 {
319    n / 2
320}
321
322#[inline]
323pub fn big_half(n: i32) -> i32 {
324    n - small_half(n)
325}
326
327// Returns a Vec v, of size p, such that the sum all the elements is n.
328// Each element x in v is such that |x - n/p| < 1.
329pub fn divide(n: i32, p: i32) -> Vec<i32> {
330    let size = n.checked_div(p).unwrap_or(0);
331    let mut rem = n - p * size;
332    let tick = p.checked_div(rem).unwrap_or(0);
333    let mut vec = Vec::with_capacity(p as usize);
334    for i in 0..p {
335        if rem > 0 && (i + 1) % tick == 0 {
336            vec.push(size + 1);
337            rem -= 1;
338        } else {
339            vec.push(size);
340        }
341    }
342    vec
343}
344
345#[inline]
346pub fn lerp(a: f32, b: f32, t: f32) -> f32 {
347    (1.0 - t) * a + t * b
348}
349
350// Returns the clockwise and anti-clockwise modulo p distance from a to b.
351#[inline]
352pub fn circular_distances(a: u16, mut b: u16, p: u16) -> (u16, u16) {
353    if b < a {
354        b += p;
355    }
356    let d0 = b - a;
357    let d1 = p - d0;
358    (d0, d1)
359}
360
361impl Point {
362    pub fn new(x: i32, y: i32) -> Point {
363        Point { x, y }
364    }
365
366    pub fn dist2(self, pt: Point) -> u32 {
367        ((pt.x - self.x).pow(2) + (pt.y - self.y).pow(2)) as u32
368    }
369
370    pub fn rdist2(self, rect: &Rectangle) -> u32 {
371        if rect.includes(self) {
372            0
373        } else if self.y >= rect.min.y && self.y < rect.max.y {
374            if self.x < rect.min.x {
375                (rect.min.x - self.x).pow(2) as u32
376            } else {
377                (self.x - rect.max.x + 1).pow(2) as u32
378            }
379        } else if self.x >= rect.min.x && self.x < rect.max.x {
380            if self.y < rect.min.y {
381                (rect.min.y - self.y).pow(2) as u32
382            } else {
383                (self.y - rect.max.y + 1).pow(2) as u32
384            }
385        } else if self.x < rect.min.x {
386            if self.y < rect.min.y {
387                self.dist2(rect.min)
388            } else {
389                self.dist2(Point::new(rect.min.x, rect.max.y - 1))
390            }
391        } else {
392            if self.y < rect.min.y {
393                self.dist2(Point::new(rect.max.x - 1, rect.min.y))
394            } else {
395                self.dist2(Point::new(rect.max.x - 1, rect.max.y - 1))
396            }
397        }
398    }
399
400    pub fn length(self) -> f32 {
401        ((self.x.pow(2) + self.y.pow(2)) as f32).sqrt()
402    }
403
404    pub fn angle(self) -> f32 {
405        (-self.y as f32).atan2(self.x as f32)
406    }
407
408    pub fn dir(self) -> Dir {
409        if self.x.abs() > self.y.abs() {
410            if self.x.is_positive() {
411                Dir::East
412            } else {
413                Dir::West
414            }
415        } else {
416            if self.y.is_positive() {
417                Dir::South
418            } else {
419                Dir::North
420            }
421        }
422    }
423
424    pub fn diag_dir(self) -> DiagDir {
425        if self.x.is_positive() {
426            if self.y.is_positive() {
427                DiagDir::SouthEast
428            } else {
429                DiagDir::NorthEast
430            }
431        } else {
432            if self.y.is_positive() {
433                DiagDir::SouthWest
434            } else {
435                DiagDir::NorthWest
436            }
437        }
438    }
439}
440
441impl Default for Point {
442    fn default() -> Self {
443        Point::new(0, 0)
444    }
445}
446
447impl Into<(f32, f32)> for Point {
448    fn into(self) -> (f32, f32) {
449        (self.x as f32, self.y as f32)
450    }
451}
452
453impl From<Point> for Vec2 {
454    fn from(pt: Point) -> Self {
455        Vec2::new(pt.x as f32, pt.y as f32)
456    }
457}
458
459impl From<Vec2> for Point {
460    fn from(pt: Vec2) -> Self {
461        Point::new(pt.x as i32, pt.y as i32)
462    }
463}
464
465#[derive(Debug, Copy, Clone)]
466pub struct Vec2 {
467    pub x: f32,
468    pub y: f32,
469}
470
471#[macro_export]
472macro_rules! vec2 {
473    ($x:expr, $y:expr $(,)* ) => {
474        $crate::geom::Vec2::new($x, $y)
475    };
476    ($a:expr) => {
477        $crate::geom::Vec2::new($a, $a)
478    };
479}
480
481impl Vec2 {
482    pub fn new(x: f32, y: f32) -> Vec2 {
483        Vec2 { x, y }
484    }
485
486    pub fn dot(self, other: Vec2) -> f32 {
487        self.x * other.x + self.y * other.y
488    }
489
490    pub fn cross(self, other: Vec2) -> f32 {
491        self.x * other.y - self.y * other.x
492    }
493
494    pub fn length(self) -> f32 {
495        self.x.hypot(self.y)
496    }
497
498    pub fn angle(self) -> f32 {
499        (-self.y).atan2(self.x)
500    }
501
502    pub fn dir(self) -> Dir {
503        if self.x.abs() > self.y.abs() {
504            if self.x.is_sign_positive() {
505                Dir::East
506            } else {
507                Dir::West
508            }
509        } else {
510            if self.y.is_sign_positive() {
511                Dir::South
512            } else {
513                Dir::North
514            }
515        }
516    }
517
518    pub fn diag_dir(self) -> DiagDir {
519        if self.x.is_sign_positive() {
520            if self.y.is_sign_positive() {
521                DiagDir::SouthEast
522            } else {
523                DiagDir::NorthEast
524            }
525        } else {
526            if self.y.is_sign_positive() {
527                DiagDir::SouthWest
528            } else {
529                DiagDir::NorthWest
530            }
531        }
532    }
533}
534
535// Based on https://golang.org/pkg/image/#Rectangle
536#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
537pub struct Rectangle {
538    pub min: Point,
539    pub max: Point,
540}
541
542#[macro_export]
543macro_rules! rect {
544    ($x0:expr, $y0:expr, $x1:expr, $y1:expr $(,)* ) => {
545        $crate::geom::Rectangle::new(
546            $crate::geom::Point::new($x0, $y0),
547            $crate::geom::Point::new($x1, $y1),
548        )
549    };
550    ($min:expr, $max:expr $(,)* ) => {
551        $crate::geom::Rectangle::new($min, $max)
552    };
553}
554
555impl fmt::Display for Rectangle {
556    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
557        write!(
558            f,
559            "[{}, {}, {}, {}]",
560            self.min.x, self.min.y, self.max.x, self.max.y
561        )
562    }
563}
564
565impl Rectangle {
566    pub fn new(min: Point, max: Point) -> Rectangle {
567        Rectangle { min, max }
568    }
569
570    pub fn from_point(pt: Point) -> Rectangle {
571        Rectangle {
572            min: pt,
573            max: pt + 1,
574        }
575    }
576
577    pub fn from_disk(center: Point, radius: i32) -> Rectangle {
578        Rectangle {
579            min: center - radius,
580            max: center + radius,
581        }
582    }
583
584    pub fn from_segment(start: Point, end: Point, start_radius: i32, end_radius: i32) -> Rectangle {
585        let x_min = (start.x - start_radius).min(end.x - end_radius);
586        let x_max = (start.x + start_radius).max(end.x + end_radius);
587        let y_min = (start.y - start_radius).min(end.y - end_radius);
588        let y_max = (start.y + start_radius).max(end.y + end_radius);
589        Rectangle {
590            min: pt!(x_min, y_min),
591            max: pt!(x_max, y_max),
592        }
593    }
594
595    pub fn to_boundary(&self) -> Boundary {
596        Boundary {
597            min: Vec2::new(self.min.x as f32, self.min.y as f32),
598            max: Vec2::new(self.max.x as f32, self.max.y as f32),
599        }
600    }
601
602    pub fn diag2(&self) -> u32 {
603        self.min.dist2(self.max)
604    }
605
606    pub fn includes(&self, pt: Point) -> bool {
607        self.min.x <= pt.x && pt.x < self.max.x && self.min.y <= pt.y && pt.y < self.max.y
608    }
609
610    pub fn contains(&self, rect: &Rectangle) -> bool {
611        rect.min.x >= self.min.x
612            && rect.max.x <= self.max.x
613            && rect.min.y >= self.min.y
614            && rect.max.y <= self.max.y
615    }
616
617    pub fn overlaps(&self, rect: &Rectangle) -> bool {
618        self.min.x < rect.max.x
619            && rect.min.x < self.max.x
620            && self.min.y < rect.max.y
621            && rect.min.y < self.max.y
622    }
623
624    pub fn extends(&self, rect: &Rectangle) -> bool {
625        let dmin = [self.width(), self.height(), rect.width(), rect.height()]
626            .into_iter()
627            .min()
628            .unwrap() as i32
629            / 3;
630
631        // rect is on top of self.
632        if self.min.y >= rect.max.y && self.min.x < rect.max.x && rect.min.x < self.max.x {
633            (self.min.y - rect.max.y) <= dmin
634        // rect is at the right of self.
635        } else if rect.min.x >= self.max.x && self.min.y < rect.max.y && rect.min.y < self.max.y {
636            (rect.min.x - self.max.x) <= dmin
637        // rect is on bottom of self.
638        } else if rect.min.y >= self.max.y && self.min.x < rect.max.x && rect.min.x < self.max.x {
639            (rect.min.y - self.max.y) <= dmin
640        // rect is at the left of self.
641        } else if self.min.x >= rect.max.x && self.min.y < rect.max.y && rect.min.y < self.max.y {
642            (self.min.x - rect.max.x) <= dmin
643        } else {
644            false
645        }
646    }
647
648    pub fn touches(&self, rect: &Rectangle) -> bool {
649        ((self.min.x == rect.max.x
650            || self.max.x == rect.min.x
651            || self.min.x == rect.min.x
652            || self.max.x == rect.max.x)
653            && (self.max.y >= rect.min.y && self.min.y <= rect.max.y))
654            || ((self.min.y == rect.max.y
655                || self.max.y == rect.min.y
656                || self.min.y == rect.min.y
657                || self.max.y == rect.max.y)
658                && (self.max.x >= rect.min.x && self.min.x <= rect.max.x))
659    }
660
661    pub fn merge(&mut self, pt: Point) {
662        if pt.x < self.min.x {
663            self.min.x = pt.x;
664        }
665        if pt.x >= self.max.x {
666            self.max.x = pt.x + 1;
667        }
668        if pt.y < self.min.y {
669            self.min.y = pt.y;
670        }
671        if pt.y >= self.max.y {
672            self.max.y = pt.y + 1;
673        }
674    }
675
676    pub fn absorb(&mut self, rect: &Rectangle) {
677        if self.min.x > rect.min.x {
678            self.min.x = rect.min.x;
679        }
680        if self.max.x < rect.max.x {
681            self.max.x = rect.max.x;
682        }
683        if self.min.y > rect.min.y {
684            self.min.y = rect.min.y;
685        }
686        if self.max.y < rect.max.y {
687            self.max.y = rect.max.y;
688        }
689    }
690
691    pub fn intersection(&self, rect: &Rectangle) -> Option<Rectangle> {
692        if self.overlaps(rect) {
693            Some(Rectangle::new(
694                Point::new(self.min.x.max(rect.min.x), self.min.y.max(rect.min.y)),
695                Point::new(self.max.x.min(rect.max.x), self.max.y.min(rect.max.y)),
696            ))
697        } else {
698            None
699        }
700    }
701
702    pub fn is_empty(&self) -> bool {
703        self.max.x <= self.min.x || self.max.y <= self.min.y
704    }
705
706    #[inline]
707    pub fn width(&self) -> u32 {
708        (self.max.x - self.min.x) as u32
709    }
710
711    #[inline]
712    pub fn height(&self) -> u32 {
713        (self.max.y - self.min.y) as u32
714    }
715
716    #[inline]
717    pub fn ratio(&self) -> f32 {
718        self.width() as f32 / self.height() as f32
719    }
720
721    #[inline]
722    pub fn area(&self) -> u32 {
723        self.width() * self.height()
724    }
725
726    #[inline]
727    pub fn center(&self) -> Point {
728        (self.min + self.max) / 2
729    }
730
731    pub fn grow(&mut self, edges: &Edge) {
732        self.min.x -= edges.left;
733        self.min.y -= edges.top;
734        self.max.x += edges.right;
735        self.max.y += edges.bottom;
736    }
737
738    pub fn shrink(&mut self, edges: &Edge) {
739        self.min.x += edges.left;
740        self.min.y += edges.top;
741        self.max.x -= edges.right;
742        self.max.y -= edges.bottom;
743    }
744}
745
746impl Default for Rectangle {
747    fn default() -> Self {
748        Rectangle::new(Point::default(), Point::default())
749    }
750}
751
752impl From<(u32, u32)> for Rectangle {
753    fn from(dims: (u32, u32)) -> Rectangle {
754        Rectangle::new(Point::new(0, 0), Point::new(dims.0 as i32, dims.1 as i32))
755    }
756}
757
758impl PartialOrd for Rectangle {
759    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
760        Some(self.cmp(other))
761    }
762}
763
764impl Ord for Rectangle {
765    fn cmp(&self, other: &Self) -> Ordering {
766        if self.min.y >= other.max.y {
767            Ordering::Greater
768        } else if self.max.y <= other.min.y {
769            Ordering::Less
770        } else {
771            if self.min.x >= other.max.x {
772                Ordering::Greater
773            } else if self.max.x <= other.min.x {
774                Ordering::Less
775            } else {
776                Ordering::Equal
777            }
778        }
779    }
780}
781
782impl Add for Point {
783    type Output = Point;
784    fn add(self, rhs: Point) -> Point {
785        Point {
786            x: self.x + rhs.x,
787            y: self.y + rhs.y,
788        }
789    }
790}
791
792impl AddAssign for Point {
793    fn add_assign(&mut self, rhs: Point) {
794        self.x += rhs.x;
795        self.y += rhs.y;
796    }
797}
798
799impl Sub for Point {
800    type Output = Point;
801    fn sub(self, rhs: Point) -> Point {
802        Point {
803            x: self.x - rhs.x,
804            y: self.y - rhs.y,
805        }
806    }
807}
808
809impl SubAssign for Point {
810    fn sub_assign(&mut self, rhs: Point) {
811        self.x -= rhs.x;
812        self.y -= rhs.y;
813    }
814}
815
816impl Mul<Point> for Point {
817    type Output = Point;
818    fn mul(self, rhs: Point) -> Point {
819        Point {
820            x: self.x * rhs.x,
821            y: self.y * rhs.y,
822        }
823    }
824}
825
826impl MulAssign<Point> for Point {
827    fn mul_assign(&mut self, rhs: Point) {
828        self.x *= rhs.x;
829        self.y *= rhs.y;
830    }
831}
832
833impl Div<Point> for Point {
834    type Output = Point;
835    fn div(self, rhs: Point) -> Point {
836        Point {
837            x: self.x / rhs.x,
838            y: self.y / rhs.y,
839        }
840    }
841}
842
843impl DivAssign<Point> for Point {
844    fn div_assign(&mut self, rhs: Point) {
845        self.x /= rhs.x;
846        self.y /= rhs.y;
847    }
848}
849
850impl Add<i32> for Point {
851    type Output = Point;
852    fn add(self, rhs: i32) -> Point {
853        Point {
854            x: self.x + rhs,
855            y: self.y + rhs,
856        }
857    }
858}
859
860impl Add<Point> for i32 {
861    type Output = Point;
862    fn add(self, rhs: Point) -> Point {
863        Point {
864            x: self + rhs.x,
865            y: self + rhs.y,
866        }
867    }
868}
869
870impl AddAssign<i32> for Point {
871    fn add_assign(&mut self, rhs: i32) {
872        self.x += rhs;
873        self.y += rhs;
874    }
875}
876
877impl Sub<i32> for Point {
878    type Output = Point;
879    fn sub(self, rhs: i32) -> Point {
880        Point {
881            x: self.x - rhs,
882            y: self.y - rhs,
883        }
884    }
885}
886
887impl Sub<Point> for i32 {
888    type Output = Point;
889    fn sub(self, rhs: Point) -> Point {
890        Point {
891            x: self - rhs.x,
892            y: self - rhs.y,
893        }
894    }
895}
896
897impl SubAssign<i32> for Point {
898    fn sub_assign(&mut self, rhs: i32) {
899        self.x -= rhs;
900        self.y -= rhs;
901    }
902}
903
904impl Mul<i32> for Point {
905    type Output = Point;
906    fn mul(self, rhs: i32) -> Point {
907        Point {
908            x: self.x * rhs,
909            y: self.y * rhs,
910        }
911    }
912}
913
914impl Mul<Point> for i32 {
915    type Output = Point;
916    fn mul(self, rhs: Point) -> Point {
917        Point {
918            x: self * rhs.x,
919            y: self * rhs.y,
920        }
921    }
922}
923
924impl MulAssign<i32> for Point {
925    fn mul_assign(&mut self, rhs: i32) {
926        self.x *= rhs;
927        self.y *= rhs;
928    }
929}
930
931impl Div<i32> for Point {
932    type Output = Point;
933    fn div(self, rhs: i32) -> Point {
934        Point {
935            x: self.x / rhs,
936            y: self.y / rhs,
937        }
938    }
939}
940
941impl Div<Point> for i32 {
942    type Output = Point;
943    fn div(self, rhs: Point) -> Point {
944        Point {
945            x: self / rhs.x,
946            y: self / rhs.y,
947        }
948    }
949}
950
951impl DivAssign<i32> for Point {
952    fn div_assign(&mut self, rhs: i32) {
953        self.x /= rhs;
954        self.y /= rhs;
955    }
956}
957
958impl Add<Point> for Rectangle {
959    type Output = Rectangle;
960    fn add(self, rhs: Point) -> Rectangle {
961        Rectangle {
962            min: self.min + rhs,
963            max: self.max + rhs,
964        }
965    }
966}
967
968impl AddAssign<Point> for Rectangle {
969    fn add_assign(&mut self, rhs: Point) {
970        self.min += rhs;
971        self.max += rhs;
972    }
973}
974
975impl Sub<Point> for Rectangle {
976    type Output = Rectangle;
977    fn sub(self, rhs: Point) -> Rectangle {
978        Rectangle {
979            min: self.min - rhs,
980            max: self.max - rhs,
981        }
982    }
983}
984
985impl SubAssign<Point> for Rectangle {
986    fn sub_assign(&mut self, rhs: Point) {
987        self.min -= rhs;
988        self.max -= rhs;
989    }
990}
991
992impl Add for Vec2 {
993    type Output = Vec2;
994    fn add(self, rhs: Vec2) -> Vec2 {
995        Vec2 {
996            x: self.x + rhs.x,
997            y: self.y + rhs.y,
998        }
999    }
1000}
1001
1002impl AddAssign for Vec2 {
1003    fn add_assign(&mut self, rhs: Vec2) {
1004        self.x += rhs.x;
1005        self.y += rhs.y;
1006    }
1007}
1008
1009impl Sub for Vec2 {
1010    type Output = Vec2;
1011    fn sub(self, rhs: Vec2) -> Vec2 {
1012        Vec2 {
1013            x: self.x - rhs.x,
1014            y: self.y - rhs.y,
1015        }
1016    }
1017}
1018
1019impl SubAssign for Vec2 {
1020    fn sub_assign(&mut self, rhs: Vec2) {
1021        self.x -= rhs.x;
1022        self.y -= rhs.y;
1023    }
1024}
1025
1026impl Mul<Vec2> for Vec2 {
1027    type Output = Vec2;
1028    fn mul(self, rhs: Vec2) -> Vec2 {
1029        Vec2 {
1030            x: self.x * rhs.x,
1031            y: self.y * rhs.y,
1032        }
1033    }
1034}
1035
1036impl MulAssign<Vec2> for Vec2 {
1037    fn mul_assign(&mut self, rhs: Vec2) {
1038        self.x *= rhs.x;
1039        self.y *= rhs.y;
1040    }
1041}
1042
1043impl Div<Vec2> for Vec2 {
1044    type Output = Vec2;
1045    fn div(self, rhs: Vec2) -> Vec2 {
1046        Vec2 {
1047            x: self.x / rhs.x,
1048            y: self.y / rhs.y,
1049        }
1050    }
1051}
1052
1053impl DivAssign<Vec2> for Vec2 {
1054    fn div_assign(&mut self, rhs: Vec2) {
1055        self.x /= rhs.x;
1056        self.y /= rhs.y;
1057    }
1058}
1059
1060impl Add<f32> for Vec2 {
1061    type Output = Vec2;
1062    fn add(self, rhs: f32) -> Vec2 {
1063        Vec2 {
1064            x: self.x + rhs,
1065            y: self.y + rhs,
1066        }
1067    }
1068}
1069
1070impl Add<Vec2> for f32 {
1071    type Output = Vec2;
1072    fn add(self, rhs: Vec2) -> Vec2 {
1073        Vec2 {
1074            x: self + rhs.x,
1075            y: self + rhs.y,
1076        }
1077    }
1078}
1079
1080impl AddAssign<f32> for Vec2 {
1081    fn add_assign(&mut self, rhs: f32) {
1082        self.x += rhs;
1083        self.y += rhs;
1084    }
1085}
1086
1087impl Sub<f32> for Vec2 {
1088    type Output = Vec2;
1089    fn sub(self, rhs: f32) -> Vec2 {
1090        Vec2 {
1091            x: self.x - rhs,
1092            y: self.y - rhs,
1093        }
1094    }
1095}
1096
1097impl Sub<Vec2> for f32 {
1098    type Output = Vec2;
1099    fn sub(self, rhs: Vec2) -> Vec2 {
1100        Vec2 {
1101            x: self - rhs.x,
1102            y: self - rhs.y,
1103        }
1104    }
1105}
1106
1107impl SubAssign<f32> for Vec2 {
1108    fn sub_assign(&mut self, rhs: f32) {
1109        self.x -= rhs;
1110        self.y -= rhs;
1111    }
1112}
1113
1114impl Mul<f32> for Vec2 {
1115    type Output = Vec2;
1116    fn mul(self, rhs: f32) -> Vec2 {
1117        Vec2 {
1118            x: self.x * rhs,
1119            y: self.y * rhs,
1120        }
1121    }
1122}
1123
1124impl Mul<Vec2> for f32 {
1125    type Output = Vec2;
1126    fn mul(self, rhs: Vec2) -> Vec2 {
1127        Vec2 {
1128            x: self * rhs.x,
1129            y: self * rhs.y,
1130        }
1131    }
1132}
1133
1134impl MulAssign<f32> for Vec2 {
1135    fn mul_assign(&mut self, rhs: f32) {
1136        self.x *= rhs;
1137        self.y *= rhs;
1138    }
1139}
1140
1141impl Div<f32> for Vec2 {
1142    type Output = Vec2;
1143    fn div(self, rhs: f32) -> Vec2 {
1144        Vec2 {
1145            x: self.x / rhs,
1146            y: self.y / rhs,
1147        }
1148    }
1149}
1150
1151impl Div<Vec2> for f32 {
1152    type Output = Vec2;
1153    fn div(self, rhs: Vec2) -> Vec2 {
1154        Vec2 {
1155            x: self / rhs.x,
1156            y: self / rhs.y,
1157        }
1158    }
1159}
1160
1161impl DivAssign<f32> for Vec2 {
1162    fn div_assign(&mut self, rhs: f32) {
1163        self.x /= rhs;
1164        self.y /= rhs;
1165    }
1166}
1167
1168#[derive(Debug, Copy, Clone)]
1169pub struct Boundary {
1170    pub min: Vec2,
1171    pub max: Vec2,
1172}
1173
1174impl Boundary {
1175    pub fn new(min: Vec2, max: Vec2) -> Boundary {
1176        Boundary { min, max }
1177    }
1178
1179    pub fn to_rect(&self) -> Rectangle {
1180        Rectangle {
1181            min: Point::new(self.min.x.floor() as i32, self.min.y.floor() as i32),
1182            max: Point::new(self.max.x.ceil() as i32, self.max.y.ceil() as i32),
1183        }
1184    }
1185
1186    pub fn overlaps(&self, rect: &Boundary) -> bool {
1187        self.min.x < rect.max.x
1188            && rect.min.x < self.max.x
1189            && self.min.y < rect.max.y
1190            && rect.min.y < self.max.y
1191    }
1192
1193    pub fn contains(&self, rect: &Boundary) -> bool {
1194        rect.min.x >= self.min.x
1195            && rect.max.x <= self.max.x
1196            && rect.min.y >= self.min.y
1197            && rect.max.y <= self.max.y
1198    }
1199
1200    pub fn width(&self) -> f32 {
1201        self.max.x - self.min.x
1202    }
1203
1204    pub fn height(&self) -> f32 {
1205        self.max.y - self.min.y
1206    }
1207}
1208
1209#[macro_export]
1210macro_rules! bndr {
1211    ($x0:expr, $y0:expr, $x1:expr, $y1:expr $(,)* ) => {
1212        $crate::geom::Boundary::new(
1213            $crate::geom::Vec2::new($x0, $y0),
1214            $crate::geom::Vec2::new($x1, $y1),
1215        )
1216    };
1217    ($min:expr, $max:expr $(,)* ) => {
1218        $crate::geom::Boundary::new($min, $max)
1219    };
1220}
1221
1222impl Into<Rectangle> for Boundary {
1223    fn into(self) -> Rectangle {
1224        Rectangle {
1225            min: Point::new(self.min.x.floor() as i32, self.min.y.floor() as i32),
1226            max: Point::new(self.max.x.ceil() as i32, self.max.y.ceil() as i32),
1227        }
1228    }
1229}
1230
1231impl Into<Boundary> for Rectangle {
1232    fn into(self) -> Boundary {
1233        Boundary {
1234            min: Vec2::new(self.min.x as f32, self.min.y as f32),
1235            max: Vec2::new(self.max.x as f32, self.max.y as f32),
1236        }
1237    }
1238}
1239
1240impl Mul<f32> for Boundary {
1241    type Output = Boundary;
1242    fn mul(self, rhs: f32) -> Boundary {
1243        Boundary {
1244            min: self.min * rhs,
1245            max: self.max * rhs,
1246        }
1247    }
1248}
1249
1250impl Mul<Boundary> for f32 {
1251    type Output = Boundary;
1252    fn mul(self, rhs: Boundary) -> Boundary {
1253        Boundary {
1254            min: self * rhs.min,
1255            max: self * rhs.max,
1256        }
1257    }
1258}
1259
1260impl MulAssign<f32> for Boundary {
1261    fn mul_assign(&mut self, rhs: f32) {
1262        self.min *= rhs;
1263        self.max *= rhs;
1264    }
1265}
1266
1267impl Div<f32> for Boundary {
1268    type Output = Boundary;
1269    fn div(self, rhs: f32) -> Boundary {
1270        Boundary {
1271            min: self.min / rhs,
1272            max: self.max / rhs,
1273        }
1274    }
1275}
1276
1277impl Div<Boundary> for f32 {
1278    type Output = Boundary;
1279    fn div(self, rhs: Boundary) -> Boundary {
1280        Boundary {
1281            min: rhs.min / self,
1282            max: rhs.max / self,
1283        }
1284    }
1285}
1286
1287impl DivAssign<f32> for Boundary {
1288    fn div_assign(&mut self, rhs: f32) {
1289        self.min /= rhs;
1290        self.max /= rhs;
1291    }
1292}
1293
1294#[derive(Debug, Copy, Clone)]
1295pub enum Region {
1296    Corner(DiagDir),
1297    Strip(Dir),
1298    Center,
1299}
1300
1301impl Region {
1302    // pt ∈ rect
1303    // 0.0 < {corner,strip}_width < 1.0
1304    pub fn from_point(pt: Point, rect: Rectangle, strip_width: f32, corner_width: f32) -> Region {
1305        let w = rect.width() as i32;
1306        let h = rect.height() as i32;
1307        let m = w.min(h) as f32 / 2.0;
1308
1309        let d = (m * corner_width).max(1.0) as i32;
1310        let x1 = rect.min.x + d - 1;
1311        let x2 = rect.max.x - d;
1312
1313        // The four corners are on top of all the other regions.
1314        if pt.x <= x1 {
1315            let dx = x1 - pt.x;
1316            if pt.y <= rect.min.y + dx {
1317                return Region::Corner(DiagDir::NorthWest);
1318            } else if pt.y >= rect.max.y - 1 - dx {
1319                return Region::Corner(DiagDir::SouthWest);
1320            }
1321        } else if pt.x >= x2 {
1322            let dx = pt.x - x2;
1323            if pt.y <= rect.min.y + dx {
1324                return Region::Corner(DiagDir::NorthEast);
1325            } else if pt.y >= rect.max.y - 1 - dx {
1326                return Region::Corner(DiagDir::SouthEast);
1327            }
1328        }
1329
1330        let d = (m * strip_width).max(1.0) as i32;
1331        let x1 = rect.min.x + d - 1;
1332        let x2 = rect.max.x - d;
1333        let y1 = rect.min.y + d - 1;
1334        let y2 = rect.max.y - d;
1335
1336        // The four strips are above the center region.
1337        // Each of the diagonals between the strips has to belong to one of the strip.
1338        if pt.x <= x1 {
1339            let dx = pt.x - rect.min.x;
1340            if pt.y >= rect.min.y + dx && pt.y < rect.max.y - 1 - dx {
1341                return Region::Strip(Dir::West);
1342            }
1343        } else if pt.x >= x2 {
1344            let dx = rect.max.x - 1 - pt.x;
1345            if pt.y > rect.min.y + dx && pt.y <= rect.max.y - 1 - dx {
1346                return Region::Strip(Dir::East);
1347            }
1348        }
1349
1350        if pt.y <= y1 {
1351            let dy = pt.y - rect.min.y;
1352            if pt.x > rect.min.x + dy && pt.y <= rect.max.x - 1 - dy {
1353                return Region::Strip(Dir::North);
1354            }
1355        } else if pt.y >= y2 {
1356            let dy = rect.max.y - 1 - pt.y;
1357            if pt.x >= rect.min.x + dy && pt.x < rect.max.x - 1 - dy {
1358                return Region::Strip(Dir::South);
1359            }
1360        }
1361
1362        // The center rectangle is below everything else.
1363        Region::Center
1364    }
1365}
1366
1367#[cfg(test)]
1368mod tests {
1369    use super::{divide, LinearDir};
1370
1371    #[test]
1372    fn test_linear_dir_opposite() {
1373        assert_eq!(LinearDir::Forward.opposite(), LinearDir::Backward);
1374        assert_eq!(LinearDir::Backward.opposite(), LinearDir::Forward);
1375    }
1376
1377    #[test]
1378    fn overlaping_rectangles() {
1379        let a = rect![2, 2, 10, 10];
1380        let b = rect![2, 5, 3, 6];
1381        let c = rect![1, 3, 2, 7];
1382        let d = rect![9, 9, 12, 12];
1383        let e = rect![4, 3, 5, 6];
1384        assert!(b.overlaps(&a));
1385        assert!(!c.overlaps(&a));
1386        assert!(d.overlaps(&a));
1387        assert!(e.overlaps(&a));
1388        assert!(a.overlaps(&e));
1389    }
1390
1391    #[test]
1392    fn contained_rectangles() {
1393        let a = rect![2, 2, 10, 10];
1394        let b = rect![4, 3, 5, 6];
1395        let c = rect![4, 3, 12, 9];
1396        assert!(a.contains(&b));
1397        assert!(!b.contains(&a));
1398        assert!(!a.contains(&c));
1399        assert!(c.contains(&b));
1400    }
1401
1402    #[test]
1403    fn extended_rectangles() {
1404        let a = rect![30, 30, 60, 60];
1405        let b = rect![23, 0, 67, 28];
1406        let c = rect![60, 40, 110, 80];
1407        let d = rect![26, 62, 55, 96];
1408        let e = rect![0, 25, 29, 60];
1409        assert!(b.extends(&a));
1410        assert!(c.extends(&a));
1411        assert!(d.extends(&a));
1412        assert!(e.extends(&a));
1413        assert!(!b.extends(&d));
1414        assert!(!c.extends(&e));
1415        assert!(!e.extends(&b));
1416    }
1417
1418    #[test]
1419    fn divide_integers() {
1420        let a: i32 = 73;
1421        let b: i32 = 23;
1422        let v = divide(a, b);
1423        let s: i32 = v.iter().sum();
1424        assert_eq!(v.len(), b as usize);
1425        assert_eq!(s, a);
1426        assert_eq!(v.iter().max(), Some(&4));
1427        assert_eq!(v.iter().min(), Some(&3));
1428    }
1429
1430    #[test]
1431    fn point_rectangle_distance() {
1432        let pt1 = pt!(4, 5);
1433        let pt2 = pt!(1, 2);
1434        let pt3 = pt!(3, 8);
1435        let pt4 = pt!(8, 6);
1436        let pt5 = pt!(7, 4);
1437        let rect = rect![2, 3, 7, 6];
1438        assert_eq!(pt1.rdist2(&rect), 0);
1439        assert_eq!(pt2.rdist2(&rect), 2);
1440        assert_eq!(pt3.rdist2(&rect), 9);
1441        assert_eq!(pt4.rdist2(&rect), 5);
1442        assert_eq!(pt5.rdist2(&rect), 1);
1443    }
1444}