tri_tri_intersect.cpp 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2021 Vladimir S. FONOV <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. /*
  9. *
  10. * C++ version based on the routines published in
  11. * "Fast and Robust Triangle-Triangle Overlap Test
  12. * Using Orientation Predicates" P. Guigue - O. Devillers
  13. *
  14. * Works with Eigen data structures instead of plain C arrays
  15. * returns bool values
  16. *
  17. * Code is rewritten to get rid of the macros and use C++ lambda and
  18. * inline functions instead
  19. *
  20. * Original notice:
  21. *
  22. * Triangle-Triangle Overlap Test Routines
  23. * July, 2002
  24. * Updated December 2003
  25. *
  26. * Updated by Vladimir S. FONOV
  27. * March, 2023
  28. *
  29. * This file contains C implementation of algorithms for
  30. * performing two and three-dimensional triangle-triangle intersection test
  31. * The algorithms and underlying theory are described in
  32. *
  33. * "Fast and Robust Triangle-Triangle Overlap Test
  34. * Using Orientation Predicates" P. Guigue - O. Devillers
  35. *
  36. * Journal of Graphics Tools, 8(1), 2003
  37. *
  38. * Several geometric predicates are defined. Their parameters are all
  39. * points. Each point is an array of two or three double precision
  40. * floating point numbers. The geometric predicates implemented in
  41. * this file are:
  42. *
  43. * int tri_tri_overlap_test_3d(p1,q1,r1,p2,q2,r2)
  44. * int tri_tri_overlap_test_2d(p1,q1,r1,p2,q2,r2)
  45. *
  46. * int tri_tri_intersection_test_3d(p1,q1,r1,p2,q2,r2,
  47. * coplanar,source,target)
  48. *
  49. * is a version that computes the segment of intersection when
  50. * the triangles overlap (and are not coplanar)
  51. *
  52. * each function returns 1 if the triangles (including their
  53. * boundary) intersect, otherwise 0
  54. *
  55. *
  56. * Other information are available from the Web page
  57. * http://www.acm.org/jgt/papers/GuigueDevillers03/
  58. *
  59. */
  60. #ifndef IGL_TRI_TRI_INTERSECT_CPP
  61. #define IGL_TRI_TRI_INTERSECT_CPP
  62. #include "tri_tri_intersect.h"
  63. #include "EPS.h"
  64. #include <Eigen/Geometry>
  65. // helper functions
  66. namespace igl {
  67. namespace internal {
  68. template <typename DerivedP1,typename DerivedQ1,typename DerivedR1,
  69. typename DerivedP2,typename DerivedQ2,typename DerivedR2,
  70. typename DerivedN1>
  71. IGL_INLINE bool coplanar_tri_tri3d(
  72. const Eigen::MatrixBase<DerivedP1> &p1, const Eigen::MatrixBase<DerivedQ1> &q1, const Eigen::MatrixBase<DerivedR1> &r1,
  73. const Eigen::MatrixBase<DerivedP2> &p2, const Eigen::MatrixBase<DerivedQ2> &q2, const Eigen::MatrixBase<DerivedR2> &r2,
  74. const Eigen::MatrixBase<DerivedN1> &normal_1);
  75. template <typename DerivedP1,typename DerivedQ1,typename DerivedR1,
  76. typename DerivedP2,typename DerivedQ2,typename DerivedR2>
  77. IGL_INLINE bool ccw_tri_tri_intersection_2d(
  78. const Eigen::MatrixBase<DerivedP1> &p1, const Eigen::MatrixBase<DerivedQ1> &q1, const Eigen::MatrixBase<DerivedR1> &r1,
  79. const Eigen::MatrixBase<DerivedP2> &p2, const Eigen::MatrixBase<DerivedQ2> &q2, const Eigen::MatrixBase<DerivedR2> &r2);
  80. template <typename DerivedP1,typename DerivedQ1,typename DerivedR1,
  81. typename DerivedP2,typename DerivedQ2,typename DerivedR2>
  82. inline bool _IGL_CHECK_MIN_MAX(
  83. const Eigen::MatrixBase<DerivedP1> &p1, const Eigen::MatrixBase<DerivedQ1> &q1, const Eigen::MatrixBase<DerivedR1> &r1,
  84. const Eigen::MatrixBase<DerivedP2> &p2, const Eigen::MatrixBase<DerivedQ2> &q2, const Eigen::MatrixBase<DerivedR2> &r2)
  85. {
  86. using Scalar = typename DerivedP1::Scalar;
  87. using RowVector = typename Eigen::Matrix<Scalar, 1, 3>;
  88. RowVector v1=p2-q1;
  89. RowVector v2=p1-q1;
  90. RowVector N1=v1.cross(v2);
  91. v1=q2-q1;
  92. if (v1.dot(N1) > 0.0) return false;
  93. v1=p2-p1;
  94. v2=r1-p1;
  95. N1=v1.cross(v2);
  96. v1=r2-p1;
  97. if (v1.dot(N1) > 0.0) return false;
  98. else return true;
  99. }
  100. /* Permutation in a canonical form of T2's vertices */
  101. template <typename DerivedP1,typename DerivedQ1,typename DerivedR1,
  102. typename DerivedP2,typename DerivedQ2,typename DerivedR2,
  103. typename DP2,typename DQ2,typename DR2,
  104. typename DerivedN1>
  105. inline bool _IGL_TRI_TRI_3D(
  106. const Eigen::MatrixBase<DerivedP1> &p1, const Eigen::MatrixBase<DerivedQ1> &q1, const Eigen::MatrixBase<DerivedR1> &r1,
  107. const Eigen::MatrixBase<DerivedP2> &p2, const Eigen::MatrixBase<DerivedQ2> &q2, const Eigen::MatrixBase<DerivedR2> &r2,
  108. DP2 dp2, DQ2 dq2,DR2 dr2,
  109. const Eigen::MatrixBase<DerivedN1> &N1)
  110. {
  111. if (dp2 > 0.0) {
  112. if (dq2 > 0.0) return _IGL_CHECK_MIN_MAX(p1,r1,q1,r2,p2,q2);
  113. else if (dr2 > 0.0) return _IGL_CHECK_MIN_MAX(p1,r1,q1,q2,r2,p2);
  114. else return _IGL_CHECK_MIN_MAX(p1,q1,r1,p2,q2,r2); }
  115. else if (dp2 < 0.0) {
  116. if (dq2 < 0.0) return _IGL_CHECK_MIN_MAX(p1,q1,r1,r2,p2,q2);
  117. else if (dr2 < 0.0) return _IGL_CHECK_MIN_MAX(p1,q1,r1,q2,r2,p2);
  118. else return _IGL_CHECK_MIN_MAX(p1,r1,q1,p2,q2,r2);
  119. } else {
  120. if (dq2 < 0.0) {
  121. if (dr2 >= 0.0) return _IGL_CHECK_MIN_MAX(p1,r1,q1,q2,r2,p2);
  122. else return _IGL_CHECK_MIN_MAX(p1,q1,r1,p2,q2,r2);
  123. }
  124. else if (dq2 > 0.0) {
  125. if (dr2 > 0.0) return _IGL_CHECK_MIN_MAX(p1,r1,q1,p2,q2,r2);
  126. else return _IGL_CHECK_MIN_MAX(p1,q1,r1,q2,r2,p2);
  127. }
  128. else {
  129. if (dr2 > 0.0) return _IGL_CHECK_MIN_MAX(p1,q1,r1,r2,p2,q2);
  130. else if (dr2 < 0.0) return _IGL_CHECK_MIN_MAX(p1,r1,q1,r2,p2,q2);
  131. else return coplanar_tri_tri3d(p1,q1,r1,p2,q2,r2,N1);
  132. }}
  133. }
  134. } //igl
  135. } // internal
  136. /*
  137. *
  138. * Three-dimensional Triangle-Triangle Overlap Test
  139. *
  140. */
  141. template <typename DerivedP1,typename DerivedQ1,typename DerivedR1,
  142. typename DerivedP2,typename DerivedQ2,typename DerivedR2>
  143. IGL_INLINE bool igl::tri_tri_overlap_test_3d(
  144. const Eigen::MatrixBase<DerivedP1> & p1,
  145. const Eigen::MatrixBase<DerivedQ1> & q1,
  146. const Eigen::MatrixBase<DerivedR1> & r1,
  147. const Eigen::MatrixBase<DerivedP2> & p2,
  148. const Eigen::MatrixBase<DerivedQ2> & q2,
  149. const Eigen::MatrixBase<DerivedR2> & r2)
  150. {
  151. using Scalar = typename DerivedP1::Scalar;
  152. using RowVector = typename Eigen::Matrix<Scalar, 1, 3>;
  153. Scalar dp1, dq1, dr1, dp2, dq2, dr2;
  154. RowVector v1, v2;
  155. RowVector N1, N2;
  156. /* Compute distance signs of p1, q1 and r1 to the plane of
  157. triangle(p2,q2,r2) */
  158. v1=p2-r2;
  159. v2=q2-r2;
  160. N2=v1.cross(v2);
  161. v1=p1-r2;
  162. dp1 = v1.dot(N2);
  163. v1=q1-r2;
  164. dq1 = v1.dot(N2);
  165. v1=r1-r2;
  166. dr1 = v1.dot(N2);
  167. if (((dp1 * dq1) > 0.0) && ((dp1 * dr1) > 0.0)) return false;
  168. /* Compute distance signs of p2, q2 and r2 to the plane of
  169. triangle(p1,q1,r1) */
  170. v1=q1-p1;
  171. v2=r1-p1;
  172. N1=v1.cross(v2);
  173. v1=p2-r1;
  174. dp2 = v1.dot(N1);
  175. v1=q2-r1;
  176. dq2 = v1.dot(N1);
  177. v1=r2-r1;
  178. dr2 = v1.dot(N1);
  179. if (((dp2 * dq2) > 0.0) && ((dp2 * dr2) > 0.0)) return false;
  180. /* Permutation in a canonical form of T1's vertices */
  181. if (dp1 > 0.0) {
  182. if (dq1 > 0.0) return internal::_IGL_TRI_TRI_3D(r1,p1,q1,p2,r2,q2,dp2,dr2,dq2,N1);
  183. else if (dr1 > 0.0) return internal::_IGL_TRI_TRI_3D(q1,r1,p1,p2,r2,q2,dp2,dr2,dq2,N1);
  184. else return internal::_IGL_TRI_TRI_3D(p1,q1,r1,p2,q2,r2,dp2,dq2,dr2,N1);
  185. } else if (dp1 < 0.0) {
  186. if (dq1 < 0.0) return internal::_IGL_TRI_TRI_3D(r1,p1,q1,p2,q2,r2,dp2,dq2,dr2,N1);
  187. else if (dr1 < 0.0) return internal::_IGL_TRI_TRI_3D(q1,r1,p1,p2,q2,r2,dp2,dq2,dr2,N1);
  188. else return internal::_IGL_TRI_TRI_3D(p1,q1,r1,p2,r2,q2,dp2,dr2,dq2,N1);
  189. } else {
  190. if (dq1 < 0.0) {
  191. if (dr1 >= 0.0) return internal::_IGL_TRI_TRI_3D(q1,r1,p1,p2,r2,q2,dp2,dr2,dq2,N1);
  192. else return internal::_IGL_TRI_TRI_3D(p1,q1,r1,p2,q2,r2,dp2,dq2,dr2,N1);
  193. }
  194. else if (dq1 > 0.0) {
  195. if (dr1 > 0.0) return internal::_IGL_TRI_TRI_3D(p1,q1,r1,p2,r2,q2,dp2,dr2,dq2,N1);
  196. else return internal::_IGL_TRI_TRI_3D(q1,r1,p1,p2,q2,r2,dp2,dq2,dr2,N1);
  197. }
  198. else {
  199. if (dr1 > 0.0) return internal::_IGL_TRI_TRI_3D(r1,p1,q1,p2,q2,r2,dp2,dq2,dr2,N1);
  200. else if (dr1 < 0.0) return internal::_IGL_TRI_TRI_3D(r1,p1,q1,p2,r2,q2,dp2,dr2,dq2,N1);
  201. else return internal::coplanar_tri_tri3d(p1,q1,r1,p2,q2,r2,N1);
  202. }
  203. }
  204. };
  205. template <typename DerivedP1,typename DerivedQ1,typename DerivedR1,
  206. typename DerivedP2,typename DerivedQ2,typename DerivedR2,
  207. typename DerivedN1>
  208. IGL_INLINE bool igl::internal::coplanar_tri_tri3d(
  209. const Eigen::MatrixBase<DerivedP1> &p1, const Eigen::MatrixBase<DerivedQ1> &q1, const Eigen::MatrixBase<DerivedR1> &r1,
  210. const Eigen::MatrixBase<DerivedP2> &p2, const Eigen::MatrixBase<DerivedQ2> &q2, const Eigen::MatrixBase<DerivedR2> &r2,
  211. const Eigen::MatrixBase<DerivedN1> &normal_1)
  212. {
  213. using Scalar= typename DerivedP1::Scalar;
  214. using RowVector2D = typename Eigen::Matrix<Scalar,1,2>;
  215. RowVector2D P1,Q1,R1;
  216. RowVector2D P2,Q2,R2;
  217. Scalar n_x, n_y, n_z;
  218. n_x = ((normal_1[0]<0.0)?-normal_1[0]:normal_1[0]);
  219. n_y = ((normal_1[1]<0.0)?-normal_1[1]:normal_1[1]);
  220. n_z = ((normal_1[2]<0.0)?-normal_1[2]:normal_1[2]);
  221. /* Projection of the triangles in 3D onto 2D such that the area of
  222. the projection is maximized. */
  223. if (( n_x > n_z ) && ( n_x >= n_y )) {
  224. // Project onto plane YZ
  225. P1[0] = q1[2]; P1[1] = q1[1];
  226. Q1[0] = p1[2]; Q1[1] = p1[1];
  227. R1[0] = r1[2]; R1[1] = r1[1];
  228. P2[0] = q2[2]; P2[1] = q2[1];
  229. Q2[0] = p2[2]; Q2[1] = p2[1];
  230. R2[0] = r2[2]; R2[1] = r2[1];
  231. } else if (( n_y > n_z ) && ( n_y >= n_x )) {
  232. // Project onto plane XZ
  233. P1[0] = q1[0]; P1[1] = q1[2];
  234. Q1[0] = p1[0]; Q1[1] = p1[2];
  235. R1[0] = r1[0]; R1[1] = r1[2];
  236. P2[0] = q2[0]; P2[1] = q2[2];
  237. Q2[0] = p2[0]; Q2[1] = p2[2];
  238. R2[0] = r2[0]; R2[1] = r2[2];
  239. } else {
  240. // Project onto plane XY
  241. P1[0] = p1[0]; P1[1] = p1[1];
  242. Q1[0] = q1[0]; Q1[1] = q1[1];
  243. R1[0] = r1[0]; R1[1] = r1[1];
  244. P2[0] = p2[0]; P2[1] = p2[1];
  245. Q2[0] = q2[0]; Q2[1] = q2[1];
  246. R2[0] = r2[0]; R2[1] = r2[1];
  247. }
  248. return tri_tri_overlap_test_2d(P1,Q1,R1,P2,Q2,R2);
  249. };
  250. namespace igl
  251. {
  252. namespace internal {
  253. /*
  254. *
  255. * Three-dimensional Triangle-Triangle Intersection
  256. *
  257. */
  258. /*
  259. This macro is called when the triangles surely intersect
  260. It constructs the segment of intersection of the two triangles
  261. if they are not coplanar.
  262. */
  263. // NOTE: a faster, but possibly less precise, method of computing
  264. // point B is described here: https://github.com/erich666/jgt-code/issues/5
  265. template <typename DerivedP1,typename DerivedQ1,typename DerivedR1,
  266. typename DerivedP2,typename DerivedQ2,typename DerivedR2,
  267. typename DerivedS,typename DerivedT,
  268. typename DerivedN1,typename DerivedN2>
  269. bool _IGL_CONSTRUCT_INTERSECTION(
  270. const Eigen::MatrixBase<DerivedP1> &p1, const Eigen::MatrixBase<DerivedQ1> &q1, const Eigen::MatrixBase<DerivedR1> &r1,
  271. const Eigen::MatrixBase<DerivedP2> &p2, const Eigen::MatrixBase<DerivedQ2> &q2, const Eigen::MatrixBase<DerivedR2> &r2,
  272. Eigen::MatrixBase<DerivedS> &source, Eigen::MatrixBase<DerivedT> &target,
  273. const Eigen::MatrixBase<DerivedN1> &N1,const Eigen::MatrixBase<DerivedN2> &N2)
  274. {
  275. using Scalar = typename DerivedP1::Scalar;
  276. using RowVector3D = typename Eigen::Matrix<Scalar,1,3>;
  277. RowVector3D v,v1,v2,N;
  278. v1=q1-p1;
  279. v2=r2-p1;
  280. N=v1.cross(v2);
  281. v=p2-p1;
  282. if (v.dot(N) > 0.0) {
  283. v1=r1-p1;
  284. N=v1.cross(v2);
  285. if (v.dot(N) <= 0.0) {
  286. v2=q2-p1;
  287. N=v1.cross(v2);
  288. if (v.dot(N) > 0.0) {
  289. v1=p1-p2;
  290. v2=p1-r1;
  291. Scalar alpha = v1.dot(N2) / v2.dot(N2);
  292. v1=v2*alpha;
  293. source=p1-v1;
  294. v1=p2-p1;
  295. v2=p2-r2;
  296. alpha = v1.dot(N1) / v2.dot(N1);
  297. v1=v2*alpha;
  298. target=p2-v1;
  299. return true;
  300. } else {
  301. v1=p2-p1;
  302. v2=p2-q2;
  303. Scalar alpha = v1.dot(N1) / v2.dot(N1);
  304. v1=v2*alpha;
  305. source=p2-v1;
  306. v1=p2-p1;
  307. v2=p2-r2;
  308. alpha = v1.dot(N1) / v2.dot(N1);
  309. v1=v2*alpha;
  310. target=p2-v1;
  311. return true;
  312. }
  313. } else {
  314. return false;
  315. }
  316. } else {
  317. v2=q2-p1;
  318. N=v1.cross(v2);
  319. if (v.dot(N) < 0.0) {
  320. return false;
  321. } else {
  322. v1=r1-p1;
  323. N=v1.cross(v2);
  324. if (v.dot(N) >= 0.0) {
  325. v1=p1-p2;
  326. v2=p1-r1;
  327. Scalar alpha = v1.dot(N2) / v2.dot(N2);
  328. v1=v2*alpha;
  329. source=p1-v1;
  330. v1=p1-p2;
  331. v2=p1-q1;
  332. alpha = v1.dot(N2) / v2.dot(N2);
  333. v1=v2*alpha;
  334. target=p1-v1 ;
  335. return true;
  336. } else {
  337. v1=p2-p1 ;
  338. v2=p2-q2 ;
  339. Scalar alpha = v1.dot(N1) / v2.dot(N1);
  340. v1=v2*alpha;
  341. source=p2-v1;
  342. v1=p1-p2;
  343. v2=p1-q1;
  344. alpha = v1.dot(N2) / v2.dot(N2);
  345. v1=v2*alpha;
  346. target=p1-v1 ;
  347. return true;
  348. }}}
  349. }
  350. // #define _IGL_CONSTRUCT_INTERSECTION(p1,q1,r1,p2,q2,r2) { \
  351. // _IGL_SUB(v1,q1,p1) \
  352. // _IGL_SUB(v2,r2,p1) \
  353. // _IGL_CROSS(N,v1,v2) \
  354. // _IGL_SUB(v,p2,p1) \
  355. // if (_IGL_DOT(v,N) > 0.0) {\
  356. // _IGL_SUB(v1,r1,p1) \
  357. // _IGL_CROSS(N,v1,v2) \
  358. // if (_IGL_DOT(v,N) <= 0.0) { \
  359. // _IGL_SUB(v2,q2,p1) \
  360. // _IGL_CROSS(N,v1,v2) \
  361. // if (_IGL_DOT(v,N) > 0.0) { \
  362. // _IGL_SUB(v1,p1,p2) \
  363. // _IGL_SUB(v2,p1,r1) \
  364. // alpha = _IGL_DOT(v1,N2) / _IGL_DOT(v2,N2); \
  365. // _IGL_SCALAR(v1,alpha,v2) \
  366. // _IGL_SUB(source,p1,v1) \
  367. // _IGL_SUB(v1,p2,p1) \
  368. // _IGL_SUB(v2,p2,r2) \
  369. // alpha = _IGL_DOT(v1,N1) / _IGL_DOT(v2,N1); \
  370. // _IGL_SCALAR(v1,alpha,v2) \
  371. // _IGL_SUB(target,p2,v1) \
  372. // return true; \
  373. // } else { \
  374. // _IGL_SUB(v1,p2,p1) \
  375. // _IGL_SUB(v2,p2,q2) \
  376. // alpha = _IGL_DOT(v1,N1) / _IGL_DOT(v2,N1); \
  377. // _IGL_SCALAR(v1,alpha,v2) \
  378. // _IGL_SUB(source,p2,v1) \
  379. // _IGL_SUB(v1,p2,p1) \
  380. // _IGL_SUB(v2,p2,r2) \
  381. // alpha = _IGL_DOT(v1,N1) / _IGL_DOT(v2,N1); \
  382. // _IGL_SCALAR(v1,alpha,v2) \
  383. // _IGL_SUB(target,p2,v1) \
  384. // return true; \
  385. // } \
  386. // } else { \
  387. // return false; \
  388. // } \
  389. // } else { \
  390. // _IGL_SUB(v2,q2,p1) \
  391. // _IGL_CROSS(N,v1,v2) \
  392. // if (_IGL_DOT(v,N) < 0.0) { \
  393. // return false; \
  394. // } else { \
  395. // _IGL_SUB(v1,r1,p1) \
  396. // _IGL_CROSS(N,v1,v2) \
  397. // if (_IGL_DOT(v,N) >= 0.0) { \
  398. // _IGL_SUB(v1,p1,p2) \
  399. // _IGL_SUB(v2,p1,r1) \
  400. // alpha = _IGL_DOT(v1,N2) / _IGL_DOT(v2,N2); \
  401. // _IGL_SCALAR(v1,alpha,v2) \
  402. // _IGL_SUB(source,p1,v1) \
  403. // _IGL_SUB(v1,p1,p2) \
  404. // _IGL_SUB(v2,p1,q1) \
  405. // alpha = _IGL_DOT(v1,N2) / _IGL_DOT(v2,N2); \
  406. // _IGL_SCALAR(v1,alpha,v2) \
  407. // _IGL_SUB(target,p1,v1) \
  408. // return true; \
  409. // } else { \
  410. // _IGL_SUB(v1,p2,p1) \
  411. // _IGL_SUB(v2,p2,q2) \
  412. // alpha = _IGL_DOT(v1,N1) / _IGL_DOT(v2,N1); \
  413. // _IGL_SCALAR(v1,alpha,v2) \
  414. // _IGL_SUB(source,p2,v1) \
  415. // _IGL_SUB(v1,p1,p2) \
  416. // _IGL_SUB(v2,p1,q1) \
  417. // alpha = _IGL_DOT(v1,N2) / _IGL_DOT(v2,N2); \
  418. // _IGL_SCALAR(v1,alpha,v2) \
  419. // _IGL_SUB(target,p1,v1) \
  420. // return true; \
  421. // }}}}
  422. template <typename DerivedP1,typename DerivedQ1,typename DerivedR1,
  423. typename DerivedP2,typename DerivedQ2,typename DerivedR2,
  424. typename DP2,typename DQ2,typename DR2,
  425. typename DerivedS,typename DerivedT,
  426. typename DerivedN1,typename DerivedN2
  427. >
  428. inline bool _IGL_TRI_TRI_INTER_3D(
  429. const Eigen::MatrixBase<DerivedP1> &p1, const Eigen::MatrixBase<DerivedQ1> &q1, const Eigen::MatrixBase<DerivedR1> &r1,
  430. const Eigen::MatrixBase<DerivedP2> &p2, const Eigen::MatrixBase<DerivedQ2> &q2, const Eigen::MatrixBase<DerivedR2> &r2,
  431. DP2 dp2, DQ2 dq2,DR2 dr2,
  432. bool & coplanar,
  433. Eigen::MatrixBase<DerivedS> &source, Eigen::MatrixBase<DerivedT> &target,
  434. const Eigen::MatrixBase<DerivedN1> &N1,const Eigen::MatrixBase<DerivedN2> &N2
  435. )
  436. {
  437. if (dp2 > 0.0) {
  438. if (dq2 > 0.0) return _IGL_CONSTRUCT_INTERSECTION(p1,r1,q1,r2,p2,q2,source,target,N1,N2);
  439. else if (dr2 > 0.0) return _IGL_CONSTRUCT_INTERSECTION(p1,r1,q1,q2,r2,p2,source,target,N1,N2);
  440. else return _IGL_CONSTRUCT_INTERSECTION(p1,q1,r1,p2,q2,r2,source,target,N1,N2); }
  441. else if (dp2 < 0.0) {
  442. if (dq2 < 0.0) return _IGL_CONSTRUCT_INTERSECTION(p1,q1,r1,r2,p2,q2,source,target,N1,N2);
  443. else if (dr2 < 0.0) return _IGL_CONSTRUCT_INTERSECTION(p1,q1,r1,q2,r2,p2,source,target,N1,N2);
  444. else return _IGL_CONSTRUCT_INTERSECTION(p1,r1,q1,p2,q2,r2,source,target,N1,N2);
  445. } else {
  446. if (dq2 < 0.0) {
  447. if (dr2 >= 0.0) return _IGL_CONSTRUCT_INTERSECTION(p1,r1,q1,q2,r2,p2,source,target,N1,N2);
  448. else return _IGL_CONSTRUCT_INTERSECTION(p1,q1,r1,p2,q2,r2,source,target,N1,N2);
  449. }
  450. else if (dq2 > 0.0) {
  451. if (dr2 > 0.0) return _IGL_CONSTRUCT_INTERSECTION(p1,r1,q1,p2,q2,r2,source,target,N1,N2);
  452. else return _IGL_CONSTRUCT_INTERSECTION(p1,q1,r1,q2,r2,p2,source,target,N1,N2);
  453. }
  454. else {
  455. if (dr2 > 0.0) return _IGL_CONSTRUCT_INTERSECTION(p1,q1,r1,r2,p2,q2,source,target,N1,N2);
  456. else if (dr2 < 0.0) return _IGL_CONSTRUCT_INTERSECTION(p1,r1,q1,r2,p2,q2,source,target,N1,N2);
  457. else {
  458. coplanar = true;
  459. return igl::internal::coplanar_tri_tri3d(p1,q1,r1,p2,q2,r2,N1);
  460. }
  461. }}
  462. }
  463. // #define _IGL_TRI_TRI_INTER_3D(p1,q1,r1,p2,q2,r2,dp2,dq2,dr2) { \
  464. // if (dp2 > 0.0) { \
  465. // if (dq2 > 0.0) _IGL_CONSTRUCT_INTERSECTION(p1,r1,q1,r2,p2,q2) \
  466. // else if (dr2 > 0.0) _IGL_CONSTRUCT_INTERSECTION(p1,r1,q1,q2,r2,p2)\
  467. // else _IGL_CONSTRUCT_INTERSECTION(p1,q1,r1,p2,q2,r2) }\
  468. // else if (dp2 < 0.0) { \
  469. // if (dq2 < 0.0) _IGL_CONSTRUCT_INTERSECTION(p1,q1,r1,r2,p2,q2)\
  470. // else if (dr2 < 0.0) _IGL_CONSTRUCT_INTERSECTION(p1,q1,r1,q2,r2,p2)\
  471. // else _IGL_CONSTRUCT_INTERSECTION(p1,r1,q1,p2,q2,r2)\
  472. // } else { \
  473. // if (dq2 < 0.0) { \
  474. // if (dr2 >= 0.0) _IGL_CONSTRUCT_INTERSECTION(p1,r1,q1,q2,r2,p2)\
  475. // else _IGL_CONSTRUCT_INTERSECTION(p1,q1,r1,p2,q2,r2)\
  476. // } \
  477. // else if (dq2 > 0.0) { \
  478. // if (dr2 > 0.0) _IGL_CONSTRUCT_INTERSECTION(p1,r1,q1,p2,q2,r2)\
  479. // else _IGL_CONSTRUCT_INTERSECTION(p1,q1,r1,q2,r2,p2)\
  480. // } \
  481. // else { \
  482. // if (dr2 > 0.0) _IGL_CONSTRUCT_INTERSECTION(p1,q1,r1,r2,p2,q2)\
  483. // else if (dr2 < 0.0) _IGL_CONSTRUCT_INTERSECTION(p1,r1,q1,r2,p2,q2)\
  484. // else { \
  485. // coplanar = true; \
  486. // return coplanar_tri_tri3d(p1,q1,r1,p2,q2,r2,N1);\
  487. // } \
  488. // }} }
  489. } //internal
  490. } //igl
  491. /*
  492. The following version computes the segment of intersection of the
  493. two triangles if it exists.
  494. coplanar returns whether the triangles are coplanar
  495. source and target are the endpoints of the line segment of intersection
  496. */
  497. template <typename DerivedP1,typename DerivedQ1,typename DerivedR1,
  498. typename DerivedP2,typename DerivedQ2,typename DerivedR2,
  499. typename DerivedS,typename DerivedT>
  500. IGL_INLINE bool igl::tri_tri_intersection_test_3d(
  501. const Eigen::MatrixBase<DerivedP1> & p1, const Eigen::MatrixBase<DerivedQ1> & q1, const Eigen::MatrixBase<DerivedR1> & r1,
  502. const Eigen::MatrixBase<DerivedP2> & p2, const Eigen::MatrixBase<DerivedQ2> & q2, const Eigen::MatrixBase<DerivedR2> & r2,
  503. bool & coplanar,
  504. Eigen::MatrixBase<DerivedS> & source, Eigen::MatrixBase<DerivedT> & target )
  505. {
  506. using Scalar = typename DerivedP1::Scalar;
  507. using RowVector3D = typename Eigen::Matrix<Scalar, 1, 3>;
  508. Scalar dp1, dq1, dr1, dp2, dq2, dr2;
  509. RowVector3D v1, v2, v;
  510. RowVector3D N1, N2, N;
  511. // Compute distance signs of p1, q1 and r1
  512. // to the plane of triangle(p2,q2,r2)
  513. v1=p2-r2;
  514. v2=q2-r2;
  515. N2=v1.cross(v2);
  516. v1=p1-r2;
  517. dp1 = v1.dot(N2);
  518. v1=q1-r2;
  519. dq1 = v1.dot(N2);
  520. v1=r1-r2;
  521. dr1 = v1.dot(N2);
  522. coplanar = false;
  523. if (((dp1 * dq1) > 0.0) && ((dp1 * dr1) > 0.0)) return false;
  524. // Compute distance signs of p2, q2 and r2
  525. // to the plane of triangle(p1,q1,r1)
  526. v1=q1-p1;
  527. v2=r1-p1;
  528. N1=v1.cross(v2);
  529. v1=p2-r1;
  530. dp2 = v1.dot(N1);
  531. v1=q2-r1;
  532. dq2 = v1.dot(N1);
  533. v1=r2-r1;
  534. dr2 = v1.dot(N1);
  535. if (((dp2 * dq2) > 0.0) && ((dp2 * dr2) > 0.0)) return false;
  536. // Alec: it's hard to believe this will ever be perfectly robust, but checking
  537. // 1e-22 against zero seems like a recipe for bad logic.
  538. // Switching all these 0.0s to epsilons makes other tests fail. My claim is
  539. // that the series of logic below is a bad way of determining coplanarity, so
  540. // instead just check for it right away.
  541. const Scalar eps = igl::EPS<Scalar>();
  542. using std::abs;
  543. if(
  544. abs(dp1) < eps && abs(dq1) < eps && abs(dr1) < eps &&
  545. abs(dp2) < eps && abs(dq2) < eps && abs(dr2) < eps)
  546. {
  547. coplanar = true;
  548. return internal::coplanar_tri_tri3d(p1,q1,r1,p2,q2,r2,N1);
  549. };
  550. // Permutation in a canonical form of T1's vertices
  551. if (dp1 > 0.0) {
  552. if (dq1 > 0.0) return internal::_IGL_TRI_TRI_INTER_3D(r1,p1,q1,p2,r2,q2,dp2,dr2,dq2,coplanar,source,target,N1,N2);
  553. else if (dr1 > 0.0) return internal::_IGL_TRI_TRI_INTER_3D(q1,r1,p1,p2,r2,q2,dp2,dr2,dq2,coplanar,source,target,N1,N2);
  554. else return internal::_IGL_TRI_TRI_INTER_3D(p1,q1,r1,p2,q2,r2,dp2,dq2,dr2,coplanar,source,target,N1,N2);
  555. } else if (dp1 < 0.0) {
  556. if (dq1 < 0.0) return internal::_IGL_TRI_TRI_INTER_3D(r1,p1,q1,p2,q2,r2,dp2,dq2,dr2,coplanar,source,target,N1,N2);
  557. else if (dr1 < 0.0) return internal::_IGL_TRI_TRI_INTER_3D(q1,r1,p1,p2,q2,r2,dp2,dq2,dr2,coplanar,source,target,N1,N2);
  558. else return internal::_IGL_TRI_TRI_INTER_3D(p1,q1,r1,p2,r2,q2,dp2,dr2,dq2,coplanar,source,target,N1,N2);
  559. } else {
  560. if (dq1 < 0.0) {
  561. if (dr1 >= 0.0) return internal::_IGL_TRI_TRI_INTER_3D(q1,r1,p1,p2,r2,q2,dp2,dr2,dq2,coplanar,source,target,N1,N2);
  562. else return internal::_IGL_TRI_TRI_INTER_3D(p1,q1,r1,p2,q2,r2,dp2,dq2,dr2,coplanar,source,target,N1,N2);
  563. }
  564. else if (dq1 > 0.0) {
  565. if (dr1 > 0.0) return internal::_IGL_TRI_TRI_INTER_3D(p1,q1,r1,p2,r2,q2,dp2,dr2,dq2,coplanar,source,target,N1,N2);
  566. else return internal::_IGL_TRI_TRI_INTER_3D(q1,r1,p1,p2,q2,r2,dp2,dq2,dr2,coplanar,source,target,N1,N2);
  567. }
  568. else {
  569. if (dr1 > 0.0) return internal::_IGL_TRI_TRI_INTER_3D(r1,p1,q1,p2,q2,r2,dp2,dq2,dr2,coplanar,source,target,N1,N2);
  570. else if (dr1 < 0.0) return internal::_IGL_TRI_TRI_INTER_3D(r1,p1,q1,p2,r2,q2,dp2,dr2,dq2,coplanar,source,target,N1,N2);
  571. else {
  572. // triangles are co-planar (should have been caught above).
  573. coplanar = true;
  574. return internal::coplanar_tri_tri3d(p1,q1,r1,p2,q2,r2,N1);
  575. }
  576. }
  577. }
  578. };
  579. namespace igl {
  580. namespace internal {
  581. /*
  582. *
  583. * Two dimensional Triangle-Triangle Overlap Test
  584. *
  585. */
  586. /* some 2D macros */
  587. //#define _IGL_ORIENT_2D(a, b, c) ((a[0]-c[0])*(b[1]-c[1])-(a[1]-c[1])*(b[0]-c[0]))
  588. template <typename DerivedA,typename DerivedB,typename DerivedC>
  589. inline typename Eigen::MatrixBase<DerivedA>::Scalar _IGL_ORIENT_2D(
  590. const Eigen::MatrixBase<DerivedA> & a,
  591. const Eigen::MatrixBase<DerivedB> & b,
  592. const Eigen::MatrixBase<DerivedC> & c)
  593. {
  594. return ((a[0]-c[0])*(b[1]-c[1])-(a[1]-c[1])*(b[0]-c[0]));
  595. }
  596. template <typename DerivedP1,typename DerivedQ1,typename DerivedR1,
  597. typename DerivedP2,typename DerivedQ2,typename DerivedR2>
  598. bool _IGL_INTERSECTION_TEST_VERTEX(
  599. const Eigen::MatrixBase<DerivedP1> & P1, const Eigen::MatrixBase<DerivedQ1> & Q1, const Eigen::MatrixBase<DerivedR1> & R1,
  600. const Eigen::MatrixBase<DerivedP2> & P2, const Eigen::MatrixBase<DerivedQ2> & Q2, const Eigen::MatrixBase<DerivedR2> & R2
  601. )
  602. {
  603. if (_IGL_ORIENT_2D(R2,P2,Q1) >= 0.0)
  604. if (_IGL_ORIENT_2D(R2,Q2,Q1) <= 0.0)
  605. if (_IGL_ORIENT_2D(P1,P2,Q1) > 0.0) {
  606. if (_IGL_ORIENT_2D(P1,Q2,Q1) <= 0.0) return true;
  607. else return false;}
  608. else {
  609. if (_IGL_ORIENT_2D(P1,P2,R1) >= 0.0)
  610. if (_IGL_ORIENT_2D(Q1,R1,P2) >= 0.0) return true;
  611. else return false;
  612. else return false;
  613. }
  614. else
  615. if (_IGL_ORIENT_2D(P1,Q2,Q1) <= 0.0)
  616. if (_IGL_ORIENT_2D(R2,Q2,R1) <= 0.0)
  617. if (_IGL_ORIENT_2D(Q1,R1,Q2) >= 0.0) return true;
  618. else return false;
  619. else return false;
  620. else return false;
  621. else
  622. if (_IGL_ORIENT_2D(R2,P2,R1) >= 0.0)
  623. if (_IGL_ORIENT_2D(Q1,R1,R2) >= 0.0)
  624. if (_IGL_ORIENT_2D(P1,P2,R1) >= 0.0) return true;
  625. else return false;
  626. else
  627. if (_IGL_ORIENT_2D(Q1,R1,Q2) >= 0.0) {
  628. if (_IGL_ORIENT_2D(R2,R1,Q2) >= 0.0) return true;
  629. else return false;
  630. }
  631. else return false;
  632. else return false;
  633. }
  634. // #define INTERSECTION_TEST_VERTEX(P1, Q1, R1, P2, Q2, R2) {\
  635. // if (_IGL_ORIENT_2D(R2,P2,Q1) >= 0.0)\
  636. // if (_IGL_ORIENT_2D(R2,Q2,Q1) <= 0.0)\
  637. // if (_IGL_ORIENT_2D(P1,P2,Q1) > 0.0) {\
  638. // if (_IGL_ORIENT_2D(P1,Q2,Q1) <= 0.0) return true; \
  639. // else return false;} else {\
  640. // if (_IGL_ORIENT_2D(P1,P2,R1) >= 0.0)\
  641. // if (_IGL_ORIENT_2D(Q1,R1,P2) >= 0.0) return true; \
  642. // else return false;\
  643. // else return false;}\
  644. // else \
  645. // if (_IGL_ORIENT_2D(P1,Q2,Q1) <= 0.0)\
  646. // if (_IGL_ORIENT_2D(R2,Q2,R1) <= 0.0)\
  647. // if (_IGL_ORIENT_2D(Q1,R1,Q2) >= 0.0) return true; \
  648. // else return false;\
  649. // else return false;\
  650. // else return false;\
  651. // else\
  652. // if (_IGL_ORIENT_2D(R2,P2,R1) >= 0.0) \
  653. // if (_IGL_ORIENT_2D(Q1,R1,R2) >= 0.0)\
  654. // if (_IGL_ORIENT_2D(P1,P2,R1) >= 0.0) return true;\
  655. // else return false;\
  656. // else \
  657. // if (_IGL_ORIENT_2D(Q1,R1,Q2) >= 0.0) {\
  658. // if (_IGL_ORIENT_2D(R2,R1,Q2) >= 0.0) return true; \
  659. // else return false; }\
  660. // else return false; \
  661. // else return false; \
  662. // };
  663. template <typename DerivedP1,typename DerivedQ1,typename DerivedR1,
  664. typename DerivedP2,typename DerivedQ2,typename DerivedR2>
  665. bool _IGL_INTERSECTION_TEST_EDGE(
  666. const Eigen::MatrixBase<DerivedP1> & P1, const Eigen::MatrixBase<DerivedQ1> & Q1, const Eigen::MatrixBase<DerivedR1> & R1,
  667. const Eigen::MatrixBase<DerivedP2> & P2, const Eigen::MatrixBase<DerivedQ2> & /*Q2*/, const Eigen::MatrixBase<DerivedR2> & R2
  668. )
  669. {
  670. if (_IGL_ORIENT_2D(R2,P2,Q1) >= 0.0) {
  671. if (_IGL_ORIENT_2D(P1,P2,Q1) >= 0.0) {
  672. if (_IGL_ORIENT_2D(P1,Q1,R2) >= 0.0) return true;
  673. else return false;} else {
  674. if (_IGL_ORIENT_2D(Q1,R1,P2) >= 0.0){
  675. if (_IGL_ORIENT_2D(R1,P1,P2) >= 0.0) return true; else return false;}
  676. else return false; }
  677. } else {
  678. if (_IGL_ORIENT_2D(R2,P2,R1) >= 0.0) {
  679. if (_IGL_ORIENT_2D(P1,P2,R1) >= 0.0) {
  680. if (_IGL_ORIENT_2D(P1,R1,R2) >= 0.0) return true;
  681. else {
  682. if (_IGL_ORIENT_2D(Q1,R1,R2) >= 0.0) return true; else return false;}}
  683. else return false; }
  684. else return false; }
  685. }
  686. // #define _IGL_INTERSECTION_TEST_EDGE(P1, Q1, R1, P2, Q2, R2) { \
  687. // if (_IGL_ORIENT_2D(R2,P2,Q1) >= 0.0) {\
  688. // if (_IGL_ORIENT_2D(P1,P2,Q1) >= 0.0) { \
  689. // if (_IGL_ORIENT_2D(P1,Q1,R2) >= 0.0) return true; \
  690. // else return false;} else { \
  691. // if (_IGL_ORIENT_2D(Q1,R1,P2) >= 0.0){ \
  692. // if (_IGL_ORIENT_2D(R1,P1,P2) >= 0.0) return true; else return false;} \
  693. // else return false; } \
  694. // } else {\
  695. // if (_IGL_ORIENT_2D(R2,P2,R1) >= 0.0) {\
  696. // if (_IGL_ORIENT_2D(P1,P2,R1) >= 0.0) {\
  697. // if (_IGL_ORIENT_2D(P1,R1,R2) >= 0.0) return true; \
  698. // else {\
  699. // if (_IGL_ORIENT_2D(Q1,R1,R2) >= 0.0) return true; else return false;}}\
  700. // else return false; }\
  701. // else return false; }}
  702. template <typename DerivedP1,typename DerivedQ1,typename DerivedR1,
  703. typename DerivedP2,typename DerivedQ2,typename DerivedR2>
  704. IGL_INLINE bool ccw_tri_tri_intersection_2d(
  705. const Eigen::MatrixBase<DerivedP1> &p1, const Eigen::MatrixBase<DerivedQ1> &q1, const Eigen::MatrixBase<DerivedR1> &r1,
  706. const Eigen::MatrixBase<DerivedP2> &p2, const Eigen::MatrixBase<DerivedQ2> &q2, const Eigen::MatrixBase<DerivedR2> &r2)
  707. {
  708. if ( _IGL_ORIENT_2D(p2,q2,p1) >= 0.0 ) {
  709. if ( _IGL_ORIENT_2D(q2,r2,p1) >= 0.0 ) {
  710. if ( _IGL_ORIENT_2D(r2,p2,p1) >= 0.0 ) return true;
  711. else return _IGL_INTERSECTION_TEST_EDGE(p1,q1,r1,p2,q2,r2);
  712. } else {
  713. if ( _IGL_ORIENT_2D(r2,p2,p1) >= 0.0 )
  714. return _IGL_INTERSECTION_TEST_EDGE(p1,q1,r1,r2,p2,q2);
  715. else return _IGL_INTERSECTION_TEST_VERTEX(p1,q1,r1,p2,q2,r2);}}
  716. else {
  717. if ( _IGL_ORIENT_2D(q2,r2,p1) >= 0.0 ) {
  718. if ( _IGL_ORIENT_2D(r2,p2,p1) >= 0.0 )
  719. return _IGL_INTERSECTION_TEST_EDGE(p1,q1,r1,q2,r2,p2);
  720. else return _IGL_INTERSECTION_TEST_VERTEX(p1,q1,r1,q2,r2,p2);}
  721. else return _IGL_INTERSECTION_TEST_VERTEX(p1,q1,r1,r2,p2,q2);}
  722. };
  723. }//internal
  724. } //igl
  725. template <typename DerivedP1,typename DerivedQ1,typename DerivedR1,
  726. typename DerivedP2,typename DerivedQ2,typename DerivedR2>
  727. IGL_INLINE bool igl::tri_tri_overlap_test_2d(
  728. const Eigen::MatrixBase<DerivedP1> &p1, const Eigen::MatrixBase<DerivedQ1> &q1, const Eigen::MatrixBase<DerivedR1> &r1,
  729. const Eigen::MatrixBase<DerivedP2> &p2, const Eigen::MatrixBase<DerivedQ2> &q2, const Eigen::MatrixBase<DerivedR2> &r2)
  730. {
  731. if ( igl::internal::_IGL_ORIENT_2D(p1,q1,r1) < 0.0)
  732. if ( igl::internal::_IGL_ORIENT_2D(p2,q2,r2) < 0.0)
  733. return igl::internal::ccw_tri_tri_intersection_2d(p1,r1,q1,p2,r2,q2);
  734. else
  735. return igl::internal::ccw_tri_tri_intersection_2d(p1,r1,q1,p2,q2,r2);
  736. else
  737. if ( igl::internal::_IGL_ORIENT_2D(p2,q2,r2) < 0.0 )
  738. return igl::internal::ccw_tri_tri_intersection_2d(p1,q1,r1,p2,r2,q2);
  739. else
  740. return igl::internal::ccw_tri_tri_intersection_2d(p1,q1,r1,p2,q2,r2);
  741. };
  742. #endif //IGL_TRI_TRI_INTERSECT_CPP
  743. #ifdef IGL_STATIC_LIBRARY
  744. // Explicit template specialization
  745. template bool igl::tri_tri_intersection_test_3d<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, bool&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
  746. template bool igl::tri_tri_intersection_test_3d<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Matrix<double, 1, -1, 1, 1, -1>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, -1, 1, 1, -1> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, bool&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
  747. template bool igl::tri_tri_intersection_test_3d<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false> > const&, bool&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
  748. template bool igl::tri_tri_intersection_test_3d<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, bool&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
  749. template bool igl::tri_tri_intersection_test_3d<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, bool&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
  750. template bool igl::tri_tri_overlap_test_3d<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> >(Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&);
  751. template bool igl::tri_tri_overlap_test_3d<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Matrix<double, 1, -1, 1, 1, -1>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> >(Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, -1, 1, 1, -1> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&);
  752. template bool igl::tri_tri_overlap_test_3d<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> >(Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1> const, 1, -1, false> > const&);
  753. #endif