i_triangle 0.42.0

Polygon Triangulation Library: Efficient Delaunay Triangulation for Complex Shapes.
Documentation
use crate::int::meta::MeshMetaProvider;
use crate::int::monotone::triangulator::MonotoneTriangulator;
use crate::int::triangulation::RawIntTriangulation;
use crate::int::unchecked::IntUncheckedTriangulatable;
use crate::int::validation::Validation;
use alloc::vec::Vec;
use i_overlay::core::simplify::Simplify;
use i_overlay::i_float::int::point::IntPoint;
use i_overlay::i_shape::int::shape::{IntContour, IntShape, IntShapes};

pub(super) struct ShapesSolver;
pub(super) struct ShapeSolver;
pub(super) struct ContourSolver;

impl ShapesSolver {
    #[inline]
    pub(super) fn triangulate(validation: Validation, shapes: &IntShapes) -> RawIntTriangulation {
        let shapes = shapes.simplify(validation.fill_rule, validation.options);
        Self::uncheck_triangulate(&shapes)
    }

    pub(super) fn uncheck_triangulate(shapes: &IntShapes) -> RawIntTriangulation {
        if shapes.len() <= 1 {
            return if let Some(first) = shapes.first() {
                first.uncheck_triangulate()
            } else {
                Default::default()
            };
        }

        let mut triangles_count = 0;
        let mut points_count = 0;
        for shape in shapes.iter() {
            let meta = shape.meta(0);
            triangles_count += meta.triangles_count;
            points_count += meta.vertices_count;
        }

        let mut triangles = Vec::with_capacity(triangles_count);
        let mut points = Vec::with_capacity(points_count);

        let mut iter = shapes.iter();
        if let Some(first) = iter.next() {
            let mut raw_0 = first.uncheck_triangulate();
            triangles.append(&mut raw_0.triangles);
            points.append(&mut raw_0.points);

            for shape in iter {
                let points_offset = points.len();
                let triangle_offset = triangles.len();
                let mut raw_i = shape.uncheck_triangulate();
                raw_i.shift(points_offset, triangle_offset);

                triangles.append(&mut raw_i.triangles);
                points.append(&mut raw_i.points);
            }
        }

        RawIntTriangulation::new(triangles, points)
    }

    #[inline]
    pub(super) fn triangulate_with_steiner_points(
        validation: Validation,
        shapes: &IntShapes,
        points: &[IntPoint],
    ) -> RawIntTriangulation {
        shapes
            .simplify(validation.fill_rule, validation.options)
            .uncheck_triangulate_with_steiner_points(points)
    }

    pub(super) fn uncheck_triangulate_with_steiner_points(
        shapes: &IntShapes,
        groups: &[Vec<IntPoint>],
    ) -> RawIntTriangulation {
        if shapes.len() <= 1 {
            return if let Some(first) = shapes.first() {
                first.uncheck_triangulate_with_steiner_points(&groups[0])
            } else {
                Default::default()
            };
        }

        let mut triangles_count = 0;
        let mut points_count = 0;
        for (i, shape) in shapes.iter().enumerate() {
            let meta = shape.meta(groups[i].len());
            triangles_count += meta.triangles_count;
            points_count += meta.vertices_count;
        }

        let mut triangles = Vec::with_capacity(triangles_count);
        let mut points = Vec::with_capacity(points_count);

        let mut raw_buffer = RawIntTriangulation::default();

        let mut triangulator = MonotoneTriangulator::default();
        triangulator.shape_into_net_triangulation(&shapes[0], Some(&groups[0]), &mut raw_buffer);

        triangles.extend_from_slice(&raw_buffer.triangles);
        points.extend_from_slice(&raw_buffer.points);

        let mut i = 1;
        while i < shapes.len() {
            let shape = &shapes[i];
            let steiner_points = &groups[i];
            i += 1;

            let points_offset = points.len();
            let triangle_offset = triangles.len();

            triangulator.shape_into_net_triangulation(shape, Some(steiner_points), &mut raw_buffer);
            raw_buffer.shift(points_offset, triangle_offset);

            triangles.extend_from_slice(&raw_buffer.triangles);
            points.extend_from_slice(&raw_buffer.points);
        }

        RawIntTriangulation::new(triangles, points)
    }
}

impl ShapeSolver {
    #[inline]
    pub(super) fn triangulate(validation: Validation, shape: &IntShape) -> RawIntTriangulation {
        let shapes = shape.simplify(validation.fill_rule, validation.options);
        ShapesSolver::uncheck_triangulate(&shapes)
    }

    #[inline]
    pub(super) fn uncheck_triangulate(shape: &IntShape) -> RawIntTriangulation {
        let mut raw = RawIntTriangulation::default();
        MonotoneTriangulator::default().shape_into_net_triangulation(shape, None, &mut raw);
        raw
    }

    #[inline]
    pub(super) fn triangulate_with_steiner_points(
        validation: Validation,
        shape: &IntShape,
        points: &[IntPoint],
    ) -> RawIntTriangulation {
        shape
            .simplify(validation.fill_rule, validation.options)
            .uncheck_triangulate_with_steiner_points(points)
    }

    #[inline]
    pub(super) fn uncheck_triangulate_with_steiner_points(
        shape: &IntShape,
        points: &[IntPoint],
    ) -> RawIntTriangulation {
        if shape.len() <= 1 {
            return if let Some(first) = shape.first() {
                first.uncheck_triangulate_with_steiner_points(points)
            } else {
                RawIntTriangulation::default()
            };
        }
        let mut raw = RawIntTriangulation::default();
        MonotoneTriangulator::default().shape_into_net_triangulation(shape, Some(points), &mut raw);
        raw
    }
}

impl ContourSolver {
    #[inline]
    pub(super) fn triangulate(validation: Validation, contour: &IntContour) -> RawIntTriangulation {
        contour
            .simplify(validation.fill_rule, validation.options)
            .uncheck_triangulate()
    }

    #[inline]
    pub(super) fn uncheck_triangulate(contour: &IntContour) -> RawIntTriangulation {
        if contour.len() < 3 {
            RawIntTriangulation::default()
        } else {
            let mut raw = RawIntTriangulation::default();
            MonotoneTriangulator::default().contour_into_net_triangulation(contour, None, &mut raw);
            raw
        }
    }

    #[inline]
    pub(super) fn triangulate_with_steiner_points(
        validation: Validation,
        contour: &IntContour,
        points: &[IntPoint],
    ) -> RawIntTriangulation {
        contour
            .simplify(validation.fill_rule, validation.options)
            .uncheck_triangulate_with_steiner_points(points)
    }

    #[inline]
    pub(super) fn uncheck_triangulate_with_steiner_points(
        contour: &IntContour,
        points: &[IntPoint],
    ) -> RawIntTriangulation {
        if contour.len() < 3 {
            Default::default()
        } else {
            let mut raw = RawIntTriangulation::default();
            MonotoneTriangulator::default().contour_into_net_triangulation(
                contour,
                Some(points),
                &mut raw,
            );
            raw
        }
    }
}