1#![warn(missing_docs)]
6
7use core::iter::Sum;
8use core::ops::{Add, Mul, Sub};
9
10pub fn deform_affine(
16 controls_p: &[(f32, f32)], controls_q: &[(f32, f32)], point: (f32, f32), ) -> (f32, f32) {
20 let v = Point::from(point);
21 let sqr_dist = |p: Point| (p - v).sqr_norm();
22
23 let weight = |pt| 1.0 / sqr_dist(pt);
26 let w_all: Vec<_> = controls_p.iter().map(|&p| weight(p.into())).collect();
27 let w_sum: f32 = w_all.iter().sum();
28 if w_sum.is_infinite() {
29 let index = w_all
32 .iter()
33 .position(|w| w.is_infinite())
34 .expect("There is an infinite sum of the weights but none is infinite");
35 return controls_q[index];
36 }
37
38 let wp_star_sum: Point = w_all
40 .iter()
41 .zip(controls_p)
42 .map(|(&w, &p)| w * Point::from(p))
43 .sum();
44 let p_star = (1.0 / w_sum) * wp_star_sum;
45
46 let wq_star_sum: Point = w_all
48 .iter()
49 .zip(controls_q)
50 .map(|(&w, &q)| w * Point::from(q))
51 .sum();
52 let q_star = (1.0 / w_sum) * wq_star_sum;
53
54 let p_hat: Vec<Point> = controls_p
56 .iter()
57 .map(|&p| Point::from(p) - p_star)
58 .collect();
59 let mp: Mat2 = w_all
61 .iter()
62 .zip(&p_hat)
63 .map(|(&w, &p)| w * p.times_transpose(p))
64 .sum();
65 let mq: Mat2 = w_all
67 .iter()
68 .zip(&p_hat)
69 .zip(controls_q)
70 .map(|((&w, &ph), &q)| {
71 let qh = Point::from(q) - q_star;
72 (w * ph).times_transpose(qh)
73 })
74 .sum();
75
76 ((v - p_star).transpose_mul(mp.inv()).transpose_mul(mq) + q_star).into()
78}
79
80pub fn deform_similarity(
86 controls_p: &[(f32, f32)], controls_q: &[(f32, f32)], point: (f32, f32), ) -> (f32, f32) {
90 let v = Point::from(point);
91 let sqr_dist = |p: Point| (p - v).sqr_norm();
92
93 let weight = |pt| 1.0 / sqr_dist(pt);
96 let w_all: Vec<_> = controls_p.iter().map(|&p| weight(p.into())).collect();
97 let w_sum: f32 = w_all.iter().sum();
98 if w_sum.is_infinite() {
99 let index = w_all
102 .iter()
103 .position(|w| w.is_infinite())
104 .expect("There is an infinite sum of the weights but none is infinite");
105 return controls_q[index];
106 }
107
108 let wp_star_sum: Point = w_all
110 .iter()
111 .zip(controls_p)
112 .map(|(&w, &p)| w * Point::from(p))
113 .sum();
114 let p_star = (1.0 / w_sum) * wp_star_sum;
115
116 let wq_star_sum: Point = w_all
118 .iter()
119 .zip(controls_q)
120 .map(|(&w, &q)| w * Point::from(q))
121 .sum();
122 let q_star = (1.0 / w_sum) * wq_star_sum;
123
124 let p_hat: Vec<Point> = controls_p
126 .iter()
127 .map(|&p| Point::from(p) - p_star)
128 .collect();
129
130 let q_hat: Vec<Point> = controls_q
132 .iter()
133 .map(|&q| Point::from(q) - q_star)
134 .collect();
135
136 let mu_s: f32 = w_all
138 .iter()
139 .zip(&p_hat)
140 .map(|(wi, pi)| wi * pi.sqr_norm())
141 .sum();
142
143 let m: Mat2 = w_all
145 .iter()
146 .zip(&p_hat)
147 .zip(&q_hat)
148 .map(|((&wi, pi), qi)| {
149 let p_mat = Mat2 {
150 m11: pi.x,
151 m12: pi.y,
152 m21: pi.y,
153 m22: -pi.x,
154 };
155 let q_mat = Mat2 {
156 m11: qi.x,
157 m21: qi.y,
158 m12: qi.y,
159 m22: -qi.x,
160 };
161 wi * p_mat * q_mat
162 })
163 .sum();
164 let m = (1.0 / mu_s) * m;
165
166 ((v - p_star).transpose_mul(m) + q_star).into()
168}
169
170pub fn deform_rigid(
176 controls_p: &[(f32, f32)], controls_q: &[(f32, f32)], point: (f32, f32), ) -> (f32, f32) {
180 let v = Point::from(point);
181 let sqr_dist = |p: Point| (p - v).sqr_norm();
182
183 let weight = |pt| 1.0 / sqr_dist(pt);
186 let w_all: Vec<_> = controls_p.iter().map(|&p| weight(p.into())).collect();
187 let w_sum: f32 = w_all.iter().sum();
188 if w_sum.is_infinite() {
189 let index = w_all
192 .iter()
193 .position(|w| w.is_infinite())
194 .expect("There is an infinite sum of the weights but none is infinite");
195 return controls_q[index];
196 }
197
198 let wp_star_sum: Point = w_all
200 .iter()
201 .zip(controls_p)
202 .map(|(&w, &p)| w * Point::from(p))
203 .sum();
204 let p_star = (1.0 / w_sum) * wp_star_sum;
205
206 let wq_star_sum: Point = w_all
208 .iter()
209 .zip(controls_q)
210 .map(|(&w, &q)| w * Point::from(q))
211 .sum();
212 let q_star = (1.0 / w_sum) * wq_star_sum;
213
214 let p_hat: Vec<Point> = controls_p
216 .iter()
217 .map(|&p| Point::from(p) - p_star)
218 .collect();
219
220 let q_hat: Vec<Point> = controls_q
222 .iter()
223 .map(|&q| Point::from(q) - q_star)
224 .collect();
225
226 let mu_r_vec: Point = w_all
228 .iter()
229 .zip(&p_hat)
230 .zip(&q_hat)
231 .map(|((&wi, pi), qi)| {
232 let pi_perp = Point { x: -pi.y, y: pi.x };
233 Point {
234 x: wi * qi.dot(*pi),
235 y: wi * qi.dot(pi_perp),
236 }
237 })
238 .sum();
239 let mu_r = mu_r_vec.sqr_norm().sqrt();
240
241 let m: Mat2 = w_all
243 .iter()
244 .zip(&p_hat)
245 .zip(&q_hat)
246 .map(|((&wi, pi), qi)| {
247 let p_mat = Mat2 {
248 m11: pi.x,
249 m12: pi.y,
250 m21: pi.y,
251 m22: -pi.x,
252 };
253 let q_mat = Mat2 {
254 m11: qi.x,
255 m21: qi.y,
256 m12: qi.y,
257 m22: -qi.x,
258 };
259 wi * p_mat * q_mat
260 })
261 .sum();
262 let m = (1.0 / mu_r) * m;
263
264 ((v - p_star).transpose_mul(m) + q_star).into()
266}
267
268#[derive(Clone, Copy)]
273struct Point {
274 x: f32,
275 y: f32,
276}
277
278impl Point {
279 fn zero() -> Self {
281 Self { x: 0.0, y: 0.0 }
282 }
283
284 fn dot(self, rhs: Self) -> f32 {
286 self.x * rhs.x + self.y * rhs.y
287 }
288
289 fn sqr_norm(self) -> f32 {
291 self.x * self.x + self.y * self.y
292 }
293
294 fn times_transpose(self, rhs: Self) -> Mat2 {
296 Mat2 {
297 m11: self.x * rhs.x,
298 m21: self.y * rhs.x,
299 m12: self.x * rhs.y,
300 m22: self.y * rhs.y,
301 }
302 }
303
304 fn transpose_mul(self, rhs: Mat2) -> Self {
307 Self {
308 x: rhs.m11 * self.x + rhs.m21 * self.y,
309 y: rhs.m12 * self.x + rhs.m22 * self.y,
310 }
311 }
312}
313
314impl From<(f32, f32)> for Point {
316 fn from((x, y): (f32, f32)) -> Self {
317 Point { x, y }
318 }
319}
320
321impl From<Point> for (f32, f32) {
323 fn from(point: Point) -> (f32, f32) {
324 (point.x, point.y)
325 }
326}
327
328impl Add for Point {
330 type Output = Self;
331 fn add(self, rhs: Self) -> Self::Output {
332 Self {
333 x: self.x + rhs.x,
334 y: self.y + rhs.y,
335 }
336 }
337}
338
339impl Sub for Point {
341 type Output = Self;
342 fn sub(self, rhs: Self) -> Self::Output {
343 Self {
344 x: self.x - rhs.x,
345 y: self.y - rhs.y,
346 }
347 }
348}
349
350impl Mul<Point> for f32 {
352 type Output = Point;
353 fn mul(self, rhs: Point) -> Self::Output {
354 Point {
355 x: self * rhs.x,
356 y: self * rhs.y,
357 }
358 }
359}
360
361impl Sum for Point {
363 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
364 iter.fold(Self::zero(), |s, p| s + p)
365 }
366}
367
368#[derive(Clone, Copy)]
376struct Mat2 {
377 m11: f32,
378 m21: f32,
379 m12: f32,
380 m22: f32,
381}
382
383impl Mat2 {
384 fn zero() -> Self {
386 Self {
387 m11: 0.0,
388 m21: 0.0,
389 m12: 0.0,
390 m22: 0.0,
391 }
392 }
393
394 fn det(self) -> f32 {
396 self.m11 * self.m22 - self.m21 * self.m12
397 }
398
399 fn inv(self) -> Self {
401 1.0 / self.det()
402 * Self {
403 m11: self.m22,
404 m21: -self.m21,
405 m12: -self.m12,
406 m22: self.m11,
407 }
408 }
409}
410
411impl Add for Mat2 {
413 type Output = Self;
414 fn add(self, rhs: Self) -> Self::Output {
415 Self {
416 m11: self.m11 + rhs.m11,
417 m21: self.m21 + rhs.m21,
418 m12: self.m12 + rhs.m12,
419 m22: self.m22 + rhs.m22,
420 }
421 }
422}
423
424impl Mul<Mat2> for f32 {
426 type Output = Mat2;
427 fn mul(self, rhs: Mat2) -> Self::Output {
428 Mat2 {
429 m11: self * rhs.m11,
430 m21: self * rhs.m21,
431 m12: self * rhs.m12,
432 m22: self * rhs.m22,
433 }
434 }
435}
436
437impl Mul for Mat2 {
439 type Output = Self;
440 fn mul(self, rhs: Self) -> Self::Output {
441 Mat2 {
442 m11: self.m11 * rhs.m11 + self.m12 * rhs.m21,
443 m21: self.m21 * rhs.m11 + self.m22 * rhs.m21,
444 m12: self.m11 * rhs.m12 + self.m12 * rhs.m22,
445 m22: self.m21 * rhs.m12 + self.m22 * rhs.m22,
446 }
447 }
448}
449
450impl Sum for Mat2 {
452 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
453 iter.fold(Self::zero(), |s, m| s + m)
454 }
455}