diff --git a/Filtered_kernel/include/CGAL/Filtered_kernel.h b/Filtered_kernel/include/CGAL/Filtered_kernel.h index 81b8bd4d07d..06a9fa53829 100644 --- a/Filtered_kernel/include/CGAL/Filtered_kernel.h +++ b/Filtered_kernel/include/CGAL/Filtered_kernel.h @@ -61,6 +61,8 @@ struct Filtered_kernel_base enum { Has_filtered_predicates = true }; typedef Boolean_tag Has_filtered_predicates_tag; + typedef Tag_true Can_construct_exact_intersection_point_2; + template < typename Kernel2 > struct Base { typedef typename CK::template Base CK2; diff --git a/Installation/include/CGAL/Exact_kernel_selector_fwd.h b/Installation/include/CGAL/Exact_kernel_selector_fwd.h new file mode 100644 index 00000000000..8f0213606a7 --- /dev/null +++ b/Installation/include/CGAL/Exact_kernel_selector_fwd.h @@ -0,0 +1,25 @@ +// Copyright (c) 2017 +// Utrecht University (The Netherlands), +// ETH Zurich (Switzerland), +// INRIA Sophia-Antipolis (France), +// Max-Planck-Institute Saarbruecken (Germany), +// and Tel-Aviv University (Israel). All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Sylvain Pion, +// Mael Rouxel-Labbé + +#ifndef CGAL_EXACT_KERNEL_SELECTOR_FWD_H +#define CGAL_EXACT_KERNEL_SELECTOR_FWD_H + +namespace CGAL { +template +struct Exact_kernel_selector; +} + +#endif // CGAL_EXACT_KERNEL_SELECTOR_FWD_H diff --git a/Intersections_2/include/CGAL/Intersections_2/Segment_2_Segment_2.h b/Intersections_2/include/CGAL/Intersections_2/Segment_2_Segment_2.h index 19d1b300232..e7725ea561c 100644 --- a/Intersections_2/include/CGAL/Intersections_2/Segment_2_Segment_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/Segment_2_Segment_2.h @@ -27,6 +27,8 @@ #include #include #include +#include +#include namespace CGAL { @@ -456,6 +458,33 @@ intersection(const typename K::Segment_2 &seg1, } } +template +boost::optional +exact_intersection_point(const typename K::Point_2& pa, + const typename K::Point_2& pb, + const typename K::Point_2& pc, + const typename K::Point_2& pd, + const K&) +{ + using EK = typename Exact_kernel_selector::Exact_kernel; + using EK_Line_2 = typename EK::Line_2; + using EK_Point_2 = typename EK::Point_2; + Cartesian_converter to_exact; + Cartesian_converter from_exact; + typename EK::Intersect_2 exact_intersect; + const auto exact_intersection = + exact_intersect(EK_Line_2{to_exact(pa), to_exact(pb)}, + EK_Line_2{to_exact(pc), to_exact(pd)}); + if(!exact_intersection.has_value()) return {}; + using boost::get; + if (const auto *p = get(&*exact_intersection)) { + return { from_exact(*p) }; + } else { + return {}; + } + +} + } // namespace internal } // namespace Intersections @@ -464,4 +493,6 @@ CGAL_DO_INTERSECT_FUNCTION_SELF(Segment_2, 2) } //namespace CGAL +#include + #endif diff --git a/Kernel_23/include/CGAL/Exact_kernel_selector.h b/Kernel_23/include/CGAL/Exact_kernel_selector.h index 9929cb5a02b..23ed23d3afb 100644 --- a/Kernel_23/include/CGAL/Exact_kernel_selector.h +++ b/Kernel_23/include/CGAL/Exact_kernel_selector.h @@ -29,9 +29,11 @@ #include #include +#include + namespace CGAL { -template +template struct Exact_kernel_selector { typedef typename internal::Exact_field_selector::Type Exact_nt; diff --git a/Kernel_23/include/CGAL/Kernel/function_objects.h b/Kernel_23/include/CGAL/Kernel/function_objects.h index 2bc9704ed04..6c00b7591aa 100644 --- a/Kernel_23/include/CGAL/Kernel/function_objects.h +++ b/Kernel_23/include/CGAL/Kernel/function_objects.h @@ -3553,6 +3553,17 @@ namespace CommonKernelFunctors { { return Intersections::internal::intersection(t1, t2, K()); } }; + template + class Construct_exact_intersection_point_2 + { + public: + + template + decltype(auto) + operator()(const T&... t) const + { return Intersections::internal::exact_intersection_point(t..., K()); } + }; + template class Intersect_3 { diff --git a/Kernel_23/include/CGAL/Kernel/interface_macros.h b/Kernel_23/include/CGAL/Kernel/interface_macros.h index d0ba827fa37..e0d6c57bbf6 100644 --- a/Kernel_23/include/CGAL/Kernel/interface_macros.h +++ b/Kernel_23/include/CGAL/Kernel/interface_macros.h @@ -302,6 +302,8 @@ CGAL_Kernel_cons(Construct_circumcenter_3, construct_circumcenter_3_object) CGAL_Kernel_cons(Construct_weighted_circumcenter_3, construct_weighted_circumcenter_3_object) +CGAL_Kernel_cons(Construct_exact_intersection_point_2, + construct_exact_intersection_point_2_object) CGAL_Kernel_cons(Compute_power_product_2, compute_power_product_2_object) CGAL_Kernel_cons(Compute_power_product_3, diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index 57c36a5ee36..9f8f515eccd 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -28,10 +28,11 @@ #include #include #include -#include -#include +#include + #include +#include #include #include @@ -1132,25 +1133,13 @@ intersect(Face_handle f, int i, } } else{ //intersection computed - if(intersection_not_in_the_two_triangle(pi)) { + if(can_construct_almost_exact_intersection(geom_traits(), itag) && + intersection_not_in_the_two_triangle(pi)) + { // now compute the exact intersection point - using EK = Simple_cartesian; - using EK_Line_2 = EK::Line_2; - using EK_Point_2 = EK::Point_2; - Cartesian_converter to_exact; - Cartesian_converter from_exact; - EK::Intersect_2 exact_intersect; - auto exact_intersection = - exact_intersect(EK_Line_2{to_exact(pa), to_exact(pb)}, - EK_Line_2{to_exact(pc), to_exact(pd)}); - CGAL_assertion(exact_intersection.has_value()); - using boost::get; - if (const auto *p = get(&*exact_intersection)) { - pi = from_exact(*p); - } else { - CGAL_error(); - } - if(intersection_not_in_the_two_triangle(pi)) { + const bool result = + almost_exact_intersection(geom_traits(), pa, pb, pc, pd, pi, itag); + if (!result || intersection_not_in_the_two_triangle(pi)) { // If the most-exact intersection point is not in the union of the two // triangles, then snap to `pc` or `pd`... if(compare_distance(pi, pc, pd) == SMALLER) { @@ -1831,11 +1820,11 @@ limit_intersection(const Gt& , template int limit_intersection(const Gt& gt, - const typename Gt::Point_2& pa, - const typename Gt::Point_2& pb, - const typename Gt::Point_2& pc, - const typename Gt::Point_2& pd, - Exact_predicates_tag) + const typename Gt::Point_2& pa, + const typename Gt::Point_2& pb, + const typename Gt::Point_2& pc, + const typename Gt::Point_2& pd, + Exact_predicates_tag) { typename Gt::Construct_line_2 line = gt.construct_line_2_object(); typename Gt::Compute_squared_distance_2 @@ -1853,6 +1842,82 @@ limit_intersection(const Gt& gt, return i; } +BOOST_MPL_HAS_XXX_TRAIT_DEF(Can_construct_exact_intersection_point_2) + +template ::value> +struct Can_construct_almost_exact_intersection + : public CGAL::Boolean_tag< + Gt::Can_construct_exact_intersection_point_2::value> {}; + +template +struct Can_construct_almost_exact_intersection + : public CGAL::Tag_false {}; + +template +constexpr bool can_construct_almost_exact_intersection(const Gt&, Exact_predicates_tag) { + return Can_construct_almost_exact_intersection::value; +} + +template +constexpr bool can_construct_almost_exact_intersection(const Gt&, Tag) { + return false; +} + +template +bool almost_exact_intersection(const Gt&, + const typename Gt::Point_2&, + const typename Gt::Point_2&, + const typename Gt::Point_2&, + const typename Gt::Point_2&, + typename Gt::Point_2&, + Tag) +{ + CGAL_error_msg("this function should be call only with Exact_predicates_tag"); +} + +template +bool almost_exact_intersection(const Gt& gt, + const typename Gt::Point_2& pa, + const typename Gt::Point_2& pb, + const typename Gt::Point_2& pc, + const typename Gt::Point_2& pd, + typename Gt::Point_2& pi, + Exact_predicates_tag) +{ + Boolean_tag::value> tag; + return almost_exact_intersection(gt, pa, pb, pc, pd, pi, tag); +} + +template +bool almost_exact_intersection(const Gt&, + const typename Gt::Point_2&, + const typename Gt::Point_2&, + const typename Gt::Point_2&, + const typename Gt::Point_2&, + typename Gt::Point_2&, + Tag_false) +{ + CGAL_error_msg("this function should be call only with Exact_predicates_tag" + " and with an appropriate traits class"); +} + +template +bool almost_exact_intersection(const Gt& gt, + const typename Gt::Point_2& pa, + const typename Gt::Point_2& pb, + const typename Gt::Point_2& pc, + const typename Gt::Point_2& pd, + typename Gt::Point_2& pi, + Tag_true /* gt has Construct_exact_intersection_point_2 */) +{ + auto exact_intersect = gt.construct_exact_intersection_point_2_object(); + const auto exact_intersection = exact_intersect(pa, pb, pc, pd); + if(!exact_intersection.has_value()) return false; + pi = *exact_intersection; + return true; +} + } //namespace CGAL #include