#![allow(dead_code)]
use crate::constants::GEOMETRIC_EPSILON;
use crate::prelude::*;
const ZERO: f64 = 0f64;
const ONE: f64 = 1f64;
pub fn dist_segment_arc(seg: &Segment, arc: &Arc) -> f64 {
let res = int_segment_arc(seg, arc);
match res {
SegmentArcConfig::NoIntersection() => {
let dist0 = dist_point_arc_dist(&seg.a, arc);
let dist1 = dist_point_arc_dist(&seg.b, arc);
let mut min_dist = dist0.min(dist1);
if min_dist < GEOMETRIC_EPSILON {
return min_dist;
}
let (dist2, _) = dist_point_segment(&arc.a, seg);
let (dist3, _) = dist_point_segment(&arc.b, seg);
min_dist = min_dist.min(dist2).min(dist3);
if min_dist < GEOMETRIC_EPSILON {
return min_dist;
}
let line = line(seg.a, seg.b - seg.a);
let circle = circle(arc.c, arc.r);
let res2 = dist_line_circle(&line, &circle);
let dist4 = match res2 {
DistLineCircleConfig::OnePair(_, param, closest0, closest1) => {
if param >= ZERO && param <= ONE && arc.contains(closest1) {
(closest0 - closest1).norm()
} else {
f64::MAX
}
}
DistLineCircleConfig::TwoPairs(..) => f64::MAX,
};
min_dist.min(dist4)
}
_ => {
0.0
}
}
}
#[cfg(test)]
mod tests_distance_segment_arc {
use crate::{arc::arc, point::point, segment::segment};
#[test]
fn test_segment_outside_circle_01() {
let seg = segment(point(-1.0, 2.0), point(1.0, 2.0));
let arc = arc(point(1.0, 0.0), point(-1.0, 0.0), point(0.0, 0.0), 1.0);
let res = super::dist_segment_arc(&seg, &arc);
assert_eq!(res, 1.0);
}
#[test]
fn test_segment_outside_circle_02() {
let seg = segment(point(-1.0, 2.0), point(1.0, 2.0));
let arc = arc(point(-1.0, 0.0), point(1.0, 0.0), point(0.0, 0.0), 1.0);
let res = super::dist_segment_arc(&seg, &arc);
assert_eq!(res, 2.0);
}
#[test]
fn test_segment_inside_circle_01() {
let seg = segment(point(-2.0, 0.0), point(0.5, 0.0));
let arc = arc(point(1.0, 0.0), point(-1.0, 0.0), point(0.0, 0.0), 1.0);
let res = super::dist_segment_arc(&seg, &arc);
assert_eq!(res, 0.0);
}
#[test]
fn test_segment_inside_circle_02() {
let seg = segment(point(-0.5, 0.0), point(2.0, 0.0));
let arc = arc(point(1.0, 0.0), point(-1.0, 0.0), point(0.0, 0.0), 1.0);
let res = super::dist_segment_arc(&seg, &arc);
assert_eq!(res, 0.0);
}
#[test]
fn test_segment_inside_circle_03() {
let seg = segment(point(-2.0, 0.0), point(2.0, 0.0));
let arc = arc(point(1.0, 0.0), point(-1.0, 0.0), point(0.0, 0.0), 1.0);
let res = super::dist_segment_arc(&seg, &arc);
assert_eq!(res, 0.0);
}
#[test]
fn test_segment_inside_circle_04() {
let seg = segment(point(-0.5, 0.0), point(2.0, 0.0));
let arc = arc(point(0.0, 1.0), point(-1.0, 0.0), point(0.0, 0.0), 1.0);
let res = super::dist_segment_arc(&seg, &arc);
assert_eq!(res, 0.5);
}
#[test]
fn test_segment_inside_circle_05() {
let seg = segment(point(-2.0, 0.0), point(0.5, 0.0));
let arc = arc(point(1.0, 0.0), point(0.0, 1.0), point(0.0, 0.0), 1.0);
let res = super::dist_segment_arc(&seg, &arc);
assert_eq!(res, 0.5);
}
#[test]
fn test_segment_inside_circle_06() {
let seg = segment(point(-2.0, 0.0), point(2.0, 0.0));
let arc = arc(point(1.0, 1.0), point(-1.0, 1.0), point(0.0, 0.0), 2.0);
let res = super::dist_segment_arc(&seg, &arc);
assert_eq!(res, 1.0);
}
#[test]
fn test_segment_inside_circle_07() {
let seg = segment(point(0.0, 0.0), point(2.0, 0.0));
let arc = arc(point(1.0, 1.0), point(-1.0, 1.0), point(0.0, 0.0), 2.0);
let res = super::dist_segment_arc(&seg, &arc);
assert_eq!(res, 1.0);
}
#[test]
fn test_segment_inside_circle_08() {
let seg = segment(point(-2.0, 0.0), point(0.0, 0.0));
let arc = arc(point(1.0, 1.0), point(-1.0, 1.0), point(0.0, 0.0), 2.0);
let res = super::dist_segment_arc(&seg, &arc);
assert_eq!(res, 1.0);
}
}