i_curve 0.1.2

Boolean operations on closed paths of lines, Bezier curves, and rational elliptic arcs
Documentation
use crate::int::CurveInt;
use i_overlay::i_float::int::number::uint::UIntNumber;
use i_overlay::i_float::int::number::wide_int::WideIntNumber;
use i_overlay::i_float::int::vector::IntVector;

pub(crate) trait ApproximateAngle {
    fn is_nearly_collinear_with(&self, other: Self, sin_angle_neg_pow2: u32) -> bool;
}

impl<I: CurveInt> ApproximateAngle for IntVector<I> {
    fn is_nearly_collinear_with(&self, other: Self, sin_angle_neg_pow2: u32) -> bool {
        let abs_cross = self.cross_product(other).unsigned_abs();
        if abs_cross == I::WideUInt::ZERO {
            return true;
        }
        let log_cross = abs_cross.ilog2();
        let sqr_len_0 = self.sqr_length();
        let sqr_len_1 = other.sqr_length();
        debug_assert!(sqr_len_0 != I::Wide::ZERO);
        debug_assert!(sqr_len_1 != I::Wide::ZERO);

        let log_len = (sqr_len_0.ilog2() + sqr_len_1.ilog2()) >> 1;

        if log_len < log_cross {
            return false;
        }

        log_len - log_cross >= sin_angle_neg_pow2
    }
}

#[cfg(test)]
mod tests {
    use crate::kernel::int::math::angle::ApproximateAngle;
    use i_overlay::i_float::int::vector::IntVector;

    #[test]
    fn test_0() {
        let a: IntVector<i32> = IntVector::new(8, 0);
        let b: IntVector<i32> = IntVector::new(8, 1);
        let c: IntVector<i32> = IntVector::new(8, 2);
        let d: IntVector<i32> = IntVector::new(8, 3);
        let e: IntVector<i32> = IntVector::new(8, 4);
        let f: IntVector<i32> = IntVector::new(8, 5);

        assert!(a.is_nearly_collinear_with(b, 3));
        assert!(!a.is_nearly_collinear_with(c, 3));
        assert!(!a.is_nearly_collinear_with(d, 3));
        assert!(!a.is_nearly_collinear_with(e, 3));
        assert!(!a.is_nearly_collinear_with(f, 3));
    }
}