pub fn polygons_intersection(
poly1: &[Point2<f32>],
poly2: &[Point2<f32>],
out: impl FnMut(Option<PolylinePointLocation>, Option<PolylinePointLocation>),
) -> Result<(), PolygonsIntersectionError>Expand description
Computes the intersection of two possibly non-convex polygons with closure-based output.
This is the closure-based version of polygons_intersection_points, providing more
control over how intersection vertices are processed. It handles non-convex (concave)
polygons but requires they do not self-intersect.
§Arguments
poly1- First polygon as a slice of verticespoly2- Second polygon as a slice of verticesout- Closure called for each intersection vertex or component separator
§Closure Arguments
The closure receives (Option<PolylinePointLocation>, Option<PolylinePointLocation>):
- When both are
Some: An edge-edge intersection point - When one is
Some: A vertex from one polygon inside the other - When both are
None: Marks the end of a connected component
§Algorithm
This function uses a graph-based traversal algorithm:
- Finds all edge-edge intersection points between the two polygons
- Builds a graph where vertices are intersection points
- Traverses the graph, alternating between polygons at intersection points
- Outputs vertices that form the intersection boundary
§Examples
§Example 1: Collecting intersection points
let pentagon = vec![
Point2::new(1.0, 0.0),
Point2::new(0.309, 0.951),
Point2::new(-0.809, 0.588),
Point2::new(-0.809, -0.588),
Point2::new(0.309, -0.951),
];
let square = vec![
Point2::new(-0.5, -0.5),
Point2::new(0.5, -0.5),
Point2::new(0.5, 0.5),
Point2::new(-0.5, 0.5),
];
let mut components = Vec::new();
let mut current_component = Vec::new();
polygons_intersection(&pentagon, &square, |loc1, loc2| {
if loc1.is_none() && loc2.is_none() {
// End of a component
if !current_component.is_empty() {
components.push(std::mem::take(&mut current_component));
}
} else if let Some(loc) = loc1 {
current_component.push(loc.to_point(&pentagon));
} else if let Some(loc) = loc2 {
current_component.push(loc.to_point(&square));
}
}).unwrap();
// Should have at least one intersection component
assert!(!components.is_empty());§Example 2: Counting intersection vertices
let hexagon = vec![
Point2::new(2.0, 0.0),
Point2::new(1.0, 1.732),
Point2::new(-1.0, 1.732),
Point2::new(-2.0, 0.0),
Point2::new(-1.0, -1.732),
Point2::new(1.0, -1.732),
];
let circle_approx = vec![
Point2::new(1.0, 0.0),
Point2::new(0.707, 0.707),
Point2::new(0.0, 1.0),
Point2::new(-0.707, 0.707),
Point2::new(-1.0, 0.0),
Point2::new(-0.707, -0.707),
Point2::new(0.0, -1.0),
Point2::new(0.707, -0.707),
];
let mut vertex_count = 0;
polygons_intersection(&hexagon, &circle_approx, |loc1, loc2| {
if loc1.is_some() || loc2.is_some() {
vertex_count += 1;
}
}).unwrap();
assert!(vertex_count > 0);§Errors
Returns PolygonsIntersectionError::InfiniteLoop if the polygons are ill-formed.
§See Also
polygons_intersection_points- Simpler vector-based outputconvex_polygons_intersection- Faster version for convex polygons