gemini_engine/primitives/
helpers.rs1use crate::core::Vec2D;
2
3fn is_left_turn(p0: Vec2D, p1: Vec2D, p2: Vec2D) -> bool {
4 let v1 = p1 - p0;
5 let v2 = p2 - p0;
6 v1.perp_dot(v2) > 0
7}
8
9fn is_ear(vertex: Vec2D, prev_vertex: Vec2D, next_vertex: Vec2D, polygon: &[Vec2D]) -> bool {
10 for i in 0..polygon.len() {
11 let p1 = polygon[i];
12 let p2 = polygon[(i + 1) % polygon.len()];
13 let p3 = polygon[(i + 2) % polygon.len()];
14
15 if p1 != vertex
16 && p2 != vertex
17 && p3 != vertex
18 && is_left_turn(vertex, p1, p2)
19 && is_left_turn(vertex, p2, p3)
20 && is_left_turn(vertex, p3, p1)
21 {
22 let triangle_area = (p1 - p2).perp_dot(p3 - p2).abs();
23 if triangle_area > 0 {
24 let p = (vertex - prev_vertex).perp_dot(next_vertex - prev_vertex);
25 return (p1 - prev_vertex).perp_dot(p1 - next_vertex) > 0 && p > 0;
26 }
27 }
28 }
29 false
30}
31
32#[must_use]
34pub fn triangulate(vertices: &[Vec2D]) -> Vec<[Vec2D; 3]> {
35 let mut triangles = Vec::new();
36 let n = vertices.len();
37
38 if n < 3 {
39 return triangles;
40 }
41
42 let mut remaining_vertices = vertices.to_vec();
43
44 while remaining_vertices.len() > 3 {
45 let mut ear_index = 0;
46 for i in 0..remaining_vertices.len() {
47 let prev_index = (i + remaining_vertices.len() - 1) % remaining_vertices.len();
48 let next_index = (i + 1) % remaining_vertices.len();
49
50 let vertex = remaining_vertices[i];
51 let prev_vertex = remaining_vertices[prev_index];
52 let next_vertex = remaining_vertices[next_index];
53
54 if is_ear(vertex, prev_vertex, next_vertex, &remaining_vertices) {
55 ear_index = i;
56 break;
57 }
58 }
59
60 let ear_vertex = remaining_vertices[ear_index];
61 let prev_index = (ear_index + remaining_vertices.len() - 1) % remaining_vertices.len();
62 let next_index = (ear_index + 1) % remaining_vertices.len();
63 let prev_vertex = remaining_vertices[prev_index];
64 let next_vertex = remaining_vertices[next_index];
65
66 triangles.push([prev_vertex, ear_vertex, next_vertex]);
67 remaining_vertices.remove(ear_index);
68 }
69
70 triangles.push([
71 remaining_vertices[0],
72 remaining_vertices[1],
73 remaining_vertices[2],
74 ]);
75
76 triangles
77}
78
79#[must_use]
81pub fn interpolate(i0: i64, d0: i64, i1: i64, d1: i64) -> Vec<i64> {
82 interpolate_floating(i0, d0 as f64, i1, d1 as f64)
83 .iter()
84 .map(|n| n.round() as i64)
85 .collect()
86}
87
88#[must_use]
90pub fn interpolate_floating(i0: i64, d0: f64, i1: i64, d1: f64) -> Vec<f64> {
91 if i0 == i1 {
92 return vec![d0];
93 }
94 let mut values = vec![];
95
96 let a = (d1 - d0) / (i1 - i0) as f64;
97 let mut d = d0;
98 for _i in i0..=i1 {
99 values.push(d);
100 d += a;
101 }
102 values
103}