higher_order_point/
lib.rs

1//! # Higher Order Point
2
3#![deny(missing_docs)]
4
5extern crate higher_order_core;
6
7use higher_order_core::*;
8
9use std::sync::Arc;
10use std::ops::{Add, Div, Mul, Sub};
11
12/// A point function.
13pub type PointFunc<T> = Point<Arg<T>>;
14
15pub use math::*;
16pub use ops::*;
17
18pub mod math;
19pub mod ops;
20
21/// 3D point.
22#[derive(Clone)]
23pub struct Point<T = ()> where f64: Ho<T> {
24    /// Function for x-coordinates.
25    pub x: Fun<T, f64>,
26    /// Function for y-coordinates.
27    pub y: Fun<T, f64>,
28    /// Function for z-coordinates.
29    pub z: Fun<T, f64>,
30}
31
32impl Copy for Point {}
33
34impl PointFunc<[f64; 2]> {
35    /// Returns ground plane with zero z-values.
36    pub fn ground_plane() -> Self {
37        Point {
38            x: Arc::new(move |p: [f64; 2]| p[0]),
39            y: Arc::new(move |p: [f64; 2]| p[1]),
40            z: zero(),
41        }
42    }
43}
44
45impl PointFunc<[f64; 3]> {
46    /// Returns plain Euclidean space.
47    pub fn space() -> Self {
48        Point {
49            x: Arc::new(move |p: [f64; 3]| p[0]),
50            y: Arc::new(move |p: [f64; 3]| p[1]),
51            z: Arc::new(move |p: [f64; 3]| p[2]),
52        }
53    }
54}
55
56impl std::fmt::Debug for Point {
57    fn fmt(&self, w: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
58        write!(w, "Point {{x: {:?}, y: {:?}, z: {:?}}}",
59            self.x,
60            self.y,
61            self.z
62        )
63    }
64}
65
66impl PartialEq for Point {
67    fn eq(&self, other: &Self) -> bool {
68        self.x == other.x && self.y == other.y && self.z == other.z
69    }
70}
71
72impl Dot for Point {
73    type Output = f64;
74    fn dot(self, other: Self) -> f64 {
75        self.x * other.x +
76        self.y * other.y +
77        self.z * other.z
78    }
79}
80
81impl<T: 'static + Copy> Dot for PointFunc<T> {
82    type Output = Func<T, f64>;
83    fn dot(self, other: Self) -> Func<T, f64> {
84        let ax = self.x;
85        let ay = self.y;
86        let az = self.z;
87        let bx = other.x;
88        let by = other.y;
89        let bz = other.z;
90        Arc::new(move |a| ax(a) * bx(a) + ay(a) * by(a) + az(a) * bz(a))
91    }
92}
93
94impl Cross for Point {
95    type Output = Point;
96    fn cross(self, other: Self) -> Self {
97        let a = self;
98        let b = other;
99        Point {
100            x: a.y * b.z - a.z * b.y,
101            y: a.z * b.x - a.x * b.z,
102            z: a.x * b.y - a.y * b.x,
103        }
104    }
105}
106
107impl<T: 'static + Copy> Cross for PointFunc<T> {
108    type Output = Self;
109    fn cross(self, other: Self) -> Self {
110        let ax1 = self.x.clone();
111        let ax2 = self.x;
112        let ay1 = self.y.clone();
113        let ay2 = self.y;
114        let az1 = self.z.clone();
115        let az2 = self.z;
116        let bx1 = other.x.clone();
117        let bx2 = other.x;
118        let by1 = other.y.clone();
119        let by2 = other.y;
120        let bz1 = other.z.clone();
121        let bz2 = other.z;
122        Point {
123            x: Arc::new(move |v| ay1(v) * bz1(v) - az1(v) * by1(v)),
124            y: Arc::new(move |v| az2(v) * bx1(v) - ax1(v) * bz2(v)),
125            z: Arc::new(move |v| ax2(v) * by2(v) - ay2(v) * bx2(v)),
126        }
127    }
128}
129
130impl Norm for Point {
131    type Output = f64;
132    fn norm(self) -> f64 {
133        (self.x * self.x + self.y * self.y + self.z * self.z).sqrt()
134    }
135}
136
137impl<T: 'static + Copy> Norm for PointFunc<T> {
138    type Output = Func<T, f64>;
139    fn norm(self) -> Func<T, f64> {
140        let fx = self.x;
141        let fy = self.y;
142        let fz = self.z;
143        Arc::new(move |v| (fx(v).powi(2) + fy(v).powi(2) + fz(v).powi(2)).sqrt())
144    }
145}
146
147impl<T: 'static> PointFunc<T> {
148    /// Adds another parameter to the right.
149    pub fn lift_right<U>(self) -> PointFunc<(T, U)> {
150        let fx = self.x;
151        let fy = self.y;
152        let fz = self.z;
153        Point {
154            x: Arc::new(move |(a, _)| fx(a)),
155            y: Arc::new(move |(a, _)| fy(a)),
156            z: Arc::new(move |(a, _)| fz(a)),
157        }
158    }
159
160    /// Adds another parameter to the left.
161    pub fn lift_left<U>(self) -> PointFunc<(U, T)> {
162        let fx = self.x;
163        let fy = self.y;
164        let fz = self.z;
165        Point {
166            x: Arc::new(move |(_, a)| fx(a)),
167            y: Arc::new(move |(_, a)| fy(a)),
168            z: Arc::new(move |(_, a)| fz(a)),
169        }
170    }
171
172    /// Helper method for calling value.
173    pub fn call(&self, val: T) -> Point where T: Copy {
174        <Point as Call<T>>::call(self, val)
175    }
176}
177
178impl<T: 'static, U> Map<T, U> for PointFunc<T> {
179    type Output = PointFunc<U>;
180    /// Maps input into another.
181    fn map<F: 'static + Fn(U) -> T + Clone + Send + Sync>(self, f: F) -> PointFunc<U> {
182        let fx = self.x;
183        let fy = self.y;
184        let fz = self.z;
185        let f1 = f.clone();
186        let f2 = f.clone();
187        let f3 = f;
188        Point {
189            x: Arc::new(move |v| fx(f1(v))),
190            y: Arc::new(move |v| fy(f2(v))),
191            z: Arc::new(move |v| fz(f3(v))),
192        }
193    }
194}
195
196impl PointFunc<f64> {
197    /// Creates a new circle in the xy-plane.
198    pub fn circle() -> Self {
199        Point {
200            x: Arc::new(move |ang: f64| (ang * TAU).cos()),
201            y: Arc::new(move |ang: f64| (ang * TAU).sin()),
202            z: zero(),
203        }
204    }
205
206    /// Creates a new circle in xy-plane that uses radians.
207    pub fn circle_radians() -> Self {
208        Point {
209            x: Arc::new(move |ang: f64| ang.cos()),
210            y: Arc::new(move |ang: f64| ang.sin()),
211            z: zero(),
212        }
213    }
214
215    /// Creates a new zig-zag function in the xy-plane.
216    pub fn zig_zag() -> Self {
217        Point {
218            x: zip(id(), Arc::new(move |a| a.floor() + 1.0)),
219            y: zip(floor(), id()),
220            z: zero(),
221        }
222    }
223
224    /// Creates a new zag-zig function in the xy-plane.
225    pub fn zag_zig() -> Self {
226        Point {
227            x: zip(floor(), id()),
228            y: zip(id(), Arc::new(move |a| a.floor() + 1.0)),
229            z: zero(),
230        }
231    }
232
233    /// Points along the x-axis.
234    pub fn x() -> Self {
235        Point {
236            x: Arc::new(move |v| v),
237            y: zero(),
238            z: zero(),
239        }
240    }
241
242    /// Points along the y-axis.
243    pub fn y() -> Self {
244        Point {
245            x: zero(),
246            y: Arc::new(move |v| v),
247            z: zero(),
248        }
249    }
250
251    /// Points along the z-axis.
252    pub fn z() -> Self {
253        Point {
254            x: zero(),
255            y: zero(),
256            z: Arc::new(move |v| v),
257        }
258    }
259}
260
261impl Diff for PointFunc<f64> {
262    fn diff(self, eps: f64) -> Self {
263        let fx = self.x;
264        let fy = self.y;
265        let fz = self.z;
266        Point {
267            x: Arc::new(move |t| (fx(t+eps)-fx(t))/eps),
268            y: Arc::new(move |t| (fy(t+eps)-fy(t))/eps),
269            z: Arc::new(move |t| (fz(t+eps)-fz(t))/eps),
270        }
271    }
272}
273
274impl<T: 'static + Copy> From<PointFunc<(T, T)>> for PointFunc<[T; 2]> {
275    fn from(val: PointFunc<(T, T)>) -> Self {
276        let fx = val.x;
277        let fy = val.y;
278        let fz = val.z;
279        Point {
280            x: Arc::new(move |a| fx((a[0], a[1]))),
281            y: Arc::new(move |a| fy((a[0], a[1]))),
282            z: Arc::new(move |a| fz((a[0], a[1]))),
283        }
284    }
285}
286
287impl<T: Clone> Ho<Arg<T>> for Point {
288    type Fun = PointFunc<T>;
289}
290
291impl<T: Copy> Call<T> for Point
292    where f64: Ho<Arg<T>> + Call<T>
293{
294    fn call(f: &Self::Fun, val: T) -> Point {
295        Point::<()> {
296            x: <f64 as Call<T>>::call(&f.x, val),
297            y: <f64 as Call<T>>::call(&f.y, val),
298            z: <f64 as Call<T>>::call(&f.z, val),
299        }
300    }
301}
302
303impl From<Point> for [f64; 3] {
304    fn from(val: Point) -> [f64; 3] {
305        [val.x, val.y, val.z]
306    }
307}
308
309impl Into<Point> for [f64; 3] {
310    fn into(self) -> Point {
311        Point {x: self[0], y: self[1], z: self[2]}
312    }
313}
314
315impl<T> Into<PointFunc<T>> for [f64; 3] {
316    fn into(self) -> PointFunc<T> {
317        let x = self[0];
318        let y = self[1];
319        let z = self[2];
320        Point {
321            x: Arc::new(move |_| x),
322            y: Arc::new(move |_| y),
323            z: Arc::new(move |_| z),
324        }
325    }
326}
327
328impl Add<f64> for Point {
329    type Output = Self;
330
331    fn add(self, val: f64) -> Self {
332        Point {
333            x: self.x + val,
334            y: self.y + val,
335            z: self.z + val,
336        }
337    }
338}
339
340impl Add for Point {
341    type Output = Self;
342
343    fn add(self, other: Self) -> Self {
344        Point {
345            x: self.x + other.x,
346            y: self.y + other.y,
347            z: self.z + other.z,
348        }
349    }
350}
351
352impl<T: 'static + Copy> Add for PointFunc<T> {
353    type Output = Self;
354
355    fn add(self, other: Self) -> Self {
356        Point {
357            x: add(self.x, other.x),
358            y: add(self.y, other.y),
359            z: add(self.z, other.z),
360        }
361    }
362}
363
364impl<T: 'static> Add<PointFunc<T>> for Point {
365    type Output = PointFunc<T>;
366
367    fn add(self, other: PointFunc<T>) -> PointFunc<T> {
368        let ax = self.x;
369        let ay = self.y;
370        let az = self.z;
371        let bx = other.x;
372        let by = other.y;
373        let bz = other.z;
374        Point {
375            x: Arc::new(move |a: T| ax + bx(a)),
376            y: Arc::new(move |a: T| ay + by(a)),
377            z: Arc::new(move |a: T| az + bz(a)),
378        }
379    }
380}
381
382impl<T: 'static, U: Into<Point>> Add<U> for PointFunc<T> {
383    type Output = PointFunc<T>;
384    fn add(self, other: U) -> PointFunc<T> {
385        let other = other.into();
386        let ax = self.x;
387        let ay = self.y;
388        let az = self.z;
389        let bx = other.x;
390        let by = other.y;
391        let bz = other.z;
392        Point {
393            x: Arc::new(move |a: T| ax(a) + bx),
394            y: Arc::new(move |a: T| ay(a) + by),
395            z: Arc::new(move |a: T| az(a) + bz),
396        }
397    }
398}
399
400impl<T: 'static + Copy> Add<Func<T, Point>> for PointFunc<T> {
401    type Output = PointFunc<T>;
402    fn add(self, other: Func<T, Point>) -> PointFunc<T> {
403        let ax = self.x;
404        let ay = self.y;
405        let az = self.z;
406        let ox = other.clone();
407        let oy = other.clone();
408        let oz = other;
409        Point {
410            x: Arc::new(move |t: T| ax(t) + ox(t).x),
411            y: Arc::new(move |t: T| ay(t) + oy(t).y),
412            z: Arc::new(move |t: T| az(t) + oz(t).z),
413        }
414    }
415}
416
417impl Sub<f64> for Point {
418    type Output = Self;
419    fn sub(self, val: f64) -> Self {
420        Point {
421            x: self.x - val,
422            y: self.y - val,
423            z: self.z - val,
424        }
425    }
426}
427
428impl Sub for Point {
429    type Output = Self;
430    fn sub(self, other: Self) -> Self {
431        Point {
432            x: self.x - other.x,
433            y: self.y - other.y,
434            z: self.z - other.z,
435        }
436    }
437}
438
439impl<T: 'static + Copy> Sub for PointFunc<T> {
440    type Output = Self;
441    fn sub(self, other: Self) -> Self {
442        Point {
443            x: sub(self.x, other.x),
444            y: sub(self.y, other.y),
445            z: sub(self.z, other.z),
446        }
447    }
448}
449
450impl<T: 'static> Sub<PointFunc<T>> for Point {
451    type Output = PointFunc<T>;
452    fn sub(self, other: PointFunc<T>) -> PointFunc<T> {
453        let ax = self.x;
454        let ay = self.y;
455        let az = self.z;
456        let bx = other.x;
457        let by = other.y;
458        let bz = other.z;
459        Point {
460            x: Arc::new(move |a: T| ax - bx(a)),
461            y: Arc::new(move |a: T| ay - by(a)),
462            z: Arc::new(move |a: T| az - bz(a)),
463        }
464    }
465}
466
467impl<T: 'static, U: Into<Point>> Sub<U> for PointFunc<T> {
468    type Output = Self;
469    fn sub(self, other: U) -> Self {
470        let other = other.into();
471        let ax = self.x;
472        let ay = self.y;
473        let az = self.z;
474        let bx = other.x;
475        let by = other.y;
476        let bz = other.z;
477        Point {
478            x: Arc::new(move |a: T| ax(a) - bx),
479            y: Arc::new(move |a: T| ay(a) - by),
480            z: Arc::new(move |a: T| az(a) - bz),
481        }
482    }
483}
484
485impl Mul<f64> for Point {
486    type Output = Self;
487    fn mul(self, other: f64) -> Self {
488        Point {
489            x: self.x * other,
490            y: self.y * other,
491            z: self.z * other,
492        }
493    }
494}
495
496impl<T: 'static> Mul<f64> for PointFunc<T> {
497    type Output = Self;
498    fn mul(self, other: f64) -> Self {
499        let x = self.x;
500        let y = self.y;
501        let z = self.z;
502        Point {
503            x: Arc::new(move |a: T| x(a) * other),
504            y: Arc::new(move |a: T| y(a) * other),
505            z: Arc::new(move |a: T| z(a) * other),
506        }
507    }
508}
509
510impl<T: 'static> Mul<Func<T, f64>> for Point {
511    type Output = PointFunc<T>;
512    fn mul(self, other: Func<T, f64>) -> PointFunc<T> {
513        let x = self.x;
514        let y = self.y;
515        let z = self.z;
516        let ox = other.clone();
517        let oy = other.clone();
518        let oz = other;
519        Point {
520            x: Arc::new(move |t| x * ox(t)),
521            y: Arc::new(move |t| y * oy(t)),
522            z: Arc::new(move |t| z * oz(t)),
523        }
524    }
525}
526
527impl<T: 'static + Copy> Mul<Func<T, f64>> for PointFunc<T> {
528    type Output = Self;
529    fn mul(self, other: Func<T, f64>) -> Self {
530        let x = self.x;
531        let y = self.y;
532        let z = self.z;
533        let ox = other.clone();
534        let oy = other.clone();
535        let oz = other;
536        Point {
537            x: Arc::new(move |a: T| x(a) * ox(a)),
538            y: Arc::new(move |a: T| y(a) * oy(a)),
539            z: Arc::new(move |a: T| z(a) * oz(a)),
540        }
541    }
542}
543
544impl<T: 'static> Mul<PointFunc<T>> for Point {
545    type Output = PointFunc<T>;
546    fn mul(self, other: PointFunc<T>) -> PointFunc<T> {
547        let x = self.x;
548        let y = self.y;
549        let z = self.z;
550        let ox = other.x;
551        let oy = other.y;
552        let oz = other.z;
553        Point {
554            x: Arc::new(move |t| x * ox(t)),
555            y: Arc::new(move |t| y * oy(t)),
556            z: Arc::new(move |t| z * oz(t)),
557        }
558    }
559}
560
561impl<T: 'static + Copy> Mul for PointFunc<T> {
562    type Output = Self;
563    fn mul(self, other: Self) -> Self {
564        let ax = self.x;
565        let ay = self.y;
566        let az = self.z;
567        let bx = other.x;
568        let by = other.y;
569        let bz = other.z;
570        Point {
571            x: Arc::new(move |t| ax(t) * bx(t)),
572            y: Arc::new(move |t| ay(t) * by(t)),
573            z: Arc::new(move |t| az(t) * bz(t)),
574        }
575    }
576}
577
578impl<T: 'static> Div<f64> for PointFunc<T> {
579    type Output = Self;
580    fn div(self, other: f64) -> Self {
581        let fx = self.x;
582        let fy = self.y;
583        let fz = self.z;
584        Point {
585            x: Arc::new(move |v| fx(v) / other),
586            y: Arc::new(move |v| fy(v) / other),
587            z: Arc::new(move |v| fz(v) / other),
588        }
589    }
590}
591
592impl<T: 'static + Copy> Div<Func<T, f64>> for PointFunc<T> {
593    type Output = Self;
594    fn div(self, other: Func<T, f64>) -> Self {
595        let fx = self.x;
596        let fy = self.y;
597        let fz = self.z;
598        let ox = other.clone();
599        let oy = other.clone();
600        let oz = other;
601        Point {
602            x: Arc::new(move |v| fx(v) / ox(v)),
603            y: Arc::new(move |v| fy(v) / oy(v)),
604            z: Arc::new(move |v| fz(v) / oz(v)),
605        }
606    }
607}
608
609#[cfg(test)]
610mod tests {
611    use super::*;
612
613    #[test]
614    fn bool_arg() {
615        let p: Point = Point {x: 2.0, y: 4.0, z: 6.0};
616        assert_eq!(p.x, 2.0);
617
618        let p: PointFunc<_> = Point {
619            x: Arc::new(move |b| if b {1.0} else {2.0}),
620            y: Arc::new(move |b| if b {3.0} else {4.0}),
621            z: Arc::new(move |_| 0.0),
622        };
623        assert_eq!((p.x)(true), 1.0);
624        assert_eq!((p.y)(false), 4.0);
625        let q1 = p.call(true);
626        assert_eq!(q1.x, 1.0);
627        assert_eq!(q1.y, 3.0);
628        let q2 = p.call(false);
629        assert_eq!(q2.x, 2.0);
630        assert_eq!(q2.y, 4.0);
631
632        let p: PointFunc<_> = Point {
633            x: k(1.0),
634            y: k(2.0),
635            z: zero(),
636        };
637        let q = p.call(());
638        assert_eq!(q.x, 1.0);
639        assert_eq!(q.y, 2.0);
640    }
641
642    #[test]
643    fn cylinder() {
644        let p: PointFunc<_> = Point {
645            x: Arc::new(move |(ang, _height): (f64, f64)| ang.cos()),
646            y: Arc::new(move |(ang, _height): (f64, f64)| ang.sin()),
647            z: zero(),
648        };
649        let q: PointFunc<_> = Point {
650            x: zero(),
651            y: zero(),
652            z: Arc::new(move |(_, height): (f64, f64)| height),
653        };
654        let r = p + q;
655        let r1 = r.call((0.0, 0.0));
656        assert_eq!(r1.x, 1.0);
657        assert_eq!(r1.y, 0.0);
658        assert_eq!(r1.z, 0.0);
659        let r2 = r.call((0.0, 1.0));
660        assert_eq!(r2.x, 1.0);
661        assert_eq!(r2.y, 0.0);
662        assert_eq!(r2.z, 1.0);
663    }
664
665    #[test]
666    fn lift() {
667        let p = Point::circle();
668        let q = Point::z();
669        let r = p.lift_right::<f64>() + q.lift_left::<f64>();
670        let r1 = r.call((0.0, 0.0));
671        assert_eq!(r1.x, 1.0);
672        assert_eq!(r1.y, 0.0);
673        assert_eq!(r1.z, 0.0);
674        let r2 = r.call((0.0, 1.0));
675        assert_eq!(r2.x, 1.0);
676        assert_eq!(r2.y, 0.0);
677        assert_eq!(r2.z, 1.0);
678    }
679
680    #[test]
681    fn mul_scalar() {
682        let p = Point::circle();
683        let q = p * 0.5;
684        assert_eq!((q.x)(0.0), 0.5);
685        assert_eq!((q.y)(0.0), 0.0);
686        assert!(((q.x)(0.25) - 0.0).abs() < 0.0000000001);
687        assert_eq!((q.y)(0.25), 0.5);
688    }
689
690    #[test]
691    fn disc() {
692        let p = Point::circle();
693        let q = id();
694        let r = p.lift_right::<f64>() * lift_left::<f64, _, _>(q);
695        let r1 = r.call((0.0, 1.0));
696        assert_eq!(r1.x, 1.0);
697        assert_eq!(r1.y, 0.0);
698        let r2 = r.call((0.25, 0.75));
699        assert!((r2.x - 0.0).abs() < 0.0000000001);
700        assert_eq!(r2.y, 0.75);
701    }
702
703    #[test]
704    fn into() {
705        let p = Point::circle();
706        let q = p.lift_right::<f64>();
707        let r: PointFunc<[f64; 2]> = q.into();
708        let r1 = r.call([0.0, 0.0]);
709        assert_eq!(r1.x, 1.0);
710        assert_eq!(r1.y, 0.0);
711    }
712
713    #[test]
714    fn line_shape() {
715        let p = Point::circle().lift_right::<f64>();
716        let q: Point = Point {x: 0.0, y: 0.0, z: 0.0};
717        let t = lift_left::<f64, f64, f64>(id());
718        let r1 = line(&p, &q, &t);
719        let r2 = line(&q, &p, &t);
720
721        let r1a = r1.call((0.0, 0.0));
722        assert_eq!(r1a.x, 1.0);
723        assert_eq!(r1a.y, 0.0);
724        let r1b = r1.call((0.0, 1.0));
725        assert_eq!(r1b.x, 0.0);
726        assert_eq!(r1b.y, 0.0);
727
728        let r2a = r2.call((0.0, 0.0));
729        assert_eq!(r2a.x, 0.0);
730        assert_eq!(r2a.y, 0.0);
731        let r2b = r2.call((0.0, 1.0));
732        assert_eq!(r2b.x, 1.0);
733        assert_eq!(r2b.y, 0.0);
734    }
735
736    #[test]
737    fn qbez_shape() {
738        // Create 3 circles that are transported along a line.
739        let a = Point::circle() + [0.0; 3];
740        let b = Point::circle() + [0.5, 0.0, 0.0];
741        let c = Point::circle() + [1.0, 0.0, 0.0];
742
743        let a = a.lift_right::<f64>();
744        let b = b.lift_right::<f64>();
745        let c = c.lift_right::<f64>();
746
747        let t = lift_left::<f64, f64, f64>(id());
748
749        let r = qbez!(&a, &b, &c, &t);
750
751        let r1 = r.call((0.0, 0.0));
752        assert_eq!(r1.x, 1.0);
753        assert_eq!(r1.y, 0.0);
754        let r2 = r.call((0.0, 0.5));
755        assert_eq!(r2.x, 1.5);
756        assert_eq!(r2.y, 0.0);
757        let r3 = r.call((0.0, 1.0));
758        assert_eq!(r3.x, 2.0);
759        assert_eq!(r3.y, 0.0);
760
761        let r1 = r.call((0.25, 0.0));
762        assert!((r1.x - 0.0).abs() < 0.0000001);
763        assert_eq!(r1.y, 1.0);
764        let r2 = r.call((0.25, 0.5));
765        assert_eq!(r2.x, 0.5);
766        assert_eq!(r2.y, 1.0);
767        let r3 = r.call((0.25, 1.0));
768        assert_eq!(r3.x, 1.0);
769        assert_eq!(r3.y, 1.0);
770    }
771
772    #[test]
773    fn cbez_shape() {
774        let a = Point::circle() - [0.0; 3];
775        let b = Point::circle() - [0.5, 0.0, 0.0];
776        let c = Point::circle() - [1.0, 0.0, 0.0];
777
778        let a = a.lift_right::<f64>();
779        let b = b.lift_right::<f64>();
780        let c = c.lift_right::<f64>();
781
782        let t = lift_left::<f64, f64, f64>(id());
783
784        let r: PointFunc<(f64, f64)> = cbez!(&a, &b, &b, &c, &t);
785
786        let r1 = r.call((0.0, 0.0));
787        assert_eq!(r1.x, 1.0);
788        let r2 = r.call((0.0, 0.5));
789        assert_eq!(r2.x, 0.5);
790        let r3 = r.call((0.0, 1.0));
791        assert_eq!(r3.x, 0.0);
792    }
793
794    #[test]
795    fn into_function() {
796        let _: PointFunc<[f64; 2]> = [0.0; 3].into();
797    }
798
799    #[test]
800    fn dot() {
801        let a: PointFunc<f64> = [1.0, 0.0, 0.0].into();
802        let b: PointFunc<f64> = [0.5, 0.5, 0.0].into();
803        let c = a.dot(b);
804        let c0 = c(0.0);
805        assert_eq!(c0, 0.5);
806    }
807
808    #[test]
809    fn cross() {
810        let a = Point::circle();
811        let b = Point::circle().map(|t| t + 0.25);
812        let c = a.cross(b);
813
814        let c1 = c.call(0.0);
815        assert_eq!(c1.x, 0.0);
816        assert_eq!(c1.y, 0.0);
817        assert_eq!(c1.z, 1.0);
818
819        let c2 = c.call(0.25);
820        assert_eq!(c2.x, 0.0);
821        assert_eq!(c2.y, 0.0);
822        assert_eq!(c2.z, 1.0);
823    }
824
825    #[test]
826    fn diff() {
827        let a = Point::circle();
828        let da = a.diff(0.00000001);
829
830        let a1 = da.call(0.0);
831        assert!((a1.x - 0.0).abs() < 0.000001);
832        assert!((a1.y - TAU).abs() < 0.00001);
833        assert_eq!(a1.z, 0.0);
834
835        let a2 = da.call(0.25);
836        assert!((a2.x + TAU).abs() < 0.000001);
837        assert!((a2.y - 0.0).abs() < 0.00001);
838        assert_eq!(a2.z, 0.0);
839    }
840
841    #[test]
842    fn norm() {
843        let a = Point::circle();
844        let b = a.clone().norm();
845        assert_eq!(b(0.0), 1.0);
846        assert_eq!(b(0.25), 1.0);
847
848        let _ = a.clone() / b;
849        let _ = a / 2.0;
850    }
851
852    #[test]
853    fn test_step() {
854        let a = Point::circle() * step();
855
856        let a1 = a.call(-0.001);
857        assert_eq!(a1.x, 0.0);
858        assert_eq!(a1.y, 0.0);
859        assert_eq!(a1.z, 0.0);
860
861        let a2 = a.call(0.0);
862        assert_eq!(a2.x, 1.0);
863        assert_eq!(a2.y, 0.0);
864        assert_eq!(a2.z, 0.0);
865    }
866
867    #[test]
868    fn test_floor() {
869        let a = Point::circle() * floor();
870
871        assert_eq!(a.call(-2.0).x, -2.0);
872        assert_eq!(a.call(-1.0).x, -1.0);
873        assert_eq!(a.call(0.0).x, 0.0);
874        assert_eq!(a.call(1.0).x, 1.0);
875    }
876
877    #[test]
878    fn zig_zag() {
879        let a = Point::zig_zag();
880        let a1 = a.call(0.0);
881        assert_eq!(a1.x, 0.0);
882        assert_eq!(a1.y, 0.0);
883        let a2 = a.call(0.5);
884        assert_eq!(a2.x, 0.5);
885        assert_eq!(a2.y, 0.0);
886        let a3 = a.call(1.0);
887        assert_eq!(a3.x, 1.0);
888        assert_eq!(a3.y, 0.0);
889        let a4 = a.call(1.5);
890        assert_eq!(a4.x, 1.0);
891        assert_eq!(a4.y, 0.5);
892        let a5 = a.call(2.0);
893        assert_eq!(a5.x, 1.0);
894        assert_eq!(a5.y, 1.0);
895        let a6 = a.call(2.5);
896        assert_eq!(a6.x, 1.5);
897        assert_eq!(a6.y, 1.0);
898        let a7 = a.call(3.0);
899        assert_eq!(a7.x, 2.0);
900        assert_eq!(a7.y, 1.0);
901        let a8 = a.call(3.5);
902        assert_eq!(a8.x, 2.0);
903        assert_eq!(a8.y, 1.5);
904        let a9 = a.call(4.0);
905        assert_eq!(a9.x, 2.0);
906        assert_eq!(a9.y, 2.0);
907    }
908
909    #[test]
910    fn into_vec() {
911        let a = Point {x: 0.0, y: 1.0, z: 2.0};
912        let b: [f64; 3] = a.into();
913        assert_eq!(b, [0.0, 1.0, 2.0]);
914    }
915}