38 #ifndef FCL_NARROWPHASE_DETAIL_SPHERETRIANGLE_INL_H 39 #define FCL_NARROWPHASE_DETAIL_SPHERETRIANGLE_INL_H 41 #include "fcl/narrowphase/detail/primitive_shape_algorithm/sphere_triangle.h" 43 #include "fcl/math/detail/project.h" 53 double segmentSqrDistance(
const Vector3<double>& from,
const Vector3<double>& to,
const Vector3<double>& p, Vector3<double>& nearest);
57 bool projectInTriangle(
const Vector3<double>& p1,
const Vector3<double>& p2,
const Vector3<double>& p3,
const Vector3<double>& normal,
const Vector3<double>& p);
61 bool sphereTriangleIntersect(
const Sphere<double>& s,
const Transform3<double>& tf,
62 const Vector3<double>& P1,
const Vector3<double>& P2,
const Vector3<double>& P3, Vector3<double>* contact_points,
double* penetration_depth, Vector3<double>* normal_);
66 bool sphereTriangleDistance(
const Sphere<double>& sp,
const Transform3<double>& tf,
67 const Vector3<double>& P1,
const Vector3<double>& P2,
const Vector3<double>& P3,
72 bool sphereTriangleDistance(
const Sphere<double>& sp,
const Transform3<double>& tf,
73 const Vector3<double>& P1,
const Vector3<double>& P2,
const Vector3<double>& P3,
74 double* dist, Vector3<double>* p1, Vector3<double>* p2);
78 bool sphereTriangleDistance(
const Sphere<double>& sp,
const Transform3<double>& tf1,
79 const Vector3<double>& P1,
const Vector3<double>& P2,
const Vector3<double>& P3,
const Transform3<double>& tf2,
80 double* dist, Vector3<double>* p1, Vector3<double>* p2);
84 S segmentSqrDistance(
const Vector3<S>& from,
const Vector3<S>& to,
const Vector3<S>& p, Vector3<S>& nearest)
86 Vector3<S> diff = p - from;
87 Vector3<S> v = to - from;
107 nearest = from + v * t;
108 return diff.dot(diff);
112 template <
typename S>
113 bool projectInTriangle(
const Vector3<S>& p1,
const Vector3<S>& p2,
const Vector3<S>& p3,
const Vector3<S>& normal,
const Vector3<S>& p)
115 Vector3<S> edge1(p2 - p1);
116 Vector3<S> edge2(p3 - p2);
117 Vector3<S> edge3(p1 - p3);
119 Vector3<S> p1_to_p(p - p1);
120 Vector3<S> p2_to_p(p - p2);
121 Vector3<S> p3_to_p(p - p3);
123 Vector3<S> edge1_normal(edge1.cross(normal));
124 Vector3<S> edge2_normal(edge2.cross(normal));
125 Vector3<S> edge3_normal(edge3.cross(normal));
128 r1 = edge1_normal.dot(p1_to_p);
129 r2 = edge2_normal.dot(p2_to_p);
130 r3 = edge3_normal.dot(p3_to_p);
131 if ( ( r1 > 0 && r2 > 0 && r3 > 0 ) ||
132 ( r1 <= 0 && r2 <= 0 && r3 <= 0 ) )
138 template <
typename S>
139 bool sphereTriangleIntersect(
const Sphere<S>& s,
const Transform3<S>& tf,
140 const Vector3<S>& P1,
const Vector3<S>& P2,
const Vector3<S>& P3, Vector3<S>* contact_points, S* penetration_depth, Vector3<S>* normal_)
142 Vector3<S> normal = (P2 - P1).cross(P3 - P1);
144 const Vector3<S>& center = tf.translation();
145 const S& radius = s.radius;
146 S radius_with_threshold = radius + std::numeric_limits<S>::epsilon();
147 Vector3<S> p1_to_center = center - P1;
148 S distance_from_plane = p1_to_center.dot(normal);
150 if(distance_from_plane < 0)
152 distance_from_plane *= -1;
156 bool is_inside_contact_plane = (distance_from_plane < radius_with_threshold);
158 bool has_contact =
false;
159 Vector3<S> contact_point;
160 if(is_inside_contact_plane)
162 if(projectInTriangle(P1, P2, P3, normal, center))
165 contact_point = center - normal * distance_from_plane;
169 S contact_capsule_radius_sqr = radius_with_threshold * radius_with_threshold;
170 Vector3<S> nearest_on_edge;
172 distance_sqr = segmentSqrDistance(P1, P2, center, nearest_on_edge);
173 if(distance_sqr < contact_capsule_radius_sqr)
176 contact_point = nearest_on_edge;
179 distance_sqr = segmentSqrDistance(P2, P3, center, nearest_on_edge);
180 if(distance_sqr < contact_capsule_radius_sqr)
183 contact_point = nearest_on_edge;
186 distance_sqr = segmentSqrDistance(P3, P1, center, nearest_on_edge);
187 if(distance_sqr < contact_capsule_radius_sqr)
190 contact_point = nearest_on_edge;
197 Vector3<S> contact_to_center = contact_point - center;
198 S distance_sqr = contact_to_center.squaredNorm();
200 if(distance_sqr < radius_with_threshold * radius_with_threshold)
204 S
distance = std::sqrt(distance_sqr);
205 if(normal_) *normal_ = contact_to_center.normalized();
206 if(contact_points) *contact_points = contact_point;
207 if(penetration_depth) *penetration_depth = -(radius -
distance);
211 if(normal_) *normal_ = -normal;
212 if(contact_points) *contact_points = contact_point;
213 if(penetration_depth) *penetration_depth = -radius;
224 template <
typename S>
225 bool sphereTriangleDistance(
const Sphere<S>& sp,
const Transform3<S>& tf,
226 const Vector3<S>& P1,
const Vector3<S>& P2,
const Vector3<S>& P3,
231 const Vector3<S>& center = tf.translation();
232 S radius = sp.radius;
233 Vector3<S> diff = P1 - center;
234 Vector3<S> edge0 = P2 - P1;
235 Vector3<S> edge1 = P3 - P1;
236 S a00 = edge0.squaredNorm();
237 S a01 = edge0.dot(edge1);
238 S a11 = edge1.squaredNorm();
239 S b0 = diff.dot(edge0);
240 S b1 = diff.dot(edge1);
241 S c = diff.squaredNorm();
242 S det = fabs(a00*a11 - a01*a01);
243 S s = a01*b1 - a11*b0;
244 S t = a01*b0 - a00*b1;
260 sqr_dist = a00 + 2*b0 + c;
279 sqr_dist = a11 + 2*b1 + c;
299 sqr_dist = a11 + 2*b1 + c;
319 sqr_dist = a00 + 2*b0 + c;
333 sqr_dist = s*(a00*s + a01*t + 2*b0) + t*(a01*s + a11*t + 2*b1) + c;
338 S tmp0, tmp1, numer, denom;
347 denom = a00 - 2*a01 + a11;
352 sqr_dist = a00 + 2*b0 + c;
358 sqr_dist = s*(a00*s + a01*t + 2*b0) + t*(a01*s + a11*t + 2*b1) + c;
367 sqr_dist = a11 + 2*b1 + c;
388 denom = a00 - 2*a01 + a11;
393 sqr_dist = a11 + 2*b1 + c;
399 sqr_dist = s*(a00*s + a01*t + 2*b0) + t*(a01*s + a11*t + 2*b1) + c;
408 sqr_dist = a00 + 2*b0 + c;
424 numer = a11 + b1 - a01 - b0;
429 sqr_dist = a11 + 2*b1 + c;
433 denom = a00 - 2*a01 + a11;
438 sqr_dist = a00 + 2*b0 + c;
444 sqr_dist = s*(a00*s + a01*t + 2*b0) + t*(a01*s + a11*t + 2*b1) + c;
454 if(sqr_dist > radius * radius)
456 if(dist) *dist = std::sqrt(sqr_dist) - radius;
467 template <
typename S>
468 bool sphereTriangleDistance(
const Sphere<S>& sp,
const Transform3<S>& tf,
469 const Vector3<S>& P1,
const Vector3<S>& P2,
const Vector3<S>& P3,
470 S* dist, Vector3<S>* p1, Vector3<S>* p2)
474 Vector3<S> o = tf.translation();
475 typename Project<S>::ProjectResult result;
477 if(result.sqr_distance > sp.radius * sp.radius)
479 if(dist) *dist = std::sqrt(result.sqr_distance) - sp.radius;
480 Vector3<S> project_p = P1 * result.parameterization[0] + P2 * result.parameterization[1] + P3 * result.parameterization[2];
481 Vector3<S> dir = o - project_p;
483 if(p1) { *p1 = o - dir * sp.radius; *p1 = tf.inverse(Eigen::Isometry) * (*p1); }
484 if(p2) *p2 = project_p;
492 return sphereTriangleDistance(sp, tf, P1, P2, P3, dist);
497 template <
typename S>
498 bool sphereTriangleDistance(
const Sphere<S>& sp,
const Transform3<S>& tf1,
499 const Vector3<S>& P1,
const Vector3<S>& P2,
const Vector3<S>& P3,
const Transform3<S>& tf2,
500 S* dist, Vector3<S>* p1, Vector3<S>* p2)
502 bool res = detail::sphereTriangleDistance(sp, tf1, tf2 * P1, tf2 * P2, tf2 * P3, dist, p1, p2);
503 if(p2) *p2 = tf2.inverse(Eigen::Isometry) * (*p2);
Main namespace.
Definition: broadphase_bruteforce-inl.h:45
static ProjectResult projectTriangle(const Vector3< S > &a, const Vector3< S > &b, const Vector3< S > &c, const Vector3< S > &p)
Project point p onto triangle a-b-c.
Definition: project-inl.h:77
S distance(const Eigen::MatrixBase< DerivedA > &R0, const Eigen::MatrixBase< DerivedB > &T0, const kIOS< S > &b1, const kIOS< S > &b2, Vector3< S > *P, Vector3< S > *Q)
Approximate distance between two kIOS bounding volumes.
Definition: kIOS-inl.h:266