rcgal 0.2.2

Rust Computational Geometry Algorithms Library.
Documentation
use crate::{
    algorithm::{
        intersection::circle_segment_2_circle_segment_2::circle_segment_2_circle_segment_2_intersection,
        location::{
            location_enum::Point2ArcSegment2Location,
            point_2_arc_segment_2::{is_point_2_on_arc_segment_2, locate_point_2_arc_segment_2},
        },
    },
    kernel::{
        circle_segment_2::CircleSegment2, number_type::NumberType, point_2::Point2,
        segment_2::Segment2,
    },
};

pub fn is_arc_segment_2_arc_segment_2_intersected<T: NumberType>(
    arc_segment_a: &impl Segment2<T>,
    arc_segment_b: &impl Segment2<T>,
) -> bool {
    let result = arc_segment_2_arc_segment_2_intersection(arc_segment_a, arc_segment_b);
    return !result.is_empty();
}

pub fn arc_segment_2_arc_segment_2_intersection<T: NumberType>(
    arc_segment_a: &impl Segment2<T>,
    arc_segment_b: &impl Segment2<T>,
) -> Vec<Point2<T>> {
    let circle_segment_a = CircleSegment2::new(arc_segment_a.center(), arc_segment_a.radius());
    let circle_segment_b = CircleSegment2::new(arc_segment_b.center(), arc_segment_b.radius());
    let points =
        circle_segment_2_circle_segment_2_intersection(&circle_segment_a, &circle_segment_b);
    let mut result = Vec::new();
    if points.is_empty() {
        if is_point_2_on_arc_segment_2(&arc_segment_a.source(), arc_segment_b) {
            result.push(arc_segment_a.source());
        }
        if is_point_2_on_arc_segment_2(&arc_segment_a.target(), arc_segment_b) {
            result.push(arc_segment_a.target());
        }
        if is_point_2_on_arc_segment_2(&arc_segment_b.source(), arc_segment_a) {
            result.push(arc_segment_b.source());
        }
        if is_point_2_on_arc_segment_2(&arc_segment_b.target(), arc_segment_a) {
            result.push(arc_segment_b.target());
        }
        result.sort();
        result.dedup();
    } else {
        for point in &points {
            let on_arc_segment_a = locate_point_2_arc_segment_2(point, arc_segment_a);
            let on_arc_segment_b = locate_point_2_arc_segment_2(point, arc_segment_b);
            if on_arc_segment_a == on_arc_segment_b
                && on_arc_segment_a == Point2ArcSegment2Location::On
            {
                result.push(point.clone());
            }
        }
    }
    return result;
}

#[cfg(test)]
mod tests {
    use std::f64::consts::PI;

    use crate::kernel::arc_segment_2::ArcSegment2;

    use super::*;

    #[test]
    fn test_is_arc_segment_2_arc_segment_2_intersected() {
        let arc_segment_a =
            ArcSegment2::new(CircleSegment2::new(Point2::new(0.0, 0.0), 5.0), 0.0, PI);

        let arc_segment_b =
            ArcSegment2::new(CircleSegment2::new(Point2::new(0.0, 0.0), 5.0), 0.0, PI);
        assert_eq!(
            is_arc_segment_2_arc_segment_2_intersected(&arc_segment_a, &arc_segment_b),
            true
        );

        let arc_segment_b =
            ArcSegment2::new(CircleSegment2::new(Point2::new(5.0, 0.0), 5.0), 0.0, PI);
        assert_eq!(
            is_arc_segment_2_arc_segment_2_intersected(&arc_segment_a, &arc_segment_b),
            true
        );
    }

    #[test]
    fn test_arc_segment_2_arc_segment_2_intersection() {
        let arc_segment_a =
            ArcSegment2::new(CircleSegment2::new(Point2::new(0.0, 0.0), 5.0), 0.0, PI);

        let arc_segment_b =
            ArcSegment2::new(CircleSegment2::new(Point2::new(0.0, 0.0), 5.0), 0.0, PI);
        assert_eq!(
            arc_segment_2_arc_segment_2_intersection(&arc_segment_a, &arc_segment_b),
            vec![Point2::new(5.0, 0.0), Point2::new(-5.0, 0.0),]
        );

        let arc_segment_b =
            ArcSegment2::new(CircleSegment2::new(Point2::new(5.0, 0.0), 5.0), 0.0, PI);
        assert_eq!(
            arc_segment_2_arc_segment_2_intersection(&arc_segment_a, &arc_segment_b),
            vec![Point2::new(2.5, 2.5 * 3.0.sqrt()),]
        );

        let arc_segment_b = ArcSegment2::new(
            CircleSegment2::new(Point2::new(0.0, 0.0), 5.0),
            PI,
            PI * 2.0,
        );
        assert_eq!(
            arc_segment_2_arc_segment_2_intersection(&arc_segment_a, &arc_segment_b),
            vec![Point2::new(5.0, 0.0), Point2::new(-5.0, 0.0),]
        );
    }
}