00001 #include "vgl_triangle_3d.h"
00002
00003
00004
00005
00006
00007
00008 #include <vgl/vgl_distance.h>
00009 #include <vgl/vgl_intersection.h>
00010 #include <vgl/vgl_line_3d_2_points.h>
00011 #include <vgl/vgl_plane_3d.h>
00012 #include <vgl/vgl_point_3d.h>
00013 #include <vgl/vgl_vector_3d.h>
00014 #include <vgl/vgl_closest_point.h>
00015 #include <vcl_limits.h>
00016 #include <vcl_cassert.h>
00017
00018
00019 static const double vgl_nan = vcl_sqrt(-1.0);
00020 static const double sqrteps = vcl_sqrt(vcl_numeric_limits<double>::epsilon());
00021 static const double pi = 3.14159265358979323846;
00022
00023 namespace
00024 {
00025
00026 vgl_plane_3d<double> create_plane_and_ignore_degenerate(const vgl_point_3d<double>& p1,
00027 const vgl_point_3d<double>& p2,
00028 const vgl_point_3d<double>& p3)
00029 {
00030 vgl_plane_3d<double> plane;
00031 double *a = reinterpret_cast<double *>(&plane);
00032
00033 a[0] = p2.y()*p3.z() - p2.z()*p3.y()
00034 + p3.y()*p1.z() - p3.z()*p1.y()
00035 + p1.y()*p2.z() - p1.z()*p2.y();
00036
00037 a[1] = p2.z()*p3.x() - p2.x()*p3.z()
00038 + p3.z()*p1.x() - p3.x()*p1.z()
00039 + p1.z()*p2.x() - p1.x()*p2.z();
00040
00041 a[2] = p2.x()*p3.y() - p2.y()*p3.x()
00042 + p3.x()*p1.y() - p3.y()*p1.x()
00043 + p1.x()*p2.y() - p1.y()*p2.x();
00044
00045 a[3] = p1.x()*(p2.z()*p3.y() - p2.y()*p3.z())
00046 + p2.x()*(p3.z()*p1.y() - p3.y()*p1.z())
00047 + p3.x()*(p1.z()*p2.y() - p1.y()*p2.z());
00048 return plane;
00049 }
00050 }
00051
00052
00053
00054
00055 vcl_vector<vcl_pair<unsigned,unsigned> > vgl_triangle_3d_coincident_edges(
00056 const vgl_point_3d<double>& a_p1,
00057 const vgl_point_3d<double>& a_p2,
00058 const vgl_point_3d<double>& a_p3,
00059 const vgl_point_3d<double>& b_p1,
00060 const vgl_point_3d<double>& b_p2,
00061 const vgl_point_3d<double>& b_p3)
00062 {
00063 vcl_vector<vcl_pair<unsigned,unsigned> > coinc_edges;
00064
00065
00066 vgl_point_3d<double> a[3] = {a_p1, a_p2, a_p3};
00067 vgl_point_3d<double> b[3] = {b_p1, b_p2, b_p3};
00068 vcl_pair<unsigned,unsigned> e[3] = { vcl_make_pair(0,1),
00069 vcl_make_pair(1,2),
00070 vcl_make_pair(2,0) };
00071
00072
00073 for (unsigned j = 0; j < 3; ++j)
00074 {
00075 for (unsigned i = 0; i < 3; ++i)
00076 {
00077
00078
00079 double e1_len = length(a[e[j].first] - a[e[j].second]);
00080 double b1_dist = length(a[e[j].first] - b[e[i].first]) +
00081 length(a[e[j].second] - b[e[i].first]);
00082 double b2_dist = length(a[e[j].first] - b[e[i].second]) +
00083 length(a[e[j].second] - b[e[i].second]);
00084
00085 double e2_len = length(b[e[i].first] - b[e[i].second]);
00086 double a1_dist = length(b[e[i].first] - a[e[j].first]) +
00087 length(b[e[i].second] - a[e[j].first]);
00088 double a2_dist = length(b[e[i].first] - a[e[j].second]) +
00089 length(b[e[i].second] - a[e[j].second]);
00090
00091 if ((vcl_fabs(e1_len - b1_dist) < sqrteps &&
00092 vcl_fabs(e1_len - b2_dist) < sqrteps) ||
00093 (vcl_fabs(e2_len - a1_dist) < sqrteps &&
00094 vcl_fabs(e2_len - a2_dist) < sqrteps))
00095 {
00096 coinc_edges.push_back(vcl_make_pair(j,i));
00097 break;
00098 }
00099 }
00100 }
00101
00102 return coinc_edges;
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112 bool vgl_triangle_3d_test_inside(const vgl_point_3d<double>& i_pnt,
00113 const vgl_point_3d<double>& p1,
00114 const vgl_point_3d<double>& p2,
00115 const vgl_point_3d<double>& p3,
00116 double coplanar_tolerance)
00117 {
00118
00119 if (collinear(p1,p2,p3))
00120 {
00121
00122 if (p1==p2&&p2==p3&&p1==p3)
00123 {
00124 return i_pnt == p1;
00125 }
00126
00127 return vgl_line_segment_3d<double>(p1,p2).contains(i_pnt) ||
00128 vgl_line_segment_3d<double>(p2,p3).contains(i_pnt) ||
00129 vgl_line_segment_3d<double>(p1,p3).contains(i_pnt);
00130 }
00131
00132
00133
00134 vgl_plane_3d<double> plane =
00135 create_plane_and_ignore_degenerate(p1, p2, p3);
00136
00137
00138
00139
00140
00141 if (vgl_distance(plane,i_pnt) > coplanar_tolerance)
00142 return false;
00143
00144 vgl_vector_3d<double> norm = plane.normal();
00145 norm.set(vcl_fabs(norm.x()),vcl_fabs(norm.y()),vcl_fabs(norm.z()));
00146
00147 unsigned i1 = 0;
00148 unsigned i2 = 1;
00149 if (norm.y()>=norm.x() && norm.y()>=norm.z())
00150 {
00151 i2 = 2;
00152 }
00153 else if (norm.x()>=norm.y() && norm.x()>=norm.z())
00154 {
00155 i1 = 2;
00156 }
00157
00158 double point[3] = {i_pnt.x(), i_pnt.y(), i_pnt.z()};
00159 double vert0[3] = {p1.x(), p1.y(), p1.z()};
00160 double vert1[3] = {p2.x(), p2.y(), p2.z()};
00161 double vert2[3] = {p3.x(), p3.y(), p3.z()};
00162
00163 double beta = 0.0;
00164 double alpha = 0.0;
00165
00166
00167 double u0 = (vcl_fabs(point[i1]) < sqrteps ? 0 : point[i1]) - (vcl_fabs(vert0[i1]) < sqrteps ? 0 : vert0[i1]);
00168 double v0 = (vcl_fabs(point[i2]) < sqrteps ? 0 : point[i2]) - (vcl_fabs(vert0[i2]) < sqrteps ? 0 : vert0[i2]);
00169
00170 double u1 = (vcl_fabs(vert1[i1]) < sqrteps ? 0 : vert1[i1]) - (vcl_fabs(vert0[i1]) < sqrteps ? 0 : vert0[i1]);
00171 double u2 = (vcl_fabs(vert2[i1]) < sqrteps ? 0 : vert2[i1]) - (vcl_fabs(vert0[i1]) < sqrteps ? 0 : vert0[i1]);
00172 double v1 = (vcl_fabs(vert1[i2]) < sqrteps ? 0 : vert1[i2]) - (vcl_fabs(vert0[i2]) < sqrteps ? 0 : vert0[i2]);
00173 double v2 = (vcl_fabs(vert2[i2]) < sqrteps ? 0 : vert2[i2]) - (vcl_fabs(vert0[i2]) < sqrteps ? 0 : vert0[i2]);
00174
00175
00176 if (u1 == 0)
00177 {
00178 beta = u0 / u2;
00179 if (beta < -sqrteps/*0*/ || beta > 1+sqrteps)
00180 return false;
00181 alpha = (v0 - beta * v2) / v1;
00182 }
00183 else
00184 {
00185 beta = (v0 * u1 - u0 * v1) / (v2 * u1 - u2 * v1);
00186 if (beta < -sqrteps/*0*/ || beta > 1+sqrteps)
00187 return false;
00188 alpha = (u0 - beta * u2) / u1;
00189 }
00190
00191 return alpha >= -sqrteps
00192 && alpha + beta <= 1.0+sqrteps;
00193 }
00194
00195
00196
00197
00198
00199
00200 bool vgl_triangle_3d_test_inside(const vgl_point_3d<double>& i_pnt,
00201 const vgl_point_3d<double>& p1,
00202 const vgl_point_3d<double>& p2,
00203 const vgl_point_3d<double>& p3)
00204 {
00205 return vgl_triangle_3d_test_inside(i_pnt, p1, p2, p3, sqrteps);
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215 bool vgl_triangle_3d_test_inside_simple(const vgl_point_3d<double>& i_pnt,
00216 const vgl_point_3d<double>& p1,
00217 const vgl_point_3d<double>& p2,
00218 const vgl_point_3d<double>& p3 )
00219 {
00220 vgl_vector_3d<double> vec1 = normalized(i_pnt - p1);
00221 vgl_vector_3d<double> vec2 = normalized(i_pnt - p2);
00222 vgl_vector_3d<double> vec3 = normalized(i_pnt - p3);
00223
00224 double int_ang = vcl_acos(dot_product(vec1,vec2)) + vcl_acos(dot_product(vec2,vec3)) + vcl_acos(dot_product(vec3,vec1));
00225 double test_val = vcl_fabs(int_ang-(2*pi));
00226
00227 return test_val < sqrteps;
00228 }
00229
00230
00231
00232
00233 static vgl_triangle_3d_intersection_t same_side(
00234 const vgl_point_3d<double>& A,
00235 const vgl_point_3d<double>& B,
00236 const vgl_point_3d<double>& C,
00237 const vgl_point_3d<double>& D,
00238 const vgl_point_3d<double>& E)
00239 {
00240 vgl_vector_3d<double> b = B - A;
00241 vgl_vector_3d<double> c = C - A;
00242
00243 vgl_vector_3d<double> n = cross_product(b, c);
00244
00245 vgl_vector_3d<double> d = D - A;
00246 double d_dot = dot_product(d, n);
00247 vgl_vector_3d<double> e = E - A;
00248 double e_dot = dot_product(e, n);
00249
00250 if (vcl_abs(d_dot) < vcl_sqrt(
00251 vcl_numeric_limits<double>::epsilon()) *
00252 vcl_max(1.0e-100, vcl_max(vcl_sqrt(A.x()*A.x()+A.y()*A.y()+A.z()*A.z()),
00253 vcl_sqrt(D.x()*D.x()+D.y()*D.y()+D.z()*D.z()) ) ) )
00254 {
00255 return Coplanar;
00256 }
00257
00258 if (d_dot * e_dot >= 0)
00259 return Skew;
00260 else
00261 return None;
00262 }
00263
00264
00265
00266
00267
00268
00269 vgl_triangle_3d_intersection_t vgl_triangle_3d_line_intersection(
00270 const vgl_line_segment_3d<double>& line,
00271 const vgl_point_3d<double>& p1,
00272 const vgl_point_3d<double>& p2,
00273 const vgl_point_3d<double>& p3,
00274 vgl_point_3d<double>& i_pnt,
00275 bool ignore_coplanar)
00276 {
00277 vgl_point_3d<double> line_p1 = line.point1();
00278 vgl_point_3d<double> line_p2 = line.point2();
00279
00280
00281 if (line_p1 == line_p2)
00282 {
00283 if (!ignore_coplanar && vgl_triangle_3d_test_inside(line_p1,p1,p2,p3))
00284 return Coplanar;
00285
00286 return None;
00287 }
00288
00289 if (collinear(p1,p2,p3))
00290 {
00291 if (p1==p2&&p2==p3&&p1==p3)
00292 {
00293 return !ignore_coplanar && line.contains(p1) ? Coplanar : None;
00294 }
00295
00296 vgl_line_3d_2_points<double> i_line(line_p1,line_p2);
00297 if ( !ignore_coplanar && (
00298 ( p1!=p2 && concurrent(vgl_line_3d_2_points<double>(p1,p2), i_line) &&
00299 vgl_intersection(line,vgl_line_segment_3d<double>(p1,p2),i_pnt) ) ||
00300 ( p2!=p3 && concurrent(vgl_line_3d_2_points<double>(p2,p3), i_line) &&
00301 vgl_intersection(line,vgl_line_segment_3d<double>(p2,p3),i_pnt) ) ||
00302 ( p1!=p3 && concurrent(vgl_line_3d_2_points<double>(p1,p3), i_line) &&
00303 vgl_intersection(line,vgl_line_segment_3d<double>(p1,p3),i_pnt) ) ) )
00304 {
00305 return Coplanar;
00306 }
00307
00308 return None;
00309 }
00310
00311 vgl_triangle_3d_intersection_t rv1 = same_side(line.point1(), p1, p2, p3, line.point2());
00312 if (rv1 == None) return None;
00313
00314 vgl_triangle_3d_intersection_t rv2 = same_side(line.point1(), p2, p3, p1, line.point2());
00315 if (rv2 == None) return None;
00316
00317 vgl_triangle_3d_intersection_t rv3 = same_side(line.point1(), p3, p1, p2, line.point2());
00318 if (rv3 == None) return None;
00319
00320 if (rv1 == Coplanar || rv2 == Coplanar || rv3==Coplanar)
00321 {
00322 if (ignore_coplanar)
00323 return None;
00324
00325
00326
00327
00328 vgl_line_3d_2_points<double> i_line(line_p1,line_p2);
00329 vgl_line_segment_3d<double> edge1(p1,p2);
00330
00331 vgl_point_3d<double> test_pt;
00332 if (concurrent(vgl_line_3d_2_points<double>(p1,p2),i_line) &&
00333 vgl_intersection(edge1,line,test_pt))
00334 {
00335 i_pnt = test_pt;
00336 return Coplanar;
00337 }
00338 vgl_line_segment_3d<double> edge2(p1,p3);
00339 if (concurrent(vgl_line_3d_2_points<double>(p1,p3),i_line) &&
00340 vgl_intersection(edge2,line,test_pt))
00341 {
00342 i_pnt = test_pt;
00343 return Coplanar;
00344 }
00345 vgl_line_segment_3d<double> edge3(p2,p3);
00346 if (concurrent(vgl_line_3d_2_points<double>(p2,p3),i_line) &&
00347 vgl_intersection(edge3,line,test_pt))
00348 {
00349 i_pnt = test_pt;
00350 return Coplanar;
00351 }
00352
00353
00354 if (vgl_triangle_3d_test_inside(line_p2, p1, p2, p3))
00355 {
00356 i_pnt.set(vgl_nan, vgl_nan, vgl_nan);
00357 return Coplanar;
00358 }
00359
00360 return None;
00361 }
00362
00363 if (same_side(p1, p2, p3, line_p1, line_p2) == Skew)
00364 return None;
00365
00366 i_pnt = vgl_intersection(vgl_line_3d_2_points<double>(line_p1, line_p2),
00367 vgl_plane_3d<double>(p1, p2, p3) );
00368 return Skew;
00369 }
00370
00371
00372 #ifndef UINT_MAX
00373 #define UINT_MAX 0xffffffffU
00374 #endif
00375 namespace
00376 {
00377 static const unsigned calc_edge_index_lookup[8] = {UINT_MAX, 0, 2, 0, UINT_MAX, 1, 2, 1};
00378
00379
00380
00381 inline unsigned calc_edge_index(unsigned v, unsigned w)
00382 {
00383 unsigned lookup = v*3u + w;
00384 assert (lookup < 8);
00385 unsigned edge = calc_edge_index_lookup[lookup];
00386 assert (edge < 3);
00387 return edge;
00388 }
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 vgl_triangle_3d_intersection_t vgl_triangle_3d_triangle_intersection(
00402 const vgl_point_3d<double>& a_p1,
00403 const vgl_point_3d<double>& a_p2,
00404 const vgl_point_3d<double>& a_p3,
00405 const vgl_point_3d<double>& b_p1,
00406 const vgl_point_3d<double>& b_p2,
00407 const vgl_point_3d<double>& b_p3,
00408 vgl_line_segment_3d<double>& i_line,
00409 unsigned &i_line_point1_edge,
00410 unsigned &i_line_point2_edge
00411 )
00412 {
00413
00414
00415
00416
00417 if (collinear(a_p1,a_p2,a_p3))
00418 {
00419 if (a_p1 == a_p2 && a_p2==a_p3)
00420 {
00421 if (vgl_triangle_3d_test_inside(a_p1,b_p1,b_p2,b_p3))
00422 {
00423 i_line_point1_edge = i_line_point2_edge = 0;
00424 i_line.set(a_p1,a_p1);
00425 return Coplanar;
00426 }
00427 return None;
00428 }
00429
00430 vgl_triangle_3d_intersection_t ret = None;
00431 vgl_point_3d<double> i_pnt;
00432 unsigned tmp_iline_edges[2];
00433 unsigned n_tmp_iline_edges = 0;
00434 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 )
00435 {
00436 i_line.set(i_pnt,i_pnt);
00437 if (ret == Coplanar)
00438 {
00439 i_line_point1_edge = i_line_point2_edge = 0;
00440 return ret;
00441 }
00442 tmp_iline_edges[0] = 0;
00443 n_tmp_iline_edges = 1;
00444 }
00445 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 )
00446 {
00447 i_line.set(i_pnt,i_pnt);
00448 if (ret == Coplanar)
00449 {
00450 i_line_point1_edge = i_line_point2_edge = 1;
00451 return ret;
00452 }
00453 tmp_iline_edges[n_tmp_iline_edges] = 1;
00454 n_tmp_iline_edges++;
00455 }
00456 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 )
00457 {
00458 i_line.set(i_pnt,i_pnt);
00459 if (ret == Coplanar)
00460 {
00461 i_line_point1_edge = i_line_point2_edge = 2;
00462 return ret;
00463 }
00464 if (n_tmp_iline_edges >= 2)
00465 {
00466 i_line_point1_edge = i_line_point2_edge = 0;
00467 return ret;
00468 }
00469 tmp_iline_edges[n_tmp_iline_edges] = 2;
00470 n_tmp_iline_edges++;
00471 }
00472 if (!n_tmp_iline_edges) return None;
00473 if (n_tmp_iline_edges == 1)
00474 {
00475 i_line_point1_edge = i_line_point2_edge = tmp_iline_edges[0];
00476 return Skew;
00477 }
00478
00479 i_line_point1_edge = tmp_iline_edges[0];
00480 i_line_point2_edge = tmp_iline_edges[1];
00481 return Skew;
00482 }
00483 if (collinear(b_p1,b_p2,b_p3))
00484 {
00485 if (b_p1 == b_p2 && b_p2==b_p3 && b_p1 == b_p3)
00486 {
00487 if (vgl_triangle_3d_test_inside(b_p1,a_p1,a_p2,a_p3))
00488 {
00489 i_line_point1_edge = i_line_point2_edge = 3;
00490 i_line.set(b_p1,b_p1);
00491 return Coplanar;
00492 }
00493 return None;
00494 }
00495
00496 vgl_triangle_3d_intersection_t ret = None;
00497 vgl_point_3d<double> i_pnt;
00498 unsigned tmp_iline_edges[2];
00499 unsigned n_tmp_iline_edges = 0;
00500 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 )
00501 {
00502 i_line.set(i_pnt,i_pnt);
00503 if (ret == Coplanar)
00504 {
00505 i_line_point1_edge = i_line_point2_edge = 3;
00506 return ret;
00507 }
00508 tmp_iline_edges[0] = 3;
00509 n_tmp_iline_edges = 1;
00510 }
00511 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 )
00512 {
00513 i_line.set(i_pnt,i_pnt);
00514 if (ret == Coplanar)
00515 {
00516 i_line_point1_edge = i_line_point2_edge = 4;
00517 return ret;
00518 }
00519 tmp_iline_edges[n_tmp_iline_edges] = 4;
00520 n_tmp_iline_edges++;
00521 }
00522 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 )
00523 {
00524 i_line.set(i_pnt,i_pnt);
00525 if (ret == Coplanar)
00526 {
00527 i_line_point1_edge = i_line_point2_edge = 5;
00528 return ret;
00529 }
00530 if (n_tmp_iline_edges >= 2)
00531 {
00532 i_line_point1_edge = i_line_point2_edge = 3;
00533 return ret;
00534 }
00535 tmp_iline_edges[n_tmp_iline_edges] = 5;
00536 n_tmp_iline_edges++;
00537 }
00538 if (!n_tmp_iline_edges) return None;
00539 if (n_tmp_iline_edges == 1)
00540 {
00541 i_line_point1_edge = i_line_point2_edge = tmp_iline_edges[0];
00542 return Skew;
00543 }
00544
00545 i_line_point1_edge = tmp_iline_edges[0];
00546 i_line_point2_edge = tmp_iline_edges[1];
00547 return Skew;
00548 }
00549
00550
00551
00552 vgl_vector_3d<double> edge1,edge2;
00553 vgl_vector_3d<double> a_norm, b_norm, int_line;
00554
00555 double a_d, b_d;
00556 double d_b[3], d_a[3];
00557 double d_b1d_b2, d_b1d_b3, d_a1d_a2, d_a1d_a3;
00558
00559 double p_a[3];
00560 double p_b[3];
00561 bool coplanar = false;
00562
00563 double TRI_TRI_EPS = 1000000*vcl_numeric_limits<double>::epsilon();
00564
00565
00566
00567
00568
00569 edge1 = a_p2 - a_p1;
00570 edge2 = a_p3 - a_p1;
00571
00572 a_norm = normalized(cross_product(edge1, edge2));
00573 a_d = -( a_norm.x()*a_p1.x() + a_norm.y()*a_p1.y() +a_norm.z()*a_p1.z() );
00574
00575
00576
00577 d_b[0] = ( a_norm.x()*b_p1.x() + a_norm.y()*b_p1.y() + a_norm.z()*b_p1.z() ) + a_d;
00578 d_b[1] = ( a_norm.x()*b_p2.x() + a_norm.y()*b_p2.y() + a_norm.z()*b_p2.z() ) + a_d;
00579 d_b[2] = ( a_norm.x()*b_p3.x() + a_norm.y()*b_p3.y() + a_norm.z()*b_p3.z() ) + a_d;
00580 #if 0
00581 d_b[0] = (a_plane.nx()*b_p1.x() + a_plane.ny()*b_p1.y() + a_plane.nz()*b_p1.z() ) + a_plane.d();
00582 d_b[1] = (a_plane.nx()*b_p2.x() + a_plane.ny()*b_p2.y() + a_plane.nz()*b_p2.z() ) + a_plane.d();
00583 d_b[2] = (a_plane.nx()*b_p3.x() + a_plane.ny()*b_p3.y() + a_plane.nz()*b_p3.z() ) + a_plane.d();
00584 #endif // 0
00585
00586
00587 if (vcl_fabs(d_b[0]) < TRI_TRI_EPS) d_b[0] = 0.0;
00588 if (vcl_fabs(d_b[1]) < TRI_TRI_EPS) d_b[1] = 0.0;
00589 if (vcl_fabs(d_b[2]) < TRI_TRI_EPS) d_b[2] = 0.0;
00590
00591 d_b1d_b2 = d_b[0]*d_b[1];
00592 d_b1d_b3 = d_b[0]*d_b[2];
00593
00594
00595 if (d_b1d_b2 > 0 && d_b1d_b3 > 0)
00596 {
00597 return None;
00598 }
00599
00600
00601 edge1 = b_p2 - b_p1;
00602 edge2 = b_p3 - b_p1;
00603
00604 b_norm = normalized(cross_product(edge1,edge2));
00605 b_d = -( b_norm.x()*b_p1.x() + b_norm.y()*b_p1.y() + b_norm.z()*b_p1.z() );
00606
00607
00608
00609 d_a[0] = ( b_norm.x()*a_p1.x() + b_norm.y()*a_p1.y() + b_norm.z()*a_p1.z() ) + b_d;
00610 d_a[1] = ( b_norm.x()*a_p2.x() + b_norm.y()*a_p2.y() + b_norm.z()*a_p2.z() ) + b_d;
00611 d_a[2] = ( b_norm.x()*a_p3.x() + b_norm.y()*a_p3.y() + b_norm.z()*a_p3.z() ) + b_d;
00612 #if 0
00613 d_a[0] = (b_plane.nx()*a_p1.x() + b_plane.ny()*a_p1.y() + b_plane.nz()*a_p1.z() ) + b_plane.d();
00614 d_a[1] = (b_plane.nx()*a_p2.x() + b_plane.ny()*a_p2.y() + b_plane.nz()*a_p2.z() ) + b_plane.d();
00615 d_a[2] = (b_plane.nx()*a_p3.x() + b_plane.ny()*a_p3.y() + b_plane.nz()*a_p3.z() ) + b_plane.d();
00616 #endif // 0
00617
00618
00619 if (vcl_fabs(d_a[0]) < TRI_TRI_EPS) d_a[0] = 0.0;
00620 if (vcl_fabs(d_a[1]) < TRI_TRI_EPS) d_a[1] = 0.0;
00621 if (vcl_fabs(d_a[2]) < TRI_TRI_EPS) d_a[2] = 0.0;
00622
00623 d_a1d_a2 = d_a[0]*d_a[1];
00624 d_a1d_a3 = d_a[0]*d_a[2];
00625
00626
00627 if (d_a1d_a2 > 0 && d_a1d_a3 > 0)
00628 {
00629 return None;
00630 }
00631
00632
00633
00634
00635
00636
00637
00638 int_line = cross_product(a_norm,b_norm);
00639
00640
00641
00642
00643 int_line.set(vcl_fabs(int_line.x()),vcl_fabs(int_line.y()),vcl_fabs(int_line.z()));
00644
00645 if (int_line.y()>=int_line.x() && int_line.y()>=int_line.z())
00646 {
00647 p_a[0] = a_p1.y();
00648 p_a[1] = a_p2.y();
00649 p_a[2] = a_p3.y();
00650
00651 p_b[0] = b_p1.y();
00652 p_b[1] = b_p2.y();
00653 p_b[2] = b_p3.y();
00654 }
00655 else if (int_line.x()>=int_line.y() && int_line.x()>=int_line.z())
00656 {
00657 p_a[0] = a_p1.x();
00658 p_a[1] = a_p2.x();
00659 p_a[2] = a_p3.x();
00660
00661 p_b[0] = b_p1.x();
00662 p_b[1] = b_p2.x();
00663 p_b[2] = b_p3.x();
00664 }
00665 else {
00666 p_a[0] = a_p1.z();
00667 p_a[1] = a_p2.z();
00668 p_a[2] = a_p3.z();
00669
00670 p_b[0] = b_p1.z();
00671 p_b[1] = b_p2.z();
00672 p_b[2] = b_p3.z();
00673 }
00674
00675 int a_ival[3] = {0,1,2};
00676
00677
00678
00679 if (d_a1d_a2 > 0)
00680 {
00681 a_ival[0] = 2;
00682 a_ival[1] = 0;
00683 a_ival[2] = 1;
00684 }
00685 else if (d_a1d_a3 > 0)
00686 {
00687 a_ival[0] = 1;
00688 a_ival[1] = 0;
00689 a_ival[2] = 2;
00690 }
00691 else if (d_a[1]*d_a[2] > 0 || d_a[0] != 0)
00692 {
00693 a_ival[0] = 0;
00694 a_ival[1] = 1;
00695 a_ival[2] = 2;
00696 }
00697 else if (d_a[1] != 0)
00698 {
00699 a_ival[0] = 1;
00700 a_ival[1] = 0;
00701 a_ival[2] = 2;
00702 }
00703 else if (d_a[2] != 0)
00704 {
00705 a_ival[0] = 2;
00706 a_ival[1] = 0;
00707 a_ival[2] = 1;
00708 }
00709 else
00710 {
00711
00712 coplanar = true;
00713 }
00714
00715 int b_ival[3] = {0,1,2};
00716 if (!coplanar)
00717 {
00718
00719 if (d_b1d_b2 > 0)
00720 {
00721 b_ival[0] = 2;
00722 b_ival[1] = 0;
00723 b_ival[2] = 1;
00724 }
00725 else if (d_b1d_b3 > 0)
00726 {
00727 b_ival[0] = 1;
00728 b_ival[1] = 0;
00729 b_ival[2] = 2;
00730 }
00731 else if (d_b[1]*d_b[2] > 0 || d_b[0] != 0)
00732 {
00733 b_ival[0] = 0;
00734 b_ival[1] = 1;
00735 b_ival[2] = 2;
00736 }
00737 else if (d_b[1] != 0)
00738 {
00739 b_ival[0] = 1;
00740 b_ival[1] = 0;
00741 b_ival[2] = 2;
00742 }
00743 else if (d_b[2] != 0)
00744 {
00745 b_ival[0] = 2;
00746 b_ival[1] = 0;
00747 b_ival[2] = 1;
00748 }
00749 else
00750 {
00751 coplanar = true;
00752 }
00753 }
00754
00755
00756 if (coplanar)
00757 {
00758
00759 vgl_point_3d<double> i_pnt1, i_pnt2, i_pnt3;
00760 bool isect1 = vgl_triangle_3d_line_intersection(
00761 vgl_line_segment_3d<double>(a_p1,a_p2), b_p1, b_p2, b_p3, i_pnt1) != None;
00762 bool isect2 = vgl_triangle_3d_line_intersection(
00763 vgl_line_segment_3d<double>(a_p2,a_p3), b_p1, b_p2, b_p3, i_pnt2) != None;
00764 bool isect3 = vgl_triangle_3d_line_intersection(
00765 vgl_line_segment_3d<double>(a_p3,a_p1), b_p1, b_p2, b_p3, i_pnt3) != None;
00766
00767 if ( isect1 || isect2 || isect3 )
00768 {
00769 vgl_point_3d<double> i_line_point1, i_line_point2;
00770 if (isect1)
00771 {
00772 i_line_point1 = i_pnt1;
00773 i_line_point1_edge = i_line_point2_edge = 0;
00774 }
00775 else
00776 {
00777 if (isect2)
00778 {
00779 i_line_point1 = i_pnt2;
00780 i_line_point1_edge = i_line_point2_edge = 1;
00781 }
00782 else
00783 {
00784 i_line_point1 = i_pnt3;
00785 i_line_point1_edge = i_line_point2_edge = 2;
00786 }
00787 }
00788
00789 if (isect1 && isect2)
00790 i_line_point2 = i_pnt2;
00791 else if ((isect1 || isect2) && isect3)
00792 i_line_point2 = i_pnt3;
00793 else
00794 {
00795 if (isect1)
00796 i_line_point2 = i_pnt1;
00797 else
00798 {
00799 if (isect2)
00800 i_line_point2 = i_pnt2;
00801 else
00802 i_line_point2 = i_pnt3;
00803 }
00804 }
00805 i_line.set( i_line_point1, i_line_point2);
00806 return Coplanar;
00807 }
00808
00809
00810 if (vgl_triangle_3d_test_inside(a_p1, b_p1, b_p2, b_p3))
00811 {
00812 i_line_point1_edge = i_line_point2_edge = 0;
00813 i_line.set(a_p1, a_p3);
00814 return Coplanar;
00815 }
00816
00817 if (vgl_triangle_3d_test_inside(b_p1, a_p1, a_p2, a_p3))
00818 {
00819 i_line_point1_edge = i_line_point2_edge = 3;
00820 i_line.set(b_p1, b_p3);
00821 return Coplanar;
00822 }
00823
00824 return None;
00825 }
00826
00827 vgl_point_3d<double> i_pnts[4];
00828 double isect_a[2];
00829
00830 double tmp = d_a[a_ival[0]]/(d_a[a_ival[0]]-d_a[a_ival[1]]);
00831 isect_a[0] = p_a[a_ival[0]] + (p_a[a_ival[1]] - p_a[a_ival[0]])*tmp;
00832 vgl_point_3d<double> a_vs[] = {a_p1,a_p2,a_p3};
00833 vgl_vector_3d<double> diff = a_vs[a_ival[1]] - a_vs[a_ival[0]];
00834 diff *= tmp;
00835 i_pnts[0] = a_vs[a_ival[0]] + diff ;
00836
00837 tmp = d_a[a_ival[0]]/(d_a[a_ival[0]]-d_a[a_ival[2]]);
00838 isect_a[1] = p_a[a_ival[0]] + (p_a[a_ival[2]] - p_a[a_ival[0]])*tmp;
00839 diff = a_vs[a_ival[2]] - a_vs[a_ival[0]];
00840 diff *= tmp;
00841 i_pnts[1] = a_vs[a_ival[0]] + diff;
00842
00843 double isect_b[2];
00844
00845 tmp = d_b[b_ival[0]]/(d_b[b_ival[0]] - d_b[b_ival[1]]);
00846 isect_b[0] = p_b[b_ival[0]] + (p_b[b_ival[1]] - p_b[b_ival[0]])*tmp;
00847 vgl_point_3d<double> b_vs[] = {b_p1,b_p2,b_p3};
00848 diff = b_vs[b_ival[1]] - b_vs[b_ival[0]];
00849 diff *= tmp;
00850 i_pnts[2] = b_vs[b_ival[0]] + diff;
00851
00852 tmp = d_b[b_ival[0]]/(d_b[b_ival[0]]-d_b[b_ival[2]]);
00853 isect_b[1] = p_b[b_ival[0]] + (p_b[b_ival[2]] - p_b[b_ival[0]])*tmp;
00854 diff = b_vs[b_ival[2]] - b_vs[b_ival[0]];
00855 diff *= tmp;
00856 i_pnts[3] = b_vs[b_ival[0]] + diff;
00857
00858 unsigned smallest1 = 0;
00859 if (isect_a[0] > isect_a[1])
00860 {
00861 vcl_swap(isect_a[0], isect_a[1]);
00862 smallest1 = 1;
00863 }
00864 unsigned smallest2 = 0;
00865 if (isect_b[0] > isect_b[1])
00866 {
00867 vcl_swap(isect_b[0], isect_b[1]);
00868 smallest2 = 1;
00869 }
00870
00871 if (isect_a[1] < isect_b[0] || isect_b[1] < isect_a[0])
00872 {
00873 return None;
00874 }
00875
00876 unsigned i_pt1,i_pt2;
00877
00878 if (isect_b[0]<isect_a[0])
00879 {
00880 if (smallest1==0)
00881 {
00882 i_pt1 = 0;
00883 i_line_point1_edge = calc_edge_index(a_ival[0], a_ival[1]);
00884 }
00885 else
00886 {
00887 i_pt1 = 1;
00888 i_line_point1_edge = calc_edge_index(a_ival[0], a_ival[2]);
00889 }
00890
00891 if (isect_b[1]<isect_a[1])
00892 {
00893 if (smallest2==0)
00894 {
00895 i_pt2 = 3;
00896 i_line_point2_edge = calc_edge_index(b_ival[0], b_ival[2]) + 3;
00897 }
00898 else
00899 {
00900 i_pt2 = 2;
00901 i_line_point2_edge = calc_edge_index(b_ival[0], b_ival[1]) + 3;
00902 }
00903 }
00904 else
00905 {
00906 if (smallest1==0)
00907 {
00908 i_pt2 = 1;
00909 i_line_point2_edge = calc_edge_index(a_ival[0], a_ival[2]);
00910 }
00911 else
00912 {
00913 i_pt2 = 0;
00914 i_line_point2_edge = calc_edge_index(a_ival[0], a_ival[1]);
00915 }
00916 }
00917 }
00918 else
00919 {
00920 if (smallest2==0)
00921 {
00922 i_pt1 = 2;
00923 i_line_point1_edge = calc_edge_index(b_ival[0], b_ival[1]) + 3;
00924 }
00925 else
00926 {
00927 i_pt1 = 3;
00928 i_line_point1_edge = calc_edge_index(b_ival[0], b_ival[2]) + 3;
00929 }
00930
00931 if (isect_b[1]>isect_a[1])
00932 {
00933 if (smallest1==0)
00934 {
00935 i_pt2 = 1;
00936 i_line_point2_edge = calc_edge_index(a_ival[0], a_ival[2]);
00937 }
00938 else
00939 {
00940 i_pt2 = 0;
00941 i_line_point2_edge = calc_edge_index(a_ival[0], a_ival[1]);
00942 }
00943 }
00944 else
00945 {
00946 if (smallest2==0)
00947 {
00948 i_pt2 = 3;
00949 i_line_point2_edge = calc_edge_index(b_ival[0], b_ival[2]) + 3;
00950 }
00951 else
00952 {
00953 i_pt2 = 2;
00954 i_line_point2_edge = calc_edge_index(b_ival[0], b_ival[1]) + 3;
00955 }
00956 }
00957 }
00958
00959 i_line.set(i_pnts[i_pt1],i_pnts[i_pt2]);
00960 return Skew;
00961 }
00962
00963
00964
00965
00966
00967
00968 vgl_triangle_3d_intersection_t vgl_triangle_3d_triangle_intersection(
00969 const vgl_point_3d<double>& a_p1,
00970 const vgl_point_3d<double>& a_p2,
00971 const vgl_point_3d<double>& a_p3,
00972 const vgl_point_3d<double>& b_p1,
00973 const vgl_point_3d<double>& b_p2,
00974 const vgl_point_3d<double>& b_p3,
00975 vgl_line_segment_3d<double>& i_line)
00976 {
00977 unsigned iline_p1, iline_p2;
00978 return vgl_triangle_3d_triangle_intersection(
00979 a_p1, a_p2, a_p3,
00980 b_p1, b_p2, b_p3,
00981 i_line, iline_p1, iline_p2);
00982 }
00983
00984
00985
00986
00987
00988
00989 vgl_triangle_3d_intersection_t vgl_triangle_3d_triangle_intersection(
00990 const vgl_point_3d<double>& a_p1,
00991 const vgl_point_3d<double>& a_p2,
00992 const vgl_point_3d<double>& a_p3,
00993 const vgl_point_3d<double>& b_p1,
00994 const vgl_point_3d<double>& b_p2,
00995 const vgl_point_3d<double>& b_p3)
00996 {
00997
00998
00999
01000
01001 if (collinear(a_p1,a_p2,a_p3))
01002 {
01003 if (a_p1 == a_p2 && a_p2==a_p3 && a_p1 == a_p3)
01004 {
01005 if (vgl_triangle_3d_test_inside(a_p1,b_p1,b_p2,b_p3))
01006 return Coplanar;
01007 return None;
01008 }
01009
01010 vgl_triangle_3d_intersection_t ret = None;
01011 vgl_point_3d<double> i_pnt;
01012 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 ) ||
01013 ( 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 ) ||
01014 ( 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 ) )
01015 return ret;
01016
01017 return None;
01018 }
01019 if (collinear(b_p1,b_p2,b_p3))
01020 {
01021 if (b_p1 == b_p2 && b_p2==b_p3 && b_p1 == b_p3)
01022 {
01023 if (vgl_triangle_3d_test_inside(b_p1,a_p1,a_p2,a_p3))
01024 return Coplanar;
01025 return None;
01026 }
01027
01028 vgl_triangle_3d_intersection_t ret = None;
01029 vgl_point_3d<double> i_pnt;
01030 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 ) ||
01031 ( 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 ) ||
01032 ( 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 ) )
01033 return ret;
01034
01035 return None;
01036 }
01037
01038
01039
01040 vgl_vector_3d<double> edge1,edge2;
01041 vgl_vector_3d<double> a_norm, b_norm, int_line;
01042
01043
01044 double a_d, b_d;
01045 double d_b1, d_b2, d_b3, d_a1, d_a2, d_a3;
01046 double isect1[2], isect2[2];
01047 double d_b1d_b2, d_b1d_b3, d_a1d_a2, d_a1d_a3;
01048
01049 double p_a1, p_a2, p_a3;
01050 double p_b1, p_b2, p_b3;
01051 bool coplanar = false;
01052
01053 double a=0.0, b=0.0, c=0.0, x0=0.0, x1=0.0;
01054 double d=0.0, e=0.0, f=0.0, y0=0.0, y1=0.0;
01055 double xx, yy, xxyy, tmp;
01056 double TRI_TRI_EPS = 100000*vcl_numeric_limits<double>::epsilon();
01057
01058
01059
01060
01061
01062 edge1 = a_p2 - a_p1;
01063 edge2 = a_p3 - a_p1;
01064
01065 a_norm = normalized(cross_product(edge1, edge2));
01066
01067 a_d = -( a_norm.x()*a_p1.x() + a_norm.y()*a_p1.y() +a_norm.z()*a_p1.z() );
01068
01069
01070
01071 d_b1 = ( a_norm.x()*b_p1.x() + a_norm.y()*b_p1.y() + a_norm.z()*b_p1.z() ) + a_d;
01072 d_b2 = ( a_norm.x()*b_p2.x() + a_norm.y()*b_p2.y() + a_norm.z()*b_p2.z() ) + a_d;
01073 d_b3 = ( a_norm.x()*b_p3.x() + a_norm.y()*b_p3.y() + a_norm.z()*b_p3.z() ) + a_d;
01074 #if 0
01075 d_b1 = (a_plane.nx()*b_p1.x() + a_plane.ny()*b_p1.y() + a_plane.nz()*b_p1.z() ) + a_plane.d();
01076 d_b2 = (a_plane.nx()*b_p2.x() + a_plane.ny()*b_p2.y() + a_plane.nz()*b_p2.z() ) + a_plane.d();
01077 d_b3 = (a_plane.nx()*b_p3.x() + a_plane.ny()*b_p3.y() + a_plane.nz()*b_p3.z() ) + a_plane.d();
01078 #endif // 0
01079
01080
01081 if (vcl_fabs(d_b1) < TRI_TRI_EPS) d_b1 = 0.0;
01082 if (vcl_fabs(d_b2) < TRI_TRI_EPS) d_b2 = 0.0;
01083 if (vcl_fabs(d_b3) < TRI_TRI_EPS) d_b3 = 0.0;
01084
01085 d_b1d_b2 = d_b1*d_b2;
01086 d_b1d_b3 = d_b1*d_b3;
01087
01088
01089 if (d_b1d_b2 > 0 && d_b1d_b3 > 0)
01090 {
01091 return None;
01092 }
01093
01094
01095 edge1 = b_p2 - b_p1;
01096 edge2 = b_p3 - b_p1;
01097
01098 b_norm = normalized(cross_product(edge1,edge2));
01099
01100 b_d = -( b_norm.x()*b_p1.x() + b_norm.y()*b_p1.y() + b_norm.z()*b_p1.z() );
01101
01102
01103
01104 d_a1 = ( b_norm.x()*a_p1.x() + b_norm.y()*a_p1.y() + b_norm.z()*a_p1.z() ) + b_d;
01105 d_a2 = ( b_norm.x()*a_p2.x() + b_norm.y()*a_p2.y() + b_norm.z()*a_p2.z() ) + b_d;
01106 d_a3 = ( b_norm.x()*a_p3.x() + b_norm.y()*a_p3.y() + b_norm.z()*a_p3.z() ) + b_d;
01107 #if 0
01108 d_a1 = (b_plane.nx()*a_p1.x() + b_plane.ny()*a_p1.y() + b_plane.nz()*a_p1.z() ) + b_plane.d();
01109 d_a2 = (b_plane.nx()*a_p2.x() + b_plane.ny()*a_p2.y() + b_plane.nz()*a_p2.z() ) + b_plane.d();
01110 d_a3 = (b_plane.nx()*a_p3.x() + b_plane.ny()*a_p3.y() + b_plane.nz()*a_p3.z() ) + b_plane.d();
01111 #endif // 0
01112
01113
01114 if (vcl_fabs(d_a1) < TRI_TRI_EPS) d_a1 = 0.0;
01115 if (vcl_fabs(d_a2) < TRI_TRI_EPS) d_a2 = 0.0;
01116 if (vcl_fabs(d_a3) < TRI_TRI_EPS) d_a3 = 0.0;
01117
01118 d_a1d_a2 = d_a1*d_a2;
01119 d_a1d_a3 = d_a1*d_a3;
01120
01121
01122 if (d_a1d_a2 > 0 && d_a1d_a3 > 0)
01123 {
01124 return None;
01125 }
01126
01127
01128
01129
01130
01131
01132
01133 int_line = cross_product(a_norm,b_norm);
01134
01135
01136
01137
01138 int_line.set(vcl_fabs(int_line.x()),vcl_fabs(int_line.y()),vcl_fabs(int_line.z()));
01139
01140 if (int_line.y()>=int_line.x() && int_line.y()>=int_line.z())
01141 {
01142 p_a1 = a_p1.y();
01143 p_a2 = a_p2.y();
01144 p_a3 = a_p3.y();
01145
01146 p_b1 = b_p1.y();
01147 p_b2 = b_p2.y();
01148 p_b3 = b_p3.y();
01149 }
01150 else if (int_line.x()>=int_line.y() && int_line.x()>=int_line.z())
01151 {
01152 p_a1 = a_p1.x();
01153 p_a2 = a_p2.x();
01154 p_a3 = a_p3.x();
01155
01156 p_b1 = b_p1.x();
01157 p_b2 = b_p2.x();
01158 p_b3 = b_p3.x();
01159 }
01160 else {
01161 p_a1 = a_p1.z();
01162 p_a2 = a_p2.z();
01163 p_a3 = a_p3.z();
01164
01165 p_b1 = b_p1.z();
01166 p_b2 = b_p2.z();
01167 p_b3 = b_p3.z();
01168 }
01169
01170
01171 if (d_a1d_a2 > 0)
01172 {
01173 a = p_a3;
01174 b = (p_a1-p_a3)*d_a3;
01175 c = (p_a2-p_a3)*d_a3;
01176
01177 x0 = d_a3-d_a1;
01178 x1 = d_a3-d_a2;
01179 }
01180 else if (d_a1d_a3 > 0)
01181 {
01182 a = p_a2;
01183 b = (p_a1-p_a2)*d_a2;
01184 c = (p_a3-p_a2)*d_a2;
01185
01186 x0 = d_a2-d_a1;
01187 x1 = d_a2-d_a3;
01188 }
01189 else if (d_a2*d_a3 > 0 || d_a1 != 0)
01190 {
01191 a = p_a1;
01192 b = (p_a2-p_a1)*d_a1;
01193 c = (p_a3-p_a1)*d_a1;
01194
01195 x0 = d_a1-d_a2;
01196 x1 = d_a1-d_a3;
01197 }
01198 else if (d_a2 != 0)
01199 {
01200 a = p_a2;
01201 b = (p_a1-p_a2)*d_a2;
01202 c = (p_a3-p_a2)*d_a2;
01203
01204 x0 = d_a2-d_a1;
01205 x1 = d_a2-d_a3;
01206 }
01207 else if (d_a3 != 0)
01208 {
01209 a = p_a3;
01210 b = (p_a1-p_a3)*d_a3;
01211 c = (p_a2-p_a3)*d_a3;
01212
01213 x0 = d_a3-d_a1;
01214 x1 = d_a3-d_a2;
01215 }
01216 else
01217 {
01218
01219 coplanar = true;
01220 }
01221
01222 if (!coplanar)
01223 {
01224
01225 if (d_b1d_b2 > 0)
01226 {
01227 d = p_b3;
01228 e = (p_b1-p_b3)*d_b3;
01229 f = (p_b2-p_b3)*d_b3;
01230
01231 y0 = d_b3-d_b1;
01232 y1 = d_b3-d_b2;
01233 }
01234 else if (d_b1d_b3 > 0)
01235 {
01236 d = p_b2;
01237 e=(p_b1-p_b2)*d_b2;
01238 f=(p_b3-p_b2)*d_b2;
01239
01240 y0=d_b2-d_b1;
01241 y1=d_b2-d_b3;
01242 }
01243 else if (d_b2*d_b3 > 0 || d_b1 != 0)
01244 {
01245 d = p_b1;
01246 e = (p_b2-p_b1)*d_b1;
01247 f = (p_b3-p_b1)*d_b1;
01248
01249 y0 = d_b1-d_b2;
01250 y1 = d_b1-d_b3;
01251 }
01252 else if (d_b2 != 0)
01253 {
01254 d = p_b2;
01255 e = (p_b1-p_b2)*d_b2;
01256 f = (p_b3-p_b2)*d_b2;
01257
01258 y0 = d_b2-d_b1;
01259 y1 = d_b2-d_b3;
01260 }
01261 else if (d_b3 != 0)
01262 {
01263 d = p_b3;
01264 e = (p_b1-p_b3)*d_b3;
01265 f = (p_b2-p_b3)*d_b3;
01266
01267 y0 = d_b3-d_b1;
01268 y1 = d_b3-d_b2;
01269 }
01270 else
01271 {
01272 coplanar = true;
01273 }
01274 }
01275
01276
01277 if (coplanar)
01278 {
01279
01280 vgl_point_3d<double> i_pnt;
01281 if (vgl_triangle_3d_line_intersection(vgl_line_segment_3d<double>(a_p1,a_p2), b_p1, b_p2, b_p3, i_pnt) ||
01282 vgl_triangle_3d_line_intersection(vgl_line_segment_3d<double>(a_p2,a_p3), b_p1, b_p2, b_p3, i_pnt) ||
01283 vgl_triangle_3d_line_intersection(vgl_line_segment_3d<double>(a_p3,a_p1), b_p1, b_p2, b_p3, i_pnt) )
01284 {
01285 return Coplanar;
01286 }
01287
01288
01289 if (vgl_triangle_3d_test_inside(a_p1, b_p1, b_p2, b_p3) ||
01290 vgl_triangle_3d_test_inside(b_p1, a_p1, a_p2, a_p3))
01291 {
01292 return Coplanar;
01293 }
01294
01295 return None;
01296 }
01297
01298
01299
01300 xx = x0*x1;
01301 yy = y0*y1;
01302 xxyy = xx*yy;
01303
01304 tmp = a*xxyy;
01305 isect1[0] = tmp+b*x1*yy;
01306 isect1[1] = tmp+c*x0*yy;
01307
01308 tmp = d*xxyy;
01309 isect2[0] = tmp+e*xx*y1;
01310 isect2[1] = tmp+f*xx*y0;
01311
01312 if (isect1[0] > isect1[1])
01313 {
01314 tmp = isect1[0];
01315 isect1[0] = isect1[1];
01316 isect1[1] = tmp;
01317 }
01318
01319 if (isect2[0] > isect2[1])
01320 {
01321 tmp = isect2[0];
01322 isect2[0] = isect2[1];
01323 isect2[1] = tmp;
01324 }
01325
01326 if (isect1[1] < isect2[0] || isect2[1] < isect1[0])
01327 {
01328 return None;
01329 }
01330
01331 return Skew;
01332 }
01333
01334
01335
01336
01337
01338
01339 vgl_triangle_3d_intersection_t vgl_triangle_3d_plane_intersection(
01340 const vgl_point_3d<double>& p1,
01341 const vgl_point_3d<double>& p2,
01342 const vgl_point_3d<double>& p3,
01343 const vgl_plane_3d<double>& i_plane,
01344 vgl_line_segment_3d<double>& i_line)
01345 {
01346
01347
01348
01349
01350 double p1_d = i_plane.nx()*p1.x() + i_plane.ny()*p1.y() + i_plane.nz()*p1.z() + i_plane.d();
01351 double p2_d = i_plane.nx()*p2.x() + i_plane.ny()*p2.y() + i_plane.nz()*p2.z() + i_plane.d();
01352 double p3_d = i_plane.nx()*p3.x() + i_plane.ny()*p3.y() + i_plane.nz()*p3.z() + i_plane.d();
01353
01354
01355 if (vcl_fabs(p1_d) < sqrteps) p1_d = 0.0;
01356 if (vcl_fabs(p2_d) < sqrteps) p2_d = 0.0;
01357 if (vcl_fabs(p3_d) < sqrteps) p3_d = 0.0;
01358
01359 vgl_line_3d_2_points<double> edge;
01360
01361 if (p1_d*p2_d > 0 && p1_d*p3_d > 0)
01362 {
01363 i_line.set(vgl_point_3d<double>(),vgl_point_3d<double>());
01364 return None;
01365 }
01366 else if (p1_d == 0 && p2_d == 0 && p3_d == 0)
01367 {
01368 vgl_point_3d<double> i_pnt1; i_pnt1.set(vgl_nan, vgl_nan, vgl_nan);
01369 i_line.set(i_pnt1,i_pnt1);
01370 return Coplanar;
01371 }
01372 else if (p1_d*p2_d > 0)
01373 {
01374 edge.set(p1,p3);
01375 vgl_point_3d<double> i_pnt1 = vgl_intersection(edge, i_plane);
01376 edge.set(p2,p3);
01377 vgl_point_3d<double> i_pnt2 = vgl_intersection(edge, i_plane);
01378 i_line.set(i_pnt1,i_pnt2);
01379 }
01380 else if (p1_d*p3_d > 0)
01381 {
01382 edge.set(p1,p2);
01383 vgl_point_3d<double> i_pnt1 = vgl_intersection(edge, i_plane);
01384 edge.set(p3,p2);
01385 vgl_point_3d<double> i_pnt2 = vgl_intersection(edge, i_plane);
01386 i_line.set(i_pnt1,i_pnt2);
01387 }
01388 else if (p2_d*p3_d > 0)
01389 {
01390 edge.set(p2,p1);
01391 vgl_point_3d<double> i_pnt1 = vgl_intersection(edge, i_plane);
01392 edge.set(p3,p1);
01393 vgl_point_3d<double> i_pnt2 = vgl_intersection(edge, i_plane);
01394 i_line.set(i_pnt1,i_pnt2);
01395 }
01396 else if (p1_d == 0 && p2_d == 0)
01397 {
01398 i_line.set(p1,p2);
01399 }
01400 else if (p1_d == 0 && p3_d == 0)
01401 {
01402 i_line.set(p1,p3);
01403 }
01404 else if (p3_d == 0 && p2_d == 0)
01405 {
01406 i_line.set(p2,p3);
01407 }
01408 else if (p1_d == 0)
01409 {
01410 edge.set(p3,p2);
01411 vgl_point_3d<double> i_pnt2 = vgl_intersection(edge, i_plane);
01412 i_line.set(p1,i_pnt2);
01413 }
01414 else if (p2_d == 0)
01415 {
01416 edge.set(p3,p1);
01417 vgl_point_3d<double> i_pnt2 = vgl_intersection(edge, i_plane);
01418 i_line.set(p2,i_pnt2);
01419 }
01420 else if (p3_d == 0)
01421 {
01422 edge.set(p2,p1);
01423 vgl_point_3d<double> i_pnt2 = vgl_intersection(edge, i_plane);
01424 i_line.set(p3,i_pnt2);
01425 }
01426 return Skew;
01427 }
01428
01429
01430
01431
01432
01433 vgl_point_3d<double> vgl_triangle_3d_closest_point(
01434 const vgl_point_3d<double>& q,
01435 const vgl_point_3d<double>& p1,
01436 const vgl_point_3d<double>& p2,
01437 const vgl_point_3d<double>& p3)
01438 {
01439
01440 if (p1 == p2)
01441 {
01442 if (p2 == p3) return p3;
01443 return vgl_closest_point(vgl_line_3d_2_points<double>(p3, p1), q);
01444 }
01445 if (p2 == p3)
01446 return vgl_closest_point(vgl_line_3d_2_points<double>(p1, p2), q);
01447 if (p3 == p1)
01448 return vgl_closest_point(vgl_line_3d_2_points<double>(p2, p3), q);
01449
01450
01451 vgl_plane_3d<double> plane = create_plane_and_ignore_degenerate(p1, p2, p3);
01452
01453
01454 vgl_point_3d<double> cp = vgl_closest_point<double>(plane, q);
01455
01456
01457 if (vgl_triangle_3d_test_inside(cp, p1, p2, p3))
01458 {
01459 return cp;
01460 }
01461 else
01462 {
01463
01464
01465
01466 double cp1x, cp1y, cp1z;
01467 vgl_closest_point_to_linesegment(
01468 cp1x, cp1y, cp1z,
01469 p1.x(), p1.y(), p1.z(),
01470 p2.x(), p2.y(), p2.z(),
01471 q.x(), q.y(), q.z());
01472 vgl_point_3d<double> cp1(cp1x, cp1y, cp1z);
01473 double d1 = vgl_distance(cp1, q);
01474
01475
01476 double cp2x, cp2y, cp2z;
01477 vgl_closest_point_to_linesegment(
01478 cp2x, cp2y, cp2z,
01479 p2.x(), p2.y(), p2.z(),
01480 p3.x(), p3.y(), p3.z(),
01481 q.x(), q.y(), q.z());
01482 vgl_point_3d<double> cp2(cp2x, cp2y, cp2z);
01483 double d2 = vgl_distance(cp2, q);
01484
01485
01486 double cp3x, cp3y, cp3z;
01487 vgl_closest_point_to_linesegment(
01488 cp3x, cp3y, cp3z,
01489 p1.x(), p1.y(), p1.z(),
01490 p3.x(), p3.y(), p3.z(),
01491 q.x(), q.y(), q.z());
01492 vgl_point_3d<double> cp3(cp3x, cp3y, cp3z);
01493 double d3 = vgl_distance(cp3, q);
01494
01495
01496 if (d1<=d2 && d1<=d3)
01497 return cp1;
01498 else if (d2<=d1 && d2<=d3)
01499 return cp2;
01500 else
01501 return cp3;
01502 }
01503 }
01504
01505
01506
01507
01508
01509 double vgl_triangle_3d_distance(const vgl_point_3d<double>& q,
01510 const vgl_point_3d<double>& p1,
01511 const vgl_point_3d<double>& p2,
01512 const vgl_point_3d<double>& p3)
01513 {
01514 vgl_point_3d<double> c = vgl_triangle_3d_closest_point(q, p1, p2, p3);
01515 return vgl_distance(c, q);
01516 }
01517
01518
01519
01520
01521
01522 bool vgl_triangle_3d_triangle_coplanar(
01523 const vgl_point_3d<double>& a_p1,
01524 const vgl_point_3d<double>& a_p2,
01525 const vgl_point_3d<double>& a_p3,
01526 const vgl_point_3d<double>& b_p1,
01527 const vgl_point_3d<double>& b_p2,
01528 const vgl_point_3d<double>& b_p3)
01529 {
01530 return coplanar(a_p1,b_p1,b_p2,b_p3)
01531 && coplanar(a_p2,b_p1,b_p2,b_p3)
01532 && coplanar(a_p3,b_p1,b_p2,b_p3);
01533 }
01534
01535
01536
01537
01538 double vgl_triangle_3d_area(const vgl_point_3d<double> &p0,
01539 const vgl_point_3d<double> &p1,
01540 const vgl_point_3d<double> &p2 )
01541 {
01542 vgl_vector_3d<double> edge_vector0;
01543 edge_vector0 = p0 - p1;
01544 vgl_vector_3d<double> edge_vector1;
01545 edge_vector1 = p0 - p2;
01546
01547 vgl_vector_3d<double> area_vector;
01548 area_vector = cross_product( edge_vector0, edge_vector1 );
01549
01550 double area;
01551 area = area_vector.length();
01552 area /= 2;
01553
01554 return area;
01555 }
01556
01557
01558
01559
01560 double vgl_triangle_3d_aspect_ratio(
01561 const vgl_point_3d<double> &p0,
01562 const vgl_point_3d<double> &p1,
01563 const vgl_point_3d<double> &p2 )
01564 {
01565 return vgl_triangle_3d_longest_side( p0, p1, p2 ) / vgl_triangle_3d_shortest_side( p0, p1, p2 );
01566 }
01567