plexus/geometry/
convert.rs

1use num::{NumCast, ToPrimitive};
2
3use crate::geometry::{Duplet, Triplet};
4
5pub trait FromGeometry<T> {
6    fn from_geometry(other: T) -> Self;
7}
8
9pub trait IntoGeometry<T> {
10    fn into_geometry(self) -> T;
11}
12
13impl<T, U> IntoGeometry<U> for T
14where
15    U: FromGeometry<T>,
16{
17    fn into_geometry(self) -> U {
18        U::from_geometry(self)
19    }
20}
21
22impl<T> FromGeometry<T> for T {
23    fn from_geometry(other: T) -> Self {
24        other
25    }
26}
27
28impl<T, U> FromGeometry<(U, U)> for Duplet<T>
29where
30    T: NumCast,
31    U: ToPrimitive,
32{
33    fn from_geometry(other: (U, U)) -> Self {
34        Duplet(T::from(other.0).unwrap(), T::from(other.1).unwrap())
35    }
36}
37
38impl<T, U> FromGeometry<(U, U, U)> for Triplet<T>
39where
40    T: NumCast,
41    U: ToPrimitive,
42{
43    fn from_geometry(other: (U, U, U)) -> Self {
44        Triplet(
45            T::from(other.0).unwrap(),
46            T::from(other.1).unwrap(),
47            T::from(other.2).unwrap(),
48        )
49    }
50}
51
52// TODO: The interior versions of geometry conversion traits do not have a
53//       reflexive implementation. This allows for conversions from `Mesh<T>`
54//       to `Mesh<U>`, where `T` and `U` may be the same.
55//
56//       This is a bit confusing; consider removing these if they aren't
57//       useful.
58pub trait FromInteriorGeometry<T> {
59    fn from_interior_geometry(other: T) -> Self;
60}
61
62pub trait IntoInteriorGeometry<T> {
63    fn into_interior_geometry(self) -> T;
64}
65
66impl<T, U> IntoInteriorGeometry<U> for T
67where
68    U: FromInteriorGeometry<T>,
69{
70    fn into_interior_geometry(self) -> U {
71        U::from_interior_geometry(self)
72    }
73}
74
75/// Exposes a reference to positional vertex data.
76///
77/// To enable geometric features, this trait must be implemented for the type
78/// representing vertex data. Additionally, geometric operations should be
79/// implemented for the `Target` type.
80pub trait AsPosition {
81    type Target;
82
83    fn as_position(&self) -> &Self::Target;
84    fn as_position_mut(&mut self) -> &mut Self::Target;
85}
86
87// TODO: Implement `FromGeometry` for points and vectors with `FloatProxy`
88//       scalars once specialization lands. This isn't possible now, because it
89//       would conflict with the blanket implementation for some shared scalar
90//       type `T`, which is arguably a more important implementation.
91#[cfg(feature = "geometry-cgmath")]
92mod feature_geometry_cgmath {
93    use cgmath::{Point2, Point3, Vector2, Vector3};
94    use decorum::{Finite, NotNan, Ordered, Primitive};
95    use num::Float;
96
97    use crate::geometry::convert::*;
98    use crate::geometry::{Duplet, Triplet};
99
100    // TODO: Implement `FromGeometry` for proxy types via specialization.
101    // TODO: Implement these conversions for two-dimensional points.
102    macro_rules! ordered {
103        (geometry => $g:ident,proxy => $p:ident) => {
104            impl<T> FromGeometry<$g<$p<T>>> for $g<T>
105            where
106                T: Float + Primitive,
107            {
108                fn from_geometry(other: $g<$p<T>>) -> Self {
109                    $g::new(
110                        other.x.into_inner(),
111                        other.y.into_inner(),
112                        other.z.into_inner(),
113                    )
114                }
115            }
116
117            impl<T> FromGeometry<$g<T>> for $g<$p<T>>
118            where
119                T: Float + Primitive,
120            {
121                fn from_geometry(other: $g<T>) -> Self {
122                    $g::new(
123                        $p::<T>::from_inner(other.x),
124                        $p::<T>::from_inner(other.y),
125                        $p::<T>::from_inner(other.z),
126                    )
127                }
128            }
129        };
130    }
131    ordered!(geometry => Point3, proxy => Finite);
132    ordered!(geometry => Point3, proxy => NotNan);
133    ordered!(geometry => Point3, proxy => Ordered);
134
135    impl<T, U> FromGeometry<(U, U)> for Point2<T>
136    where
137        T: NumCast,
138        U: ToPrimitive,
139    {
140        fn from_geometry(other: (U, U)) -> Self {
141            Point2::new(T::from(other.0).unwrap(), T::from(other.1).unwrap())
142        }
143    }
144
145    impl<T, U> FromGeometry<(U, U, U)> for Point3<T>
146    where
147        T: NumCast,
148        U: ToPrimitive,
149    {
150        fn from_geometry(other: (U, U, U)) -> Self {
151            Point3::new(
152                T::from(other.0).unwrap(),
153                T::from(other.1).unwrap(),
154                T::from(other.2).unwrap(),
155            )
156        }
157    }
158
159    impl<T, U> FromGeometry<Duplet<U>> for Point2<T>
160    where
161        T: NumCast,
162        U: ToPrimitive,
163    {
164        fn from_geometry(other: Duplet<U>) -> Self {
165            Point2::new(T::from(other.0).unwrap(), T::from(other.1).unwrap())
166        }
167    }
168
169    impl<T, U> FromGeometry<Triplet<U>> for Point3<T>
170    where
171        T: NumCast,
172        U: ToPrimitive,
173    {
174        fn from_geometry(other: Triplet<U>) -> Self {
175            Point3::new(
176                T::from(other.0).unwrap(),
177                T::from(other.1).unwrap(),
178                T::from(other.2).unwrap(),
179            )
180        }
181    }
182
183    impl<T, U> FromGeometry<(U, U)> for Vector2<T>
184    where
185        T: NumCast,
186        U: ToPrimitive,
187    {
188        fn from_geometry(other: (U, U)) -> Self {
189            Vector2::new(T::from(other.0).unwrap(), T::from(other.1).unwrap())
190        }
191    }
192
193    impl<T, U> FromGeometry<(U, U, U)> for Vector3<T>
194    where
195        T: NumCast,
196        U: ToPrimitive,
197    {
198        fn from_geometry(other: (U, U, U)) -> Self {
199            Vector3::new(
200                T::from(other.0).unwrap(),
201                T::from(other.1).unwrap(),
202                T::from(other.2).unwrap(),
203            )
204        }
205    }
206
207    impl<T, U> FromGeometry<Duplet<U>> for Vector2<T>
208    where
209        T: NumCast,
210        U: ToPrimitive,
211    {
212        fn from_geometry(other: Duplet<U>) -> Self {
213            Vector2::new(T::from(other.0).unwrap(), T::from(other.1).unwrap())
214        }
215    }
216
217    impl<T, U> FromGeometry<Triplet<U>> for Vector3<T>
218    where
219        T: NumCast,
220        U: ToPrimitive,
221    {
222        fn from_geometry(other: Triplet<U>) -> Self {
223            Vector3::new(
224                T::from(other.0).unwrap(),
225                T::from(other.1).unwrap(),
226                T::from(other.2).unwrap(),
227            )
228        }
229    }
230
231    impl<T> AsPosition for Point2<T> {
232        type Target = Self;
233
234        fn as_position(&self) -> &Self::Target {
235            self
236        }
237
238        fn as_position_mut(&mut self) -> &mut Self::Target {
239            self
240        }
241    }
242
243    impl<T> AsPosition for Point3<T> {
244        type Target = Self;
245
246        fn as_position(&self) -> &Self::Target {
247            self
248        }
249
250        fn as_position_mut(&mut self) -> &mut Self::Target {
251            self
252        }
253    }
254}
255
256#[cfg(feature = "geometry-mint")]
257mod feature_geometry_mint {
258    use decorum::{Finite, NotNan, Ordered, Primitive};
259    use mint::{Point2, Point3, Vector2, Vector3};
260    use num::{Float, NumCast, ToPrimitive};
261
262    use crate::geometry::convert::*;
263    use crate::geometry::{Duplet, Triplet};
264
265    // TODO: Implement `FromGeometry` for proxy types via specialization.
266    // TODO: Implement these conversions for two-dimensional points.
267    macro_rules! ordered {
268        (geometry => $g:ident,proxy => $p:ident) => {
269            impl<T> FromGeometry<$g<$p<T>>> for $g<T>
270            where
271                T: Float + Primitive,
272            {
273                fn from_geometry(other: $g<$p<T>>) -> Self {
274                    $g {
275                        x: other.x.into_inner(),
276                        y: other.y.into_inner(),
277                        z: other.z.into_inner(),
278                    }
279                }
280            }
281
282            impl<T> FromGeometry<$g<T>> for $g<$p<T>>
283            where
284                T: Float + Primitive,
285            {
286                fn from_geometry(other: $g<T>) -> Self {
287                    $g {
288                        x: $p::<T>::from_inner(other.x),
289                        y: $p::<T>::from_inner(other.y),
290                        z: $p::<T>::from_inner(other.z),
291                    }
292                }
293            }
294        };
295    }
296    ordered!(geometry => Point3, proxy => Finite);
297    ordered!(geometry => Point3, proxy => NotNan);
298    ordered!(geometry => Point3, proxy => Ordered);
299
300    impl<T, U> FromGeometry<(U, U)> for Point2<T>
301    where
302        T: NumCast,
303        U: ToPrimitive,
304    {
305        fn from_geometry(other: (U, U)) -> Self {
306            Point2 {
307                x: T::from(other.0).unwrap(),
308                y: T::from(other.1).unwrap(),
309            }
310        }
311    }
312
313    impl<T, U> FromGeometry<(U, U, U)> for Point3<T>
314    where
315        T: NumCast,
316        U: ToPrimitive,
317    {
318        fn from_geometry(other: (U, U, U)) -> Self {
319            Point3 {
320                x: T::from(other.0).unwrap(),
321                y: T::from(other.1).unwrap(),
322                z: T::from(other.2).unwrap(),
323            }
324        }
325    }
326
327    impl<T, U> FromGeometry<Duplet<U>> for Point2<T>
328    where
329        T: NumCast,
330        U: ToPrimitive,
331    {
332        fn from_geometry(other: Duplet<U>) -> Self {
333            Point2 {
334                x: T::from(other.0).unwrap(),
335                y: T::from(other.1).unwrap(),
336            }
337        }
338    }
339
340    impl<T, U> FromGeometry<Triplet<U>> for Point3<T>
341    where
342        T: NumCast,
343        U: ToPrimitive,
344    {
345        fn from_geometry(other: Triplet<U>) -> Self {
346            Point3 {
347                x: T::from(other.0).unwrap(),
348                y: T::from(other.1).unwrap(),
349                z: T::from(other.2).unwrap(),
350            }
351        }
352    }
353
354    impl<T, U> FromGeometry<(U, U)> for Vector2<T>
355    where
356        T: NumCast,
357        U: ToPrimitive,
358    {
359        fn from_geometry(other: (U, U)) -> Self {
360            Vector2 {
361                x: T::from(other.0).unwrap(),
362                y: T::from(other.1).unwrap(),
363            }
364        }
365    }
366
367    impl<T, U> FromGeometry<(U, U, U)> for Vector3<T>
368    where
369        T: NumCast,
370        U: ToPrimitive,
371    {
372        fn from_geometry(other: (U, U, U)) -> Self {
373            Vector3 {
374                x: T::from(other.0).unwrap(),
375                y: T::from(other.1).unwrap(),
376                z: T::from(other.2).unwrap(),
377            }
378        }
379    }
380
381    impl<T, U> FromGeometry<Duplet<U>> for Vector2<T>
382    where
383        T: NumCast,
384        U: ToPrimitive,
385    {
386        fn from_geometry(other: Duplet<U>) -> Self {
387            Vector2 {
388                x: T::from(other.0).unwrap(),
389                y: T::from(other.1).unwrap(),
390            }
391        }
392    }
393
394    impl<T, U> FromGeometry<Triplet<U>> for Vector3<T>
395    where
396        T: NumCast,
397        U: ToPrimitive,
398    {
399        fn from_geometry(other: Triplet<U>) -> Self {
400            Vector3 {
401                x: T::from(other.0).unwrap(),
402                y: T::from(other.1).unwrap(),
403                z: T::from(other.2).unwrap(),
404            }
405        }
406    }
407
408    impl<T> AsPosition for Point2<T> {
409        type Target = Self;
410
411        fn as_position(&self) -> &Self::Target {
412            self
413        }
414
415        fn as_position_mut(&mut self) -> &mut Self::Target {
416            self
417        }
418    }
419
420    impl<T> AsPosition for Point3<T> {
421        type Target = Self;
422
423        fn as_position(&self) -> &Self::Target {
424            self
425        }
426
427        fn as_position_mut(&mut self) -> &mut Self::Target {
428            self
429        }
430    }
431}
432
433#[cfg(feature = "geometry-nalgebra")]
434mod feature_geometry_nalgebra {
435    use decorum::{Finite, NotNan, Ordered, Primitive};
436    use nalgebra::{Point2, Point3, Scalar, Vector2, Vector3};
437    use num::{Float, NumCast, ToPrimitive};
438
439    use crate::geometry::convert::*;
440    use crate::geometry::{Duplet, Triplet};
441
442    // TODO: Implement `FromGeometry` for proxy types via specialization.
443    // TODO: Implement these conversions for two-dimensional points.
444    macro_rules! ordered {
445        (geometry => $g:ident,proxy => $p:ident) => {
446            impl<T> FromGeometry<$g<$p<T>>> for $g<T>
447            where
448                T: Float + Primitive + Scalar,
449            {
450                fn from_geometry(other: $g<$p<T>>) -> Self {
451                    $g::new(
452                        other.x.into_inner(),
453                        other.y.into_inner(),
454                        other.z.into_inner(),
455                    )
456                }
457            }
458
459            impl<T> FromGeometry<$g<T>> for $g<$p<T>>
460            where
461                T: Float + Primitive + Scalar,
462            {
463                fn from_geometry(other: $g<T>) -> Self {
464                    $g::new(
465                        $p::<T>::from_inner(other.x),
466                        $p::<T>::from_inner(other.y),
467                        $p::<T>::from_inner(other.z),
468                    )
469                }
470            }
471        };
472    }
473    ordered!(geometry => Point3, proxy => Finite);
474    ordered!(geometry => Point3, proxy => NotNan);
475    ordered!(geometry => Point3, proxy => Ordered);
476
477    impl<T, U> FromGeometry<(U, U)> for Point2<T>
478    where
479        T: NumCast + Scalar,
480        U: ToPrimitive,
481    {
482        fn from_geometry(other: (U, U)) -> Self {
483            Point2::new(T::from(other.0).unwrap(), T::from(other.1).unwrap())
484        }
485    }
486
487    impl<T, U> FromGeometry<(U, U, U)> for Point3<T>
488    where
489        T: NumCast + Scalar,
490        U: ToPrimitive,
491    {
492        fn from_geometry(other: (U, U, U)) -> Self {
493            Point3::new(
494                T::from(other.0).unwrap(),
495                T::from(other.1).unwrap(),
496                T::from(other.2).unwrap(),
497            )
498        }
499    }
500
501    impl<T, U> FromGeometry<Duplet<U>> for Point2<T>
502    where
503        T: NumCast + Scalar,
504        U: ToPrimitive,
505    {
506        fn from_geometry(other: Duplet<U>) -> Self {
507            Point2::new(T::from(other.0).unwrap(), T::from(other.1).unwrap())
508        }
509    }
510
511    impl<T, U> FromGeometry<Triplet<U>> for Point3<T>
512    where
513        T: NumCast + Scalar,
514        U: ToPrimitive,
515    {
516        fn from_geometry(other: Triplet<U>) -> Self {
517            Point3::new(
518                T::from(other.0).unwrap(),
519                T::from(other.1).unwrap(),
520                T::from(other.2).unwrap(),
521            )
522        }
523    }
524
525    impl<T, U> FromGeometry<(U, U)> for Vector2<T>
526    where
527        T: NumCast + Scalar,
528        U: ToPrimitive,
529    {
530        fn from_geometry(other: (U, U)) -> Self {
531            Vector2::new(T::from(other.0).unwrap(), T::from(other.1).unwrap())
532        }
533    }
534
535    impl<T, U> FromGeometry<(U, U, U)> for Vector3<T>
536    where
537        T: NumCast + Scalar,
538        U: ToPrimitive,
539    {
540        fn from_geometry(other: (U, U, U)) -> Self {
541            Vector3::new(
542                T::from(other.0).unwrap(),
543                T::from(other.1).unwrap(),
544                T::from(other.2).unwrap(),
545            )
546        }
547    }
548
549    impl<T, U> FromGeometry<Duplet<U>> for Vector2<T>
550    where
551        T: NumCast + Scalar,
552        U: ToPrimitive,
553    {
554        fn from_geometry(other: Duplet<U>) -> Self {
555            Vector2::new(T::from(other.0).unwrap(), T::from(other.1).unwrap())
556        }
557    }
558
559    impl<T, U> FromGeometry<Triplet<U>> for Vector3<T>
560    where
561        T: NumCast + Scalar,
562        U: ToPrimitive,
563    {
564        fn from_geometry(other: Triplet<U>) -> Self {
565            Vector3::new(
566                T::from(other.0).unwrap(),
567                T::from(other.1).unwrap(),
568                T::from(other.2).unwrap(),
569            )
570        }
571    }
572
573    impl<T> AsPosition for Point2<T>
574    where
575        T: Scalar,
576    {
577        type Target = Self;
578
579        fn as_position(&self) -> &Self::Target {
580            self
581        }
582
583        fn as_position_mut(&mut self) -> &mut Self::Target {
584            self
585        }
586    }
587
588    impl<T> AsPosition for Point3<T>
589    where
590        T: Scalar,
591    {
592        type Target = Self;
593
594        fn as_position(&self) -> &Self::Target {
595            self
596        }
597
598        fn as_position_mut(&mut self) -> &mut Self::Target {
599            self
600        }
601    }
602}