Add Kernel::Construct_exact_intersection_point_2

This commit is contained in:
Laurent Rineau 2022-05-31 16:40:34 +02:00
parent e60a6327be
commit feaf6a4ca2
7 changed files with 164 additions and 26 deletions

View File

@ -61,6 +61,8 @@ struct Filtered_kernel_base
enum { Has_filtered_predicates = true };
typedef Boolean_tag<Has_filtered_predicates> Has_filtered_predicates_tag;
typedef Tag_true Can_construct_exact_intersection_point_2;
template < typename Kernel2 >
struct Base {
typedef typename CK::template Base<Kernel2> CK2;

View File

@ -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 <class CK, class Rep = typename CK::Rep_tag /* Cartesian_tag */>
struct Exact_kernel_selector;
}
#endif // CGAL_EXACT_KERNEL_SELECTOR_FWD_H

View File

@ -27,6 +27,8 @@
#include <CGAL/Intersections_2/Line_2_Line_2.h>
#include <CGAL/Uncertain.h>
#include <CGAL/Intersection_traits_2.h>
#include <CGAL/Cartesian_converter.h>
#include <CGAL/Exact_kernel_selector_fwd.h>
namespace CGAL {
@ -456,6 +458,33 @@ intersection(const typename K::Segment_2 &seg1,
}
}
template <class K>
boost::optional<typename K::Point_2>
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<K>::Exact_kernel;
using EK_Line_2 = typename EK::Line_2;
using EK_Point_2 = typename EK::Point_2;
Cartesian_converter<K, EK> to_exact;
Cartesian_converter<EK, K> 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<EK_Point_2>(&*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 <CGAL/Exact_kernel_selector.h>
#endif

View File

@ -29,9 +29,11 @@
#include <CGAL/Cartesian_converter.h>
#include <CGAL/Homogeneous_converter.h>
#include <CGAL/Exact_kernel_selector_fwd.h>
namespace CGAL {
template <class CK, class Rep = typename CK::Rep_tag /* Cartesian_tag */>
template <class CK, class Rep /* = typename CK::Rep_tag (Cartesian_tag) */>
struct Exact_kernel_selector
{
typedef typename internal::Exact_field_selector<typename CK::RT>::Type Exact_nt;

View File

@ -3553,6 +3553,17 @@ namespace CommonKernelFunctors {
{ return Intersections::internal::intersection(t1, t2, K()); }
};
template <typename K>
class Construct_exact_intersection_point_2
{
public:
template <class... T>
decltype(auto)
operator()(const T&... t) const
{ return Intersections::internal::exact_intersection_point(t..., K()); }
};
template <typename K>
class Intersect_3
{

View File

@ -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,

View File

@ -28,10 +28,11 @@
#include <CGAL/Default.h>
#include <CGAL/intersections.h>
#include <CGAL/squared_distance_2.h>
#include <CGAL/Exact_rational.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/tags.h>
#include <boost/mpl/if.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/iterator/filter_iterator.hpp>
#include <boost/utility/result_of.hpp>
@ -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<Exact_rational>;
using EK_Line_2 = EK::Line_2;
using EK_Point_2 = EK::Point_2;
Cartesian_converter<Gt, EK> to_exact;
Cartesian_converter<EK, Gt> 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<EK_Point_2>(&*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) {
@ -1853,6 +1842,82 @@ limit_intersection(const Gt& gt,
return i;
}
BOOST_MPL_HAS_XXX_TRAIT_DEF(Can_construct_exact_intersection_point_2)
template <typename Gt,
bool = has_Can_construct_exact_intersection_point_2<Gt>::value>
struct Can_construct_almost_exact_intersection
: public CGAL::Boolean_tag<
Gt::Can_construct_exact_intersection_point_2::value> {};
template <typename Gt>
struct Can_construct_almost_exact_intersection<Gt, false>
: public CGAL::Tag_false {};
template <typename Gt>
constexpr bool can_construct_almost_exact_intersection(const Gt&, Exact_predicates_tag) {
return Can_construct_almost_exact_intersection<Gt>::value;
}
template <typename Gt, typename Tag>
constexpr bool can_construct_almost_exact_intersection(const Gt&, Tag) {
return false;
}
template <typename Gt, typename Tag>
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 <typename Gt>
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<Can_construct_almost_exact_intersection<Gt>::value> tag;
return almost_exact_intersection(gt, pa, pb, pc, pd, pi, tag);
}
template <typename Gt>
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 <typename Gt>
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 <CGAL/enable_warnings.h>