1use std::hash::{
2 Hash,
3 Hasher,
4};
5use std::ops::{
6 Index,
7 IndexMut,
8};
9
10use fnv::FnvHasher;
11
12pub fn quantize(a: f32, d: f32) -> f32 {
13 (a / d + 0.5).trunc() * d
14}
15
16pub fn pt_equals(x1: f32, y1: f32, x2: f32, y2: f32, tol: f32) -> bool {
17 let dx = x2 - x1;
18 let dy = y2 - y1;
19
20 dx * dx + dy * dy < tol * tol
21}
22
23pub fn cross(dx0: f32, dy0: f32, dx1: f32, dy1: f32) -> f32 {
24 dx1 * dy0 - dx0 * dy1
25}
26
27pub fn dist_pt_segment(x: f32, y: f32, px: f32, py: f32, qx: f32, qy: f32) -> f32 {
28 let pqx = qx - px;
29 let pqy = qy - py;
30 let dx = x - px;
31 let dy = y - py;
32 let d = pqx * pqx + pqy * pqy;
33 let mut t = pqx * dx + pqy * dy;
34
35 if d > 0.0 {
36 t /= d;
37 }
38
39 if t < 0.0 {
40 t = 0.0;
41 } else if t > 1.0 {
42 t = 1.0;
43 }
44
45 let dx = px + t * pqx - x;
46 let dy = py + t * pqy - y;
47
48 dx * dx + dy * dy
49}
50
51pub fn normalize(x: &mut f32, y: &mut f32) -> f32 {
53 let d = ((*x) * (*x) + (*y) * (*y)).sqrt();
54
55 if d > 1e-6 {
56 let id = 1.0 / d;
57 *x *= id;
58 *y *= id;
59 }
60
61 d
62}
63
64#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
68#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
69pub struct Transform2D(pub [f32; 6]);
70
71impl Transform2D {
73 pub fn identity() -> Self {
75 Self([1.0, 0.0, 0.0, 1.0, 0.0, 0.0])
76 }
77
78 pub fn new_translation(x: f32, y: f32) -> Self {
80 let mut new = Self::identity();
81 new.translate(x, y);
82 new
83 }
84
85 pub fn translate(&mut self, tx: f32, ty: f32) {
87 self[4] = tx;
90 self[5] = ty;
91 }
92
93 pub fn scale(&mut self, sx: f32, sy: f32) {
95 self[0] = sx;
96 self[1] = 0.0;
97 self[2] = 0.0;
98 self[3] = sy;
99 self[4] = 0.0;
100 self[5] = 0.0;
101 }
102
103 pub fn rotate(&mut self, a: f32) {
105 let cs = a.cos();
106 let sn = a.sin();
107
108 self[0] = cs;
109 self[1] = sn;
110 self[2] = -sn;
111 self[3] = cs;
112 self[4] = 0.0;
113 self[5] = 0.0;
114 }
115
116 pub fn skew_x(&mut self, a: f32) {
118 self[0] = 1.0;
119 self[1] = 0.0;
120 self[2] = a.tan();
121 self[3] = 1.0;
122 self[4] = 0.0;
123 self[5] = 0.0;
124 }
125
126 pub fn skew_y(&mut self, a: f32) {
128 self[0] = 1.0;
129 self[1] = a.tan();
130 self[2] = 0.0;
131 self[3] = 1.0;
132 self[4] = 0.0;
133 self[5] = 0.0;
134 }
135
136 pub fn multiply(&mut self, other: &Self) {
138 let t0 = self[0] * other[0] + self[1] * other[2];
139 let t2 = self[2] * other[0] + self[3] * other[2];
140 let t4 = self[4] * other[0] + self[5] * other[2] + other[4];
141 self[1] = self[0] * other[1] + self[1] * other[3];
142 self[3] = self[2] * other[1] + self[3] * other[3];
143 self[5] = self[4] * other[1] + self[5] * other[3] + other[5];
144 self[0] = t0;
145 self[2] = t2;
146 self[4] = t4;
147 }
148
149 pub fn premultiply(&mut self, other: &Self) {
151 let mut other = *other;
152 other.multiply(self);
153 *self = other;
154 }
155
156 pub fn inverse(&mut self) {
158 let t = *self;
159 let det = t[0] as f64 * t[3] as f64 - t[2] as f64 * t[1] as f64;
160
161 if det > -1e-6 && det < 1e-6 {
162 *self = Self::identity();
163 }
164
165 let invdet = 1.0 / det;
166
167 self[0] = (t[3] as f64 * invdet) as f32;
168 self[2] = (-t[2] as f64 * invdet) as f32;
169 self[4] = ((t[2] as f64 * t[5] as f64 - t[3] as f64 * t[4] as f64) * invdet) as f32;
170 self[1] = (-t[1] as f64 * invdet) as f32;
171 self[3] = (t[0] as f64 * invdet) as f32;
172 self[5] = ((t[1] as f64 * t[4] as f64 - t[0] as f64 * t[5] as f64) * invdet) as f32;
173 }
174
175 pub fn inversed(&self) -> Self {
177 let mut inv = *self;
178 inv.inverse();
179 inv
180 }
181
182 pub fn transform_point(&self, sx: f32, sy: f32) -> (f32, f32) {
184 let dx = sx * self[0] + sy * self[2] + self[4];
185 let dy = sx * self[1] + sy * self[3] + self[5];
186 (dx, dy)
187 }
188
189 pub fn average_scale(&self) -> f32 {
191 let sx = (self[0] * self[0] + self[2] * self[2]).sqrt();
192 let sy = (self[1] * self[1] + self[3] * self[3]).sqrt();
193
194 (sx + sy) * 0.5
195 }
196
197 pub fn to_mat3x4(self) -> [f32; 12] {
199 [
200 self[0], self[1], 0.0, 0.0, self[2], self[3], 0.0, 0.0, self[4], self[5], 1.0, 0.0,
201 ]
202 }
203
204 pub fn cache_key(&self) -> u64 {
206 let mut hasher = FnvHasher::default();
207
208 for i in 0..6 {
209 self.0[i].to_bits().hash(&mut hasher);
210 }
211
212 hasher.finish()
213 }
214}
215
216impl Default for Transform2D {
217 fn default() -> Self {
218 Self::identity()
219 }
220}
221
222impl Index<usize> for Transform2D {
223 type Output = f32;
224
225 fn index(&self, index: usize) -> &Self::Output {
226 &self.0[index]
227 }
228}
229
230impl IndexMut<usize> for Transform2D {
231 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
232 &mut self.0[index]
233 }
234}
235
236#[derive(Copy, Clone, Default, Debug, PartialEq, PartialOrd)]
237pub struct Rect {
238 pub x: f32,
239 pub y: f32,
240 pub w: f32,
241 pub h: f32,
242}
243
244impl Rect {
245 pub fn new(x: f32, y: f32, w: f32, h: f32) -> Self {
246 Self { x, y, w, h }
247 }
248
249 pub fn intersect(&self, other: Rect) -> Rect {
250 let minx = self.x.max(other.x);
251 let miny = self.y.max(other.y);
252 let maxx = (self.x + self.w).min(other.x + other.w);
253 let maxy = (self.y + self.h).min(other.y + other.h);
254
255 Rect::new(minx, miny, 0.0f32.max(maxx - minx), 0.0f32.max(maxy - miny))
256 }
257}
258
259#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
260pub struct Bounds {
261 pub minx: f32,
262 pub miny: f32,
263 pub maxx: f32,
264 pub maxy: f32,
265}
266
267impl Default for Bounds {
268 fn default() -> Self {
269 Self {
270 minx: 1e6,
271 miny: 1e6,
272 maxx: -1e6,
273 maxy: -1e6,
274 }
275 }
276}