| 70 /// Halfspaces described by an orthogonal vector and an offset. |
70 /// Halfspaces described by an orthogonal vector and an offset. |
| 71 /// |
71 /// |
| 72 /// The halfspace is $H = \\{ t v + a \mid a^⊤ v = 0 \\}$, where $v$ is the orthogonal |
72 /// The halfspace is $H = \\{ t v + a \mid a^⊤ v = 0 \\}$, where $v$ is the orthogonal |
| 73 /// vector and $t$ the offset. |
73 /// vector and $t$ the offset. |
| 74 #[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)] |
74 #[derive(Clone, Copy, Debug, Serialize, Eq, PartialEq)] |
| 75 pub struct Halfspace<A, F> |
75 pub struct Halfspace<A> |
| 76 where |
76 where |
| 77 A: Euclidean<F>, |
77 A: Euclidean, |
| 78 F: Float, |
|
| 79 { |
78 { |
| 80 pub orthogonal: A, |
79 pub orthogonal: A, |
| 81 pub offset: F, |
80 pub offset: A::Field, |
| 82 } |
81 } |
| 83 |
82 |
| 84 impl<A, F> Halfspace<A, F> |
83 impl<A> Halfspace<A> |
| 85 where |
84 where |
| 86 A: Euclidean<F>, |
85 A: Euclidean, |
| 87 F: Float, |
|
| 88 { |
86 { |
| 89 #[inline] |
87 #[inline] |
| 90 pub fn new(orthogonal: A, offset: F) -> Self { |
88 pub fn new(orthogonal: A, offset: A::Field) -> Self { |
| 91 Halfspace { |
89 Halfspace { |
| 92 orthogonal: orthogonal, |
90 orthogonal: orthogonal, |
| 93 offset: offset, |
91 offset: offset, |
| 94 } |
92 } |
| 95 } |
93 } |
| 96 } |
94 } |
| 97 |
95 |
| 98 /// Trait for generating a halfspace spanned by another set `Self` of elements of type `U`. |
96 /// Trait for generating a halfspace spanned by another set `Self` of elements of type `U`. |
| 99 pub trait SpannedHalfspace<F> |
97 pub trait SpannedHalfspace { |
| 100 where |
|
| 101 F: Float, |
|
| 102 { |
|
| 103 /// Type of the orthogonal vector describing the halfspace. |
98 /// Type of the orthogonal vector describing the halfspace. |
| 104 type A: Euclidean<F>; |
99 type A: Euclidean; |
| 105 /// Returns the halfspace spanned by this set. |
100 /// Returns the halfspace spanned by this set. |
| 106 fn spanned_halfspace(&self) -> Halfspace<Self::A, F>; |
101 fn spanned_halfspace(&self) -> Halfspace<Self::A>; |
| 107 } |
102 } |
| 108 |
103 |
| 109 // TODO: Gram-Schmidt for higher N. |
104 // TODO: Gram-Schmidt for higher N. |
| 110 impl<F: Float> SpannedHalfspace<F> for [Loc<1, F>; 2] { |
105 impl<F: Float> SpannedHalfspace for [Loc<1, F>; 2] { |
| 111 type A = Loc<1, F>; |
106 type A = Loc<1, F>; |
| 112 fn spanned_halfspace(&self) -> Halfspace<Self::A, F> { |
107 fn spanned_halfspace(&self) -> Halfspace<Self::A> { |
| 113 let (x0, x1) = (self[0], self[1]); |
108 let (x0, x1) = (self[0], self[1]); |
| 114 Halfspace::new(x1 - x0, x0[0]) |
109 Halfspace::new(x1 - x0, x0[0]) |
| 115 } |
110 } |
| 116 } |
111 } |
| 117 |
112 |
| 118 // TODO: Gram-Schmidt for higher N. |
113 // TODO: Gram-Schmidt for higher N. |
| 119 impl<F: Float> SpannedHalfspace<F> for [Loc<2, F>; 2] { |
114 impl<F: Float> SpannedHalfspace for [Loc<2, F>; 2] { |
| 120 type A = Loc<2, F>; |
115 type A = Loc<2, F>; |
| 121 fn spanned_halfspace(&self) -> Halfspace<Self::A, F> { |
116 fn spanned_halfspace(&self) -> Halfspace<Self::A> { |
| 122 let (x0, x1) = (&self[0], &self[1]); |
117 let (x0, x1) = (&self[0], &self[1]); |
| 123 let d = x1 - x0; |
118 let d = x1 - x0; |
| 124 let orthog = loc![d[1], -d[0]]; // We don't normalise for efficiency |
119 let orthog = loc![d[1], -d[0]]; // We don't normalise for efficiency |
| 125 let offset = x0.dot(&orthog); |
120 let offset = x0.dot(&orthog); |
| 126 Halfspace::new(orthog, offset) |
121 Halfspace::new(orthog, offset) |
| 127 } |
122 } |
| 128 } |
123 } |
| 129 |
124 |
| 130 impl<A, F> Set<A> for Halfspace<A, F> |
125 impl<A> Set<A> for Halfspace<A> |
| 131 where |
126 where |
| 132 A: Euclidean<F>, |
127 A: Euclidean, |
| 133 F: Float, |
|
| 134 { |
128 { |
| 135 #[inline] |
129 #[inline] |
| 136 fn contains<I: Instance<A>>(&self, item: I) -> bool { |
130 fn contains<I: Instance<A>>(&self, item: I) -> bool { |
| 137 self.orthogonal.dot(item) >= self.offset |
131 self.orthogonal.dot(item) >= self.offset |
| 138 } |
132 } |
| 139 } |
133 } |
| 140 |
134 |
| 141 /// Polygons defined by `N` `Halfspace`s. |
135 /// Polygons defined by `N` `Halfspace`s. |
| 142 #[derive(Clone, Copy, Debug, Eq, PartialEq)] |
136 #[derive(Clone, Copy, Debug, PartialEq)] |
| 143 pub struct NPolygon<A, const N: usize, F = f64>(pub [Halfspace<A, F>; N]) |
137 pub struct NPolygon<A: Euclidean, const N: usize>(pub [Halfspace<A>; N]); |
| 144 where |
|
| 145 A: Euclidean<F>, |
|
| 146 F: Float; |
|
| 147 |
138 |
| 148 impl<A, F, const N: usize> Set<A> for NPolygon<A, N, F> |
139 impl<A: Euclidean, const N: usize> Set<A> for NPolygon<A, N> { |
| 149 where |
|
| 150 A: Euclidean<F>, |
|
| 151 F: Float, |
|
| 152 { |
|
| 153 fn contains<I: Instance<A>>(&self, item: I) -> bool { |
140 fn contains<I: Instance<A>>(&self, item: I) -> bool { |
| 154 let r = item.ref_instance(); |
141 let r = item.ref_instance(); |
| 155 self.0.iter().all(|halfspace| halfspace.contains(r)) |
142 self.0.iter().all(|halfspace| halfspace.contains(r)) |
| 156 } |
143 } |
| 157 } |
144 } |