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::core::edge_data::OverlayEdgeData;
use crate::core::overlay::ShapeType;
use crate::geom::x_segment::XSegment;
use crate::segm::boolean::ShapeCountBoolean;
use crate::segm::winding::WindingCount;
use core::cmp::Ordering;
use i_float::int::number::int::IntNumber;
use i_float::int::point::IntPoint;

pub type SegmentFill = u8;

pub const NONE: SegmentFill = 0;

pub const SUBJ_TOP: SegmentFill = 0b0001;
pub const SUBJ_BOTTOM: SegmentFill = 0b0010;
pub const CLIP_TOP: SegmentFill = 0b0100;
pub const CLIP_BOTTOM: SegmentFill = 0b1000;

pub const SUBJ_BOTH: SegmentFill = SUBJ_TOP | SUBJ_BOTTOM;
pub const CLIP_BOTH: SegmentFill = CLIP_TOP | CLIP_BOTTOM;
pub const BOTH_TOP: SegmentFill = SUBJ_TOP | CLIP_TOP;
pub const BOTH_BOTTOM: SegmentFill = SUBJ_BOTTOM | CLIP_BOTTOM;

pub const ALL: SegmentFill = SUBJ_BOTH | CLIP_BOTH;

#[derive(Debug, Clone, Copy)]
pub(crate) struct Segment<C, I: IntNumber, D = ()> {
    pub(crate) x_segment: XSegment<I>,
    pub(crate) count: C,
    pub(crate) data: D,
}

impl<C: WindingCount, I: IntNumber, D: OverlayEdgeData<C>> Segment<C, I, D> {
    #[inline(always)]
    pub(crate) fn create_and_validate_with_data(
        a: IntPoint<I>,
        b: IntPoint<I>,
        count: C,
        data: D,
        store: &mut D::Store,
    ) -> Self {
        if a < b {
            Self {
                x_segment: XSegment { a, b },
                count,
                data,
            }
        } else {
            Self {
                x_segment: XSegment { a: b, b: a },
                count: count.invert(),
                data: data.reversed(store),
            }
        }
    }
}

impl<I: IntNumber, D: OverlayEdgeData<ShapeCountBoolean>> Segment<ShapeCountBoolean, I, D> {
    #[inline]
    pub(crate) fn try_ab_and_data(
        a: IntPoint<I>,
        b: IntPoint<I>,
        shape_type: ShapeType,
        data: D,
        store: &mut D::Store,
    ) -> Option<Self> {
        match a.cmp(&b) {
            Ordering::Equal => None,
            Ordering::Less => Some(Self {
                x_segment: XSegment { a, b },
                count: ShapeCountBoolean::direct_count(shape_type),
                data,
            }),
            Ordering::Greater => Some(Self {
                x_segment: XSegment { a: b, b: a },
                count: ShapeCountBoolean::invert_count(shape_type),
                data: data.reversed(store),
            }),
        }
    }
}

impl<C, I: IntNumber, D> PartialEq<Self> for Segment<C, I, D> {
    #[inline(always)]
    fn eq(&self, other: &Self) -> bool {
        self.x_segment == other.x_segment
    }
}

impl<C, I: IntNumber, D> Eq for Segment<C, I, D> {}

impl<C, I: IntNumber, D> PartialOrd for Segment<C, I, D> {
    #[inline(always)]
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<C, I: IntNumber, D> Ord for Segment<C, I, D> {
    #[inline(always)]
    fn cmp(&self, other: &Self) -> Ordering {
        self.x_segment.cmp(&other.x_segment)
    }
}