#[cfg(test)]
mod test_line {
#[cfg(test)]
mod tests {
use crate::{Line, LineIntersection, PointLineRelation, V2};
#[test]
fn point_relation() {
let line = Line::new(V2::new(0.0, 0.0), V2::new(5.0, 5.0));
let point_on_line = V2::new(3.0, 3.0);
assert_eq!(
line.point_relation(point_on_line),
PointLineRelation::OnLine
);
let point_left = V2::new(-1.0, 2.0);
assert_eq!(line.point_relation(point_left), PointLineRelation::Left);
let point_right = V2::new(6.0, 3.0);
assert_eq!(line.point_relation(point_right), PointLineRelation::Right);
}
#[test]
fn intersection() {
let line1 = Line::new(V2::new(0.0, 0.0), V2::new(5.0, 5.0));
let line2 = Line::new(V2::new(0.0, 5.0), V2::new(5.0, 0.0));
assert_eq!(
line1.intersection(line2),
LineIntersection::Intersection(V2 { x: 2.5, y: 2.5 })
);
}
#[test]
fn intersection_colinear() {
let line1 = Line::new(V2::new(0.0, 0.0), V2::new(5.0, 5.0));
let line2 = Line::new(V2::new(6.0, 6.0), V2::new(8.0, 8.0));
assert_eq!(line1.intersection(line2), LineIntersection::NoIntersection);
}
#[test]
fn intersection_lines_intersect_outside() {
let line1 = Line::new(V2::new(0.0, 0.0), V2::new(1.0, 1.0));
let line2 = Line::new(V2::new(3.5, 0.0), V2::new(0.0, 3.5));
assert_eq!(line1.intersection(line2), LineIntersection::NoIntersection);
let line1 = Line::new(V2::new(0.0, 0.0), V2::new(1.0, 0.0));
let line2 = Line::new(V2::new(1.0, -1.0), V2::new(3.0, 1.0));
assert_eq!(line1.intersection(line2), LineIntersection::NoIntersection);
let line1 = Line::new(V2::new(5.0, 5.0), V2::new(5.0, -3.0));
let line2 = Line::new(V2::new(4.0, -7.0), V2::new(6.0, -5.0));
assert_eq!(line1.intersection(line2), LineIntersection::NoIntersection);
}
#[test]
fn intersection_lines_end_to_end() {
let line1 = Line::new(V2::new(0.0, 0.0), V2::new(1.0, 1.0));
let line2 = Line::new(V2::new(1.0, 1.0), V2::new(2.0, 2.0));
assert_eq!(
line1.intersection(line2),
LineIntersection::Intersection(line1.to)
);
}
#[test]
fn intersection_lines_t() {
let line1 = Line::new(V2::new(0.0, 0.0), V2::new(1.0, 0.0));
let line2 = Line::new(V2::new(1.0, 1.0), V2::new(1.0, -1.0));
assert_eq!(
line1.intersection(line2),
LineIntersection::Intersection(line1.to)
);
}
#[test]
fn intersection_lines_t_2() {
let line1 = Line::new(V2::new(1.0, 1.0), V2::new(0.0, 0.0));
let line2 = Line::new(V2::new(0.0, 2.0), V2::new(2.0, 0.0));
assert_eq!(
line1.intersection(line2),
LineIntersection::Intersection(line1.from)
);
}
#[test]
fn intersection_inf_lines() {
let line1 = Line::new(V2::xy(0.0), V2::xy(1.0));
let line2 = Line::new(V2::new(0.0, 5.0), V2::new(1.0, 4.0));
assert_eq!(
line1.intersection_as_inf_lines(&line2),
LineIntersection::Intersection(V2 { x: 2.5, y: 2.5 })
);
}
#[test]
fn intersection_inf_lines_parallel() {
let line1 = Line::new(V2::xy(0.0), V2::xy(1.0));
let line2 = Line::new(V2::new(0.0, -1.0), V2::new(1.0, 0.0));
assert_eq!(
line1.intersection_as_inf_lines(&line2),
LineIntersection::NoIntersection
);
}
#[test]
fn intersection_inf_lines_colinear() {
let line1 = Line::new(V2::xy(0.0), V2::xy(1.0));
let line2 = Line::new(V2::xy(5.0), V2::xy(4.0));
assert_eq!(
line1.intersection_as_inf_lines(&line2),
LineIntersection::NoIntersection
);
}
#[test]
fn closest_point() {
let line = Line::new(V2::new(0.0, 0.0), V2::new(3.0, 3.0));
let point = V2::new(3.0, 3.0);
assert_eq!(line.closest_point(point), point);
let point = V2::new(5.0, 5.0);
assert_eq!(line.closest_point(point), line.to.clone());
let point = V2::new(1.5, 1.5);
assert_eq!(line.closest_point(point), point);
let point = V2::new(0.0, 3.0);
assert_eq!(line.closest_point(point), V2::new(1.5, 1.5));
let point = V2::new(3.0, 0.0);
assert_eq!(line.closest_point(point), V2::new(1.5, 1.5));
let point = V2::new(100.0, 0.0);
assert_eq!(line.closest_point(point), V2::new(3.0, 3.0));
let point = V2::new(0.0, 5.0);
assert_eq!(line.closest_point(point), V2::new(2.5, 2.5));
let point = V2::new(5.0, 0.0);
assert_eq!(line.closest_point(point), V2::new(2.5, 2.5));
}
#[test]
fn closest_point_line_points_coincident() {
let line = Line::new(V2::new(0.0, 0.0), V2::new(0.0, 0.0));
let point = V2::new(1.0, 1.0);
assert_eq!(line.closest_point(point), V2::new(0.0, 0.0));
}
#[test]
fn project() {
let line = Line::new(V2::new(0.0, 1.0), V2::new(1.0, 2.0));
let point = V2::new(0.0, 2.0);
assert_eq!(line.project(point), V2::new(0.5, 1.5));
}
#[test]
fn contains_point_on_segment() {
let line = Line::new(V2::new(0.0, 0.0), V2::new(2.0, 2.0));
assert!(line.contains_point_on_segment(V2::new(1.0, 1.0)));
assert!(line.contains_point_on_segment(V2::new(0.0, 0.0)));
assert!(line.contains_point_on_segment(V2::new(2.0, 2.0)));
assert!(!line.contains_point_on_segment(V2::new(3.0, 3.0)));
assert!(!line.contains_point_on_segment(V2::new(1.0, 1.2)));
}
#[test]
fn intersect_multiple_sorted() {
let a = Line::new(V2::new(0.0, 0.0), V2::new(1.0, 1.0));
let i1 = Line::new(V2::new(0.0, 0.25), V2::new(1.0, 0.25));
let i2 = Line::new(V2::new(0.0, 0.5), V2::new(1.0, 0.5));
let i3 = Line::new(V2::new(0.0, 0.75), V2::new(1.0, 0.75));
let order1 = vec![i1, i2, i3];
let order2 = vec![i1, i3, i2];
let order3 = vec![i2, i1, i3];
let order4 = vec![i2, i3, i1];
let order5 = vec![i3, i1, i2];
let order6 = vec![i3, i2, i1];
for order in [order1, order2, order3, order4, order5, order6] {
let r = a.intersect_multiple_sorted_by_dist(&order);
assert_eq!(r.len(), 3);
assert_eq!(r[0], V2::xy(0.25));
assert_eq!(r[1], V2::xy(0.5));
assert_eq!(r[2], V2::xy(0.75));
}
}
}
mod traits {
use crate::{
Angle, BoundingBox, Layer, Line, Path, Plottable, Rect, Rotate, SampleSettings,
Translate, LARGE_EPSILON, V2,
};
#[test]
fn helpers() {
let line = Line::new(V2::new(0.0, 0.0), V2::new(4.0, 0.0));
assert_eq!(line.length(), 4.0);
assert_eq!(line.point_at(0.25), V2::new(1.0, 0.0));
assert_eq!(line.normal_right(), V2::new(0.0, -1.0));
assert_eq!(line.offset_left(2.0).from, V2::new(0.0, 2.0));
}
#[test]
fn transforms() {
let line = Line::new(V2::new(1.0, 0.0), V2::new(2.0, 0.0));
assert_eq!(line.translate(V2::new(0.0, 1.0)).to, V2::new(2.0, 1.0));
let rotated = line.rotate_around(V2::new(1.0, 0.0), Angle::quarter_rotation());
assert!(rotated.to.dist(V2::new(1.0, 1.0)) < LARGE_EPSILON);
let bb = Line::new(V2::new(3.0, 1.0), V2::new(0.0, 2.0)).bounding_box();
assert_eq!(bb, Some(Rect::new(V2::new(0.0, 1.0), V2::new(3.0, 2.0))));
}
#[test]
fn into_path_shape_layer() {
let lines = vec![
Line::new(V2::new(0.0, 0.0), V2::new(1.0, 0.0)),
Line::new(V2::new(1.0, 0.0), V2::new(1.0, 1.0)),
];
let layer: Layer = lines.iter().copied().collect();
assert_eq!(layer.len(), 2);
let path: Path = lines[0].into();
assert_eq!(path.len(), 2);
assert_eq!(path.length(), 1.0);
let segments: Vec<Line> = Path::new_from(vec![
V2::new(0.0, 0.0),
V2::new(1.0, 0.0),
V2::new(1.0, 1.0),
])
.segments()
.collect();
assert_eq!(segments, lines);
let _ = SampleSettings::default();
}
}
}