use std::cmp::Ordering;
use crate::locatable::{Locatable, Location};
use crate::operations::Orient;
use crate::oriented::Orientation;
use crate::seidel::edge::Edge;
use crate::seidel::trapezoid::Trapezoid;
use super::node::Node;
use super::trapezoidation::Trapezoidation;
impl Node {
fn locate_trapezoid<'a, Point: PartialOrd>(
&'a self,
point: &Point,
edges: &[Edge],
endpoints: &[Point],
nodes: &'a [Node],
) -> Option<&'a Trapezoid>
where
for<'b> &'b Point: Orient,
{
match self {
Self::Leaf { trapezoid } => Some(trapezoid),
Self::X {
left_node_index,
right_node_index,
point_index,
} => point.partial_cmp(&endpoints[*point_index]).and_then(
|ordering| match ordering {
Ordering::Less => nodes[*left_node_index]
.locate_trapezoid(point, edges, endpoints, nodes),
Ordering::Greater => nodes[*right_node_index]
.locate_trapezoid(point, edges, endpoints, nodes),
Ordering::Equal => None,
},
),
Self::Y {
above_node_index,
below_node_index,
edge_index,
} => match edges[*edge_index].orientation_of(point, endpoints) {
Orientation::Counterclockwise => nodes[*above_node_index]
.locate_trapezoid(point, edges, endpoints, nodes),
Orientation::Clockwise => nodes[*below_node_index]
.locate_trapezoid(point, edges, endpoints, nodes),
Orientation::Collinear => None,
},
}
}
}
impl<Point: PartialOrd> Locatable<&Point> for &Trapezoidation<Point>
where
for<'a> &'a Point: Orient,
{
fn locate(self, point: &Point) -> Location {
match self.get_root().locate_trapezoid(
point,
self.get_edges(),
self.get_endpoints(),
self.get_nodes(),
) {
Some(trapezoid) => {
if trapezoid.is_component {
Location::Interior
} else {
Location::Exterior
}
}
None => Location::Boundary,
}
}
}