1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use glam::Vec2;
#[derive(Debug, Clone, Copy)]
pub enum Shape {
Line(Line),
Quad {
from: Vec2,
by: Vec2,
to: Vec2,
},
Curve {
from: Vec2,
by_a: Vec2,
by_b: Vec2,
to: Vec2,
},
}
#[derive(Debug, Clone, Copy)]
pub struct Line {
pub from: Vec2,
pub to: Vec2,
}
impl Shape {
pub fn iter_lines(self) -> impl Iterator<Item = Line> {
enum ShapeIter<I0, I1, I2>
where
I0: Iterator<Item = Line>,
I1: Iterator<Item = Line>,
I2: Iterator<Item = Line>,
{
I0(I0),
I1(I1),
I2(I2),
}
impl<I0, I1, I2> Iterator for ShapeIter<I0, I1, I2>
where
I0: Iterator<Item = Line>,
I1: Iterator<Item = Line>,
I2: Iterator<Item = Line>,
{
type Item = Line;
fn next(&mut self) -> Option<Self::Item> {
match self {
ShapeIter::I0(i0) => i0.next(),
ShapeIter::I1(i1) => i1.next(),
ShapeIter::I2(i2) => i2.next(),
}
}
}
const RES: usize = 8;
const STEP: f32 = 1.0 / RES as f32;
match self {
Shape::Line(line) => ShapeIter::I0(Some(line).into_iter()),
Shape::Quad { from, by, to } => {
let mut prev = from;
ShapeIter::I1((1..=RES).map(|i| i as f32 * STEP).map(move |t| {
let from_by = from.lerp(by, t);
let by_to = by.lerp(to, t);
let next = from_by.lerp(by_to, t);
let result = Line {
from: prev,
to: next,
};
prev = next;
result
}))
}
Shape::Curve {
from,
by_a,
by_b,
to,
} => {
let mut prev = from;
ShapeIter::I2((1..=RES).map(|i| i as f32 * STEP).map(move |t| {
let from_by_a = from.lerp(by_a, t);
let by_a_by_b = by_a.lerp(by_b, t);
let by_b_to = by_b.lerp(to, t);
let from_by_a_by_a_by_b = from_by_a.lerp(by_a_by_b, t);
let by_a_by_b_by_b_to = by_a_by_b.lerp(by_b_to, t);
let next = from_by_a_by_a_by_b.lerp(by_a_by_b_by_b_to, t);
let result = Line {
from: prev,
to: next,
};
prev = next;
result
}))
}
}
}
}
impl Line {
pub fn distance(&self, p: Vec2) -> f32 {
let a = self.from;
let b = self.to;
let a_to_p = p - a;
let a_to_b = b - a;
let t = (a_to_p.dot(a_to_b) / a_to_b.length_squared())
.min(1.0)
.max(0.0);
((a + a_to_b * t) - p).length()
}
}
impl From<Line> for Shape {
fn from(val: Line) -> Self {
Self::Line(val)
}
}