Function polygons_intersection

Source
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 vertices
  • poly2 - Second polygon as a slice of vertices
  • out - 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:

  1. Finds all edge-edge intersection points between the two polygons
  2. Builds a graph where vertices are intersection points
  3. Traverses the graph, alternating between polygons at intersection points
  4. 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