From 5e9891ea75bc3121baad5a97ef74fcb64ef9f2bd Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 6 Jun 2019 10:46:02 +0200 Subject: [PATCH] Tet / tr --- .../include/CGAL/Intersection_traits_3.h | 43 ++ .../Intersections_3/Iso_cuboid_3_Plane_3.h | 2 + .../Intersections_3/Plane_3_Tetrahedron_3.h | 2 +- .../Intersections_3/Ray_3_Tetrahedron_3.h | 2 +- .../Intersections_3/Segment_3_Tetrahedron_3.h | 2 +- .../Tetrahedron_3_Triangle_3.h | 2 + .../Iso_cuboid_3_Plane_3_intersection.h | 262 ++++++++ ...h => Tetrahedron_3_Plane_3_intersection.h} | 61 +- ...s.h => Tetrahedron_3_Ray_3_intersection.h} | 0 ...=> Tetrahedron_3_Segment_3_intersection.h} | 0 .../Tetrahedron_3_Triangle_3_intersection.h | 299 ++++++++++ .../tetrahedron_intersection_helpers.h | 246 ++++++++ .../Intersections_3/test_intersections_3.cpp | 563 ++++++++++++++---- 13 files changed, 1308 insertions(+), 176 deletions(-) create mode 100644 Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Plane_3_intersection.h rename Intersections_3/include/CGAL/Intersections_3/internal/{Tetrahedron_3_Plane_3_intersections.h => Tetrahedron_3_Plane_3_intersection.h} (74%) rename Intersections_3/include/CGAL/Intersections_3/internal/{Tetrahedron_3_Ray_3_intersections.h => Tetrahedron_3_Ray_3_intersection.h} (100%) rename Intersections_3/include/CGAL/Intersections_3/internal/{Tetrahedron_3_Segment_3_intersections.h => Tetrahedron_3_Segment_3_intersection.h} (100%) create mode 100644 Intersections_3/include/CGAL/Intersections_3/internal/Tetrahedron_3_Triangle_3_intersection.h create mode 100644 Intersections_3/include/CGAL/Intersections_3/internal/tetrahedron_intersection_helpers.h diff --git a/Intersections_3/include/CGAL/Intersection_traits_3.h b/Intersections_3/include/CGAL/Intersection_traits_3.h index b1f8c7eb761..ac9513417f8 100644 --- a/Intersections_3/include/CGAL/Intersection_traits_3.h +++ b/Intersections_3/include/CGAL/Intersection_traits_3.h @@ -187,6 +187,28 @@ struct Intersection_traits { typedef typename boost::optional< variant_type > result_type; }; + +// Iso_cuboid_3 Plane_3, variant of 4 +template +struct Intersection_traits { + typedef typename + boost::variant< typename K::Point_3, typename K::Segment_3, + typename K::Triangle_3, std::vector > variant_type; + + typedef typename boost::optional< variant_type > result_type; +}; + +template +struct Intersection_traits { + typedef typename + boost::variant< typename K::Point_3, typename K::Segment_3, + typename K::Triangle_3, std::vector > variant_type; + + typedef typename boost::optional< variant_type > result_type; +}; + + + // Point_3 Line_3, variant of one template struct Intersection_traits { @@ -324,6 +346,27 @@ struct Intersection_traits }; +//Triangle_3 Tetrahedron_3, variant of 4 +template +struct Intersection_traits +{ + typedef typename + boost::variant< typename K::Point_3 , typename K::Segment_3, + typename K::Triangle_3, std::vector > variant_type; + typedef typename boost::optional< variant_type > result_type; +}; + +// Tetrahedron_3 Triangle_3, variant of 4 +template +struct Intersection_traits +{ + typedef typename + boost::variant< typename K::Point_3 , typename K::Segment_3, + typename K::Triangle_3, std::vector > variant_type; + typedef typename boost::optional< variant_type > result_type; +}; + + } // namespace #endif /* CGAL_INTERSECTION_TRAITS_3_H */ diff --git a/Intersections_3/include/CGAL/Intersections_3/Iso_cuboid_3_Plane_3.h b/Intersections_3/include/CGAL/Intersections_3/Iso_cuboid_3_Plane_3.h index 11c5eff3120..c503bbba418 100644 --- a/Intersections_3/include/CGAL/Intersections_3/Iso_cuboid_3_Plane_3.h +++ b/Intersections_3/include/CGAL/Intersections_3/Iso_cuboid_3_Plane_3.h @@ -26,10 +26,12 @@ #include #include #include +#include namespace CGAL { CGAL_DO_INTERSECT_FUNCTION(Iso_cuboid_3, Plane_3, 3) + CGAL_INTERSECTION_FUNCTION(Iso_cuboid_3, Plane_3, 3) } #endif // CGAL_INTERSECTIONS_3_ISO_CUBOID_3_PLANE_3_H diff --git a/Intersections_3/include/CGAL/Intersections_3/Plane_3_Tetrahedron_3.h b/Intersections_3/include/CGAL/Intersections_3/Plane_3_Tetrahedron_3.h index 5eb429d8917..55c171a63d2 100644 --- a/Intersections_3/include/CGAL/Intersections_3/Plane_3_Tetrahedron_3.h +++ b/Intersections_3/include/CGAL/Intersections_3/Plane_3_Tetrahedron_3.h @@ -27,7 +27,7 @@ #include #include -#include +#include namespace CGAL { CGAL_DO_INTERSECT_FUNCTION(Tetrahedron_3, Plane_3, 3) diff --git a/Intersections_3/include/CGAL/Intersections_3/Ray_3_Tetrahedron_3.h b/Intersections_3/include/CGAL/Intersections_3/Ray_3_Tetrahedron_3.h index 6d8fbe3ef4c..40429f99666 100644 --- a/Intersections_3/include/CGAL/Intersections_3/Ray_3_Tetrahedron_3.h +++ b/Intersections_3/include/CGAL/Intersections_3/Ray_3_Tetrahedron_3.h @@ -27,7 +27,7 @@ #include #include -#include +#include namespace CGAL { CGAL_DO_INTERSECT_FUNCTION(Ray_3, Tetrahedron_3, 3) diff --git a/Intersections_3/include/CGAL/Intersections_3/Segment_3_Tetrahedron_3.h b/Intersections_3/include/CGAL/Intersections_3/Segment_3_Tetrahedron_3.h index 7184ab76cb7..f58529d8db9 100644 --- a/Intersections_3/include/CGAL/Intersections_3/Segment_3_Tetrahedron_3.h +++ b/Intersections_3/include/CGAL/Intersections_3/Segment_3_Tetrahedron_3.h @@ -27,7 +27,7 @@ #include #include -#include +#include namespace CGAL { CGAL_DO_INTERSECT_FUNCTION(Segment_3, Tetrahedron_3, 3) diff --git a/Intersections_3/include/CGAL/Intersections_3/Tetrahedron_3_Triangle_3.h b/Intersections_3/include/CGAL/Intersections_3/Tetrahedron_3_Triangle_3.h index da0193e3291..671498a6246 100644 --- a/Intersections_3/include/CGAL/Intersections_3/Tetrahedron_3_Triangle_3.h +++ b/Intersections_3/include/CGAL/Intersections_3/Tetrahedron_3_Triangle_3.h @@ -27,9 +27,11 @@ #include #include +#include namespace CGAL { CGAL_DO_INTERSECT_FUNCTION(Tetrahedron_3, Triangle_3, 3) + CGAL_INTERSECTION_FUNCTION(Tetrahedron_3, Triangle_3, 3) } #endif // CGAL_INTERSECTIONS_3_TETRAHEDRON_3_TRIANGLE_3_H diff --git a/Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Plane_3_intersection.h b/Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Plane_3_intersection.h new file mode 100644 index 00000000000..2715b9e40ae --- /dev/null +++ b/Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Plane_3_intersection.h @@ -0,0 +1,262 @@ +// Copyright (c) 2019 GeometryFactory(France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// +// Author(s) : Maxime Gimeno +// + +#ifndef CGAL_INTERNAL_INTERSECTIONS_3_ISO_CUBOID_3_PLANE_3_INTERSECTION_H +#define CGAL_INTERNAL_INTERSECTIONS_3_ISO_CUBOID_3_PLANE_3_INTERSECTION_H +#include +#include +#include +#include +#include + +#include +namespace CGAL { + +namespace Intersections { + +namespace internal { + +template +void filter_points(const std::vector& input, + std::vector& output) +{ + std::set tmp; + for( auto p : input) + tmp.insert(p); + for(auto p: tmp) + output.push_back(p); +} + +//Tetrahedron_3 Line_3 +template +typename Intersection_traits::result_type +intersection( + const typename K::Iso_cuboid_3 &cub, + const typename K::Plane_3 &pl, + const K&) +{ + typedef typename K::Point_3 Point_3; + typedef typename K::Segment_3 Segment_3; + typedef typename K::Line_3 Line_3; + typedef typename K::Plane_3 Plane_3; + typedef std::vector Poly; + + typedef typename Intersection_traits, + CGAL::Plane_3 >::result_type Result_type; + + typedef typename Intersection_traits, + CGAL::Plane_3 >::result_type Inter_type; + + std::vector edges; + edges.reserve(12); + + //get all edges of cub + for(int i=0; i< 4; ++i) + { + edges.push_back(Segment_3(cub.vertex(i), cub.vertex((i+1)%4))); + } + + for(int i=0; i < 4; ++i) + { + edges.push_back(Segment_3(cub.vertex(i+4), cub.vertex((i+1)%4+4))); + } + + for(int i=0; i < 4; ++i) + { + edges.push_back(Segment_3(cub.vertex(i), cub.vertex((i+1)%4+4))); + } + //get all intersections between pl and cub edges + std::vector segments; + std::vector points; + + for(int i=0; i < 12; ++i) + { + Inter_type inter = typename K::Intersect_3()(pl, edges[i]); + if(inter){ + if(const Segment_3* seg = boost::get(&*inter)) + { + segments.push_back(*seg); + } + else if(const Point_3* p = boost::get(&*inter)) + { + points.push_back(*p); + } + } + } + + switch(segments.size()) + { + case 1: //adj to an edge + { + return Result_type(std::forward(segments.front())); + } + break; + + case 2: //intersects diagonally + { + Poly res(4); + Segment_3 front(segments.front()), + back(segments.back()); + res[0] = front.target(); + if((front.target() - front.source()) + * (back.target() - back.source()) > 0) + { + res[1] = back.target(); + res[2] = back.source(); + } + else + { + res[1] = back.source(); + res[2] = back.target(); + } + res[3] = front.source(); + + return Result_type(std::forward(res)); + } + break; + case 4: // intersects a face + { + Poly res; + res.reserve(4); + std::list tmp; + std::list seg_list; + for(auto s : segments) + seg_list.push_back(s); + fill_points_list(seg_list, tmp); + for(auto p : tmp) + res.push_back(p); + return Result_type(std::forward(res)); + } + break; + default: + break; + } + + Poly filtered_points; + filter_points(points, filtered_points); + if(filtered_points.empty()) + return Result_type(); + //adjacent to a vertex + if(filtered_points.size() == 1) + { + return Result_type(std::forward(filtered_points.front())); + } + else + { + //get intersections between pl and each face -> line. Foreach line, creates segment with points. Then use helper_function to recover polygon. + typedef typename Intersection_traits, + CGAL::Plane_3 >::result_type Pl_pl_type; + + std::vector plane_intersections; + Pl_pl_type pl_inter = CGAL::intersection(pl, Plane_3(cub.vertex(0), + cub.vertex(1), + cub.vertex(5))); + if(const Line_3* line = boost::get(&*pl_inter)){ + plane_intersections.push_back(*line); + } + pl_inter = CGAL::intersection(pl, Plane_3(cub.vertex(0), + cub.vertex(3), + cub.vertex(4))); + if(const Line_3* line = boost::get(&*pl_inter)){ + plane_intersections.push_back(*line); + } + pl_inter = CGAL::intersection(pl, Plane_3(cub.vertex(0), + cub.vertex(1), + cub.vertex(3))); + if(const Line_3* line = boost::get(&*pl_inter)){ + plane_intersections.push_back(*line); + } + pl_inter = CGAL::intersection(pl, Plane_3(cub.vertex(7), + cub.vertex(6), + cub.vertex(1))); + if(const Line_3* line = boost::get(&*pl_inter)){ + plane_intersections.push_back(*line); + } + pl_inter = CGAL::intersection(pl, Plane_3(cub.vertex(7), + cub.vertex(4), + cub.vertex(3))); + if(const Line_3* line = boost::get(&*pl_inter)){ + plane_intersections.push_back(*line); + } + pl_inter = CGAL::intersection(pl, Plane_3(cub.vertex(7), + cub.vertex(6), + cub.vertex(4))); + if(const Line_3* line = boost::get(&*pl_inter)){ + plane_intersections.push_back(*line); + } + + std::list tmp_segs; + for(auto line : plane_intersections) + { + bool first_found = false; + Point_3 first_p; + for(auto p : filtered_points) + { + if(line.has_on(p)) + { + if(!first_found) + { + first_found = true; + first_p = p; + } + else + { + tmp_segs.push_back(Segment_3(first_p, p)); + break; + } + } + } + } + if(tmp_segs.size() < 3) + return Result_type(); + std::list tmp_pts; + fill_points_list(tmp_segs,tmp_pts); + Poly res; + for(auto p : tmp_pts) + res.push_back(p); + if(res.size() == 3){ + typename K::Triangle_3 tr(res[0], res[1], res[2]); + return Result_type(std::forward(tr)); + } + else + { + return Result_type(std::forward(res)); + } + } +} + +template +typename Intersection_traits::result_type +intersection( + const typename K::Plane_3 &pl, + const typename K::Iso_cuboid_3 &cub, + const K& k) +{ + return intersection(cub, pl, k); +} + +}}} + +#endif // CGAL_INTERNAL_INTERSECTIONS_3_ISO_CUBOID_3_PLANE_3_INTERSECTION_H diff --git a/Intersections_3/include/CGAL/Intersections_3/internal/Tetrahedron_3_Plane_3_intersections.h b/Intersections_3/include/CGAL/Intersections_3/internal/Tetrahedron_3_Plane_3_intersection.h similarity index 74% rename from Intersections_3/include/CGAL/Intersections_3/internal/Tetrahedron_3_Plane_3_intersections.h rename to Intersections_3/include/CGAL/Intersections_3/internal/Tetrahedron_3_Plane_3_intersection.h index 141c4701311..3a6353c9809 100644 --- a/Intersections_3/include/CGAL/Intersections_3/internal/Tetrahedron_3_Plane_3_intersections.h +++ b/Intersections_3/include/CGAL/Intersections_3/internal/Tetrahedron_3_Plane_3_intersection.h @@ -27,6 +27,7 @@ #include #include #include +#include #include namespace CGAL { @@ -34,6 +35,7 @@ namespace Intersections { namespace internal { + //Tetrahedron_3 Segment_3 template typename Intersection_traits::result_type @@ -123,56 +125,15 @@ intersection( } else //size = 4 { - Segment_3 edge = segments.back(); - segments.pop_back(); - std::vector result; - auto s_it = segments.begin(); - - result.push_back(edge.source()); - result.push_back(edge.target()); - - int counter = 0; - for(; counter <2; ++counter )//1 or 2 rounds - { - if(edge.target() == s_it->source()) - { - result.push_back(s_it->target()); - break; - } - else if (edge.target() == s_it->target()) - { - result.push_back(s_it->source()); - break; - } - else - ++s_it; - } - if(counter > 1) //not exact, won't find the right inter anyway. - return Result_type(); - - segments.erase(s_it); - - s_it = segments.begin(); - if(edge.source() == s_it->target()) - { - result.push_back(s_it->source()); - } - else if(edge.source() == s_it->source()) - { - result.push_back(s_it->target()); - } - else - { - if(result.back() == s_it->target()) - { - result.push_back(s_it->source()); - } - else if(result.back() == s_it->source()) - { - result.push_back(s_it->target()); - } - } - return Result_type(std::forward >(result)); + std::list segs; + for(auto s : segments) + segs.push_back(s); + std::list tmp; + fill_points_list(segs, tmp); + std::vector res; + for( auto p : tmp) + res.push_back(p); + return Result_type(std::forward >(res)); } } break; diff --git a/Intersections_3/include/CGAL/Intersections_3/internal/Tetrahedron_3_Ray_3_intersections.h b/Intersections_3/include/CGAL/Intersections_3/internal/Tetrahedron_3_Ray_3_intersection.h similarity index 100% rename from Intersections_3/include/CGAL/Intersections_3/internal/Tetrahedron_3_Ray_3_intersections.h rename to Intersections_3/include/CGAL/Intersections_3/internal/Tetrahedron_3_Ray_3_intersection.h diff --git a/Intersections_3/include/CGAL/Intersections_3/internal/Tetrahedron_3_Segment_3_intersections.h b/Intersections_3/include/CGAL/Intersections_3/internal/Tetrahedron_3_Segment_3_intersection.h similarity index 100% rename from Intersections_3/include/CGAL/Intersections_3/internal/Tetrahedron_3_Segment_3_intersections.h rename to Intersections_3/include/CGAL/Intersections_3/internal/Tetrahedron_3_Segment_3_intersection.h diff --git a/Intersections_3/include/CGAL/Intersections_3/internal/Tetrahedron_3_Triangle_3_intersection.h b/Intersections_3/include/CGAL/Intersections_3/internal/Tetrahedron_3_Triangle_3_intersection.h new file mode 100644 index 00000000000..14e28980475 --- /dev/null +++ b/Intersections_3/include/CGAL/Intersections_3/internal/Tetrahedron_3_Triangle_3_intersection.h @@ -0,0 +1,299 @@ +// Copyright (c) 2019 GeometryFactory(France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0+ +// +// +// Author(s) : Maxime Gimeno +// + + +#ifndef CGAL_INTERNAL_INTERSECTIONS_3_TETRAHEDRON_3_TRIANGLE_3_INTERSECTIONS_H +#define CGAL_INTERNAL_INTERSECTIONS_3_TETRAHEDRON_3_TRIANGLE_3_INTERSECTIONS_H + +#include +#include +#include +#include +#include +namespace CGAL { + +namespace Intersections { + +namespace internal { + +//Tetrahedron_3 Segment_3 +template +typename Intersection_traits::result_type +intersection( + const typename K::Tetrahedron_3 &tet, + const typename K::Triangle_3 &tr, + const K&) +{ + typedef typename Intersection_traits::result_type Result_type; + + typedef typename Intersection_traits::result_type Inter_type; + + typedef typename K::Segment_3 Segment_3; + typedef typename K::Point_3 Point_3; + typedef typename K::Triangle_3 Triangle_3; + typedef std::vector Poly; + + std::vector inside_points; + for(int i = 0; i< 3; ++i) + { + if(tet.has_on_bounded_side(tr.vertex(i)) + || tet.has_on_boundary(tr.vertex(i))) + inside_points.push_back(tr.vertex(i)); + } + switch(inside_points.size()) + { + case 0: + { + Inter_type intersections[4]; + std::vector segments; + std::vector seg_ids; + std::vector points; + for(std::size_t i = 0; i < 4; ++i) + { + const typename K::Triangle_3 triangle(tet.vertex((i+1)%4), + tet.vertex((i+2)%4), + tet.vertex((i+3)%4)); + intersections[i] = typename K::Intersect_3()(tr, triangle); + if(intersections[i]){ + //a face is inside the input tr + if(const Triangle_3* t = boost::get(&*intersections[i])) + { + Triangle_3 res = *t; + return Result_type(std::forward(res)); + } + //get segs and pts to construct poly + else if( const Segment_3* s + = boost::get(&*intersections[i])) + { + segments.push_back(*s); + seg_ids.push_back(i); + } + else if( const typename K::Point_3* p + = boost::get(&*intersections[i])) + { + points.push_back(*p); + } + //if poly : then the input is in a supporting plane of a face, return the poly. + else if( const Poly* p + = boost::get(&*intersections[i])) + { + Poly res = *p; + return Result_type(std::forward(res)); + } + } + } + if(segments.size() > 1) + { + std::vector filtered; + filter_segments(segments, filtered); + segments = filtered; + } + //if there are several segments, then we need to compute the polygone. + if(segments.size() > 1) + { + std::list tmp; + fill_segments_infos(segments,tmp, tr); + Poly res; + res.reserve(4); + for( auto p : tmp) + res.push_back(p); + return Result_type(std::forward(res)); + } + //else it must be adjacent to an vertex, so we return the point + else if(segments.size() == 1) + { + //adjacency to an edge, return resulting segment. + return Result_type(std::forward(segments.front())); + } + else + { + //no segment = adjacency to an vertex or an edge : return result point + return Result_type(std::forward(points.front())); + + } + } + break; + case 1: + case 2: + { + //tricky cases + Inter_type intersections[4]; + std::vector points; + std::vector segments; + for(std::size_t i = 0; i < 4; ++i) + { + const typename K::Triangle_3 triangle(tet.vertex((i+1)%4), + tet.vertex((i+2)%4), + tet.vertex((i+3)%4)); + intersections[i] = typename K::Intersect_3()(tr, triangle); + if(intersections[i]){ + if(const Triangle_3* t = boost::get(&*intersections[i])) + { + Triangle_3 res = *t; + return Result_type(std::forward(res)); + } + //get segs and pts to construct poly + else if( const Segment_3* s + = boost::get(&*intersections[i])) + { + segments.push_back(*s); + } + else if( const typename K::Point_3* p + = boost::get(&*intersections[i])) + { + points.push_back(*p); + } + //if poly : then the input is in a supporting plane of a face, return the poly. + else if( const Poly* p + = boost::get(&*intersections[i])) + { + Poly res = *p; + return Result_type(std::forward(res)); + } + } + } + if(segments.empty()) + { + //then there is only one point of contact. Return it: + return Result_type(std::forward(points.front())); + } + + if(segments.size() > 1) + { + std::vector filtered; + filter_segments(segments, filtered); + segments = filtered; + } + + switch(segments.size()) + { + case 1: + { + bool return_solo_seg = true; + //only one intersection, a triangle edge is one of the tet edges, and + //the 3rd point is outside. This is the only intersection. + for(auto p : inside_points) + { + if(!tet.has_on_boundary(p)) + { + return_solo_seg = false; + break; + } + } + if(return_solo_seg) + { + return Result_type(std::forward(segments.front())); + } + + if(inside_points.size() == 1) + { + Triangle_3 res(inside_points.front(), segments.front().source(), + segments.front().target()); + return Result_type(std::forward(res)); + } + else //size 2 + { + Poly res(4); + res[0] = inside_points.front(); + res[1] = inside_points.back(); + if((inside_points.front() - inside_points.back()) * + (segments.front().source() - segments.front().target()) > 0) + { + res[2] = segments.front().target(); + res[3] = segments.front().source(); + } + else + { + res[3] = segments.front().target(); + res[2] = segments.front().source(); + } + return Result_type(std::forward(res)); + } + } + break; + case 2: + case 3: + { + std::list segs; + for(auto s : segments) + segs.push_back(s); + std::list tmp; + fill_points_list(segs, tmp); + if(inside_points.size() == 1) + { + Poly res; + res.reserve(4); + res.push_back(inside_points.front()); + for( auto p : tmp) + res.push_back(p); + return Result_type(std::forward(res)); + } + else //size 2 + { + Poly res; + res.reserve(5); + if((inside_points.front() - inside_points.back()) * + (tmp.front() - tmp.back()) > 0) + res.push_back(inside_points.front()); + res.push_back(inside_points.back()); + for( auto p : tmp) + res.push_back(p); + return Result_type(std::forward(res)); + } + } + break; + default: + //3 faces max if a point or more are inside tetrahedron + break; + } + } + break; + + case 3: + { + //triangle entirely inside tetra : return input triangle + typename K::Triangle_3 res = tr; + return Result_type(std::forward(res)); + } + break; + default: + //never happens (only 3 pts in a tr) + break; + } +} + +template +typename Intersection_traits::result_type +intersection( + const typename K::Triangle_3 &pl, + const typename K::Tetrahedron_3 &tet, + const K& k) +{ + return intersection(tet, pl, k); +} + +}}} +#endif // CGAL_INTERNAL_INTERSECTIONS_3_TETRAHEDRON_3_TRIANGLE_3_INTERSECTIONS_H diff --git a/Intersections_3/include/CGAL/Intersections_3/internal/tetrahedron_intersection_helpers.h b/Intersections_3/include/CGAL/Intersections_3/internal/tetrahedron_intersection_helpers.h new file mode 100644 index 00000000000..ced97166b57 --- /dev/null +++ b/Intersections_3/include/CGAL/Intersections_3/internal/tetrahedron_intersection_helpers.h @@ -0,0 +1,246 @@ +#ifndef CGAL_INTERNAL_TETRAHEDRON_INTERSECTION_HELPERS_H +#define CGAL_INTERNAL_TETRAHEDRON_INTERSECTION_HELPERS_H + +#include +#include +#include + +namespace CGAL { + +namespace Intersections { + +namespace internal { + +template +void filter_segments(const std::vector& input, + std::vector& output) +{ + std::list tmp(input.begin(), input.end()); + + do + { + Segment s = tmp.back(); + tmp.pop_back(); + auto s_it = tmp.begin(); + for(; s_it != tmp.end();) + { + if(s == *s_it || s == s_it->opposite()) + { + s_it = tmp.erase(s_it); + } + else { + ++s_it; + } + } + output.push_back(s); + }while (!tmp.empty()); +} + +template +void fill_segments_infos(std::vector& segments, + std::list& points, const Triangle& input_tr) +{ + struct Wrapped_segment + { + Segment segment; + bool s_dangling; + bool t_dangling; + std::size_t s_neighbor; + std::size_t t_neighbor; + Wrapped_segment(const Segment& s) + :segment(s), s_dangling(true), + t_dangling(true){} + }; + + std::vector wrapped_segments; + + for(auto s:segments) + wrapped_segments.push_back(Wrapped_segment(s)); + + std::vector bis = segments; + for(int plouf = 0; plouf < bis.size()-1; ++plouf) + { + Segment s = bis.back(); + bis.pop_back(); + Wrapped_segment& super_s = wrapped_segments.back(); + if(!super_s.s_dangling && ! super_s.t_dangling) + continue; + for(std::size_t i = 0; i< bis.size(); ++i) + { + const Segment& s2 = bis[i]; + if(s2.target() == s.source()) + { + super_s.s_dangling = false; + super_s.s_neighbor = i; + //same i because we empty from the bottom + wrapped_segments[i].t_dangling = false; + wrapped_segments[i].t_neighbor = bis.size(); + } + else if(s2.target() == s.target()) + { + super_s.t_dangling = false; + super_s.t_neighbor = i; + wrapped_segments[i].s_dangling = false; + wrapped_segments[i].s_neighbor = bis.size(); + wrapped_segments[i].segment = wrapped_segments[i].segment.opposite(); //also orient the structure + + } + else if(s2.source() == s.source()) + { + super_s.s_dangling = false; + super_s.s_neighbor = i; + wrapped_segments[i].t_dangling = false; + wrapped_segments[i].t_neighbor = bis.size(); + wrapped_segments[i].segment = wrapped_segments[i].segment.opposite(); + } + else if(s2.source() == s.target()) + { + super_s.t_dangling = false; + super_s.t_neighbor = i; + wrapped_segments[i].s_dangling = false; + wrapped_segments[i].s_neighbor = bis.size(); + } + } + + //fill dangling extremities using triangle edges + if(super_s.s_dangling) + { + for(std::size_t e_id = 0; e_id < 3; ++e_id) + { + Segment edge(input_tr.vertex(e_id), input_tr.vertex(e_id+1)); + if(!edge.has_on(s.source())) + { + continue; + } + for(std::size_t i = 0; i< bis.size(); ++i) + { + if(edge.has_on(bis[i].source())) + { + super_s.s_dangling = false; + super_s.s_neighbor = i; + //same i because we empty from the bottom + wrapped_segments[i].t_dangling = false; + wrapped_segments[i].t_neighbor = bis.size(); + wrapped_segments[i].segment = wrapped_segments[i].segment.opposite(); + } + else if(edge.has_on(bis[i].target())) + { + super_s.s_dangling = false; + super_s.s_neighbor = i; + //same i because we empty from the bottom + wrapped_segments[i].t_dangling = false; + wrapped_segments[i].t_neighbor = bis.size(); + } + } + } + } + if(super_s.t_dangling) + { + for(std::size_t e_id = 0; e_id < 3; ++e_id) + { + Segment edge(input_tr.vertex(e_id), input_tr.vertex(e_id+1)); + if(!edge.has_on(s.target())) + { + continue; + } + for(std::size_t i = 0; i< bis.size(); ++i) + { + if(edge.has_on(bis[i].source())) + { + super_s.t_dangling = false; + super_s.t_neighbor = i; + //same i because we empty from the bottom + wrapped_segments[i].s_dangling = false; + wrapped_segments[i].s_neighbor = bis.size(); + } + else if(edge.has_on(bis[i].target())) + { + super_s.t_dangling = false; + super_s.t_neighbor = i; + //same i because we empty from the bottom + wrapped_segments[i].s_dangling = false; + wrapped_segments[i].s_neighbor = bis.size(); + wrapped_segments[i].segment = wrapped_segments[i].segment.opposite(); + } + } + } + } + + if(super_s.s_dangling || super_s.t_dangling) + { + std::cerr<<"Error. Kernel must have exact constructions to compute this intersection."< +void fill_points_list(std::list& segments, std::list& points) +{ + assert(segments.size() > 1); + //init : take seg.front = seg. + Segment seg = segments.front(); + segments.pop_front(); + //put source and target in points. + points.push_back(seg.source()); + points.push_back(seg.target()); + //find first seg with a point in common with seg.front = s2. + do{ + auto seg_it = segments.begin(); + bool found = false; + for(;seg_it != segments.end(); ++seg_it) + { + if(seg_it->source() == points.front()) + { + points.push_front(seg_it->target()); + found = true; + } + else if(seg_it->source() == points.back()) + { + points.push_back(seg_it->target()); + found = true; + } + else if(seg_it->target() == points.front()) + { + points.push_front(seg_it->source()); + found = true; + } + else if(seg_it->target() == points.back()) + { + points.push_back(seg_it->source()); + found = true; + } + if(found) + { + break; + } + } + if(!found) + { + std::cerr<<"Error. Kernel must have exact constructions to compute this intersection."< @@ -68,79 +68,78 @@ struct Test { template < typename Type > bool approx_equal_nt(const Type &t1, const Type &t2) { - if (t1 == t2) - return true; - if (CGAL::abs(t1 - t2) / (CGAL::max)(CGAL::abs(t1), CGAL::abs(t2)) < epsilon) - return true; - std::cout << " Approximate comparison failed between : " << t1 << " and " << t2 << "\n"; - return false; + if (t1 == t2) + return true; + if (CGAL::abs(t1 - t2) / (CGAL::max)(CGAL::abs(t1), CGAL::abs(t2)) < epsilon) + return true; + std::cout << " Approximate comparison failed between : " << t1 << " and " << t2 << "\n"; + return false; } template < typename Type > bool approx_equal(const Type&t1, const Type&t2) { - return t1 == t2; - // we need approx equal to check approx kernels, but maybe we should only test with exact kernels - // (approx kernels were useful before, when the text output was checked by diff ?) - // idea : test containment with intervals ? or use some "epsilon double"? - // I need to convert the text output to exact rationals in the source... - // Well, for now the current scheme works. + return t1 == t2; + // we need approx equal to check approx kernels, but maybe we should only test with exact kernels + // (approx kernels were useful before, when the text output was checked by diff ?) + // idea : test containment with intervals ? or use some "epsilon double"? + // I need to convert the text output to exact rationals in the source... + // Well, for now the current scheme works. } bool approx_equal(const P & p, const P & q) { - return approx_equal_nt(p.x(), q.x()) && - approx_equal_nt(p.y(), q.y()) && - approx_equal_nt(p.z(), q.z()); + return approx_equal_nt(p.x(), q.x()) && + approx_equal_nt(p.y(), q.y()) && + approx_equal_nt(p.z(), q.z()); } bool approx_equal(const S & p, const S & q) { - return approx_equal(p.source(), q.source()) && approx_equal(p.target(), q.target()); + return approx_equal(p.source(), q.source()) && approx_equal(p.target(), q.target()); } /* bool approx_equal(const Pol & p, const Pol & q) { - if (p.size() != q.size()) - return false; - for(typename Pol::const_iterator itp = p.begin(), itq = q.begin(); itp != p.end(); ++itp, ++itq) - if (!approx_equal(*itp, *itq)) - return false; - return true; + if (p.size() != q.size()) + return false; + for(typename Pol::const_iterator itp = p.begin(), itq = q.begin(); itp != p.end(); ++itp, ++itq) + if (!approx_equal(*itp, *itq)) + return false; + return true; } */ template < typename O1, typename O2> void check_no_intersection(const O1& o1, const O2& o2) { - assert(!CGAL::do_intersect(o1, o2)); - assert(!CGAL::do_intersect(o2, o1)); + assert(!CGAL::do_intersect(o1, o2)); + assert(!CGAL::do_intersect(o2, o1)); } template < typename Res, typename O1, typename O2 > void check_intersection(const O1& o1, const O2& o2) { - Res tmp; - assert(CGAL::do_intersect(o1, o2)); - assert(CGAL::assign(tmp, CGAL::intersection(o1, o2))); - assert(CGAL::do_intersect(o2, o1)); - assert(CGAL::assign(tmp, CGAL::intersection(o2, o1))); + Res tmp; + assert(CGAL::do_intersect(o1, o2)); + assert(CGAL::assign(tmp, CGAL::intersection(o1, o2))); + assert(CGAL::do_intersect(o2, o1)); + assert(CGAL::assign(tmp, CGAL::intersection(o2, o1))); } template < typename Res, typename O1, typename O2 > void check_intersection(const O1& o1, const O2& o2, const Res& result, bool do_opposite = true) { - Res tmp; - assert(CGAL::do_intersect(o1, o2)); - assert(CGAL::assign(tmp, CGAL::intersection(o1, o2))); - std::cout< (pl(0, 0, 1,-1), L(p( 1, 1, 1), p( 2, 3, 1))); check_no_intersection (pl(0, 0, 1,-2), L(p( 1, 1, 1), p( 2, 3, 1))); check_intersection (pl(1, 0, 1, 3), L(p( 1, 1, 1), p( 2, 3, -1)), - P( 6, 11, -9)); + P( 6, 11, -9)); check_intersection (pl(1, 2, 4, 7), L(p( 1, 1, 1), p( 2, 3, 4)), - P( 0.176471, -0.647059, -1.47059)); + P( 0.176471, -0.647059, -1.47059)); } void Pl_Pl() @@ -292,35 +291,35 @@ struct Test { { std::cout << "Ray - Iso_cuboid\n"; check_intersection (R(p( -3, 1, -5), p( -2, -5, -7)), Cub(p( -7, -8, -9), p( -1, 2, -4)), - S(P(-3, 1, -5), P(-1.5, -8, -8))); + S(P(-3, 1, -5), P(-1.5, -8, -8))); check_intersection (R(p( 0, 0, 3), p( 1, 2, 3)), Cub(p( 1, 1, 1), p( 3, 5, 8)), - S(P( 1, 2, 3), P( 2.5, 5, 3))); + S(P( 1, 2, 3), P( 2.5, 5, 3))); check_intersection (R(p( 1, 0, 0), p( 1, 2, 3)), Cub(p( 1, 1, 1), p( 3, 5, 8)), - S(P( 1, 1,1.5), P( 1, 5,7.5))); + S(P( 1, 1,1.5), P( 1, 5,7.5))); check_intersection (R(p( 0, 2, 0), p( 1, 2, 3)), Cub(p( 2, 1, 1), p( 3, 5, 8)), - S(P( 2, 2, 6), P(2.66667,2, 8))); + S(P( 2, 2, 6), P(2.66667,2, 8))); check_no_intersection (R(p( 0, 0, 0), p( 1, 0, 3)), Cub(p( 2, 1, 1), p( 3, 5, 8))); check_no_intersection (R(p( 4, 0, 0), p( 4, 1, 3)), Cub(p( 2, 1, 1), p( 3, 5, 8))); check_intersection (R(p( 0, 0, 0), p( 1, 2, 3)), Cub(p( 1, 1, 1), p( 3, 5, 8)), - S(P( 1, 2, 3), P(2.5, 5, 7.5))); + S(P( 1, 2, 3), P(2.5, 5, 7.5))); } void S_Cub() { std::cout << "Segment - Iso_cuboid\n"; check_intersection (S(p( -3, 1, -5), p( -2, -5, -7)), Cub(p( -7, -8, -9), p( -1, 2, -4)), - S(P(-3, 1, -5), P( -2, -5, -7))); + S(P(-3, 1, -5), P( -2, -5, -7))); check_intersection (S(p( 0, 0, 3), p( 1, 2, 3)), Cub(p( 1, 1, 1), p( 3, 5, 8)), - P( 1, 2, 3)); + P( 1, 2, 3)); check_intersection (S(p( 1, 0, 0), p( 1, 2, 3)), Cub(p( 1, 1, 1), p( 3, 5, 8)), - S(P( 1, 1, 1.5), P( 1, 2, 3))); + S(P( 1, 1, 1.5), P( 1, 2, 3))); check_no_intersection (S(p( 0, 2, 0), p( 1, 2, 3)), Cub(p( 2, 1, 1), p( 3, 5, 8))); check_no_intersection (S(p( 0, 0, 0), p( 1, 0, 3)), Cub(p( 2, 1, 1), p( 3, 5, 8))); check_no_intersection (S(p( 4, 0, 0), p( 4, 1, 3)), Cub(p( 2, 1, 1), p( 3, 5, 8))); check_intersection (S(p( 0, 0, 0), p( 1, 2, 3)), Cub(p( 1, 1, 1), p( 3, 5, 8)), - P( 1, 2, 3)); + P( 1, 2, 3)); } - + void Pl_Tr() { std::cout << "Plane - Triangle\n"; @@ -329,7 +328,7 @@ struct Test { check_intersection ( Pl(P(0,0,0),P(12,0,0),P(0,11,0)),Tr(P(0,0,0),P(1,0,0),P(0,1,1)),S(P(0,0,0),P(1,0,0)),true); check_intersection ( Pl(P(0,0,0),P(12,0,0),P(0,11,0)),Tr(P(1,0,-1),P(-1,0,-1),P(0,0,1)),S(P(0.5,0,0),P(-0.5,0,0)),true); } - + void S_L() { std::cout << "Segment - Line\n"; @@ -337,7 +336,7 @@ struct Test { check_intersection ( S(P(0,0,0),P(12,0,0)),L(P(0,1,0),P(0,-1,0)),P(0,0,0),true); check_intersection ( S(P(-12,0,0),P(12,0,0)),L(P(0,1,0),P(0,-1,0)),P(0,0,0),true); } - + void R_L() { std::cout << "Ray - Line\n"; @@ -395,11 +394,11 @@ struct Test { check_no_intersection (R(P(0,0,0),P(1,0,0)),R(P(0,-1,0),P(0,-2,0))); check_no_intersection (R(P(0,0,0),P(1,0,0)),R(P(0,1,0),P(0,2,0))); } - + void Bbox_L(){ std::cout << "Bbox - Line\n"; Bbox box(-1,-1,-1,1,1,1); - + //not in x,y,z slab check_no_intersection (box,L(P(2,0,0),P(2,0,0.5))); check_no_intersection (box,L(P(0,2,0),P(0,2,0.5))); @@ -411,41 +410,41 @@ struct Test { //in each slab, time not matching //xz check_no_intersection (box,L(P(-8,0,0),P(0,0, 8))); - check_no_intersection (box,L(P( 8,0,0),P(0,0, 8))); + check_no_intersection (box,L(P( 8,0,0),P(0,0, 8))); check_no_intersection (box,L(P(-8,0,0),P(0,0,-8))); check_no_intersection (box,L(P( 8,0,0),P(0,0,-8))); //yz check_no_intersection (box,L(P(0,-8,0),P(0,0, 8))); - check_no_intersection (box,L(P(0, 8,0),P(0,0, 8))); + check_no_intersection (box,L(P(0, 8,0),P(0,0, 8))); check_no_intersection (box,L(P(0,-8,0),P(0,0,-8))); check_no_intersection (box,L(P(0, 8,0),P(0,0,-8))); //xy check_no_intersection (box,L(P(0,-8,0),P(8,0,0))); - check_no_intersection (box,L(P(0, 8,0),P(8,0,0))); + check_no_intersection (box,L(P(0, 8,0),P(8,0,0))); check_no_intersection (box,L(P(0,-8,0),P(-8,0,0))); check_no_intersection (box,L(P(0, 8,0),P(-8,0,0))); //Intersecting //xz check_intersection (box,L(P(-0.5,0,0),P(0,0, 0.5))); - check_intersection (box,L(P( 0.5,0,0),P(0,0, 0.5))); + check_intersection (box,L(P( 0.5,0,0),P(0,0, 0.5))); check_intersection (box,L(P(-0.5,0,0),P(0,0,-0.5))); check_intersection (box,L(P( 0.5,0,0),P(0,0,-0.5))); //yz check_intersection (box,L(P(0,-0.5,0),P(0,0, 0.5))); - check_intersection (box,L(P(0, 0.5,0),P(0,0, 0.5))); + check_intersection (box,L(P(0, 0.5,0),P(0,0, 0.5))); check_intersection (box,L(P(0,-0.5,0),P(0,0,-0.5))); check_intersection (box,L(P(0, 0.5,0),P(0,0,-0.5))); //xy check_intersection (box,L(P(0,-0.5,0),P(0.5,0,0))); - check_intersection (box,L(P(0, 0.5,0),P(0.5,0,0))); + check_intersection (box,L(P(0, 0.5,0),P(0.5,0,0))); check_intersection (box,L(P(0,-0.5,0),P(-0.5,0,0))); check_intersection (box,L(P(0, 0.5,0),P(-0.5,0,0))); } - + void Bbox_R(){ std::cout << "Bbox - Ray\n"; Bbox box(-1,-1,-1,1,1,1); - + //not in x,y,z slab check_no_intersection (box,R(P(2,0,0),P(2,0,0.5))); check_no_intersection (box,R(P(0,2,0),P(0,2,0.5))); @@ -457,33 +456,33 @@ struct Test { //in each slab, time not matching //xz check_no_intersection (box,R(P(-8,0,0),P(0,0, 8))); - check_no_intersection (box,R(P( 8,0,0),P(0,0, 8))); + check_no_intersection (box,R(P( 8,0,0),P(0,0, 8))); check_no_intersection (box,R(P(-8,0,0),P(0,0,-8))); check_no_intersection (box,R(P( 8,0,0),P(0,0,-8))); //yz check_no_intersection (box,R(P(0,-8,0),P(0,0, 8))); - check_no_intersection (box,R(P(0, 8,0),P(0,0, 8))); + check_no_intersection (box,R(P(0, 8,0),P(0,0, 8))); check_no_intersection (box,R(P(0,-8,0),P(0,0,-8))); check_no_intersection (box,R(P(0, 8,0),P(0,0,-8))); //xy check_no_intersection (box,R(P(0,-8,0),P(8,0,0))); - check_no_intersection (box,R(P(0, 8,0),P(8,0,0))); + check_no_intersection (box,R(P(0, 8,0),P(8,0,0))); check_no_intersection (box,R(P(0,-8,0),P(-8,0,0))); check_no_intersection (box,R(P(0, 8,0),P(-8,0,0))); //Intersecting //xz check_intersection (box,R(P(-0.5,0,0),P(0,0, 0.5))); - check_intersection (box,R(P( 0.5,0,0),P(0,0, 0.5))); + check_intersection (box,R(P( 0.5,0,0),P(0,0, 0.5))); check_intersection (box,R(P(-0.5,0,0),P(0,0,-0.5))); check_intersection (box,R(P( 0.5,0,0),P(0,0,-0.5))); //yz check_intersection (box,R(P(0,-0.5,0),P(0,0, 0.5))); - check_intersection (box,R(P(0, 0.5,0),P(0,0, 0.5))); + check_intersection (box,R(P(0, 0.5,0),P(0,0, 0.5))); check_intersection (box,R(P(0,-0.5,0),P(0,0,-0.5))); check_intersection (box,R(P(0, 0.5,0),P(0,0,-0.5))); //xy check_intersection (box,R(P(0,-0.5,0),P(0.5,0,0))); - check_intersection (box,R(P(0, 0.5,0),P(0.5,0,0))); + check_intersection (box,R(P(0, 0.5,0),P(0.5,0,0))); check_intersection (box,R(P(0,-0.5,0),P(-0.5,0,0))); check_intersection (box,R(P(0, 0.5,0),P(-0.5,0,0))); } @@ -566,85 +565,400 @@ struct Test { << do_intersect_counter << "\n"; } // end function Bbox_Tr - void Tet_L() + void Tet_L(bool is_exact) { std::cout << "Tetrahedron_3 - Line_3\n"; Tet tet(P(0,0,0), P(0,1,0), P(1,0,0), P(0,0,1)); - check_no_intersection (tet, L(P(5,0,0), P(5,1,0))); - check_intersection (tet, L(P(0,2,0), P(0,3,0)), S(P(0,0,0), P(0,1,0))); - check_intersection (tet, L(P(0,1,0), P(0.25,0,0.25)), S(P(0,1,0), P(0.25,0,0.25))); - check_intersection (tet, L(P(1,1,0), P(-1,1,0)), P(0,1,0)); + if(is_exact) + { + check_no_intersection (tet, L(P(5,0,0), P(5,1,0))); + check_intersection (tet, L(P(0,2,0), P(0,3,0)), S(P(0,0,0), P(0,1,0))); + check_intersection (tet, L(P(0,1,0), P(0.25,0,0.25)), S(P(0,1,0), P(0.25,0,0.25))); + check_intersection (tet, L(P(1,1,0), P(-1,1,0)), P(0,1,0)); + } } - void Tet_S() + void Tet_S(bool is_exact) { std::cout << "Tetrahedron_3 - Segment_3\n"; Tet tet(P(0,0,0), P(0,1,0), P(1,0,0), P(0,0,1)); - check_no_intersection (tet, S(P(5,0,0), P(5,1,0))); - check_intersection (tet, S(P(0,2,0), P(0,-2,0)), S(P(0,1,0), P(0,0,0))); - check_intersection (tet, S(P(0,1,0), P(0.25,0,0.25)), S(P(0,1,0), P(0.25,0,0.25))); - check_intersection (tet, S(P(2,1,0), P(-2,1,0)), P(0,1,0)); + if(is_exact) + { + check_no_intersection (tet, S(P(5,0,0), P(5,1,0))); + check_intersection (tet, S(P(0,2,0), P(0,-2,0)), S(P(0,1,0), P(0,0,0))); + check_intersection (tet, S(P(0,1,0), P(0.25,0,0.25)), S(P(0,1,0), P(0.25,0,0.25))); + check_intersection (tet, S(P(2,1,0), P(-2,1,0)), P(0,1,0)); - check_intersection (tet, S(P(0.1,0.1,0.1), P(0.2,0.2,0.2)), S(P(0.1,0.1,0.1), P(0.2,0.2,0.2))); - typename K::FT coord = 1.0/3.0; - check_intersection (tet, S(P(0.25,0.25,0.25), P(2,2,2)), S(P(0.25,0.25,0.25), P(coord, coord, coord))); + check_intersection (tet, S(P(0.1,0.1,0.1), P(0.2,0.2,0.2)), S(P(0.1,0.1,0.1), P(0.2,0.2,0.2))); + typename K::FT coord = 1.0/3.0; + check_intersection (tet, S(P(0.25,0.25,0.25), P(2,2,2)), S(P(0.25,0.25,0.25), P(coord, coord, coord))); + } + else + { + CGAL::intersection (tet, S(P(0,2,0), P(0,-2,0))); + CGAL::intersection (tet, S(P(0,1,0), P(0.25,0,0.25))); + CGAL::intersection (tet, S(P(2,1,0), P(-2,1,0))); + CGAL::intersection (tet, S(P(0.1,0.1,0.1), P(0.2,0.2,0.2))); + CGAL::intersection (tet, S(P(0.25,0.25,0.25), P(2,2,2))); + } } - void Tet_R() + void Tet_R(bool is_exact) { std::cout << "Tetrahedron_3 - Ray_3\n"; Tet tet(P(0,0,0), P(0,1,0), P(1,0,0), P(0,0,1)); - check_no_intersection (tet, R(P(5,0,0), P(5,1,0))); + if(is_exact) + { + check_no_intersection (tet, R(P(5,0,0), P(5,1,0))); - check_intersection (tet, R(P(0,2,0), P(0,-2,0)), S(P(0,1,0), P(0,0,0))); - check_intersection (tet, R(P(0,1,0), P(0.25,0,0.25)), S(P(0,1,0), P(0.25,0,0.25))); - check_intersection (tet, R(P(2,1,0), P(-2,1,0)), P(0,1,0)); + check_intersection (tet, R(P(0,2,0), P(0,-2,0)), S(P(0,1,0), P(0,0,0))); + check_intersection (tet, R(P(0,1,0), P(0.25,0,0.25)), S(P(0,1,0), P(0.25,0,0.25))); + check_intersection (tet, R(P(2,1,0), P(-2,1,0)), P(0,1,0)); - typename K::FT coord = 1.0/3.0; - check_intersection (tet, R(P(0.1,0.1,0.1), P(0.2,0.2,0.2)), S(P(0.1,0.1,0.1), P(coord, coord, coord))); - check_intersection (tet, R(P(0.25,0.25,0.25), P(2,2,2)), S(P(0.25,0.25,0.25), P(coord, coord, coord))); + typename K::FT coord = 1.0/3.0; + check_intersection (tet, R(P(0.1,0.1,0.1), P(0.2,0.2,0.2)), S(P(0.1,0.1,0.1), P(coord, coord, coord))); + check_intersection (tet, R(P(0.25,0.25,0.25), P(2,2,2)), S(P(0.25,0.25,0.25), P(coord, coord, coord))); + } + else + { + CGAL::intersection (tet, R(P(0,2,0), P(0,-2,0))); + CGAL::intersection (tet, R(P(0,1,0), P(0.25,0,0.25))); + CGAL::intersection (tet, R(P(2,1,0), P(-2,1,0))); + CGAL::intersection (tet, R(P(0.1,0.1,0.1), P(0.2,0.2,0.2))); + CGAL::intersection (tet, R(P(0.25,0.25,0.25), P(2,2,2))); + } } - void Tet_Pl() + void Tet_Pl(bool is_exact) { std::cout << "Tetrahedron_3 - Plane_3\n"; Tet tet(P(0,0,0), P(0,1,0), P(1,0,0), P(0,0,1)); - check_no_intersection (tet, Pl(P(2,0,0), - P(2,1,0), - P(2,0,1))); + if(is_exact) + { + check_no_intersection (tet, Pl(P(2,0,0), + P(2,1,0), + P(2,0,1))); - check_intersection (tet, Pl(P(0,2,0), P(0,0,0), P(0,0,1)), - Tr(P(0,0,0), P(0,1,0), P(0,0,1))); + check_intersection (tet, Pl(P(0,2,0), P(0,0,0), P(0,0,1)), + Tr(P(0,0,0), P(0,1,0), P(0,0,1))); - check_intersection (tet, Pl(P(0,1,0), P(1,0,0), P(0.5,0,-0.5)), - S(P(0,1,0), P(1,0,0))); + check_intersection (tet, Pl(P(0,1,0), P(1,0,0), P(0.5,0,-0.5)), + S(P(0,1,0), P(1,0,0))); - check_intersection (tet, Pl(P(-1,1,12), P(0,1,-50), P(0.5,1,-0.5)), - P(0,1,0)); + check_intersection (tet, Pl(P(-1,1,12), P(0,1,-50), P(0.5,1,-0.5)), + P(0,1,0)); - check_intersection (tet, Pl(P(0,0.5,0), P(1,0.5,-5), P(0.5,0.5,0.5)), - Tr(P(0.5,0.5,0), P(0,0.5,0), P(0,0.5,0.5))); - Pl pl(P(0,0.9,0), P(0.9,0,0), P(0.9,0.01,0.06)); + check_intersection (tet, Pl(P(0,0.5,0), P(1,0.5,-5), P(0.5,0.5,0.5)), + Tr(P(0.5,0.5,0), P(0,0.5,0), P(0,0.5,0.5))); + Pl pl(P(0,0.9,0), P(0.9,0,0), P(0.9,0.01,0.06)); + + typedef typename CGAL::Intersection_traits::result_type Res; + + + //Don't have the right values to test further. + Res res = CGAL::intersection (tet, pl); + + const std::vector

