Sat, 22 Oct 2022 18:12:49 +0300
Fix some unit tests after fundamental changes that made them invalid
0 | 1 | /// Various types of sets. |
2 | use std::ops::{RangeFull,RangeFrom,Range,RangeInclusive,RangeTo,RangeToInclusive}; | |
3 | use std::marker::PhantomData; | |
4 | use crate::types::*; | |
5 | use crate::loc::{Loc}; | |
6 | use crate::norms::Dot; | |
7 | use serde::Serialize; | |
8 | ||
9 | pub mod cube; | |
10 | pub use cube::*; | |
11 | ||
12 | /// Trait for arbitrary sets. The parameter `U` is the element type. | |
13 | pub trait Set<U> where U : ?Sized { | |
14 | /// Check for containment. | |
15 | fn contains(&self, item : &U) -> bool; | |
16 | } | |
17 | ||
18 | pub trait SetOrd : Sized { | |
19 | /// Returns the smallest set of same class contain both parameters. | |
20 | fn common(&self, other : &Self) -> Self; | |
21 | ||
22 | /// Returns the greatest set of same class contaied by n both parameter sets. | |
23 | fn intersect(&self, other : &Self) -> Option<Self>; | |
24 | } | |
25 | ||
26 | impl<U, const N : usize> Set<Loc<U, N>> | |
27 | for Cube<U,N> | |
28 | where U : Num + PartialOrd + Sized { | |
29 | fn contains(&self, item : &Loc<U, N>) -> bool { | |
30 | self.0.iter().zip(item.iter()).all(|(s, x)| s.contains(x)) | |
31 | } | |
32 | } | |
33 | ||
34 | impl<U> Set<U> for RangeFull { | |
35 | fn contains(&self, _item : &U) -> bool { true } | |
36 | } | |
37 | ||
38 | macro_rules! impl_ranges { | |
39 | ($($range:ident),*) => { $( | |
40 | impl<U,Idx> Set<U> | |
41 | for $range<Idx> | |
42 | where Idx : PartialOrd<U>, U : PartialOrd<Idx> + ?Sized, Idx : PartialOrd { | |
43 | #[inline] | |
44 | fn contains(&self, item : &U) -> bool { $range::contains(&self, item) } | |
45 | } | |
46 | )* } | |
47 | } | |
48 | ||
49 | impl_ranges!(RangeFrom,Range,RangeInclusive,RangeTo,RangeToInclusive); | |
50 | ||
51 | /// Halfspace. The orthogonal (dual) vectors `A` are supposed to implement [`Dot`]`<U,F>` | |
52 | /// for `U` the element type. | |
53 | #[derive(Clone,Copy,Debug,Serialize,Eq,PartialEq)] | |
54 | pub struct Halfspace<A, F, U> where A : Dot<U,F>, F : Float { | |
55 | pub orthogonal : A, | |
56 | pub offset : F, | |
57 | _phantom : PhantomData<U>, | |
58 | } | |
59 | ||
60 | impl<A,F,U> Halfspace<A,F,U> where A : Dot<U,F>, F : Float { | |
61 | #[inline] | |
62 | pub fn new(orthogonal : A, offset : F) -> Self { | |
63 | Halfspace{ orthogonal : orthogonal, offset : offset, _phantom : PhantomData } | |
64 | } | |
65 | } | |
66 | ||
67 | pub trait SpannedHalfspace<F,U> where F : Float { | |
68 | type A : Dot<U,F>; | |
69 | fn spanned_halfspace(&self) -> Halfspace<Self::A, F, U>; | |
70 | } | |
71 | ||
72 | // TODO: Gram-Schmidt for higher N. | |
73 | impl<F : Float> SpannedHalfspace<F,Loc<F, 1>> for [Loc<F, 1>; 2] { | |
74 | type A = Loc<F, 1>; | |
75 | fn spanned_halfspace(&self) -> Halfspace<Self::A, F, Loc<F, 1>> { | |
76 | let (x0, x1) = (self[0], self[1]); | |
77 | Halfspace::new(x1-x0, x0[0]) | |
78 | } | |
79 | } | |
80 | ||
81 | // TODO: Gram-Schmidt for higher N. | |
82 | impl<F : Float> SpannedHalfspace<F,Loc<F, 2>> for [Loc<F, 2>; 2] { | |
83 | type A = Loc<F, 2>; | |
84 | fn spanned_halfspace(&self) -> Halfspace<Self::A, F, Loc<F, 2>> { | |
85 | let (x0, x1) = (&self[0], &self[1]); | |
86 | let d = x1 - x0; | |
87 | let orthog = loc![d[1], -d[0]]; // We don't normalise for efficiency | |
88 | let offset = x0.dot(&orthog); | |
89 | Halfspace::new(orthog, offset) | |
90 | } | |
91 | } | |
92 | ||
93 | impl<A,U,F> Set<U> for Halfspace<A,F,U> where A : Dot<U,F>, F : Float { | |
94 | #[inline] | |
95 | fn contains(&self, item : &U) -> bool { | |
96 | self.orthogonal.dot(item) >= self.offset | |
97 | } | |
98 | } | |
99 | ||
100 | /// Polygons defined by `N` `Halfspace`s. | |
101 | #[derive(Clone,Copy,Debug,Eq,PartialEq)] | |
102 | pub struct NPolygon<A, F, U, const N : usize>(pub [Halfspace<A,F,U>; N]) where A : Dot<U,F>, F : Float; | |
103 | ||
104 | impl<A,U,F,const N : usize> Set<U> for NPolygon<A,F,U,N> where A : Dot<U,F>, F : Float { | |
105 | fn contains(&self, item : &U) -> bool { | |
106 | self.0.iter().all(|halfspace| halfspace.contains(item)) | |
107 | } | |
108 | } |