geometry/
contains.rs

1//! Traits for checking whether a shape contains another shape.
2
3use serde::{Deserialize, Serialize};
4
5/// Ways in which an inner shape can be contained within an enclosing shape.
6#[derive(
7    Debug, Default, Clone, Copy, Serialize, Deserialize, Hash, PartialEq, Eq, Ord, PartialOrd,
8)]
9pub enum Containment {
10    /// The enclosing shape does not contain any part of the inner shape.
11    #[default]
12    None,
13    /// The shape is partially contained in the enclosing shape.
14    Partial,
15    /// The shape is fully contained in the enclosing shape.
16    Full,
17}
18
19/// Provides information on whether a shape contains another shape.
20pub trait Contains<T> {
21    /// Returns a [`Containment`] indicating how `other` is enclosed within this shape.
22    ///
23    /// * If `other` is entirely contained, returns [`Containment::Full`].
24    /// * If `other` is only partially contained, returns [`Containment::Partial`].
25    /// * If no part of `other` lies within this shape, returns [`Containment::None`].
26    fn contains(&self, other: &T) -> Containment;
27
28    /// Returns true if `other` is fully enclosed in this shape.
29    #[inline]
30    fn encloses(&self, other: &T) -> bool {
31        self.contains(other).is_full()
32    }
33
34    /// Returns true if `other` is fully or partially enclosed in this shape.
35    #[inline]
36    fn partially_intersects(&self, other: &T) -> bool {
37        self.contains(other).intersects()
38    }
39}
40
41impl Containment {
42    /// Returns true when fully contained.
43    #[inline]
44    pub fn is_full(&self) -> bool {
45        matches!(self, Self::Full)
46    }
47
48    /// Returns true if there is **at least** partial containment.
49    #[inline]
50    pub fn intersects(&self) -> bool {
51        matches!(self, Self::Full | Self::Partial)
52    }
53
54    /// Returns true if there is **only** partial containment.
55    #[inline]
56    pub fn only_partially_intersects(&self) -> bool {
57        matches!(self, Self::Partial)
58    }
59
60    /// Returns true if there is no containment.
61    #[inline]
62    pub fn is_none(&self) -> bool {
63        matches!(self, Self::None)
64    }
65}