From ad1fbbd2428691842d4305eb7842c01ccefce9ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 20 May 2019 10:06:14 +0200 Subject: [PATCH] Fix Circle_2 -- Bbox_2/Iso_rectangle_2 intersection Bbox_2 is inherently inexact as it is double-based. Thus, Bbox_2 should use its conversion to Iso_rectangle_2 (a kernel type) and not the other way around, otherwise we are doing FT --> double --> FT and losing precision. --- .../CGAL/Intersections_2/Bbox_2_Circle_2.h | 33 ++++- .../Circle_2_Iso_rectangle_2.h | 82 +++++++++++- .../internal/Bbox_2_Circle_2_do_intersect.h | 126 ------------------ 3 files changed, 104 insertions(+), 137 deletions(-) delete mode 100644 Intersections_2/include/CGAL/Intersections_2/internal/Bbox_2_Circle_2_do_intersect.h diff --git a/Intersections_2/include/CGAL/Intersections_2/Bbox_2_Circle_2.h b/Intersections_2/include/CGAL/Intersections_2/Bbox_2_Circle_2.h index aaa9f323f1c..88f342201ac 100644 --- a/Intersections_2/include/CGAL/Intersections_2/Bbox_2_Circle_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/Bbox_2_Circle_2.h @@ -26,21 +26,46 @@ #include #include -#include +#include namespace CGAL { +namespace Intersections { +namespace internal { + +template +bool do_intersect(const CGAL::Bbox_2& bbox, + const typename K::Circle_2& circle, + const K&) +{ + return do_intersect_circle_iso_rectangle_2(circle, bbox, K()); +} + + +template +bool do_intersect(const typename K::Circle_2& circle, + const CGAL::Bbox_2& bbox, + const K&) +{ + return do_intersect_circle_iso_rectangle_2(circle, bbox, K()); +} + +} // namespace internal +} // namespace Intersections template bool do_intersect(const CGAL::Bbox_2& a, - const Circle_2& b) { + const Circle_2& b) +{ return K().do_intersect_2_object()(a, b); } template bool do_intersect(const Circle_2& a, - const CGAL::Bbox_2& b) { + const CGAL::Bbox_2& b) +{ return K().do_intersect_2_object()(a, b); } -} +} // namespace CGAL + #endif // CGAL_INTERSECTIONS_2_BBOX_2_CIRCLE_2_H diff --git a/Intersections_2/include/CGAL/Intersections_2/Circle_2_Iso_rectangle_2.h b/Intersections_2/include/CGAL/Intersections_2/Circle_2_Iso_rectangle_2.h index a932a1c8a0d..94193a52746 100644 --- a/Intersections_2/include/CGAL/Intersections_2/Circle_2_Iso_rectangle_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/Circle_2_Iso_rectangle_2.h @@ -23,30 +23,98 @@ #ifndef CGAL_INTERSECTIONS_2_ISO_RECTANGLE_2_CIRCLE_2_H #define CGAL_INTERSECTIONS_2_ISO_RECTANGLE_2_CIRCLE_2_H -#include #include - -#include +#include +#include namespace CGAL { namespace Intersections { namespace internal { +// Circle_2 is not a disk, thus if the box is contained within the circle, there is no intersection. template -bool do_intersect(const typename K::Iso_rectangle_2& bbox, +bool do_intersect_circle_iso_rectangle_2(const typename K::Circle_2& circle, + const typename K::Iso_rectangle_2& rec, + const K&) +{ + typedef typename K::FT FT; + typedef typename K::Point_2 Point; + + Point center = circle.center(); + + // Check that the minimum distance to the box is smaller than the radius, otherwise there is + // no intersection. + FT distance = FT(0); + if(center.x() < rec.xmin()) + { + FT d = rec.xmin() - center.x(); + distance += d * d; + } + else if(center.x() > rec.xmax()) + { + FT d = center.x() - rec.xmax(); + distance += d * d; + } + + if(center.y() < rec.ymin()) + { + FT d = rec.ymin() - center.y(); + distance += d * d; + } + else if(center.y() > rec.ymax()) + { + FT d = center.y() - rec.ymax(); + distance += d * d; + } + + // Note that with the way the distance above is computed, the distance is '0' if the box strictly + // contains the circle. But since we use '>', we don't exit + if(distance > circle.squared_radius()) + return false; + + // Check that the maximum distance between the center of the circle and the box is not (strictly) + // smaller than the radius of the center, otherwise the box is entirely contained. + distance = FT(0); + if(center.x() <= (rec.xmin() + rec.xmax()) / FT(2)) + { + FT d = rec.xmax() - center.x(); + distance += d * d; + } + else + { + FT d = center.x() - rec.xmin(); + distance += d * d; + } + + if(center.y() < (rec.ymin() + rec.ymax()) / FT(2)) + { + FT d = rec.ymax() - center.y(); + distance += d * d; + } + else + { + FT d = center.y() - rec.ymin(); + distance += d * d; + } + + return (distance >= circle.squared_radius()); +} + +template +bool do_intersect(const typename K::Iso_rectangle_2& rec, const typename K::Circle_2& circle, const K&) { - return do_intersect_circle_box_2(circle, bbox, K()); + return do_intersect_circle_iso_rectangle_2(circle, rec, K()); } template bool do_intersect(const typename K::Circle_2& circle, - const typename K::Iso_rectangle_2& bbox, + const typename K::Iso_rectangle_2& rec, const K&) { - return do_intersect_circle_box_2(circle, bbox, K()); + return do_intersect_circle_iso_rectangle_2(circle, rec, K()); } } // namespace internal diff --git a/Intersections_2/include/CGAL/Intersections_2/internal/Bbox_2_Circle_2_do_intersect.h b/Intersections_2/include/CGAL/Intersections_2/internal/Bbox_2_Circle_2_do_intersect.h deleted file mode 100644 index 30dc13b4580..00000000000 --- a/Intersections_2/include/CGAL/Intersections_2/internal/Bbox_2_Circle_2_do_intersect.h +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) 2018 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) : Andreas Fabri - - -#ifndef CGAL_INTERNAL_INTERSECTIONS_2_BBOX_2_CIRCLE_2_DO_INTERSECT_H -#define CGAL_INTERNAL_INTERSECTIONS_2_BBOX_2_CIRCLE_2_DO_INTERSECT_H - -#include -#include - -#include - - -namespace CGAL { -namespace Intersections { -namespace internal { - -// Circle_2 is not a disk, thus if the box is contained within the circle, there is no intersection. -template -bool do_intersect_circle_box_2(const typename K::Circle_2& circle, - const Box2& bbox, - const K&) -{ - typedef typename K::FT FT; - typedef typename K::Point_2 Point; - - Point center = circle.center(); - - // Check that the minimum distance to the box is smaller than the radius, otherwise there is - // no intersection. - FT distance = FT(0); - if(center.x() < FT(bbox.xmin())) - { - FT d = FT(bbox.xmin()) - center.x(); - distance += d * d; - } - else if(center.x() > FT(bbox.xmax())) - { - FT d = center.x() - FT(bbox.xmax()); - distance += d * d; - } - - if(center.y() < FT(bbox.ymin())) - { - FT d = FT(bbox.ymin()) - center.y(); - distance += d * d; - } - else if(center.y() > FT(bbox.ymax())) - { - FT d = center.y() - FT(bbox.ymax()); - distance += d * d; - } - - // Note that with the way the distance above is computed, the distance is '0' if the box strictly - // contains the circle. But since we use '>', we don't exit - if(distance > circle.squared_radius()) - return false; - - // Check that the maximum distance between the center of the circle and the box is not (strictly) - // smaller than the radius of the center, otherwise the box is entirely contained. - distance = FT(0); - if(center.x() <= FT(bbox.xmin() + bbox.xmax()) / FT(2)) - { - FT d = FT(bbox.xmax()) - center.x(); - distance += d * d; - } - else - { - FT d = center.x() - FT(bbox.xmin()); - distance += d * d; - } - - if(center.y() < FT(bbox.ymin() + bbox.ymax()) / FT(2)) - { - FT d = FT(bbox.ymax()) - center.y(); - distance += d * d; - } - else - { - FT d = center.y() - FT(bbox.ymin()); - distance += d * d; - } - - return (distance >= circle.squared_radius()); -} - -template -bool do_intersect(const CGAL::Bbox_2& bbox, - const typename K::Circle_2& circle, - const K&) -{ - return do_intersect_circle_box_2(circle, bbox, K()); -} - - -template -bool do_intersect(const typename K::Circle_2& circle, - const CGAL::Bbox_2& bbox, - const K&) -{ - return do_intersect_circle_box_2(circle, bbox, K()); -} - -} // namespace internal -} // namespace Intersections -} // namespace CGAL - -#endif // CGAL_INTERNAL_INTERSECTIONS_2_BBOX_2_CIRCLE_2_DO_INTERSECT_H