1use super::*;
2use crate::{
3 affine_subspace::EmbeddedAffineSubspace, ambient_space::AffineSpace,
4 oriented_simplex::OrientedSimplex, vector::Vector,
5};
6use itertools::Itertools;
7
8#[derive(Clone)]
9pub struct Simplex<'f, FS: OrderedRingSignature + FieldSignature> {
10 ambient_space: AffineSpace<'f, FS>,
11 points: Vec<Vector<'f, FS>>,
15}
16
17impl<'f, FS: OrderedRingSignature + FieldSignature> std::fmt::Debug for Simplex<'f, FS> {
18 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19 f.debug_struct("Simplex")
20 .field("points", &self.points)
21 .finish()
22 }
23}
24
25impl<'f, FS: OrderedRingSignature + FieldSignature> PartialEq for Simplex<'f, FS> {
26 fn eq(&self, other: &Self) -> bool {
27 self.ambient_space == other.ambient_space && self.points == other.points
28 }
29}
30
31impl<'f, FS: OrderedRingSignature + FieldSignature> Eq for Simplex<'f, FS> {}
32
33impl<'f, FS: OrderedRingSignature + FieldSignature> Hash for Simplex<'f, FS>
34where
35 FS::Set: Hash,
36{
37 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
38 self.points.hash(state);
39 }
40}
41
42impl<'f, FS: OrderedRingSignature + FieldSignature> Simplex<'f, FS>
43where
44 AffineSpace<'f, FS>: Clone,
45{
46 fn new(
47 ambient_space: AffineSpace<'f, FS>,
48 mut points: Vec<Vector<'f, FS>>,
49 ) -> Result<Self, &'static str> {
50 for point in &points {
51 assert_eq!(ambient_space, point.ambient_space());
52 }
53 points.sort_unstable();
54 if ambient_space
55 .borrow()
56 .are_points_affine_independent(points.iter().collect())
57 {
58 Ok(Self {
59 ambient_space,
60 points,
61 })
62 } else {
63 Err("Can't make a simplex using degenerate points")
64 }
65 }
66}
67
68impl<'f, FS: OrderedRingSignature + FieldSignature> AffineSpace<'f, FS>
69where
70 AffineSpace<'f, FS>: Clone,
71{
72 pub fn simplex(&self, points: Vec<Vector<'f, FS>>) -> Result<Simplex<'f, FS>, &'static str> {
73 Simplex::new(*self, points)
74 }
75}
76
77impl<'f, FS: OrderedRingSignature + FieldSignature> Simplex<'f, FS>
78where
79 AffineSpace<'f, FS>: Clone,
80{
81 pub fn ambient_space(&self) -> AffineSpace<'f, FS> {
82 self.ambient_space
83 }
84
85 pub fn n(&self) -> usize {
86 self.points.len()
87 }
88
89 pub fn points(&self) -> &Vec<Vector<'f, FS>> {
90 &self.points
91 }
92
93 pub fn into_points(self) -> Vec<Vector<'f, FS>> {
94 self.points
95 }
96
97 pub fn point(&self, i: usize) -> &Vector<'f, FS> {
98 &self.points[i]
99 }
100
101 pub fn skeleton(&self, skel_n: isize) -> Vec<Self> {
102 if skel_n < 0 {
103 vec![]
104 } else {
105 let skel_n = skel_n as usize;
106 let mut parts = vec![];
107 for subset in (0..self.points.len()).combinations(skel_n) {
108 let part = Self::new(
109 self.ambient_space,
110 subset.into_iter().map(|i| self.points[i].clone()).collect(),
111 )
112 .unwrap();
113 parts.push(part);
114 }
115 parts
116 }
117 }
118
119 pub fn vertices(&self) -> Vec<Self> {
120 self.skeleton(1)
121 }
122
123 pub fn edges(&self) -> Vec<Self> {
124 self.skeleton(2)
125 }
126
127 pub fn faces(&self) -> Vec<Self> {
128 self.skeleton(3)
129 }
130
131 pub fn ridges(&self) -> Vec<Self> {
132 self.skeleton(self.points.len() as isize - 2)
133 }
134
135 pub fn facets(&self) -> Vec<Self> {
136 self.skeleton(self.points.len() as isize - 1)
137 }
138
139 pub fn facet(&self, k: usize) -> Self {
140 assert!(k <= self.points.len());
141 Self::new(self.ambient_space, {
142 let mut facet_points = self.points.clone();
143 facet_points.remove(k);
144 facet_points
145 })
146 .unwrap()
147 }
148
149 pub fn sub_simplices(&self) -> Vec<Self> {
150 self.points()
151 .clone()
152 .into_iter()
153 .powerset()
154 .map(|sub_points| Self::new(self.ambient_space, sub_points).unwrap())
155 .collect()
156 }
157
158 pub fn sub_simplices_not_null(&self) -> Vec<Self> {
159 self.sub_simplices()
160 .into_iter()
161 .filter(|spx| spx.n() != 0)
162 .collect()
163 }
164
165 pub fn proper_sub_simplices_not_null(&self) -> Vec<Self> {
166 self.sub_simplices()
167 .into_iter()
168 .filter(|spx| spx.n() != 0 && spx.n() != self.n())
169 .collect()
170 }
171
172 pub fn sub_simplex(&self, pts: Vec<usize>) -> Self {
173 Self::new(
174 self.ambient_space(),
175 pts.iter().map(|idx| self.points[*idx].clone()).collect(),
176 )
177 .unwrap()
178 }
179
180 pub fn oriented_facet(&self, k: usize) -> OrientedSimplex<'f, FS> {
181 assert!(k <= self.points.len());
183 let mut facet_points = self.points.clone();
184 let other_pt = facet_points.remove(k);
185 OrientedSimplex::new_with_positive_point(self.ambient_space, facet_points, &other_pt)
186 .unwrap()
187 }
188
189 pub fn oriented_facets(&self) -> Vec<OrientedSimplex<'f, FS>> {
190 assert_eq!(self.ambient_space.borrow().affine_dimension(), self.n());
191 (0..self.n()).map(|k| self.oriented_facet(k)).collect()
192 }
193
194 pub fn into_affine_span(self) -> (EmbeddedAffineSubspace<'f, FS>, Vec<Vector<'f, FS>>) {
195 EmbeddedAffineSubspace::new_affine_independent_span(self.ambient_space, self.into_points())
196 .unwrap()
197 }
198}
199
200#[cfg(test)]
201mod tests {
202 use super::*;
203 use algebraeon_nzq::Rational;
204
205 #[test]
206 fn make_simplex() {
207 let space = AffineSpace::new_linear(Rational::structure_ref(), 2);
208 let v1 = space.vector([1, 1]);
209 let v2 = space.vector([1, 0]);
210 let v3 = space.vector([0, 1]);
211 let s = Simplex::new(space, vec![v1, v2, v3]);
212 assert!(s.is_ok());
213
214 let space = AffineSpace::new_linear(Rational::structure_ref(), 2);
215 let v1 = space.vector([0, 0]);
216 let v2 = space.vector([1, 0]);
217 let v3 = space.vector([2, 0]);
218 let s = Simplex::new(space, vec![v1, v2, v3]);
219 assert!(s.is_err());
220 }
221
222 #[test]
223 fn simplex_skeleton() {
224 let space = AffineSpace::new_linear(Rational::structure_ref(), 2);
225 let v1 = space.vector([1, 1]);
226 let v2 = space.vector([1, 0]);
227 let v3 = space.vector([0, 1]);
228 let s = Simplex::new(space, vec![v1, v2, v3]).unwrap();
229
230 assert_eq!(s.skeleton(-2).len(), 0);
231 assert_eq!(s.skeleton(-1).len(), 0);
232 assert_eq!(s.skeleton(0).len(), 1);
233 assert_eq!(s.vertices().len(), 3);
234 assert_eq!(s.edges().len(), 3);
235 assert_eq!(s.faces().len(), 1);
236 assert_eq!(s.skeleton(4).len(), 0);
237 }
238}