38 #ifndef FCL_NARROWPHASE_DETAIL_BOXBOX_INL_H
39 #define FCL_NARROWPHASE_DETAIL_BOXBOX_INL_H
54 const Vector3<double>& pb,
const Vector3<double>& ub,
55 double* alpha,
double* beta);
63 void cullPoints2(
int n,
double p[],
int m,
int i0,
int iret[]);
68 const Vector3<double>& side1,
69 const Transform3<double>& tf1,
70 const Vector3<double>& side2,
71 const Transform3<double>& tf2,
72 Vector3<double>& normal,
76 std::vector<ContactPoint<double>>& contacts);
81 const Box<double>& s2,
const Transform3<double>& tf2,
82 std::vector<ContactPoint<double>>* contacts_);
94 S d = 1 - uaub * uaub;
103 *alpha = (q1 + uaub * q2) * d;
104 *beta = (uaub * q1 + q2) * d;
109 template <
typename S>
118 for(
int dir = 0; dir <= 1; ++dir)
121 for(
int sign = -1; sign <= 1; sign += 2)
127 for(
int i = nq; i > 0; --i)
130 if(sign * pq[dir] < h[dir])
143 S* nextq = (i > 1) ? pq+2 : q;
144 if((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir]))
147 pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) /
148 (nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]);
149 pr[dir] = sign*h[dir];
161 r = (q == ret) ? buffer : ret;
167 if(q != ret) memcpy(ret, q, nr*2*
sizeof(S));
172 template <
typename S>
184 cx = 0.5 * (p[0] + p[2]);
185 cy = 0.5 * (p[1] + p[3]);
191 for(
int i = 0; i < n-1; ++i)
193 q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1];
195 cx += q*(p[i*2]+p[i*2+2]);
196 cy += q*(p[i*2+1]+p[i*2+3]);
198 q = p[n*2-2]*p[1] - p[0]*p[n*2-1];
204 cx = a*(cx + q*(p[n*2-2]+p[0]));
205 cy = a*(cy + q*(p[n*2-1]+p[1]));
211 for(
int i = 0; i < n; ++i)
212 A[i] = atan2(p[i*2+1]-cy,p[i*2]-cx);
216 for(
int i = 0; i < n; ++i) avail[i] = 1;
221 for(
int j = 1; j < m; ++j)
223 a = j*(2*pi/m) + A[i0];
224 if (a > pi) a -= 2*pi;
225 S maxdiff= 1e9, diff;
228 for(
int i = 0; i < n; ++i)
232 diff = std::abs(A[i]-a);
233 if(diff > pi) diff = 2*pi - diff;
247 template <
typename S,
typename DerivedA,
typename DerivedB>
250 const Eigen::MatrixBase<DerivedA>& R1,
251 const Eigen::MatrixBase<DerivedB>& T1,
253 const Eigen::MatrixBase<DerivedA>& R2,
254 const Eigen::MatrixBase<DerivedB>& T2,
264 const S fudge_factor = S(1.05);
267 int invert_normal, code;
290 int best_col_id = -1;
291 const Eigen::MatrixBase<DerivedA>* normalR = 0;
300 s2 = std::abs(tmp) - (Q.row(0).dot(B) + A[0]);
301 if(s2 > 0) { *return_code = 0;
return 0; }
307 invert_normal = (tmp < 0);
312 s2 = std::abs(tmp) - (Q.row(1).dot(B) + A[1]);
313 if(s2 > 0) { *return_code = 0;
return 0; }
319 invert_normal = (tmp < 0);
324 s2 = std::abs(tmp) - (Q.row(2).dot(B) + A[2]);
325 if(s2 > 0) { *return_code = 0;
return 0; }
331 invert_normal = (tmp < 0);
336 tmp = R2.col(0).dot(p);
337 s2 = std::abs(tmp) - (Q.col(0).dot(A) + B[0]);
338 if(s2 > 0) { *return_code = 0;
return 0; }
344 invert_normal = (tmp < 0);
348 tmp = R2.col(1).dot(p);
349 s2 = std::abs(tmp) - (Q.col(1).dot(A) + B[1]);
350 if(s2 > 0) { *return_code = 0;
return 0; }
356 invert_normal = (tmp < 0);
360 tmp = R2.col(2).dot(p);
361 s2 = std::abs(tmp) - (Q.col(2).dot(A) + B[2]);
362 if(s2 > 0) { *return_code = 0;
return 0; }
368 invert_normal = (tmp < 0);
396 S scale_factor =
max(
max(A.maxCoeff(), B.maxCoeff()), S(1.0)) * S(10) * eps;
397 Q.array() += scale_factor;
403 tmp = pp[2] * R(1, 0) - pp[1] * R(2, 0);
404 s2 = std::abs(tmp) - (A[1] * Q(2, 0) + A[2] * Q(1, 0) + B[1] * Q(0, 2) + B[2] * Q(0, 1));
405 if(s2 > 0) { *return_code = 0;
return 0; }
411 if(s2 * fudge_factor > s)
416 invert_normal = (tmp < 0);
421 tmp = pp[2] * R(1, 1) - pp[1] * R(2, 1);
422 s2 = std::abs(tmp) - (A[1] * Q(2, 1) + A[2] * Q(1, 1) + B[0] * Q(0, 2) + B[2] * Q(0, 0));
423 if(s2 > 0) { *return_code = 0;
return 0; }
429 if(s2 * fudge_factor > s)
434 invert_normal = (tmp < 0);
439 tmp = pp[2] * R(1, 2) - pp[1] * R(2, 2);
440 s2 = std::abs(tmp) - (A[1] * Q(2, 2) + A[2] * Q(1, 2) + B[0] * Q(0, 1) + B[1] * Q(0, 0));
441 if(s2 > 0) { *return_code = 0;
return 0; }
447 if(s2 * fudge_factor > s)
452 invert_normal = (tmp < 0);
458 tmp = pp[0] * R(2, 0) - pp[2] * R(0, 0);
459 s2 = std::abs(tmp) - (A[0] * Q(2, 0) + A[2] * Q(0, 0) + B[1] * Q(1, 2) + B[2] * Q(1, 1));
460 if(s2 > 0) { *return_code = 0;
return 0; }
466 if(s2 * fudge_factor > s)
471 invert_normal = (tmp < 0);
476 tmp = pp[0] * R(2, 1) - pp[2] * R(0, 1);
477 s2 = std::abs(tmp) - (A[0] * Q(2, 1) + A[2] * Q(0, 1) + B[0] * Q(1, 2) + B[2] * Q(1, 0));
478 if(s2 > 0) { *return_code = 0;
return 0; }
484 if(s2 * fudge_factor > s)
489 invert_normal = (tmp < 0);
494 tmp = pp[0] * R(2, 2) - pp[2] * R(0, 2);
495 s2 = std::abs(tmp) - (A[0] * Q(2, 2) + A[2] * Q(0, 2) + B[0] * Q(1, 1) + B[1] * Q(1, 0));
496 if(s2 > 0) { *return_code = 0;
return 0; }
502 if(s2 * fudge_factor > s)
507 invert_normal = (tmp < 0);
513 tmp = pp[1] * R(0, 0) - pp[0] * R(1, 0);
514 s2 = std::abs(tmp) - (A[0] * Q(1, 0) + A[1] * Q(0, 0) + B[1] * Q(2, 2) + B[2] * Q(2, 1));
515 if(s2 > 0) { *return_code = 0;
return 0; }
521 if(s2 * fudge_factor > s)
526 invert_normal = (tmp < 0);
531 tmp = pp[1] * R(0, 1) - pp[0] * R(1, 1);
532 s2 = std::abs(tmp) - (A[0] * Q(1, 1) + A[1] * Q(0, 1) + B[0] * Q(2, 2) + B[2] * Q(2, 0));
533 if(s2 > 0) { *return_code = 0;
return 0; }
539 if(s2 * fudge_factor > s)
544 invert_normal = (tmp < 0);
549 tmp = pp[1] * R(0, 2) - pp[0] * R(1, 2);
550 s2 = std::abs(tmp) - (A[0] * Q(1, 2) + A[1] * Q(0, 2) + B[0] * Q(2, 1) + B[1] * Q(2, 0));
551 if(s2 > 0) { *return_code = 0;
return 0; }
557 if(s2 * fudge_factor > s)
562 invert_normal = (tmp < 0);
567 if (!code) { *return_code = code;
return 0; }
571 if(best_col_id != -1)
572 normal = normalR->col(best_col_id);
574 normal = R1 * normalC;
590 for(
int j = 0; j < 3; ++j)
592 sign = (R1.col(j).dot(normal) > 0) ? 1 : -1;
593 pa += R1.col(j) * (A[j] * sign);
599 for(
int j = 0; j < 3; ++j)
601 sign = (R2.col(j).dot(normal) > 0) ? -1 : 1;
602 pb += R2.col(j) * (B[j] * sign);
614 contacts.emplace_back(normal, pointInWorld, *depth);
625 const Eigen::MatrixBase<DerivedA> *Ra, *Rb;
626 const Eigen::MatrixBase<DerivedB> *pa, *pb;
656 nr = Rb->transpose() * normal2;
697 center = (*pb) - (*pa) + Rb->col(lanr) * ((*Sb)[lanr]);
699 center = (*pb) - (*pa) - Rb->col(lanr) * ((*Sb)[lanr]);
702 int codeN, code1, code2;
725 S c1, c2, m11, m12, m21, m22;
726 c1 = Ra->col(code1).dot(center);
727 c2 = Ra->col(code2).dot(center);
732 m11 = Rb->col(a1).dot(tempRac);
733 m12 = Rb->col(a2).dot(tempRac);
734 tempRac = Ra->col(code2);
735 m21 = Rb->col(a1).dot(tempRac);
736 m22 = Rb->col(a2).dot(tempRac);
738 S k1 = m11 * (*Sb)[a1];
739 S k2 = m21 * (*Sb)[a1];
740 S k3 = m12 * (*Sb)[a2];
741 S k4 = m22 * (*Sb)[a2];
742 quad[0] = c1 - k1 - k3;
743 quad[1] = c2 - k2 - k4;
744 quad[2] = c1 - k1 + k3;
745 quad[3] = c2 - k2 + k4;
746 quad[4] = c1 + k1 + k3;
747 quad[5] = c2 + k2 + k4;
748 quad[6] = c1 + k1 - k3;
749 quad[7] = c2 + k2 - k4;
753 rect[0] = (*Sa)[code1];
754 rect[1] = (*Sa)[code2];
759 if(n_intersect < 1) { *return_code = code;
return 0; }
767 S det1 = 1.f/(m11*m22 - m12*m21);
773 for(
int j = 0; j < n_intersect; ++j)
775 S k1 = m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2);
776 S k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2);
777 points[cnum] = center + Rb->col(a1) * k1 + Rb->col(a2) * k2;
778 dep[cnum] = (*Sa)[codeN] - normal2.dot(points[cnum]);
781 ret[cnum*2] = ret[j*2];
782 ret[cnum*2+1] = ret[j*2+1];
786 if(cnum < 1) { *return_code = code;
return 0; }
789 if(maxc > cnum) maxc = cnum;
790 if(maxc < 1) maxc = 1;
801 int iret[] = {0, 1, 2, 3, 4, 5, 6, 7};
805 for(
int i = 1; i < cnum; ++i)
807 if(dep[i] > maxdepth)
819 for(
int j = 0; j < cnum; ++j)
822 Vector3<S> pointInWorld = points[i] + (*pa) + normal * (dep[i] / 2);
823 contacts.emplace_back(normal, pointInWorld, dep[i]);
826 for(
int j = 0; j < cnum; ++j)
829 Vector3<S> pointInWorld = points[i] + (*pa) - normal * (dep[i] / 2);
830 contacts.emplace_back(normal, pointInWorld, dep[i]);
839 template <
typename S>
851 return boxBox2(side1, tf1.linear(), tf1.translation(), side2, tf2.linear(),
852 tf2.translation(), normal, depth, return_code, maxc, contacts);
856 template <
typename S>
861 std::vector<ContactPoint<S>> contacts;
867 normal, &depth, &return_code,
871 *contacts_ = contacts;
873 return return_code != 0;