i_overlay 7.0.2

Boolean Operations for 2D Polygons: Supports intersection, union, difference, xor, and self-intersections for all polygon varieties.
Documentation
use crate::build::builder::GraphBuilder;
use crate::core::edge_data::OverlayEdgeData;
use crate::core::extract::BooleanExtractionBuffer;
use crate::core::fill_rule::FillRule;
use crate::core::graph::OverlayNode;
use crate::core::overlay::{IntOverlayOptions, ShapeType};
use crate::core::overlay_rule::OverlayRule;
use crate::core::solver::Solver;
use crate::segm::boolean::ShapeCountBoolean;
use crate::segm::segment::Segment;
use crate::split::solver::SplitSolver;
use crate::vector::edge::{DataVectorEdge, DataVectorShape};
use alloc::vec::Vec;
use i_float::int::number::int::IntNumber;
use i_float::int::point::IntPoint;
use i_key_sort::sort::key::SortKey;
use i_tree::{Expiration, LayoutNumber};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct InputEdge<I: IntNumber, D> {
    pub a: IntPoint<I>,
    pub b: IntPoint<I>,
    pub data: D,
}

pub struct EdgeOverlay<I: IntNumber + Expiration, D: OverlayEdgeData> {
    pub solver: Solver,
    pub options: IntOverlayOptions<I::WideUInt>,
    pub boolean_buffer: Option<BooleanExtractionBuffer<I>>,
    data_store: D::Store,
    segments: Vec<Segment<ShapeCountBoolean, I, D>>,
    split_solver: SplitSolver<I>,
    graph_builder: GraphBuilder<ShapeCountBoolean, OverlayNode, I, D>,
}

impl<I, D> EdgeOverlay<I, D>
where
    I: IntNumber + Expiration + LayoutNumber + SortKey,
    D: OverlayEdgeData,
{
    pub fn new(capacity: usize) -> Self {
        Self {
            solver: Default::default(),
            options: IntOverlayOptions::keep_output_points(),
            boolean_buffer: None,
            data_store: Default::default(),
            segments: Vec::with_capacity(capacity),
            split_solver: SplitSolver::new(),
            graph_builder: GraphBuilder::<ShapeCountBoolean, OverlayNode, I, D>::new(),
        }
    }

    pub fn add_edge(&mut self, edge: InputEdge<I, D>, shape_type: ShapeType) {
        if let Some(segment) =
            Segment::try_ab_and_data(edge.a, edge.b, shape_type, edge.data, &mut self.data_store)
        {
            self.segments.push(segment);
        }
    }

    pub fn add_edges<It>(&mut self, edges: It, shape_type: ShapeType)
    where
        It: IntoIterator<Item = InputEdge<I, D>>,
    {
        for edge in edges {
            self.add_edge(edge, shape_type);
        }
    }

    pub fn data_store(&self) -> &D::Store {
        &self.data_store
    }

    pub fn data_store_mut(&mut self) -> &mut D::Store {
        &mut self.data_store
    }

    pub fn into_data_store(self) -> D::Store {
        self.data_store
    }

    pub fn build_vectors(
        &mut self,
        overlay_rule: OverlayRule,
        fill_rule: FillRule,
    ) -> Vec<DataVectorEdge<I, D>> {
        self.split_solver
            .split_segments_with_store(&mut self.segments, &self.solver, &mut self.data_store);
        if self.segments.is_empty() {
            return Vec::new();
        }

        self.graph_builder
            .build_boolean_overlay(
                fill_rule,
                overlay_rule,
                self.options,
                &self.solver,
                &self.segments,
            )
            .extract_vectors_with_store(&mut self.data_store)
    }

    pub fn build_vector_shapes(
        &mut self,
        overlay_rule: OverlayRule,
        fill_rule: FillRule,
    ) -> Vec<DataVectorShape<I, D>> {
        self.split_solver
            .split_segments_with_store(&mut self.segments, &self.solver, &mut self.data_store);
        if self.segments.is_empty() {
            return Vec::new();
        }

        let mut buffer = self.boolean_buffer.take().unwrap_or_default();

        let shapes = self
            .graph_builder
            .build_boolean_overlay(
                fill_rule,
                overlay_rule,
                self.options,
                &self.solver,
                &self.segments,
            )
            .extract_vector_shapes_with_store(overlay_rule, &mut buffer, &mut self.data_store);

        self.boolean_buffer = Some(buffer);

        shapes
    }
}

impl<I, D> EdgeOverlay<I, D>
where
    I: IntNumber + Expiration + LayoutNumber + SortKey,
    D: OverlayEdgeData,
{
    pub fn edges(&self) -> impl Iterator<Item = [IntPoint<I>; 2]> + '_ {
        self.segments.iter().map(|e| [e.x_segment.a, e.x_segment.b])
    }
}