b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 1 | use crate::geom::Rect; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 2 | |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 3 | pub(crate) const LEFT: u8 = 1; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 4 | pub(crate) const RIGHT: u8 = 2; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 5 | pub(crate) const ABOVE: u8 = 4; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 6 | pub(crate) const BELOW: u8 = 8; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 7 | pub(crate) const X_BITS: u8 = LEFT | RIGHT; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 8 | pub(crate) const Y_BITS: u8 = ABOVE | BELOW; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 9 | |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 10 | /// Which ways `a` is apart from `b`. Touching edges count as apart. |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 11 | pub(crate) fn separation(a: &Rect, b: &Rect, eps: f64) -> u8 { |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 12 | let mut s = 0; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 13 | if a.right() <= b.x + eps { |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 14 | s |= LEFT; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 15 | } |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 16 | if b.right() <= a.x + eps { |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 17 | s |= RIGHT; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 18 | } |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 19 | if a.bottom() <= b.y + eps { |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 20 | s |= ABOVE; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 21 | } |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 22 | if b.bottom() <= a.y + eps { |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 23 | s |= BELOW; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 24 | } |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 25 | s |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 26 | } |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 27 | |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 28 | /// Which sides of `a` sit against `b`, at most one gap apart and facing each other. |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 29 | pub(crate) fn adjacency(a: &Rect, b: &Rect, gap: f64, eps: f64) -> u8 { |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 30 | let overlap_x = a.x < b.right() + eps && b.x < a.right() + eps; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 31 | let overlap_y = a.y < b.bottom() + eps && b.y < a.bottom() + eps; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 32 | let near = |d: f64| d.abs() <= gap + eps; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 33 | let mut s = 0; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 34 | if overlap_y && near(b.x - a.right()) { |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 35 | s |= LEFT; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 36 | } |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 37 | if overlap_y && near(a.x - b.right()) { |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 38 | s |= RIGHT; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 39 | } |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 40 | if overlap_x && near(b.y - a.bottom()) { |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 41 | s |= ABOVE; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 42 | } |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 43 | if overlap_x && near(a.y - b.bottom()) { |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 44 | s |= BELOW; |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 45 | } |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 46 | s |
b563d2da1c80 | atagen | 2026-10-16 08:25 UTC | 47 | } |