use std::ops;
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct InputRelation {
pub contains: bool,
pub strict_contains: bool,
pub contained: bool,
pub strict_contained: bool,
pub intersect: bool,
pub disjoint: bool,
pub early_exit: bool,
}
impl InputRelation {
pub fn all() -> Self {
Self {
contains: true,
strict_contains: true,
contained: true,
strict_contained: true,
intersect: true,
disjoint: true,
early_exit: false,
}
}
pub fn any() -> Self {
Self {
contains: true,
strict_contains: true,
contained: true,
strict_contained: true,
intersect: true,
disjoint: true,
early_exit: true,
}
}
pub fn swap_contains_relation(mut self) -> Self {
std::mem::swap(&mut self.contains, &mut self.contained);
std::mem::swap(&mut self.strict_contains, &mut self.strict_contained);
self
}
pub fn none() -> Self {
Self::default()
}
pub fn to_false(self) -> OutputRelation {
OutputRelation::false_from_input(self)
}
pub fn to_true(self) -> OutputRelation {
OutputRelation::true_from_input(self)
}
pub fn strip_strict(mut self) -> Self {
self.strict_contains = false;
self.strict_contained = false;
self
}
pub fn strip_strict_contained(mut self) -> Self {
self.strict_contained = false;
self
}
pub fn strip_disjoint(mut self) -> Self {
self.disjoint = false;
self
}
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct OutputRelation {
pub contains: Option<bool>,
pub strict_contains: Option<bool>,
pub contained: Option<bool>,
pub strict_contained: Option<bool>,
pub intersect: Option<bool>,
pub disjoint: Option<bool>,
}
impl OutputRelation {
pub(crate) fn false_from_input(relation: InputRelation) -> Self {
Self {
contains: relation.contains.then_some(false),
strict_contains: relation.strict_contains.then_some(false),
contained: relation.contained.then_some(false),
strict_contained: relation.strict_contained.then_some(false),
intersect: relation.intersect.then_some(false),
disjoint: relation.disjoint.then_some(false),
}
}
pub(crate) fn true_from_input(relation: InputRelation) -> Self {
Self {
contains: relation.contains.then_some(true),
strict_contains: relation.strict_contains.then_some(true),
contained: relation.contained.then_some(true),
strict_contained: relation.strict_contained.then_some(true),
intersect: relation.intersect.then_some(true),
disjoint: relation.disjoint.then_some(true),
}
}
pub(crate) fn make_contains_if_set(mut self) -> Self {
self.contains = self.contains.map(|_| true);
self
}
pub(crate) fn make_strict_contains_if_set(mut self) -> Self {
self.strict_contains = self.strict_contains.map(|_| true);
self.make_contains_if_set()
}
pub(crate) fn make_contained_if_set(mut self) -> Self {
self.contained = self.contained.map(|_| true);
self
}
pub(crate) fn make_strict_contained_if_set(mut self) -> Self {
self.strict_contained = self.strict_contained.map(|_| true);
self.make_contained_if_set()
}
pub(crate) fn make_intersect_if_set(mut self) -> Self {
self.intersect = self.intersect.map(|_| true);
self
}
pub(crate) fn make_disjoint_if_set(mut self) -> Self {
self.disjoint = self.disjoint.map(|_| true);
self
}
pub(crate) fn strip_strict(mut self) -> Self {
self.strict_contains = None;
self.strict_contained = None;
self
}
pub fn any_relation(&self) -> bool {
(!self.disjoint.unwrap_or_default())
&& (self.contains.unwrap_or_default()
|| self.strict_contains.unwrap_or_default()
|| self.contained.unwrap_or_default()
|| self.strict_contained.unwrap_or_default()
|| self.intersect.unwrap_or_default())
}
pub fn swap_contains_relation(mut self) -> Self {
std::mem::swap(&mut self.contains, &mut self.contained);
std::mem::swap(&mut self.strict_contains, &mut self.strict_contained);
self
}
}
impl ops::BitOr for OutputRelation {
type Output = Self;
fn bitor(self, other: Self) -> Self::Output {
let Self {
mut contains,
mut strict_contains,
mut contained,
mut strict_contained,
mut intersect,
mut disjoint,
} = self;
if let Some(ref mut s) = contains {
*s |= other.contains.unwrap_or_default()
}
if let Some(ref mut s) = strict_contains {
*s |= other.strict_contains.unwrap_or_default()
}
if let Some(ref mut s) = contained {
*s |= other.contained.unwrap_or_default()
}
if let Some(ref mut s) = strict_contained {
*s |= other.strict_contained.unwrap_or_default()
}
if let Some(ref mut s) = intersect {
*s |= other.intersect.unwrap_or_default()
}
if let Some(ref mut s) = disjoint {
*s |= other.disjoint.unwrap_or_default()
}
Self {
contains,
strict_contains,
contained,
strict_contained,
intersect,
disjoint,
}
}
}
impl ops::BitOrAssign for OutputRelation {
fn bitor_assign(&mut self, rhs: Self) {
*self = *self | rhs;
}
}
pub trait RelationBetweenShapes<Other: ?Sized> {
fn relation(&self, other: &Other, relation: InputRelation) -> OutputRelation;
fn all_relation(&self, other: &Other) -> OutputRelation {
self.relation(other, InputRelation::all())
}
fn any_relation(&self, other: &Other) -> OutputRelation {
self.relation(other, InputRelation::any())
}
fn contains(&self, other: &Other) -> bool {
self.relation(
other,
InputRelation {
contains: true,
early_exit: true,
..Default::default()
},
)
.contains
.unwrap_or_default()
}
fn strict_contains(&self, other: &Other) -> bool {
self.relation(
other,
InputRelation {
strict_contains: true,
early_exit: true,
..Default::default()
},
)
.strict_contains
.unwrap_or_default()
}
fn contained(&self, other: &Other) -> bool {
self.relation(
other,
InputRelation {
contained: true,
early_exit: true,
..Default::default()
},
)
.contained
.unwrap_or_default()
}
fn strict_contained(&self, other: &Other) -> bool {
self.relation(
other,
InputRelation {
strict_contained: true,
early_exit: true,
..Default::default()
},
)
.strict_contained
.unwrap_or_default()
}
fn intersects(&self, other: &Other) -> bool {
self.relation(
other,
InputRelation {
intersect: true,
early_exit: true,
..Default::default()
},
)
.intersect
.unwrap_or_default()
}
fn disjoint(&self, other: &Other) -> bool {
self.relation(
other,
InputRelation {
disjoint: true,
early_exit: true,
..Default::default()
},
)
.disjoint
.unwrap_or_default()
}
}