1use decorum::{Real, R64};
2use num::{Num, NumCast};
3use std::ops::{Add, AddAssign, Div, Mul, Neg, Sub};
4
5use crate::geometry::{self, Duplet, Triplet};
6use crate::Half;
7
8pub trait Normalize {
9 fn normalize(self) -> Self;
10}
11
12pub trait Average: Sized {
13 fn average<I>(values: I) -> Self
14 where
15 I: IntoIterator<Item = Self>;
16}
17
18pub trait Interpolate<T = Self>: Sized {
19 type Output;
20
21 fn lerp(self, other: T, f: R64) -> Self::Output;
22
23 fn midpoint(self, other: T) -> Self::Output {
24 self.lerp(other, Half::half())
25 }
26}
27
28pub trait Dot<T = Self> {
29 type Output;
30
31 fn dot(self, other: T) -> Self::Output;
32}
33
34pub trait Cross<T = Self> {
35 type Output;
36
37 fn cross(self, other: T) -> Self::Output;
38}
39
40pub trait Project<T = Self> {
41 type Output;
42
43 fn project(self, other: T) -> Self::Output;
44}
45
46impl<T> Project<T> for T
47where
48 T: Dot + Clone + Mul<<<Self as Dot>::Output as Div>::Output, Output = Self>,
49 <T as Dot>::Output: Div,
50{
51 type Output = T;
52
53 fn project(self, other: T) -> Self::Output {
54 let n = other.dot(self.clone());
55 let d = self.clone().dot(self.clone());
56 self * (n / d)
57 }
58}
59
60impl<T> Interpolate for Duplet<T>
61where
62 T: Copy + Num + NumCast,
63{
64 type Output = Self;
65
66 fn lerp(self, other: Self, f: R64) -> Self::Output {
67 Duplet(
68 geometry::lerp(self.0, other.0, f),
69 geometry::lerp(self.1, other.1, f),
70 )
71 }
72}
73
74impl<T> Normalize for Duplet<T>
75where
76 T: Real,
77{
78 fn normalize(self) -> Self {
79 let m = (self.0.powi(2) + self.1.powi(2)).sqrt();
80 Duplet(self.0 / m, self.1 / m)
81 }
82}
83
84impl<T> Average for Duplet<T>
85where
86 T: AddAssign + Clone + Num + NumCast,
87{
88 fn average<I>(values: I) -> Self
89 where
90 I: IntoIterator<Item = Self>,
91 {
92 let (n, sum) = {
93 let mut n = T::zero();
94 let mut sum = Duplet(T::zero(), T::zero());
95 for point in values {
96 n += T::one();
97 sum = Duplet(sum.0 + point.0, sum.1 + point.1);
98 }
99 (n, sum)
100 };
101 let m = T::one() / n;
102 Duplet(sum.0 * m.clone(), sum.1 * m)
103 }
104}
105
106impl<T> Dot for Duplet<T>
107where
108 T: Mul,
109 <T as Mul>::Output: Add<Output = T>,
110{
111 type Output = T;
112
113 fn dot(self, other: Self) -> Self::Output {
114 (self.0 * other.0) + (self.1 * other.1)
115 }
116}
117
118impl<T> Interpolate for Triplet<T>
119where
120 T: Copy + Num + NumCast,
121{
122 type Output = Self;
123
124 fn lerp(self, other: Self, f: R64) -> Self::Output {
125 Triplet(
126 geometry::lerp(self.0, other.0, f),
127 geometry::lerp(self.1, other.1, f),
128 geometry::lerp(self.2, other.2, f),
129 )
130 }
131}
132
133impl<T> Normalize for Triplet<T>
134where
135 T: Real,
136{
137 fn normalize(self) -> Self {
138 let m = (self.0.powi(2) + self.1.powi(2) + self.2.powi(2)).sqrt();
139 Triplet(self.0 / m, self.1 / m, self.2 / m)
140 }
141}
142
143impl<T> Average for Triplet<T>
144where
145 T: AddAssign + Clone + Num + NumCast,
146{
147 fn average<I>(values: I) -> Self
148 where
149 I: IntoIterator<Item = Self>,
150 {
151 let (n, sum) = {
152 let mut n = T::zero();
153 let mut sum = Triplet(T::zero(), T::zero(), T::zero());
154 for point in values {
155 n += T::one();
156 sum = Triplet(sum.0 + point.0, sum.1 + point.1, sum.2 + point.2);
157 }
158 (n, sum)
159 };
160 let m = T::one() / n;
161 Triplet(sum.0 * m.clone(), sum.1 * m.clone(), sum.2 * m)
162 }
163}
164
165impl<T> Dot for Triplet<T>
166where
167 T: Mul<Output = T>,
168 <T as Mul>::Output: Add<Output = T>,
169{
170 type Output = T;
171
172 fn dot(self, other: Self) -> Self::Output {
173 (self.0 * other.0) + (self.1 * other.1) + (self.2 * other.2)
174 }
175}
176
177impl<T> Cross for Triplet<T>
178where
179 T: Clone + Mul + Neg,
180 <T as Mul>::Output: Sub<Output = T>,
181 <<T as Mul>::Output as Sub>::Output: Neg<Output = T>,
182{
183 type Output = Self;
184
185 fn cross(self, other: Self) -> Self::Output {
186 Triplet(
187 (self.1.clone() * other.2.clone()) - (self.2.clone() * other.1.clone()),
188 -((self.0.clone() * other.2.clone()) - (self.2 * other.0.clone())),
189 (self.0.clone() * other.1.clone()) - (self.1 * other.0),
190 )
191 }
192}
193
194#[cfg(feature = "geometry-cgmath")]
195mod feature_geometry_cgmath {
196 use cgmath::{
197 BaseFloat, BaseNum, EuclideanSpace, InnerSpace, Point2, Point3, Vector2, Vector3,
198 };
199 use num::{Num, NumCast};
200 use std::ops::AddAssign;
201
202 use crate::geometry;
203 use crate::geometry::ops::*;
204
205 impl<T> Normalize for Vector2<T>
206 where
207 T: BaseFloat,
208 {
209 fn normalize(self) -> Self {
210 <Self as InnerSpace>::normalize(self)
211 }
212 }
213
214 impl<T> Normalize for Vector3<T>
215 where
216 T: BaseFloat,
217 {
218 fn normalize(self) -> Self {
219 <Self as InnerSpace>::normalize(self)
220 }
221 }
222
223 impl<T> Average for Point2<T>
224 where
225 T: AddAssign + BaseNum + NumCast,
226 {
227 fn average<I>(values: I) -> Self
228 where
229 I: IntoIterator<Item = Self>,
230 {
231 let (n, sum) = {
232 let mut n = T::zero();
233 let mut sum = Point2::origin();
234 for point in values {
235 n += T::one();
236 sum += Vector2::<T>::new(point.x, point.y);
237 }
238 (n, sum)
239 };
240 sum * (T::one() / n)
241 }
242 }
243
244 impl<T> Average for Point3<T>
245 where
246 T: AddAssign + BaseNum + NumCast,
247 {
248 fn average<I>(values: I) -> Self
249 where
250 I: IntoIterator<Item = Self>,
251 {
252 let (n, sum) = {
253 let mut n = T::zero();
254 let mut sum = Point3::origin();
255 for point in values {
256 n += T::one();
257 sum += Vector3::<T>::new(point.x, point.y, point.z);
258 }
259 (n, sum)
260 };
261 sum * (T::one() / n)
262 }
263 }
264
265 impl<T> Interpolate for Point2<T>
266 where
267 T: Num + NumCast,
268 {
269 type Output = Self;
270
271 fn lerp(self, other: Self, f: R64) -> Self::Output {
272 Point2::new(
273 geometry::lerp(self.x, other.x, f),
274 geometry::lerp(self.y, other.y, f),
275 )
276 }
277 }
278
279 impl<T> Interpolate for Point3<T>
280 where
281 T: Num + NumCast,
282 {
283 type Output = Self;
284
285 fn lerp(self, other: Self, f: R64) -> Self::Output {
286 Point3::new(
287 geometry::lerp(self.x, other.x, f),
288 geometry::lerp(self.y, other.y, f),
289 geometry::lerp(self.z, other.z, f),
290 )
291 }
292 }
293
294 impl<T> Interpolate for Vector2<T>
295 where
296 T: Num + NumCast,
297 {
298 type Output = Self;
299
300 fn lerp(self, other: Self, f: R64) -> Self::Output {
301 Vector2::new(
302 geometry::lerp(self.x, other.x, f),
303 geometry::lerp(self.y, other.y, f),
304 )
305 }
306 }
307
308 impl<T> Interpolate for Vector3<T>
309 where
310 T: Num + NumCast,
311 {
312 type Output = Self;
313
314 fn lerp(self, other: Self, f: R64) -> Self::Output {
315 Vector3::new(
316 geometry::lerp(self.x, other.x, f),
317 geometry::lerp(self.y, other.y, f),
318 geometry::lerp(self.z, other.z, f),
319 )
320 }
321 }
322
323 impl<T> Dot for Vector2<T>
324 where
325 T: BaseFloat,
326 {
327 type Output = T;
328
329 fn dot(self, other: Self) -> Self::Output {
330 <Self as InnerSpace>::dot(self, other)
331 }
332 }
333
334 impl<T> Dot for Vector3<T>
335 where
336 T: BaseFloat,
337 {
338 type Output = T;
339
340 fn dot(self, other: Self) -> Self::Output {
341 <Self as InnerSpace>::dot(self, other)
342 }
343 }
344
345 impl<T> Cross for Vector3<T>
346 where
347 T: BaseFloat,
348 {
349 type Output = Self;
350
351 fn cross(self, other: Self) -> Self::Output {
352 Self::cross(self, other)
353 }
354 }
355}
356
357#[cfg(feature = "geometry-mint")]
358mod feature_geometry_mint {
359 use decorum::Real;
360 use mint::{Point2, Point3, Vector2, Vector3};
361 use num::{Num, NumCast};
362 use std::ops::{Add, Mul, Neg, Sub};
363
364 use crate::geometry;
365 use crate::geometry::ops::*;
366
367 impl<T> Normalize for Vector2<T>
368 where
369 T: Real,
370 {
371 fn normalize(self) -> Self {
372 let m = (self.x.powi(2) + self.y.powi(2)).sqrt();
373 Vector2 {
374 x: self.x / m,
375 y: self.y / m,
376 }
377 }
378 }
379
380 impl<T> Normalize for Vector3<T>
381 where
382 T: Real,
383 {
384 fn normalize(self) -> Self {
385 let m = (self.x.powi(2) + self.y.powi(2) + self.z.powi(2)).sqrt();
386 Vector3 {
387 x: self.x / m,
388 y: self.y / m,
389 z: self.z / m,
390 }
391 }
392 }
393
394 impl<T> Average for Point2<T>
395 where
396 T: AddAssign + Clone + Num + NumCast,
397 {
398 fn average<I>(values: I) -> Self
399 where
400 I: IntoIterator<Item = Self>,
401 {
402 let (n, sum) = {
403 let mut n = T::zero();
404 let mut sum = Point2 {
405 x: T::zero(),
406 y: T::zero(),
407 };
408 for point in values {
409 n += T::one();
410 sum = Point2 {
411 x: sum.x + point.x,
412 y: sum.y + point.y,
413 };
414 }
415 (n, sum)
416 };
417 let m = T::one() / n;
418 Point2 {
419 x: sum.x * m.clone(),
420 y: sum.y * m,
421 }
422 }
423 }
424
425 impl<T> Average for Point3<T>
426 where
427 T: AddAssign + Clone + Num + NumCast,
428 {
429 fn average<I>(values: I) -> Self
430 where
431 I: IntoIterator<Item = Self>,
432 {
433 let (n, sum) = {
434 let mut n = T::zero();
435 let mut sum = Point3 {
436 x: T::zero(),
437 y: T::zero(),
438 z: T::zero(),
439 };
440 for point in values {
441 n += T::one();
442 sum = Point3 {
443 x: sum.x + point.x,
444 y: sum.y + point.y,
445 z: sum.z + point.z,
446 };
447 }
448 (n, sum)
449 };
450 let m = T::one() / n;
451 Point3 {
452 x: sum.x * m.clone(),
453 y: sum.y * m.clone(),
454 z: sum.z * m,
455 }
456 }
457 }
458
459 impl<T> Interpolate for Point2<T>
460 where
461 T: Num + NumCast,
462 {
463 type Output = Self;
464
465 fn lerp(self, other: Self, f: R64) -> Self::Output {
466 Point2 {
467 x: geometry::lerp(self.x, other.x, f),
468 y: geometry::lerp(self.y, other.y, f),
469 }
470 }
471 }
472
473 impl<T> Interpolate for Point3<T>
474 where
475 T: Num + NumCast,
476 {
477 type Output = Self;
478
479 fn lerp(self, other: Self, f: R64) -> Self::Output {
480 Point3 {
481 x: geometry::lerp(self.x, other.x, f),
482 y: geometry::lerp(self.y, other.y, f),
483 z: geometry::lerp(self.z, other.z, f),
484 }
485 }
486 }
487
488 impl<T> Interpolate for Vector2<T>
489 where
490 T: Num + NumCast,
491 {
492 type Output = Self;
493
494 fn lerp(self, other: Self, f: R64) -> Self::Output {
495 Vector2 {
496 x: geometry::lerp(self.x, other.x, f),
497 y: geometry::lerp(self.y, other.y, f),
498 }
499 }
500 }
501
502 impl<T> Interpolate for Vector3<T>
503 where
504 T: Num + NumCast,
505 {
506 type Output = Self;
507
508 fn lerp(self, other: Self, f: R64) -> Self::Output {
509 Vector3 {
510 x: geometry::lerp(self.x, other.x, f),
511 y: geometry::lerp(self.y, other.y, f),
512 z: geometry::lerp(self.z, other.z, f),
513 }
514 }
515 }
516
517 impl<T> Dot for Vector2<T>
518 where
519 T: Mul,
520 <T as Mul>::Output: Add<Output = T>,
521 {
522 type Output = T;
523
524 fn dot(self, other: Self) -> Self::Output {
525 (self.x * other.x) + (self.y * other.y)
526 }
527 }
528
529 impl<T> Dot for Vector3<T>
530 where
531 T: Mul<Output = T>,
532 <T as Mul>::Output: Add<Output = T>,
533 {
534 type Output = T;
535
536 fn dot(self, other: Self) -> Self::Output {
537 (self.x * other.x) + (self.y * other.y) + (self.z * other.z)
538 }
539 }
540
541 impl<T> Cross for Vector3<T>
542 where
543 T: Clone + Mul + Neg,
544 <T as Mul>::Output: Sub<Output = T>,
545 <<T as Mul>::Output as Sub>::Output: Neg<Output = T>,
546 {
547 type Output = Self;
548
549 fn cross(self, other: Self) -> Self::Output {
550 Vector3 {
551 x: (self.y.clone() * other.z.clone()) - (self.z.clone() * other.y.clone()),
552 y: -((self.x.clone() * other.z.clone()) - (self.z * other.x.clone())),
553 z: (self.x.clone() * other.y.clone()) - (self.y * other.x),
554 }
555 }
556 }
557}
558
559#[cfg(feature = "geometry-nalgebra")]
560mod feature_geometry_nalgebra {
561 use decorum::Real;
562 use nalgebra::core::Matrix;
563 use nalgebra::{Point2, Point3, Scalar, Vector2, Vector3};
564 use num::{Num, NumCast, Zero};
565 use std::ops::{AddAssign, Mul, MulAssign, Neg, Sub};
566
567 use crate::geometry;
568 use crate::geometry::ops::*;
569
570 impl<T> Normalize for Vector2<T>
571 where
572 T: Real + Scalar,
573 {
574 fn normalize(self) -> Self {
583 let m = (self.x.powi(2) + self.y.powi(2)).sqrt();
584 Vector2::new(self.x / m, self.y / m)
585 }
586 }
587
588 impl<T> Normalize for Vector3<T>
589 where
590 T: Real + Scalar,
591 {
592 fn normalize(self) -> Self {
601 let m = (self.x.powi(2) + self.y.powi(2) + self.z.powi(2)).sqrt();
602 Vector3::new(self.x / m, self.y / m, self.z / m)
603 }
604 }
605
606 impl<T> Average for Point2<T>
608 where
609 T: AddAssign + MulAssign + Num + NumCast + Scalar,
610 {
611 fn average<I>(values: I) -> Self
612 where
613 I: IntoIterator<Item = Self>,
614 {
615 let (n, sum) = {
616 let mut n = T::zero();
617 let mut sum = Point2::origin();
618 for point in values {
619 n += T::one();
620 sum += Vector2::<T>::new(point.x, point.y);
621 }
622 (n, sum)
623 };
624 sum * (T::one() / n)
625 }
626 }
627
628 impl<T> Average for Point3<T>
629 where
630 T: AddAssign + MulAssign + Num + NumCast + Scalar,
631 {
632 fn average<I>(values: I) -> Self
633 where
634 I: IntoIterator<Item = Self>,
635 {
636 let (n, sum) = {
637 let mut n = T::zero();
638 let mut sum = Point3::origin();
639 for point in values {
640 n += T::one();
641 sum += Vector3::<T>::new(point.x, point.y, point.z);
642 }
643 (n, sum)
644 };
645 sum * (T::one() / n)
646 }
647 }
648
649 impl<T> Interpolate for Point2<T>
650 where
651 T: Num + NumCast + Scalar,
652 {
653 type Output = Self;
654
655 fn lerp(self, other: Self, f: R64) -> Self::Output {
656 Point2::new(
657 geometry::lerp(self.x, other.x, f),
658 geometry::lerp(self.y, other.y, f),
659 )
660 }
661 }
662
663 impl<T> Interpolate for Point3<T>
664 where
665 T: Num + NumCast + Scalar,
666 {
667 type Output = Self;
668
669 fn lerp(self, other: Self, f: R64) -> Self::Output {
670 Point3::new(
671 geometry::lerp(self.x, other.x, f),
672 geometry::lerp(self.y, other.y, f),
673 geometry::lerp(self.z, other.z, f),
674 )
675 }
676 }
677
678 impl<T> Interpolate for Vector2<T>
679 where
680 T: Num + NumCast + Scalar,
681 {
682 type Output = Self;
683
684 fn lerp(self, other: Self, f: R64) -> Self::Output {
685 Vector2::new(
686 geometry::lerp(self.x, other.x, f),
687 geometry::lerp(self.y, other.y, f),
688 )
689 }
690 }
691
692 impl<T> Interpolate for Vector3<T>
693 where
694 T: Num + NumCast + Scalar,
695 {
696 type Output = Self;
697
698 fn lerp(self, other: Self, f: R64) -> Self::Output {
699 Vector3::new(
700 geometry::lerp(self.x, other.x, f),
701 geometry::lerp(self.y, other.y, f),
702 geometry::lerp(self.z, other.z, f),
703 )
704 }
705 }
706
707 impl<T> Dot for Vector2<T>
708 where
709 T: AddAssign + Mul<Output = T> + MulAssign + Scalar + Zero,
710 {
711 type Output = T;
712
713 fn dot(self, other: Self) -> Self::Output {
714 Matrix::dot(&self, &other)
715 }
716 }
717
718 impl<T> Dot for Vector3<T>
719 where
720 T: AddAssign + Mul<Output = T> + MulAssign + Scalar + Zero,
721 {
722 type Output = T;
723
724 fn dot(self, other: Self) -> Self::Output {
725 Matrix::dot(&self, &other)
726 }
727 }
728
729 impl<T> Cross for Vector3<T>
730 where
731 T: Mul + Neg + Scalar,
732 <T as Mul>::Output: Sub<Output = T>,
733 <<T as Mul>::Output as Sub>::Output: Neg<Output = T>,
734 {
735 type Output = Self;
736
737 fn cross(self, other: Self) -> Self::Output {
745 Vector3::new(
746 (self.y * other.z) - (self.z * other.y),
747 -((self.x * other.z) - (self.z * other.x)),
748 (self.x * other.y) - (self.y * other.x),
749 )
750 }
751 }
752}