pub fn triangle_coords(zeta: &mut [f64], xa: &[f64], xb: &[f64], xc: &[f64], xp: &[f64]) {
let a2 = xa[0] * (xb[1] - xc[1]) + xb[0] * (xc[1] - xa[1]) + xc[0] * (xa[1] - xb[1]);
zeta[0] = (xp[0] * (xb[1] - xc[1]) + xb[0] * (xc[1] - xp[1]) + xc[0] * (xp[1] - xb[1])) / a2;
zeta[1] = (xa[0] * (xp[1] - xc[1]) + xp[0] * (xc[1] - xa[1]) + xc[0] * (xa[1] - xp[1])) / a2;
zeta[2] = (xa[0] * (xb[1] - xp[1]) + xb[0] * (xp[1] - xa[1]) + xp[0] * (xa[1] - xb[1])) / a2;
}
#[inline]
pub fn in_triangle(zeta: &[f64]) -> bool {
if zeta[0] < 0.0 || zeta[1] < 0.0 || zeta[2] < 0.0 {
false
} else {
true
}
}
#[cfg(test)]
mod tests {
use super::{in_triangle, triangle_coords};
use plotpy::{Canvas, Plot, PolyCode, Text};
fn draw_triangles(plot: &mut Plot, triangles: &[[[f64; 2]; 3]]) {
let mut ids = Text::new();
let mut canvas = Canvas::new();
canvas.set_face_color("#fefddc80").set_edge_color("#fcb827");
for t in 0..triangles.len() {
let (mut xc, mut yc) = (0.0, 0.0);
canvas.polycurve_begin();
for m in 0..3 {
let code = if m == 0 { PolyCode::MoveTo } else { PolyCode::LineTo };
canvas.polycurve_add(triangles[t][m][0], triangles[t][m][1], code);
xc += triangles[t][m][0];
yc += triangles[t][m][1];
}
canvas.polycurve_end(true);
xc /= 3.0;
yc /= 3.0;
ids.draw(xc, yc, format!("{}", t).as_str());
}
plot.add(&canvas).add(&ids);
}
#[test]
fn draw_triangles_works() {
let mut plot = Plot::new();
const T: [[[f64; 2]; 3]; 1] = [[[0.0, 0.0], [1.0, 0.0], [0.0, 1.0]]];
draw_triangles(&mut plot, &T);
}
#[test]
fn triangle_coords_works() {
let xa = &[0.0, 0.0];
let xb = &[1.0, 0.0];
let xc = &[0.0, 1.0];
let mut zeta = vec![0.0; 3];
triangle_coords(&mut zeta, xa, xb, xc, &[0.0, 0.0]);
assert_eq!(zeta, &[1.0, 0.0, 0.0]);
triangle_coords(&mut zeta, xa, xb, xc, &[1.0, 0.0]);
assert_eq!(zeta, &[0.0, 1.0, 0.0]);
triangle_coords(&mut zeta, xa, xb, xc, &[0.0, 1.0]);
assert_eq!(zeta, &[0.0, 0.0, 1.0]);
triangle_coords(&mut zeta, xa, xb, xc, &[0.5, 0.5]);
assert_eq!(zeta, &[0.0, 0.5, 0.5]);
triangle_coords(&mut zeta, xa, xb, xc, &[1.0, 1.0]);
assert_eq!(zeta, &[-1.0, 1.0, 1.0]);
}
#[test]
#[rustfmt::skip]
fn in_triangle_works_1() {
let xa = &[0.0, 0.0];
let xb = &[1.0, 0.0];
let xc = &[0.0, 1.0];
let mut zeta = vec![0.0; 3];
triangle_coords(&mut zeta, xa, xb, xc, &[0.0, 0.0]); assert!(in_triangle(&zeta));
triangle_coords(&mut zeta, xa, xb, xc, &[1.0, 0.0]); assert!(in_triangle(&zeta));
triangle_coords(&mut zeta, xa, xb, xc, &[0.0, 1.0]); assert!(in_triangle(&zeta));
triangle_coords(&mut zeta, xa, xb, xc, &[0.5, 0.5]); assert!(in_triangle(&zeta));
triangle_coords(&mut zeta, xa, xb, xc, &[0.5, 0.0]); assert!(in_triangle(&zeta));
triangle_coords(&mut zeta, xa, xb, xc, &[0.0, 0.5]); assert!(in_triangle(&zeta));
triangle_coords(&mut zeta, xa, xb, xc, &[0.3, 0.3]); assert!(in_triangle(&zeta));
triangle_coords(&mut zeta, xa, xb, xc, &[1e-15, 1e-15]); assert!(in_triangle(&zeta));
triangle_coords(&mut zeta, xa, xb, xc, &[1e-15, -1e-15]); assert!(!in_triangle(&zeta));
triangle_coords(&mut zeta, xa, xb, xc, &[1.1, 0.0]); assert!(!in_triangle(&zeta));
triangle_coords(&mut zeta, xa, xb, xc, &[0.0, 1.1]); assert!(!in_triangle(&zeta));
triangle_coords(&mut zeta, xa, xb, xc, &[1.0, 1.0]); assert!(!in_triangle(&zeta));
triangle_coords(&mut zeta, xa, xb, xc, &[-1e-15, -1e-15]); assert!(!in_triangle(&zeta));
}
#[test]
fn in_triangle_works_2() {
#[rustfmt::skip]
const T: [[[f64; 2]; 3]; 12] = [
[[0.230951, 0.558482], [0.133721, 0.348832], [0.540745, 0.331184]], [[0.13928, 0.180603], [0.133721, 0.348832], [0.0307942, 0.459123]], [[0.0307942, 0.459123], [0.230951, 0.558482], [0.0980015, 0.981755]], [[0.230951, 0.558482], [0.0307942, 0.459123], [0.133721, 0.348832]], [[0.0980015, 0.981755], [0.230951, 0.558482], [0.578587, 0.760349]], [[0.133721, 0.348832], [0.13928, 0.180603], [0.540745, 0.331184]], [[0.540745, 0.331184], [0.578587, 0.760349], [0.230951, 0.558482]], [[0.540745, 0.331184], [0.478554, 0.00869692], [0.648071, 0.369534]], [[0.578587, 0.760349], [0.648071, 0.369534], [0.903726, 0.975904]], [[0.648071, 0.369534], [0.578587, 0.760349], [0.540745, 0.331184]], [[0.578587, 0.760349], [0.903726, 0.975904], [0.0980015, 0.981755]], [[0.540745, 0.331184], [0.13928, 0.180603], [0.478554, 0.00869692]], ];
let mut zeta = vec![0.0; 3];
for tri in &T {
for m in 0..3 {
triangle_coords(&mut zeta, &tri[0], &tri[1], &tri[2], &tri[m]);
assert!(in_triangle(&zeta));
}
triangle_coords(&mut zeta, &tri[0], &tri[1], &tri[2], &[0.1, 0.1]);
assert!(!in_triangle(&zeta));
triangle_coords(&mut zeta, &tri[0], &tri[1], &tri[2], &[0.6, 0.2]);
assert!(!in_triangle(&zeta));
}
triangle_coords(&mut zeta, &T[0][0], &T[0][1], &T[0][2], &[0.3, 0.4]);
assert!(in_triangle(&zeta));
triangle_coords(&mut zeta, &T[8][0], &T[8][1], &T[8][2], &[0.7, 0.7]);
assert!(in_triangle(&zeta));
}
}