diff --git a/AABB_tree/include/CGAL/AABB_intersections/Triangle_3_line_3_intersection.h b/AABB_tree/include/CGAL/AABB_intersections/Triangle_3_line_3_intersection.h index 59a7eb3e186..42a60254700 100644 --- a/AABB_tree/include/CGAL/AABB_intersections/Triangle_3_line_3_intersection.h +++ b/AABB_tree/include/CGAL/AABB_intersections/Triangle_3_line_3_intersection.h @@ -31,85 +31,371 @@ namespace CGAL { namespace internal { + +template +Object +t3l3_intersection_coplanar_aux(const typename K::Point_3& a, + const typename K::Point_3& b, + const typename K::Point_3& c, + const typename K::Line_3& l, + const bool negative_side, + const K& k) +{ + // This function is designed to clip pq into the triangle abc. + // Point configuration should be as follows + // + // +q + // | +a + // | + // +c | +b + // | + // +p + // + // We know that c is isolated on the negative side of pq + + typedef typename K::Point_3 Point_3; + + typename K::Intersect_3 intersection = + k.intersect_3_object(); + + typename K::Construct_line_3 line = + k.construct_line_3_object(); + + typename K::Construct_segment_3 segment = + k.construct_segment_3_object(); + + // Let's get the intersection points + Object l_bc_obj = intersection(l,line(b,c)); + const Point_3* l_bc = object_cast(&l_bc_obj); + if ( NULL == l_bc ) + { + CGAL_kernel_assertion(false); + return Object(); + } + + Object l_ca_obj = intersection(l,line(c,a)); + const Point_3* l_ca = object_cast(&l_ca_obj); + if ( NULL == l_ca ) + { + CGAL_kernel_assertion(false); + return Object(); + } + + if ( negative_side ) + return make_object(segment(*l_bc, *l_ca)); + else + return make_object(segment(*l_ca, *l_bc)); +} + + +template +Object +intersection_coplanar(const typename K::Triangle_3 &t, + const typename K::Line_3 &l, + const K & k ) +{ + + CGAL_kernel_precondition( ! k.is_degenerate_3_object()(t) ) ; + CGAL_kernel_precondition( ! k.is_degenerate_3_object()(l) ) ; + + typedef typename K::Point_3 Point_3; + + + typename K::Construct_point_on_3 point_on = + k.construct_point_on_3_object(); + + typename K::Construct_vertex_3 vertex_on = + k.construct_vertex_3_object(); + + typename K::Coplanar_orientation_3 coplanar_orientation = + k.coplanar_orientation_3_object(); + + typename K::Construct_line_3 line = + k.construct_line_3_object(); + + typename K::Construct_segment_3 segment = + k.construct_segment_3_object(); + + + const Point_3 & p = point_on(l,0); + const Point_3 & q = point_on(l,1); + + const Point_3 & A = vertex_on(t,0); + const Point_3 & B = vertex_on(t,1); + const Point_3 & C = vertex_on(t,2); + + int k0 = 0; + int k1 = 1; + int k2 = 2; + + // Determine the orientation of the triangle in the common plane + if (coplanar_orientation(A,B,C) != POSITIVE) + { + // The triangle is not counterclockwise oriented + // swap two vertices. + std::swap(k1,k2); + } + + const Point_3& a = vertex_on(t,k0); + const Point_3& b = vertex_on(t,k1); + const Point_3& c = vertex_on(t,k2); + + // Test whether the segment's supporting line intersects the + // triangle in the common plane + const Orientation pqa = coplanar_orientation(p,q,a); + const Orientation pqb = coplanar_orientation(p,q,b); + const Orientation pqc = coplanar_orientation(p,q,c); + + + switch ( pqa ) { + // ----------------------------------- + // pqa POSITIVE + // ----------------------------------- + case POSITIVE: + switch ( pqb ) { + case POSITIVE: + switch ( pqc ) { + case POSITIVE: + // the triangle lies in the positive halfspace + // defined by the segment's supporting line. + return Object(); + case NEGATIVE: + // c is isolated on the negative side + return t3l3_intersection_coplanar_aux(a,b,c,l,true,k); + case COLLINEAR: + return make_object(c); + } + + case NEGATIVE: + if ( POSITIVE == pqc ) + // b is isolated on the negative side + return t3l3_intersection_coplanar_aux(c,a,b,l,true,k); + else + // a is isolated on the positive side (here mb c could be use as + // an endpoint instead of computing an intersection is some cases) + return t3l3_intersection_coplanar_aux(b,c,a,l,false,k); + + case COLLINEAR: + switch ( pqc ) { + case POSITIVE: + return make_object(b); + case NEGATIVE: + // a is isolated on the positive side (here mb b could be use as + // an endpoint instead of computing an intersection) + return t3l3_intersection_coplanar_aux(b,c,a,l,false,k); + case COLLINEAR: + // b,c,p,q are aligned, [p,q]&[b,c] have the same direction + return make_object(segment(b,c)); + } + + default: // should not happen. + CGAL_kernel_assertion(false); + return Object(); + } + + // ----------------------------------- + // pqa NEGATIVE + // ----------------------------------- + case NEGATIVE: + switch ( pqb ) { + case POSITIVE: + if ( POSITIVE == pqc ) + // a is isolated on the negative side + return t3l3_intersection_coplanar_aux(b,c,a,l,true,k); + else + // b is isolated on the positive side (here mb c could be use as + // an endpoint instead of computing an intersection, in some cases) + return t3l3_intersection_coplanar_aux(c,a,b,l,false,k); + + case NEGATIVE: + switch ( pqc ) { + case POSITIVE: + // c is isolated on the positive side + return t3l3_intersection_coplanar_aux(a,b,c,l,false,k); + case NEGATIVE: + // the triangle lies in the negative halfspace + // defined by the segment's supporting line. + return Object(); + case COLLINEAR: + return make_object(c); + } + + case COLLINEAR: + switch ( pqc ) { + case POSITIVE: + // a is isolated on the negative side (here mb b could be use as + // an endpoint instead of computing an intersection) + return t3l3_intersection_coplanar_aux(b,c,a,l,true,k); + case NEGATIVE: + return make_object(b); + case COLLINEAR: + // b,c,p,q are aligned, [p,q]&[c,b] have the same direction + return make_object(segment(c,b)); + } + + default: // should not happen. + CGAL_kernel_assertion(false); + return Object(); + } + + // ----------------------------------- + // pqa COLLINEAR + // ----------------------------------- + case COLLINEAR: + switch ( pqb ) { + case POSITIVE: + switch ( pqc ) { + case POSITIVE: + return make_object(a); + case NEGATIVE: + // b is isolated on the positive side (here mb a could be use as + // an endpoint instead of computing an intersection) + return t3l3_intersection_coplanar_aux(c,a,b,l,false,k); + case COLLINEAR: + // a,c,p,q are aligned, [p,q]&[c,a] have the same direction + return make_object(segment(c,a)); + } + + case NEGATIVE: + switch ( pqc ) { + case POSITIVE: + // b is isolated on the negative side (here mb a could be use as + // an endpoint instead of computing an intersection) + return t3l3_intersection_coplanar_aux(c,a,b,l,true,k); + case NEGATIVE: + return make_object(a); + case COLLINEAR: + // a,c,p,q are aligned, [p,q]&[a,c] have the same direction + return make_object(segment(a,c)); + } + + case COLLINEAR: + switch ( pqc ) { + case POSITIVE: + // a,b,p,q are aligned, [p,q]&[a,b] have the same direction + return make_object(segment(a,b)); + case NEGATIVE: + // a,b,p,q are aligned, [p,q]&[b,a] have the same direction + return make_object(segment(b,a)); + case COLLINEAR: + // case pqc == COLLINEAR is impossible since the triangle is + // assumed to be non flat + CGAL_kernel_assertion(false); + return Object(); + } + + default: // should not happen. + CGAL_kernel_assertion(false); + return Object(); + + } + + default:// should not happen. + CGAL_kernel_assertion(false); + return Object(); + + } +} + + + + + + + template Object intersection(const typename K::Triangle_3 &t, const typename K::Line_3 &l, const K& k) { + CGAL_kernel_precondition( ! k.is_degenerate_3_object()(t) ) ; + CGAL_kernel_precondition( ! k.is_degenerate_3_object()(l) ) ; + typedef typename K::Point_3 Point_3; - typedef typename K::Segment_3 Segment_3; - typedef typename K::Object_3 Object_3; - typedef typename K::Line_3 Line_3; - - if ( !CGAL::do_intersect(t, l) ) - return Object_3(); - - // TOFIX: here we assume that we have already tested - // do_intersect between the triangle and the line - const Object intersection = CGAL::intersection(t.supporting_plane(), - l); - - // intersection is either a point, either a line - // if it is a line, then we need to clip it to a segment - if ( const Line_3* line = object_cast(&intersection)) + + typename K::Construct_point_on_3 point_on = + k.construct_point_on_3_object(); + + typename K::Construct_vertex_3 vertex_on = + k.construct_vertex_3_object(); + + typename K::Orientation_3 orientation = + k.orientation_3_object(); + + typename K::Coplanar_orientation_3 coplanar_orientation = + k.coplanar_orientation_3_object(); + + typename K::Intersect_3 intersection = + k.intersect_3_object(); + + const Point_3 & a = vertex_on(t,0); + const Point_3 & b = vertex_on(t,1); + const Point_3 & c = vertex_on(t,2); + const Point_3 & p = point_on(l,0); + const Point_3 & q = point_on(l,1); + + if ( ( orientation(a,b,c,p) != COPLANAR ) + || ( orientation(a,b,c,q) != COPLANAR ) ) { - typename K::Intersect_3 intersect = k.intersect_3_object(); - typename K::Construct_line_3 f_line = k.construct_line_3_object(); - typename K::Construct_vertex_3 vertex_on = k.construct_vertex_3_object(); - typename K::Construct_object_3 make_object = k.construct_object_3_object(); - typename K::Construct_segment_3 f_segment = k.construct_segment_3_object(); - typename K::Has_on_3 has_on = k.has_on_3_object(); - - const Point_3& t0 = vertex_on(t,0); - const Point_3& t1 = vertex_on(t,1); - const Point_3& t2 = vertex_on(t,2); - - const Line_3 l01 = f_line(t0,t1); - const Line_3 l02 = f_line(t0,t2); - const Line_3 l12 = f_line(t1,t2); - - const Segment_3 s01 = f_segment(t0,t1); - const Segment_3 s02 = f_segment(t0,t2); - const Segment_3 s12 = f_segment(t1,t2); - - const Object_3 inter_01 = intersect(l01,*line); - const Object_3 inter_02 = intersect(l02,*line); - const Object_3 inter_12 = intersect(l12,*line); - - const Point_3* p01 = object_cast(&inter_01); - const Point_3* p02 = object_cast(&inter_02); - const Point_3* p12 = object_cast(&inter_12); - - if ( p01 && has_on(s01, *p01) ) - { - if ( p02 && has_on(s02, *p02) ) - return make_object(f_segment(*p01,*p02)); - else if ( p12 && has_on(s12, *p12) ) - return make_object(f_segment(*p01,*p12)); - else - return make_object(*p01); + const Orientation pqab = orientation(p,q,a,b); + const Orientation pqbc = orientation(p,q,b,c); + + switch ( pqab ) { + case POSITIVE: + if ( pqbc != NEGATIVE && orientation(p,q,c,a) != NEGATIVE ) + return intersection(l,t.supporting_plane()); + else + return Object(); + + case NEGATIVE: + if ( pqbc != POSITIVE && orientation(p,q,c,a) != POSITIVE ) + return intersection(l,t.supporting_plane()); + else + return Object(); + + case COPLANAR: + switch ( pqbc ) { + case POSITIVE: + if ( orientation(p,q,c,a) != NEGATIVE ) + return intersection(l,t.supporting_plane()); + else + return Object(); + + case NEGATIVE: + if ( orientation(p,q,c,a) != POSITIVE ) + return intersection(l,t.supporting_plane()); + else + return Object(); + + case COPLANAR: // pqa or pqb or pqc are collinear + return intersection(l,t.supporting_plane()); + + default: // should not happen. + CGAL_kernel_assertion(false); + return Object(); + } + + default: // should not happen. + CGAL_kernel_assertion(false); + return Object(); } - else if ( p02 && has_on(s02, *p02) ) - { - if ( p12 && has_on(s12, *p12) ) - return make_object(f_segment(*p02,*p12)); - else - return make_object(*p02); - } - else if ( p12 && has_on(s12, *p12) ) - { - return make_object(*p12); - } - - // should not happen - CGAL_kernel_assertion(false); - return Object_3(); } - else - return intersection; + + // Coplanar case + return intersection_coplanar(t,l,k); } +template +Object +intersection(const typename K::Line_3 &l, + const typename K::Triangle_3 &t, + const K& k) +{ + return internal::intersection(t,l,k); +} + + } // end namespace internal template diff --git a/AABB_tree/include/CGAL/AABB_intersections/Triangle_3_segment_3_intersection.h b/AABB_tree/include/CGAL/AABB_intersections/Triangle_3_segment_3_intersection.h index f994c604b42..8e35ab9c582 100644 --- a/AABB_tree/include/CGAL/AABB_intersections/Triangle_3_segment_3_intersection.h +++ b/AABB_tree/include/CGAL/AABB_intersections/Triangle_3_segment_3_intersection.h @@ -174,9 +174,6 @@ intersection_coplanar(const typename K::Triangle_3 &t, typename K::Collinear_are_ordered_along_line_3 collinear_ordered = k.collinear_are_ordered_along_line_3_object(); - typename K::Intersect_3 intersection = - k.intersect_3_object(); - typename K::Construct_line_3 line = k.construct_line_3_object(); diff --git a/AABB_tree/test/AABB_tree/aabb_do_intersect_test.cpp b/AABB_tree/test/AABB_tree/aabb_do_intersect_test.cpp index ec4dcb2f88d..3c4ad48720a 100644 --- a/AABB_tree/test/AABB_tree/aabb_do_intersect_test.cpp +++ b/AABB_tree/test/AABB_tree/aabb_do_intersect_test.cpp @@ -28,6 +28,7 @@ #include #include #include +#include template @@ -175,6 +176,9 @@ int main() std::cout << "Testing with Exact_predicates_inexact_constructions_kernel..." << std::endl ; b &= test(); + + std::cout << "Testing with Exact_predicates_exact_constructions_kernel..." << std::endl ; + b &= test(); if ( b ) return EXIT_SUCCESS; diff --git a/AABB_tree/test/AABB_tree/aabb_intersection_test.cpp b/AABB_tree/test/AABB_tree/aabb_intersection_test.cpp index 87a62d94a14..41412041bed 100644 --- a/AABB_tree/test/AABB_tree/aabb_intersection_test.cpp +++ b/AABB_tree/test/AABB_tree/aabb_intersection_test.cpp @@ -77,7 +77,7 @@ bool test() // +E +1 // / \ // +C 6+ +8 +4 +B - // / +7 \ + // / 9++7 \ // 3+-------+5--+2 // // +F +A @@ -91,10 +91,14 @@ bool test() // Edges of t Segment s12(p1,p2); + Segment s21(p2,p1); Segment s13(p1,p3); Segment s23(p2,p3); + Segment s32(p3,p2); + Segment s31(p3,p1); bool b = test_aux(t,s12,"t-s12",s12); + b &= test_aux(t,s21,"t-s21",s21); b &= test_aux(t,s13,"t-s13",s13); b &= test_aux(t,s23,"t-s23",s23); @@ -121,6 +125,8 @@ bool test() Segment s46(p4,p6); Segment s48(p4,p8); Segment s56(p5,p6); + Segment s65(p6,p5); + Segment s64(p6,p4); Segment s17(p1,p7); Segment s67(p6,p7); Segment s68(p6,p8); @@ -142,6 +148,8 @@ bool test() b &= test_aux(t,s26,"t-s26",s26); b &= test_aux(t,s62,"t-s62",s62); b &= test_aux(t,s46,"t-s46",s46); + b &= test_aux(t,s65,"t-s65",s65); + b &= test_aux(t,s64,"t-s64",s64); b &= test_aux(t,s48,"t-s48",s48); b &= test_aux(t,s56,"t-s56",s56); b &= test_aux(t,s17,"t-t17",s17); @@ -200,6 +208,108 @@ bool test() b &= test_aux(t,sa8,"t-sa8",p8); b &= test_aux(t,sb2,"t-sb2",p2); + + // ----------------------------------- + // Line queries + // ----------------------------------- + // Edges of t + Line l12(p1,p2); + Line l21(p2,p1); + Line l13(p1,p3); + Line l23(p2,p3); + + b &= test_aux(t,l12,"t-l12",s12); + b &= test_aux(t,l21,"t-l21",s21); + b &= test_aux(t,l13,"t-l13",s13); + b &= test_aux(t,l23,"t-l23",s23); + + // In triangle + Point p9_(FT(0.), FT(0.5), FT(0.5)); + Point p9(FT(0.25), FT(0.375), FT(0.375)); + + Line l14(p1,p4); + Line l41(p4,p1); + Line l24(p2,p4); + Line l42(p4,p2); + Line l15(p1,p5); + Line l25(p2,p5); + Line l34(p3,p4); + Line l35(p3,p5); + Line l36(p3,p6); + Line l45(p4,p5); + Line l16(p1,p6); + Line l26(p2,p6); + Line l62(p6,p2); + Line l46(p4,p6); + Line l48(p4,p8); + Line l56(p5,p6); + Line l47(p4,p7); + Line l89(p8,p9); + Line l86(p8,p6); + Line l68(p6,p8); + Segment s89_res(p1,p9_); + + b &= test_aux(t,l14,"t-l14",s12); + b &= test_aux(t,l41,"t-l41",s21); + b &= test_aux(t,l24,"t-l24",s21); + b &= test_aux(t,l42,"t-l42",s12); + b &= test_aux(t,l15,"t-l15",s15); + b &= test_aux(t,l25,"t-l25",s23); + b &= test_aux(t,l34,"t-l34",s34); + b &= test_aux(t,l35,"t-l35",s32); + b &= test_aux(t,l36,"t-l36",s31); + b &= test_aux(t,l45,"t-l45",s45); + b &= test_aux(t,l16,"t-l16",s13); + b &= test_aux(t,l26,"t-l26",s26); + b &= test_aux(t,l62,"t-l62",s62); + b &= test_aux(t,l46,"t-l46",s46); + b &= test_aux(t,l48,"t-l48",s46); + b &= test_aux(t,l56,"t-l56",s56); + b &= test_aux(t,l47,"t-l47",s45); + b &= test_aux(t,l89,"t-t89",s89_res); + b &= test_aux(t,l68,"t-l68",s64); + b &= test_aux(t,l86,"t-l86",s46); + + + // Outside points (in triangle plane) + Line lAB(pA,pB); + Line lBC(pB,pC); + Line l2E(p2,pE); + Line lE2(pE,p2); + Line l2A(p2,pA); + Line l6E(p6,pE); + Line lB8(pB,p8); + Line lC8(pC,p8); + Line l8C(p8,pC); + Line l1F(p1,pF); + Line lF6(pF,p6); + + b &= test_aux(t,lAB,"t-lAB",p2); + b &= test_aux(t,lBC,"t-lBC",s46); + b &= test_aux(t,l2E,"t-l2E",s26); + b &= test_aux(t,lE2,"t-lE2",s62); + b &= test_aux(t,l2A,"t-l2A",p2); + b &= test_aux(t,l6E,"t-l6E",s26); + b &= test_aux(t,lB8,"t-lB8",s46); + b &= test_aux(t,lC8,"t-lC8",s64); + b &= test_aux(t,l8C,"t-l8C",s46); + b &= test_aux(t,l1F,"t-l1F",s13); + b &= test_aux(t,lF6,"t-lF6",s31); + + // Outside triangle plane + Line lab(pa,pb); + Line lac(pa,pc); + Line lae(pa,pe); + Line la8(pa,p8); + Line lb2(pb,p2); + + b &= test_aux(t,lab,"t-lab",p1); + b &= test_aux(t,lac,"t-lac",p6); + b &= test_aux(t,lae,"t-lae",p8); + b &= test_aux(t,la8,"t-la8",p8); + b &= test_aux(t,lb2,"t-lb2",p2); + + return b; }