1
// Copyright (C) 2014 Anders Logg and August Johansson
3
// This file is part of DOLFIN.
5
// DOLFIN is free software: you can redistribute it and/or modify
6
// it under the terms of the GNU Lesser General Public License as published by
7
// the Free Software Foundation, either version 3 of the License, or
8
// (at your option) any later version.
10
// DOLFIN is distributed in the hope that it will be useful,
11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
// GNU Lesser General Public License for more details.
15
// You should have received a copy of the GNU Lesser General Public License
16
// along with DOLFIN. If not, see <http://www.gnu.org/licenses/>.
18
// First added: 2014-02-03
19
// Last changed: 2014-02-24
21
//-----------------------------------------------------------------------------
22
// Special note regarding the function collides_tetrahedron_tetrahedron
23
//-----------------------------------------------------------------------------
25
// The source code for the tetrahedron-tetrahedron collision test is
26
// from Fabio Ganovelli, Federico Ponchio and Claudio Rocchini: Fast
27
// Tetrahedron-Tetrahedron Overlap Algorithm, Journal of Graphics
28
// Tools, 7(2), 2002, and is under the following copyright:
30
// Visual Computing Group
31
// IEI Institute, CNUCE Institute, CNR Pisa
33
// Copyright(C) 2002 by Fabio Ganovelli, Federico Ponchio and Claudio
36
// All rights reserved.
38
// Permission to use, copy, modify, distribute and sell this software
39
// and its documentation for any purpose is hereby granted without
40
// fee, provided that the above copyright notice appear in all copies
41
// and that both that copyright notice and this permission notice
42
// appear in supporting documentation. the author makes no
43
// representations about the suitability of this software for any
44
// purpose. It is provided "as is" without express or implied
47
//-----------------------------------------------------------------------------
48
// Special note regarding the function collides_triangle_triangle
49
//-----------------------------------------------------------------------------
51
// The source code for the triangle-triangle collision test is from
52
// Tomas Moller: A Fast Triangle-Triangle Intersection Test, Journal
53
// of Graphics Tools, 2(2), 1997, and is in the public domain.
55
//-----------------------------------------------------------------------------
57
#include <dolfin/mesh/MeshEntity.h>
59
#include "CollisionDetection.h"
61
using namespace dolfin;
63
//-----------------------------------------------------------------------------
64
bool CollisionDetection::collides(const MeshEntity& entity,
70
dolfin_not_implemented();
73
return collides_interval_point(entity, point);
75
return collides_triangle_point(entity, point);
77
return collides_tetrahedron_point(entity, point);
79
dolfin_error("CollisionDetection.cpp",
80
"collides entity with point",
81
"Unknown dimension of entity");
86
//-----------------------------------------------------------------------------
88
CollisionDetection::collides(const MeshEntity& entity_0,
89
const MeshEntity& entity_1)
91
switch (entity_0.dim())
94
// Collision with PointCell
95
dolfin_not_implemented();
98
// Collision with interval
99
switch (entity_1.dim())
102
dolfin_not_implemented();
105
return collides_interval_interval(entity_1, entity_0);
108
dolfin_not_implemented();
111
dolfin_not_implemented();
114
dolfin_error("CollisionDetection.cpp",
115
"collides entity_0 with entity_1",
116
"Unknown dimension of entity_1 in IntervalCell collision");
120
// Collision with triangle
121
switch (entity_1.dim())
124
dolfin_not_implemented();
127
dolfin_not_implemented();
130
return collides_triangle_triangle(entity_0, entity_1);
132
return collides_tetrahedron_triangle(entity_1, entity_0);
134
dolfin_error("CollisionDetection.cpp",
135
"collides entity_0 with entity_1",
136
"Unknown dimension of entity_1 in TriangleCell collision");
140
// Collision with tetrahedron
141
switch (entity_1.dim())
144
dolfin_not_implemented();
147
dolfin_not_implemented();
150
return collides_tetrahedron_triangle(entity_0, entity_1);
153
return collides_tetrahedron_tetrahedron(entity_0, entity_1);
156
dolfin_error("CollisionDetection.cpp",
157
"collides entity_0 with entity_1",
158
"Unknown dimension of entity_1 in TetrahedronCell collision");
162
dolfin_error("CollisionDetection.cpp",
163
"collides entity_0 with entity_1",
164
"Unknown dimension of entity_0");
169
//-----------------------------------------------------------------------------
170
bool CollisionDetection::collides_interval_point(const MeshEntity& entity,
174
const MeshGeometry& geometry = entity.mesh().geometry();
175
const unsigned int* vertices = entity.entities(0);
176
const double x0 = geometry.point(vertices[0])[0];
177
const double x1 = geometry.point(vertices[1])[0];
178
const double x = point.x();
180
// Check for collision
181
const double dx = std::abs(x1 - x0);
182
const double eps = std::max(DOLFIN_EPS_LARGE, DOLFIN_EPS_LARGE*dx);
183
return ((x >= x0 - eps && x <= x1 + eps) ||
184
(x >= x1 - eps && x <= x0 + eps));
186
//-----------------------------------------------------------------------------
188
CollisionDetection::collides_interval_interval(const MeshEntity& interval_0,
189
const MeshEntity& interval_1)
192
const MeshGeometry& geometry_0 = interval_0.mesh().geometry();
193
const MeshGeometry& geometry_1 = interval_1.mesh().geometry();
194
const unsigned int* vertices_0 = interval_0.entities(0);
195
const unsigned int* vertices_1 = interval_1.entities(0);
196
const double x00 = geometry_0.point(vertices_0[0])[0];
197
const double x01 = geometry_0.point(vertices_0[1])[0];
198
const double x10 = geometry_1.point(vertices_1[0])[0];
199
const double x11 = geometry_1.point(vertices_1[1])[0];
201
const double a0 = std::min(x00, x01);
202
const double b0 = std::max(x00, x01);
203
const double a1 = std::min(x10, x11);
204
const double b1 = std::max(x10, x11);
206
// Check for collisions
207
const double dx = std::min(b0 - a0, b1 - a1);
208
const double eps = std::max(DOLFIN_EPS_LARGE, DOLFIN_EPS_LARGE*dx);
209
return b1 > a0 - eps && a1 < b0 + eps;
211
//-----------------------------------------------------------------------------
212
bool CollisionDetection::collides_triangle_point(const MeshEntity& triangle,
215
dolfin_assert(triangle.mesh().topology().dim() == 2);
217
const MeshGeometry& geometry = triangle.mesh().geometry();
218
const unsigned int* vertices = triangle.entities(0);
219
return collides_triangle_point(geometry.point(vertices[0]),
220
geometry.point(vertices[1]),
221
geometry.point(vertices[2]),
224
//-----------------------------------------------------------------------------
226
CollisionDetection::collides_triangle_triangle(const MeshEntity& triangle_0,
227
const MeshEntity& triangle_1)
229
dolfin_assert(triangle_0.mesh().topology().dim() == 2);
230
dolfin_assert(triangle_1.mesh().topology().dim() == 2);
232
// Get vertices as points
233
const MeshGeometry& geometry_0 = triangle_0.mesh().geometry();
234
const unsigned int* vertices_0 = triangle_0.entities(0);
235
const MeshGeometry& geometry_1 = triangle_1.mesh().geometry();
236
const unsigned int* vertices_1 = triangle_1.entities(0);
238
return collides_triangle_triangle(geometry_0.point(vertices_0[0]),
239
geometry_0.point(vertices_0[1]),
240
geometry_0.point(vertices_0[2]),
241
geometry_1.point(vertices_1[0]),
242
geometry_1.point(vertices_1[1]),
243
geometry_1.point(vertices_1[2]));
245
//-----------------------------------------------------------------------------
247
CollisionDetection::collides_tetrahedron_point(const MeshEntity& tetrahedron,
250
dolfin_assert(tetrahedron.mesh().topology().dim() == 3);
252
// Get the vertices as points
253
const MeshGeometry& geometry = tetrahedron.mesh().geometry();
254
const unsigned int* vertices = tetrahedron.entities(0);
256
return collides_tetrahedron_point(geometry.point(vertices[0]),
257
geometry.point(vertices[1]),
258
geometry.point(vertices[2]),
259
geometry.point(vertices[3]),
262
//-----------------------------------------------------------------------------
264
CollisionDetection::collides_tetrahedron_triangle(const MeshEntity& tetrahedron,
265
const MeshEntity& triangle)
267
dolfin_assert(tetrahedron.mesh().topology().dim() == 3);
268
dolfin_assert(triangle.mesh().topology().dim() == 2);
270
// Get the vertices of the tetrahedron as points
271
const MeshGeometry& geometry_tet = tetrahedron.mesh().geometry();
272
const unsigned int* vertices_tet = tetrahedron.entities(0);
274
// Get the vertices of the triangle as points
275
const MeshGeometry& geometry_tri = triangle.mesh().geometry();
276
const unsigned int* vertices_tri = triangle.entities(0);
278
return collides_tetrahedron_triangle(geometry_tet.point(vertices_tet[0]),
279
geometry_tet.point(vertices_tet[1]),
280
geometry_tet.point(vertices_tet[2]),
281
geometry_tet.point(vertices_tet[3]),
282
geometry_tri.point(vertices_tri[0]),
283
geometry_tri.point(vertices_tri[1]),
284
geometry_tri.point(vertices_tri[2]));
286
//-----------------------------------------------------------------------------
288
CollisionDetection::collides_tetrahedron_tetrahedron
289
(const MeshEntity& tetrahedron_0,
290
const MeshEntity& tetrahedron_1)
292
// This algorithm checks whether two tetrahedra intersect.
294
// Algorithm and source code from Fabio Ganovelli, Federico Ponchio
295
// and Claudio Rocchini: Fast Tetrahedron-Tetrahedron Overlap
296
// Algorithm, Journal of Graphics Tools, 7(2), 2002. DOI:
297
// 10.1080/10867651.2002.10487557. Source code available at
298
// http://web.archive.org/web/20031130075955/http://www.acm.org/jgt/papers/GanovelliPonchioRocchini02/tet_a_tet.html
300
dolfin_assert(tetrahedron_0.mesh().topology().dim() == 3);
301
dolfin_assert(tetrahedron_1.mesh().topology().dim() == 3);
303
// Get the vertices as points
304
const MeshGeometry& geometry = tetrahedron_0.mesh().geometry();
305
const unsigned int* vertices = tetrahedron_0.entities(0);
306
const MeshGeometry& geometry_q = tetrahedron_1.mesh().geometry();
307
const unsigned int* vertices_q = tetrahedron_1.entities(0);
308
std::vector<Point> V1(4), V2(4);
309
for (std::size_t i = 0; i < 4; ++i)
311
V1[i] = geometry.point(vertices[i]);
312
V2[i] = geometry_q.point(vertices_q[i]);
315
// Get the vectors between V2 and V1[0]
316
std::vector<Point> P_V1(4);
317
for (std::size_t i = 0; i < 4; ++i)
318
P_V1[i] = V2[i]-V1[0];
320
// Data structure for edges of V1 and V2
321
std::vector<Point> e_v1(5), e_v2(5);
322
e_v1[0] = V1[1] - V1[0];
323
e_v1[1] = V1[2] - V1[0];
324
e_v1[2] = V1[3] - V1[0];
325
Point n = e_v1[1].cross(e_v1[0]);
327
// Maybe flip normal. Normal should be outward.
328
if (n.dot(e_v1[2]) > 0)
330
std::vector<int> masks(4);
331
std::vector<std::vector<double> > Coord_1(4, std::vector<double>(4));
332
if (separating_plane_face_A_1(P_V1, n, Coord_1[0], masks[0]))
334
n = e_v1[0].cross(e_v1[2]);
337
if (n.dot(e_v1[1]) > 0)
339
if (separating_plane_face_A_1(P_V1, n, Coord_1[1], masks[1]))
341
if (separating_plane_edge_A(Coord_1, masks, 0, 1))
343
n = e_v1[2].cross(e_v1[1]);
346
if (n.dot(e_v1[0]) > 0)
348
if (separating_plane_face_A_1(P_V1, n, Coord_1[2], masks[2]))
350
if (separating_plane_edge_A(Coord_1, masks, 0, 2))
352
if (separating_plane_edge_A(Coord_1, masks, 1,2))
354
e_v1[4] = V1[3] - V1[1];
355
e_v1[3] = V1[2] - V1[1];
356
n = e_v1[3].cross(e_v1[4]);
358
// Maybe flip normal. Note the < since e_v1[0]=v1-v0.
359
if (n.dot(e_v1[0]) < 0)
361
if (separating_plane_face_A_2(V1, V2, n, Coord_1[3], masks[3]))
363
if (separating_plane_edge_A(Coord_1, masks, 0, 3))
365
if (separating_plane_edge_A(Coord_1, masks, 1, 3))
367
if (separating_plane_edge_A(Coord_1, masks, 2, 3))
369
if ((masks[0] | masks[1] | masks[2] | masks[3] )!= 15)
372
// From now on, if there is a separating plane, it is parallel to a
374
std::vector<Point> P_V2(4);
375
for (std::size_t i = 0; i < 4; ++i)
376
P_V2[i] = V1[i] - V2[0];
377
e_v2[0] = V2[1] - V2[0];
378
e_v2[1] = V2[2] - V2[0];
379
e_v2[2] = V2[3] - V2[0];
380
n = e_v2[1].cross(e_v2[0]);
383
if (n.dot(e_v2[2])>0)
385
if (separating_plane_face_B_1(P_V2, n))
387
n=e_v2[0].cross(e_v2[2]);
390
if (n.dot(e_v2[1]) > 0)
392
if (separating_plane_face_B_1(P_V2, n))
394
n = e_v2[2].cross(e_v2[1]);
397
if (n.dot(e_v2[0]) > 0)
399
if (separating_plane_face_B_1(P_V2, n))
401
e_v2[4] = V2[3] - V2[1];
402
e_v2[3] = V2[2] - V2[1];
403
n = e_v2[3].cross(e_v2[4]);
405
// Maybe flip normal. Note the < since e_v2[0] = V2[1] - V2[0].
406
if (n.dot(e_v2[0]) < 0)
408
if (separating_plane_face_B_2(V1, V2, n))
413
//-----------------------------------------------------------------------------
415
CollisionDetection::collides_edge_edge(const Point& a,
420
const double tol = DOLFIN_EPS_LARGE;
422
// Check if two edges are the same
423
if ((a - c).norm() < tol and (b - d).norm() < tol)
425
if ((a - d).norm() < tol and (b - c).norm() < tol)
428
// Get edges as vectors and compute the normal
429
const Point L1 = b - a;
430
const Point L2 = d - c;
431
const Point n = L1.cross(L2);
433
// Check if L1 and L2 are coplanar
434
const Point ca = c - a;
435
if (std::abs(ca.dot(n)) > tol)
438
// Find orthogonal plane with normal n1
439
const Point n1 = n.cross(L1);
440
const double n1dotL2 = n1.dot(L2);
441
if (std::abs(n1dotL2) < tol)
443
const double t = n1.dot(a - c) / n1dotL2;
444
if (t <= 0 or t >= 1)
447
// Find orthogonal plane with normal n2
448
const Point n2 = n.cross(L2);
449
const double n2dotL1 = n2.dot(L1);
450
if (std::abs(n2dotL1) < tol)
452
const double s = n2.dot(c - a) / n2dotL1;
453
if (s <= 0 or s >= 1)
458
//-----------------------------------------------------------------------------
459
bool CollisionDetection::collides_triangle_point(const Point& p0,
464
// Algorithm from http://www.blackpawn.com/texts/pointinpoly/
465
// See also "Real-Time Collision Detection" by Christer Ericson.
467
// We express AP as a linear combination of the vectors AB and
468
// AC. Point is inside triangle iff AP is a convex combination.
470
// Note: This function may be optimized if only 2D vectors and inner
471
// products need to be computed.
474
const Point v1 = p1 - p0;
475
const Point v2 = p2 - p0;
476
const Point v = point - p0;
478
// Compute entries of linear system
479
const double a11 = v1.dot(v1);
480
const double a12 = v1.dot(v2);
481
const double a22 = v2.dot(v2);
482
const double b1 = v.dot(v1);
483
const double b2 = v.dot(v2);
485
// Solve linear system
486
const double inv_det = 1.0 / (a11*a22 - a12*a12);
487
const double x1 = inv_det*( a22*b1 - a12*b2);
488
const double x2 = inv_det*(-a12*b1 + a11*b2);
490
// Tolerance for numeric test (using vector v1)
491
const double dx = std::abs(v1.x());
492
const double dy = std::abs(v1.y());
493
const double eps = std::max(DOLFIN_EPS_LARGE, DOLFIN_EPS_LARGE*std::max(dx, dy));
495
// Check if point is inside
496
return x1 >= -eps && x2 >= -eps && x1 + x2 <= 1.0 + eps;
498
//-----------------------------------------------------------------------------
500
CollisionDetection::collides_triangle_triangle(const Point& p0,
507
// Algorithm and code from Tomas Moller: A Fast Triangle-Triangle
508
// Intersection Test, Journal of Graphics Tools, 2(2), 1997. Source
509
// code is available at
510
// http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/code/opttritri.txt
512
// First check if the triangles are the same. We need to do this
513
// separately if we do _not_ allow for adjacent edges to be
514
// classified as colliding (see the edge_edge_test).
516
const Point Vmid = (p0 + p1 + p2) / 3.;
517
const Point Umid = (q0 + q1 + q2) / 3.;
518
if ((Vmid-Umid).norm() < DOLFIN_EPS_LARGE)
524
double du0, du1, du2, dv0, dv1, dv2;
526
double isect1[2], isect2[2];
527
double du0du1, du0du2, dv0dv1, dv0dv2;
529
double vp0, vp1, vp2;
530
double up0, up1, up2;
533
// Compute plane equation of triangle(p0,p1,p2)
539
// Plane equation 1: N1.X+d1=0. Put q0,q1,q2 into plane equation 1
540
// to compute signed distances to the plane
545
// Coplanarity robustness check
546
if (std::abs(du0) < DOLFIN_EPS_LARGE)
548
if (std::abs(du1) < DOLFIN_EPS_LARGE)
550
if (std::abs(du2) < DOLFIN_EPS_LARGE)
555
// Same sign on all of them + not equal 0?
556
if (du0du1>0. && du0du2>0.)
559
// Compute plane of triangle (q0,q1,q2)
564
// Plane equation 2: N2.X+d2=0. Put p0,p1,p2 into plane equation 2
570
if (std::abs(dv0) < DOLFIN_EPS_LARGE)
572
if (std::abs(dv1) < DOLFIN_EPS_LARGE)
574
if (std::abs(dv2) < DOLFIN_EPS_LARGE)
579
// Same sign on all of them + not equal 0 ?
580
if (dv0dv1>0. && dv0dv2>0.)
583
// Compute direction of intersection line
586
// Compute and index to the largest component of D
587
max = (double)std::abs(D[0]);
589
bb = (double)std::abs(D[1]);
590
cc = (double)std::abs(D[2]);
596
// This is the simplified projection onto L
605
// Compute interval for triangle 1
606
double a, b, c, x0, x1;
607
if (compute_intervals(vp0, vp1, vp2, dv0, dv1, dv2, dv0dv1, dv0dv2,
609
return coplanar_tri_tri(N1, p0, p1, p2, q0, q1, q2);
611
// Compute interval for triangle 2
612
double d, e, f, y0, y1;
613
if (compute_intervals(up0, up1, up2, du0, du1, du2, du0du1, du0du2,
615
return coplanar_tri_tri(N1, p0, p1, p2, q0, q1, q2);
617
double xx, yy, xxyy, tmp;
623
isect1[0] = tmp+b*x1*yy;
624
isect1[1] = tmp+c*x0*yy;
627
isect2[0] = tmp+e*xx*y1;
628
isect2[1] = tmp+f*xx*y0;
630
if (isect1[0] > isect1[1])
631
std::swap(isect1[0], isect1[1]);
632
if (isect2[0] > isect2[1])
633
std::swap(isect2[0], isect2[1]);
635
if (isect1[1] < isect2[0] ||
636
isect2[1] < isect1[0])
641
//-----------------------------------------------------------------------------
643
CollisionDetection::collides_tetrahedron_point(const Point& p0,
649
// Algorithm from http://www.blackpawn.com/texts/pointinpoly/
650
// See also "Real-Time Collision Detection" by Christer Ericson.
652
// We express AP as a linear combination of the vectors AB, AC and
653
// AD. Point is inside triangle iff AP is a convex combination.
656
const Point v1 = p1 - p0;
657
const Point v2 = p2 - p0;
658
const Point v3 = p3 - p0;
659
const Point v = point - p0;
661
// Compute entries of linear system
662
const double a11 = v1.dot(v1);
663
const double a12 = v1.dot(v2);
664
const double a13 = v1.dot(v3);
665
const double a22 = v2.dot(v2);
666
const double a23 = v2.dot(v3);
667
const double a33 = v3.dot(v3);
668
const double b1 = v.dot(v1);
669
const double b2 = v.dot(v2);
670
const double b3 = v.dot(v3);
672
// Compute subdeterminants
673
const double d11 = a22*a33 - a23*a23;
674
const double d12 = a12*a33 - a23*a13;
675
const double d13 = a12*a23 - a22*a13;
676
const double d22 = a11*a33 - a13*a13;
677
const double d23 = a11*a23 - a12*a13;
678
const double d33 = a11*a22 - a12*a12;
680
// Compute inverse of determinant determinant
681
const double inv_det = 1.0 / (a11*d11 - a12*d12 + a13*d13);
683
// Solve linear system
684
const double x1 = inv_det*( d11*b1 - d12*b2 + d13*b3);
685
const double x2 = inv_det*(-d12*b1 + d22*b2 - d23*b3);
686
const double x3 = inv_det*( d13*b1 - d23*b2 + d33*b3);
688
// Tolerance for numeric test (using vector v1)
689
const double dx = std::abs(v1.x());
690
const double dy = std::abs(v1.y());
691
const double dz = std::abs(v1.z());
692
const double eps = std::max(DOLFIN_EPS_LARGE, DOLFIN_EPS_LARGE*std::max(dx, std::max(dy, dz)));
694
// Check if point is inside cell
695
return x1 >= -eps && x2 >= -eps && x3 >= -eps && x1 + x2 + x3 <= 1.0 + eps;
697
//-----------------------------------------------------------------------------
699
CollisionDetection::collides_tetrahedron_triangle(const Point& p0,
707
// Collision is determined by first if any triangle vertex is inside
708
// the tetrahedron. If not, we continue checking the intersection of
709
// the triangle with the four faces of the tetrahedron.
711
// Triangle vertex in tetrahedron collision
712
if (collides_tetrahedron_point(p0, p1, p2, p3, q0))
714
if (collides_tetrahedron_point(p0, p1, p2, p3, q1))
716
if (collides_tetrahedron_point(p0, p1, p2, p3, q2))
719
// Triangle-triangle collision tests
720
if (collides_triangle_triangle(q0, q1, q2, p1, p2, p3))
722
if (collides_triangle_triangle(q0, q1, q2, p0, p2, p3))
724
if (collides_triangle_triangle(q0, q1, q2, p0, p1, p3))
726
if (collides_triangle_triangle(q0, q1, q2, p0, p1, p2))
731
//-----------------------------------------------------------------------------
732
bool CollisionDetection::edge_edge_test(int i0,
740
// Helper function for triangle triangle collision. Test edge vs
743
// Here we have the option of classifying adjacent edges of two
744
// triangles as colliding by changing > to >= and < to <= below.
746
const double Bx = U0[i0] - U1[i0];
747
const double By = U0[i1] - U1[i1];
748
const double Cx = V0[i0] - U0[i0];
749
const double Cy = V0[i1] - U0[i1];
750
const double f = Ay*Bx - Ax*By;
751
const double d = By*Cx - Bx*Cy;
753
if ((f > 0 && d >= 0 && d <= f) ||
754
(f < 0 && d <= 0 && d >= f))
756
const double e = Ax*Cy - Ay*Cx;
759
// Allow or not allow adjacent edges as colliding:
760
//if (e >= 0 && e <= f) return true;
766
// Allow or not allow adjacent edges as colliding:
767
//if (e <= 0 && e >= f) return true;
774
//-----------------------------------------------------------------------------
775
bool CollisionDetection::edge_against_tri_edges(int i0,
783
// Helper function for triangle triangle collision
784
const double Ax = V1[i0] - V0[i0];
785
const double Ay = V1[i1] - V0[i1];
787
// Test edge U0,U1 against V0,V1
788
if (edge_edge_test(i0, i1, Ax, Ay, V0, U0, U1))
791
// Test edge U1,U2 against V0,V1
792
if (edge_edge_test(i0, i1, Ax, Ay, V0, U1, U2))
795
// Test edge U2,U1 against V0,V1
796
if (edge_edge_test(i0, i1, Ax, Ay, V0, U2, U0))
801
//-----------------------------------------------------------------------------
802
bool CollisionDetection::point_in_tri(int i0,
809
// Helper function for triangle triangle collision
810
// Is T1 completly inside T2?
811
// Check if V0 is inside tri(U0,U1,U2)
812
double a = U1[i1] - U0[i1];
813
double b = -(U1[i0] - U0[i0]);
814
double c = -a*U0[i0] - b*U0[i1];
815
const double d0 = a*V0[i0] + b*V0[i1] + c;
818
b = -(U2[i0] - U1[i0]);
819
c = -a*U1[i0] - b*U1[i1];
820
const double d1 = a*V0[i0] + b*V0[i1] + c;
823
b = -(U0[i0] - U2[i0]);
824
c = -a*U2[i0] - b*U2[i1];
825
const double d2 = a*V0[i0] + b*V0[i1] + c;
835
//-----------------------------------------------------------------------------
836
bool CollisionDetection::coplanar_tri_tri(const Point& N,
844
// Helper function for triangle triangle collision
849
// First project onto an axis-aligned plane, that maximizes the area
850
// of the triangles, compute indices: i0,i1.
851
A[0] = std::abs(N[0]);
852
A[1] = std::abs(N[1]);
853
A[2] = std::abs(N[2]);
859
i0 = 1; // A[0] is greatest
864
i0 = 0; // A[2] is greatest
872
i0 = 0; // A[2] is greatest
877
i0 = 0; // A[1] is greatest
882
// Test all edges of triangle 1 against the edges of triangle 2
883
if (edge_against_tri_edges(i0, i1, V0, V1, U0, U1, U2))
885
if (edge_against_tri_edges(i0, i1, V1, V2, U0, U1, U2))
887
if (edge_against_tri_edges(i0, i1, V2, V0, U0, U1, U2))
890
// Finally, test if tri1 is totally contained in tri2 or vice versa
891
if (point_in_tri(i0, i1, V0, U0, U1, U2))
893
if (point_in_tri(i0, i1, U0, V0, V1, V2))
898
//-----------------------------------------------------------------------------
899
bool CollisionDetection::compute_intervals(double VV0,
913
// Helper function for triangle triangle collision
917
// Here we know that D0D2<=0.0, that is D0, D1 are on the same
918
// side, D2 on the other or on the plane
927
// Here we know that d0d1<=0.0
934
else if (D1*D2 > 0. || D0 != 0.)
936
// Here we know that d0d1<=0.0 or that D0!=0.0
960
// Go to coplanar test
966
//-----------------------------------------------------------------------------
968
CollisionDetection::separating_plane_face_A_1(const std::vector<Point>& pv1,
970
std::vector<double>& coord,
973
// Helper function for tetrahedron-tetrahedron collision test:
974
// checks if plane pv1 is a separating plane. Stores local
975
// coordinates and the mask bit mask_edges.
978
const int shifts[4] = {1, 2, 4, 8};
980
for (std::size_t i = 0; i < 4; ++i)
982
coord[i] = pv1[i].dot(n);
984
mask_edges |= shifts[i];
987
return (mask_edges == 15);
989
//-----------------------------------------------------------------------------
991
CollisionDetection::separating_plane_face_A_2(const std::vector<Point>& V1,
992
const std::vector<Point>& V2,
994
std::vector<double>& coord,
997
// Helper function for tetrahedron-tetrahedron collision test:
998
// checks if plane v1,v2 is a separating plane. Stores local
999
// coordinates and the mask bit mask_edges.
1002
const int shifts[4] = {1, 2, 4, 8};
1004
for (std::size_t i = 0; i < 4; ++i)
1006
coord[i] = (V2[i] - V1[1]).dot(n);
1008
mask_edges |= shifts[i];
1011
return (mask_edges == 15);
1013
//-----------------------------------------------------------------------------
1015
CollisionDetection::separating_plane_edge_A
1016
(const std::vector<std::vector<double> >& coord_1,
1017
const std::vector<int>& masks,
1021
// Helper function for tetrahedron-tetrahedron collision: checks if
1022
// edge is in the plane separating faces f0 and f1.
1024
const std::vector<double>& coord_f0 = coord_1[f0];
1025
const std::vector<double>& coord_f1 = coord_1[f1];
1027
int maskf0 = masks[f0];
1028
int maskf1 = masks[f1];
1030
if ((maskf0 | maskf1) != 15) // if there is a vertex of b
1031
return false; // included in (-,-) return false
1033
maskf0 &= (maskf0 ^ maskf1); // exclude the vertices in (+,+)
1034
maskf1 &= (maskf0 ^ maskf1);
1037
if ((maskf0 & 1) && // the vertex 0 of b is in (-,+)
1038
(maskf1 & 2)) // the vertex 1 of b is in (+,-)
1039
if ((coord_f0[1]*coord_f1[0] - coord_f0[0]*coord_f1[1]) > 0)
1040
// the edge of b (0,1) intersect (-,-) (see the paper)
1045
if ((coord_f0[1]*coord_f1[0] - coord_f0[0]*coord_f1[1]) < 0)
1051
if ((coord_f0[2]*coord_f1[0] - coord_f0[0]*coord_f1[2]) > 0)
1056
if ((coord_f0[2]*coord_f1[0] - coord_f0[0]*coord_f1[2]) < 0)
1062
if ((coord_f0[3]*coord_f1[0] - coord_f0[0]*coord_f1[3]) > 0)
1067
if ((coord_f0[3]*coord_f1[0] - coord_f0[0]*coord_f1[3]) < 0)
1073
if ((coord_f0[2]*coord_f1[1] - coord_f0[1]*coord_f1[2]) > 0)
1078
if ((coord_f0[2]*coord_f1[1] - coord_f0[1]*coord_f1[2]) < 0)
1084
if ((coord_f0[3]*coord_f1[1] - coord_f0[1]*coord_f1[3]) > 0)
1089
if ((coord_f0[3]*coord_f1[1] - coord_f0[1]*coord_f1[3]) < 0)
1095
if ((coord_f0[3]*coord_f1[2] - coord_f0[2]*coord_f1[3]) > 0)
1100
if ((coord_f0[3]*coord_f1[2] - coord_f0[2]*coord_f1[3]) < 0)
1103
// Now there exists a separating plane supported by the edge shared
1107
//-----------------------------------------------------------------------------