* poly = boost::get >(&*res); + CGAL_assertion(poly != nullptr); + CGAL_assertion(poly->size() == 4); + } + else + { + CGAL::intersection (tet, Pl(P(0,2,0), P(0,0,0), P(0,0,1))); + CGAL::intersection (tet, Pl(P(0,1,0), P(1,0,0), P(0.5,0,-0.5))); + CGAL::intersection (tet, Pl(P(-1,1,12), P(0,1,-50), P(0.5,1,-0.5))); + CGAL::intersection (tet, Pl(P(0,0.5,0), P(1,0.5,-5), P(0.5,0.5,0.5))); + } + + } + + void Tet_Tr(bool is_exact) + { + std::cout << "Tetrahedron_3 - Triangle_3\n"; typedef typename CGAL::Intersection_traits::result_type Res; - assert(CGAL::do_intersect(tet, pl)); - //Don't have the right values to test further. + typename K::Triangle_3>::result_type Res; + + Tet tet(P(0,0,0), P(0,1,0), P(1,0,0), P(0,0,1)); + if(is_exact) + { + check_no_intersection (tet, Tr(P(2,0,0), + P(2,1,0), + P(2,0,1))); + + //tr inside a face + check_intersection (tet, Tr(P(0,0.9,0), P(0,0.1,0), P(0,0,0.9)), + Tr(P(0,0.9,0), P(0,0.1,0), P(0,0,0.9))); + //face inside tr + check_intersection (tet, Tr(P(0,2,0), P(0,-2,0), P(0,0,2)), + Tr(P(0,0,1), P(0,0,0), P(0,1,0))); + + Tr tr(P(-2,2,0), P(2,2,0), P(0.25,0.25,0)); + + Res res = CGAL::intersection(tet, tr); + const std::vector

* poly = boost::get >(&*res); + CGAL_assertion(poly != nullptr); + CGAL_assertion(poly->size() == 4); + for(auto p : *poly) + { + CGAL_assertion(tet.has_on_boundary(p) && tr.has_on(p)); + } + + //only one edge intersecting + check_intersection (tet, Tr(P(-2, 0.5, 0.5), P(-2,0.75,1), P(1.5, 0.5, 0.5)), + P(0,0.5,0.5)); + + + //edge shared, 3rd point outside + check_intersection (tet, Tr(P(0,1,0), P(1,0,0), P(0.5,0,-100)), + S(P(0,1,0), P(1,0,0))); + + //shared edge, 3rd point inside + check_intersection (tet, Tr(P(0,1,0), P(1,0,0), P(0.25,0.25,0.25)), + Tr(P(0,1,0), P(1,0,0), P(0.25,0.25,0.25))); + + //tr adjacent to a vertex, outside + check_intersection (tet, Tr(P(-1,1,12), P(0,1,-50), P(0.5,1,-0.5)), + P(0,1,0)); + + //tr adjacent to an edge, outside + check_intersection (tet, Tr(P(-0.6, 1, 0.6), + P(0.5, 1.20, -0.5), + P(0, -0.5, 0)), + S(P(0,0,0), P(0,1,0))); + + + //tr share a vertex, inside + check_intersection (tet, Tr(P(0,1,0), P(0.1,0.1,0), P(0.5,0.1,0)), + Tr(P(0,1,0), P(0.1,0.1,0), P(0.5,0.1,0))); + + //tr edge adjacent to a vertex + check_intersection (tet, Tr(P(-1,1,0), P(3,1,0), P(0,3,0)), + P(0,1,0)); + + //tr vertex adjacent to a vertex + check_intersection (tet, Tr(P(0,1,0), P(3,1,0), P(0,3,0)), + P(0,1,0)); + + + //traversing triangles + tr = Tr(P(-2, 0.5, 0.25), + P(-2, 0.75, 0.6), + P(1.5, 0.5, 0.25)); + + res = CGAL::intersection(tet, tr); + + + std::vector

* inter = boost::get >(&*res); + CGAL_assertion(inter != nullptr); + CGAL_assertion(inter->size() == 4); + for(auto p : *inter) + { + CGAL_assertion(tet.has_on_boundary(p) && tr.has_on(p)); + } + + tr = Tr(P(-2, 0.25, 0), + P(-2, 0.75, 0), + P(1.5, 0.5, 0)); + + res = CGAL::intersection(tet, tr); + + + inter = boost::get >(&*res); + CGAL_assertion(inter != nullptr); + CGAL_assertion(inter->size() == 4); + for(auto p : *inter) + { + CGAL_assertion(tet.has_on_boundary(p) && tr.has_on(p)); + } + + tr = Tr(P(0.2, 0.15, 0.3), + P(-2, 0.6, 0.15), + P(-2, 0.12, 0.15)); + + res = CGAL::intersection(tet, tr); + Tr* res_tr = boost::get(&*res); + CGAL_assertion(res_tr != nullptr); + + tr = Tr(P(0.2, 0.15, 0.3), + P(-1, 0.15, -2), + P(-1, 0.15, 2)); + + res = CGAL::intersection(tet, tr); + + + inter = boost::get >(&*res); + CGAL_assertion(inter != nullptr); + CGAL_assertion(inter->size() == 4); + + tr = Tr(P(0.45, 0.20, 0.1), + P(0.1, 0.20, 0.5), + P(-0.5, 0.25, -0.5)); + + res = CGAL::intersection(tet, tr); + + + inter = boost::get >(&*res); + CGAL_assertion(inter != nullptr); + CGAL_assertion(inter->size() == 4); + + for(auto p : *inter) + { + CGAL_assertion( + (tet.has_on_bounded_side(p) || tet.has_on_boundary(p)) + && tr.has_on(p)); + } + + //tr share a vertex, through + tr = Tr(P(0,1,0), P(0.1,0.1,0), P(0.9,0.1,0)); + res = CGAL::intersection(tet, tr); + res_tr = boost::get(&*res); + CGAL_assertion(res_tr != nullptr); + + + tr = Tr(P(0.1, 0.5, 0.1), P(0.3,0.1,0.1), P(4,0.3,0.9)); + res = CGAL::intersection(tet, tr); + inter = boost::get >(&*res); + CGAL_assertion(inter != nullptr); + CGAL_assertion(inter->size() == 4); + } + else + { + //tr inside a face + CGAL::intersection(tet, Tr(P(0,0.9,0), P(0,0.1,0), P(0,0,0.9))); + //face inside tr + CGAL::intersection(tet, Tr(P(0,2,0), P(0,-2,0), P(0,0,2))); + + //only one edge intersecting + CGAL::intersection(tet, Tr(P(-2, 0.5, 0.5), P(-2,0.75,1), P(1.5, 0.5, 0.5))); + + //edge shared, 3rd point outside + CGAL::intersection(tet, Tr(P(0,1,0), P(1,0,0), P(0.5,0,-100))); + + //shared edge, 3rd point inside + CGAL::intersection(tet, Tr(P(0,1,0), P(1,0,0), P(0.25,0.25,0.25))); + + //tr adjacent to a vertex, outside + CGAL::intersection(tet, Tr(P(-1,1,12), P(0,1,-50), P(0.5,1,-0.5))); + + //tr share a vertex, inside + CGAL::intersection(tet, Tr(P(0,1,0), P(0.1,0.1,0), P(0.5,0.1,0))); + + //tr edge adjacent to a vertex + CGAL::intersection(tet, Tr(P(-1,1,0), P(3,1,0), P(0,3,0))); + + //tr vertex adjacent to a vertex + CGAL::intersection(tet, Tr(P(0,1,0), P(3,1,0), P(0,3,0))); + + typedef typename CGAL::Intersection_traits::result_type Res; + //traversing triangles + Tr tr(P(-2, 0.5, 0.25), + P(-2, 0.75, 0.6), + P(1.5, 0.5, 0.25)); + + Res res = CGAL::intersection(tet, tr); + + //tr share a vertex, through + tr = Tr(P(0,1,0), P(0.1,0.1,0), P(0.9,0.1,0)); + res = CGAL::intersection(tet, tr); + } } + void Pl_Cub(bool is_exact) + { + std::cout << "Plane_3 - Cuboid_3\n"; + + Cub cub(P(1,1,1), P(2,2,2)); + + if(is_exact) + { + check_no_intersection (cub, Pl(P(3,0,0), + P(3,1,0), + P(3,0,1))); + + //edge + check_intersection (cub, Pl(P(1,1,1), P(1,2,1), P(1.5,0,0)), + S(P(1,2,1), P(1,1,1))); + //face + typedef typename CGAL::Intersection_traits::result_type Res; + Res res = CGAL::intersection(cub, Pl(P(1,1,1), P(1,2,1), P(1,2,2))); + + const std::vector

* poly = boost::get >(&*res); + CGAL_assertion(poly != nullptr); + CGAL_assertion(poly->size() == 4); + for(auto p : *poly) + { + CGAL_assertion(p.x() == 1); + } + res = CGAL::intersection(cub, Pl(P(1,1,1), P(1,2,1), P(2,2,2))); + poly = boost::get >(&*res); + CGAL_assertion(poly != nullptr); + CGAL_assertion(poly->size() == 4); + for(auto p : *poly) + { + CGAL_assertion(cub.has_on_boundary(p)); + } + //vertex + check_intersection (cub, Pl(0.5, -0.5, -0.5, 0), + P(2,1,1)); + //triangle + + check_intersection (cub, Pl(P(2, 1.66, 2), + P(1.66,2,2), + P(2,2,1.66)), + Tr(P(2, 1.66, 2), + P(1.66,2,2), + P(2,2,1.66))); + //random + Pl pl(0.265189, 0.902464, 0.33946, -2.47551); + res = CGAL::intersection(cub, pl); + poly = boost::get >(&*res); + CGAL_assertion(poly != nullptr); + CGAL_assertion(poly->size() == 5); + for(auto p : *poly) + { + CGAL_assertion(pl.has_on(p) && cub.has_on_boundary(p)); + } + } + else + { + CGAL::intersection(cub, Pl(P(1,1,1), P(1,2,1), P(1.5,0,0))); + //face + typedef typename CGAL::Intersection_traits::result_type Res; + Res res = CGAL::intersection(cub, Pl(P(1,1,1), P(1,2,1), P(1,2,2))); + res = CGAL::intersection(cub, Pl(P(1,1,1), P(1,2,1), P(2,2,2))); + CGAL::intersection (cub, Pl(0.5, -0.5, -0.5, 0)); + CGAL::intersection (cub, Pl(P(2, 1.66, 2), + P(1.66,2,2), + P(2,2,1.66))); + Pl pl(0.265189, 0.902464, 0.33946, -2.47551); + res = CGAL::intersection(cub, pl); + } + } + + void run(bool is_exact = false) { std::cout << "3D Intersection tests\n"; + /* P_do_intersect(); - /* Cub_Cub(); + Cub_Cub(); L_Cub(); Pl_L(); Pl_Pl(); @@ -658,12 +972,15 @@ struct Test { R_L(); R_S(); R_R();*/ - if(is_exact){ - Tet_L(); - Tet_S(); - Tet_R(); - Tet_Pl(); - } + + //If not exact, only check that it doesn't crash{ + //Tet_L(is_exact); + //Tet_S(is_exact); + //Tet_R(is_exact); + //Tet_Pl(is_exact); + Tet_Tr(is_exact); + // Pl_Cub(is_exact); + //} /* Bbox_L(); Bbox_R(); @@ -678,6 +995,6 @@ int main() Test< CGAL::Simple_cartesian >().run(); Test< CGAL::Homogeneous >().run(); Test< CGAL::Epeck >().run(true); - // TODO : test more kernels. + // TODO : test more kernels. }