1use crate::bounding_volume::{self, BoundingVolume, AABB};
4use crate::math::{Isometry, Point, Vector, DIM};
5use crate::partitioning::{BVHImpl, BVT};
6use crate::query::{
7 Contact, ContactKinematic, ContactPrediction, ContactPreprocessor, LocalShapeApproximation,
8 NeighborhoodGeometry,
9};
10use crate::shape::{CompositeShape, DeformableShape, DeformationsType, FeatureId, Segment, Shape};
11use na::{self, Point2, RealField, Unit};
12use std::iter;
13use std::ops::Range;
14use std::slice;
15
16#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
17#[derive(Clone)]
18struct DeformationInfos<N: RealField + Copy> {
19 margin: N,
20 curr_timestamp: usize,
21 timestamps: Vec<usize>,
22 ref_vertices: Vec<Point<N>>,
23 seg_to_update: Vec<usize>,
24}
25
26#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
27#[derive(Clone)]
28pub struct PolylineEdge<N: RealField + Copy> {
29 pub indices: Point2<usize>,
30 bvt_leaf: usize,
31 pub normal: Option<Unit<Vector<N>>>, }
33
34#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
35#[derive(Clone)]
36pub struct PolylineVertex {
37 pub adj_edges: Range<usize>,
38 pub adj_vertices: Range<usize>,
39}
40
41#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
43#[derive(Clone)]
44pub struct Polyline<N: RealField + Copy> {
45 bvt: BVT<usize, AABB<N>>,
46 points: Vec<Point<N>>,
47 vertices: Vec<PolylineVertex>,
48 edges: Vec<PolylineEdge<N>>,
49 adj_edge_list: Vec<usize>,
50 adj_vertex_list: Vec<usize>,
52 deformations: DeformationInfos<N>,
53 oriented: bool, }
55
56impl<N: RealField + Copy> Polyline<N> {
57 pub fn new(points: Vec<Point<N>>, indices: Option<Vec<Point2<usize>>>) -> Polyline<N> {
59 let indices = indices.unwrap_or(
60 (0..)
61 .map(|i| Point2::new(i, i + 1))
62 .take(points.len() - 1)
63 .collect(),
64 );
65 let mut leaves = Vec::with_capacity(indices.len());
66 let mut vertices: Vec<PolylineVertex> = iter::repeat(PolylineVertex {
67 adj_edges: 0..0,
68 adj_vertices: 0..0,
69 })
70 .take(points.len())
71 .collect();
72 let mut edges = Vec::with_capacity(indices.len());
73
74 let adj_edge_list = Self::adj_edge_list(&indices, &mut vertices);
75 let adj_vertex_list = Self::adj_vertex_list(&indices, &mut vertices);
76
77 {
78 let is = &*indices;
79
80 for (i, is) in is.iter().enumerate() {
81 let segment = Segment::new(points[is.x], points[is.y]);
82 let normal = segment.normal();
83
84 let bv = segment.local_aabb();
85 leaves.push((i, bv.clone()));
86 edges.push(PolylineEdge {
87 indices: *is,
88 bvt_leaf: 0, normal,
90 })
91 }
92 }
93
94 let bvt = BVT::new_balanced(leaves);
95
96 for (i, leaf) in bvt.leaves().iter().enumerate() {
98 edges[*leaf.data()].bvt_leaf = i;
99 }
100
101 let deformations = DeformationInfos {
102 margin: na::convert(0.1), curr_timestamp: 0,
104 timestamps: Vec::new(),
105 ref_vertices: Vec::new(),
106 seg_to_update: Vec::new(),
107 };
108
109 Polyline {
110 bvt,
111 points,
112 deformations,
113 vertices,
114 edges,
115 adj_edge_list,
116 adj_vertex_list,
117 oriented: false,
118 }
119 }
120
121 fn adj_vertex_list(edges: &[Point2<usize>], vertices: &mut [PolylineVertex]) -> Vec<usize> {
122 let mut num_neighbors: Vec<usize> = iter::repeat(0).take(vertices.len()).collect();
123
124 for e in edges {
125 num_neighbors[e.x] += 1;
126 num_neighbors[e.y] += 1;
127 }
128
129 let mut total_num_nbh = 0;
130
131 for (num_nbh, vtx) in num_neighbors.iter().zip(vertices.iter_mut()) {
132 vtx.adj_vertices = total_num_nbh..total_num_nbh + num_nbh;
133 total_num_nbh += num_nbh;
134 }
135
136 let mut adj_vertex_list: Vec<usize> = iter::repeat(0).take(total_num_nbh).collect();
137
138 for n in &mut num_neighbors {
140 *n = 0;
141 }
142
143 for e in edges.iter() {
144 adj_vertex_list[vertices[e.x].adj_vertices.start + num_neighbors[e.x]] = e.y;
145 adj_vertex_list[vertices[e.y].adj_vertices.start + num_neighbors[e.y]] = e.x;
146
147 num_neighbors[e.x] += 1;
148 num_neighbors[e.y] += 1;
149 }
150
151 adj_vertex_list
152 }
153
154 fn adj_edge_list(edges: &[Point2<usize>], vertices: &mut [PolylineVertex]) -> Vec<usize> {
155 let mut num_neighbors: Vec<usize> = iter::repeat(0).take(vertices.len()).collect();
156
157 for idx in edges {
158 num_neighbors[idx.x] += 1;
159 num_neighbors[idx.y] += 1;
160 }
161
162 let mut total_num_nbh = 0;
163
164 for (num_nbh, vtx) in num_neighbors.iter().zip(vertices.iter_mut()) {
165 vtx.adj_edges = total_num_nbh..total_num_nbh + num_nbh;
166 total_num_nbh += num_nbh;
167 }
168
169 let mut adj_edge_list: Vec<usize> = iter::repeat(0).take(total_num_nbh).collect();
170
171 for n in &mut num_neighbors {
173 *n = 0;
174 }
175
176 for (i, idx) in edges.iter().enumerate() {
177 adj_edge_list[vertices[idx.x].adj_edges.start + num_neighbors[idx.x]] = i;
178 adj_edge_list[vertices[idx.y].adj_edges.start + num_neighbors[idx.y]] = i;
179
180 num_neighbors[idx.x] += 1;
181 num_neighbors[idx.y] += 1;
182 }
183
184 adj_edge_list
185 }
186
187 pub fn quad(nx: usize, ny: usize) -> Self {
189 let mut vertices = Vec::new();
190 let step_x = N::one() / na::convert(nx as f64);
191 let step_y = N::one() / na::convert(ny as f64);
192 let _0_5: N = na::convert(0.5);
193
194 for i in 0..=nx {
195 vertices.push(xy_point(step_x * na::convert(i as f64) - _0_5, -_0_5));
196 }
197 for j in 1..=ny {
198 vertices.push(xy_point(_0_5, step_y * na::convert(j as f64) - _0_5));
199 }
200 for i in 1..=nx {
201 vertices.push(xy_point(_0_5 - step_x * na::convert(i as f64), _0_5));
202 }
203 for j in 1..ny {
204 vertices.push(xy_point(-_0_5, _0_5 - step_y * na::convert(j as f64)));
205 }
206
207 let mut indices: Vec<_> = (0..)
208 .map(|i| Point2::new(i, i + 1))
209 .take(vertices.len() - 1)
210 .collect();
211 indices.push(Point2::new(vertices.len() - 1, 0));
212
213 Polyline::new(vertices, Some(indices))
214 }
215
216 #[inline]
218 pub fn aabb(&self) -> &AABB<N> {
219 self.bvt
220 .root_bounding_volume()
221 .expect("An empty Polyline has no AABB.")
222 }
223
224 #[inline]
226 pub fn points(&self) -> &[Point<N>] {
227 &self.points
228 }
229
230 #[inline]
232 pub fn edges(&self) -> &[PolylineEdge<N>] {
233 &self.edges
234 }
235
236 #[inline]
240 pub fn oriented(&self) -> bool {
241 self.oriented
242 }
243
244 #[inline]
248 pub fn set_oriented(&mut self, oriented: bool) {
249 self.oriented = oriented
250 }
251
252 #[inline]
254 pub fn edge_containing_feature(&self, id: FeatureId) -> usize {
255 match id {
256 FeatureId::Vertex(i) => self.adj_edge_list[self.vertices[i].adj_edges.start],
257 #[cfg(feature = "dim3")]
258 FeatureId::Edge(i) => i,
259 FeatureId::Face(i) => i % self.edges.len(),
260 _ => panic!("Feature ID cannot be unknown."),
261 }
262 }
263
264 #[inline]
266 pub fn segment_feature_to_polyline_feature(
267 &self,
268 edge_id: usize,
269 feature: FeatureId,
270 ) -> FeatureId {
271 let edge = &self.edges[edge_id];
272 match feature {
273 FeatureId::Vertex(i) => FeatureId::Vertex(edge.indices[i]),
274 #[cfg(feature = "dim3")]
275 FeatureId::Edge(_) => FeatureId::Edge(edge_id),
276 FeatureId::Face(i) => {
277 if i == 0 {
278 FeatureId::Face(edge_id)
279 } else {
280 FeatureId::Face(edge_id + self.edges.len())
281 }
282 }
283 FeatureId::Unknown => FeatureId::Unknown,
284 }
285 }
286
287 #[inline]
289 pub fn edge_segment(&self, i: usize) -> Segment<N> {
290 let edge = &self.edges[i];
291 Segment::new(self.points[edge.indices.x], self.points[edge.indices.y])
292 }
293
294 #[inline]
296 pub fn segment_at(&self, i: usize) -> Segment<N> {
297 let idx = self.edges[i].indices;
298 Segment::new(self.points[idx.x], self.points[idx.y])
299 }
300
301 #[inline]
303 pub fn bvt(&self) -> &BVT<usize, AABB<N>> {
304 &self.bvt
305 }
306
307 #[cfg(feature = "dim3")]
310 pub fn vertex_tangent_cone_contains_dir(
311 &self,
312 _i: usize,
313 _deformations: Option<&[N]>,
314 _dir: &Unit<Vector<N>>,
315 ) -> bool {
316 return false;
317 }
318
319 #[cfg(feature = "dim2")]
322 pub fn vertex_tangent_cone_contains_dir(
323 &self,
324 i: usize,
325 deformations: Option<&[N]>,
326 dir: &Unit<Vector<N>>,
327 ) -> bool {
328 if !self.oriented {
329 return false;
330 }
331
332 let v = &self.vertices[i];
333
334 if let Some(coords) = deformations {
335 for adj_edge in &self.adj_edge_list[v.adj_edges.clone()] {
336 let indices = self.edges[*adj_edge].indices * DIM;
337 let seg = Segment::new(
338 Point::from_slice(&coords[indices.x..indices.x + DIM]),
339 Point::from_slice(&coords[indices.y..indices.y + DIM]),
340 );
341
342 if seg.scaled_normal().dot(dir) > N::zero() {
343 return false;
344 }
345 }
346 } else {
347 for adj_edge in &self.adj_edge_list[v.adj_edges.clone()] {
348 let edge = &self.edges[*adj_edge];
349
350 if let Some(ref n) = edge.normal {
351 if n.dot(dir) > N::zero() {
352 return false;
353 }
354 }
355 }
356 }
357
358 true
359 }
360
361 pub fn transform_by(&mut self, transform: &Isometry<N>) {
363 for pt in &mut self.points {
364 *pt = transform * *pt
365 }
366 }
367
368 #[inline]
370 pub fn transformed(mut self, t: &Isometry<N>) -> Self {
371 self.transform_by(t);
372 self
373 }
374
375 pub fn scale_by(&mut self, scale: &Vector<N>) {
377 for pt in &mut self.points {
378 pt.coords.component_mul_assign(scale)
379 }
380 }
381
382 #[inline]
384 pub fn scaled(mut self, s: &Vector<N>) -> Self {
385 self.scale_by(s);
386 self
387 }
388
389 #[inline]
392 pub fn is_backface(&self, feature: FeatureId) -> bool {
393 if let FeatureId::Face(i) = feature {
394 i >= self.edges.len()
395 } else {
396 false
397 }
398 }
399
400 pub fn vertex_tangent_cone_polar_contains_dir(
403 &self,
404 i: usize,
405 dir: &Unit<Vector<N>>,
406 sin_ang_tol: N,
407 ) -> bool {
408 let v = &self.vertices[i];
409
410 for adj_vtx in &self.adj_vertex_list[v.adj_vertices.clone()] {
411 let edge_dir = self.points[i] - self.points[*adj_vtx];
412
413 if edge_dir.dot(dir) < -sin_ang_tol * edge_dir.norm() {
415 return false;
416 }
417 }
418
419 true
420 }
421
422 #[cfg(feature = "dim3")]
425 pub fn edge_tangent_cone_contains_dir(
426 &self,
427 _i: usize,
428 _deformations: Option<&[N]>,
429 _dir: &Unit<Vector<N>>,
430 ) -> bool {
431 return false;
432 }
433
434 #[cfg(feature = "dim2")]
437 pub fn edge_tangent_cone_contains_dir(
438 &self,
439 i: usize,
440 deformations: Option<&[N]>,
441 dir: &Unit<Vector<N>>,
442 ) -> bool {
443 if !self.oriented {
444 return false;
445 }
446
447 let normal;
448
449 if let Some(coords) = deformations {
450 let indices = self.edges[i % self.edges.len()].indices * DIM;
451 let seg = Segment::new(
452 Point::from_slice(&coords[indices.x..indices.x + DIM]),
453 Point::from_slice(&coords[indices.y..indices.y + DIM]),
454 );
455
456 if i >= self.edges.len() {
457 normal = -seg.scaled_normal();
458 } else {
459 normal = seg.scaled_normal();
460 }
461 } else {
462 if i >= self.edges.len() {
463 normal = -self.edges[i - self.edges.len()]
464 .normal
465 .map(|n| n.into_inner())
466 .unwrap_or(Vector::zeros());
467 } else {
468 normal = self.edges[i]
469 .normal
470 .map(|n| n.into_inner())
471 .unwrap_or(Vector::zeros());
472 }
473 }
474
475 normal.dot(dir) <= N::zero()
476 }
477
478 pub fn edge_tangent_cone_polar_contains_dir(
481 &self,
482 i: usize,
483 dir: &Unit<Vector<N>>,
484 cos_ang_tol: N,
485 ) -> bool {
486 let normal;
487
488 if i >= self.edges.len() {
489 normal = -self.edges[i - self.edges.len()]
490 .normal
491 .map(|n| n.into_inner())
492 .unwrap_or(Vector::zeros());
493 } else {
494 normal = self.edges[i]
495 .normal
496 .map(|n| n.into_inner())
497 .unwrap_or(Vector::zeros());
498 }
499
500 normal.dot(dir) >= cos_ang_tol
501 }
502
503 pub fn tangent_cone_polar_contains_dir(
506 &self,
507 _feature: FeatureId,
508 _dir: &Unit<Vector<N>>,
509 _sin_ang_tol: N,
510 _cos_ang_tol: N,
511 ) -> bool {
512 unimplemented!()
513 }
521
522 fn init_deformation_infos(&mut self) -> bool {
523 if self.deformations.ref_vertices.is_empty() {
524 self.deformations.timestamps = iter::repeat(0).take(self.edges.len()).collect();
525 self.deformations.ref_vertices = self.points.clone();
526 true
527 } else {
528 false
529 }
530 }
531}
532
533impl<N: RealField + Copy> CompositeShape<N> for Polyline<N> {
534 #[inline]
535 fn nparts(&self) -> usize {
536 self.edges.len()
537 }
538
539 #[inline(always)]
540 fn map_part_at(
541 &self,
542 i: usize,
543 m: &Isometry<N>,
544 f: &mut dyn FnMut(&Isometry<N>, &dyn Shape<N>),
545 ) {
546 let element = self.segment_at(i);
547 f(m, &element)
548 }
549
550 fn map_part_and_preprocessor_at(
551 &self,
552 i: usize,
553 m: &Isometry<N>,
554 prediction: &ContactPrediction<N>,
555 f: &mut dyn FnMut(&Isometry<N>, &dyn Shape<N>, &dyn ContactPreprocessor<N>),
556 ) {
557 let element = self.segment_at(i);
558 let proc = PolylineContactProcessor::new(self, m, i, prediction);
559 f(m, &element, &proc)
560 }
561
562 #[inline]
563 fn aabb_at(&self, i: usize) -> AABB<N> {
564 self.bvt
565 .leaf(self.edges[i].bvt_leaf)
566 .bounding_volume()
567 .clone()
568 }
569
570 #[inline]
571 fn bvh(&self) -> BVHImpl<N, usize, AABB<N>> {
572 BVHImpl::BVT(&self.bvt)
573 }
574}
575
576impl<N: RealField + Copy> DeformableShape<N> for Polyline<N> {
577 fn deformations_type(&self) -> DeformationsType {
578 DeformationsType::Vectors
579 }
580
581 fn set_deformations(&mut self, coords: &[N]) {
583 assert!(
584 coords.len() >= self.points.len() * DIM,
585 "Set deformations error: dimension mismatch."
586 );
587 let is_first_init = self.init_deformation_infos();
588 self.deformations.curr_timestamp += 1;
589
590 unsafe {
594 let len = self.points.len();
595 let coords_ptr = coords.as_ptr() as *const Point<N>;
596 let coords_pt: &[Point<N>] = slice::from_raw_parts(coords_ptr, len);
597 self.points.copy_from_slice(coords_pt);
598 }
599
600 for (target, pt) in self.points.iter_mut().enumerate() {
601 let ref_pt = &mut self.deformations.ref_vertices[target];
602 let sq_dist_to_ref = na::distance_squared(pt, ref_pt);
603
604 if is_first_init || sq_dist_to_ref > self.deformations.margin * self.deformations.margin
605 {
606 let ids = self.vertices[target].adj_edges.clone();
610 self.deformations
611 .seg_to_update
612 .extend_from_slice(&self.adj_edge_list[ids]);
613 *ref_pt = *pt;
614 }
615 }
616
617 for e in &mut self.edges {
619 let seg = Segment::new(self.points[e.indices.x], self.points[e.indices.y]);
620 e.normal = seg.normal();
621 }
622
623 for seg_id in self.deformations.seg_to_update.drain(..) {
625 if self.deformations.timestamps[seg_id] != self.deformations.curr_timestamp {
626 let idx = &self.edges[seg_id].indices;
628 let mut new_bv = bounding_volume::local_point_cloud_aabb(&[
629 self.points[idx.x],
630 self.points[idx.y],
631 ]);
632 new_bv.loosen(self.deformations.margin);
633 self.bvt
634 .set_leaf_bounding_volume(self.edges[seg_id].bvt_leaf, new_bv, false);
635 self.deformations.timestamps[seg_id] = self.deformations.curr_timestamp;
636 }
637 }
638
639 self.bvt.refit(N::zero())
641 }
642
643 fn update_local_approximation(&self, coords: &[N], approx: &mut LocalShapeApproximation<N>) {
644 match approx.feature {
645 FeatureId::Vertex(i) => {
646 approx.point = Point::from_slice(&coords[i * DIM..(i + 1) * DIM]);
647 approx.geometry = NeighborhoodGeometry::Point;
648 }
649 #[cfg(feature = "dim3")]
650 FeatureId::Edge(i) => {
651 let edge = &self.edges[i];
652 let pid1 = edge.indices.x * DIM;
653 let pid2 = edge.indices.y * DIM;
654 let seg = Segment::new(
655 Point::from_slice(&coords[pid1..pid1 + DIM]),
656 Point::from_slice(&coords[pid2..pid2 + DIM]),
657 );
658 approx.point = seg.a;
659
660 if let Some(dir) = seg.direction() {
661 approx.geometry = NeighborhoodGeometry::Line(dir);
662 } else {
663 approx.geometry = NeighborhoodGeometry::Point;
664 }
665 }
666 #[cfg(feature = "dim3")]
667 FeatureId::Face(_) => unreachable!(),
668 #[cfg(feature = "dim2")]
669 FeatureId::Face(mut i) => {
670 let is_backface = i >= self.edges.len();
671 if is_backface {
672 i -= self.edges.len();
673 }
674
675 let edge = &self.edges[i];
676 let pid1 = edge.indices.x * DIM;
677 let pid2 = edge.indices.y * DIM;
678 let seg = Segment::new(
679 Point::from_slice(&coords[pid1..pid1 + DIM]),
680 Point::from_slice(&coords[pid2..pid2 + DIM]),
681 );
682
683 approx.point = seg.a;
684
685 if let Some(n) = seg.normal() {
686 if !is_backface {
687 approx.geometry = NeighborhoodGeometry::Plane(n);
688 } else {
689 approx.geometry = NeighborhoodGeometry::Plane(-n);
690 }
691 } else {
692 approx.geometry = NeighborhoodGeometry::Point;
693 }
694 }
695 _ => panic!(
696 "Encountered invalid triangle feature: {:?}.",
697 approx.feature
698 ),
699 }
700 }
701}
702
703#[allow(dead_code)]
704struct PolylineContactProcessor<'a, N: RealField + Copy> {
705 polyline: &'a Polyline<N>,
706 pos: &'a Isometry<N>,
707 edge_id: usize,
708 prediction: &'a ContactPrediction<N>,
709}
710
711impl<'a, N: RealField + Copy> PolylineContactProcessor<'a, N> {
712 pub fn new(
713 polyline: &'a Polyline<N>,
714 pos: &'a Isometry<N>,
715 edge_id: usize,
716 prediction: &'a ContactPrediction<N>,
717 ) -> Self {
718 PolylineContactProcessor {
719 polyline,
720 pos,
721 edge_id,
722 prediction,
723 }
724 }
725}
726
727impl<'a, N: RealField + Copy> ContactPreprocessor<N> for PolylineContactProcessor<'a, N> {
728 fn process_contact(
729 &self,
730 _c: &mut Contact<N>,
731 kinematic: &mut ContactKinematic<N>,
732 is_first: bool,
733 ) -> bool {
734 let feature = if is_first {
736 kinematic.feature1()
737 } else {
738 kinematic.feature2()
739 };
740
741 let edge = &self.polyline.edges()[self.edge_id];
742 let actual_feature = match feature {
743 FeatureId::Vertex(i) => FeatureId::Vertex(edge.indices[i]),
744 #[cfg(feature = "dim3")]
745 FeatureId::Edge(_) => FeatureId::Edge(self.edge_id),
746 FeatureId::Face(i) => {
747 if i == 0 {
748 FeatureId::Face(self.edge_id)
749 } else {
750 FeatureId::Face(self.edge_id + self.polyline.edges().len())
751 }
752 }
753 FeatureId::Unknown => FeatureId::Unknown,
754 };
755
756 if is_first {
757 kinematic.set_feature1(actual_feature);
758 } else {
759 kinematic.set_feature2(actual_feature);
760 }
761
762 true
776 }
777}
778
779#[cfg(feature = "dim2")]
780fn xy_point<N: RealField + Copy>(x: N, y: N) -> Point<N> {
781 Point::new(x, y)
782}
783
784#[cfg(feature = "dim3")]
785fn xy_point<N: RealField + Copy>(x: N, y: N) -> Point<N> {
786 Point::new(x, y, N::zero())
787}