From 7381e39e1fd28274239a5f67cc058622025f734d Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 29 Jan 2024 21:55:39 +0200 Subject: [PATCH] Cleaned up; eliminated local kernels --- Envelope_3/include/CGAL/Env_plane_traits_3.h | 488 ++++--- Envelope_3/include/CGAL/Env_sphere_traits_3.h | 499 ++++--- .../include/CGAL/Env_surface_data_traits_3.h | 86 +- .../include/CGAL/Env_triangle_traits_3.h | 1225 +++++++---------- 4 files changed, 1100 insertions(+), 1198 deletions(-) diff --git a/Envelope_3/include/CGAL/Env_plane_traits_3.h b/Envelope_3/include/CGAL/Env_plane_traits_3.h index 85fbbf161be3..839f6e9553bd 100644 --- a/Envelope_3/include/CGAL/Env_plane_traits_3.h +++ b/Envelope_3/include/CGAL/Env_plane_traits_3.h @@ -7,7 +7,8 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Baruch Zukerman +// Author(s) : Baruch Zukerman +// Efi Fogel #ifndef CGAL_ENV_PLANE_TRAITS_3_H #define CGAL_ENV_PLANE_TRAITS_3_H @@ -27,169 +28,149 @@ namespace CGAL { -template -class Env_plane_traits_3 : public Arr_linear_traits_2 -{ +template +class Env_plane_traits_3 : public Arr_linear_traits_2 { public: - typedef Kernel_ Kernel; - typedef typename Kernel::FT FT; - typedef Arr_linear_traits_2 Base; - typedef Env_plane_traits_3 Self; - - typedef typename Base::Multiplicity Multiplicity; - typedef typename Base::Point_2 Point_2; - typedef typename Base::Curve_2 Curve_2; - typedef typename Base::X_monotone_curve_2 X_monotone_curve_2; - typedef typename Kernel::Plane_3 Plane_3; - typedef typename Kernel::Vector_2 Vector_2; - typedef typename Kernel::Vector_3 Vector_3; - typedef typename Kernel::Segment_2 Segment_2; - typedef typename Kernel::Ray_2 Ray_2; - typedef typename Kernel::Line_2 Line_2; - typedef typename Kernel::Line_3 Line_3; - typedef std::pair Intersection_curve; - - typedef typename Base::Left_side_category Left_side_category; - typedef typename Base::Bottom_side_category Bottom_side_category; - typedef typename Base::Top_side_category Top_side_category; - typedef typename Base::Right_side_category Right_side_category; - - class Is_vertical_3 - { + using Kernel = Kernel_; + using FT = typename Kernel::FT; + using Base = Arr_linear_traits_2; + using Self = Env_plane_traits_3; + + using Multiplicity = typename Base::Multiplicity; + using Point_2 = typename Base::Point_2; + using Curve_2 = typename Base::Curve_2; + using X_monotone_curve_2 = typename Base::X_monotone_curve_2; + using Plane_3 = typename Kernel::Plane_3; + using Vector_2 = typename Kernel::Vector_2; + using Vector_3 = typename Kernel::Vector_3; + using Segment_2 = typename Kernel::Segment_2; + using Ray_2 = typename Kernel::Ray_2; + using Line_2 = typename Kernel::Line_2; + using Line_3 = typename Kernel::Line_3; + using Intersection_curve = std::pair; + + using Left_side_category = typename Base::Left_side_category; + using Bottom_side_category = typename Base::Bottom_side_category; + using Top_side_category = typename Base::Top_side_category; + using Right_side_category = typename Base::Right_side_category; + + //! + class Is_vertical_3 { public: - bool operator()(const Plane_3& h) const - { - return CGAL::is_zero(h.c()); - } + bool operator()(const Plane_3& h) const { return CGAL::is_zero(h.c()); } }; - Is_vertical_3 is_vertical_3_object() const - { - return Is_vertical_3(); - } + //! Obtain an Is_vertical_3 functor object. + Is_vertical_3 is_vertical_3_object() const { return Is_vertical_3(); } - class _Env_plane - { + // + class _Env_plane { protected: - Plane_3 m_plane; - Line_2 m_line; - bool m_is_all_plane; // true -> all plane, false -> halfplane - bool m_is_vert; + Plane_3 m_plane; + Line_2 m_line; + bool m_is_all_plane; // true -> all plane, false -> halfplane + bool m_is_vert; public: - _Env_plane() - {} + _Env_plane() {} - _Env_plane(const Plane_3& h) : m_plane(h), - m_is_all_plane(true) - { + _Env_plane(const Plane_3& h) : m_plane(h), m_is_all_plane(true) { Self s; m_is_vert = s.is_vertical_3_object()(h); } - _Env_plane(const Plane_3& h, const Line_2& l) : m_plane(h), - m_line(l), - m_is_all_plane(false), - m_is_vert(false) - { + _Env_plane(const Plane_3& h, const Line_2& l) : + m_plane(h), m_line(l), m_is_all_plane(false), m_is_vert(false) { CGAL_precondition_code(Self s); - CGAL_precondition(!s.is_vertical_3_object()(h)); - } - - bool is_vertical() const - { - return m_is_vert; + CGAL_precondition(! s.is_vertical_3_object()(h)); } - const Plane_3& plane() const - { - return m_plane; - } + bool is_vertical() const { return m_is_vert; } + const Plane_3& plane() const { return m_plane; } - operator Plane_3 () const - { - return (m_plane); - } + operator Plane_3() const { return m_plane; } - const Line_2& line() const - { - CGAL_assertion(!m_is_all_plane); + const Line_2& line() const { + CGAL_assertion(! m_is_all_plane); return m_line; } - bool is_all_plane() const - { - return m_is_all_plane; - } + bool is_all_plane() const { return m_is_all_plane; } }; - typedef _Env_plane Xy_monotone_surface_3; - typedef _Env_plane Surface_3; + using Xy_monotone_surface_3 = _Env_plane; + using Surface_3 = _Env_plane; - class Make_xy_monotone_3 - { + /*! Subdivide a given surface into \f$xy\f$-monotone parts. + */ + class Make_xy_monotone_3 { public: - - template - OutputIterator operator()(const Surface_3& s, - bool /* is_lower */, - OutputIterator o) const - { + template + OutputIterator operator()(const Surface_3& s, bool /* is_lower */, + OutputIterator o) const { *o++ = s; return o; } }; + //! Obtain a Make_xy_monotone_3 functor object. Make_xy_monotone_3 make_xy_monotone_3_object() const - { - return Make_xy_monotone_3(); - } + { return Make_xy_monotone_3(); } - class Compare_z_at_xy_3 - { - public: + /*! Determine the relative \f$z\f$-order of two given \f$xy\f$-monotone + * surfaces at the \f$xy\f$-coordinates of a given point or \f$x\f$-monotone + * curve. + */ + class Compare_z_at_xy_3 { + protected: + using Traits_3 = Env_plane_traits_3; + + //! The traits (in case it has state). + const Traits_3& m_traits; + /*! Constructor + * \param traits the traits + */ + Compare_z_at_xy_3(const Traits_3& traits) : m_traits(traits) {} + + friend class Env_plane_traits_3; + + public: + // Comparison_result operator()(const Point_2& p, const Xy_monotone_surface_3& h1, - const Xy_monotone_surface_3& h2) const - { + const Xy_monotone_surface_3& h2) const { const Plane_3& plane1 = h1.plane(); const Plane_3& plane2 = h2.plane(); Sign sign_of_c1c2 = CGAL::sign(plane1.c() * plane2.c()); Sign sign_of_expr = - CGAL::sign ((p.x()*plane1.a() + p.y()*plane1.b() + - plane1.d())*plane2.c() - - (p.x()*plane2.a() + p.y()*plane2.b() + - plane2.d())*plane1.c()); + CGAL::sign((p.x()*plane1.a() + p.y()*plane1.b() + + plane1.d())*plane2.c() - + (p.x()*plane2.a() + p.y()*plane2.b() + + plane2.d())*plane1.c()); int i = -1 * static_cast(sign_of_c1c2) * static_cast(sign_of_expr); return static_cast(i); } + // Comparison_result operator()(const X_monotone_curve_2& cv, const Xy_monotone_surface_3& h1, - const Xy_monotone_surface_3& h2) const - { - Kernel k; - Point_2 p; - if(cv.is_segment()) - p = k.construct_midpoint_2_object()(cv.left(), cv.right()); - else - if(cv.is_ray()) - p = k.construct_point_on_2_object()(cv.ray(), 1); - else - { - CGAL_assertion(cv.is_line()); - p = k.construct_point_on_2_object()(cv.line(), 1); - } + const Xy_monotone_surface_3& h2) const { + const Kernel& kernel = m_traits; + Point_2 p = (cv.is_segment()) ? + kernel.construct_midpoint_2_object()(cv.left(), cv.right()) : + ((cv.is_ray()) ? + kernel.construct_point_on_2_object()(cv.ray(), 1) : + kernel.construct_point_on_2_object()(cv.line(), 1)); return this->operator()(p, h1, h2); } + // Comparison_result operator()(const Xy_monotone_surface_3& h1, - const Xy_monotone_surface_3& h2) const - { + const Xy_monotone_surface_3& h2) const { CGAL_assertion(h1.is_all_plane() && h2.is_all_plane()); const Plane_3& p1 = h1.plane(); @@ -201,35 +182,63 @@ class Env_plane_traits_3 : public Arr_linear_traits_2 } }; + //! Obtain a Compare_z_at_xy_3 functor object. Compare_z_at_xy_3 compare_z_at_xy_3_object() const - { - return Compare_z_at_xy_3(); - } + { return Compare_z_at_xy_3(*this); } + + /*! Determine the relative \f$z\f$-order of the two given \f$xy\f$-monotone + * surfaces immediately above their projected intersection curve (a planar + * point \f$p\f$ is above an \f$x\f$-monotone curve \f$c\f$ if it is in the + * \f$x\f$-range of \f$c\f$, and lies to its left when the curve is traversed + * from its \f$xy\f$-lexicographically smaller endpoint to its larger + * endpoint). + */ + class Compare_z_at_xy_above_3 { + protected: + using Traits_3 = Env_plane_traits_3; + + //! The traits (in case it has state). + const Traits_3& m_traits; + + /*! Constructor + * \param traits the traits + */ + Compare_z_at_xy_above_3(const Traits_3& traits) : m_traits(traits) {} + + friend class Env_plane_traits_3; - class Compare_z_at_xy_above_3 - { public: + /*! Determine the relative \f$z\f$-order of the two given \f$xy\f$-monotone + * surfaces immediately above their projected intersection curve, which is + * also given. + * + * \param cv the intersection curve. + * \param h1 the first surface. + * \param h2 the second surface. + * \pre `h1` and `h2` are defined "above" `cv`, and their relative + * \f$z\f$-order is the same for some small enough neighborhood of points + * above `cv`. + */ Comparison_result operator()(const X_monotone_curve_2& cv, const Xy_monotone_surface_3& h1, - const Xy_monotone_surface_3& h2) const - { + const Xy_monotone_surface_3& h2) const { const Plane_3& plane1 = h1.plane(); const Plane_3& plane2 = h2.plane(); - const FT& a1 = plane1.a(), - b1 = plane1.b(), - c1 = plane1.c(); + const FT& a1 = plane1.a(); + const FT& b1 = plane1.b(); + const FT& c1 = plane1.c(); - const FT& a2 = plane2.a(), - b2 = plane2.b(), - c2 = plane2.c(); + const FT& a2 = plane2.a(); + const FT& b2 = plane2.b(); + const FT& c2 = plane2.c(); // our line is a3*x + b3*y + c3 = 0 // it is assumed that the planes intersect over this line const Line_2& line = cv.supp_line(); - const FT& a3 = line.a(), - b3 = line.b(), - c3 = line.c(); + const FT& a3 = line.a(); + const FT& b3 = line.b(); + const FT& c3 = line.c(); // if the line was parallel to the y-axis (i.e x = const), // then it was enough to compare dz/dx of both planes @@ -266,62 +275,97 @@ class Env_plane_traits_3 : public Arr_linear_traits_2 // are transformed to (v1,w1) and (v2,w2), so we need that w2 > w1 // (otherwise the result should be multiplied by -1) - Kernel k; - Point_2 p1 (k.construct_point_on_2_object()(line, 0)); - Point_2 p2 (k.construct_point_on_2_object()(line, 1)); + const Kernel& kernel = m_traits; + Point_2 p1 = kernel.construct_point_on_2_object()(line, 0); + Point_2 p2 = kernel.construct_point_on_2_object()(line, 1); - if(k.compare_xy_2_object()(p1, p2) == LARGER) - std::swap(p1, p2); + if (kernel.compare_xy_2_object()(p1, p2) == LARGER) std::swap(p1, p2); - CGAL_assertion(k.compare_xy_2_object()(p1, p2) == SMALLER); + CGAL_assertion(kernel.compare_xy_2_object()(p1, p2) == SMALLER); - const FT& x1 = p1.x(), - y1 = p1.y(), - x2 = p2.x(), - y2 = p2.y(); + const FT& x1 = p1.x(); + const FT& y1 = p1.y(); + const FT& x2 = p2.x(); + const FT& y2 = p2.y(); Sign s2 = CGAL_NTS sign(-b3*x1+a3*y1-(-b3*x2+a3*y2)); return s1 * s2; } - }; + //! Obtain a Compare_z_at_xy_above_3 functor object. Compare_z_at_xy_above_3 compare_z_at_xy_above_3_object() const - { - return Compare_z_at_xy_above_3(); - } + { return Compare_z_at_xy_above_3(*this); } + + /*! Determine the relative \f$z\f$-order of the two given \f$xy\f$-monotone + * surfaces immediately below their projected intersection curve (a planar + * point \f$p\f$ is below an \f$x\f$-monotone curve \f$c\f$ if it is in the + * \f$x\f$-range of \f$c\f$, and lies to its left when the curve is traversed + * from its \f$xy\f$-lexicographically smaller endpoint to its larger + * endpoint). + */ + class Compare_z_at_xy_below_3 { + protected: + using Traits_3 = Env_plane_traits_3; + + //! The traits (in case it has state). + const Traits_3& m_traits; + + /*! Constructor + * \param traits the traits + */ + Compare_z_at_xy_below_3(const Traits_3& traits) : m_traits(traits) {} + + friend class Env_plane_traits_3; - class Compare_z_at_xy_below_3 - { public: + /*! Determine the relative \f$z\f$-order of the two given \f$xy\f$-monotone + * surfaces immediately below their projected intersection curve, which is + * also given. + * + * \param cv the intersection curve. + * \param h1 the first surface. + * \param h2 the second surface. + * \pre `h1` and `h2` are defined "above" `cv`, and their relative + * \f$z\f$-order is the same for some small enough neighborhood of points + * below `cv`. + */ Comparison_result operator()(const X_monotone_curve_2& cv, const Xy_monotone_surface_3& h1, - const Xy_monotone_surface_3& h2) const - { - Compare_z_at_xy_above_3 cmp_above; + const Xy_monotone_surface_3& h2) const { + auto cmp_above = m_traits.compare_z_at_xy_above_3_object(); return CGAL::opposite(cmp_above(cv, h1, h2)); } - }; + //! Obtain a Compare_z_at_xy_below_3 functor object. Compare_z_at_xy_below_3 compare_z_at_xy_below_3_object() const - { - return Compare_z_at_xy_below_3(); - } + { return Compare_z_at_xy_below_3(*this); } + /*! Compute all planar \f$x\f$-monotone curves and possibly isolated planar + * points that form the projection of the boundary of the given + * \f$xy\f$-monotone surface s onto the \f$xy\f$-plane. + */ + class Construct_projected_boundary_2 { + protected: + using Traits_3 = Env_plane_traits_3; - class Construct_projected_boundary_2 - { - public: + //! The traits (in case it has state). + const Traits_3& m_traits; + + /*! Constructor + * \param traits the traits + */ + Construct_projected_boundary_2(const Traits_3& traits) : m_traits(traits) {} - template + friend class Env_plane_traits_3; + + public: + template OutputIterator operator()(const Xy_monotone_surface_3& s, - OutputIterator o) const - { - if(s.is_all_plane()) - { - if(!s.is_vertical()) - return o; + OutputIterator o) const { + if (s.is_all_plane()) { + if (! s.is_vertical()) return o; const Plane_3& h = s.plane(); Line_2 proj_line(h.a(), h.b(), h.d()); @@ -331,10 +375,10 @@ class Env_plane_traits_3 : public Arr_linear_traits_2 } // s is half-plane - Kernel k; - const Point_2& p1 = k.construct_point_on_2_object()(s.line(), 0); - const Point_2& p2 = k.construct_point_on_2_object()(s.line(), 1); - Comparison_result res = k.compare_xy_2_object()(p1, p2); + const Kernel& kernel = m_traits; + const Point_2& p1 = kernel.construct_point_on_2_object()(s.line(), 0); + const Point_2& p2 = kernel.construct_point_on_2_object()(s.line(), 1); + Comparison_result res = kernel.compare_xy_2_object()(p1, p2); Oriented_side side = (res == SMALLER) ? ON_POSITIVE_SIDE : ON_NEGATIVE_SIDE; @@ -343,118 +387,106 @@ class Env_plane_traits_3 : public Arr_linear_traits_2 } }; + // Construct_projected_boundary_2 construct_projected_boundary_2_object() const - { - return Construct_projected_boundary_2(); - } + { return Construct_projected_boundary_2(*this); } + /*! compute the projection of the intersections of the \f$xy\f$-monotone + * surfaces onto the \f$xy\f$-plane, + */ + class Construct_projected_intersections_2 { + protected: + using Traits_3 = Env_plane_traits_3; - class Construct_projected_intersections_2 - { - public: + //! The traits (in case it has state). + const Traits_3& m_traits; - template + /*! Constructor + * \param traits the traits + */ + Construct_projected_intersections_2(const Traits_3& traits) : + m_traits(traits) + {} + + friend class Env_plane_traits_3; + + public: + template OutputIterator operator()(const Xy_monotone_surface_3& s1, const Xy_monotone_surface_3& s2, - OutputIterator o) const - { - Kernel k; + OutputIterator o) const { + const Kernel& kernel = m_traits; const Plane_3& h1 = s1.plane(); const Plane_3& h2 = s2.plane(); - if(s1.is_vertical() && s2.is_vertical()) - { + if (s1.is_vertical() && s2.is_vertical()) { Line_2 l1(h1.a(), h1.b(), h1.d()); Line_2 l2(h2.a(), h2.b(), h2.d()); - auto obj = k.intersect_2_object()(l1, l2); + auto obj = kernel.intersect_2_object()(l1, l2); - if(const Point_2* p = std::get_if(&(*obj))) - *o++ = *p; + if (const auto* p = std::get_if(&(*obj))) *o++ = *p; // otherwise, the vertical planes are parallel or overlap, so we return // nothing. return o; } - if(s1.is_all_plane() && s2.is_all_plane()) - { - auto obj = k.intersect_3_object()(h1, h2); + if (s1.is_all_plane() && s2.is_all_plane()) { + auto obj = kernel.intersect_3_object()(h1, h2); CGAL_assertion(obj != std::nullopt); - if(const Line_3* l = std::get_if(&(*obj))) - *o++ = Intersection_curve(project_xy(*l, k), 1); - + if (const auto* l = std::get_if(&(*obj))) + *o++ = Intersection_curve(project_xy(*l, kernel), 1); return o; } - if(s1.is_all_plane() && !s2.is_all_plane()) - { - auto obj = plane_half_plane_proj_intersection(h1, - h2, - s2.line(), - k); - if(obj ==std::nullopt) - return o; - if(const Line_2* line = std::get_if(&(*obj))) - { + if (s1.is_all_plane() && ! s2.is_all_plane()) { + auto obj = plane_half_plane_proj_intersection(h1, h2, s2.line(), kernel); + if (obj == std::nullopt) return o; + if (const auto* line = std::get_if(&(*obj))) { *o++ = Intersection_curve(*line, 1); return o; } - if(const Ray_2* ray = std::get_if(&(*obj))) - { + if (const auto* ray = std::get_if(&(*obj))) { *o++ = Intersection_curve(*ray, 1); return o; } return o; } - if(!s2.is_all_plane() && s2.is_all_plane()) - { - auto obj = plane_half_plane_proj_intersection(h2, - h1, - s1.line(), - k); - if(obj == std::nullopt) - return o; - if(const Line_2* line = std::get_if(&(*obj))) - { + if (! s2.is_all_plane() && s2.is_all_plane()) { + auto obj = plane_half_plane_proj_intersection(h2, h1, s1.line(), kernel); + if (obj == std::nullopt) return o; + if (const auto* line = std::get_if(&(*obj))) { *o++ = Intersection_curve(*line, 1); return o; } - if(const Ray_2* ray = std::get_if(&(*obj))) - { + if (const auto* ray = std::get_if(&(*obj))) { *o++ = Intersection_curve(*ray, 1); return o; } return o; } - CGAL_assertion(!s2.is_all_plane() && !s2.is_all_plane()); - auto obj = - half_plane_half_plane_proj_intersection(h1, s1.line(), h2, s2.line(), k); + CGAL_assertion(! s2.is_all_plane() && ! s2.is_all_plane()); + auto obj = half_plane_half_plane_proj_intersection(h1, s1.line(), + h2, s2.line(), kernel); - if(obj ==std::nullopt ) - return o; + if (obj == std::nullopt) return o; - if(const Line_2* line = std::get_if(&(*obj))) - { + if (const auto* line = std::get_if(&(*obj))) { *o++ = Intersection_curve(*line, 1); return o; } - if(const Ray_2* ray = std::get_if(&(*obj))) - { + if (const auto* ray = std::get_if(&(*obj))) { *o++ = Intersection_curve(*ray, 1); return o; } - - if(const Segment_2* seg = std::get_if(&(*obj))) - { + if (const auto* seg = std::get_if(&(*obj))) { *o++ = Intersection_curve(*seg, 1); return o; } - - if(const Point_2* p = std::get_if(&(*obj))) - { + if (const auto* p = std::get_if(&(*obj))) { *o++ = *p; return o; } @@ -462,12 +494,10 @@ class Env_plane_traits_3 : public Arr_linear_traits_2 } }; + //! Obtain a Construct_projected_intersections_2 functor object. Construct_projected_intersections_2 construct_projected_intersections_2_object() const - { - return Construct_projected_intersections_2(); - } - + { return Construct_projected_intersections_2(*this); } }; } //namespace CGAL diff --git a/Envelope_3/include/CGAL/Env_sphere_traits_3.h b/Envelope_3/include/CGAL/Env_sphere_traits_3.h index 2a42d07f0a02..67959b4ebe3b 100644 --- a/Envelope_3/include/CGAL/Env_sphere_traits_3.h +++ b/Envelope_3/include/CGAL/Env_sphere_traits_3.h @@ -7,10 +7,10 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Michal Meyerovitch -// Baruch Zukerman -// Ron Wein -// Efi Fogel +// Author(s) : Michal Meyerovitch +// Baruch Zukerman +// Ron Wein +// Efi Fogel #ifndef CGAL_ENV_SPHERE_TRAITS_3_H #define CGAL_ENV_SPHERE_TRAITS_3_H @@ -32,96 +32,115 @@ namespace CGAL { template class Env_sphere_traits_3 : public ConicTraits_2 { public: - typedef ConicTraits_2 Traits_2; - typedef Env_sphere_traits_3 Self; + using Traits_2 = ConicTraits_2; - typedef typename Traits_2::Point_2 Point_2; - typedef typename Traits_2::Curve_2 Curve_2; - typedef typename Traits_2::X_monotone_curve_2 X_monotone_curve_2; - typedef typename Traits_2::Multiplicity Multiplicity; + using Point_2 = typename Traits_2::Point_2; + using Curve_2 = typename Traits_2::Curve_2; + using X_monotone_curve_2 = typename Traits_2::X_monotone_curve_2; + using Multiplicity = typename Traits_2::Multiplicity; - typedef typename Traits_2::Rat_kernel Rat_kernel; - typedef typename Traits_2::Alg_kernel Alg_kernel; - typedef typename Traits_2::Nt_traits Nt_traits; + using Rat_kernel = typename Traits_2::Rat_kernel; + using Alg_kernel = typename Traits_2::Alg_kernel; + using Nt_traits = typename Traits_2::Nt_traits; - typedef typename Rat_kernel::FT Rational; - typedef typename Rat_kernel::Point_2 Rat_point_2; - typedef typename Rat_kernel::Segment_2 Rat_segment_2; - typedef typename Rat_kernel::Line_2 Rat_line_2; - typedef typename Rat_kernel::Circle_2 Rat_circle_2; - typedef typename Rat_kernel::Point_3 Rat_point_3; + using Rational = typename Rat_kernel::FT; + using Rat_point_2 = typename Rat_kernel::Point_2; + using Rat_segment_2 = typename Rat_kernel::Segment_2; + using Rat_line_2 = typename Rat_kernel::Line_2; + using Rat_circle_2 = typename Rat_kernel::Circle_2; + using Rat_point_3 = typename Rat_kernel::Point_3; - typedef typename Alg_kernel::FT Algebraic; - typedef typename Alg_kernel::Point_2 Alg_point_2; - typedef typename Alg_kernel::Circle_2 Alg_circle_2; + using Algebraic = typename Alg_kernel::FT; + using Alg_point_2 = typename Alg_kernel::Point_2; + using Alg_circle_2 = typename Alg_kernel::Circle_2; - typedef typename Rat_kernel::Sphere_3 Surface_3; + using Surface_3 = typename Rat_kernel::Sphere_3; // here we refer to the lower part of the sphere only - typedef Surface_3 Xy_monotone_surface_3; + using Xy_monotone_surface_3 = Surface_3; protected: - typedef std::pair Intersection_curve; + using Intersection_curve = std::pair; public: + /*! Subdivide a given surface into \f$xy\f$-monotone parts. + */ class Make_xy_monotone_3 { protected: - const Self& parent; + using Traits_3 = Env_sphere_traits_3; - public: - Make_xy_monotone_3(const Self * p) : parent(*p) {} + //! The traits (in case it has state). + const Traits_3& m_traits; + + /*! Constructor + * \param traits the traits + */ + Make_xy_monotone_3(const Traits_3& traits) : m_traits(traits) {} + + friend class Env_sphere_traits_3; + public: // create xy-monotone surfaces from a general surface // return a past-the-end iterator - template - OutputIterator operator()(const Surface_3& s, - bool is_lower, - OutputIterator o) const - { + template + OutputIterator operator()(const Surface_3& s, bool is_lower, + OutputIterator o) const { // our half sphere is of same type as our full sphere since we always // need only the lower/upper part of each sphere - parent.m_is_lower = is_lower; + m_traits.m_is_lower = is_lower; *o++ = s; return o; } }; - /*! Get a Make_xy_monotone_3 functor object. */ - Make_xy_monotone_3 - make_xy_monotone_3_object() const { return Make_xy_monotone_3(this); } + /*! Obtain a Make_xy_monotone_3 functor object. */ + Make_xy_monotone_3 make_xy_monotone_3_object() const + { return Make_xy_monotone_3(*this); } + /*! Compute all planar \f$x\f$-monotone curves and possibly isolated planar + * points that form the projection of the boundary of the given + * \f$xy\f$-monotone surface s onto the \f$xy\f$-plane. + */ class Construct_projected_boundary_2 { protected: - const Self& parent; + using Traits_3 = Env_sphere_traits_3; - public: - Construct_projected_boundary_2(const Self* p) : parent(*p) {} + //! The traits (in case it has state). + const Traits_3& m_traits; + /*! Constructor + * \param traits the traits + */ + Construct_projected_boundary_2(const Traits_3& traits) : m_traits(traits) {} + + friend class Env_sphere_traits_3; + + public: // insert into the OutputIterator all the (2d) curves of the boundary of // the vertical projection of the surface on the xy-plane // the OutputIterator value type is X_monotone_curve_2 - template + template OutputIterator operator()(const Xy_monotone_surface_3& s, OutputIterator o) const { - const auto gt_2 = parent.geometry_traits_2(); + const Traits_2& gt2 = m_traits; // the projected boundary in a circle, with a projected center, // and same radius - Rat_point_2 proj_center = parent.project(s.center()); + Rat_point_2 proj_center = m_traits.project(s.center()); Rat_circle_2 circ(proj_center, s.squared_radius()); - Curve_2 curve = gt_2->construct_curve_2_object()(circ); - typedef std::variant Variant; + Curve_2 curve = gt2.construct_curve_2_object()(circ); + using Variant = std::variant; Variant objs[2]; CGAL_assertion_code(Variant* p = ) - parent.make_x_monotone_2_object()(curve, objs); + m_traits.make_x_monotone_2_object()(curve, objs); CGAL_assertion(p == objs + 2); - const X_monotone_curve_2* cv1 = std::get_if(&(objs[0])); - const X_monotone_curve_2* cv2 = std::get_if(&(objs[1])); + const auto* cv1 = std::get_if(&(objs[0])); + const auto* cv2 = std::get_if(&(objs[1])); - CGAL_assertion(cv1!=nullptr); - CGAL_assertion(cv2!=nullptr); + CGAL_assertion(cv1 != nullptr); + CGAL_assertion(cv2 != nullptr); if (cv1->is_lower()) { CGAL_assertion(cv2->is_upper()); @@ -138,39 +157,52 @@ class Env_sphere_traits_3 : public ConicTraits_2 { } }; - /*! Get a Construct_projected_boundary_2 functor object. */ + /*! Obtain a Construct_projected_boundary_2 functor object. */ Construct_projected_boundary_2 construct_projected_boundary_2_object() const - { return Construct_projected_boundary_2(this); } + { return Construct_projected_boundary_2(*this); } + /*! compute the projection of the intersections of the \f$xy\f$-monotone + * surfaces onto the \f$xy\f$-plane, + */ class Construct_projected_intersections_2 { protected: - const Self& parent; + using Traits_3 = Env_sphere_traits_3; - public: - Construct_projected_intersections_2(const Self * p) : parent(*p) {} + //! The traits (in case it has state). + const Traits_3& m_traits; + + /*! Constructor + * \param traits the traits + */ + Construct_projected_intersections_2(const Traits_3& traits) : + m_traits(traits) + {} + friend class Env_sphere_traits_3; + + public: // insert into OutputIterator all the (2d) projections on the xy plane of // the intersection objects between the 2 surfaces // the data type of OutputIterator is Object template - OutputIterator - operator()(const Xy_monotone_surface_3& s1, const Xy_monotone_surface_3& s2, - OutputIterator o) const { - const auto gt_2 = parent.geometry_traits_2(); - auto ctr_cv = gt_2->construct_curve_2_object(); - auto nt_traits = gt_2->nt_traits(); - - Rat_point_3 p1 = s1.center(); - Rat_point_3 p2 = s2.center(); - const Rational a1 = p1.x(); - const Rational b1 = p1.y(); - const Rational c1 = p1.z(); - const Rational a2 = p2.x(); - const Rational b2 = p2.y(); - const Rational c2 = p2.z(); - const Rational sqr_r1 = s1.squared_radius(); - const Rational sqr_r2 = s2.squared_radius(); + OutputIterator operator()(const Xy_monotone_surface_3& s1, + const Xy_monotone_surface_3& s2, + OutputIterator o) const { + const Traits_2& gt2 = m_traits; + auto ctr_cv = gt2.construct_curve_2_object(); + auto nt_traits = gt2.nt_traits(); + + const Rat_point_3& p1 = s1.center(); + const Rat_point_3& p2 = s2.center(); + const Rational& a1 = p1.x(); + const Rational& b1 = p1.y(); + const Rational& c1 = p1.z(); + const Rational& a2 = p2.x(); + const Rational& b2 = p2.y(); + const Rational& c2 = p2.z(); + const Rational& sqr_r1 = s1.squared_radius(); + const Rational& sqr_r2 = s2.squared_radius(); // // the spheres intersect iff d(p1, p2) <= (r1+r2) // // squaring this twice, we get the condition @@ -225,7 +257,7 @@ class Env_sphere_traits_3 : public ConicTraits_2 { Rational B = -8*b1*sqr_a_diff; Rational C = 4*sqr_a_diff*(sqr_a1+sqr_b1-sqr_r1) + m*m - 4*m*a1*a_diff; - Algebraic ys[2]; + Algebraic ys[2]; Algebraic* ys_end = nt_traits->solve_quadratic_equation(A, B, C, ys); std::ptrdiff_t n_ys = ys_end - ys; @@ -254,7 +286,7 @@ class Env_sphere_traits_3 : public ConicTraits_2 { // 2(a1-a2)x - m = 0 Curve_2 res = ctr_cv(0, 0, 0, 2*a_diff, 0, -m, COLLINEAR, end1, end2); - parent.add_curve_to_output(res, o); + m_traits.add_curve_to_output(res, o); //*o++ = Intersection_curve(res, TRANSVERSAL); } else { @@ -328,7 +360,7 @@ class Env_sphere_traits_3 : public ConicTraits_2 { // 2(a1-a2)x + 2(b1-b2)y - m = 0 Curve_2 res = ctr_cv(0,0,0, 2*a_diff, 2*b_diff, -m, COLLINEAR, end1, end2); - parent.add_curve_to_output(res, o); + m_traits.add_curve_to_output(res, o); //*o++ = Intersection_curve(res, TRANSVERSAL); } } @@ -401,14 +433,14 @@ class Env_sphere_traits_3 : public ConicTraits_2 { // if the full spheres do not intersect, the equation we get has no // real solution, so we should check it: bool ellipse_is_point = false; - if (! parent.is_valid_conic_equation(R, S, T, U, V, W, ellipse_is_point)) + if (! m_traits.is_valid_conic_equation(R, S, T, U, V, W, ellipse_is_point)) return o; // we need only a part of the ellipse (as stated in (**)) so we // construct the cutting line, which is: // equation (*) <= min(c1,c2) -- for lower envelope // equation (*) >= max(c1,c2) -- for upper envelope - Rational z_plane = (parent.m_is_lower) ? + Rational z_plane = (m_traits.m_is_lower) ? ((c1 < c2) ? c1 : c2) : ((c1 > c2) ? c1 : c2); @@ -423,7 +455,7 @@ class Env_sphere_traits_3 : public ConicTraits_2 { // for upper envelope, we should multiply the line equation by -1 int envelope_coef = 1; - if (! parent.m_is_lower) envelope_coef = -1; + if (! m_traits.m_is_lower) envelope_coef = -1; Sign sign_c_diff = CGAL_NTS sign(c_diff); Rational la = envelope_coef*2*a_diff*sign_c_diff; @@ -454,13 +486,12 @@ class Env_sphere_traits_3 : public ConicTraits_2 { // intersection - in which case lc >= 0 // or there is no intersection at all between the 2 half spheres - // in which case lc < 0 - if (CGAL_NTS compare(a_diff, zero) == EQUAL && - CGAL_NTS compare(b_diff, zero) == EQUAL) - { + if ((CGAL_NTS compare(a_diff, zero) == EQUAL) && + (CGAL_NTS compare(b_diff, zero) == EQUAL)) { Sign sign_lc = CGAL_NTS sign(lc); if (sign_lc != NEGATIVE) { Curve_2 res = ctr_cv(R, S, T, U, V, W); - parent.add_curve_to_output(res, o); + m_traits.add_curve_to_output(res, o); //*o++ = Intersection_curve(res, TRANSVERSAL); } return o; @@ -510,7 +541,7 @@ class Env_sphere_traits_3 : public ConicTraits_2 { Curve_2 inter_cv = ctr_cv(R, S, T, U, V, W); CGAL_precondition_code(x_mid_n_y_points = ) - gt_2->points_at_x(inter_cv, x_mid_point, x_mid_y_points); + gt2.points_at_x(inter_cv, x_mid_point, x_mid_y_points); CGAL_precondition(x_mid_n_y_points > 0); @@ -566,7 +597,7 @@ class Env_sphere_traits_3 : public ConicTraits_2 { Curve_2 inter_cv = ctr_cv(R, S, T, U, V, W); CGAL_precondition_code(int y_mid_n_x_points =) - gt_2->points_at_y(inter_cv, y_mid_point, y_mid_x_points); + gt2.points_at_y(inter_cv, y_mid_point, y_mid_x_points); CGAL_precondition(y_mid_n_x_points > 0); Algebraic x1 = y_mid_x_points[0].x(), x2 = y_mid_x_points[1].x(); @@ -600,7 +631,7 @@ class Env_sphere_traits_3 : public ConicTraits_2 { Alg_point_2 vtan_ps[2]; CGAL_assertion_code(std::size_t n_vtan_ps =) - gt_2->vertical_tangency_points(inter_cv, vtan_ps); + gt2.vertical_tangency_points(inter_cv, vtan_ps); CGAL_assertion(n_vtan_ps == 2); @@ -609,7 +640,7 @@ class Env_sphere_traits_3 : public ConicTraits_2 { Sign lval_sign = CGAL_NTS sign(lval); if (lval_sign == POSITIVE) { // the full ellipse is in the positive side - parent.add_curve_to_output(inter_cv, o); + m_traits.add_curve_to_output(inter_cv, o); //*o++ = Intersection_curve(inter_cv, TRANSVERSAL); return o; } @@ -630,7 +661,7 @@ class Env_sphere_traits_3 : public ConicTraits_2 { lval_sign = CGAL_NTS sign(lval); CGAL_assertion(lval_sign != ZERO); - if (lval_sign == POSITIVE) parent.add_curve_to_output(inter_cv, o); + if (lval_sign == POSITIVE) m_traits.add_curve_to_output(inter_cv, o); //*o++ = Intersection_curve(inter_cv, TRANSVERSAL); else *o++ = Point_2(source); @@ -644,14 +675,14 @@ class Env_sphere_traits_3 : public ConicTraits_2 { // If the mid-point forms a left-turn with the source and the target // points, the orientation is positive (going counterclockwise). // Otherwise, it is negative (going clockwise). - auto alg_kernel = gt_2->alg_kernel(); + auto alg_kernel = gt2.alg_kernel(); auto orient_f = alg_kernel->orientation_2_object(); Orientation orient = (orient_f(source, pmid, target) == LEFT_TURN) ? CGAL::COUNTERCLOCKWISE : CGAL::CLOCKWISE; Curve_2 res = ctr_cv(R, S, T, U, V, W, orient, source, target); CGAL_assertion(res.is_valid()); - parent.add_curve_to_output(res, o); + m_traits.add_curve_to_output(res, o); //*o++ = Intersection_curve(res, TRANSVERSAL); } @@ -659,18 +690,30 @@ class Env_sphere_traits_3 : public ConicTraits_2 { } }; - /*! Get a Construct_projected_intersections_2 functor object. */ + /*! Obtain a Construct_projected_intersections_2 functor object. */ Construct_projected_intersections_2 construct_projected_intersections_2_object() const - { return Construct_projected_intersections_2(this); } + { return Construct_projected_intersections_2(*this); } + /*! Determine the relative \f$z\f$-order of two given \f$xy\f$-monotone + * surfaces at the \f$xy\f$-coordinates of a given point or \f$x\f$-monotone + * curve. + */ class Compare_z_at_xy_3 { protected: - const Self& parent; + using Traits_3 = Env_sphere_traits_3; - public: - Compare_z_at_xy_3(const Self* p) : parent(*p) {} + //! The traits (in case it has state). + const Traits_3& m_traits; + + /*! Constructor + * \param traits the traits + */ + Compare_z_at_xy_3(const Traits_3& traits) : m_traits(traits) {} + + friend class Env_sphere_traits_3; + public: // check which of the surfaces is closer to the envelope at the xy // coordinates of point (i.e. lower if computing the lower envelope, or // upper if computing the upper envelope) @@ -697,9 +740,8 @@ class Env_sphere_traits_3 : public ConicTraits_2 { const Xy_monotone_surface_3& s1, const Xy_monotone_surface_3& s2) const { // we compute a middle point on cv and use the previous function - Point_2 mid = parent.construct_middle_point(cv); - Comparison_result res = parent.compare_z_at_xy_3_object()(mid, s1, s2); - return res; + Point_2 mid = m_traits.construct_middle_point(cv); + return m_traits.compare_z_at_xy_3_object()(mid, s1, s2); } protected: @@ -710,12 +752,12 @@ class Env_sphere_traits_3 : public ConicTraits_2 { const Xy_monotone_surface_3& s1, const Xy_monotone_surface_3& s2) const { // find the z coordinates of surface 1 over p - Algebraic z1 = parent.compute_envelope_z_in_point(p, s1); + Algebraic z1 = m_traits.compute_envelope_z_in_point(p, s1); // find the z coordinates of surface 2 over p - Algebraic z2 = parent.compute_envelope_z_in_point(p, s2); + Algebraic z2 = m_traits.compute_envelope_z_in_point(p, s2); Sign res = CGAL_NTS sign(z1 - z2); - if (parent.m_is_lower) return res; + if (m_traits.m_is_lower) return res; else return -res; } @@ -735,19 +777,19 @@ class Env_sphere_traits_3 : public ConicTraits_2 { Comparison_result compare_in_point_second_method(const Point_2& p, const Xy_monotone_surface_3& s1, - const Xy_monotone_surface_3& s2) const - { - Rat_point_3 p1 = s1.center(); - Rat_point_3 p2 = s2.center(); - const Rational a1 = p1.x(); - const Rational b1 = p1.y(); - const Rational c1 = p1.z(); - const Rational a2 = p2.x(); - const Rational b2 = p2.y(); - const Rational c2 = p2.z(); - const Rational sqr_r1 = s1.squared_radius(); - const Rational sqr_r2 = s2.squared_radius(); - const Algebraic x1 = p.x(), y1 = p.y(); + const Xy_monotone_surface_3& s2) const { + const Rat_point_3& p1 = s1.center(); + const Rat_point_3& p2 = s2.center(); + const Rational& a1 = p1.x(); + const Rational& b1 = p1.y(); + const Rational& c1 = p1.z(); + const Rational& a2 = p2.x(); + const Rational& b2 = p2.y(); + const Rational& c2 = p2.z(); + const Rational& sqr_r1 = s1.squared_radius(); + const Rational& sqr_r2 = s2.squared_radius(); + const Algebraic& x1 = p.x(); + const Algebraic& y1 = p.y(); Rational c_diff = c1 - c2; Algebraic x_diff1 = x1 - a1, y_diff1 = y1 - b1; @@ -773,17 +815,32 @@ class Env_sphere_traits_3 : public ConicTraits_2 { } }; - /*! Get a Compare_z_at_xy_3 functor object. */ + /*! Obtain a Compare_z_at_xy_3 functor object. */ Compare_z_at_xy_3 - compare_z_at_xy_3_object() const { return Compare_z_at_xy_3(this); } - + compare_z_at_xy_3_object() const { return Compare_z_at_xy_3(*this); } + + /*! Determine the relative \f$z\f$-order of the two given \f$xy\f$-monotone + * surfaces immediately above their projected intersection curve (a planar + * point \f$p\f$ is above an \f$x\f$-monotone curve \f$c\f$ if it is in the + * \f$x\f$-range of \f$c\f$, and lies to its left when the curve is traversed + * from its \f$xy\f$-lexicographically smaller endpoint to its larger + * endpoint). + */ class Compare_z_at_xy_above_3 { protected: - const Self& parent; + using Traits_3 = Env_sphere_traits_3; - public: - Compare_z_at_xy_above_3(const Self* p) : parent(*p) {} + //! The traits (in case it has state). + const Traits_3& m_traits; + + /*! Constructor + * \param traits the traits + */ + Compare_z_at_xy_above_3(const Traits_3& traits) : m_traits(traits) {} + + friend class Env_sphere_traits_3; + public: // check which of the surfaces is closer to the envelope on the points above // the curve cv (i.e. lower if computing the lower envelope, or upper if // computing the upper envelope) @@ -795,35 +852,46 @@ class Env_sphere_traits_3 : public ConicTraits_2 { operator()(const X_monotone_curve_2& cv, const Xy_monotone_surface_3& s1, const Xy_monotone_surface_3& s2) const - { return parent.compare_on_side(cv, s1, s2, false); } + { return m_traits.compare_on_side(cv, s1, s2, false); } }; - /*! Get a Compare_z_at_xy_above_3 functor object. */ + /*! Obtain a Compare_z_at_xy_above_3 functor object. */ Compare_z_at_xy_above_3 compare_z_at_xy_above_3_object() const - { return Compare_z_at_xy_above_3(this); } - + { return Compare_z_at_xy_above_3(*this); } + + /*! Determine the relative \f$z\f$-order of the two given \f$xy\f$-monotone + * surfaces immediately below their projected intersection curve (a planar + * point \f$p\f$ is below an \f$x\f$-monotone curve \f$c\f$ if it is in the + * \f$x\f$-range of \f$c\f$, and lies to its left when the curve is traversed + * from its \f$xy\f$-lexicographically smaller endpoint to its larger + * endpoint). + */ class Compare_z_at_xy_below_3 { protected: - const Self& parent; + using Traits_3 = Env_sphere_traits_3; - public: - Compare_z_at_xy_below_3(const Self* p) : parent(*p) {} + //! The traits (in case it has state). + const Traits_3& m_traits; - Comparison_result - operator()(const X_monotone_curve_2& cv, - const Xy_monotone_surface_3& s1, - const Xy_monotone_surface_3& s2) const - { - Comparison_result res = parent.compare_on_side(cv, s1, s2, true); - return res; - } + /*! Constructor + * \param traits the traits + */ + Compare_z_at_xy_below_3(const Traits_3& traits) : m_traits(traits) {} + + friend class Env_sphere_traits_3; + + public: + Comparison_result operator()(const X_monotone_curve_2& cv, + const Xy_monotone_surface_3& s1, + const Xy_monotone_surface_3& s2) const + { return m_traits.compare_on_side(cv, s1, s2, true); } }; - /*! Get a Compare_z_at_xy_below_3 functor object. */ + /*! Obtain a Compare_z_at_xy_below_3 functor object. */ Compare_z_at_xy_below_3 compare_z_at_xy_below_3_object() const - { return Compare_z_at_xy_below_3(this); } + { return Compare_z_at_xy_below_3(*this); } /***************************************************************************/ @@ -832,31 +900,39 @@ class Env_sphere_traits_3 : public ConicTraits_2 { // checks if point is in the xy-range of surf class Is_defined_over { protected: - const Self& parent; + using Traits_3 = Env_sphere_traits_3; - public: - Is_defined_over(const Self* p) : parent(*p) {} + //! The traits (in case it has state). + const Traits_3& m_traits; + + /*! Constructor + * \param traits the traits + */ + Is_defined_over(const Traits_3& traits) : m_traits(traits) {} + friend class Env_sphere_traits_3; + + public: // checks if point is in the xy-range of surf bool operator()(const Point_2& p, const Xy_monotone_surface_3& s) const { // project the surface on the plane - Rat_point_2 proj_center = parent.project(s.center()); + Rat_point_2 proj_center = m_traits.project(s.center()); Rat_circle_2 boundary(proj_center, s.squared_radius()); - const auto gt_2 = parent.geometry_traits_2(); - auto nt_traits = gt_2->nt_traits(); + const Traits_2& gt2 = m_traits; + auto nt_traits = gt2.nt_traits(); Alg_point_2 aproj_center(proj_center.x(), proj_center.y()); Alg_circle_2 aboundary(aproj_center, nt_traits->convert(s.squared_radius())); // check if the projected point is inside the projected boundary - auto alg_kernel = gt_2->alg_kernel(); + auto alg_kernel = gt2.alg_kernel(); return (! alg_kernel->has_on_unbounded_side_2_object()(aboundary, p)); } }; - /*! Get a Is_defined_over functor object. */ + /*! Obtain a Is_defined_over functor object. */ Is_defined_over is_defined_over_object() const - { return Is_defined_over(this); } + { return Is_defined_over(*this); } /***************************************************************************/ @@ -867,8 +943,7 @@ class Env_sphere_traits_3 : public ConicTraits_2 { Comparison_result compare_on_side(const X_monotone_curve_2& cv, const Xy_monotone_surface_3& s1, const Xy_monotone_surface_3& s2, - bool compare_on_right) const - { + bool compare_on_right) const { // cv(x,y) : r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 // let p be the leftmost endpoint of cv, p=(x0, y0) // the tangence of cv at p is a line. on the infinitesimal region @@ -881,7 +956,8 @@ class Env_sphere_traits_3 : public ConicTraits_2 { // since we assume that such point represents better what is going // on all internal curve points Point_2 cv_point = construct_middle_point(cv); - Algebraic x0 = cv_point.x(), y0 = cv_point.y(); + const Algebraic& x0 = cv_point.x(); + const Algebraic& y0 = cv_point.y(); // d(cv)/dx : 2r*x + 2s*y*dy/dx + t*y + t*x*dy/dx +u + v*dy/dx = 0 // in point p=(x0,y0) we get @@ -895,8 +971,12 @@ class Env_sphere_traits_3 : public ConicTraits_2 { // n != 0: y - y0 = y'(x-x0) ==> -y'x + y + (y'x0 - y0) = 0 // and in general we have: // -m*x + n*y + (m*x0 -n*y0) = 0 (with integer coordinates) - const Rational r = cv.r(), s = cv.s(), t = cv.t(), - u = cv.u(), v = cv.v(), w = cv.w(); + const Rational& r = cv.r(); + const Rational& s = cv.s(); + const Rational& t = cv.t(); + const Rational& u = cv.u(); + const Rational& v = cv.v(); + const Rational& w = cv.w(); Algebraic m = -1 * (2*r*x0 + t*y0 + u); Algebraic n = 2*s*y0 + t*x0 + v; // line coefficients: A3, B3, C3 @@ -931,14 +1011,14 @@ class Env_sphere_traits_3 : public ConicTraits_2 { // Di = -(x0-ai)x0 - (y0-bi)y0 - (z0-ci)z0 // // and we solve the problem as for triangles - Rat_point_3 p1 = s1.center(); - Rat_point_3 p2 = s2.center(); - const Rational a1 = p1.x(); - const Rational b1 = p1.y(); - const Rational c1 = p1.z(); - const Rational a2 = p2.x(); - const Rational b2 = p2.y(); - const Rational c2 = p2.z(); + const Rat_point_3& p1 = s1.center(); + const Rat_point_3& p2 = s2.center(); + const Rational& a1 = p1.x(); + const Rational& b1 = p1.y(); + const Rational& c1 = p1.z(); + const Rational& a2 = p2.x(); + const Rational& b2 = p2.y(); + const Rational& c2 = p2.z(); Algebraic A1 = x0 - a1, B1 = y0 - b1, C1 = z0 - c1; Algebraic A2 = x0 - a2, B2 = y0 - b2, C2 = z0 - c2; if (C1 != 0 && C2 != 0) { @@ -971,6 +1051,7 @@ class Env_sphere_traits_3 : public ConicTraits_2 { return EQUAL; } + // Rat_point_2 project(const Rat_point_3& p) const { return Rat_point_2(p.x(), p.y()); } @@ -979,15 +1060,15 @@ class Env_sphere_traits_3 : public ConicTraits_2 { // precondition: s is defined at p Algebraic compute_envelope_z_in_point(const Point_2& p, const Xy_monotone_surface_3& s) const { - Algebraic res; - // the point coordinates const Algebraic x1 = p.x(), y1 = p.y(); // the surface equations - Rat_point_3 center = s.center(); - const Rational a = center.x(), b = center.y(), c = center.z(); - const Rational sqr_r = s.squared_radius(); + const Rat_point_3& center = s.center(); + const Rational& a = center.x(); + const Rational& b = center.y(); + const Rational& c = center.z(); + const Rational& sqr_r = s.squared_radius(); // we substitute x1 and y1 in the equation of s // (x-a)^2 + (y-b)^2 + (z-c)^2 = r^2 @@ -999,11 +1080,12 @@ class Env_sphere_traits_3 : public ConicTraits_2 { Algebraic B = -2*c; Algebraic C = x_diff*x_diff + y_diff*y_diff + c*c - sqr_r; - Algebraic zs[2]; + Algebraic zs[2]; Algebraic* zs_end; std::ptrdiff_t n_zs; - auto nt_traits = m_geometry_traits_2->nt_traits(); + const Traits_2& gt2 = *this; + auto nt_traits = gt2.nt_traits(); zs_end = nt_traits->solve_quadratic_equation(A, B, C, zs); n_zs = zs_end - zs; @@ -1013,6 +1095,7 @@ class Env_sphere_traits_3 : public ConicTraits_2 { if (n_zs == 1) return zs[0]; CGAL_assertion(n_zs == 2); + Algebraic res; Comparison_result comp = CGAL_NTS compare(zs[0], zs[1]); if (m_is_lower) res = ((comp == SMALLER) ? zs[0] : zs[1]); else res = ((comp == LARGER) ? zs[0] : zs[1]); @@ -1021,8 +1104,10 @@ class Env_sphere_traits_3 : public ConicTraits_2 { // construct the point in the middle of cv Point_2 construct_middle_point(const X_monotone_curve_2& cv) const { + const Traits_2& gt2 = *this; + // get the x-value of the middle point - auto alg_kernel = m_geometry_traits_2->alg_kernel(); + auto alg_kernel = gt2.alg_kernel(); Alg_point_2 mid_x = alg_kernel->construct_midpoint_2_object()(cv.source(), cv.target()); @@ -1030,13 +1115,14 @@ class Env_sphere_traits_3 : public ConicTraits_2 { // maybe we want it there? // if (cv.is_segment()) return mid_x; if (cv.is_vertical()) return Point_2(mid_x); - return Point_2(m_geometry_traits_2->point_at_x(cv, mid_x)); + return Point_2(gt2.point_at_x(cv, mid_x)); } // for the test Point_2 construct_middle_point(const Point_2& p1, const Point_2& p2) const { - auto alg_kernel = m_geometry_traits_2->alg_kernel(); + const Traits_2& gt2 = *this; + auto alg_kernel = gt2.alg_kernel(); return Point_2(alg_kernel->construct_midpoint_2_object()(p1, p2)); } @@ -1044,7 +1130,7 @@ class Env_sphere_traits_3 : public ConicTraits_2 { // r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0 // has real solutions // is_point is set to true if the equation represents just one point - template + template bool is_valid_conic_equation(const NT& r, const NT& s, const NT& t, const NT& u, const NT& v, const NT& w, bool& is_point) const { @@ -1103,30 +1189,31 @@ class Env_sphere_traits_3 : public ConicTraits_2 { // for the test: Point_2 vertical_ray_shoot_2(const Point_2& pt, const X_monotone_curve_2& cv) - const - { + const { + const Traits_2& gt2 = *this; if (cv.is_vertical()) { - auto alg_kernel = m_geometry_traits_2->alg_kernel(); - if (! alg_kernel->less_y_2_object()(cv.left(), pt)) - return cv.left(); - else { - CGAL_assertion(alg_kernel->less_y_2_object()(cv.right(), pt)); - return cv.right(); - } + auto alg_kernel = gt2.alg_kernel(); + if (! alg_kernel->less_y_2_object()(cv.left(), pt)) return cv.left(); + + CGAL_assertion(alg_kernel->less_y_2_object()(cv.right(), pt)); + return cv.right(); } - else return m_geometry_traits_2->point_at_x(cv, pt); + + return gt2.point_at_x(cv, pt); } + // template OutputIterator add_curve_to_output(const Curve_2& c, OutputIterator oi) const { std::variant objs[2]; - std::variant* p_obj = this->make_x_monotone_2_object()(c, objs); - for(std::variant* o = objs; o != p_obj; ++o) { - if(const X_monotone_curve_2* cv = std::get_if(o)) + std::variant* p_obj = + this->make_x_monotone_2_object()(c, objs); + for (std::variant* o = objs; o != p_obj; ++o) { + if (const auto* cv = std::get_if(o)) *oi++ = Intersection_curve(*cv, 1); else { - const Point_2* pt = std::get_if(o); + const auto* pt = std::get_if(o); CGAL_assertion(pt!=nullptr); *oi++ = *pt; } @@ -1134,55 +1221,39 @@ class Env_sphere_traits_3 : public ConicTraits_2 { return oi; } - typedef std::shared_ptr Shared_geometry_traits_2; - /*! Default constructor. */ - Env_sphere_traits_3() : - m_is_lower(true), - m_geometry_traits_2(new Traits_2) - {} - - /*! Constructor from a conic 2D geometry traits. */ - Env_sphere_traits_3(Shared_geometry_traits_2 geometry_traits_2) : - m_is_lower(true), - m_geometry_traits_2(geometry_traits_2) - {} - - /*! Obtain the undelying conic 2D geometry traits. - */ - const Shared_geometry_traits_2 geometry_traits_2() const - { return m_geometry_traits_2; } + Env_sphere_traits_3() : m_is_lower(true) {} protected: mutable bool m_is_lower; - -private: - //! The conic geometry-traits. - const Shared_geometry_traits_2 m_geometry_traits_2; }; -/*! - * Compare two spheres: first compare their center points in an - * xyz-lexicographic order, then by their radii. +/*! Compare two spheres: first compare their center points in an + * xyz-lexicographic order, then by their squared radii. + * + * \todo This should be deprecated and instead the traits should provide this + * functionality. */ template bool operator<(const CGAL::Sphere_3& a, const CGAL::Sphere_3& b) { Kernel k; Comparison_result res = k.compare_xyz_3_object()(a.center(), b.center()); - if (res == EQUAL) res = CGAL::compare (a.squared_radius(), b.squared_radius()); + if (res == EQUAL) res = CGAL::compare(a.squared_radius(), b.squared_radius()); return (res == SMALLER); } -/*! - * Compare two spheres for equality. +/*! Compare two spheres for equality. + * + * \todo This should be deprecated and instead the traits should provide this + * functionality. */ template -bool operator== (const typename Kernel::Sphere_3& a, - const typename Kernel::Sphere_3& b) { +bool operator==(const typename Kernel::Sphere_3& a, + const typename Kernel::Sphere_3& b) { Kernel k; - if (! k.equal_3_object() (a.center(), b.center())) return (false); - return (CGAL::compare (a.squared_radius(), b.squared_radius()) == EQUAL); + if (! k.equal_3_object()(a.center(), b.center())) return (false); + return (CGAL::compare(a.squared_radius(), b.squared_radius()) == EQUAL); } } //namespace CGAL diff --git a/Envelope_3/include/CGAL/Env_surface_data_traits_3.h b/Envelope_3/include/CGAL/Env_surface_data_traits_3.h index 9624b70a79d5..835ec7b35e2c 100644 --- a/Envelope_3/include/CGAL/Env_surface_data_traits_3.h +++ b/Envelope_3/include/CGAL/Env_surface_data_traits_3.h @@ -8,7 +8,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Ron Wein +// Author(s) : Ron Wein +// Efi Fogel + #ifndef CGAL_ENV_SURFACE_DATA_TRAITS_3_H #define CGAL_ENV_SURFACE_DATA_TRAITS_3_H @@ -19,9 +21,10 @@ * Definition of the env_surface_data_traits_3<> class template. */ -#include #include +#include + namespace CGAL { /*! \class @@ -31,95 +34,80 @@ namespace CGAL { * It can attach data objects to Surface_3 and to Xy_monotone_surface_3 objects * (possibly of two different types). */ -template > -class Env_surface_data_traits_3 : public Traits_ -{ +template > +class Env_surface_data_traits_3 : public Traits_ { public: + using Base_traits_3 = Traits_; + using Xy_monotone_surface_data = XyMonotoneSurfaceData; + using Surface_data = SurfaceData; + using Convert = Convert_; - typedef Traits_ Base_traits_3; - typedef XyMonotoneSurfaceData_ Xy_monotone_surface_data; - typedef SurfaceData_ Surface_data; - typedef Convert_ Convert; - - typedef typename Base_traits_3::Surface_3 Base_surface_3; - typedef typename Base_traits_3::Xy_monotone_surface_3 - Base_xy_monotone_surface_3; + using Base_surface_3 = typename Base_traits_3::Surface_3; + using Base_xy_monotone_surface_3 = + typename Base_traits_3::Xy_monotone_surface_3; // Representation of a surface with an additional data field: - typedef _Curve_data_ex Surface_3; + using Surface_3 = _Curve_data_ex; // Representation of an xy-monotone surface with an additional data field: - typedef _Curve_data_ex Xy_monotone_surface_3; + using Xy_monotone_surface_3 = + _Curve_data_ex; public: - /// \name Construction. //@{ /*! Default constructor. */ - Env_surface_data_traits_3 () - {} + Env_surface_data_traits_3() {} /*! Constructor from a base-traits class. */ - Env_surface_data_traits_3 (const Base_traits_3 & traits) : - Base_traits_3 (traits) + Env_surface_data_traits_3(const Base_traits_3& traits) : + Base_traits_3(traits) {} //@} /// \name Overridden functors. //@{ - class Make_xy_monotone_3 - { + class Make_xy_monotone_3 { private: - const Base_traits_3 * base; + const Base_traits_3* base; public: - /*! Constructor. */ - Make_xy_monotone_3 (const Base_traits_3 * _base) : base (_base) - {} + Make_xy_monotone_3(const Base_traits_3* _base) : base (_base) {} - /*! - * Subdivide the given surface into xy-monotone surfaces and insert them + /*! Subdivide the given surface into xy-monotone surfaces and insert them * to the given output iterator. * \param S The surface. * \param oi The output iterator, * whose value-type is Xy_monotone_surface_2. * \return The past-the-end iterator. */ - template - OutputIterator operator() (const Surface_3& S, bool is_lower, - OutputIterator oi) const - { + template + OutputIterator operator()(const Surface_3& S, bool is_lower, + OutputIterator oi) const { // Make the original surface xy-monotone. - std::list xy_surfaces; - typename std::list::iterator xys_it; + std::list xy_surfaces; + typename std::list::iterator xys_it; - base->make_xy_monotone_3_object() - (S, is_lower, std::back_inserter (xy_surfaces)); + base->make_xy_monotone_3_object()(S, is_lower, + std::back_inserter(xy_surfaces)); // Attach the data to each of the resulting xy-monotone surfaces. for (xys_it = xy_surfaces.begin(); xys_it != xy_surfaces.end(); ++xys_it) - { - *oi = Xy_monotone_surface_3 (*xys_it, - Convert() (S.data())); - ++oi; - } + *oi++ = Xy_monotone_surface_3(*xys_it, Convert() (S.data())); - return (oi); + return oi; } }; /*! Get a Make_xy_monotone_3 functor object. */ Make_xy_monotone_3 make_xy_monotone_3_object() const - { - return Make_xy_monotone_3 (this); - } + { return Make_xy_monotone_3(this); } //@} diff --git a/Envelope_3/include/CGAL/Env_triangle_traits_3.h b/Envelope_3/include/CGAL/Env_triangle_traits_3.h index 00ccc69e8faf..10218a7ceb11 100644 --- a/Envelope_3/include/CGAL/Env_triangle_traits_3.h +++ b/Envelope_3/include/CGAL/Env_triangle_traits_3.h @@ -7,8 +7,9 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Michal Meyerovitch -// Baruch Zukerman +// Author(s) : Michal Meyerovitch +// Baruch Zukerman +// Efi Fogel /*! \file CGAL/Envelope_triangles_traits_3.h * \brief Model for CGAL's EnvelopeTraits_3 concept. @@ -20,72 +21,61 @@ #include + +#include + #include #include #include #include -#include - namespace CGAL { -template class Env_triangle_3; +template class Env_triangle_3; // this traits class supports both triagles and segments in 3d -template -class Env_triangle_traits_3 : public Arr_segment_traits_2 -{ +template +class Env_triangle_traits_3 : public Arr_segment_traits_2 { public: - typedef Arr_segment_traits_2 Traits_2; - typedef typename Traits_2::Point_2 Point_2; - typedef typename Traits_2::X_monotone_curve_2 X_monotone_curve_2; - typedef typename Traits_2::Multiplicity Multiplicity; + using Traits_2 = Arr_segment_traits_2; + using Point_2 = typename Traits_2::Point_2; + using X_monotone_curve_2 = typename Traits_2::X_monotone_curve_2; + using Multiplicity = typename Traits_2::Multiplicity; - typedef Kernel_ Kernel; - typedef Env_triangle_traits_3 Self; + using Kernel = Kernel_; + using Self = Env_triangle_traits_3; - typedef typename Kernel::Point_3 Point_3; + using Point_3 = typename Kernel::Point_3; - /*! - * \class Representation of a 3d triangle with cached data. + /*! \class Representation of a 3d triangle with cached data. */ - class _Triangle_cached_3 - { + class _Triangle_cached_3 { public: - - typedef typename Kernel::Plane_3 Plane_3; - typedef typename Kernel::Triangle_3 Triangle_3; - typedef typename Kernel::Point_3 Point_3; - typedef typename Kernel::Segment_3 Segment_3; + using Plane_3 = typename Kernel::Plane_3; + using Triangle_3 = typename Kernel::Triangle_3; + using Point_3 = typename Kernel::Point_3; + using Segment_3 = typename Kernel::Segment_3; protected: - Plane_3 pl; // The plane that supports the triangle. Point_3 vertices[3]; // The vertices of the triangle. - bool is_vert; // Is this a vertical triangle (or a segment). - bool is_seg; // Is this a segment. - public: + bool is_vert; // Is this a vertical triangle (or a segment). + bool is_seg; // Is this a segment. - /*! - * Default constructor. + public: + /*! Default constructor. */ - _Triangle_cached_3() : - is_vert(false), - is_seg(false) - {} + _Triangle_cached_3() : is_vert(false), is_seg(false) {} - /*! - * Constructor from a non-degenerate triangle. + /*! Constructor from a non-degenerate triangle. * \param tri The triangle. * \pre The triangle is not degenerate. */ - _Triangle_cached_3(const Triangle_3 & tri) - { - Kernel kernel; - CGAL_assertion(!kernel.is_degenerate_3_object()(tri)); + _Triangle_cached_3(const Triangle_3& tri) { + Kernel kernel; + CGAL_assertion(! kernel.is_degenerate_3_object()(tri)); - typename Kernel::Construct_vertex_3 - construct_vertex = kernel.construct_vertex_3_object(); + auto construct_vertex = kernel.construct_vertex_3_object(); vertices[0] = construct_vertex(tri, 0); vertices[1] = construct_vertex(tri, 1); @@ -100,25 +90,22 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 is_seg = false; } - /*! - * Construct a triangle from three non-collinear end-points. + /*! Construct a triangle from three non-collinear end-points. * \param p1 The first point. * \param p2 The second point. * \param p3 The third point. * \pre The 3 endpoints are not the collinear. */ - _Triangle_cached_3(const Point_3 &p1, const Point_3 &p2, - const Point_3 &p3) - { - Kernel kernel; - CGAL_assertion(!kernel.collinear_3_object()(p1, p2, p3)); + _Triangle_cached_3(const Point_3& p1, const Point_3& p2, + const Point_3& p3) { + Kernel kernel; + CGAL_assertion(! kernel.collinear_3_object()(p1, p2, p3)); vertices[0] = p1; vertices[1] = p2; vertices[2] = p3; - pl = kernel.construct_plane_3_object()(vertices[0], - vertices[1], + pl = kernel.construct_plane_3_object()(vertices[0], vertices[1], vertices[2]); Self self; is_vert = kernel.collinear_2_object()(self.project(vertices[0]), @@ -127,8 +114,7 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 is_seg = false; } - /*! - * Construct a triangle from 3 end-points on a supporting plane. + /*! Construct a triangle from 3 end-points on a supporting plane. * \param supp_plane The supporting plane. * \param p1 The first point. * \param p2 The second point. @@ -136,13 +122,10 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 * \pre The 3 endpoints are not the collinear and all lie on the given * plane. */ - _Triangle_cached_3(const Plane_3& supp_plane, - const Point_3 &p1, - const Point_3 &p2, - const Point_3 &p3) : - pl(supp_plane) - { - Kernel kernel; + _Triangle_cached_3(const Plane_3& supp_plane, const Point_3& p1, + const Point_3& p2, const Point_3& p3) : + pl(supp_plane) { + Kernel kernel; CGAL_precondition(kernel.has_on_3_object() (pl, p1) && kernel.has_on_3_object() (pl, p2) && @@ -160,15 +143,13 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 is_seg = false; } - /*! - * Constructor from a segment. + /*! Constructor from a segment. * \param seg The segment. * \pre The segment is not degenerate. */ - _Triangle_cached_3(const Segment_3 & seg) - { - Kernel kernel; - CGAL_assertion(!kernel.is_degenerate_3_object()(seg)); + _Triangle_cached_3(const Segment_3& seg) { + Kernel kernel; + CGAL_assertion(! kernel.is_degenerate_3_object()(seg)); typename Kernel::Construct_vertex_3 construct_vertex = kernel.construct_vertex_3_object(); @@ -182,22 +163,18 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 // construct a vertical plane through the segment Point_3 tmp(vertices[0].x(), vertices[0].y(), vertices[0].z()-1); - pl = kernel.construct_plane_3_object()(vertices[0], - vertices[1], tmp); - + pl = kernel.construct_plane_3_object()(vertices[0], vertices[1], tmp); } - /*! - * Constructor from two points. + /*! Constructor from two points. * \param p1 The first point. * \param p2 The second point. * \param seg The segment. * \pre The segment between the points is not degenerate. */ - _Triangle_cached_3(const Point_3 &p1, const Point_3 &p2) - { - Kernel kernel; - CGAL_assertion(!kernel.equal_3_object()(p1, p2)); + _Triangle_cached_3(const Point_3& p1, const Point_3& p2) { + Kernel kernel; + CGAL_assertion(! kernel.equal_3_object()(p1, p2)); vertices[0] = p1; vertices[1] = p2; @@ -208,22 +185,17 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 // construct a vertical plane through the segment Point_3 tmp(vertices[0].x(), vertices[0].y(), vertices[0].z()-1); - pl = kernel.construct_plane_3_object()(vertices[0], - vertices[1], tmp); - + pl = kernel.construct_plane_3_object()(vertices[0], vertices[1], tmp); } - /*! - * Assignment operator. + /*! Assignment operator. * \param tri the source triangle to copy from */ - const _Triangle_cached_3& operator=(const Triangle_3 &tri) - { - Kernel kernel; - CGAL_assertion(!kernel.is_degenerate_3_object()(tri)); + const _Triangle_cached_3& operator=(const Triangle_3& tri) { + Kernel kernel; + CGAL_assertion(! kernel.is_degenerate_3_object()(tri)); - typename Kernel_::Construct_vertex_3 - construct_vertex = kernel.construct_vertex_3_object(); + auto construct_vertex = kernel.construct_vertex_3_object(); vertices[0] = construct_vertex(tri, 0); vertices[1] = construct_vertex(tri, 1); @@ -240,129 +212,105 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 return (*this); } - /*! - * Get the ith endpoint. + /*! Get the ith endpoint. */ - const Point_3& vertex(unsigned int i) const - { - return vertices[i%3]; - } + const Point_3& vertex(unsigned int i) const { return vertices[i%3]; } - /*! - * Get the supporting plane. + /*! Get the supporting plane. */ - const Plane_3& plane() const - { - return (pl); - } + const Plane_3& plane() const { return (pl); } - /*! - * Check if the triangle is vertical. + /*! Check whether the triangle is vertical. */ - bool is_vertical() const - { - return (is_vert); - } + bool is_vertical() const { return (is_vert); } - /*! - * Check if the surface is a segment. + /*! Check whether the surface is a segment. */ - bool is_segment() const - { - return (is_seg); - } + bool is_segment() const { return (is_seg); } - /*! - * Check if the surface is xy-monotone (false, if it is a vertical + /*! Check whether the surface is xy-monotone (false, if it is a vertical * triangle) */ - bool is_xy_monotone() const - { - return (!is_vertical() || is_segment()); - } + bool is_xy_monotone() const { return (!is_vertical() || is_segment()); } }; public: - // types for EnvelopeTraits_3 concept //! type of xy-monotone surfaces - typedef Env_triangle_3 Xy_monotone_surface_3; + using Xy_monotone_surface_3 = Env_triangle_3; //! type of surfaces - typedef Xy_monotone_surface_3 Surface_3; + using Surface_3 = Xy_monotone_surface_3; // we have a collision between the Kernel's Intersect_2 and the one // from the segment traits - typedef typename Traits_2::Intersect_2 Intersect_2; + using Intersect_2 = typename Traits_2::Intersect_2; protected: - typedef typename Kernel::FT FT; - typedef typename Kernel::Triangle_2 Triangle_2; - typedef typename Kernel::Segment_2 Segment_2; + using FT = typename Kernel::FT; + using Triangle_2 = typename Kernel::Triangle_2; + using Segment_2 = typename Kernel::Segment_2; - typedef typename Kernel::Segment_3 Segment_3; - typedef typename Kernel::Triangle_3 Triangle_3; - typedef typename Kernel::Plane_3 Plane_3; + using Segment_3 = typename Kernel::Segment_3; + using Triangle_3 = typename Kernel::Triangle_3; + using Plane_3 = typename Kernel::Plane_3; - typedef typename Kernel::Assign_2 Assign_2; - typedef typename Kernel::Construct_vertex_2 Construct_vertex_2; + using Assign_2 = typename Kernel::Assign_2; + using Construct_vertex_2 = typename Kernel::Construct_vertex_2; - typedef typename Kernel::Assign_3 Assign_3; - typedef typename Kernel::Intersect_3 Intersect_3; - typedef typename Kernel::Construct_vertex_3 Construct_vertex_3; + using Assign_3 = typename Kernel::Assign_3; + using Intersect_3 = typename Kernel::Intersect_3; + using Construct_vertex_3 = typename Kernel::Construct_vertex_3; - typedef typename Kernel::Line_2 Line_2; - typedef typename Kernel::Direction_2 Direction_2; + using Line_2 = typename Kernel::Line_2; + using Direction_2 = typename Kernel::Direction_2; - typedef typename Kernel::Line_3 Line_3; - typedef typename Kernel::Direction_3 Direction_3; + using Line_3 = typename Kernel::Line_3; + using Direction_3 = typename Kernel::Direction_3; - typedef std::pair Intersection_curve; -public: + using Intersection_curve = std::pair; +public: /***************************************************************************/ // EnvelopeTraits_3 functors /***************************************************************************/ - /*!\brief - * Subdivide the given surface into envelope relevant xy-monotone - * parts, and insert them into the output iterator. - * - * The iterator value-type is Xy_monotone_surface_3 + /*! Subdivide a given surface into \f$xy\f$-monotone parts. */ - class Make_xy_monotone_3 - { + class Make_xy_monotone_3 { protected: - const Self * parent; + using Traits_3 = Env_triangle_traits_3; + + //! The traits (in case it has state). + const Traits_3& m_traits; + + /*! Constructor + * \param traits the traits + */ + Make_xy_monotone_3(const Traits_3& traits) : m_traits(traits) {} + + friend class Env_triangle_traits_3; public: - Make_xy_monotone_3(const Self * p) : parent(p) - {} // create xy-monotone surfaces from a general surface // return a past-the-end iterator - template - OutputIterator operator()(const Surface_3& s, - bool is_lower, - OutputIterator o) const - { + template + OutputIterator operator()(const Surface_3& s, bool is_lower, + OutputIterator o) const { m_is_lower = is_lower; // a non-vertical triangle is already xy-monotone - if (!s.is_vertical()) - *o++ = s; - else - { + if (! s.is_vertical()) *o++ = s; + else { // split a vertical triangle into one or two segments - const Point_3 &a1 = s.vertex(0), - a2 = s.vertex(1), - a3 = s.vertex(2); - Point_2 b1 = parent->project(a1), - b2 = parent->project(a2), - b3 = parent->project(a3); - Kernel k; - if (k.collinear_are_ordered_along_line_2_object()(b1, b2, b3)) - { + const Point_3& a1 = s.vertex(0); + const Point_3& a2 = s.vertex(1); + const Point_3& a3 = s.vertex(2); + Point_2 b1 = m_traits.project(a1); + Point_2 b2 = m_traits.project(a2); + Point_2 b3 = m_traits.project(a3); + const Kernel& k = m_traits; + if (k.collinear_are_ordered_along_line_2_object()(b1, b2, b3)) { if (k.equal_2_object()(b1, b2)) // only one segment in the output - the vertical does not count *o++ = Xy_monotone_surface_3(find_envelope_point(a1, a2), a3); @@ -372,8 +320,7 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 // check whether two or one segments appear on the envelope return find_envelope_segments(a1, a2, a3, s.plane(), o); } - else if (k.collinear_are_ordered_along_line_2_object()(b1, b3, b2)) - { + else if (k.collinear_are_ordered_along_line_2_object()(b1, b3, b2)) { if (k.equal_2_object()(b1, b3)) // only one segment in the output *o++ = Xy_monotone_surface_3(find_envelope_point(a1, a3), a2); @@ -381,42 +328,35 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 // check whether two or one segments appear on the envelope return find_envelope_segments(a1, a3, a2, s.plane(), o); } - else - { + else { // check whether two or one segments appear on the envelope return find_envelope_segments(a2, a1, a3, s.plane(), o); } - } return o; } protected: // find the envelope point among the two points with same xy coordinates - const Point_3& find_envelope_point (const Point_3& p1, - const Point_3& p2) const - { + const Point_3& find_envelope_point(const Point_3& p1, const Point_3& p2) + const { CGAL_precondition(p1.x() == p2.x() && p1.y() == p2.y()); - Kernel k; + const Kernel& k = m_traits; Comparison_result cr = k.compare_z_3_object()(p1, p2); CGAL_assertion(cr != EQUAL); - if ((m_is_lower && cr == SMALLER) || - (!m_is_lower && cr == LARGER)) + if ((m_is_lower && cr == SMALLER) || (! m_is_lower && cr == LARGER)) return p1; - else - return p2; + else return p2; } // get the three triangle coordinates (ordered along 2d-line) and find // which segment(s) is(are) the envelope of this triangle // "plane" is the vertical plane on which the triangle lies - template - OutputIterator find_envelope_segments(const Point_3& p1, - const Point_3& p2, + template + OutputIterator find_envelope_segments(const Point_3& p1, const Point_3& p2, const Point_3& p3, const Plane_3& plane, - OutputIterator o) const - { + OutputIterator o) const { // our vertical plane is a*x + b*y + d = 0 FT a = plane.a(), b = plane.b(); CGAL_precondition(plane.c() == 0); @@ -445,9 +385,9 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 // (-b*x3 + a*y3 + b*x1 - a*y1)(z2 - z1) - // (z3 - z1)(-b*x2 + a*y2 + b*x1 - a*y1) // - FT w1 = a*p1.y() - b*p1.x(), - w2 = a*p2.y() - b*p2.x(), - w3 = a*p3.y() - b*p3.x(); + FT w1 = a*p1.y() - b*p1.x(); + FT w2 = a*p2.y() - b*p2.x(); + FT w3 = a*p3.y() - b*p3.x(); Sign s1 = CGAL::sign((w3 - w1)*(p2.z() - p1.z()) - (p3.z() - p1.z())*(w2 - w1)); @@ -461,16 +401,11 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 Sign s = CGAL_NTS sign(int(s1 * s2)); bool use_one_segment = true; - if ((m_is_lower && s == NEGATIVE) || - (!m_is_lower && s == POSITIVE)) + if ((m_is_lower && (s == NEGATIVE)) || (! m_is_lower && (s == POSITIVE))) use_one_segment = false; - if (use_one_segment) - { - *o++ = Xy_monotone_surface_3(p1, p3); - } - else - { + if (use_one_segment) *o++ = Xy_monotone_surface_3(p1, p3); + else { *o++ = Xy_monotone_surface_3(p1, p2); *o++ = Xy_monotone_surface_3(p2, p3); } @@ -480,50 +415,49 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 mutable bool m_is_lower; }; - /*! Get a Make_xy_monotone_3 functor object. */ + /*! Obtain a Make_xy_monotone_3 functor object. */ Make_xy_monotone_3 - make_xy_monotone_3_object() const - { - return Make_xy_monotone_3(this); - } + make_xy_monotone_3_object() const { return Make_xy_monotone_3(*this); } - /*!\brief - * Insert all 2D curves, which form the boundary of the vertical - * projection of the surface onto the xy-plane, into the output iterator. - * The iterator value-type is X_monotone_curve_2. + /*! Compute all planar \f$x\f$-monotone curves and possibly isolated planar + * points that form the projection of the boundary of the given + * \f$xy\f$-monotone surface s onto the \f$xy\f$-plane. */ - class Construct_projected_boundary_2 - { + class Construct_projected_boundary_2 { protected: - const Self *parent; - public: + using Traits_3 = Env_triangle_traits_3; - Construct_projected_boundary_2(const Self* p) - : parent(p) - {} + //! The traits (in case it has state). + const Traits_3& m_traits; + + /*! Constructor + * \param traits the traits + */ + Construct_projected_boundary_2(const Traits_3& traits) : m_traits(traits) {} + friend class Env_triangle_traits_3; + + public: // insert into the OutputIterator all the (2d) curves of the boundary of // the vertical projection of the surface on the xy-plane // the OutputIterator value type is X_monotone_curve_2 - template + template OutputIterator operator()(const Xy_monotone_surface_3& s, - OutputIterator o) const - { + OutputIterator o) const { // the input xy-monotone surface should be either non-vertical or // a segment CGAL_assertion(s.is_xy_monotone()); - if (!s.is_vertical()) - { + if (! s.is_vertical()) { // the projection is a triangle - const Point_3 &a1 = s.vertex(0), - a2 = s.vertex(1), - a3 = s.vertex(2); - Point_2 b1 = parent->project(a1), - b2 = parent->project(a2), - b3 = parent->project(a3); + const Point_3& a1 = s.vertex(0); + const Point_3& a2 = s.vertex(1); + const Point_3& a3 = s.vertex(2); + Point_2 b1 = m_traits.project(a1); + Point_2 b2 = m_traits.project(a2); + Point_2 b3 = m_traits.project(a3); - Kernel k; + const Kernel& k = m_traits; X_monotone_curve_2 A(b1, b2); X_monotone_curve_2 B(b2, b3); @@ -540,128 +474,116 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 Oriented_side s2 = k.oriented_side_2_object()(l2, b1); Oriented_side s3 = k.oriented_side_2_object()(l3, b2); - CGAL_assertion(s1 != ON_ORIENTED_BOUNDARY && - s2 != ON_ORIENTED_BOUNDARY && - s3 != ON_ORIENTED_BOUNDARY); + CGAL_assertion((s1 != ON_ORIENTED_BOUNDARY) && + (s2 != ON_ORIENTED_BOUNDARY) && + (s3 != ON_ORIENTED_BOUNDARY)); *o++ = std::make_pair(A, s1); *o++ = std::make_pair(B, s2); *o++ = std::make_pair(C, s3); + return o; } - else - { - // s is a segment, and so is its projection - // s shouldn't be a z-vertical segment - const Point_3 &a1 = s.vertex(0), - a2 = s.vertex(1); - - Point_2 b1 = parent->project(a1), - b2 = parent->project(a2); - CGAL_assertion(b1 != b2); - - *o++ = std::make_pair(X_monotone_curve_2(b1, b2), - ON_ORIENTED_BOUNDARY); - } + + // s is a segment, and so is its projection + // s shouldn't be a z-vertical segment + const Point_3& a1 = s.vertex(0); + const Point_3& a2 = s.vertex(1); + + Point_2 b1 = m_traits.project(a1); + Point_2 b2 = m_traits.project(a2); + CGAL_assertion(b1 != b2); + + *o++ = std::make_pair(X_monotone_curve_2(b1, b2), ON_ORIENTED_BOUNDARY); return o; } }; - /*! Get a Construct_projected_boundary_curves_2 functor object. */ + /*! Obtain a Construct_projected_boundary_curves_2 functor object. */ Construct_projected_boundary_2 construct_projected_boundary_2_object() const - { - return Construct_projected_boundary_2(this); - } + { return Construct_projected_boundary_2(*this); } - /*!\brief - * Insert all the 2D projections (onto the xy-plane) of the - * intersection objects between s1 and s2 into the output iterator. - * - * The iterator value-type is Object. An Object may be: - * 1. A pair, where the intersection - * type is an enumeration that can take the values - * {Transversal, Tangency, Unknown}. - * 2. A Point_2 instance (in degenerate cases). + /*! compute the projection of the intersections of the \f$xy\f$-monotone + * surfaces onto the \f$xy\f$-plane, */ - class Construct_projected_intersections_2 - { + class Construct_projected_intersections_2 { protected: - const Self *parent; - public: + using Traits_3 = Env_triangle_traits_3; - Construct_projected_intersections_2(const Self* p) - : parent(p) + //! The traits (in case it has state). + const Traits_3& m_traits; + + /*! Constructor + * \param traits the traits + */ + Construct_projected_intersections_2(const Traits_3& traits) : + m_traits(traits) {} + friend class Env_triangle_traits_3; + + public: // insert into OutputIterator all the (2d) projections on the xy plane of // the intersection objects between the 2 surfaces // the data type of OutputIterator is Object - template + template OutputIterator operator()(const Xy_monotone_surface_3& s1, const Xy_monotone_surface_3& s2, - OutputIterator o) const - { + OutputIterator o) const { CGAL_assertion(s1.is_xy_monotone() && s2.is_xy_monotone()); - Kernel k; - if (!parent->do_intersect(s1, s2)) - { - return o; - } + if (! m_traits.do_intersect(s1, s2)) return o; - std::optional> inter_obj - = parent->intersection(s1,s2); - if (inter_obj == std::nullopt) - { + const Kernel& k = m_traits; + std::optional> inter_obj = + m_traits.intersection(s1, s2); + if (inter_obj == std::nullopt) return o; + + if (const auto* point = std::get_if(&(*inter_obj))) { + *o++ = m_traits.project(*point); return o; } - if (const Point_3* point = std::get_if(&(*inter_obj))) - *o++ = parent->project(*point); - else - { - const Segment_3* curve = std::get_if(&(*inter_obj)); - CGAL_assertion(curve != nullptr); - - Segment_2 proj_seg = parent->project(*curve); - if (! k.is_degenerate_2_object() (proj_seg)) - { - Intersection_curve inter_cv (proj_seg, 1); - *o++ = inter_cv; - } - else - { - const Point_2& p = k.construct_point_on_2_object() (proj_seg, 0); - *o++ = p; - } + const auto* curve = std::get_if(&(*inter_obj)); + CGAL_assertion(curve != nullptr); + + Segment_2 proj_seg = m_traits.project(*curve); + if (! k.is_degenerate_2_object() (proj_seg)) { + Intersection_curve inter_cv (proj_seg, 1); + *o++ = inter_cv; + return o; } + const Point_2& p = k.construct_point_on_2_object() (proj_seg, 0); + *o++ = p; return o; } }; - /*! Get a Construct_projected_intersections_2 functor object. */ + /*! Obtain a Construct_projected_intersections_2 functor object. */ Construct_projected_intersections_2 construct_projected_intersections_2_object() const - { - return Construct_projected_intersections_2(this); - } + { return Construct_projected_intersections_2(*this); } - /*!\brief - * Check if the surface s1 is closer/equally distanced/farther - * from the envelope with respect to s2 at the xy-coordinates of p/c. + /*! Determine the relative \f$z\f$-order of two given \f$xy\f$-monotone + * surfaces at the \f$xy\f$-coordinates of a given point or \f$x\f$-monotone + * curve. */ - class Compare_z_at_xy_3 - { + class Compare_z_at_xy_3 { protected: - const Self *parent; + using Traits_3 = Env_triangle_traits_3; - public: + //! The traits (in case it has state). + const Traits_3& m_traits; - Compare_z_at_xy_3(const Self* p) - : parent(p) - {} + /*! Constructor + * \param traits the traits + */ + Compare_z_at_xy_3(const Traits_3& traits) : m_traits(traits) {} + + friend class Env_triangle_traits_3; + public: // check which of the surfaces is closer to the envelope at the xy // coordinates of point // (i.e. lower if computing the lower envelope, or upper if computing @@ -669,8 +591,7 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 // precondition: the surfaces are defined in point Comparison_result operator()(const Point_2& p, const Xy_monotone_surface_3& surf1, - const Xy_monotone_surface_3& surf2) const - { + const Xy_monotone_surface_3& surf2) const { // we compute the points on the planes, and then compare their z // coordinates const Plane_3& plane1 = surf1.plane(); @@ -679,18 +600,14 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 // if the 2 triangles have the same supporting plane, and they are not // vertical, then they have the same z coordinate over this point if ((plane1 == plane2 || plane1 == plane2.opposite()) && - !surf1.is_vertical()) - { + ! surf1.is_vertical()) return EQUAL; - } - - Kernel k; // Compute the intersetion between the vertical line and the given // surfaces - Point_3 ip1 = parent->envelope_point_of_surface(p, surf1); - Point_3 ip2 = parent->envelope_point_of_surface(p, surf2); - + const Kernel& k = m_traits; + Point_3 ip1 = m_traits.envelope_point_of_surface(p, surf1); + Point_3 ip2 = m_traits.envelope_point_of_surface(p, surf2); return k.compare_z_3_object()(ip1, ip2); } @@ -702,50 +619,49 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 // and the answer is the same for each of these points Comparison_result operator()(const X_monotone_curve_2& cv, const Xy_monotone_surface_3& surf1, - const Xy_monotone_surface_3& surf2) const - { + const Xy_monotone_surface_3& surf2) const { // first try the endpoints, if cannot be sure, use the mid point - Comparison_result res; - res = parent->compare_z_at_xy_3_object()(cv.left(), surf1, surf2); - - if (res == EQUAL) - { - res = parent->compare_z_at_xy_3_object()(cv.right(), surf1, surf2); - if (res == EQUAL) - { - Point_2 mid = parent->construct_middle_point(cv); - res = parent->compare_z_at_xy_3_object()(mid, surf1, surf2); + Comparison_result res = + m_traits.compare_z_at_xy_3_object()(cv.left(), surf1, surf2); + + if (res == EQUAL) { + res = m_traits.compare_z_at_xy_3_object()(cv.right(), surf1, surf2); + if (res == EQUAL) { + Point_2 mid = m_traits.construct_middle_point(cv); + res = m_traits.compare_z_at_xy_3_object()(mid, surf1, surf2); } } return res; } - }; - /*! Get a Compare_z_at_xy_3 functor object. */ + /*! Obtain a Compare_z_at_xy_3 functor object. */ Compare_z_at_xy_3 - compare_z_at_xy_3_object() const - { - return Compare_z_at_xy_3(this); - } - - /*!\brief - * Check if the surface s1 is closer/equally distanced/farther - * from the envelope with - * respect to s2 immediately above the curve c. + compare_z_at_xy_3_object() const { return Compare_z_at_xy_3(*this); } + + /*! Determine the relative \f$z\f$-order of the two given \f$xy\f$-monotone + * surfaces immediately above their projected intersection curve (a planar + * point \f$p\f$ is above an \f$x\f$-monotone curve \f$c\f$ if it is in the + * \f$x\f$-range of \f$c\f$, and lies to its left when the curve is traversed + * from its \f$xy\f$-lexicographically smaller endpoint to its larger + * endpoint). */ - class Compare_z_at_xy_above_3 - { + class Compare_z_at_xy_above_3 { protected: - const Self *parent; + using Traits_3 = Env_triangle_traits_3; - public: + //! The traits (in case it has state). + const Traits_3& m_traits; - Compare_z_at_xy_above_3(const Self* p) - : parent(p) - {} + /*! Constructor + * \param traits the traits + */ + Compare_z_at_xy_above_3(const Traits_3& traits) : m_traits(traits) {} + + friend class Env_triangle_traits_3; + public: // check which of the surfaces is closer to the envelope on the points // above the curve cv // (i.e. lower if computing the lower envelope, or upper if computing the @@ -759,29 +675,24 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 Comparison_result operator()(const X_monotone_curve_2& cv, const Xy_monotone_surface_3& surf1, - const Xy_monotone_surface_3& surf2) const - { + const Xy_monotone_surface_3& surf2) const { // a vertical surface cannot be defined in the infinitesimal region above // a curve - CGAL_precondition(!surf1.is_vertical()); - CGAL_precondition(!surf2.is_vertical()); + CGAL_precondition(! surf1.is_vertical()); + CGAL_precondition(! surf2.is_vertical()); - CGAL_precondition(parent->compare_z_at_xy_3_object() - (cv, surf1, surf2) == EQUAL); - CGAL_precondition(parent->compare_z_at_xy_3_object() - (cv.source(), surf1, surf2) == EQUAL); - CGAL_precondition(parent->compare_z_at_xy_3_object() - (cv.target(), surf1, surf2) == EQUAL); + CGAL_precondition(m_traits.compare_z_at_xy_3_object() + (cv, surf1, surf2) == EQUAL); + CGAL_precondition(m_traits.compare_z_at_xy_3_object() + (cv.source(), surf1, surf2) == EQUAL); + CGAL_precondition(m_traits.compare_z_at_xy_3_object() + (cv.target(), surf1, surf2) == EQUAL); - - if (parent->do_overlap(surf1, surf2)) - { - return EQUAL; - } + if (m_traits.do_overlap(surf1, surf2)) return EQUAL; // now we must have 2 different non-vertical planes: - // plane1: a1*x + b1*y + c1*z + d1 = 0 , c1 != 0 - // plane2: a2*x + b2*y + c2*z + d2 = 0 , c2 != 0 + // plane1: a1*x + b1*y + c1*z + d1 = 0 , c1 != 0 + // plane2: a2*x + b2*y + c2*z + d2 = 0 , c2 != 0 const Plane_3& plane1 = surf1.plane(); const Plane_3& plane2 = surf2.plane(); @@ -789,8 +700,8 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 FT a1 = plane1.a(), b1 = plane1.b(), c1 = plane1.c(); FT a2 = plane2.a(), b2 = plane2.b(), c2 = plane2.c(); - // our line is a3*x + b3*y + c3 = 0 - // it is assumed that the planes intersect over this line + // our line is a3*x + b3*y + c3 = 0 + // it is assumed that the planes intersect over this line const Line_2& line = cv.line(); FT a3 = line.a(), b3 = line.b(), c3 = line.c(); @@ -838,37 +749,40 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 } }; - - /*! Get a Compare_z_at_xy_above_3 functor object. */ + /*! Obtain a Compare_z_at_xy_above_3 functor object. */ Compare_z_at_xy_above_3 compare_z_at_xy_above_3_object() const - { - return Compare_z_at_xy_above_3(this); - } - - /*!\brief - * Check if the surface s1 is closer/equally distanced/farther - * from the envelope with - * respect to s2 immediately below the curve c. + { return Compare_z_at_xy_above_3(*this); } + + /*! Determine the relative \f$z\f$-order of the two given \f$xy\f$-monotone + * surfaces immediately below their projected intersection curve (a planar + * point \f$p\f$ is below an \f$x\f$-monotone curve \f$c\f$ if it is in the + * \f$x\f$-range of \f$c\f$, and lies to its left when the curve is traversed + * from its \f$xy\f$-lexicographically smaller endpoint to its larger + * endpoint). */ - class Compare_z_at_xy_below_3 - { + class Compare_z_at_xy_below_3 { protected: - const Self *parent; + using Traits_3 = Env_triangle_traits_3; - public: + //! The traits (in case it has state). + const Traits_3& m_traits; - Compare_z_at_xy_below_3(const Self* p) - : parent(p) - {} + /*! Constructor + * \param traits the traits + */ + Compare_z_at_xy_below_3(const Traits_3& traits) : m_traits(traits) {} + + friend class Env_triangle_traits_3; + public: + // Comparison_result operator()(const X_monotone_curve_2& cv, const Xy_monotone_surface_3& surf1, - const Xy_monotone_surface_3& surf2) const - { + const Xy_monotone_surface_3& surf2) const { Comparison_result left_res = - parent->compare_z_at_xy_above_3_object()(cv, surf1, surf2); + m_traits.compare_z_at_xy_above_3_object()(cv, surf1, surf2); return CGAL::opposite(left_res); /*if (left_res == LARGER) @@ -880,12 +794,10 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 } }; - /*! Get a Compare_z_at_xy_below_3 functor object. */ + /*! Obtain a Compare_z_at_xy_below_3 functor object. */ Compare_z_at_xy_below_3 compare_z_at_xy_below_3_object() const - { - return Compare_z_at_xy_below_3(this); - } + { return Compare_z_at_xy_below_3(*this); } /***************************************************************************/ @@ -911,24 +823,33 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 // public method needed for testing // checks if point is in the xy-range of surf - class Is_defined_over - { + class Is_defined_over { + protected: + using Traits_3 = Env_triangle_traits_3; + + //! The traits (in case it has state). + const Traits_3& m_traits; + + /*! Constructor + * \param traits the traits + */ + Is_defined_over(const Traits_3& traits) : m_traits(traits) {} + + friend class Env_triangle_traits_3; + public: // checks if point is in the xy-range of surf - bool operator()(const Point_2& point, - const Xy_monotone_surface_3& surf) const - - { - Kernel k; - Self parent; + bool operator()(const Point_2& point, const Xy_monotone_surface_3& surf) + const { + const Kernel& k = m_traits; // project the surface on the plane - Triangle_2 boundary = parent.project(surf); + Triangle_2 boundary = m_traits.project(surf); // if surface is not vertical (i.e. boundary is not degenerate) // check if the projected point is inside the projected boundary - if (!k.is_degenerate_2_object()(boundary)) - return (!k.has_on_unbounded_side_2_object()(boundary, point)); + if (! k.is_degenerate_2_object()(boundary)) + return (! k.has_on_unbounded_side_2_object()(boundary, point)); // if surface is vertical, we check if the point is collinear // with the projected vertices, and on one of the projected segments @@ -937,7 +858,7 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 Point_2 v2 = k.construct_vertex_2_object()(boundary, 1); Point_2 v3 = k.construct_vertex_2_object()(boundary, 2); - if (!k.collinear_2_object()(v1, v2, point)) + if (! k.collinear_2_object()(v1, v2, point)) return false; // enough to check 2 edges, because the 3rd is part of their union @@ -949,67 +870,60 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 /*! Get a Is_defined_over functor object. */ Is_defined_over is_defined_over_object() const - { - return Is_defined_over(); - } - - Segment_2 project (const Segment_3& seg) const - { - typedef typename Kernel::Construct_vertex_3 Construct_vertex_3; - - Kernel k; - Construct_vertex_3 vertex_on = k.construct_vertex_3_object(); - - const Point_3 q0 = (vertex_on (seg, 0)); - const Point_3 q1 = (vertex_on (seg, 1)); - const Point_2 p0 (q0.x(), q0.y()); - const Point_2 p1 (q1.x(), q1.y()); - + { return Is_defined_over(*this); } + + // + Segment_2 project (const Segment_3& seg) const { + using Construct_vertex_3 = typename Kernel::Construct_vertex_3; + + const Kernel& k = *this; + Construct_vertex_3 vertex_on = k.construct_vertex_3_object(); + const Point_3 q0 = vertex_on(seg, 0); + const Point_3 q1 = vertex_on(seg, 1); + const Point_2 p0(q0.x(), q0.y()); + const Point_2 p1(q1.x(), q1.y()); return (k.construct_segment_2_object() (p0, p1)); } + // Point_2 project(const Point_3& obj) const - { - return Point_2(obj.x(), obj.y()); - } - - Triangle_2 project(const Xy_monotone_surface_3& triangle_3) const - { - const Point_3& end1 = triangle_3.vertex(0), - end2 = triangle_3.vertex(1), - end3 = triangle_3.vertex(2); - Point_2 projected_end1(end1.x(), end1.y()), - projected_end2(end2.x(), end2.y()), - - projected_end3(end3.x(), end3.y()); + { return Point_2(obj.x(), obj.y()); } + + // + Triangle_2 project(const Xy_monotone_surface_3& triangle_3) const { + const Point_3& end1 = triangle_3.vertex(0); + const Point_3& end2 = triangle_3.vertex(1); + const Point_3& end3 = triangle_3.vertex(2); + Point_2 projected_end1(end1.x(), end1.y()); + Point_2 projected_end2(end2.x(), end2.y()); + Point_2 projected_end3(end3.x(), end3.y()); return Triangle_2(projected_end1, projected_end2, projected_end3); } // triangles overlap if they lie on the same plane and intersect on it. // this test is only needed for non-vertical triangles bool do_overlap(const Xy_monotone_surface_3& s1, - const Xy_monotone_surface_3& s2) const - { - CGAL_precondition(s1.is_xy_monotone() && !s1.is_vertical()); - CGAL_precondition(s2.is_xy_monotone() && !s2.is_vertical()); + const Xy_monotone_surface_3& s2) const { + CGAL_precondition(s1.is_xy_monotone() && ! s1.is_vertical()); + CGAL_precondition(s2.is_xy_monotone() && ! s2.is_vertical()); - Kernel k; - if (!k.do_intersect_3_object()(static_cast(s1), - static_cast(s2))) + const Kernel& k = *this; + auto do_x = k.do_intersect_3_object(); + if (! do_x(static_cast(s1), static_cast(s2))) return false; // check if they are coplanar - Point_3 a1 = s1.vertex(0), - b1 = s1.vertex(1), - c1 = s1.vertex(2); - Point_3 a2 = s2.vertex(0), - b2 = s2.vertex(1), - c2 = s2.vertex(2); + Point_3 a1 = s1.vertex(0); + Point_3 b1 = s1.vertex(1); + Point_3 c1 = s1.vertex(2); + Point_3 a2 = s2.vertex(0); + Point_3 b2 = s2.vertex(1); + Point_3 c2 = s2.vertex(2); bool b = k.coplanar_3_object()(a1, b1, c1, a2); - if (!b) return false; + if (! b) return false; b = k.coplanar_3_object()(a1, b1, c1, b2); - if (!b) return false; + if (! b) return false; b = k.coplanar_3_object()(a1, b1, c1, c2); return b; @@ -1018,75 +932,61 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 // check whether two xy-monotone surfaces (3D-triangles or segments) // intersect bool do_intersect(const Xy_monotone_surface_3& s1, - const Xy_monotone_surface_3& s2) const - { + const Xy_monotone_surface_3& s2) const { CGAL_precondition(s1.is_xy_monotone()); CGAL_precondition(s2.is_xy_monotone()); - Kernel k; - if (!s1.is_segment() && !s2.is_segment()) - return k.do_intersect_3_object()(static_cast(s1), - static_cast(s2)); - else if (!s1.is_segment()) - return k.do_intersect_3_object()(static_cast(s1), - static_cast(s2)); - else if (!s2.is_segment()) - return k.do_intersect_3_object()(static_cast(s1), - static_cast(s2)); - else - // in case of two segments, we don't use easy do-intersect test - return true; + + const Kernel& k = *this; + auto do_x = k.do_intersect_3_object(); + if (! s1.is_segment() && ! s2.is_segment()) + return do_x(static_cast(s1), static_cast(s2)); + else if (! s1.is_segment()) + return do_x(static_cast(s1), static_cast(s2)); + else if (! s2.is_segment()) + return do_x(static_cast(s1), static_cast(s2)); + else return true; // if two segments, we don't use easy do-intersect test } // intersect two xy-monotone surfaces (3D-triangles or segments) // if the triangles overlap, the result is empty // the result can be a segment or a point - std::optional< std::variant> - intersection(const Xy_monotone_surface_3& s1, - const Xy_monotone_surface_3& s2) const - { + std::optional> + intersection(const Xy_monotone_surface_3& s1, const Xy_monotone_surface_3& s2) + const { CGAL_precondition(s1.is_xy_monotone()); CGAL_precondition(s2.is_xy_monotone()); Kernel k; // first, try to intersect the bounding boxes of the triangles, // efficiently return empty object when the triangles are faraway - if (!CGAL::do_overlap(s1.bbox(), s2.bbox())) - return std::nullopt; + if (! CGAL::do_overlap(s1.bbox(), s2.bbox())) return std::nullopt; // if intersecting two segment - alculate the intersection // as in the case of dimension 2 if (s1.is_segment() && s2.is_segment()) - { return intersection_of_segments(s1, s2); - } // if both triangles lie on the same (non-vertical) plane, they overlap // we don't care about overlaps, because they are not passed to the // algorithm anyway, so we save the costly computation Plane_3 p1 = s1.plane(); Plane_3 p2 = s2.plane(); - if (p1 == p2 || p1 == p2.opposite()) - return std::nullopt; + if ((p1 == p2) || (p1 == p2.opposite())) return std::nullopt; // calculate intersection between a triangle and the other triangle's // supporting plane // if there is no intersection - then the triangles have no intersection // between them. auto inter_obj = intersection(p1, s2); - - if (inter_obj == std::nullopt) - return std::nullopt; + if (inter_obj == std::nullopt) return std::nullopt; // otherwise, if the intersection in a point, we should check if it lies // inside the first triangle - if (const Point_3* inter_point = std::get_if(&(*inter_obj))) - { + if (const Point_3* inter_point = std::get_if(&(*inter_obj))) { std::optional res = intersection_on_plane_3(p1, s1, *inter_point); - if (res != std::nullopt) - return res.value(); + if (res != std::nullopt) return res.value(); } - else - { + else { // if the intersection is a segment, we check the intersection of the // other plane-triangle pair const Segment_3* inter_seg = std::get_if(&(*inter_obj)); @@ -1096,51 +996,40 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 // if there is no intersection - then the triangles have no intersection // between them. - if (inter_obj2 == std::nullopt) - return std::nullopt; + if (inter_obj2 == std::nullopt) return std::nullopt; - if (const Point_3* inter_point = std::get_if(&(*inter_obj2))) - { + if (const Point_3* inter_point = std::get_if(&(*inter_obj2))) { // if the intersection is a point, which lies on the segment, // than it is the result, // otherwise, empty result - if (k.has_on_3_object()(*inter_seg, *inter_point)) - return *inter_point; - else - return std::nullopt; + if (k.has_on_3_object()(*inter_seg, *inter_point)) return *inter_point; + else return std::nullopt; } - else - { + else { // both plane-triangle intersections are segments, which are collinear, // and lie on the line which is the intersection of the two supporting // planes const Segment_3* inter_seg2 = std::get_if(&(*inter_obj)); CGAL_assertion(inter_seg2 != nullptr); - Point_3 min1 = k.construct_min_vertex_3_object()(*inter_seg), - max1 = k.construct_max_vertex_3_object()(*inter_seg); - Point_3 min2 = k.construct_min_vertex_3_object()(*inter_seg2), - max2 = k.construct_max_vertex_3_object()(*inter_seg2); + Point_3 min1 = k.construct_min_vertex_3_object()(*inter_seg); + Point_3 max1 = k.construct_max_vertex_3_object()(*inter_seg); + Point_3 min2 = k.construct_min_vertex_3_object()(*inter_seg2); + Point_3 max2 = k.construct_max_vertex_3_object()(*inter_seg2); CGAL_assertion((k.collinear_3_object()(min1, min2, max1) && k.collinear_3_object()(min1, max2, max1))); // we need to find the overlapping part, if exists Point_3 min, max; - if (k.less_xyz_3_object()(min1, min2)) - min = min2; - else - min = min1; - if (k.less_xyz_3_object()(max1, max2)) - max = max1; - else - max = max2; + if (k.less_xyz_3_object()(min1, min2)) min = min2; + else min = min1; + if (k.less_xyz_3_object()(max1, max2)) max = max1; + else max = max2; Comparison_result comp_res = k.compare_xyz_3_object()(min, max); - if (comp_res == EQUAL) - return min; - else if (comp_res == SMALLER) - return Segment_3(min, max); + if (comp_res == EQUAL) return min; + else if (comp_res == SMALLER) return Segment_3(min, max); // else - empty result } } @@ -1151,14 +1040,13 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 std::optional intersection_on_plane_3(const Plane_3& plane, const Xy_monotone_surface_3& triangle, - const Point_3& point) const - { - Kernel k; - CGAL_precondition( triangle.is_xy_monotone() ); - CGAL_precondition( !k.is_degenerate_3_object()(plane) ); - CGAL_precondition( triangle.plane() == plane || - triangle.plane() == plane.opposite()); - CGAL_precondition( k.has_on_3_object()(plane, point) ); + const Point_3& point) const { + const Kernel& k = *this; + CGAL_precondition(triangle.is_xy_monotone() ); + CGAL_precondition(! k.is_degenerate_3_object()(plane) ); + CGAL_precondition((triangle.plane() == plane) || + (triangle.plane() == plane.opposite())); + CGAL_precondition(k.has_on_3_object()(plane, point) ); CGAL_USE(plane); // if the point is inside the triangle, then the point is the intersection @@ -1168,63 +1056,55 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 has_on = k.has_on_3_object()(static_cast(triangle), point); else has_on = k.has_on_3_object()(static_cast(triangle), point); - if (has_on) - return point; - else - return std::nullopt; + if (has_on) return point; + else return std::nullopt; } // calculate intersection between 2 segments on the same vertical plane plane - std::optional< std::variant> + std::optional> intersection_of_segments(const Xy_monotone_surface_3& s1, - const Xy_monotone_surface_3& s2) const - { - Kernel k; - CGAL_precondition( s1.is_xy_monotone() && s1.is_segment()); - CGAL_precondition( s2.is_xy_monotone() && s2.is_segment()); + const Xy_monotone_surface_3& s2) const { + const Kernel& k = *this; + CGAL_precondition(s1.is_xy_monotone() && s1.is_segment()); + CGAL_precondition(s2.is_xy_monotone() && s2.is_segment()); // if the segments are not coplanar, they cannot intersect - if (!k.coplanar_3_object()(s1.vertex(0), s1.vertex(1), - s2.vertex(0), s2.vertex(1))) + if (! k.coplanar_3_object()(s1.vertex(0), s1.vertex(1), + s2.vertex(0), s2.vertex(1))) return std::nullopt; const Plane_3& plane = s1.plane(); - if (s2.plane() != plane && - s2.plane() != plane.opposite()) + if (s2.plane() != plane && s2.plane() != plane.opposite()) // todo: this case is not needed in the algorithm, // so we don't implement it return std::nullopt; - CGAL_precondition( !k.is_degenerate_3_object()(plane) ); - CGAL_precondition( s2.plane() == plane || - s2.plane() == plane.opposite()); + CGAL_precondition(! k.is_degenerate_3_object()(plane) ); + CGAL_precondition((s2.plane() == plane) || + (s2.plane() == plane.opposite())); // for simplicity, we transform the segments to the xy-plane, // compute the intersection there, and transform it back to the 3d plane. - Point_2 v1 = plane.to_2d(s1.vertex(0)), - v2 = plane.to_2d(s1.vertex(1)); + Point_2 v1 = plane.to_2d(s1.vertex(0)); + Point_2 v2 = plane.to_2d(s1.vertex(1)); Segment_2 seg1_t(v1, v2); - Point_2 u1 = plane.to_2d(s2.vertex(0)), - u2 = plane.to_2d(s2.vertex(1)); + Point_2 u1 = plane.to_2d(s2.vertex(0)); + Point_2 u2 = plane.to_2d(s2.vertex(1)); Segment_2 seg2_t(u1, u2); auto inter_obj = k.intersect_2_object()(seg1_t, seg2_t); - if (inter_obj == std::nullopt) - return std::nullopt; + if (inter_obj == std::nullopt) return std::nullopt; if (const Point_2* inter_point = std::get_if(&(*inter_obj))) return plane.to_3d(*inter_point); - else - { - const Segment_2* inter_segment = std::get_if(&(*inter_obj)); - CGAL_assertion(inter_segment!=nullptr); - return Segment_3 - (plane.to_3d(k.construct_vertex_2_object()(*inter_segment, 0)), - plane.to_3d(k.construct_vertex_2_object()(*inter_segment, 1))); - } + const Segment_2* inter_segment = std::get_if(&(*inter_obj)); + CGAL_assertion(inter_segment != nullptr); + auto ctr_vertex = k.construct_vertex_2_object(); + return Segment_3(plane.to_3d(ctr_vertex(*inter_segment, 0)), + plane.to_3d(ctr_vertex(*inter_segment, 1))); } // calculate the intersection between a triangle/segment @@ -1232,12 +1112,10 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 // the result object can be empty, a point, a segment or the original // triangle std::optional> - intersection(const Plane_3& pl, - const Xy_monotone_surface_3& tri) const - { - Kernel k; - CGAL_precondition( tri.is_xy_monotone() ); - CGAL_precondition( !k.is_degenerate_3_object()(pl) ); + intersection(const Plane_3& pl, const Xy_monotone_surface_3& tri) const { + const Kernel& k = *this; + CGAL_precondition(tri.is_xy_monotone() ); + CGAL_precondition(! k.is_degenerate_3_object()(pl) ); if (tri.is_segment()) return k.intersect_3_object()(pl, static_cast(tri)); @@ -1255,8 +1133,7 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 int n_points_on_negative = 0; Oriented_side side; - for (int i=0; i<3; ++i) - { + for (int i = 0; i < 3; ++i) { side = pl.oriented_side(tri.vertex(i)); if (side == ON_NEGATIVE_SIDE) points_on_negative[n_points_on_negative++] = i; @@ -1266,28 +1143,25 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 points_on_plane[n_points_on_plane++] = i; } - CGAL_assertion(n_points_on_plane + n_points_on_positive + n_points_on_negative == 3); + CGAL_assertion(n_points_on_plane + n_points_on_positive + + n_points_on_negative == 3); // if all vertices of tri lie on the same size (positive/negative) of pl, // there is no intersection - if (n_points_on_positive == 3 || n_points_on_negative == 3) + if ((n_points_on_positive == 3) || (n_points_on_negative == 3)) return std::nullopt; // if all vertices of tri lie on pl then we return tri - if (n_points_on_plane == 3) - return tri; + if (n_points_on_plane == 3) return tri; // if 2 vertices lie on pl, then return the segment between them - if (n_points_on_plane == 2) - { + if (n_points_on_plane == 2) { int point_idx1 = points_on_plane[0], point_idx2 = points_on_plane[1]; - return Segment_3(tri.vertex(point_idx1), - tri.vertex(point_idx2)); + return Segment_3(tri.vertex(point_idx1), tri.vertex(point_idx2)); } // if only 1 lie on pl, should check the segment opposite to it on tri - if (n_points_on_plane == 1) - { + if (n_points_on_plane == 1) { int point_on_plane_idx = points_on_plane[0]; // if the other 2 vertices are on the same side of pl, @@ -1308,23 +1182,20 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 // create the resulting segment // (between tri[point_on_plane_idx] and inter_point) - return Segment_3(tri.vertex(point_on_plane_idx), - *inter_point); - + return Segment_3(tri.vertex(point_on_plane_idx), *inter_point); } - CGAL_assertion( n_points_on_plane == 0 ); - CGAL_assertion( n_points_on_positive + n_points_on_negative == 3 ); - CGAL_assertion( n_points_on_positive != 0 ); - CGAL_assertion( n_points_on_negative != 0 ); + CGAL_assertion(n_points_on_plane == 0); + CGAL_assertion(n_points_on_positive + n_points_on_negative == 3); + CGAL_assertion(n_points_on_positive != 0); + CGAL_assertion(n_points_on_negative != 0); // now it known that there is an intersection between 2 segments of tri // and pl, it is also known which segments are those. Point_3 inter_points[2]; - int pos_it, neg_it, n_inter_points = 0; - for(pos_it = 0; pos_it < n_points_on_positive; ++pos_it) - for(neg_it = 0; neg_it < n_points_on_negative; ++neg_it) - { + int n_inter_points = 0; + for (int pos_it = 0; pos_it < n_points_on_positive; ++pos_it) + for (int neg_it = 0; neg_it < n_points_on_negative; ++neg_it) { Segment_3 seg(tri.vertex(points_on_positive[pos_it]), tri.vertex(points_on_negative[neg_it])); auto inter_result = k.intersect_3_object()(pl, seg); @@ -1339,11 +1210,8 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 // compare the value of s1 in p1 to the value of s2 in p2 Comparison_result - compare_z(const Point_2& p1, - const Xy_monotone_surface_3& s1, - const Point_2& p2, - const Xy_monotone_surface_3& s2) - { + compare_z(const Point_2& p1, const Xy_monotone_surface_3& s1, + const Point_2& p2, const Xy_monotone_surface_3& s2) { CGAL_precondition(is_defined_over_object()(p1, s1)); CGAL_precondition(is_defined_over_object()(p2, s2)); @@ -1356,21 +1224,18 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 // find the envelope point of the surface over the given point // precondition: the surface is defined in point Point_3 - envelope_point_of_surface(const Point_2& p, - const Xy_monotone_surface_3& s) const - { + envelope_point_of_surface(const Point_2& p, const Xy_monotone_surface_3& s) + const { CGAL_precondition(s.is_xy_monotone()); CGAL_precondition(is_defined_over_object()(p, s)); Point_3 point(p.x(), p.y(), 0); // Compute the intersetion between the vertical line and the given surfaces - if (s.is_segment()) - return envelope_point_of_segment(point, s); - else - { + if (s.is_segment()) return envelope_point_of_segment(point, s); + else { // s is a non-vertical triangle - CGAL_assertion(!s.is_vertical()); + CGAL_assertion(! s.is_vertical()); // Construct a vertical line passing through point Kernel k; @@ -1390,8 +1255,7 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 // find the envelope point of the surface over the given point // precondition: the surface is defined in point and is a segment Point_3 envelope_point_of_segment(const Point_3& point, - const Xy_monotone_surface_3& s) const - { + const Xy_monotone_surface_3& s) const { Kernel k; CGAL_precondition(s.is_segment()); CGAL_precondition(is_defined_over_object()(project(point), s)); @@ -1401,11 +1265,11 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 // Construct a vertical line passing through point Direction_3 dir (0, 0, 1); - Line_3 vl = k.construct_line_3_object() (point, dir); + Line_3 vl = k.construct_line_3_object() (point, dir); // we need 2 points on this line, to be transformed to 2d, // and preserve the direction of the envelope - Point_3 vl_point1 = k.construct_point_on_3_object()(vl, 0), - vl_point2 = k.construct_point_on_3_object()(vl, 1); + Point_3 vl_point1 = k.construct_point_on_3_object()(vl, 0); + Point_3 vl_point2 = k.construct_point_on_3_object()(vl, 1); // the surface and the line are on the same plane(plane), // so we transform them to the xy-plane, compute the intersecting point @@ -1427,14 +1291,12 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 return plane.to_3d(*inter_point); } - Point_2 construct_middle_point(const Point_2& p1, const Point_2& p2) const - { + Point_2 construct_middle_point(const Point_2& p1, const Point_2& p2) const { Kernel k; return k.construct_midpoint_2_object()(p1, p2); } - Point_2 construct_middle_point(const X_monotone_curve_2& cv) const - { + Point_2 construct_middle_point(const X_monotone_curve_2& cv) const { Kernel k; return k.construct_midpoint_2_object()(cv.source(), cv.target()); } @@ -1443,196 +1305,147 @@ class Env_triangle_traits_3 : public Arr_segment_traits_2 // for vertical decomposition /***************************************************************************/ - class Construct_vertical_2 - { + class Construct_vertical_2 { public: X_monotone_curve_2 operator()(const Point_2& p1, const Point_2& p2) const - { - return X_monotone_curve_2(p1, p2); - - } + { return X_monotone_curve_2(p1, p2); } }; /*! Get a Construct_vertical_2 functor object. */ Construct_vertical_2 construct_vertical_2_object() const - { - return Construct_vertical_2(); - } - + { return Construct_vertical_2(); } - Point_2 vertical_ray_shoot_2 (const Point_2& pt, - const X_monotone_curve_2& cv) const - { - CGAL_precondition(!cv.is_vertical()); + Point_2 vertical_ray_shoot_2(const Point_2& pt, const X_monotone_curve_2& cv) + const { + CGAL_precondition(! cv.is_vertical()); typename Kernel::Segment_2 seg = cv; - Kernel k; + const Kernel& k = *this; // If the curve contains pt, return it. - if (k.has_on_2_object() (seg, pt)) - return (pt); + if (k.has_on_2_object()(seg, pt)) return (pt); // Construct a vertical line passing through pt. - typename Kernel::Direction_2 dir (0, 1); - typename Kernel::Line_2 vl = k.construct_line_2_object() (pt, dir); + typename Kernel::Direction_2 dir(0, 1); + typename Kernel::Line_2 vl = k.construct_line_2_object()(pt, dir); // Compute the intersetion between the vertical line and the given curve. auto res = k.intersect_2_object()(seg, vl); const Point_2* ip = std::get_if(&(*res)); - CGAL_assertion (ip != nullptr); + CGAL_assertion(ip != nullptr); return *ip; } }; - -/*! - * \class A representation of a triangle, as used by the +/*! \class A representation of a triangle, as used by the * Env_triangle_traits_3 traits-class. */ -template -class Env_triangle_3 : - public Env_triangle_traits_3::_Triangle_cached_3 +template +class Env_triangle_3 : public Env_triangle_traits_3::_Triangle_cached_3 { - typedef Kernel_ Kernel; - typedef typename Kernel::Triangle_3 Triangle_3; - typedef typename Kernel::Point_3 Point_3; - typedef typename Kernel::Plane_3 Plane_3; - typedef typename Kernel::Segment_3 Segment_3; + using Kernel = Kernel_; + using Triangle_3 = typename Kernel::Triangle_3; + using Point_3 = typename Kernel::Point_3; + using Plane_3 = typename Kernel::Plane_3; + using Segment_3 = typename Kernel::Segment_3; - typedef typename Env_triangle_traits_3::_Triangle_cached_3 - Base; + using Base = typename Env_triangle_traits_3::_Triangle_cached_3; public: - - /*! - * Default constructor. + /*! Default constructor. */ - Env_triangle_3() : - Base() - {} + Env_triangle_3() : Base() {} - /*! - * Constructor from a "kernel" triangle. + /*! Constructor from a "kernel" triangle. * \param seg The segment. */ - Env_triangle_3(const Triangle_3& tri) : - Base(tri) - {} + Env_triangle_3(const Triangle_3& tri) : Base(tri) {} - /*! - * Construct a triangle from 3 end-points. + /*! Construct a triangle from 3 end-points. * \param p1 The first point. * \param p2 The second point. * \param p3 The third point. */ - Env_triangle_3(const Point_3 &p1, const Point_3 &p2, const Point_3 &p3) : - Base(p1, p2, p3) + Env_triangle_3(const Point_3& p1, const Point_3& p2, const Point_3& p3) : + Base(p1, p2, p3) {} - /*! - * Construct a triangle from a plane and 3 end-points. + /*! Construct a triangle from a plane and 3 end-points. * \param pl The supporting plane. * \param p1 The first point. * \param p2 The second point. * \param p3 The third point. * \pre All points must be on the supporting plane. */ - Env_triangle_3(const Plane_3& pl, - const Point_3 &p1, - const Point_3 &p2, - const Point_3 &p3) : + Env_triangle_3(const Plane_3& pl, const Point_3& p1, + const Point_3& p2, const Point_3& p3) : Base(pl, p1, p2, p3) - {} - /*! - * Construct a segment from 2 end-points. + /*! Construct a segment from 2 end-points. * \param p1 The first point. * \param p2 The second point. */ - Env_triangle_3(const Point_3 &p1, const Point_3 &p2) : - Base(p1, p2) - {} + Env_triangle_3(const Point_3& p1, const Point_3& p2) : Base(p1, p2) {} - /*! - * Cast to a triangle. + /*! Cast to a triangle. */ operator Triangle_3() const - { - return (Triangle_3(this->vertex(0), this->vertex(1), this->vertex(2))); - } + { return (Triangle_3(this->vertex(0), this->vertex(1), this->vertex(2))); } - /*! - * Cast to a segment (only when possible). + /*! Cast to a segment (only when possible). */ - operator Segment_3() const - { + operator Segment_3() const { CGAL_precondition(this->is_segment()); return (Segment_3(this->vertex(0), this->vertex(1))); } - /*! - * Create a bounding box for the triangle. + /*! Create a bounding box for the triangle. */ - Bbox_3 bbox() const - { + Bbox_3 bbox() const { Triangle_3 tri(this->vertex(0), this->vertex(1), this->vertex(2)); return (tri.bbox()); } }; -template -bool -operator<(const Env_triangle_3 &a, - const Env_triangle_3 &b) -{ - if (a.vertex(0) < b.vertex(0)) - return true; - if (a.vertex(0) > b.vertex(0)) - return false; - if (a.vertex(1) < b.vertex(1)) - return true; - if (a.vertex(1) > b.vertex(1)) - return false; - if (a.vertex(2) < b.vertex(2)) - return true; - if (a.vertex(2) > b.vertex(2)) - return false; +template +bool operator<(const Env_triangle_3& a, + const Env_triangle_3& b) { + if (a.vertex(0) < b.vertex(0)) return true; + if (a.vertex(0) > b.vertex(0)) return false; + if (a.vertex(1) < b.vertex(1)) return true; + if (a.vertex(1) > b.vertex(1)) return false; + if (a.vertex(2) < b.vertex(2)) return true; + if (a.vertex(2) > b.vertex(2)) return false; return false; } -template -bool -operator==(const Env_triangle_3 &a, - const Env_triangle_3 &b) -{ - return (a.vertex(0) == b.vertex(0) && - a.vertex(1) == b.vertex(1) && - a.vertex(2) == b.vertex(2)); + +template +bool operator==(const Env_triangle_3& a, + const Env_triangle_3& b) { + return ((a.vertex(0) == b.vertex(0)) && + (a.vertex(1) == b.vertex(1)) && + (a.vertex(2) == b.vertex(2))); } -/*! - * Exporter for the triangle class used by the traits-class. +/*! Exporter for the triangle class used by the traits-class. */ -template -OutputStream& operator<< (OutputStream& os, const Env_triangle_3& tri) -{ - os << static_cast(tri); - if (tri.is_segment()) - os << " (segment)"; - return (os); +template +OutputStream& operator<<(OutputStream& os, const Env_triangle_3& tri) { + os << static_cast(tri); + if (tri.is_segment()) os << " (segment)"; + return os; } -/*! - * Importer for the triangle class used by the traits-class. +/*! Importer for the triangle class used by the traits-class. */ -template -InputStream& operator>> (InputStream& is, Env_triangle_3& tri) -{ - typename Kernel::Triangle_3 kernel_tri; +template +InputStream& operator>>(InputStream& is, Env_triangle_3& tri) { + typename Kernel_::Triangle_3 kernel_tri; is >> kernel_tri; tri = kernel_tri; - return (is); + return is; } } //namespace CGAL