diff --git a/Filtered_kernel/include/CGAL/Filtered_kernel/internal/Static_filters/Has_on_bounded_side_3.h b/Filtered_kernel/include/CGAL/Filtered_kernel/internal/Static_filters/Has_on_bounded_side_3.h new file mode 100644 index 00000000000..02ee904b5f4 --- /dev/null +++ b/Filtered_kernel/include/CGAL/Filtered_kernel/internal/Static_filters/Has_on_bounded_side_3.h @@ -0,0 +1,225 @@ +// Copyright (c) 2026 GeometryFactory Sarl (France) +// 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) : Sven Oesau + + +#ifndef CGAL_INTERNAL_STATIC_FILTERS_HAS_ON_BOUNDED_SIDE_3_H +#define CGAL_INTERNAL_STATIC_FILTERS_HAS_ON_BOUNDED_SIDE_3_H + +#include +#include +#include +#include + +namespace CGAL { + +namespace internal { + +namespace Static_filters_predicates { + + +template < typename K_base > +class Has_on_bounded_side_3 + : public K_base::Has_on_bounded_side_3 +{ + typedef typename K_base::Boolean Boolean; + typedef typename K_base::Point_3 Point_3; + typedef typename K_base::Sphere_3 Sphere_3; + typedef typename K_base::Iso_cuboid_3 Iso_cuboid_3; + typedef typename K_base::Has_on_bounded_side_3 Base; + +public: + using Base::operator(); + + Boolean + operator()(const Sphere_3& s, const Iso_cuboid_3& b) const + { + CGAL_BRANCH_PROFILER_3(std::string("semi-static failures/attempts/calls to : ") + + std::string(CGAL_PRETTY_FUNCTION), tmp); + + Get_approx get_approx; // Identity functor for all points + const Point_3& c = s.center(); + + double scx, scy, scz, ssr; + double bxmin = b.xmin(), bymin = b.ymin(), bzmin = b.zmin(), + bxmax = b.xmax(), bymax = b.ymax(), bzmax = b.zmax(); + + if (fit_in_double(get_approx(c).x(), scx) && + fit_in_double(get_approx(c).y(), scy) && + fit_in_double(get_approx(c).z(), scz) && + fit_in_double(s.squared_radius(), ssr)) + { + CGAL_BRANCH_PROFILER_BRANCH_1(tmp); + + if ((ssr < 1.11261183279326254436e-293) || (ssr > 2.80889552322236673473e+306)) { + CGAL_BRANCH_PROFILER_BRANCH_2(tmp); + return Base::operator()(s, b); + } + double distance = 0; + double max1 = 0; + double double_tmp_result = 0; + double eps = 0; + if (scx < bxmin) + { + double bxmax_scx = bxmax - scx; + max1 = bxmax_scx; + + distance = square(bxmax_scx); + double_tmp_result = (distance - ssr); + + if ((max1 < 3.33558365626356687717e-147) || (max1 > 1.67597599124282407923e+153)) { + CGAL_BRANCH_PROFILER_BRANCH_2(tmp); + return Base::operator()(s, b); + } + + eps = 1.99986535548615598560e-15 * (std::max)(ssr, square(max1)); + + if (double_tmp_result > eps) { + return false; + } + } + else if (scx > bxmax) + { + double scx_bxmix = scx - bxmin; + max1 = scx_bxmix; + + distance = square(scx_bxmix); + double_tmp_result = (distance - ssr); + + if ((max1 < 3.33558365626356687717e-147) || (max1 > 1.67597599124282407923e+153)) { + CGAL_BRANCH_PROFILER_BRANCH_2(tmp); + return Base::operator()(s, b); + } + + eps = 1.99986535548615598560e-15 * (std::max)(ssr, square(max1)); + + if (double_tmp_result > eps) { + return false; + } + } + + + if (scy < bymin) + { + double bymax_scy = bymax - scy; + if (max1 < bymax_scy) { + max1 = bymax_scy; + } + + distance += square(bymax_scy); + double_tmp_result = (distance - ssr); + + if ((max1 < 3.33558365626356687717e-147) || ((max1 > 1.67597599124282407923e+153))) { + CGAL_BRANCH_PROFILER_BRANCH_2(tmp); + return Base::operator()(s, b); + } + + eps = 1.99986535548615598560e-15 * (std::max)(ssr, square(max1)); + + if (double_tmp_result > eps) { + return false; + } + } + else if (scy > bymax) + { + double scy_bymin = scy - bymin; + if (max1 < scy_bymin) { + max1 = scy_bymin; + } + distance += square(scy_bymin); + double_tmp_result = (distance - ssr); + + if (((max1 < 3.33558365626356687717e-147)) || ((max1 > 1.67597599124282407923e+153))) { + CGAL_BRANCH_PROFILER_BRANCH_2(tmp); + return Base::operator()(s, b); + } + + eps = 1.99986535548615598560e-15 * (std::max)(ssr, square(max1)); + + if (double_tmp_result > eps) { + return false; + } + } + + + if (scz < bzmin) + { + double bzmax_scz = bzmax - scz; + if (max1 < bzmax_scz) { + max1 = bzmax_scz; + } + distance += square(bzmax_scz); + double_tmp_result = (distance - ssr); + + if (((max1 < 3.33558365626356687717e-147)) || ((max1 > 1.67597599124282407923e+153))) { + CGAL_BRANCH_PROFILER_BRANCH_2(tmp); + return Base::operator()(s, b); + } + + eps = 1.99986535548615598560e-15 * (std::max)(ssr, square(max1)); + + if (double_tmp_result > eps) { + return false; + } + } + else if (scz > bzmax) + { + double scz_bzmin = scz - bzmin; + if (max1 < scz_bzmin) { + max1 = scz_bzmin; + } + + distance += square(scz_bzmin); + double_tmp_result = (distance - ssr); + + if (((max1 < 3.33558365626356687717e-147)) || ((max1 > 1.67597599124282407923e+153))) { + CGAL_BRANCH_PROFILER_BRANCH_2(tmp); + return Base::operator()(s, b); + } + + eps = 1.99986535548615598560e-15 * (std::max)(ssr, square(max1)); + + if (double_tmp_result > eps) { + return false; + } + } + + // double_tmp_result and eps were growing all the time + // no need to test for > eps as done earlier in at least one case + if (double_tmp_result < -eps) { + return true; + } + else { + CGAL_BRANCH_PROFILER_BRANCH_2(tmp); + return Base::operator()(s, b); + } + + CGAL_BRANCH_PROFILER_BRANCH_2(tmp); + } + return Base::operator()(s, b); + } + + Boolean + operator()(const Iso_cuboid_3& b, const Sphere_3& s) const + { + this->operator()(s, b); + } + + +}; // end class Has_on_bounded_side_3 + +} // end namespace Static_filters_predicates + +} // end namespace internal + +} // end namespace CGAL + +#endif // CGAL_INTERNAL_STATIC_FILTERS_HAS_ON_BOUNDED_SIDE_3_H diff --git a/Filtered_kernel/include/CGAL/Filtered_kernel/internal/Static_filters/Static_filters.h b/Filtered_kernel/include/CGAL/Filtered_kernel/internal/Static_filters/Static_filters.h index 04456597083..a785821de66 100644 --- a/Filtered_kernel/include/CGAL/Filtered_kernel/internal/Static_filters/Static_filters.h +++ b/Filtered_kernel/include/CGAL/Filtered_kernel/internal/Static_filters/Static_filters.h @@ -62,7 +62,7 @@ #ifndef CGAL_NO_DO_INTERSECT_STATIC_FILTERS # include # include -#endif // NOT NOT CGAL_NO_DO_INTERSECT_STATIC_FILTERS +#endif // NOT CGAL_NO_DO_INTERSECT_STATIC_FILTERS #include #include @@ -73,6 +73,7 @@ #include #include #include +#include // #include // #include @@ -129,6 +130,7 @@ public: typedef Static_filters_predicates::Power_side_of_oriented_power_sphere_3 Power_side_of_oriented_power_sphere_3; typedef Static_filters_predicates::Compare_distance_3 Compare_distance_3; + typedef Static_filters_predicates::Has_on_bounded_side_3 Has_on_bounded_side_3; Orientation_2 orientation_2_object() const @@ -207,6 +209,10 @@ public: compare_distance_3_object() const { return Compare_distance_3();} + Has_on_bounded_side_3 + has_on_bounded_side_3_object() const + { return Has_on_bounded_side_3(); } + enum { Has_static_filters = true }; diff --git a/Kernel_23/doc/Kernel_23/CGAL/Circle_2.h b/Kernel_23/doc/Kernel_23/CGAL/Circle_2.h index 2c1d8dc3d0f..ad760615bef 100644 --- a/Kernel_23/doc/Kernel_23/CGAL/Circle_2.h +++ b/Kernel_23/doc/Kernel_23/CGAL/Circle_2.h @@ -175,6 +175,11 @@ bool has_on_bounded_side(const Segment_2 &s) const; */ bool has_on_unbounded_side(const Point_2& p) const; +/*! +returns whether the segment `s` lies on the unbounded side of the circle `c`. +*/ +bool has_on_unbounded_side(const Segment_2& s) const; + /// @} /// \name Miscellaneous diff --git a/Kernel_23/doc/Kernel_23/CGAL/Sphere_3.h b/Kernel_23/doc/Kernel_23/CGAL/Sphere_3.h index aa9e272a1c2..1d787614be9 100644 --- a/Kernel_23/doc/Kernel_23/CGAL/Sphere_3.h +++ b/Kernel_23/doc/Kernel_23/CGAL/Sphere_3.h @@ -191,15 +191,6 @@ The corner points of `b` are allowed to be on the boundary of `c`. */ bool has_on_bounded_side(const Iso_cuboid_3 &b) const -/*! -returns whether the axis-aligned bounding box defined by the corner points (`bxmin`, `bymin`, `bzmin`) -and (`bxmax`, `bymax`, `bzmax`) lies on the bounded side of the sphere `c`. -The corner points are allowed to be on the boundary of `c`. -*/ -template< typename BFT > -bool has_on_bounded_side(const BFT bxmin, const BFT bymin, const BFT bzmin, - const BFT bxmax, const BFT bymax, const BFT bzmax) const - /*! */ diff --git a/Kernel_23/include/CGAL/Circle_2.h b/Kernel_23/include/CGAL/Circle_2.h index 5935df5cc2d..d6401d9810a 100644 --- a/Kernel_23/include/CGAL/Circle_2.h +++ b/Kernel_23/include/CGAL/Circle_2.h @@ -139,10 +139,7 @@ public: typename R::Boolean has_on_bounded_side(const Segment_2& s) const { - if ((center() - s.source()).squared_length() > squared_radius()) - return false; - - return (center() - s.target()).squared_length() <= squared_radius(); + return R().has_on_bounded_side_2_object()(*this, s); } typename R::Boolean diff --git a/Kernel_23/include/CGAL/Kernel/function_objects.h b/Kernel_23/include/CGAL/Kernel/function_objects.h index b71470a6262..86521dc1363 100644 --- a/Kernel_23/include/CGAL/Kernel/function_objects.h +++ b/Kernel_23/include/CGAL/Kernel/function_objects.h @@ -3548,12 +3548,22 @@ namespace CommonKernelFunctors { typedef typename K::Iso_rectangle_2 Iso_rectangle_2; typedef typename K::Circle_2 Circle_2; typedef typename K::Triangle_2 Triangle_2; + typedef typename K::Segment_2 Segment_2; public: Boolean operator()( const Circle_2& c, const Point_2& p) const { return c.has_on_bounded_side(p); } + Boolean + operator()(const Circle_2& c, const Segment_2& s) const + { + if ((c.center() - s.source()).squared_length() > c.squared_radius()) + return false; + + return (c.center() - s.target()).squared_length() <= c.squared_radius(); + } + Boolean operator()( const Triangle_2& t, const Point_2& p) const { return t.has_on_bounded_side(p); } @@ -3578,6 +3588,42 @@ namespace CommonKernelFunctors { operator()( const Sphere_3& s, const Point_3& p) const { return s.has_on_bounded_side(p); } + Boolean + operator()(const Sphere_3& s, const Iso_cuboid_3& c) const + { + typedef typename K::FT FT; + FT d = FT(0); + FT distance = FT(0); + + const Point_3& center = s.center(); + + // x + d = (std::max)(square(center.x() - c.xmin()), square(center.x() - c.xmax())); + + if (certainly(d > s.squared_radius())) + return false; + + distance = d; + + // y + d = (std::max)(square(center.y() - c.ymin()), square(center.y() - c.ymax())); + + if (certainly(d > s.squared_radius())) + return false; + + distance += d; + + // z + d = (std::max)(square(center.z() - c.zmin()), square(center.z() - c.zmax())); + + if (certainly(d > s.squared_radius())) + return false; + + distance += d; + + return (distance <= s.squared_radius()); + } + Boolean operator()( const Tetrahedron_3& t, const Point_3& p) const { return t.rep().has_on_bounded_side(p); } diff --git a/Kernel_23/include/CGAL/Sphere_3.h b/Kernel_23/include/CGAL/Sphere_3.h index ae9d655a944..c4631972673 100644 --- a/Kernel_23/include/CGAL/Sphere_3.h +++ b/Kernel_23/include/CGAL/Sphere_3.h @@ -155,85 +155,7 @@ public: typename R::Boolean has_on_bounded_side(const Iso_cuboid_3& c) const { - return has_on_bounded_side( - (c.min)().x(), (c.min)().y(), (c.min)().z(), - (c.max)().x(), (c.max)().y(), (c.max)().z()); - } - - template - typename R::Boolean has_on_bounded_side(const BFT bxmin, const BFT bymin, const BFT bzmin, - const BFT bxmax, const BFT bymax, const BFT bzmax) const - { - typedef typename R::FT SFT; - typedef typename Coercion_traits::Type FT; - typedef typename R::Point_3 Point; - - typename Coercion_traits::Cast to_FT; - - FT d = FT(0); - FT distance = FT(0); - FT sr = squared_radius(); - - const Point& c = center(); - - if (compare(c.x(), bxmin) == SMALLER) - { - d = to_FT(bxmax) - to_FT(c.x()); - d = square(d); - if (certainly(d > squared_radius())) - return false; - - distance = d; - } - else if (compare(c.x(), bxmax) == LARGER) - { - d = to_FT(c.x()) - to_FT(bxmin); - d = square(d); - if (certainly(d > squared_radius())) - return false; - - distance = d; - } - - if (compare(c.y(), bymin) == SMALLER) - { - d = to_FT(bymax) - to_FT(c.y()); - d = square(d); - if (certainly(d > squared_radius())) - return false; - - distance += d; - } - else if (compare(c.y(), bymax) == LARGER) - { - d = to_FT(c.y()) - to_FT(bymin); - d = square(d); - if (certainly(d > squared_radius())) - return false; - - distance += d; - } - - if (compare(c.z(), bzmin) == SMALLER) - { - d = to_FT(bzmax) - to_FT(c.z()); - d = square(d); - if (certainly(d > squared_radius())) - return false; - - distance += d; - } - else if (compare(c.z(), bzmax) == LARGER) - { - d = to_FT(c.z()) - to_FT(bzmin); - d = square(d); - if (certainly(d > squared_radius())) - return false; - - distance += d; - } - - return (distance <= sr); + return R().has_on_bounded_side_3_object()(*this, c); } typename R::Boolean diff --git a/Kernel_23/test/Kernel_23/include/CGAL/_test_cls_sphere_3.h b/Kernel_23/test/Kernel_23/include/CGAL/_test_cls_sphere_3.h index 92560f71294..87a868305d5 100644 --- a/Kernel_23/test/Kernel_23/include/CGAL/_test_cls_sphere_3.h +++ b/Kernel_23/test/Kernel_23/include/CGAL/_test_cls_sphere_3.h @@ -127,7 +127,16 @@ _test_cls_sphere_3(const R& ) assert( c8.bounded_side( p3 - vy6 ) == CGAL::ON_BOUNDARY ); assert( cc.has_on_boundary( p3 + vy6) ); assert( cc.has_on_boundary( p3 - vx6) ); - assert( c1.has_on_bounded_side(CGAL::Iso_cuboid_3(CGAL::ORIGIN, p0)) ); + assert(!c1.has_on_bounded_side(CGAL::Iso_cuboid_3(CGAL::ORIGIN, p0)) ); + assert( CGAL::Sphere_3(CGAL::Point_3(0, 0, 0), 0).has_on_bounded_side(CGAL::Iso_cuboid_3(CGAL::ORIGIN, CGAL::ORIGIN)) ); + assert( CGAL::Sphere_3(CGAL::Point_3(1, 0, 0), 1).has_on_bounded_side(CGAL::Iso_cuboid_3(CGAL::ORIGIN, CGAL::ORIGIN)) ); + assert(!CGAL::Sphere_3(CGAL::Point_3(2, 0, 0), 1).has_on_bounded_side(CGAL::Iso_cuboid_3(CGAL::ORIGIN, CGAL::ORIGIN)) ); + assert(!CGAL::Sphere_3(CGAL::Point_3(2, 0, 0), 4).has_on_bounded_side(CGAL::Iso_cuboid_3(CGAL::Point_3(-1, 0, 0), CGAL::Point_3(2, 0, 0))) ); + assert(!CGAL::Sphere_3(CGAL::Point_3(2, 0, 0), 4).has_on_bounded_side(CGAL::Iso_cuboid_3(CGAL::Point_3(0, 0, 0), CGAL::Point_3(FT(4.1), 0, 0))) ); + assert( CGAL::Sphere_3(CGAL::Point_3(2, 0, 0), 4).has_on_bounded_side(CGAL::Iso_cuboid_3(CGAL::Point_3(0, 0, 0), CGAL::Point_3(4, 0, 0))) ); + assert( CGAL::Sphere_3(CGAL::Point_3(2, 0, 0), 4).has_on_bounded_side(CGAL::Iso_cuboid_3(CGAL::Point_3(1, 1, 1), CGAL::Point_3(3, -1, -1))) ); + assert(!CGAL::Sphere_3(CGAL::Point_3(0, 0, 0), 4).has_on_bounded_side(CGAL::Iso_cuboid_3(CGAL::Point_3(-2, -2, -2), CGAL::Point_3(2, 2, 2))) ); + assert( CGAL::Sphere_3(CGAL::Point_3(0, 0, 0), 4).has_on_bounded_side(CGAL::Iso_cuboid_3(CGAL::Point_3(-1, -1, -1), CGAL::Point_3(1, 1, 1))) ); std::cout << '.';