1#![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
12pub type PointFunc<T> = Point<Arg<T>>;
14
15pub use math::*;
16pub use ops::*;
17
18pub mod math;
19pub mod ops;
20
21#[derive(Clone)]
23pub struct Point<T = ()> where f64: Ho<T> {
24 pub x: Fun<T, f64>,
26 pub y: Fun<T, f64>,
28 pub z: Fun<T, f64>,
30}
31
32impl Copy for Point {}
33
34impl PointFunc<[f64; 2]> {
35 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 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 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 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 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 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 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 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 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 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 pub fn x() -> Self {
235 Point {
236 x: Arc::new(move |v| v),
237 y: zero(),
238 z: zero(),
239 }
240 }
241
242 pub fn y() -> Self {
244 Point {
245 x: zero(),
246 y: Arc::new(move |v| v),
247 z: zero(),
248 }
249 }
250
251 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 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}