38 #ifndef FCL_NARROWPHASE_DETAIL_PLANE_INL_H 39 #define FCL_NARROWPHASE_DETAIL_PLANE_INL_H 41 #include "fcl/narrowphase/detail/primitive_shape_algorithm/plane.h" 51 bool spherePlaneIntersect(
const Sphere<double>& s1,
const Transform3<double>& tf1,
52 const Plane<double>& s2,
const Transform3<double>& tf2,
53 std::vector<ContactPoint<double>>* contacts);
57 bool ellipsoidPlaneIntersect(
const Ellipsoid<double>& s1,
const Transform3<double>& tf1,
58 const Plane<double>& s2,
const Transform3<double>& tf2,
59 std::vector<ContactPoint<double>>* contacts);
63 bool boxPlaneIntersect(
const Box<double>& s1,
const Transform3<double>& tf1,
64 const Plane<double>& s2,
const Transform3<double>& tf2,
65 std::vector<ContactPoint<double>>* contacts);
69 bool capsulePlaneIntersect(
const Capsule<double>& s1,
const Transform3<double>& tf1,
70 const Plane<double>& s2,
const Transform3<double>& tf2);
74 bool capsulePlaneIntersect(
const Capsule<double>& s1,
const Transform3<double>& tf1,
75 const Plane<double>& s2,
const Transform3<double>& tf2,
76 std::vector<ContactPoint<double>>* contacts);
80 bool cylinderPlaneIntersect(
const Cylinder<double>& s1,
const Transform3<double>& tf1,
81 const Plane<double>& s2,
const Transform3<double>& tf2);
85 bool cylinderPlaneIntersect(
const Cylinder<double>& s1,
const Transform3<double>& tf1,
86 const Plane<double>& s2,
const Transform3<double>& tf2,
87 std::vector<ContactPoint<double>>* contacts);
91 bool conePlaneIntersect(
const Cone<double>& s1,
const Transform3<double>& tf1,
92 const Plane<double>& s2,
const Transform3<double>& tf2,
93 std::vector<ContactPoint<double>>* contacts);
97 bool convexPlaneIntersect(
const Convex<double>& s1,
const Transform3<double>& tf1,
98 const Plane<double>& s2,
const Transform3<double>& tf2,
99 Vector3<double>* contact_points,
double* penetration_depth, Vector3<double>* normal);
103 bool planeTriangleIntersect(
const Plane<double>& s1,
const Transform3<double>& tf1,
104 const Vector3<double>& P1,
const Vector3<double>& P2,
const Vector3<double>& P3,
const Transform3<double>& tf2,
105 Vector3<double>* contact_points,
double* penetration_depth, Vector3<double>* normal);
109 bool planeIntersect(
const Plane<double>& s1,
const Transform3<double>& tf1,
110 const Plane<double>& s2,
const Transform3<double>& tf2,
111 std::vector<ContactPoint<double>>* contacts);
114 template <
typename S>
115 S planeIntersectTolerance()
121 template <
typename S>
122 bool spherePlaneIntersect(
const Sphere<S>& s1,
const Transform3<S>& tf1,
123 const Plane<S>& s2,
const Transform3<S>& tf2,
124 std::vector<ContactPoint<S>>* contacts)
126 const Plane<S> new_s2 = transform(s2, tf2);
128 const Vector3<S>& center = tf1.translation();
129 const S signed_dist = new_s2.signedDistance(center);
130 const S depth = - std::abs(signed_dist) + s1.radius;
136 const Vector3<S> normal = (signed_dist > 0) ? (-new_s2.n).eval() : new_s2.n;
137 const Vector3<S>
point = center - new_s2.n * signed_dist;
138 const S penetration_depth = depth;
140 contacts->emplace_back(normal, point, penetration_depth);
152 template <
typename S>
153 bool ellipsoidPlaneIntersect(
const Ellipsoid<S>& s1,
const Transform3<S>& tf1,
154 const Plane<S>& s2,
const Transform3<S>& tf2,
155 std::vector<ContactPoint<S>>* contacts)
160 const Plane<S>& new_s2 = transform(s2, tf1.inverse(Eigen::Isometry) * tf2);
164 const Vector3<S> normal2(std::pow(new_s2.n[0], 2), std::pow(new_s2.n[1], 2), std::pow(new_s2.n[2], 2));
165 const Vector3<S> radii2(std::pow(s1.radii[0], 2), std::pow(s1.radii[1], 2), std::pow(s1.radii[2], 2));
166 const S center_to_contact_plane = std::sqrt(normal2.dot(radii2));
168 const S signed_dist = -new_s2.d;
171 const S depth = center_to_contact_plane - std::abs(signed_dist);
178 const Vector3<S> normal = (signed_dist > 0) ? (tf1.linear() * -new_s2.n).eval() : (tf1.linear() * new_s2.n).eval();
179 const Vector3<S> support_vector = (1.0/center_to_contact_plane) * Vector3<S>(radii2[0]*new_s2.n[0], radii2[1]*new_s2.n[1], radii2[2]*new_s2.n[2]);
180 const Vector3<S> point_in_plane_coords = support_vector * (depth / new_s2.n.dot(support_vector) - 1.0);
181 const Vector3<S>
point = (signed_dist > 0) ? tf1 * point_in_plane_coords : tf1 * -point_in_plane_coords;
182 const S penetration_depth = depth;
184 contacts->emplace_back(normal, point, penetration_depth);
196 template <
typename S>
197 bool boxPlaneIntersect(
const Box<S>& s1,
const Transform3<S>& tf1,
198 const Plane<S>& s2,
const Transform3<S>& tf2,
199 std::vector<ContactPoint<S>>* contacts)
201 Plane<S> new_s2 = transform(s2, tf2);
203 const Matrix3<S>& R = tf1.linear();
204 const Vector3<S>& T = tf1.translation();
206 Vector3<S> Q = R.transpose() * new_s2.n;
207 Vector3<S> A(Q[0] * s1.side[0], Q[1] * s1.side[1], Q[2] * s1.side[2]);
208 Vector3<S> B = A.cwiseAbs();
210 S signed_dist = new_s2.signedDistance(T);
211 S depth = 0.5 * (B[0] + B[1] + B[2]) - std::abs(signed_dist);
212 if(depth < 0)
return false;
224 int sign = (signed_dist > 0) ? 1 : -1;
226 if(std::abs(Q[0] - 1) < planeIntersectTolerance<S>() || std::abs(Q[0] + 1) < planeIntersectTolerance<S>())
228 int sign2 = (A[0] > 0) ? -1 : 1;
230 p += axis[0] * (0.5 * s1.side[0] * sign2);
232 else if(std::abs(Q[1] - 1) < planeIntersectTolerance<S>() || std::abs(Q[1] + 1) < planeIntersectTolerance<S>())
234 int sign2 = (A[1] > 0) ? -1 : 1;
236 p += axis[1] * (0.5 * s1.side[1] * sign2);
238 else if(std::abs(Q[2] - 1) < planeIntersectTolerance<S>() || std::abs(Q[2] + 1) < planeIntersectTolerance<S>())
240 int sign2 = (A[2] > 0) ? -1 : 1;
242 p += axis[2] * (0.5 * s1.side[2] * sign2);
246 for(std::size_t i = 0; i < 3; ++i)
248 int sign2 = (A[i] > 0) ? -1 : 1;
250 p += axis[i] * (0.5 * s1.side[i] * sign2);
257 const Vector3<S> normal = (signed_dist > 0) ? (-new_s2.n).eval() : new_s2.n;
258 const Vector3<S>
point = p - new_s2.n * new_s2.signedDistance(p);
259 const S penetration_depth = depth;
261 contacts->emplace_back(normal, point, penetration_depth);
268 template <
typename S>
269 bool capsulePlaneIntersect(
const Capsule<S>& s1,
const Transform3<S>& tf1,
270 const Plane<S>& s2,
const Transform3<S>& tf2)
272 Plane<S> new_s2 = transform(s2, tf2);
274 const Matrix3<S>& R = tf1.linear();
275 const Vector3<S>& T = tf1.translation();
277 Vector3<S> dir_z = R.col(2);
278 Vector3<S> p1 = T + dir_z * (0.5 * s1.lz);
279 Vector3<S> p2 = T - dir_z * (0.5 * s1.lz);
281 S d1 = new_s2.signedDistance(p1);
282 S d2 = new_s2.signedDistance(p2);
289 return (std::abs(d1) <= s1.radius) || (std::abs(d2) <= s1.radius);
293 template <
typename S>
294 bool capsulePlaneIntersect(
const Capsule<S>& s1,
const Transform3<S>& tf1,
295 const Plane<S>& s2,
const Transform3<S>& tf2,
296 std::vector<ContactPoint<S>>* contacts)
300 return capsulePlaneIntersect(s1, tf1, s2, tf2);
304 Plane<S> new_s2 = transform(s2, tf2);
306 const Matrix3<S>& R = tf1.linear();
307 const Vector3<S>& T = tf1.translation();
309 Vector3<S> dir_z = R.col(2);
312 Vector3<S> p1 = T + dir_z * (0.5 * s1.lz);
313 Vector3<S> p2 = T - dir_z * (0.5 * s1.lz);
315 S d1 = new_s2.signedDistance(p1);
316 S d2 = new_s2.signedDistance(p2);
318 S abs_d1 = std::abs(d1);
319 S abs_d2 = std::abs(d2);
325 if(d1 * d2 < -planeIntersectTolerance<S>())
331 const Vector3<S> normal = (d1 < 0) ? (-new_s2.n).eval() : new_s2.n;
332 const Vector3<S> point = p1 * (abs_d2 / (abs_d1 + abs_d2)) + p2 * (abs_d1 / (abs_d1 + abs_d2));
333 const S penetration_depth = abs_d1 + s1.radius;
335 contacts->emplace_back(normal, point, penetration_depth);
342 const Vector3<S> normal = (d2 < 0) ? (-new_s2.n).eval() : new_s2.n;
343 const Vector3<S> point = p1 * (abs_d2 / (abs_d1 + abs_d2)) + p2 * (abs_d1 / (abs_d1 + abs_d2));
344 const S penetration_depth = abs_d2 + s1.radius;
346 contacts->emplace_back(normal, point, penetration_depth);
352 if(abs_d1 > s1.radius && abs_d2 > s1.radius)
360 const Vector3<S> normal = (d1 < 0) ? new_s2.n : (-new_s2.n).eval();
361 const S penetration_depth = s1.radius - std::min(abs_d1, abs_d2);
363 if(abs_d1 <= s1.radius && abs_d2 <= s1.radius)
365 const Vector3<S> c1 = p1 - new_s2.n * d2;
366 const Vector3<S> c2 = p2 - new_s2.n * d1;
367 point = (c1 + c2) * 0.5;
369 else if(abs_d1 <= s1.radius)
371 const Vector3<S> c = p1 - new_s2.n * d1;
376 assert(abs_d2 <= s1.radius);
378 const Vector3<S> c = p2 - new_s2.n * d2;
382 contacts->emplace_back(normal, point, penetration_depth);
391 template <
typename S>
392 bool cylinderPlaneIntersect(
const Cylinder<S>& s1,
const Transform3<S>& tf1,
393 const Plane<S>& s2,
const Transform3<S>& tf2)
395 Plane<S> new_s2 = transform(s2, tf2);
397 const Matrix3<S>& R = tf1.linear();
398 const Vector3<S>& T = tf1.translation();
400 Vector3<S> Q = R.transpose() * new_s2.n;
402 S term = std::abs(Q[2]) * s1.lz + s1.radius * std::sqrt(Q[0] * Q[0] + Q[1] * Q[1]);
403 S dist = new_s2.distance(T);
404 S depth = term - dist;
413 template <
typename S>
414 bool cylinderPlaneIntersect(
const Cylinder<S>& s1,
const Transform3<S>& tf1,
415 const Plane<S>& s2,
const Transform3<S>& tf2,
416 std::vector<ContactPoint<S>>* contacts)
420 return cylinderPlaneIntersect(s1, tf1, s2, tf2);
424 Plane<S> new_s2 = transform(s2, tf2);
426 const Matrix3<S>& R = tf1.linear();
427 const Vector3<S>& T = tf1.translation();
429 Vector3<S> dir_z = R.col(2);
430 S cosa = dir_z.dot(new_s2.n);
432 if(std::abs(cosa) < planeIntersectTolerance<S>())
434 S d = new_s2.signedDistance(T);
435 S depth = s1.radius - std::abs(d);
436 if(depth < 0)
return false;
441 const Vector3<S> normal = (d < 0) ? new_s2.n : (-new_s2.n).eval();
442 const Vector3<S> point = T - new_s2.n * d;
443 const S penetration_depth = depth;
445 contacts->emplace_back(normal, point, penetration_depth);
452 Vector3<S> C = dir_z * cosa - new_s2.n;
453 if(std::abs(cosa + 1) < planeIntersectTolerance<S>() || std::abs(cosa - 1) < planeIntersectTolerance<S>())
454 C = Vector3<S>(0, 0, 0);
462 Vector3<S> p1 = T + dir_z * (0.5 * s1.lz);
463 Vector3<S> p2 = T - dir_z * (0.5 * s1.lz);
477 S d1 = new_s2.signedDistance(c1);
478 S d2 = new_s2.signedDistance(c2);
482 S abs_d1 = std::abs(d1);
483 S abs_d2 = std::abs(d2);
489 const Vector3<S> normal = (d2 < 0) ? (-new_s2.n).eval() : new_s2.n;
490 const Vector3<S> point = c2 - new_s2.n * d2;
491 const S penetration_depth = abs_d2;
493 contacts->emplace_back(normal, point, penetration_depth);
500 const Vector3<S> normal = (d1 < 0) ? (-new_s2.n).eval() : new_s2.n;
501 const Vector3<S> point = c1 - new_s2.n * d1;
502 const S penetration_depth = abs_d1;
504 contacts->emplace_back(normal, point, penetration_depth);
518 template <
typename S>
519 bool conePlaneIntersect(
const Cone<S>& s1,
const Transform3<S>& tf1,
520 const Plane<S>& s2,
const Transform3<S>& tf2,
521 std::vector<ContactPoint<S>>* contacts)
523 Plane<S> new_s2 = transform(s2, tf2);
525 const Matrix3<S>& R = tf1.linear();
526 const Vector3<S>& T = tf1.translation();
528 Vector3<S> dir_z = R.col(2);
529 S cosa = dir_z.dot(new_s2.n);
531 if(std::abs(cosa) < planeIntersectTolerance<S>())
533 S d = new_s2.signedDistance(T);
534 S depth = s1.radius - std::abs(d);
535 if(depth < 0)
return false;
540 const Vector3<S> normal = (d < 0) ? new_s2.n : (-new_s2.n).eval();
541 const Vector3<S> point = T - dir_z * (0.5 * s1.lz) + dir_z * (0.5 * depth / s1.radius * s1.lz) - new_s2.n * d;
542 const S penetration_depth = depth;
544 contacts->emplace_back(normal, point, penetration_depth);
552 Vector3<S> C = dir_z * cosa - new_s2.n;
553 if(std::abs(cosa + 1) < planeIntersectTolerance<S>() || std::abs(cosa - 1) < planeIntersectTolerance<S>())
554 C = Vector3<S>(0, 0, 0);
563 c[0] = T + dir_z * (0.5 * s1.lz);
564 c[1] = T - dir_z * (0.5 * s1.lz) + C;
565 c[2] = T - dir_z * (0.5 * s1.lz) - C;
568 d[0] = new_s2.signedDistance(c[0]);
569 d[1] = new_s2.signedDistance(c[1]);
570 d[2] = new_s2.signedDistance(c[2]);
572 if((d[0] >= 0 && d[1] >= 0 && d[2] >= 0) || (d[0] <= 0 && d[1] <= 0 && d[2] <= 0))
577 for(std::size_t i = 0; i < 3; ++i)
578 positive[i] = (d[i] >= 0);
581 S d_positive = 0, d_negative = 0;
582 for(std::size_t i = 0; i < 3; ++i)
587 if(d_positive <= d[i]) d_positive = d[i];
591 if(d_negative <= -d[i]) d_negative = -d[i];
597 const Vector3<S> normal = (d_positive > d_negative) ? (-new_s2.n).eval() : new_s2.n;
598 const S penetration_depth = std::min(d_positive, d_negative);
601 Vector3<S> p[2] { Vector3<S>::Zero(), Vector3<S>::Zero() };
602 Vector3<S> q = Vector3<S>::Zero();
609 for(std::size_t i = 0, j = 0; i < 3; ++i)
611 if(positive[i]) { p[j] = c[i]; p_d[j] = d[i]; j++; }
612 else { q = c[i]; q_d = d[i]; }
615 const Vector3<S> t1 = (-p[0] * q_d + q * p_d[0]) / (-q_d + p_d[0]);
616 const Vector3<S> t2 = (-p[1] * q_d + q * p_d[1]) / (-q_d + p_d[1]);
617 point = (t1 + t2) * 0.5;
621 for(std::size_t i = 0, j = 0; i < 3; ++i)
623 if(!positive[i]) { p[j] = c[i]; p_d[j] = d[i]; j++; }
624 else { q = c[i]; q_d = d[i]; }
627 const Vector3<S> t1 = (p[0] * q_d - q * p_d[0]) / (q_d - p_d[0]);
628 const Vector3<S> t2 = (p[1] * q_d - q * p_d[1]) / (q_d - p_d[1]);
629 point = (t1 + t2) * 0.5;
632 contacts->emplace_back(normal, point, penetration_depth);
641 template <
typename S>
642 bool convexPlaneIntersect(
const Convex<S>& s1,
const Transform3<S>& tf1,
643 const Plane<S>& s2,
const Transform3<S>& tf2,
644 Vector3<S>* contact_points, S* penetration_depth, Vector3<S>* normal)
646 Plane<S> new_s2 = transform(s2, tf2);
648 Vector3<S> v_min, v_max;
649 S d_min = std::numeric_limits<S>::max(), d_max = -std::numeric_limits<S>::max();
651 for(
int i = 0; i < s1.num_points; ++i)
653 Vector3<S> p = tf1 * s1.points[i];
655 S d = new_s2.signedDistance(p);
657 if(d < d_min) { d_min = d; v_min = p; }
658 if(d > d_max) { d_max = d; v_max = p; }
661 if(d_min * d_max > 0)
return false;
664 if(d_min + d_max > 0)
666 if(penetration_depth) *penetration_depth = -d_min;
667 if(normal) *normal = -new_s2.n;
668 if(contact_points) *contact_points = v_min - new_s2.n * d_min;
672 if(penetration_depth) *penetration_depth = d_max;
673 if(normal) *normal = new_s2.n;
674 if(contact_points) *contact_points = v_max - new_s2.n * d_max;
681 template <
typename S>
682 bool planeTriangleIntersect(
const Plane<S>& s1,
const Transform3<S>& tf1,
683 const Vector3<S>& P1,
const Vector3<S>& P2,
const Vector3<S>& P3,
const Transform3<S>& tf2,
684 Vector3<S>* contact_points, S* penetration_depth, Vector3<S>* normal)
686 Plane<S> new_s1 = transform(s1, tf1);
694 d[0] = new_s1.signedDistance(c[0]);
695 d[1] = new_s1.signedDistance(c[1]);
696 d[2] = new_s1.signedDistance(c[2]);
698 if((d[0] >= 0 && d[1] >= 0 && d[2] >= 0) || (d[0] <= 0 && d[1] <= 0 && d[2] <= 0))
703 for(std::size_t i = 0; i < 3; ++i)
704 positive[i] = (d[i] > 0);
707 S d_positive = 0, d_negative = 0;
708 for(std::size_t i = 0; i < 3; ++i)
713 if(d_positive <= d[i]) d_positive = d[i];
717 if(d_negative <= -d[i]) d_negative = -d[i];
721 if(penetration_depth) *penetration_depth = std::min(d_positive, d_negative);
722 if(normal) *normal = (d_positive > d_negative) ? new_s1.n : (-new_s1.n).eval();
725 Vector3<S> p[2] = {Vector3<S>::Zero(), Vector3<S>::Zero()};
726 Vector3<S> q = Vector3<S>::Zero();
733 for(std::size_t i = 0, j = 0; i < 3; ++i)
735 if(positive[i]) { p[j] = c[i]; p_d[j] = d[i]; j++; }
736 else { q = c[i]; q_d = d[i]; }
739 Vector3<S> t1 = (-p[0] * q_d + q * p_d[0]) / (-q_d + p_d[0]);
740 Vector3<S> t2 = (-p[1] * q_d + q * p_d[1]) / (-q_d + p_d[1]);
741 *contact_points = (t1 + t2) * 0.5;
745 for(std::size_t i = 0, j = 0; i < 3; ++i)
747 if(!positive[i]) { p[j] = c[i]; p_d[j] = d[i]; j++; }
748 else { q = c[i]; q_d = d[i]; }
751 Vector3<S> t1 = (p[0] * q_d - q * p_d[0]) / (q_d - p_d[0]);
752 Vector3<S> t2 = (p[1] * q_d - q * p_d[1]) / (q_d - p_d[1]);
753 *contact_points = (t1 + t2) * 0.5;
761 template <
typename S>
762 bool planeIntersect(
const Plane<S>& s1,
const Transform3<S>& tf1,
763 const Plane<S>& s2,
const Transform3<S>& tf2,
764 std::vector<ContactPoint<S>>* )
766 Plane<S> new_s1 = transform(s1, tf1);
767 Plane<S> new_s2 = transform(s2, tf2);
769 S a = (new_s1.n).dot(new_s2.n);
770 if(a == 1 && new_s1.d != new_s2.d)
772 if(a == -1 && new_s1.d != -new_s2.d)
Main namespace.
Definition: broadphase_bruteforce-inl.h:45
std::chrono::system_clock::time_point point
Representation of a point in time.
Definition: time.h:51