parry2d/query/gjk/
voronoi_simplex2.rs1use crate::math::{Point, Real};
2use crate::query::gjk::{self, CSOPoint};
3use crate::query::{PointQuery, PointQueryWithLocation};
4use crate::shape::{Segment, SegmentPointLocation, Triangle, TrianglePointLocation};
5
6#[derive(Clone, Debug)]
8pub struct VoronoiSimplex {
9 prev_vertices: [usize; 3],
10 prev_dim: usize,
11 prev_proj: [Real; 2],
12
13 vertices: [CSOPoint; 3],
14 proj: [Real; 2],
15 dim: usize,
16}
17
18impl Default for VoronoiSimplex {
19 fn default() -> Self {
20 Self::new()
21 }
22}
23
24impl VoronoiSimplex {
25 pub fn new() -> VoronoiSimplex {
27 VoronoiSimplex {
28 prev_vertices: [0, 1, 2],
29 prev_proj: [0.0; 2],
30 prev_dim: 0,
31 vertices: [CSOPoint::origin(); 3],
32 proj: [0.0; 2],
33 dim: 0,
34 }
35 }
36
37 pub fn swap(&mut self, i1: usize, i2: usize) {
39 self.vertices.swap(i1, i2);
40 self.prev_vertices.swap(i1, i2);
41 }
42
43 pub fn reset(&mut self, pt: CSOPoint) {
45 self.prev_dim = 0;
46 self.dim = 0;
47 self.vertices[0] = pt;
48 }
49
50 pub fn add_point(&mut self, pt: CSOPoint) -> bool {
52 self.prev_dim = self.dim;
53 self.prev_proj = self.proj;
54 self.prev_vertices = [0, 1, 2];
55
56 for i in 0..self.dim + 1 {
57 if (self.vertices[i].point - pt.point).norm_squared() < gjk::eps_tol() {
58 return false;
59 }
60 }
61
62 self.dim += 1;
63 self.vertices[self.dim] = pt;
64 true
65 }
66
67 pub fn proj_coord(&self, i: usize) -> Real {
69 assert!(i <= self.dim, "Index out of bounds.");
70 self.proj[i]
71 }
72
73 pub fn point(&self, i: usize) -> &CSOPoint {
75 assert!(i <= self.dim, "Index out of bounds.");
76 &self.vertices[i]
77 }
78
79 pub fn prev_proj_coord(&self, i: usize) -> Real {
81 assert!(i <= self.prev_dim, "Index out of bounds.");
82 self.prev_proj[i]
83 }
84
85 pub fn prev_point(&self, i: usize) -> &CSOPoint {
87 assert!(i <= self.prev_dim, "Index out of bounds.");
88 &self.vertices[self.prev_vertices[i]]
89 }
90
91 pub fn project_origin_and_reduce(&mut self) -> Point<Real> {
97 if self.dim == 0 {
98 self.proj[0] = 1.0;
99 self.vertices[0].point
100 } else if self.dim == 1 {
101 let (proj, location) = Segment::new(self.vertices[0].point, self.vertices[1].point)
102 .project_local_point_and_get_location(&Point::<Real>::origin(), true);
103
104 match location {
105 SegmentPointLocation::OnVertex(0) => {
106 self.proj[0] = 1.0;
107 self.dim = 0;
108 }
109 SegmentPointLocation::OnVertex(1) => {
110 self.proj[0] = 1.0;
111 self.swap(0, 1);
112 self.dim = 0;
113 }
114 SegmentPointLocation::OnEdge(coords) => {
115 self.proj = coords;
116 }
117 _ => unreachable!(),
118 }
119
120 proj.point
121 } else {
122 assert!(self.dim == 2);
123 let (proj, location) = Triangle::new(
124 self.vertices[0].point,
125 self.vertices[1].point,
126 self.vertices[2].point,
127 )
128 .project_local_point_and_get_location(&Point::<Real>::origin(), true);
129
130 match location {
131 TrianglePointLocation::OnVertex(i) => {
132 self.swap(0, i as usize);
133 self.proj[0] = 1.0;
134 self.dim = 0;
135 }
136 TrianglePointLocation::OnEdge(0, coords) => {
137 self.proj = coords;
138 self.dim = 1;
139 }
140 TrianglePointLocation::OnEdge(1, coords) => {
141 self.swap(0, 2);
142 self.proj[0] = coords[1];
143 self.proj[1] = coords[0];
144 self.dim = 1;
145 }
146 TrianglePointLocation::OnEdge(2, coords) => {
147 self.swap(1, 2);
148 self.proj = coords;
149 self.dim = 1;
150 }
151 _ => {}
152 }
153
154 proj.point
155 }
156 }
157
158 pub fn project_origin(&mut self) -> Point<Real> {
160 if self.dim == 0 {
161 self.vertices[0].point
162 } else if self.dim == 1 {
163 let seg = Segment::new(self.vertices[0].point, self.vertices[1].point);
164 seg.project_local_point(&Point::<Real>::origin(), true)
165 .point
166 } else {
167 assert!(self.dim == 2);
168 let tri = Triangle::new(
169 self.vertices[0].point,
170 self.vertices[1].point,
171 self.vertices[2].point,
172 );
173 tri.project_local_point(&Point::<Real>::origin(), true)
174 .point
175 }
176 }
177
178 pub fn contains_point(&self, pt: &Point<Real>) -> bool {
180 for i in 0..self.dim + 1 {
181 if self.vertices[i].point == *pt {
182 return true;
183 }
184 }
185
186 false
187 }
188
189 pub fn dimension(&self) -> usize {
191 self.dim
192 }
193
194 pub fn prev_dimension(&self) -> usize {
196 self.prev_dim
197 }
198
199 pub fn max_sq_len(&self) -> Real {
201 let mut max_sq_len = 0.0;
202
203 for i in 0..self.dim + 1 {
204 let norm = self.vertices[i].point.coords.norm_squared();
205
206 if norm > max_sq_len {
207 max_sq_len = norm
208 }
209 }
210
211 max_sq_len
212 }
213
214 pub fn modify_pnts(&mut self, f: &dyn Fn(&mut CSOPoint)) {
216 for i in 0..self.dim + 1 {
217 f(&mut self.vertices[i])
218 }
219 }
220}