1use na::{self, Point2, RealField, Unit};
2use std::iter;
3
4use crate::math::{Isometry, Point, Vector};
5use crate::query::ContactPreprocessor;
6use crate::query::{
7 self, Contact, ContactKinematic, ContactManifold, ContactPrediction, NeighborhoodGeometry,
8};
9use crate::shape::{FeatureId, Segment, SegmentPointLocation};
10use crate::utils;
11
12#[derive(Clone)]
14pub struct ClippingCache<N: RealField + Copy> {
15 poly1: Vec<Point2<N>>,
16 poly2: Vec<Point2<N>>,
17}
18
19impl<N: RealField + Copy> ClippingCache<N> {
20 pub fn new() -> Self {
22 ClippingCache {
23 poly1: Vec::with_capacity(4),
24 poly2: Vec::with_capacity(4),
25 }
26 }
27
28 pub fn clear(&mut self) {
30 self.poly1.clear();
31 self.poly2.clear();
32 }
33}
34
35#[derive(Clone, Debug)]
40pub struct ConvexPolygonalFeature<N: RealField + Copy> {
41 pub vertices: Vec<Point<N>>,
44 pub edge_normals: Vec<Vector<N>>,
46 pub normal: Option<Unit<Vector<N>>>,
48 pub feature_id: FeatureId,
50 pub vertices_id: Vec<FeatureId>,
52 pub edges_id: Vec<FeatureId>,
54}
55
56impl<N: RealField + Copy> ConvexPolygonalFeature<N> {
57 pub fn new() -> Self {
59 ConvexPolygonalFeature {
60 vertices: Vec::new(),
61 edge_normals: Vec::new(),
62 normal: None,
63 feature_id: FeatureId::Unknown,
64 vertices_id: Vec::new(),
65 edges_id: Vec::new(),
66 }
67 }
68
69 pub fn with_size(n: usize) -> Self {
71 ConvexPolygonalFeature {
72 vertices: iter::repeat(Point::origin()).take(n).collect(),
73 edge_normals: iter::repeat(Vector::zeros()).take(n).collect(),
74 normal: None,
75 feature_id: FeatureId::Unknown,
76 vertices_id: iter::repeat(FeatureId::Unknown).take(n).collect(),
77 edges_id: iter::repeat(FeatureId::Unknown).take(n).collect(),
78 }
79 }
80
81 pub fn clear(&mut self) {
83 self.vertices.clear();
84 self.edge_normals.clear();
85 self.vertices_id.clear();
86 self.edges_id.clear();
87 self.normal = None;
88 self.feature_id = FeatureId::Unknown;
89 }
90
91 pub fn transform_by(&mut self, m: &Isometry<N>) {
93 for p in &mut self.vertices {
94 *p = m * *p;
95 }
96
97 for n in &mut self.edge_normals {
98 *n = m * *n;
99 }
100
101 if let Some(ref mut n) = self.normal {
102 *n = m * *n;
103 }
104 }
105
106 pub fn push(&mut self, pt: Point<N>, id: FeatureId) {
110 self.vertices.push(pt);
111 self.vertices_id.push(id);
112 }
113
114 pub fn nvertices(&self) -> usize {
116 self.vertices.len()
117 }
118
119 pub fn vertices(&self) -> &[Point<N>] {
121 &self.vertices[..]
122 }
123
124 pub fn nedges(&self) -> usize {
126 match self.vertices.len() {
127 1 => 0,
128 2 => 1,
129 l => l,
130 }
131 }
132
133 pub fn edge(&self, edge_id: FeatureId) -> Option<Segment<N>> {
135 for i1 in 0..self.vertices.len() {
136 if self.edges_id[i1] == edge_id {
137 let i2 = (i1 + 1) % self.vertices.len();
138 return Some(Segment::new(self.vertices[i1], self.vertices[i2]));
139 }
140 }
141
142 None
143 }
144
145 pub fn push_scaled_edge_normal(&mut self, normal: Vector<N>) {
147 if let Some(normal) = normal.try_normalize(N::default_epsilon()) {
148 self.edge_normals.push(normal)
149 } else {
150 self.edge_normals.push(na::zero())
151 }
152 }
153
154 pub fn push_edge_normal(&mut self, normal: Unit<Vector<N>>) {
156 self.edge_normals.push(normal.into_inner())
157 }
158
159 pub fn recompute_edge_normals(&mut self) {
163 self.edge_normals.clear();
164
165 for i1 in 0..self.vertices.len() {
166 let i2 = (i1 + 1) % self.vertices.len();
167 let dpt = self.vertices[i2] - self.vertices[i1];
168 let scaled_normal = dpt.cross(
169 self.normal
170 .as_ref()
171 .expect("The face normal must be set before computing edge normals."),
172 );
173 self.push_scaled_edge_normal(scaled_normal)
174 }
175 }
176
177 pub fn project_point(&self, pt: &Point<N>) -> Option<Contact<N>> {
179 if let Some(n) = self.normal {
180 let dpt = *pt - self.vertices[0];
181 let dist = n.dot(&dpt);
182 let proj = *pt + (-n.into_inner() * dist);
183
184 for i in 0..self.edge_normals.len() {
185 let dpt = proj - self.vertices[i];
186
187 if dpt.dot(&self.edge_normals[i]) > na::zero() {
188 return None;
189 }
190 }
191
192 Some(Contact::new(proj, *pt, n, -dist))
193 } else {
194 None
195 }
196 }
197
198 pub fn set_normal(&mut self, normal: Unit<Vector<N>>) {
200 self.normal = Some(normal)
201 }
202
203 pub fn push_edge_feature_id(&mut self, id: FeatureId) {
205 self.edges_id.push(id)
206 }
207
208 pub fn set_feature_id(&mut self, id: FeatureId) {
210 self.feature_id = id
211 }
212
213 pub fn clip(
218 &self,
219 other: &Self,
220 normal: &Unit<Vector<N>>,
221 prediction: &ContactPrediction<N>,
222 cache: &mut ClippingCache<N>,
223 out: &mut Vec<(Contact<N>, FeatureId, FeatureId)>,
224 ) {
225 cache.clear();
228
229 if self.vertices.len() <= 2 && other.vertices.len() <= 2 {
231 return;
232 }
233
234 let mut basis = [na::zero(), na::zero()];
236 let mut basis_i = 0;
237
238 Vector::orthonormal_subspace_basis(&[normal.into_inner()], |dir| {
239 basis[basis_i] = *dir;
240 basis_i += 1;
241 true
242 });
243
244 let ref_pt = self.vertices[0];
245
246 for pt in &self.vertices {
247 let dpt = *pt - ref_pt;
248 let coords = Point2::new(basis[0].dot(&dpt), basis[1].dot(&dpt));
249 cache.poly1.push(coords);
250 }
251
252 for pt in &other.vertices {
253 let dpt = *pt - ref_pt;
254 let coords = Point2::new(basis[0].dot(&dpt), basis[1].dot(&dpt));
255 cache.poly2.push(coords);
256 }
257
258 if cache.poly2.len() > 2 {
259 for i in 0..cache.poly1.len() {
260 let pt = &cache.poly1[i];
261
262 if utils::point_in_poly2d(pt, &cache.poly2) {
263 let origin = ref_pt + basis[0] * pt.x + basis[1] * pt.y;
264
265 let n2 = other.normal.as_ref().unwrap().into_inner();
266 let p2 = &other.vertices[0];
267 if let Some(toi2) =
268 query::line_toi_with_plane(p2, &n2, &origin, &normal.into_inner())
269 {
270 let world2 = origin + normal.into_inner() * toi2;
271 let world1 = self.vertices[i];
272 let f2 = other.feature_id;
273 let f1 = self.vertices_id[i];
274 let contact = Contact::new_wo_depth(world1, world2, *normal);
275
276 if -contact.depth <= prediction.linear() {
277 out.push((contact, f1, f2));
278 }
279 }
280 }
281 }
282 }
283
284 if cache.poly1.len() > 2 {
285 for i in 0..cache.poly2.len() {
286 let pt = &cache.poly2[i];
287
288 if utils::point_in_poly2d(pt, &cache.poly1) {
289 let origin = ref_pt + basis[0] * pt.x + basis[1] * pt.y;
290
291 let n1 = self.normal.as_ref().unwrap().into_inner();
292 let p1 = &self.vertices[0];
293 if let Some(toi1) =
294 query::line_toi_with_plane(p1, &n1, &origin, &normal.into_inner())
295 {
296 let world1 = origin + normal.into_inner() * toi1;
297 let world2 = other.vertices[i];
298 let f1 = self.feature_id;
299 let f2 = other.vertices_id[i];
300 let contact = Contact::new_wo_depth(world1, world2, *normal);
301
302 if -contact.depth <= prediction.linear() {
303 out.push((contact, f1, f2));
304 }
305 }
306 }
307 }
308 }
309
310 let nedges1 = self.nedges();
311 let nedges2 = other.nedges();
312
313 for i1 in 0..nedges1 {
314 let j1 = (i1 + 1) % cache.poly1.len();
315 let seg1 = (&cache.poly1[i1], &cache.poly1[j1]);
316
317 for i2 in 0..nedges2 {
318 let j2 = (i2 + 1) % cache.poly2.len();
319 let seg2 = (&cache.poly2[i2], &cache.poly2[j2]);
320
321 if let (SegmentPointLocation::OnEdge(e1), SegmentPointLocation::OnEdge(e2)) =
322 query::closest_points_segment_segment_with_locations_nD(seg1, seg2)
323 {
324 let original1 = Segment::new(self.vertices[i1], self.vertices[j1]);
325 let original2 = Segment::new(other.vertices[i2], other.vertices[j2]);
326 let world1 = original1.point_at(&SegmentPointLocation::OnEdge(e1));
327 let world2 = original2.point_at(&SegmentPointLocation::OnEdge(e2));
328 let f1 = self.edges_id[i1];
329 let f2 = other.edges_id[i2];
330 let contact = Contact::new_wo_depth(world1, world2, *normal);
331
332 if -contact.depth <= prediction.linear() {
333 out.push((contact, f1, f2));
334 }
335 }
336 }
337 }
338 }
339
340 pub fn add_contact_to_manifold(
342 &self,
343 other: &Self,
344 c: Contact<N>,
345 m1: &Isometry<N>,
346 f1: FeatureId,
347 proc1: Option<&dyn ContactPreprocessor<N>>,
348 m2: &Isometry<N>,
349 f2: FeatureId,
350 proc2: Option<&dyn ContactPreprocessor<N>>,
351 manifold: &mut ContactManifold<N>,
352 ) {
353 let mut kinematic = ContactKinematic::new();
354 let local1 = m1.inverse_transform_point(&c.world1);
355 let local2 = m2.inverse_transform_point(&c.world2);
356
357 match f1 {
358 FeatureId::Face(..) => kinematic.set_approx1(
359 f1,
360 local1,
361 NeighborhoodGeometry::Plane(
362 m1.inverse_transform_unit_vector(self.normal.as_ref().unwrap()),
363 ),
364 ),
365 FeatureId::Edge(..) => {
366 let e1 = self.edge(f1).expect("Invalid edge id.");
367 if let Some(dir1) = e1.direction() {
368 let local_dir1 = m1.inverse_transform_unit_vector(&dir1);
369 let approx1 = NeighborhoodGeometry::Line(local_dir1);
370 kinematic.set_approx1(f1, local1, approx1)
371 } else {
372 return;
373 }
374 }
375 FeatureId::Vertex(..) => kinematic.set_approx1(f1, local1, NeighborhoodGeometry::Point),
376 FeatureId::Unknown => return,
377 }
378
379 match f2 {
380 FeatureId::Face(..) => {
381 let approx2 = NeighborhoodGeometry::Plane(
382 m2.inverse_transform_unit_vector(&other.normal.as_ref().unwrap()),
383 );
384 kinematic.set_approx2(f2, local2, approx2)
385 }
386 FeatureId::Edge(..) => {
387 let e2 = other.edge(f2).expect("Invalid edge id.");
388 if let Some(dir2) = e2.direction() {
389 let local_dir2 = m2.inverse_transform_unit_vector(&dir2);
390 let approx2 = NeighborhoodGeometry::Line(local_dir2);
391 kinematic.set_approx2(f2, local2, approx2)
392 } else {
393 return;
394 }
395 }
396 FeatureId::Vertex(..) => kinematic.set_approx2(f2, local2, NeighborhoodGeometry::Point),
397 FeatureId::Unknown => return,
398 }
399
400 let _ = manifold.push(c, kinematic, local1, proc1, proc2);
401 }
402}