vgl_triangle_3d.cxx
Go to the documentation of this file.
1 #include <limits>
2 #include "vgl_triangle_3d.h"
3 //:
4 // \file
5 // \brief Some helpful functions when working with triangles
6 // \author Kieran O'Mahony
7 // \date 21 June 2007
8 
9 #include <vgl/vgl_distance.h>
10 #include <vgl/vgl_intersection.h>
12 #include <vgl/vgl_plane_3d.h>
13 #include <vgl/vgl_point_3d.h>
14 #include <vgl/vgl_vector_3d.h>
15 #include <vgl/vgl_closest_point.h>
16 #ifdef _MSC_VER
17 # include <vcl_msvc_warnings.h>
18 #endif
19 #include <cassert>
20 
21 // Define a file-scope vgl_nan constant
22 static const double vgl_nan = std::sqrt(-1.0);
23 static const double sqrteps = std::sqrt(std::numeric_limits<double>::epsilon());
24 static const double pi = 3.14159265358979323846;
25 
26 namespace
27 {
28  //: Create plane through three points. Ignore degeneracy.
29  vgl_plane_3d<double> create_plane_and_ignore_degenerate(const vgl_point_3d<double>& p1,
30  const vgl_point_3d<double>& p2,
31  const vgl_point_3d<double>& p3)
32  {
34  auto *a = reinterpret_cast<double *>(&plane);
35 
36  a[0] = p2.y()*p3.z() - p2.z()*p3.y()
37  + p3.y()*p1.z() - p3.z()*p1.y()
38  + p1.y()*p2.z() - p1.z()*p2.y();
39 
40  a[1] = p2.z()*p3.x() - p2.x()*p3.z()
41  + p3.z()*p1.x() - p3.x()*p1.z()
42  + p1.z()*p2.x() - p1.x()*p2.z();
43 
44  a[2] = p2.x()*p3.y() - p2.y()*p3.x()
45  + p3.x()*p1.y() - p3.y()*p1.x()
46  + p1.x()*p2.y() - p1.y()*p2.x();
47 
48  a[3] = p1.x()*(p2.z()*p3.y() - p2.y()*p3.z())
49  + p2.x()*(p3.z()*p1.y() - p3.y()*p1.z())
50  + p3.x()*(p1.z()*p2.y() - p1.y()*p2.z());
51  return plane;
52  }
53 }
54 
55 //=======================================================================
56 //: Check for coincident edges of triangles a and b
57 // \return a vector of the coincident edges
58 std::vector<std::pair<unsigned,unsigned> > vgl_triangle_3d_coincident_edges(
59  const vgl_point_3d<double>& a_p1,
60  const vgl_point_3d<double>& a_p2,
61  const vgl_point_3d<double>& a_p3,
62  const vgl_point_3d<double>& b_p1,
63  const vgl_point_3d<double>& b_p2,
64  const vgl_point_3d<double>& b_p3)
65 {
66  std::vector<std::pair<unsigned,unsigned> > coinc_edges;
67 
68  //create some convenient arrays for looping
69  vgl_point_3d<double> a[3] = {a_p1, a_p2, a_p3};
70  vgl_point_3d<double> b[3] = {b_p1, b_p2, b_p3};
71  std::pair<unsigned,unsigned> e[3] = { std::make_pair(0,1),
72  std::make_pair(1,2),
73  std::make_pair(2,0) };
74 
75  // Test each edge j of triangle a against each edge i of triangle b.
76  for (unsigned j = 0; j < 3; ++j)
77  {
78  for (unsigned i = 0; i < 3; ++i)
79  {
80  //check if one edge is entirely contained within the other and vice versa
81 
82  double e1_len = length(a[e[j].first] - a[e[j].second]);
83  double b1_dist = length(a[e[j].first] - b[e[i].first]) +
84  length(a[e[j].second] - b[e[i].first]);
85  double b2_dist = length(a[e[j].first] - b[e[i].second]) +
86  length(a[e[j].second] - b[e[i].second]);
87 
88  double e2_len = length(b[e[i].first] - b[e[i].second]);
89  double a1_dist = length(b[e[i].first] - a[e[j].first]) +
90  length(b[e[i].second] - a[e[j].first]);
91  double a2_dist = length(b[e[i].first] - a[e[j].second]) +
92  length(b[e[i].second] - a[e[j].second]);
93 
94  if ((std::fabs(e1_len - b1_dist) < sqrteps &&
95  std::fabs(e1_len - b2_dist) < sqrteps) ||
96  (std::fabs(e2_len - a1_dist) < sqrteps &&
97  std::fabs(e2_len - a2_dist) < sqrteps))
98  {
99  coinc_edges.emplace_back(j,i);
100  break;
101  }
102  }
103  }
104 
105  return coinc_edges;
106 }
107 
108 
109 //=======================================================================
110 //: Check if the given point is inside the triangle
111 // The triangle is represented by its vertices \a p1, \a p2, \a p3
112 // \return true if point is inside
113 // \param coplanar_tolerance used to dismiss points because they are
114 // outside the plane. This doesn't widen the triangle, just thickens it.
116  const vgl_point_3d<double>& p1,
117  const vgl_point_3d<double>& p2,
118  const vgl_point_3d<double>& p3,
119  double coplanar_tolerance)
120 {
121  // firstly perform some degeneracy checks
122  if (collinear(p1,p2,p3))
123  { //the triangle is degenerate - its vertices are collinear
124 
125  if (p1==p2&&p2==p3&&p1==p3)
126  { //all its vertices are the same
127  return i_pnt == p1;
128  }
129 
130  return vgl_line_segment_3d<double>(p1,p2).contains(i_pnt) ||
131  vgl_line_segment_3d<double>(p2,p3).contains(i_pnt) ||
133  }
134 
135  // Project to 2d plane, to avoid a degenerate result get
136  // the plane normal and identify the largest (abs) x,y or z component
137  vgl_plane_3d<double> plane =
138  create_plane_and_ignore_degenerate(p1, p2, p3);
139 
140  // use Badouel's algorithm (a barycentric method)
141  // based on the code & paper found at http://jgt.akpeters.com/papers/MollerTrumbore97/
142 
143  //the point needs to be in the triangles plane
144  if (vgl_distance(plane,i_pnt) > coplanar_tolerance)
145  return false;
146 
147  vgl_vector_3d<double> norm = plane.normal();
148  norm.set(std::fabs(norm.x()),std::fabs(norm.y()),std::fabs(norm.z()));
149 
150  unsigned i1 = 0; // Default is z.
151  unsigned i2 = 1;
152  if (norm.y()>=norm.x() && norm.y()>=norm.z())
153  {
154  i2 = 2; // Max component is y
155  }
156  else if (norm.x()>=norm.y() && norm.x()>=norm.z())
157  {
158  i1 = 2; // Max component is x
159  }
160 
161  double point[3] = {i_pnt.x(), i_pnt.y(), i_pnt.z()};
162  double vert0[3] = {p1.x(), p1.y(), p1.z()};
163  double vert1[3] = {p2.x(), p2.y(), p2.z()};
164  double vert2[3] = {p3.x(), p3.y(), p3.z()};
165 
166  double beta = 0.0;
167  double alpha = 0.0;
168 
169  //compute the barycentric vectors....& ignore numerical roundoff errors
170  double u0 = (std::fabs(point[i1]) < sqrteps ? 0 : point[i1]) - (std::fabs(vert0[i1]) < sqrteps ? 0 : vert0[i1]);
171  double v0 = (std::fabs(point[i2]) < sqrteps ? 0 : point[i2]) - (std::fabs(vert0[i2]) < sqrteps ? 0 : vert0[i2]);
172 
173  double u1 = (std::fabs(vert1[i1]) < sqrteps ? 0 : vert1[i1]) - (std::fabs(vert0[i1]) < sqrteps ? 0 : vert0[i1]);
174  double u2 = (std::fabs(vert2[i1]) < sqrteps ? 0 : vert2[i1]) - (std::fabs(vert0[i1]) < sqrteps ? 0 : vert0[i1]);
175  double v1 = (std::fabs(vert1[i2]) < sqrteps ? 0 : vert1[i2]) - (std::fabs(vert0[i2]) < sqrteps ? 0 : vert0[i2]);
176  double v2 = (std::fabs(vert2[i2]) < sqrteps ? 0 : vert2[i2]) - (std::fabs(vert0[i2]) < sqrteps ? 0 : vert0[i2]);
177 
178  // calculate and compare barycentric coordinates
179  if (u1 == 0)
180  { // uncommon case
181  beta = u0 / u2;
182  if (beta < -sqrteps/*0*/ || beta > 1+sqrteps)
183  return false;
184  alpha = (v0 - beta * v2) / v1;
185  }
186  else
187  { // common case
188  beta = (v0 * u1 - u0 * v1) / (v2 * u1 - u2 * v1);
189  if (beta < -sqrteps/*0*/ || beta > 1+sqrteps)
190  return false;
191  alpha = (u0 - beta * u2) / u1;
192  }
193 
194  return alpha >= -sqrteps /*0*/
195  && alpha + beta <= 1.0+sqrteps;
196 }
197 
198 
199 //=======================================================================
200 //: Check if the given point is inside the triangle
201 // The triangle is represented by its vertices \a p1, \a p2, \a p3
202 // \return true if point is inside
204  const vgl_point_3d<double>& p1,
205  const vgl_point_3d<double>& p2,
206  const vgl_point_3d<double>& p3)
207 {
208  return vgl_triangle_3d_test_inside(i_pnt, p1, p2, p3, sqrteps);
209 }
210 
211 
212 //=======================================================================
213 //: Check if point \a i_pnt is inside the triangle
214 // The triangle is represented by its vertices \a p1, \a p2, \a p3
215 // \return true if point is inside
216 //
217 // \note this method uses the less efficient 'angles' method which requires 3 calls to acos()
219  const vgl_point_3d<double>& p1,
220  const vgl_point_3d<double>& p2,
221  const vgl_point_3d<double>& p3 )
222 {
223  vgl_vector_3d<double> vec1 = normalized(i_pnt - p1);
224  vgl_vector_3d<double> vec2 = normalized(i_pnt - p2);
225  vgl_vector_3d<double> vec3 = normalized(i_pnt - p3);
226 
227  double int_ang = std::acos(dot_product(vec1,vec2)) + std::acos(dot_product(vec2,vec3)) + std::acos(dot_product(vec3,vec1));
228  double test_val = std::fabs(int_ang-(2*pi));
229 
230  return test_val < sqrteps;
231 }
232 
233 //! Are D and E on opposite sides of the plane that touches A, B, C
234 // \returns Skew if on same side, None if not, and Coplanar if D is on
235 // plane ABC
236 static vgl_triangle_3d_intersection_t same_side(
237  const vgl_point_3d<double>& A,
238  const vgl_point_3d<double>& B,
239  const vgl_point_3d<double>& C,
240  const vgl_point_3d<double>& D,
241  const vgl_point_3d<double>& E)
242 {
243  vgl_vector_3d<double> b = B - A;
244  vgl_vector_3d<double> c = C - A;
245 
247 
248  vgl_vector_3d<double> d = D - A;
249  double d_dot = dot_product(d, n);
250  vgl_vector_3d<double> e = E - A;
251  double e_dot = dot_product(e, n);
252 
253  if (std::abs(d_dot) < std::sqrt(
254  std::numeric_limits<double>::epsilon()) *
255  std::max(1.0e-100, std::max(std::sqrt(A.x()*A.x()+A.y()*A.y()+A.z()*A.z()),
256  std::sqrt(D.x()*D.x()+D.y()*D.y()+D.z()*D.z()) ) ) )
257  {
258  return Coplanar;
259  }
260 
261  if (d_dot * e_dot >= 0)
262  return Skew;
263  else
264  return None;
265 }
266 
267 
268 //=======================================================================
269 //: Compute the intersection point between the line segment and triangle
270 // The triangle is represented by its vertices \a p1, \a p2, \a p3
271 // \return intersection type
273  const vgl_line_segment_3d<double>& line,
274  const vgl_point_3d<double>& p1,
275  const vgl_point_3d<double>& p2,
276  const vgl_point_3d<double>& p3,
277  vgl_point_3d<double>& i_pnt,
278  bool ignore_coplanar/*=false*/)
279 {
280  vgl_point_3d<double> line_p1 = line.point1();
281  vgl_point_3d<double> line_p2 = line.point2();
282 
283  // perform some degeneracy checks on the line and triangle
284  if (line_p1 == line_p2)
285  { //the line is degenerate - it has zero length
286  if (!ignore_coplanar && vgl_triangle_3d_test_inside(line_p1,p1,p2,p3))
287  return Coplanar;
288 
289  return None;
290  }
291 
292  if (collinear(p1,p2,p3))
293  { //the triangle is degenerate - it's points are collinear
294  if (p1==p2&&p2==p3&&p1==p3)
295  { //all its vertices are the same
296  return !ignore_coplanar && line.contains(p1) ? Coplanar : None;
297  }
298 
299  vgl_line_3d_2_points<double> i_line(line_p1,line_p2);
300  if ( !ignore_coplanar && (
301  ( p1!=p2 && concurrent(vgl_line_3d_2_points<double>(p1,p2), i_line) &&
302  vgl_intersection(line,vgl_line_segment_3d<double>(p1,p2),i_pnt) ) ||
303  ( p2!=p3 && concurrent(vgl_line_3d_2_points<double>(p2,p3), i_line) &&
304  vgl_intersection(line,vgl_line_segment_3d<double>(p2,p3),i_pnt) ) ||
305  ( p1!=p3 && concurrent(vgl_line_3d_2_points<double>(p1,p3), i_line) &&
306  vgl_intersection(line,vgl_line_segment_3d<double>(p1,p3),i_pnt) ) ) )
307  {
308  return Coplanar;
309  }
310 
311  return None;
312  }
313 
314  vgl_triangle_3d_intersection_t rv1 = same_side(line.point1(), p1, p2, p3, line.point2());
315  if (rv1 == None) return None;
316 
317  vgl_triangle_3d_intersection_t rv2 = same_side(line.point1(), p2, p3, p1, line.point2());
318  if (rv2 == None) return None;
319 
320  vgl_triangle_3d_intersection_t rv3 = same_side(line.point1(), p3, p1, p2, line.point2());
321  if (rv3 == None) return None;
322 
323  if (rv1 == Coplanar || rv2 == Coplanar || rv3==Coplanar)
324  {
325  if (ignore_coplanar)
326  return None;
327  // coplanar line - uncommon case
328 
329  // check each triangle edge.
330  // behaviour is to return the first found intersection point
331  vgl_line_3d_2_points<double> i_line(line_p1,line_p2);
332  vgl_line_segment_3d<double> edge1(p1,p2);
333 
334  vgl_point_3d<double> test_pt;
335  if (concurrent(vgl_line_3d_2_points<double>(p1,p2),i_line) &&
336  vgl_intersection(edge1,line,test_pt))
337  {
338  i_pnt = test_pt;
339  return Coplanar;
340  }
341  vgl_line_segment_3d<double> edge2(p1,p3);
342  if (concurrent(vgl_line_3d_2_points<double>(p1,p3),i_line) &&
343  vgl_intersection(edge2,line,test_pt))
344  {
345  i_pnt = test_pt;
346  return Coplanar;
347  }
348  vgl_line_segment_3d<double> edge3(p2,p3);
349  if (concurrent(vgl_line_3d_2_points<double>(p2,p3),i_line) &&
350  vgl_intersection(edge3,line,test_pt))
351  {
352  i_pnt = test_pt;
353  return Coplanar;
354  }
355 
356  //special case of line completely contained within the triangle
357  if (vgl_triangle_3d_test_inside(line_p2, p1, p2, p3))
358  {
359  i_pnt.set(vgl_nan, vgl_nan, vgl_nan);
360  return Coplanar;
361  }
362 
363  return None;
364  }
365 
366  if (same_side(p1, p2, p3, line_p1, line_p2) == Skew)
367  return None;
368 
369  i_pnt = vgl_intersection(vgl_line_3d_2_points<double>(line_p1, line_p2),
370  vgl_plane_3d<double>(p1, p2, p3) );
371  return Skew;
372 }
373 
374 
375 #ifndef UINT_MAX
376 #define UINT_MAX 0xffffffffU
377 #endif
378 namespace
379 {
380  static const unsigned calc_edge_index_lookup[8] = {UINT_MAX, 0, 2, 0, UINT_MAX, 1, 2, 1};
381  //: Given the [0,2] index of two vertices, in either order, return the edge index [0,2]
382  // E.g. between vertices 2 and 0 is edge 2.
383  // Use precalculated list lookup, probably fastest.
384  inline unsigned calc_edge_index(unsigned v, unsigned w)
385  {
386  unsigned lookup = v*3u + w;
387  assert (lookup < 8);
388  unsigned edge = calc_edge_index_lookup[lookup];
389  assert (edge < 3);
390  return edge;
391  }
392 }
393 //=======================================================================
394 //: Compute the intersection line of the given triangles
395 // \see vgl_triangle_3d_triangle_intersection()
396 // \note an intersection line is not computed for a coplanar intersection
397 // \retval i_line_point1_edge A number [0-5] indicating which edge of the two triangles
398 // point1 of i_line lies on. 0 indicates [a_p1,a_p2], 1 - [a_p2,a_p3], 2 - [a_p3,a_p1],
399 // 3 - [b_p1,b_p2], 4 - [b_p2,b_p3], 5 - [b_p3,b_p1]
400 // \retval i_line_point2_edge. As i_line_point1_edge, but for the other end of the intersection.
401 // \note if i_line_point1_edge==i_line_point2_edge, this indicates that due to coplanarity, or
402 // some other corner case, there were more than two edges involved in the intersection
403 // boundaries. The returned edge is one of those edges.
405  const vgl_point_3d<double>& a_p1,
406  const vgl_point_3d<double>& a_p2,
407  const vgl_point_3d<double>& a_p3,
408  const vgl_point_3d<double>& b_p1,
409  const vgl_point_3d<double>& b_p2,
410  const vgl_point_3d<double>& b_p3,
412  unsigned &i_line_point1_edge,
413  unsigned &i_line_point2_edge
414  )
415 {
416  // triangle intersection algorithm based on code & paper
417  // found at http://jgt.akpeters.com/papers/Moller97/
418 
419  //sanity check for degenerate triangles
420  if (collinear(a_p1,a_p2,a_p3))
421  {
422  if (a_p1 == a_p2 && a_p2==a_p3) // if it has degenerated to a single point
423  {
424  if (vgl_triangle_3d_test_inside(a_p1,b_p1,b_p2,b_p3))
425  {
426  i_line_point1_edge = i_line_point2_edge = 0;
427  i_line.set(a_p1,a_p1);
428  return Coplanar;
429  }
430  return None;
431  }
432 
434  vgl_point_3d<double> i_pnt;
435  unsigned tmp_iline_edges[2];
436  unsigned n_tmp_iline_edges = 0;
437  if ( a_p1 != a_p2 && (ret = vgl_triangle_3d_line_intersection(vgl_line_segment_3d<double>(a_p1,a_p2), b_p1,b_p2,b_p3,i_pnt)) != None )
438  {// half-degenerate tri_b behaves as line. Find line intersection
439  i_line.set(i_pnt,i_pnt);
440  if (ret == Coplanar)
441  {
442  i_line_point1_edge = i_line_point2_edge = 0;
443  return ret;
444  }
445  tmp_iline_edges[0] = 0;
446  n_tmp_iline_edges = 1;
447  }
448  if ( a_p2 != a_p3 && (ret = vgl_triangle_3d_line_intersection(vgl_line_segment_3d<double>(a_p2,a_p3), b_p1,b_p2,b_p3,i_pnt)) != None )
449  {// half-degenerate tri_b behaves as line. Find line intersection
450  i_line.set(i_pnt,i_pnt);
451  if (ret == Coplanar)
452  {
453  i_line_point1_edge = i_line_point2_edge = 1;
454  return ret;
455  }
456  tmp_iline_edges[n_tmp_iline_edges] = 1;
457  n_tmp_iline_edges++;
458  }
459  if ( a_p1 != a_p3 && (ret = vgl_triangle_3d_line_intersection(vgl_line_segment_3d<double>(a_p1,a_p3), b_p1,b_p2,b_p3,i_pnt)) != None )
460  {// half-degenerate tri_b behaves as line. Find line intersection
461  i_line.set(i_pnt,i_pnt);
462  if (ret == Coplanar)
463  {
464  i_line_point1_edge = i_line_point2_edge = 2;
465  return ret;
466  }
467  if (n_tmp_iline_edges >= 2)
468  { // All edges intersect - return repeated edge to indicate problem
469  i_line_point1_edge = i_line_point2_edge = 0;
470  return ret;
471  }
472  tmp_iline_edges[n_tmp_iline_edges] = 2;
473  n_tmp_iline_edges++;
474  }
475  if (!n_tmp_iline_edges) return None; // Found no edges intersecting with triangle
476  if (n_tmp_iline_edges == 1) // Found one edge intersecting with triangle
477  {
478  i_line_point1_edge = i_line_point2_edge = tmp_iline_edges[0];
479  return Skew;
480  }
481  // Found two edges intersecting with triangle
482  i_line_point1_edge = tmp_iline_edges[0];
483  i_line_point2_edge = tmp_iline_edges[1];
484  return Skew;
485  }
486  if (collinear(b_p1,b_p2,b_p3))
487  {
488  if (b_p1 == b_p2 && b_p2==b_p3 && b_p1 == b_p3)
489  {
490  if (vgl_triangle_3d_test_inside(b_p1,a_p1,a_p2,a_p3))
491  {
492  i_line_point1_edge = i_line_point2_edge = 3;
493  i_line.set(b_p1,b_p1);
494  return Coplanar;
495  }
496  return None;
497  }
498 
500  vgl_point_3d<double> i_pnt;
501  unsigned tmp_iline_edges[2];
502  unsigned n_tmp_iline_edges = 0;
503  if (b_p1 != b_p2 && (ret = vgl_triangle_3d_line_intersection(vgl_line_segment_3d<double>(b_p1,b_p2), a_p1,a_p2,a_p3,i_pnt)) != None )
504  {// half-degenerate tri_b behaves as line. Find line intersection
505  i_line.set(i_pnt,i_pnt);
506  if (ret == Coplanar)
507  {
508  i_line_point1_edge = i_line_point2_edge = 3;
509  return ret;
510  }
511  tmp_iline_edges[0] = 3;
512  n_tmp_iline_edges = 1;
513  }
514  if ( b_p2 != b_p3 && (ret = vgl_triangle_3d_line_intersection(vgl_line_segment_3d<double>(b_p2,b_p3), a_p1,a_p2,a_p3,i_pnt)) != None )
515  {// half-degenerate tri_b behaves as line. Find line intersection
516  i_line.set(i_pnt,i_pnt);
517  if (ret == Coplanar)
518  {
519  i_line_point1_edge = i_line_point2_edge = 4;
520  return ret;
521  }
522  tmp_iline_edges[n_tmp_iline_edges] = 4;
523  n_tmp_iline_edges++;
524  }
525  if ( b_p1 != b_p3 && (ret = vgl_triangle_3d_line_intersection(vgl_line_segment_3d<double>(b_p1,b_p3), a_p1,a_p2,a_p3,i_pnt)) != None )
526  {// half-degenerate tri_b behaves as line. Find line intersection
527  i_line.set(i_pnt,i_pnt);
528  if (ret == Coplanar)
529  {
530  i_line_point1_edge = i_line_point2_edge = 5;
531  return ret;
532  }
533  if (n_tmp_iline_edges >= 2)
534  { // All edges intersect - return repeated edge to indicate problem
535  i_line_point1_edge = i_line_point2_edge = 3;
536  return ret;
537  }
538  tmp_iline_edges[n_tmp_iline_edges] = 5;
539  n_tmp_iline_edges++;
540  }
541  if (!n_tmp_iline_edges) return None; // Found no edges intersecting with triangle
542  if (n_tmp_iline_edges == 1) // Found one edge intersecting with triangle
543  {
544  i_line_point1_edge = i_line_point2_edge = tmp_iline_edges[0];
545  return Skew;
546  }
547  // Found two edges intersecting with triangle
548  i_line_point1_edge = tmp_iline_edges[0];
549  i_line_point2_edge = tmp_iline_edges[1];
550  return Skew;
551  }
552 
553  //computing intersection of triangles a and b
554 
555  vgl_vector_3d<double> edge1,edge2;
556  vgl_vector_3d<double> a_norm, b_norm, int_line;
557  //vgl_vector_3d<double> int_line;
558  double a_d, b_d;
559  double d_b[3], d_a[3]; // distance of corner [1,2,3] of tri b to plane of tri a, same for tri_a
560  double d_b1d_b2, d_b1d_b3, d_a1d_a2, d_a1d_a3;
561 
562  double p_a[3];
563  double p_b[3];
564  bool coplanar = false;
565 
566  double TRI_TRI_EPS = 1000000*std::numeric_limits<double>::epsilon();
567 
568  //Firstly check if each triangle intersects
569  // the plane of the other
570 
571  //construct plane equation of triangle a
572  edge1 = a_p2 - a_p1;
573  edge2 = a_p3 - a_p1;
574 
575  a_norm = normalized(cross_product(edge1, edge2));
576  a_d = -( a_norm.x()*a_p1.x() + a_norm.y()*a_p1.y() +a_norm.z()*a_p1.z() );
577  //vgl_plane_3d<double> a_plane(a_p1,a_p2,a_p3);
578 
579  // get signed distance of triangle b to triangle a's plane
580  d_b[0] = ( a_norm.x()*b_p1.x() + a_norm.y()*b_p1.y() + a_norm.z()*b_p1.z() ) + a_d;
581  d_b[1] = ( a_norm.x()*b_p2.x() + a_norm.y()*b_p2.y() + a_norm.z()*b_p2.z() ) + a_d;
582  d_b[2] = ( a_norm.x()*b_p3.x() + a_norm.y()*b_p3.y() + a_norm.z()*b_p3.z() ) + a_d;
583 #if 0
584  d_b[0] = (a_plane.nx()*b_p1.x() + a_plane.ny()*b_p1.y() + a_plane.nz()*b_p1.z() ) + a_plane.d();
585  d_b[1] = (a_plane.nx()*b_p2.x() + a_plane.ny()*b_p2.y() + a_plane.nz()*b_p2.z() ) + a_plane.d();
586  d_b[2] = (a_plane.nx()*b_p3.x() + a_plane.ny()*b_p3.y() + a_plane.nz()*b_p3.z() ) + a_plane.d();
587 #endif // 0
588 
589  // coplanarity robustness check
590  if (std::fabs(d_b[0]) < TRI_TRI_EPS) d_b[0] = 0.0;
591  if (std::fabs(d_b[1]) < TRI_TRI_EPS) d_b[1] = 0.0;
592  if (std::fabs(d_b[2]) < TRI_TRI_EPS) d_b[2] = 0.0;
593 
594  d_b1d_b2 = d_b[0]*d_b[1];
595  d_b1d_b3 = d_b[0]*d_b[2];
596 
597  // all distances same sign => no intersection
598  if (d_b1d_b2 > 0 && d_b1d_b3 > 0)
599  {
600  return None;
601  }
602 
603  //construct plane equation of triangle b
604  edge1 = b_p2 - b_p1;
605  edge2 = b_p3 - b_p1;
606 
607  b_norm = normalized(cross_product(edge1,edge2));
608  b_d = -( b_norm.x()*b_p1.x() + b_norm.y()*b_p1.y() + b_norm.z()*b_p1.z() );
609  //vgl_plane_3d<double> b_plane(b_p1,b_p2,b_p3);
610 
611  // get signed distance of triangle a to triangle b's plane
612  d_a[0] = ( b_norm.x()*a_p1.x() + b_norm.y()*a_p1.y() + b_norm.z()*a_p1.z() ) + b_d;
613  d_a[1] = ( b_norm.x()*a_p2.x() + b_norm.y()*a_p2.y() + b_norm.z()*a_p2.z() ) + b_d;
614  d_a[2] = ( b_norm.x()*a_p3.x() + b_norm.y()*a_p3.y() + b_norm.z()*a_p3.z() ) + b_d;
615 #if 0
616  d_a[0] = (b_plane.nx()*a_p1.x() + b_plane.ny()*a_p1.y() + b_plane.nz()*a_p1.z() ) + b_plane.d();
617  d_a[1] = (b_plane.nx()*a_p2.x() + b_plane.ny()*a_p2.y() + b_plane.nz()*a_p2.z() ) + b_plane.d();
618  d_a[2] = (b_plane.nx()*a_p3.x() + b_plane.ny()*a_p3.y() + b_plane.nz()*a_p3.z() ) + b_plane.d();
619 #endif // 0
620 
621  // coplanarity robustness check
622  if (std::fabs(d_a[0]) < TRI_TRI_EPS) d_a[0] = 0.0;
623  if (std::fabs(d_a[1]) < TRI_TRI_EPS) d_a[1] = 0.0;
624  if (std::fabs(d_a[2]) < TRI_TRI_EPS) d_a[2] = 0.0;
625 
626  d_a1d_a2 = d_a[0]*d_a[1];
627  d_a1d_a3 = d_a[0]*d_a[2];
628 
629  // all distances same sign => no intersection
630  if (d_a1d_a2 > 0 && d_a1d_a3 > 0)
631  {
632  return None;
633  }
634 
635  // Now we know triangles contain
636  // the line of their planes intersection.
637  // So...compute each triangles interval of the intersection
638  // line and determine if they overlap i.e. if the triangles intersect
639 
640  // compute direction of intersection line
641  int_line = cross_product(a_norm,b_norm);
642  //int_line = cross_product(a_plane.normal(),b_plane.normal());
643 
644  // largest component of int_line?
645  // to get a simplified 2D projection
646  int_line.set(std::fabs(int_line.x()),std::fabs(int_line.y()),std::fabs(int_line.z()));
647 
648  if (int_line.y()>=int_line.x() && int_line.y()>=int_line.z())
649  { // Max component is y
650  p_a[0] = a_p1.y();
651  p_a[1] = a_p2.y();
652  p_a[2] = a_p3.y();
653 
654  p_b[0] = b_p1.y();
655  p_b[1] = b_p2.y();
656  p_b[2] = b_p3.y();
657  }
658  else if (int_line.x()>=int_line.y() && int_line.x()>=int_line.z())
659  { // Max component is x
660  p_a[0] = a_p1.x();
661  p_a[1] = a_p2.x();
662  p_a[2] = a_p3.x();
663 
664  p_b[0] = b_p1.x();
665  p_b[1] = b_p2.x();
666  p_b[2] = b_p3.x();
667  }
668  else { // Max component is z
669  p_a[0] = a_p1.z();
670  p_a[1] = a_p2.z();
671  p_a[2] = a_p3.z();
672 
673  p_b[0] = b_p1.z();
674  p_b[1] = b_p2.z();
675  p_b[2] = b_p3.z();
676  }
677 
678  int a_ival[3] = {0,1,2}; // re-ordering of tri_a, s.t.
679  // a_ival[1,2] are on one side, and a_ival[0] on the plane or other side.
680  // or a_ival[0] one one side and a_ival[1,2) on the plne or other side.
681  // compute interval for triangle a
682  if (d_a1d_a2 > 0) //a1, a2 on same side of b's plane, a3 on the plane or other side
683  {
684  a_ival[0] = 2;
685  a_ival[1] = 0;
686  a_ival[2] = 1;
687  }
688  else if (d_a1d_a3 > 0) //a1, a3 on same side of b's plane, a2 on the plane or other side
689  {
690  a_ival[0] = 1;
691  a_ival[1] = 0;
692  a_ival[2] = 2;
693  }
694  else if (d_a[1]*d_a[2] > 0 || d_a[0] != 0) //a2, a3 on same side of b's plane, a1 on other side
695  {
696  a_ival[0] = 0;
697  a_ival[1] = 1;
698  a_ival[2] = 2;
699  }
700  else if (d_a[1] != 0) // a2 on one side of the plane, and a1, a3 on the plane
701  {
702  a_ival[0] = 1;
703  a_ival[1] = 0;
704  a_ival[2] = 2;
705  }
706  else if (d_a[2] != 0) // a3 on one side of the plane, and a1, a2 on the plane
707  {
708  a_ival[0] = 2;
709  a_ival[1] = 0;
710  a_ival[2] = 1;
711  }
712  else
713  {
714  // triangles are coplanar
715  coplanar = true;
716  }
717 
718  int b_ival[3] = {0,1,2}; // see a_ival for description
719  if (!coplanar)
720  {
721  // compute interval for triangle b
722  if (d_b1d_b2 > 0) //b1, b2 on same side of a's plane, b3 on the other side
723  {
724  b_ival[0] = 2;
725  b_ival[1] = 0;
726  b_ival[2] = 1;
727  }
728  else if (d_b1d_b3 > 0) //b1, b3 on same side of a's plane, b2 on the other side
729  {
730  b_ival[0] = 1;
731  b_ival[1] = 0;
732  b_ival[2] = 2;
733  }
734  else if (d_b[1]*d_b[2] > 0 || d_b[0] != 0)
735  {
736  b_ival[0] = 0;
737  b_ival[1] = 1;
738  b_ival[2] = 2;
739  }
740  else if (d_b[1] != 0)
741  {
742  b_ival[0] = 1;
743  b_ival[1] = 0;
744  b_ival[2] = 2;
745  }
746  else if (d_b[2] != 0)
747  {
748  b_ival[0] = 2;
749  b_ival[1] = 0;
750  b_ival[2] = 1;
751  }
752  else
753  {
754  coplanar = true;
755  }
756  }
757 
758  //special case when triangles are coplanar
759  if (coplanar)
760  {
761  //check if they intersect in their common plane
762  vgl_point_3d<double> i_pnt1, i_pnt2, i_pnt3;
763  bool isect1 = vgl_triangle_3d_line_intersection(
764  vgl_line_segment_3d<double>(a_p1,a_p2), b_p1, b_p2, b_p3, i_pnt1) != None;
765  bool isect2 = vgl_triangle_3d_line_intersection(
766  vgl_line_segment_3d<double>(a_p2,a_p3), b_p1, b_p2, b_p3, i_pnt2) != None;
767  bool isect3 = vgl_triangle_3d_line_intersection(
768  vgl_line_segment_3d<double>(a_p3,a_p1), b_p1, b_p2, b_p3, i_pnt3) != None;
769 
770  if ( isect1 || isect2 || isect3 )
771  {
772  vgl_point_3d<double> i_line_point1, i_line_point2;
773  if (isect1)
774  {
775  i_line_point1 = i_pnt1;
776  i_line_point1_edge = i_line_point2_edge = 0; // Set repeated edges to indicate incomplete answer
777  }
778  else
779  {
780  if (isect2)
781  {
782  i_line_point1 = i_pnt2;
783  i_line_point1_edge = i_line_point2_edge = 1;
784  }
785  else
786  {
787  i_line_point1 = i_pnt3;
788  i_line_point1_edge = i_line_point2_edge = 2;
789  }
790  }
791  // try and get extent of intersection as best as possible
792  if (isect1 && isect2)
793  i_line_point2 = i_pnt2;
794  else if ((isect1 || isect2) && isect3)
795  i_line_point2 = i_pnt3;
796  else
797  {
798  if (isect1)
799  i_line_point2 = i_pnt1;
800  else
801  {
802  if (isect2)
803  i_line_point2 = i_pnt2;
804  else
805  i_line_point2 = i_pnt3;
806  }
807  }
808  i_line.set( i_line_point1, i_line_point2);
809  return Coplanar;
810  }
811 
812  // finally, test if triangle a is totally contained in triangle b or vice versa
813  if (vgl_triangle_3d_test_inside(a_p1, b_p1, b_p2, b_p3))
814  {
815  i_line_point1_edge = i_line_point2_edge = 0;
816  i_line.set(a_p1, a_p3);
817  return Coplanar;
818  }
819 
820  if (vgl_triangle_3d_test_inside(b_p1, a_p1, a_p2, a_p3))
821  {
822  i_line_point1_edge = i_line_point2_edge = 3;
823  i_line.set(b_p1, b_p3);
824  return Coplanar;
825  }
826 
827  return None;
828  }
829 
830  vgl_point_3d<double> i_pnts[4];
831  double isect_a[2]; // selected_direction positions of start and end of intersection line in tri_a's p_a coords,
832  //intersection line interval for triangle a
833  double tmp = d_a[a_ival[0]]/(d_a[a_ival[0]]-d_a[a_ival[1]]); // fraction along edge a_ival[0,1] to plane_b's intersection.
834  isect_a[0] = p_a[a_ival[0]] + (p_a[a_ival[1]] - p_a[a_ival[0]])*tmp;
835  vgl_point_3d<double> a_vs[] = {a_p1,a_p2,a_p3};
836  vgl_vector_3d<double> diff = a_vs[a_ival[1]] - a_vs[a_ival[0]];
837  diff *= tmp;
838  i_pnts[0] = a_vs[a_ival[0]] + diff ; // 3D pos of start of intersection of tri_a and plane_b, on edge a[a_ival[0,1]]
839 
840  tmp = d_a[a_ival[0]]/(d_a[a_ival[0]]-d_a[a_ival[2]]);
841  isect_a[1] = p_a[a_ival[0]] + (p_a[a_ival[2]] - p_a[a_ival[0]])*tmp;
842  diff = a_vs[a_ival[2]] - a_vs[a_ival[0]];
843  diff *= tmp;
844  i_pnts[1] = a_vs[a_ival[0]] + diff; // 3D pos of end of intersection of tri_a and plane_b, on edge a[a_ival[0,2]]
845 
846  double isect_b[2]; // selected_direction positions of start and end of intersection line in tri_b's p_b coords,
847  //intersection line interval for triangle b
848  tmp = d_b[b_ival[0]]/(d_b[b_ival[0]] - d_b[b_ival[1]]);
849  isect_b[0] = p_b[b_ival[0]] + (p_b[b_ival[1]] - p_b[b_ival[0]])*tmp;
850  vgl_point_3d<double> b_vs[] = {b_p1,b_p2,b_p3};
851  diff = b_vs[b_ival[1]] - b_vs[b_ival[0]];
852  diff *= tmp;
853  i_pnts[2] = b_vs[b_ival[0]] + diff; // 3D pos of start of intersection of tri_b and plane_a, on edge b[b_ival[0,1]]
854 
855  tmp = d_b[b_ival[0]]/(d_b[b_ival[0]]-d_b[b_ival[2]]);
856  isect_b[1] = p_b[b_ival[0]] + (p_b[b_ival[2]] - p_b[b_ival[0]])*tmp;
857  diff = b_vs[b_ival[2]] - b_vs[b_ival[0]];
858  diff *= tmp;
859  i_pnts[3] = b_vs[b_ival[0]] + diff; // 3D pos of end of intersection of tri_b and plane_a, on edge b[b_ival[0,1]]
860 
861  unsigned smallest1 = 0;
862  if (isect_a[0] > isect_a[1])
863  {
864  std::swap(isect_a[0], isect_a[1]);
865  smallest1 = 1;
866  } // Now isect_a[0] <= isect_a[1]
867  unsigned smallest2 = 0;
868  if (isect_b[0] > isect_b[1])
869  {
870  std::swap(isect_b[0], isect_b[1]);
871  smallest2 = 1;
872  } // Now isect_b[0] <= isect_b[1]
873 
874  if (isect_a[1] < isect_b[0] || isect_b[1] < isect_a[0])
875  {
876  return None; //no intersection
877  }
878 
879  unsigned i_pt1,i_pt2;
880  //find the correct intersection line
881  if (isect_b[0]<isect_a[0])
882  {
883  if (smallest1==0)
884  {
885  i_pt1 = 0;
886  i_line_point1_edge = calc_edge_index(a_ival[0], a_ival[1]);
887  }
888  else
889  {
890  i_pt1 = 1;
891  i_line_point1_edge = calc_edge_index(a_ival[0], a_ival[2]);
892  }
893 
894  if (isect_b[1]<isect_a[1])
895  {
896  if (smallest2==0)
897  {
898  i_pt2 = 3;
899  i_line_point2_edge = calc_edge_index(b_ival[0], b_ival[2]) + 3;
900  }
901  else
902  {
903  i_pt2 = 2;
904  i_line_point2_edge = calc_edge_index(b_ival[0], b_ival[1]) + 3;
905  }
906  }
907  else
908  {
909  if (smallest1==0)
910  {
911  i_pt2 = 1;
912  i_line_point2_edge = calc_edge_index(a_ival[0], a_ival[2]);
913  }
914  else
915  {
916  i_pt2 = 0;
917  i_line_point2_edge = calc_edge_index(a_ival[0], a_ival[1]);
918  }
919  }
920  }
921  else
922  {
923  if (smallest2==0)
924  {
925  i_pt1 = 2;
926  i_line_point1_edge = calc_edge_index(b_ival[0], b_ival[1]) + 3;
927  }
928  else
929  {
930  i_pt1 = 3;
931  i_line_point1_edge = calc_edge_index(b_ival[0], b_ival[2]) + 3;
932  }
933 
934  if (isect_b[1]>isect_a[1])
935  {
936  if (smallest1==0)
937  {
938  i_pt2 = 1;
939  i_line_point2_edge = calc_edge_index(a_ival[0], a_ival[2]);
940  }
941  else
942  {
943  i_pt2 = 0;
944  i_line_point2_edge = calc_edge_index(a_ival[0], a_ival[1]);
945  }
946  }
947  else
948  {
949  if (smallest2==0)
950  {
951  i_pt2 = 3;
952  i_line_point2_edge = calc_edge_index(b_ival[0], b_ival[2]) + 3;
953  }
954  else
955  {
956  i_pt2 = 2;
957  i_line_point2_edge = calc_edge_index(b_ival[0], b_ival[1]) + 3;
958  }
959  }
960  }
961 
962  i_line.set(i_pnts[i_pt1],i_pnts[i_pt2]);
963  return Skew;
964 }
965 
966 
967 //=======================================================================
968 //: Compute the intersection line of the given triangles
969 // \see vgl_triangle_3d_triangle_intersection()
970 // \note an intersection line is not computed for a coplanar intersection
972  const vgl_point_3d<double>& a_p1,
973  const vgl_point_3d<double>& a_p2,
974  const vgl_point_3d<double>& a_p3,
975  const vgl_point_3d<double>& b_p1,
976  const vgl_point_3d<double>& b_p2,
977  const vgl_point_3d<double>& b_p3,
979 {
980  unsigned iline_p1, iline_p2;
982  a_p1, a_p2, a_p3,
983  b_p1, b_p2, b_p3,
984  i_line, iline_p1, iline_p2);
985 }
986 
987 //=======================================================================
988 //: Compute if the given triangles a and b intersect
989 // The triangle are represented by their respective vertices \a a_p1, \a a_p2, \a a_p3
990 // and \a b_p1, \a b_p2, \a b_p3
991 // \return intersection type
993  const vgl_point_3d<double>& a_p1,
994  const vgl_point_3d<double>& a_p2,
995  const vgl_point_3d<double>& a_p3,
996  const vgl_point_3d<double>& b_p1,
997  const vgl_point_3d<double>& b_p2,
998  const vgl_point_3d<double>& b_p3)
999 {
1000  // triangle intersection algorithm based on code & paper
1001  // found at http://jgt.akpeters.com/papers/Moller97/
1002 
1003  //sanity check for degenerate triangles
1004  if (collinear(a_p1,a_p2,a_p3))
1005  {
1006  if (a_p1 == a_p2 && a_p2==a_p3 && a_p1 == a_p3)
1007  {
1008  if (vgl_triangle_3d_test_inside(a_p1,b_p1,b_p2,b_p3))
1009  return Coplanar;
1010  return None;
1011  }
1012 
1014  vgl_point_3d<double> i_pnt;
1015  if ( ( a_p1 != a_p2 && (ret = vgl_triangle_3d_line_intersection(vgl_line_segment_3d<double>(a_p1,a_p2), b_p1,b_p2,b_p3,i_pnt)) != None ) ||
1016  ( a_p2 != a_p3 && (ret = vgl_triangle_3d_line_intersection(vgl_line_segment_3d<double>(a_p2,a_p3), b_p1,b_p2,b_p3,i_pnt)) != None ) ||
1017  ( a_p1 != a_p3 && (ret = vgl_triangle_3d_line_intersection(vgl_line_segment_3d<double>(a_p1,a_p3), b_p1,b_p2,b_p3,i_pnt)) != None ) )
1018  return ret;
1019 
1020  return None;
1021  }
1022  if (collinear(b_p1,b_p2,b_p3))
1023  {
1024  if (b_p1 == b_p2 && b_p2==b_p3 && b_p1 == b_p3)
1025  {
1026  if (vgl_triangle_3d_test_inside(b_p1,a_p1,a_p2,a_p3))
1027  return Coplanar;
1028  return None;
1029  }
1030 
1032  vgl_point_3d<double> i_pnt;
1033  if ( ( b_p1 != b_p2 && (ret = vgl_triangle_3d_line_intersection(vgl_line_segment_3d<double>(b_p1,b_p2), a_p1,a_p2,a_p3,i_pnt)) != None ) ||
1034  ( b_p2 != b_p3 && (ret = vgl_triangle_3d_line_intersection(vgl_line_segment_3d<double>(b_p2,b_p3), a_p1,a_p2,a_p3,i_pnt)) != None ) ||
1035  ( b_p1 != b_p3 && (ret = vgl_triangle_3d_line_intersection(vgl_line_segment_3d<double>(b_p1,b_p3), a_p1,a_p2,a_p3,i_pnt)) != None ) )
1036  return ret;
1037 
1038  return None;
1039  }
1040 
1041  //computing intersection of triangles a and b
1042 
1043  vgl_vector_3d<double> edge1,edge2;
1044  vgl_vector_3d<double> a_norm, b_norm, int_line;
1045 // vgl_vector_3d<double> int_line;
1046 
1047  double a_d, b_d;
1048  double d_b1, d_b2, d_b3, d_a1, d_a2, d_a3;
1049  double isect1[2], isect2[2];
1050  double d_b1d_b2, d_b1d_b3, d_a1d_a2, d_a1d_a3;
1051 
1052  double p_a1, p_a2, p_a3;
1053  double p_b1, p_b2, p_b3;
1054  bool coplanar = false;
1055 
1056  double a=0.0, b=0.0, c=0.0, x0=0.0, x1=0.0; // although variables are safely initialised further down,
1057  double d=0.0, e=0.0, f=0.0, y0=0.0, y1=0.0; // these "=0.0" silence the compiler
1058  double xx, yy, xxyy, tmp;
1059  double TRI_TRI_EPS = 100000*std::numeric_limits<double>::epsilon();
1060 
1061  //Firstly check if each triangle intersects
1062  // the plane of the other
1063 
1064  //construct plane equation of triangle a
1065  edge1 = a_p2 - a_p1;
1066  edge2 = a_p3 - a_p1;
1067 
1068  a_norm = normalized(cross_product(edge1, edge2));
1069 
1070  a_d = -( a_norm.x()*a_p1.x() + a_norm.y()*a_p1.y() +a_norm.z()*a_p1.z() );
1071  //vgl_plane_3d<double> a_plane(a_p1,a_p2,a_p3);
1072 
1073  // get signed distance of triangle b to triangle a's plane
1074  d_b1 = ( a_norm.x()*b_p1.x() + a_norm.y()*b_p1.y() + a_norm.z()*b_p1.z() ) + a_d;
1075  d_b2 = ( a_norm.x()*b_p2.x() + a_norm.y()*b_p2.y() + a_norm.z()*b_p2.z() ) + a_d;
1076  d_b3 = ( a_norm.x()*b_p3.x() + a_norm.y()*b_p3.y() + a_norm.z()*b_p3.z() ) + a_d;
1077 #if 0
1078  d_b1 = (a_plane.nx()*b_p1.x() + a_plane.ny()*b_p1.y() + a_plane.nz()*b_p1.z() ) + a_plane.d();
1079  d_b2 = (a_plane.nx()*b_p2.x() + a_plane.ny()*b_p2.y() + a_plane.nz()*b_p2.z() ) + a_plane.d();
1080  d_b3 = (a_plane.nx()*b_p3.x() + a_plane.ny()*b_p3.y() + a_plane.nz()*b_p3.z() ) + a_plane.d();
1081 #endif // 0
1082 
1083  // coplanarity robustness check
1084  if (std::fabs(d_b1) < TRI_TRI_EPS) d_b1 = 0.0;
1085  if (std::fabs(d_b2) < TRI_TRI_EPS) d_b2 = 0.0;
1086  if (std::fabs(d_b3) < TRI_TRI_EPS) d_b3 = 0.0;
1087 
1088  d_b1d_b2 = d_b1*d_b2;
1089  d_b1d_b3 = d_b1*d_b3;
1090 
1091  // all distances same sign => no intersection
1092  if (d_b1d_b2 > 0 && d_b1d_b3 > 0)
1093  {
1094  return None;
1095  }
1096 
1097  //construct plane equation of triangle b
1098  edge1 = b_p2 - b_p1;
1099  edge2 = b_p3 - b_p1;
1100 
1101  b_norm = normalized(cross_product(edge1,edge2));
1102 
1103  b_d = -( b_norm.x()*b_p1.x() + b_norm.y()*b_p1.y() + b_norm.z()*b_p1.z() );
1104  //vgl_plane_3d<double> b_plane(b_p1,b_p2,b_p3);
1105 
1106  // get signed distance of triangle a to triangle b's plane
1107  d_a1 = ( b_norm.x()*a_p1.x() + b_norm.y()*a_p1.y() + b_norm.z()*a_p1.z() ) + b_d;
1108  d_a2 = ( b_norm.x()*a_p2.x() + b_norm.y()*a_p2.y() + b_norm.z()*a_p2.z() ) + b_d;
1109  d_a3 = ( b_norm.x()*a_p3.x() + b_norm.y()*a_p3.y() + b_norm.z()*a_p3.z() ) + b_d;
1110 #if 0
1111  d_a1 = (b_plane.nx()*a_p1.x() + b_plane.ny()*a_p1.y() + b_plane.nz()*a_p1.z() ) + b_plane.d();
1112  d_a2 = (b_plane.nx()*a_p2.x() + b_plane.ny()*a_p2.y() + b_plane.nz()*a_p2.z() ) + b_plane.d();
1113  d_a3 = (b_plane.nx()*a_p3.x() + b_plane.ny()*a_p3.y() + b_plane.nz()*a_p3.z() ) + b_plane.d();
1114 #endif // 0
1115 
1116  // coplanarity robustness check
1117  if (std::fabs(d_a1) < TRI_TRI_EPS) d_a1 = 0.0;
1118  if (std::fabs(d_a2) < TRI_TRI_EPS) d_a2 = 0.0;
1119  if (std::fabs(d_a3) < TRI_TRI_EPS) d_a3 = 0.0;
1120 
1121  d_a1d_a2 = d_a1*d_a2;
1122  d_a1d_a3 = d_a1*d_a3;
1123 
1124  // all distances same sign => no intersection
1125  if (d_a1d_a2 > 0 && d_a1d_a3 > 0)
1126  {
1127  return None;
1128  }
1129 
1130  // Now know triangles contain
1131  // the line of their planes intersection.
1132  // So...compute each triangles interval of the intersection
1133  // line and determine if they overlap i.e. if the triangles intersect
1134 
1135  // compute direction of intersection line
1136  int_line = cross_product(a_norm,b_norm);
1137  //int_line = cross_product(a_plane.normal(),b_plane.normal());
1138 
1139  // largest component of int_line?
1140  // to get a simplified 2D projection
1141  int_line.set(std::fabs(int_line.x()),std::fabs(int_line.y()),std::fabs(int_line.z()));
1142 
1143  if (int_line.y()>=int_line.x() && int_line.y()>=int_line.z())
1144  { // Max component is y
1145  p_a1 = a_p1.y();
1146  p_a2 = a_p2.y();
1147  p_a3 = a_p3.y();
1148 
1149  p_b1 = b_p1.y();
1150  p_b2 = b_p2.y();
1151  p_b3 = b_p3.y();
1152  }
1153  else if (int_line.x()>=int_line.y() && int_line.x()>=int_line.z())
1154  { // Max component is x
1155  p_a1 = a_p1.x();
1156  p_a2 = a_p2.x();
1157  p_a3 = a_p3.x();
1158 
1159  p_b1 = b_p1.x();
1160  p_b2 = b_p2.x();
1161  p_b3 = b_p3.x();
1162  }
1163  else { // Max component is z
1164  p_a1 = a_p1.z();
1165  p_a2 = a_p2.z();
1166  p_a3 = a_p3.z();
1167 
1168  p_b1 = b_p1.z();
1169  p_b2 = b_p2.z();
1170  p_b3 = b_p3.z();
1171  }
1172 
1173  // compute interval for triangle a
1174  if (d_a1d_a2 > 0) //a1, a2 on same side of b's plane, a3 on the other side
1175  {
1176  a = p_a3;
1177  b = (p_a1-p_a3)*d_a3;
1178  c = (p_a2-p_a3)*d_a3;
1179 
1180  x0 = d_a3-d_a1;
1181  x1 = d_a3-d_a2;
1182  }
1183  else if (d_a1d_a3 > 0) //a1, a3 on same side of b's plane, a2 on the other side
1184  {
1185  a = p_a2;
1186  b = (p_a1-p_a2)*d_a2;
1187  c = (p_a3-p_a2)*d_a2;
1188 
1189  x0 = d_a2-d_a1;
1190  x1 = d_a2-d_a3;
1191  }
1192  else if (d_a2*d_a3 > 0 || d_a1 != 0)
1193  {
1194  a = p_a1;
1195  b = (p_a2-p_a1)*d_a1;
1196  c = (p_a3-p_a1)*d_a1;
1197 
1198  x0 = d_a1-d_a2;
1199  x1 = d_a1-d_a3;
1200  }
1201  else if (d_a2 != 0)
1202  {
1203  a = p_a2;
1204  b = (p_a1-p_a2)*d_a2;
1205  c = (p_a3-p_a2)*d_a2;
1206 
1207  x0 = d_a2-d_a1;
1208  x1 = d_a2-d_a3;
1209  }
1210  else if (d_a3 != 0)
1211  {
1212  a = p_a3;
1213  b = (p_a1-p_a3)*d_a3;
1214  c = (p_a2-p_a3)*d_a3;
1215 
1216  x0 = d_a3-d_a1;
1217  x1 = d_a3-d_a2;
1218  }
1219  else
1220  {
1221  // triangles are coplanar
1222  coplanar = true;
1223  }
1224 
1225  if (!coplanar)
1226  {
1227  // compute interval for triangle b
1228  if (d_b1d_b2 > 0) //b1, b2 on same side of a's plane, b3 on the other side
1229  {
1230  d = p_b3;
1231  e = (p_b1-p_b3)*d_b3;
1232  f = (p_b2-p_b3)*d_b3;
1233 
1234  y0 = d_b3-d_b1;
1235  y1 = d_b3-d_b2;
1236  }
1237  else if (d_b1d_b3 > 0) //b1, b3 on same side of a's plane, b2 on the other side
1238  {
1239  d = p_b2;
1240  e=(p_b1-p_b2)*d_b2;
1241  f=(p_b3-p_b2)*d_b2;
1242 
1243  y0=d_b2-d_b1;
1244  y1=d_b2-d_b3;
1245  }
1246  else if (d_b2*d_b3 > 0 || d_b1 != 0)
1247  {
1248  d = p_b1;
1249  e = (p_b2-p_b1)*d_b1;
1250  f = (p_b3-p_b1)*d_b1;
1251 
1252  y0 = d_b1-d_b2;
1253  y1 = d_b1-d_b3;
1254  }
1255  else if (d_b2 != 0)
1256  {
1257  d = p_b2;
1258  e = (p_b1-p_b2)*d_b2;
1259  f = (p_b3-p_b2)*d_b2;
1260 
1261  y0 = d_b2-d_b1;
1262  y1 = d_b2-d_b3;
1263  }
1264  else if (d_b3 != 0)
1265  {
1266  d = p_b3;
1267  e = (p_b1-p_b3)*d_b3;
1268  f = (p_b2-p_b3)*d_b3;
1269 
1270  y0 = d_b3-d_b1;
1271  y1 = d_b3-d_b2;
1272  }
1273  else
1274  {
1275  coplanar = true;
1276  }
1277  }
1278 
1279  //special case when triangles are coplanar
1280  if (coplanar)
1281  {
1282  //check if they intersect in their common plane
1283  vgl_point_3d<double> i_pnt;
1284  if (vgl_triangle_3d_line_intersection(vgl_line_segment_3d<double>(a_p1,a_p2), b_p1, b_p2, b_p3, i_pnt) ||
1285  vgl_triangle_3d_line_intersection(vgl_line_segment_3d<double>(a_p2,a_p3), b_p1, b_p2, b_p3, i_pnt) ||
1286  vgl_triangle_3d_line_intersection(vgl_line_segment_3d<double>(a_p3,a_p1), b_p1, b_p2, b_p3, i_pnt) )
1287  {
1288  return Coplanar;
1289  }
1290 
1291  // finally, test if triangle a is totally contained in triangle b or vice versa
1292  if (vgl_triangle_3d_test_inside(a_p1, b_p1, b_p2, b_p3) ||
1293  vgl_triangle_3d_test_inside(b_p1, a_p1, a_p2, a_p3))
1294  {
1295  return Coplanar;
1296  }
1297 
1298  return None;
1299  }
1300 
1301  // finally, test if the triangles respective intervals
1302  // of the intersection line overlap
1303  xx = x0*x1;
1304  yy = y0*y1;
1305  xxyy = xx*yy;
1306 
1307  tmp = a*xxyy;
1308  isect1[0] = tmp+b*x1*yy;
1309  isect1[1] = tmp+c*x0*yy;
1310 
1311  tmp = d*xxyy;
1312  isect2[0] = tmp+e*xx*y1;
1313  isect2[1] = tmp+f*xx*y0;
1314 
1315  if (isect1[0] > isect1[1])
1316  {
1317  tmp = isect1[0];
1318  isect1[0] = isect1[1];
1319  isect1[1] = tmp;
1320  }
1321 
1322  if (isect2[0] > isect2[1])
1323  {
1324  tmp = isect2[0];
1325  isect2[0] = isect2[1];
1326  isect2[1] = tmp;
1327  }
1328 
1329  if (isect1[1] < isect2[0] || isect2[1] < isect1[0])
1330  {
1331  return None;
1332  }
1333 
1334  return Skew;
1335 }
1336 
1337 //=======================================================================
1338 //: Compute the line of intersection of the given triangle and plane
1339 // The triangle is represented by its vertices \a p1, \a p2, \a p3
1340 // \return intersection type
1341 // \note an intersection line is not defined (vgl_vgl_nan) for a coplanar intersection
1343  const vgl_point_3d<double>& p1,
1344  const vgl_point_3d<double>& p2,
1345  const vgl_point_3d<double>& p3,
1346  const vgl_plane_3d<double>& i_plane,
1348 {
1349  //Firstly check if the triangle actually intersects the plane
1350  // by computing the signed distance of its vertices to the plane
1351 
1352  //all we care about is the sign of the distance
1353  double p1_d = i_plane.nx()*p1.x() + i_plane.ny()*p1.y() + i_plane.nz()*p1.z() + i_plane.d();
1354  double p2_d = i_plane.nx()*p2.x() + i_plane.ny()*p2.y() + i_plane.nz()*p2.z() + i_plane.d();
1355  double p3_d = i_plane.nx()*p3.x() + i_plane.ny()*p3.y() + i_plane.nz()*p3.z() + i_plane.d();
1356 
1357  // coplanarity robustness check
1358  if (std::fabs(p1_d) < sqrteps) p1_d = 0.0;
1359  if (std::fabs(p2_d) < sqrteps) p2_d = 0.0;
1360  if (std::fabs(p3_d) < sqrteps) p3_d = 0.0;
1361 
1363 
1364  if (p1_d*p2_d > 0 && p1_d*p3_d > 0) // all distances strictly same sign => no intersection
1365  {
1367  return None;
1368  }
1369  else if (p1_d == 0 && p2_d == 0 && p3_d == 0) //triangle lies in plane
1370  {
1371  vgl_point_3d<double> i_pnt1; i_pnt1.set(vgl_nan, vgl_nan, vgl_nan);
1372  i_line.set(i_pnt1,i_pnt1);
1373  return Coplanar;
1374  }
1375  else if (p1_d*p2_d > 0) //p1, p2 on same side, p3 on the other
1376  {
1377  edge.set(p1,p3);
1378  vgl_point_3d<double> i_pnt1 = vgl_intersection(edge, i_plane);
1379  edge.set(p2,p3);
1380  vgl_point_3d<double> i_pnt2 = vgl_intersection(edge, i_plane);
1381  i_line.set(i_pnt1,i_pnt2);
1382  }
1383  else if (p1_d*p3_d > 0) //p1, p3 on same side, p2 on the other
1384  {
1385  edge.set(p1,p2);
1386  vgl_point_3d<double> i_pnt1 = vgl_intersection(edge, i_plane);
1387  edge.set(p3,p2);
1388  vgl_point_3d<double> i_pnt2 = vgl_intersection(edge, i_plane);
1389  i_line.set(i_pnt1,i_pnt2);
1390  }
1391  else if (p2_d*p3_d > 0) //p2, p3 on same side, p1 on the other
1392  {
1393  edge.set(p2,p1);
1394  vgl_point_3d<double> i_pnt1 = vgl_intersection(edge, i_plane);
1395  edge.set(p3,p1);
1396  vgl_point_3d<double> i_pnt2 = vgl_intersection(edge, i_plane);
1397  i_line.set(i_pnt1,i_pnt2);
1398  }
1399  else if (p1_d == 0 && p2_d == 0) //edge p1,p2 in plane
1400  {
1401  i_line.set(p1,p2);
1402  }
1403  else if (p1_d == 0 && p3_d == 0) //edge p1,p3 in plane
1404  {
1405  i_line.set(p1,p3);
1406  }
1407  else if (p3_d == 0 && p2_d == 0) //edge p2,p3 in plane
1408  {
1409  i_line.set(p2,p3);
1410  }
1411  else if (p1_d == 0) //just p1 in plane
1412  {
1413  edge.set(p3,p2);
1414  vgl_point_3d<double> i_pnt2 = vgl_intersection(edge, i_plane);
1415  i_line.set(p1,i_pnt2);
1416  }
1417  else if (p2_d == 0) //just p2 in plane
1418  {
1419  edge.set(p3,p1);
1420  vgl_point_3d<double> i_pnt2 = vgl_intersection(edge, i_plane);
1421  i_line.set(p2,i_pnt2);
1422  }
1423  else if (p3_d == 0) //just p3 in plane
1424  {
1425  edge.set(p2,p1);
1426  vgl_point_3d<double> i_pnt2 = vgl_intersection(edge, i_plane);
1427  i_line.set(p3,i_pnt2);
1428  }
1429  return Skew;
1430 }
1431 
1432 
1433 //=======================================================================
1434 // Compute the closest point on a triangle to a reference point
1435 //=======================================================================
1437  const vgl_point_3d<double>& q,
1438  const vgl_point_3d<double>& p1,
1439  const vgl_point_3d<double>& p2,
1440  const vgl_point_3d<double>& p3)
1441 {
1442  // Handle degenerate case.
1443  if (p1 == p2)
1444  {
1445  if (p2 == p3) return p3;
1447  }
1448  if (p2 == p3)
1450  if (p3 == p1)
1452 
1453  // Construct a plane from the 3 vertices of the triangle
1454  vgl_plane_3d<double> plane = create_plane_and_ignore_degenerate(p1, p2, p3);
1455 
1456  // Find the closest point on the whole plane to the test point
1457  vgl_point_3d<double> cp = vgl_closest_point<double>(plane, q);
1458 
1459  // Is this closest point inside the triangle ?
1460  if (vgl_triangle_3d_test_inside(cp, p1, p2, p3))
1461  {
1462  return cp;
1463  }
1464  else
1465  {
1466  // Find the nearest point on the triangle's boundary by testing each edge
1467 
1468  // Edge 1
1469  double cp1x, cp1y, cp1z;
1471  cp1x, cp1y, cp1z,
1472  p1.x(), p1.y(), p1.z(),
1473  p2.x(), p2.y(), p2.z(),
1474  q.x(), q.y(), q.z());
1475  vgl_point_3d<double> cp1(cp1x, cp1y, cp1z);
1476  double d1 = vgl_distance(cp1, q);
1477 
1478  // Edge 2
1479  double cp2x, cp2y, cp2z;
1481  cp2x, cp2y, cp2z,
1482  p2.x(), p2.y(), p2.z(),
1483  p3.x(), p3.y(), p3.z(),
1484  q.x(), q.y(), q.z());
1485  vgl_point_3d<double> cp2(cp2x, cp2y, cp2z);
1486  double d2 = vgl_distance(cp2, q);
1487 
1488  // Edge 3
1489  double cp3x, cp3y, cp3z;
1491  cp3x, cp3y, cp3z,
1492  p1.x(), p1.y(), p1.z(),
1493  p3.x(), p3.y(), p3.z(),
1494  q.x(), q.y(), q.z());
1495  vgl_point_3d<double> cp3(cp3x, cp3y, cp3z);
1496  double d3 = vgl_distance(cp3, q);
1497 
1498  // Identify nearest edge and return closest point on that edge.
1499  if (d1<=d2 && d1<=d3)
1500  return cp1;
1501  else if (d2<=d1 && d2<=d3)
1502  return cp2;
1503  else
1504  return cp3;
1505  }
1506 }
1507 
1508 
1509 //=======================================================================
1510 // Compute the distance to the closest point on a triangle from a reference point.
1511 //=======================================================================
1513  const vgl_point_3d<double>& p1,
1514  const vgl_point_3d<double>& p2,
1515  const vgl_point_3d<double>& p3)
1516 {
1518  return vgl_distance(c, q);
1519 }
1520 
1521 //=======================================================================
1522 //: Check if the two triangles are coplanar
1523 // The triangles are represented by their respective vertices \a a_p1, \a a_p2, \a a_p3
1524 // and \a b_p1, \a b_p2, \a b_p3
1526  const vgl_point_3d<double>& a_p1,
1527  const vgl_point_3d<double>& a_p2,
1528  const vgl_point_3d<double>& a_p3,
1529  const vgl_point_3d<double>& b_p1,
1530  const vgl_point_3d<double>& b_p2,
1531  const vgl_point_3d<double>& b_p3)
1532 {
1533  return coplanar(a_p1,b_p1,b_p2,b_p3)
1534  && coplanar(a_p2,b_p1,b_p2,b_p3)
1535  && coplanar(a_p3,b_p1,b_p2,b_p3);
1536 }
1537 
1538 //=======================================================================
1539 //: Compute the area of a triangle
1540 // The triangle is represented by its vertices \a p1, \a p2, \a p3
1542  const vgl_point_3d<double> &p1,
1543  const vgl_point_3d<double> &p2 )
1544 {
1545  vgl_vector_3d<double> edge_vector0;
1546  edge_vector0 = p0 - p1;
1547  vgl_vector_3d<double> edge_vector1;
1548  edge_vector1 = p0 - p2;
1549 
1550  vgl_vector_3d<double> area_vector;
1551  area_vector = cross_product( edge_vector0, edge_vector1 );
1552 
1553  double area;
1554  area = area_vector.length();
1555  area /= 2;
1556 
1557  return area;
1558 }
1559 
1560 //=======================================================================
1561 //: Compute the aspect ration of a triangle
1562 // The triangle is represented by its vertices \a p1, \a p2, \a p3
1564  const vgl_point_3d<double> &p0,
1565  const vgl_point_3d<double> &p1,
1566  const vgl_point_3d<double> &p2 )
1567 {
1568  return vgl_triangle_3d_longest_side( p0, p1, p2 ) / vgl_triangle_3d_shortest_side( p0, p1, p2 );
1569 }
double vgl_triangle_3d_area(const vgl_point_3d< double > &p0, const vgl_point_3d< double > &p1, const vgl_point_3d< double > &p2)
Compute the area of a triangle.
Set of intersection functions.
v normalized(v const &a)
Return a normalised version of a.
T dot_product(v const &a, v const &b)
dot product or inner product of two vectors.
vgl_point_3d< Type > point1() const
void set(vgl_point_3d< Type > const &p1, vgl_point_3d< Type > const &p2)
Assignment.
void set(vgl_point_3d< Type > const &p1, vgl_point_3d< Type > const &p2)
assignment.
double vgl_triangle_3d_aspect_ratio(const vgl_point_3d< double > &p0, const vgl_point_3d< double > &p1, const vgl_point_3d< double > &p2)
Compute the aspect ration of a triangle.
std::vector< std::pair< unsigned, unsigned > > vgl_triangle_3d_coincident_edges(const vgl_point_3d< double > &a_p1, const vgl_point_3d< double > &a_p2, const vgl_point_3d< double > &a_p3, const vgl_point_3d< double > &b_p1, const vgl_point_3d< double > &b_p2, const vgl_point_3d< double > &b_p3)
Check for coincident edges of triangles a and b.
double vgl_triangle_3d_distance(const vgl_point_3d< double > &q, const vgl_point_3d< double > &p1, const vgl_point_3d< double > &p2, const vgl_point_3d< double > &p3)
Compute the distance to the closest point on a triangle from a reference point.
bool vgl_triangle_3d_test_inside(const vgl_point_3d< double > &i_pnt, const vgl_point_3d< double > &p1, const vgl_point_3d< double > &p2, const vgl_point_3d< double > &p3, double coplanar_tolerance)
Check if the given point is inside the triangle.
vgl_point_3d< Type > point2() const
vgl_triangle_3d_intersection_t vgl_triangle_3d_triangle_intersection(const vgl_point_3d< double > &a_p1, const vgl_point_3d< double > &a_p2, const vgl_point_3d< double > &a_p3, const vgl_point_3d< double > &b_p1, const vgl_point_3d< double > &b_p2, const vgl_point_3d< double > &b_p3, vgl_line_segment_3d< double > &i_line, unsigned &i_line_point1_edge, unsigned &i_line_point2_edge)
Compute the intersection line of the given triangles.
T nz() const
Definition: vgl_plane_3d.h:96
vgl_vector_3d< T > normal() const
Return the normal direction, i.e., a unit vector orthogonal to this plane.
Definition: vgl_plane_3d.h:116
direction vector in Euclidean 3D space
void vgl_closest_point_to_linesegment(T &ret_x, T &ret_y, T x1, T y1, T x2, T y2, T x, T y)
Closest point to (x,y) on the line segment (x1,y1)-(x2,y2).
vgl_point_3d< double > vgl_triangle_3d_closest_point(const vgl_point_3d< double > &q, const vgl_point_3d< double > &p1, const vgl_point_3d< double > &p2, const vgl_point_3d< double > &p3)
Compute the closest point on a triangle to a reference point.
Represents a cartesian 3D point.
Definition: vgl_fwd.h:11
vgl_triangle_3d_intersection_t vgl_triangle_3d_line_intersection(const vgl_line_segment_3d< double > &line, const vgl_point_3d< double > &p1, const vgl_point_3d< double > &p2, const vgl_point_3d< double > &p3, vgl_point_3d< double > &i_pnt, bool ignore_coplanar)
Compute the intersection point between the line segment and triangle.
bool concurrent(l const &l1, l const &l2, l const &l3)
Are three lines concurrent, i.e., do they pass through a common point?.
bool vgl_triangle_3d_test_inside_simple(const vgl_point_3d< double > &i_pnt, const vgl_point_3d< double > &p1, const vgl_point_3d< double > &p2, const vgl_point_3d< double > &p3)
Check if point i_pnt is inside the triangle.
#define UINT_MAX
vgl_triangle_3d_intersection_t vgl_triangle_3d_plane_intersection(const vgl_point_3d< double > &p1, const vgl_point_3d< double > &p2, const vgl_point_3d< double > &p3, const vgl_plane_3d< double > &i_plane, vgl_line_segment_3d< double > &i_line)
Compute the line of intersection of the given triangle and plane.
T ny() const
Definition: vgl_plane_3d.h:93
double vgl_triangle_3d_longest_side(const vgl_point_3d< double > &p1, const vgl_point_3d< double > &p2, const vgl_point_3d< double > &p3)
Compute the longest side of the given triangle.
vgl_point_3d< T > vgl_intersection(const std::vector< vgl_plane_3d< T > > &p)
Return the intersection point of vector of planes.
double length(v const &a)
Return the length of a vector.
Definition: vgl_vector_2d.h:94
vgl_triangle_3d_intersection_t
Type & z()
Definition: vgl_point_3d.h:73
A class to hold a non-homogeneous representation of a 3D line.
Definition: vgl_fwd.h:17
#define v
Definition: vgl_vector_2d.h:74
Set of closest-point functions.
bool collinear(l const &l1, vgl_homg_point_3d< Type > const &p)
Does a line pass through a point, i.e., are the point and the line collinear?.
a point in 3D nonhomogeneous space
vgl_point_2d< T > vgl_closest_point(vgl_line_2d< T > const &l, vgl_point_2d< T > const &p)
Return the point on the given line closest to the given point.
double length() const
Return the length of this vector.
T cross_product(v const &a, v const &b)
cross product of two vectors (area of enclosed parallellogram).
T y() const
Definition: vgl_vector_3d.h:37
bool contains(const vgl_point_3d< Type > &p) const
Check if point p is on the line segment.
Represents a Euclidean 3D plane.
Definition: vgl_fwd.h:23
Represents a 3D line segment using two points.
Definition: vgl_fwd.h:19
T x() const
Definition: vgl_vector_3d.h:36
T d() const
Return constant coefficient.
Definition: vgl_plane_3d.h:98
bool vgl_triangle_3d_triangle_coplanar(const vgl_point_3d< double > &a_p1, const vgl_point_3d< double > &a_p2, const vgl_point_3d< double > &a_p3, const vgl_point_3d< double > &b_p1, const vgl_point_3d< double > &b_p2, const vgl_point_3d< double > &b_p3)
Check if the two triangles are coplanar.
bool coplanar(l const &l1, l const &l2)
Are two lines coplanar, i.e., do they intersect?.
T z() const
Definition: vgl_vector_3d.h:38
T nx() const
Definition: vgl_plane_3d.h:90
Type & x()
Definition: vgl_point_3d.h:71
Direction vector in Euclidean 3D space, templated by type of element.
Definition: vgl_fwd.h:13
Some helpful functions when working with triangles.
void set(T vx, T vy, T vz)
Assignment.
Definition: vgl_vector_3d.h:60
double vgl_distance(vgl_point_2d< T >const &p1, vgl_point_2d< T >const &p2)
return the distance between two points.
Definition: vgl_distance.h:104
void set(Type px, Type py, Type pz)
Set x, y and z.
Definition: vgl_point_3d.h:81
a plane in 3D nonhomogeneous space
non-homogeneous 3D line, represented by 2 points.
Set of distance functions.
double vgl_triangle_3d_shortest_side(const vgl_point_3d< double > &p1, const vgl_point_3d< double > &p2, const vgl_point_3d< double > &p3)
Compute the shortest side of the given triangle.
Type & y()
Definition: vgl_point_3d.h:72