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