use crate::math::{Point, Real};
#[cfg(feature = "dim2")]
use crate::{math::Vector, utils};
pub type ClippingPoints = (Point<Real>, Point<Real>, usize, usize);
#[cfg(feature = "dim2")]
pub fn clip_segment_segment_with_normal(
mut seg1: (Point<Real>, Point<Real>),
mut seg2: (Point<Real>, Point<Real>),
normal: Vector<Real>,
) -> Option<(ClippingPoints, ClippingPoints)> {
use crate::utils::WBasis;
let tangent = normal.orthonormal_basis()[0];
let mut range1 = [seg1.0.coords.dot(&tangent), seg1.1.coords.dot(&tangent)];
let mut range2 = [seg2.0.coords.dot(&tangent), seg2.1.coords.dot(&tangent)];
let mut features1 = [0, 2];
let mut features2 = [0, 2];
if range1[1] < range1[0] {
range1.swap(0, 1);
features1.swap(0, 1);
std::mem::swap(&mut seg1.0, &mut seg1.1);
}
if range2[1] < range2[0] {
range2.swap(0, 1);
features2.swap(0, 1);
std::mem::swap(&mut seg2.0, &mut seg2.1);
}
if range2[0] > range1[1] || range1[0] > range2[1] {
return None;
}
let ca = if range2[0] > range1[0] {
let bcoord = (range2[0] - range1[0]) * utils::inv(range1[1] - range1[0]);
let p1 = seg1.0 + (seg1.1 - seg1.0) * bcoord;
let p2 = seg2.0;
(p1, p2, 1, features2[0])
} else {
let bcoord = (range1[0] - range2[0]) * utils::inv(range2[1] - range2[0]);
let p1 = seg1.0;
let p2 = seg2.0 + (seg2.1 - seg2.0) * bcoord;
(p1, p2, features1[0], 1)
};
let cb = if range2[1] < range1[1] {
let bcoord = (range2[1] - range1[0]) * utils::inv(range1[1] - range1[0]);
let p1 = seg1.0 + (seg1.1 - seg1.0) * bcoord;
let p2 = seg2.1;
(p1, p2, 1, features2[1])
} else {
let bcoord = (range1[1] - range2[0]) * utils::inv(range2[1] - range2[0]);
let p1 = seg1.1;
let p2 = seg2.0 + (seg2.1 - seg2.0) * bcoord;
(p1, p2, features1[1], 1)
};
Some((ca, cb))
}
pub fn clip_segment_segment(
mut seg1: (Point<Real>, Point<Real>),
mut seg2: (Point<Real>, Point<Real>),
) -> Option<(ClippingPoints, ClippingPoints)> {
let tangent1 = seg1.1 - seg1.0;
let sqnorm_tangent1 = tangent1.norm_squared();
let mut range1 = [0.0, sqnorm_tangent1];
let mut range2 = [
(seg2.0 - seg1.0).dot(&tangent1),
(seg2.1 - seg1.0).dot(&tangent1),
];
let mut features1 = [0, 2];
let mut features2 = [0, 2];
if range1[1] < range1[0] {
range1.swap(0, 1);
features1.swap(0, 1);
std::mem::swap(&mut seg1.0, &mut seg1.1);
}
if range2[1] < range2[0] {
range2.swap(0, 1);
features2.swap(0, 1);
std::mem::swap(&mut seg2.0, &mut seg2.1);
}
if range2[0] > range1[1] || range1[0] > range2[1] {
return None;
}
let length1 = range1[1] - range1[0];
let length2 = range2[1] - range2[0];
let ca = if range2[0] > range1[0] {
let bcoord = (range2[0] - range1[0]) / length1;
let p1 = seg1.0 + tangent1 * bcoord;
let p2 = seg2.0;
(p1, p2, 1, features2[0])
} else {
let bcoord = (range1[0] - range2[0]) / length2;
let p1 = seg1.0;
let p2 = seg2.0 + (seg2.1 - seg2.0) * bcoord;
(p1, p2, features1[0], 1)
};
let cb = if range2[1] < range1[1] {
let bcoord = (range2[1] - range1[0]) / length1;
let p1 = seg1.0 + tangent1 * bcoord;
let p2 = seg2.1;
(p1, p2, 1, features2[1])
} else {
let bcoord = (range1[1] - range2[0]) / length2;
let p1 = seg1.1;
let p2 = seg2.0 + (seg2.1 - seg2.0) * bcoord;
(p1, p2, features1[1], 1)
};
Some((ca, cb))
}