i_curve 0.1.2

Boolean operations on closed paths of lines, Bezier curves, and rational elliptic arcs
Documentation
use crate::kernel::int::curve::param::SegmentParam;
use i_overlay::i_float::int::number::int::IntNumber;
use i_overlay::i_float::int::number::product_uint::UIntProduct;
use i_overlay::i_float::int::number::uint::UIntNumber;
use i_overlay::i_float::int::number::wide_int::WideIntNumber;
#[cfg(test)]
use i_overlay::i_float::int::rect::IntRect;
use i_overlay::i_float::int::vector::IntVector;
use i_overlay::i_shape::int::IntPoint;

pub(crate) trait Chord<I: IntNumber> {
    fn chord(&self) -> SegmentChord<I>;
}

#[derive(Debug, Clone, Copy)]
pub(crate) struct SegmentChord<I: IntNumber> {
    pub(crate) a: IntPoint<I>,
    pub(crate) b: IntPoint<I>,
}

impl<I: IntNumber> SegmentChord<I> {
    #[inline]
    pub(crate) fn is_zero_length(&self) -> bool {
        self.b == self.a
    }

    #[inline]
    pub(crate) fn vector(&self) -> IntVector<I> {
        self.b - self.a
    }

    #[inline]
    pub(crate) fn sqr_length(&self) -> I::Wide {
        self.vector().sqr_length()
    }

    #[inline]
    #[cfg(test)]
    pub(crate) fn to_rect(self) -> IntRect<I> {
        IntRect::with_ab(self.a, self.b)
    }

    pub(crate) fn param_for_point(&self, point: IntPoint<I>) -> SegmentParam<I> {
        let vector = self.vector();
        let sqr_length = vector.sqr_length();
        debug_assert!(sqr_length > I::Wide::ZERO);

        let projection = (point - self.a).dot_product(vector);
        if projection <= I::Wide::ZERO {
            return SegmentParam::new(I::ZERO);
        }
        if projection >= sqr_length {
            return SegmentParam::new(I::from_wide(SegmentParam::<I>::DENOMINATOR));
        }

        let product = <I::WideUInt as UIntNumber>::Product::multiply(
            projection.unsigned_abs(),
            SegmentParam::<I>::DENOMINATOR.unsigned_abs(),
        );
        let value = product.divide_with_rounding(sqr_length.unsigned_abs());

        SegmentParam::new(I::from_wide(I::Wide::from_uint(value)))
    }
}