mirror of https://github.com/CGAL/cgal
Cleaned up; eliminated local kernels
This commit is contained in:
parent
1c7cdad3f0
commit
7381e39e1f
|
|
@ -7,7 +7,8 @@
|
||||||
// $Id$
|
// $Id$
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||||
//
|
//
|
||||||
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
// Author(s) : Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||||
|
// Efi Fogel <efifogel@gmail.com>
|
||||||
|
|
||||||
#ifndef CGAL_ENV_PLANE_TRAITS_3_H
|
#ifndef CGAL_ENV_PLANE_TRAITS_3_H
|
||||||
#define CGAL_ENV_PLANE_TRAITS_3_H
|
#define CGAL_ENV_PLANE_TRAITS_3_H
|
||||||
|
|
@ -27,169 +28,149 @@
|
||||||
|
|
||||||
namespace CGAL {
|
namespace CGAL {
|
||||||
|
|
||||||
template <class Kernel_>
|
template <typename Kernel_>
|
||||||
class Env_plane_traits_3 : public Arr_linear_traits_2<Kernel_>
|
class Env_plane_traits_3 : public Arr_linear_traits_2<Kernel_> {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
typedef Kernel_ Kernel;
|
using Kernel = Kernel_;
|
||||||
typedef typename Kernel::FT FT;
|
using FT = typename Kernel::FT;
|
||||||
typedef Arr_linear_traits_2<Kernel> Base;
|
using Base = Arr_linear_traits_2<Kernel>;
|
||||||
typedef Env_plane_traits_3<Kernel> Self;
|
using Self = Env_plane_traits_3<Kernel>;
|
||||||
|
|
||||||
typedef typename Base::Multiplicity Multiplicity;
|
using Multiplicity = typename Base::Multiplicity;
|
||||||
typedef typename Base::Point_2 Point_2;
|
using Point_2 = typename Base::Point_2;
|
||||||
typedef typename Base::Curve_2 Curve_2;
|
using Curve_2 = typename Base::Curve_2;
|
||||||
typedef typename Base::X_monotone_curve_2 X_monotone_curve_2;
|
using X_monotone_curve_2 = typename Base::X_monotone_curve_2;
|
||||||
typedef typename Kernel::Plane_3 Plane_3;
|
using Plane_3 = typename Kernel::Plane_3;
|
||||||
typedef typename Kernel::Vector_2 Vector_2;
|
using Vector_2 = typename Kernel::Vector_2;
|
||||||
typedef typename Kernel::Vector_3 Vector_3;
|
using Vector_3 = typename Kernel::Vector_3;
|
||||||
typedef typename Kernel::Segment_2 Segment_2;
|
using Segment_2 = typename Kernel::Segment_2;
|
||||||
typedef typename Kernel::Ray_2 Ray_2;
|
using Ray_2 = typename Kernel::Ray_2;
|
||||||
typedef typename Kernel::Line_2 Line_2;
|
using Line_2 = typename Kernel::Line_2;
|
||||||
typedef typename Kernel::Line_3 Line_3;
|
using Line_3 = typename Kernel::Line_3;
|
||||||
typedef std::pair<Curve_2, Multiplicity> Intersection_curve;
|
using Intersection_curve = std::pair<Curve_2, Multiplicity>;
|
||||||
|
|
||||||
typedef typename Base::Left_side_category Left_side_category;
|
using Left_side_category = typename Base::Left_side_category;
|
||||||
typedef typename Base::Bottom_side_category Bottom_side_category;
|
using Bottom_side_category = typename Base::Bottom_side_category;
|
||||||
typedef typename Base::Top_side_category Top_side_category;
|
using Top_side_category = typename Base::Top_side_category;
|
||||||
typedef typename Base::Right_side_category Right_side_category;
|
using Right_side_category = typename Base::Right_side_category;
|
||||||
|
|
||||||
class Is_vertical_3
|
//!
|
||||||
{
|
class Is_vertical_3 {
|
||||||
public:
|
public:
|
||||||
bool operator()(const Plane_3& h) const
|
bool operator()(const Plane_3& h) const { return CGAL::is_zero(h.c()); }
|
||||||
{
|
|
||||||
return CGAL::is_zero(h.c());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Is_vertical_3 is_vertical_3_object() const
|
//! Obtain an Is_vertical_3 functor object.
|
||||||
{
|
Is_vertical_3 is_vertical_3_object() const { return Is_vertical_3(); }
|
||||||
return Is_vertical_3();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _Env_plane
|
//
|
||||||
{
|
class _Env_plane {
|
||||||
protected:
|
protected:
|
||||||
Plane_3 m_plane;
|
Plane_3 m_plane;
|
||||||
Line_2 m_line;
|
Line_2 m_line;
|
||||||
bool m_is_all_plane; // true -> all plane, false -> halfplane
|
bool m_is_all_plane; // true -> all plane, false -> halfplane
|
||||||
bool m_is_vert;
|
bool m_is_vert;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
_Env_plane()
|
_Env_plane() {}
|
||||||
{}
|
|
||||||
|
|
||||||
_Env_plane(const Plane_3& h) : m_plane(h),
|
_Env_plane(const Plane_3& h) : m_plane(h), m_is_all_plane(true) {
|
||||||
m_is_all_plane(true)
|
|
||||||
{
|
|
||||||
Self s;
|
Self s;
|
||||||
m_is_vert = s.is_vertical_3_object()(h);
|
m_is_vert = s.is_vertical_3_object()(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
_Env_plane(const Plane_3& h, const Line_2& l) : m_plane(h),
|
_Env_plane(const Plane_3& h, const Line_2& l) :
|
||||||
m_line(l),
|
m_plane(h), m_line(l), m_is_all_plane(false), m_is_vert(false) {
|
||||||
m_is_all_plane(false),
|
|
||||||
m_is_vert(false)
|
|
||||||
{
|
|
||||||
CGAL_precondition_code(Self s);
|
CGAL_precondition_code(Self s);
|
||||||
CGAL_precondition(!s.is_vertical_3_object()(h));
|
CGAL_precondition(! s.is_vertical_3_object()(h));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_vertical() const
|
bool is_vertical() const { return m_is_vert; }
|
||||||
{
|
|
||||||
return m_is_vert;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Plane_3& plane() const
|
const Plane_3& plane() const { return m_plane; }
|
||||||
{
|
|
||||||
return m_plane;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
operator Plane_3() const { return m_plane; }
|
||||||
|
|
||||||
operator Plane_3 () const
|
const Line_2& line() const {
|
||||||
{
|
CGAL_assertion(! m_is_all_plane);
|
||||||
return (m_plane);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Line_2& line() const
|
|
||||||
{
|
|
||||||
CGAL_assertion(!m_is_all_plane);
|
|
||||||
return m_line;
|
return m_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_all_plane() const
|
bool is_all_plane() const { return m_is_all_plane; }
|
||||||
{
|
|
||||||
return m_is_all_plane;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef _Env_plane Xy_monotone_surface_3;
|
using Xy_monotone_surface_3 = _Env_plane;
|
||||||
typedef _Env_plane Surface_3;
|
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:
|
public:
|
||||||
|
template <typename OutputIterator>
|
||||||
template <class OutputIterator>
|
OutputIterator operator()(const Surface_3& s, bool /* is_lower */,
|
||||||
OutputIterator operator()(const Surface_3& s,
|
OutputIterator o) const {
|
||||||
bool /* is_lower */,
|
|
||||||
OutputIterator o) const
|
|
||||||
{
|
|
||||||
*o++ = s;
|
*o++ = s;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! Obtain a Make_xy_monotone_3 functor object.
|
||||||
Make_xy_monotone_3 make_xy_monotone_3_object() const
|
Make_xy_monotone_3 make_xy_monotone_3_object() const
|
||||||
{
|
{ return Make_xy_monotone_3(); }
|
||||||
return Make_xy_monotone_3();
|
|
||||||
}
|
/*! 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<Kernel>;
|
||||||
|
|
||||||
|
//! 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<Kernel>;
|
||||||
|
|
||||||
class Compare_z_at_xy_3
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
|
//
|
||||||
Comparison_result operator()(const Point_2& p,
|
Comparison_result operator()(const Point_2& p,
|
||||||
const Xy_monotone_surface_3& h1,
|
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& plane1 = h1.plane();
|
||||||
const Plane_3& plane2 = h2.plane();
|
const Plane_3& plane2 = h2.plane();
|
||||||
Sign sign_of_c1c2 = CGAL::sign(plane1.c() * plane2.c());
|
Sign sign_of_c1c2 = CGAL::sign(plane1.c() * plane2.c());
|
||||||
Sign sign_of_expr =
|
Sign sign_of_expr =
|
||||||
CGAL::sign ((p.x()*plane1.a() + p.y()*plane1.b() +
|
CGAL::sign((p.x()*plane1.a() + p.y()*plane1.b() +
|
||||||
plane1.d())*plane2.c() -
|
plane1.d())*plane2.c() -
|
||||||
(p.x()*plane2.a() + p.y()*plane2.b() +
|
(p.x()*plane2.a() + p.y()*plane2.b() +
|
||||||
plane2.d())*plane1.c());
|
plane2.d())*plane1.c());
|
||||||
int i = -1 * static_cast<int>(sign_of_c1c2) *
|
int i = -1 * static_cast<int>(sign_of_c1c2) *
|
||||||
static_cast<int>(sign_of_expr);
|
static_cast<int>(sign_of_expr);
|
||||||
return static_cast<Comparison_result>(i);
|
return static_cast<Comparison_result>(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
Comparison_result operator()(const X_monotone_curve_2& cv,
|
Comparison_result operator()(const X_monotone_curve_2& cv,
|
||||||
const Xy_monotone_surface_3& h1,
|
const Xy_monotone_surface_3& h1,
|
||||||
const Xy_monotone_surface_3& h2) const
|
const Xy_monotone_surface_3& h2) const {
|
||||||
{
|
const Kernel& kernel = m_traits;
|
||||||
Kernel k;
|
Point_2 p = (cv.is_segment()) ?
|
||||||
Point_2 p;
|
kernel.construct_midpoint_2_object()(cv.left(), cv.right()) :
|
||||||
if(cv.is_segment())
|
((cv.is_ray()) ?
|
||||||
p = k.construct_midpoint_2_object()(cv.left(), cv.right());
|
kernel.construct_point_on_2_object()(cv.ray(), 1) :
|
||||||
else
|
kernel.construct_point_on_2_object()(cv.line(), 1));
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return this->operator()(p, h1, h2);
|
return this->operator()(p, h1, h2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
Comparison_result operator()(const Xy_monotone_surface_3& h1,
|
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());
|
CGAL_assertion(h1.is_all_plane() && h2.is_all_plane());
|
||||||
|
|
||||||
const Plane_3& p1 = h1.plane();
|
const Plane_3& p1 = h1.plane();
|
||||||
|
|
@ -201,35 +182,63 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! Obtain a Compare_z_at_xy_3 functor object.
|
||||||
Compare_z_at_xy_3 compare_z_at_xy_3_object() const
|
Compare_z_at_xy_3 compare_z_at_xy_3_object() const
|
||||||
{
|
{ return Compare_z_at_xy_3(*this); }
|
||||||
return Compare_z_at_xy_3();
|
|
||||||
}
|
/*! 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<Kernel>;
|
||||||
|
|
||||||
|
//! 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<Kernel>;
|
||||||
|
|
||||||
class Compare_z_at_xy_above_3
|
|
||||||
{
|
|
||||||
public:
|
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,
|
Comparison_result operator()(const X_monotone_curve_2& cv,
|
||||||
const Xy_monotone_surface_3& h1,
|
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& plane1 = h1.plane();
|
||||||
const Plane_3& plane2 = h2.plane();
|
const Plane_3& plane2 = h2.plane();
|
||||||
|
|
||||||
const FT& a1 = plane1.a(),
|
const FT& a1 = plane1.a();
|
||||||
b1 = plane1.b(),
|
const FT& b1 = plane1.b();
|
||||||
c1 = plane1.c();
|
const FT& c1 = plane1.c();
|
||||||
|
|
||||||
const FT& a2 = plane2.a(),
|
const FT& a2 = plane2.a();
|
||||||
b2 = plane2.b(),
|
const FT& b2 = plane2.b();
|
||||||
c2 = plane2.c();
|
const FT& c2 = plane2.c();
|
||||||
|
|
||||||
// our line is a3*x + b3*y + c3 = 0
|
// our line is a3*x + b3*y + c3 = 0
|
||||||
// it is assumed that the planes intersect over this line
|
// it is assumed that the planes intersect over this line
|
||||||
const Line_2& line = cv.supp_line();
|
const Line_2& line = cv.supp_line();
|
||||||
const FT& a3 = line.a(),
|
const FT& a3 = line.a();
|
||||||
b3 = line.b(),
|
const FT& b3 = line.b();
|
||||||
c3 = line.c();
|
const FT& c3 = line.c();
|
||||||
|
|
||||||
// if the line was parallel to the y-axis (i.e x = const),
|
// if the line was parallel to the y-axis (i.e x = const),
|
||||||
// then it was enough to compare dz/dx of both planes
|
// then it was enough to compare dz/dx of both planes
|
||||||
|
|
@ -266,62 +275,97 @@ public:
|
||||||
// are transformed to (v1,w1) and (v2,w2), so we need that w2 > w1
|
// are transformed to (v1,w1) and (v2,w2), so we need that w2 > w1
|
||||||
// (otherwise the result should be multiplied by -1)
|
// (otherwise the result should be multiplied by -1)
|
||||||
|
|
||||||
Kernel k;
|
const Kernel& kernel = m_traits;
|
||||||
Point_2 p1 (k.construct_point_on_2_object()(line, 0));
|
Point_2 p1 = kernel.construct_point_on_2_object()(line, 0);
|
||||||
Point_2 p2 (k.construct_point_on_2_object()(line, 1));
|
Point_2 p2 = kernel.construct_point_on_2_object()(line, 1);
|
||||||
|
|
||||||
if(k.compare_xy_2_object()(p1, p2) == LARGER)
|
if (kernel.compare_xy_2_object()(p1, p2) == LARGER) std::swap(p1, p2);
|
||||||
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(),
|
const FT& x1 = p1.x();
|
||||||
y1 = p1.y(),
|
const FT& y1 = p1.y();
|
||||||
x2 = p2.x(),
|
const FT& x2 = p2.x();
|
||||||
y2 = p2.y();
|
const FT& y2 = p2.y();
|
||||||
|
|
||||||
Sign s2 = CGAL_NTS sign(-b3*x1+a3*y1-(-b3*x2+a3*y2));
|
Sign s2 = CGAL_NTS sign(-b3*x1+a3*y1-(-b3*x2+a3*y2));
|
||||||
return s1 * s2;
|
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
|
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();
|
|
||||||
}
|
/*! 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<Kernel>;
|
||||||
|
|
||||||
|
//! 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<Kernel>;
|
||||||
|
|
||||||
class Compare_z_at_xy_below_3
|
|
||||||
{
|
|
||||||
public:
|
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,
|
Comparison_result operator()(const X_monotone_curve_2& cv,
|
||||||
const Xy_monotone_surface_3& h1,
|
const Xy_monotone_surface_3& h1,
|
||||||
const Xy_monotone_surface_3& h2) const
|
const Xy_monotone_surface_3& h2) const {
|
||||||
{
|
auto cmp_above = m_traits.compare_z_at_xy_above_3_object();
|
||||||
Compare_z_at_xy_above_3 cmp_above;
|
|
||||||
return CGAL::opposite(cmp_above(cv, h1, h2));
|
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
|
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/*! 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<Kernel>;
|
||||||
|
|
||||||
|
//! 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_plane_traits_3<Kernel>;
|
||||||
|
|
||||||
class Construct_projected_boundary_2
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
|
template <typename OutputIterator>
|
||||||
template <class OutputIterator>
|
|
||||||
OutputIterator operator()(const Xy_monotone_surface_3& s,
|
OutputIterator operator()(const Xy_monotone_surface_3& s,
|
||||||
OutputIterator o) const
|
OutputIterator o) const {
|
||||||
{
|
if (s.is_all_plane()) {
|
||||||
if(s.is_all_plane())
|
if (! s.is_vertical()) return o;
|
||||||
{
|
|
||||||
if(!s.is_vertical())
|
|
||||||
return o;
|
|
||||||
|
|
||||||
const Plane_3& h = s.plane();
|
const Plane_3& h = s.plane();
|
||||||
Line_2 proj_line(h.a(), h.b(), h.d());
|
Line_2 proj_line(h.a(), h.b(), h.d());
|
||||||
|
|
@ -331,10 +375,10 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// s is half-plane
|
// s is half-plane
|
||||||
Kernel k;
|
const Kernel& kernel = m_traits;
|
||||||
const Point_2& p1 = k.construct_point_on_2_object()(s.line(), 0);
|
const Point_2& p1 = kernel.construct_point_on_2_object()(s.line(), 0);
|
||||||
const Point_2& p2 = k.construct_point_on_2_object()(s.line(), 1);
|
const Point_2& p2 = kernel.construct_point_on_2_object()(s.line(), 1);
|
||||||
Comparison_result res = k.compare_xy_2_object()(p1, p2);
|
Comparison_result res = kernel.compare_xy_2_object()(p1, p2);
|
||||||
|
|
||||||
Oriented_side side =
|
Oriented_side side =
|
||||||
(res == SMALLER) ? ON_POSITIVE_SIDE : ON_NEGATIVE_SIDE;
|
(res == SMALLER) ? ON_POSITIVE_SIDE : ON_NEGATIVE_SIDE;
|
||||||
|
|
@ -343,118 +387,106 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
Construct_projected_boundary_2
|
Construct_projected_boundary_2
|
||||||
construct_projected_boundary_2_object() const
|
construct_projected_boundary_2_object() const
|
||||||
{
|
{ return Construct_projected_boundary_2(*this); }
|
||||||
return Construct_projected_boundary_2();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/*! 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<Kernel>;
|
||||||
|
|
||||||
|
//! 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_plane_traits_3<Kernel>;
|
||||||
|
|
||||||
class Construct_projected_intersections_2
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
|
template <typename OutputIterator>
|
||||||
template <class OutputIterator>
|
|
||||||
OutputIterator operator()(const Xy_monotone_surface_3& s1,
|
OutputIterator operator()(const Xy_monotone_surface_3& s1,
|
||||||
const Xy_monotone_surface_3& s2,
|
const Xy_monotone_surface_3& s2,
|
||||||
OutputIterator o) const
|
OutputIterator o) const {
|
||||||
{
|
const Kernel& kernel = m_traits;
|
||||||
Kernel k;
|
|
||||||
|
|
||||||
const Plane_3& h1 = s1.plane();
|
const Plane_3& h1 = s1.plane();
|
||||||
const Plane_3& h2 = s2.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 l1(h1.a(), h1.b(), h1.d());
|
||||||
Line_2 l2(h2.a(), h2.b(), h2.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<Point_2>(&(*obj)))
|
if (const auto* p = std::get_if<Point_2>(&(*obj))) *o++ = *p;
|
||||||
*o++ = *p;
|
|
||||||
|
|
||||||
// otherwise, the vertical planes are parallel or overlap, so we return
|
// otherwise, the vertical planes are parallel or overlap, so we return
|
||||||
// nothing.
|
// nothing.
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(s1.is_all_plane() && s2.is_all_plane())
|
if (s1.is_all_plane() && s2.is_all_plane()) {
|
||||||
{
|
auto obj = kernel.intersect_3_object()(h1, h2);
|
||||||
auto obj = k.intersect_3_object()(h1, h2);
|
|
||||||
CGAL_assertion(obj != std::nullopt);
|
CGAL_assertion(obj != std::nullopt);
|
||||||
if(const Line_3* l = std::get_if<Line_3>(&(*obj)))
|
if (const auto* l = std::get_if<Line_3>(&(*obj)))
|
||||||
*o++ = Intersection_curve(project_xy(*l, k), 1);
|
*o++ = Intersection_curve(project_xy(*l, kernel), 1);
|
||||||
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(s1.is_all_plane() && !s2.is_all_plane())
|
if (s1.is_all_plane() && ! s2.is_all_plane()) {
|
||||||
{
|
auto obj = plane_half_plane_proj_intersection(h1, h2, s2.line(), kernel);
|
||||||
auto obj = plane_half_plane_proj_intersection(h1,
|
if (obj == std::nullopt) return o;
|
||||||
h2,
|
if (const auto* line = std::get_if<Line_2>(&(*obj))) {
|
||||||
s2.line(),
|
|
||||||
k);
|
|
||||||
if(obj ==std::nullopt)
|
|
||||||
return o;
|
|
||||||
if(const Line_2* line = std::get_if<Line_2>(&(*obj)))
|
|
||||||
{
|
|
||||||
*o++ = Intersection_curve(*line, 1);
|
*o++ = Intersection_curve(*line, 1);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
if(const Ray_2* ray = std::get_if<Ray_2>(&(*obj)))
|
if (const auto* ray = std::get_if<Ray_2>(&(*obj))) {
|
||||||
{
|
|
||||||
*o++ = Intersection_curve(*ray, 1);
|
*o++ = Intersection_curve(*ray, 1);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
if(!s2.is_all_plane() && s2.is_all_plane())
|
if (! s2.is_all_plane() && s2.is_all_plane()) {
|
||||||
{
|
auto obj = plane_half_plane_proj_intersection(h2, h1, s1.line(), kernel);
|
||||||
auto obj = plane_half_plane_proj_intersection(h2,
|
if (obj == std::nullopt) return o;
|
||||||
h1,
|
if (const auto* line = std::get_if<Line_2>(&(*obj))) {
|
||||||
s1.line(),
|
|
||||||
k);
|
|
||||||
if(obj == std::nullopt)
|
|
||||||
return o;
|
|
||||||
if(const Line_2* line = std::get_if<Line_2>(&(*obj)))
|
|
||||||
{
|
|
||||||
*o++ = Intersection_curve(*line, 1);
|
*o++ = Intersection_curve(*line, 1);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
if(const Ray_2* ray = std::get_if<Ray_2>(&(*obj)))
|
if (const auto* ray = std::get_if<Ray_2>(&(*obj))) {
|
||||||
{
|
|
||||||
*o++ = Intersection_curve(*ray, 1);
|
*o++ = Intersection_curve(*ray, 1);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
CGAL_assertion(!s2.is_all_plane() && !s2.is_all_plane());
|
CGAL_assertion(! s2.is_all_plane() && ! s2.is_all_plane());
|
||||||
auto obj =
|
auto obj = half_plane_half_plane_proj_intersection(h1, s1.line(),
|
||||||
half_plane_half_plane_proj_intersection(h1, s1.line(), h2, s2.line(), k);
|
h2, s2.line(), kernel);
|
||||||
|
|
||||||
if(obj ==std::nullopt )
|
if (obj == std::nullopt) return o;
|
||||||
return o;
|
|
||||||
|
|
||||||
if(const Line_2* line = std::get_if<Line_2>(&(*obj)))
|
if (const auto* line = std::get_if<Line_2>(&(*obj))) {
|
||||||
{
|
|
||||||
*o++ = Intersection_curve(*line, 1);
|
*o++ = Intersection_curve(*line, 1);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
if(const Ray_2* ray = std::get_if<Ray_2>(&(*obj)))
|
if (const auto* ray = std::get_if<Ray_2>(&(*obj))) {
|
||||||
{
|
|
||||||
*o++ = Intersection_curve(*ray, 1);
|
*o++ = Intersection_curve(*ray, 1);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
if (const auto* seg = std::get_if<Segment_2>(&(*obj))) {
|
||||||
if(const Segment_2* seg = std::get_if<Segment_2>(&(*obj)))
|
|
||||||
{
|
|
||||||
*o++ = Intersection_curve(*seg, 1);
|
*o++ = Intersection_curve(*seg, 1);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
if (const auto* p = std::get_if<Point_2>(&(*obj))) {
|
||||||
if(const Point_2* p = std::get_if<Point_2>(&(*obj)))
|
|
||||||
{
|
|
||||||
*o++ = *p;
|
*o++ = *p;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
@ -462,12 +494,10 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! Obtain a Construct_projected_intersections_2 functor object.
|
||||||
Construct_projected_intersections_2
|
Construct_projected_intersections_2
|
||||||
construct_projected_intersections_2_object() const
|
construct_projected_intersections_2_object() const
|
||||||
{
|
{ return Construct_projected_intersections_2(*this); }
|
||||||
return Construct_projected_intersections_2();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} //namespace CGAL
|
} //namespace CGAL
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,10 @@
|
||||||
// $Id$
|
// $Id$
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||||
//
|
//
|
||||||
// Author(s) : Michal Meyerovitch <gorgymic@post.tau.ac.il>
|
// Author(s) : Michal Meyerovitch <gorgymic@post.tau.ac.il>
|
||||||
// Baruch Zukerman <baruchzu@post.tau.ac.il>
|
// Baruch Zukerman <baruchzu@post.tau.ac.il>
|
||||||
// Ron Wein <wein@post.tau.ac.il>
|
// Ron Wein <wein@post.tau.ac.il>
|
||||||
// Efi Fogel <fogel@post.tau.ac.il>
|
// Efi Fogel <efifogel@gmail.com>
|
||||||
|
|
||||||
#ifndef CGAL_ENV_SPHERE_TRAITS_3_H
|
#ifndef CGAL_ENV_SPHERE_TRAITS_3_H
|
||||||
#define CGAL_ENV_SPHERE_TRAITS_3_H
|
#define CGAL_ENV_SPHERE_TRAITS_3_H
|
||||||
|
|
@ -32,96 +32,115 @@ namespace CGAL {
|
||||||
template <typename ConicTraits_2>
|
template <typename ConicTraits_2>
|
||||||
class Env_sphere_traits_3 : public ConicTraits_2 {
|
class Env_sphere_traits_3 : public ConicTraits_2 {
|
||||||
public:
|
public:
|
||||||
typedef ConicTraits_2 Traits_2;
|
using Traits_2 = ConicTraits_2;
|
||||||
typedef Env_sphere_traits_3<Traits_2> Self;
|
|
||||||
|
|
||||||
typedef typename Traits_2::Point_2 Point_2;
|
using Point_2 = typename Traits_2::Point_2;
|
||||||
typedef typename Traits_2::Curve_2 Curve_2;
|
using Curve_2 = typename Traits_2::Curve_2;
|
||||||
typedef typename Traits_2::X_monotone_curve_2 X_monotone_curve_2;
|
using X_monotone_curve_2 = typename Traits_2::X_monotone_curve_2;
|
||||||
typedef typename Traits_2::Multiplicity Multiplicity;
|
using Multiplicity = typename Traits_2::Multiplicity;
|
||||||
|
|
||||||
typedef typename Traits_2::Rat_kernel Rat_kernel;
|
using Rat_kernel = typename Traits_2::Rat_kernel;
|
||||||
typedef typename Traits_2::Alg_kernel Alg_kernel;
|
using Alg_kernel = typename Traits_2::Alg_kernel;
|
||||||
typedef typename Traits_2::Nt_traits Nt_traits;
|
using Nt_traits = typename Traits_2::Nt_traits;
|
||||||
|
|
||||||
typedef typename Rat_kernel::FT Rational;
|
using Rational = typename Rat_kernel::FT;
|
||||||
typedef typename Rat_kernel::Point_2 Rat_point_2;
|
using Rat_point_2 = typename Rat_kernel::Point_2;
|
||||||
typedef typename Rat_kernel::Segment_2 Rat_segment_2;
|
using Rat_segment_2 = typename Rat_kernel::Segment_2;
|
||||||
typedef typename Rat_kernel::Line_2 Rat_line_2;
|
using Rat_line_2 = typename Rat_kernel::Line_2;
|
||||||
typedef typename Rat_kernel::Circle_2 Rat_circle_2;
|
using Rat_circle_2 = typename Rat_kernel::Circle_2;
|
||||||
typedef typename Rat_kernel::Point_3 Rat_point_3;
|
using Rat_point_3 = typename Rat_kernel::Point_3;
|
||||||
|
|
||||||
typedef typename Alg_kernel::FT Algebraic;
|
using Algebraic = typename Alg_kernel::FT;
|
||||||
typedef typename Alg_kernel::Point_2 Alg_point_2;
|
using Alg_point_2 = typename Alg_kernel::Point_2;
|
||||||
typedef typename Alg_kernel::Circle_2 Alg_circle_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
|
// 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:
|
protected:
|
||||||
typedef std::pair<X_monotone_curve_2, Multiplicity> Intersection_curve;
|
using Intersection_curve = std::pair<X_monotone_curve_2, Multiplicity>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/*! Subdivide a given surface into \f$xy\f$-monotone parts.
|
||||||
|
*/
|
||||||
class Make_xy_monotone_3 {
|
class Make_xy_monotone_3 {
|
||||||
protected:
|
protected:
|
||||||
const Self& parent;
|
using Traits_3 = Env_sphere_traits_3<Traits_2>;
|
||||||
|
|
||||||
|
//! 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<Traits_2>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Make_xy_monotone_3(const Self * p) : parent(*p) {}
|
|
||||||
|
|
||||||
// create xy-monotone surfaces from a general surface
|
// create xy-monotone surfaces from a general surface
|
||||||
// return a past-the-end iterator
|
// return a past-the-end iterator
|
||||||
template <class OutputIterator>
|
template <typename OutputIterator>
|
||||||
OutputIterator operator()(const Surface_3& s,
|
OutputIterator operator()(const Surface_3& s, bool is_lower,
|
||||||
bool is_lower,
|
OutputIterator o) const {
|
||||||
OutputIterator o) const
|
|
||||||
{
|
|
||||||
// our half sphere is of same type as our full sphere since we always
|
// our half sphere is of same type as our full sphere since we always
|
||||||
// need only the lower/upper part of each sphere
|
// need only the lower/upper part of each sphere
|
||||||
parent.m_is_lower = is_lower;
|
m_traits.m_is_lower = is_lower;
|
||||||
*o++ = s;
|
*o++ = s;
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! Get a Make_xy_monotone_3 functor object. */
|
/*! Obtain a Make_xy_monotone_3 functor object. */
|
||||||
Make_xy_monotone_3
|
Make_xy_monotone_3 make_xy_monotone_3_object() const
|
||||||
make_xy_monotone_3_object() const { return Make_xy_monotone_3(this); }
|
{ 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 {
|
class Construct_projected_boundary_2 {
|
||||||
protected:
|
protected:
|
||||||
const Self& parent;
|
using Traits_3 = Env_sphere_traits_3<Traits_2>;
|
||||||
|
|
||||||
|
//! 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<Traits_2>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Construct_projected_boundary_2(const Self* p) : parent(*p) {}
|
|
||||||
|
|
||||||
// insert into the OutputIterator all the (2d) curves of the boundary of
|
// insert into the OutputIterator all the (2d) curves of the boundary of
|
||||||
// the vertical projection of the surface on the xy-plane
|
// the vertical projection of the surface on the xy-plane
|
||||||
// the OutputIterator value type is X_monotone_curve_2
|
// the OutputIterator value type is X_monotone_curve_2
|
||||||
template <class OutputIterator>
|
template <typename OutputIterator>
|
||||||
OutputIterator
|
OutputIterator
|
||||||
operator()(const Xy_monotone_surface_3& s, OutputIterator o) const {
|
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,
|
// the projected boundary in a circle, with a projected center,
|
||||||
// and same radius
|
// 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());
|
Rat_circle_2 circ(proj_center, s.squared_radius());
|
||||||
Curve_2 curve = gt_2->construct_curve_2_object()(circ);
|
Curve_2 curve = gt2.construct_curve_2_object()(circ);
|
||||||
typedef std::variant<X_monotone_curve_2, Point_2> Variant;
|
using Variant = std::variant<X_monotone_curve_2, Point_2>;
|
||||||
Variant objs[2];
|
Variant objs[2];
|
||||||
|
|
||||||
CGAL_assertion_code(Variant* p = )
|
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);
|
CGAL_assertion(p == objs + 2);
|
||||||
|
|
||||||
const X_monotone_curve_2* cv1 = std::get_if<X_monotone_curve_2>(&(objs[0]));
|
const auto* cv1 = std::get_if<X_monotone_curve_2>(&(objs[0]));
|
||||||
const X_monotone_curve_2* cv2 = std::get_if<X_monotone_curve_2>(&(objs[1]));
|
const auto* cv2 = std::get_if<X_monotone_curve_2>(&(objs[1]));
|
||||||
|
|
||||||
CGAL_assertion(cv1!=nullptr);
|
CGAL_assertion(cv1 != nullptr);
|
||||||
CGAL_assertion(cv2!=nullptr);
|
CGAL_assertion(cv2 != nullptr);
|
||||||
|
|
||||||
if (cv1->is_lower()) {
|
if (cv1->is_lower()) {
|
||||||
CGAL_assertion(cv2->is_upper());
|
CGAL_assertion(cv2->is_upper());
|
||||||
|
|
@ -138,39 +157,52 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! Get a Construct_projected_boundary_2 functor object. */
|
/*! Obtain a Construct_projected_boundary_2 functor object. */
|
||||||
Construct_projected_boundary_2
|
Construct_projected_boundary_2
|
||||||
construct_projected_boundary_2_object() const
|
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 {
|
class Construct_projected_intersections_2 {
|
||||||
protected:
|
protected:
|
||||||
const Self& parent;
|
using Traits_3 = Env_sphere_traits_3<Traits_2>;
|
||||||
|
|
||||||
|
//! 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<Traits_2>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Construct_projected_intersections_2(const Self * p) : parent(*p) {}
|
|
||||||
|
|
||||||
// insert into OutputIterator all the (2d) projections on the xy plane of
|
// insert into OutputIterator all the (2d) projections on the xy plane of
|
||||||
// the intersection objects between the 2 surfaces
|
// the intersection objects between the 2 surfaces
|
||||||
// the data type of OutputIterator is Object
|
// the data type of OutputIterator is Object
|
||||||
template <typename OutputIterator>
|
template <typename OutputIterator>
|
||||||
OutputIterator
|
OutputIterator operator()(const Xy_monotone_surface_3& s1,
|
||||||
operator()(const Xy_monotone_surface_3& s1, const Xy_monotone_surface_3& s2,
|
const Xy_monotone_surface_3& s2,
|
||||||
OutputIterator o) const {
|
OutputIterator o) const {
|
||||||
const auto gt_2 = parent.geometry_traits_2();
|
const Traits_2& gt2 = m_traits;
|
||||||
auto ctr_cv = gt_2->construct_curve_2_object();
|
auto ctr_cv = gt2.construct_curve_2_object();
|
||||||
auto nt_traits = gt_2->nt_traits();
|
auto nt_traits = gt2.nt_traits();
|
||||||
|
|
||||||
Rat_point_3 p1 = s1.center();
|
const Rat_point_3& p1 = s1.center();
|
||||||
Rat_point_3 p2 = s2.center();
|
const Rat_point_3& p2 = s2.center();
|
||||||
const Rational a1 = p1.x();
|
const Rational& a1 = p1.x();
|
||||||
const Rational b1 = p1.y();
|
const Rational& b1 = p1.y();
|
||||||
const Rational c1 = p1.z();
|
const Rational& c1 = p1.z();
|
||||||
const Rational a2 = p2.x();
|
const Rational& a2 = p2.x();
|
||||||
const Rational b2 = p2.y();
|
const Rational& b2 = p2.y();
|
||||||
const Rational c2 = p2.z();
|
const Rational& c2 = p2.z();
|
||||||
const Rational sqr_r1 = s1.squared_radius();
|
const Rational& sqr_r1 = s1.squared_radius();
|
||||||
const Rational sqr_r2 = s2.squared_radius();
|
const Rational& sqr_r2 = s2.squared_radius();
|
||||||
|
|
||||||
// // the spheres intersect iff d(p1, p2) <= (r1+r2)
|
// // the spheres intersect iff d(p1, p2) <= (r1+r2)
|
||||||
// // squaring this twice, we get the condition
|
// // squaring this twice, we get the condition
|
||||||
|
|
@ -225,7 +257,7 @@ public:
|
||||||
Rational B = -8*b1*sqr_a_diff;
|
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;
|
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);
|
Algebraic* ys_end = nt_traits->solve_quadratic_equation(A, B, C, ys);
|
||||||
std::ptrdiff_t n_ys = ys_end - ys;
|
std::ptrdiff_t n_ys = ys_end - ys;
|
||||||
|
|
@ -254,7 +286,7 @@ public:
|
||||||
// 2(a1-a2)x - m = 0
|
// 2(a1-a2)x - m = 0
|
||||||
Curve_2 res = ctr_cv(0, 0, 0, 2*a_diff, 0, -m, COLLINEAR, end1, end2);
|
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);
|
//*o++ = Intersection_curve(res, TRANSVERSAL);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -328,7 +360,7 @@ public:
|
||||||
// 2(a1-a2)x + 2(b1-b2)y - m = 0
|
// 2(a1-a2)x + 2(b1-b2)y - m = 0
|
||||||
Curve_2 res =
|
Curve_2 res =
|
||||||
ctr_cv(0,0,0, 2*a_diff, 2*b_diff, -m, COLLINEAR, end1, end2);
|
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);
|
//*o++ = Intersection_curve(res, TRANSVERSAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -401,14 +433,14 @@ public:
|
||||||
// if the full spheres do not intersect, the equation we get has no
|
// if the full spheres do not intersect, the equation we get has no
|
||||||
// real solution, so we should check it:
|
// real solution, so we should check it:
|
||||||
bool ellipse_is_point = false;
|
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;
|
return o;
|
||||||
|
|
||||||
// we need only a part of the ellipse (as stated in (**)) so we
|
// we need only a part of the ellipse (as stated in (**)) so we
|
||||||
// construct the cutting line, which is:
|
// construct the cutting line, which is:
|
||||||
// equation (*) <= min(c1,c2) -- for lower envelope
|
// equation (*) <= min(c1,c2) -- for lower envelope
|
||||||
// equation (*) >= max(c1,c2) -- for upper 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);
|
((c1 < c2) ? c1 : c2) : ((c1 > c2) ? c1 : c2);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -423,7 +455,7 @@ public:
|
||||||
|
|
||||||
// for upper envelope, we should multiply the line equation by -1
|
// for upper envelope, we should multiply the line equation by -1
|
||||||
int envelope_coef = 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);
|
Sign sign_c_diff = CGAL_NTS sign(c_diff);
|
||||||
Rational la = envelope_coef*2*a_diff*sign_c_diff;
|
Rational la = envelope_coef*2*a_diff*sign_c_diff;
|
||||||
|
|
@ -454,13 +486,12 @@ public:
|
||||||
// intersection - in which case lc >= 0
|
// intersection - in which case lc >= 0
|
||||||
// or there is no intersection at all between the 2 half spheres -
|
// or there is no intersection at all between the 2 half spheres -
|
||||||
// in which case lc < 0
|
// in which case lc < 0
|
||||||
if (CGAL_NTS compare(a_diff, zero) == EQUAL &&
|
if ((CGAL_NTS compare(a_diff, zero) == EQUAL) &&
|
||||||
CGAL_NTS compare(b_diff, zero) == EQUAL)
|
(CGAL_NTS compare(b_diff, zero) == EQUAL)) {
|
||||||
{
|
|
||||||
Sign sign_lc = CGAL_NTS sign(lc);
|
Sign sign_lc = CGAL_NTS sign(lc);
|
||||||
if (sign_lc != NEGATIVE) {
|
if (sign_lc != NEGATIVE) {
|
||||||
Curve_2 res = ctr_cv(R, S, T, U, V, W);
|
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);
|
//*o++ = Intersection_curve(res, TRANSVERSAL);
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
|
|
@ -510,7 +541,7 @@ public:
|
||||||
Curve_2 inter_cv = ctr_cv(R, S, T, U, V, W);
|
Curve_2 inter_cv = ctr_cv(R, S, T, U, V, W);
|
||||||
|
|
||||||
CGAL_precondition_code(x_mid_n_y_points = )
|
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);
|
CGAL_precondition(x_mid_n_y_points > 0);
|
||||||
|
|
||||||
|
|
@ -566,7 +597,7 @@ public:
|
||||||
Curve_2 inter_cv = ctr_cv(R, S, T, U, V, W);
|
Curve_2 inter_cv = ctr_cv(R, S, T, U, V, W);
|
||||||
|
|
||||||
CGAL_precondition_code(int y_mid_n_x_points =)
|
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);
|
CGAL_precondition(y_mid_n_x_points > 0);
|
||||||
|
|
||||||
Algebraic x1 = y_mid_x_points[0].x(), x2 = y_mid_x_points[1].x();
|
Algebraic x1 = y_mid_x_points[0].x(), x2 = y_mid_x_points[1].x();
|
||||||
|
|
@ -600,7 +631,7 @@ public:
|
||||||
Alg_point_2 vtan_ps[2];
|
Alg_point_2 vtan_ps[2];
|
||||||
|
|
||||||
CGAL_assertion_code(std::size_t n_vtan_ps =)
|
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);
|
CGAL_assertion(n_vtan_ps == 2);
|
||||||
|
|
||||||
|
|
@ -609,7 +640,7 @@ public:
|
||||||
Sign lval_sign = CGAL_NTS sign(lval);
|
Sign lval_sign = CGAL_NTS sign(lval);
|
||||||
if (lval_sign == POSITIVE) {
|
if (lval_sign == POSITIVE) {
|
||||||
// the full ellipse is in the positive side
|
// 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);
|
//*o++ = Intersection_curve(inter_cv, TRANSVERSAL);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
@ -630,7 +661,7 @@ public:
|
||||||
lval_sign = CGAL_NTS sign(lval);
|
lval_sign = CGAL_NTS sign(lval);
|
||||||
CGAL_assertion(lval_sign != ZERO);
|
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);
|
//*o++ = Intersection_curve(inter_cv, TRANSVERSAL);
|
||||||
else *o++ = Point_2(source);
|
else *o++ = Point_2(source);
|
||||||
|
|
||||||
|
|
@ -644,14 +675,14 @@ public:
|
||||||
// If the mid-point forms a left-turn with the source and the target
|
// If the mid-point forms a left-turn with the source and the target
|
||||||
// points, the orientation is positive (going counterclockwise).
|
// points, the orientation is positive (going counterclockwise).
|
||||||
// Otherwise, it is negative (going clockwise).
|
// 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();
|
auto orient_f = alg_kernel->orientation_2_object();
|
||||||
Orientation orient = (orient_f(source, pmid, target) == LEFT_TURN) ?
|
Orientation orient = (orient_f(source, pmid, target) == LEFT_TURN) ?
|
||||||
CGAL::COUNTERCLOCKWISE : CGAL::CLOCKWISE;
|
CGAL::COUNTERCLOCKWISE : CGAL::CLOCKWISE;
|
||||||
|
|
||||||
Curve_2 res = ctr_cv(R, S, T, U, V, W, orient, source, target);
|
Curve_2 res = ctr_cv(R, S, T, U, V, W, orient, source, target);
|
||||||
CGAL_assertion(res.is_valid());
|
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);
|
//*o++ = Intersection_curve(res, TRANSVERSAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -659,18 +690,30 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! Get a Construct_projected_intersections_2 functor object. */
|
/*! Obtain a Construct_projected_intersections_2 functor object. */
|
||||||
Construct_projected_intersections_2
|
Construct_projected_intersections_2
|
||||||
construct_projected_intersections_2_object() const
|
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 {
|
class Compare_z_at_xy_3 {
|
||||||
protected:
|
protected:
|
||||||
const Self& parent;
|
using Traits_3 = Env_sphere_traits_3<Traits_2>;
|
||||||
|
|
||||||
|
//! 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<Traits_2>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Compare_z_at_xy_3(const Self* p) : parent(*p) {}
|
|
||||||
|
|
||||||
// check which of the surfaces is closer to the envelope at the xy
|
// 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
|
// coordinates of point (i.e. lower if computing the lower envelope, or
|
||||||
// upper if computing the upper envelope)
|
// upper if computing the upper envelope)
|
||||||
|
|
@ -697,9 +740,8 @@ public:
|
||||||
const Xy_monotone_surface_3& s1,
|
const Xy_monotone_surface_3& s1,
|
||||||
const Xy_monotone_surface_3& s2) const {
|
const Xy_monotone_surface_3& s2) const {
|
||||||
// we compute a middle point on cv and use the previous function
|
// we compute a middle point on cv and use the previous function
|
||||||
Point_2 mid = parent.construct_middle_point(cv);
|
Point_2 mid = m_traits.construct_middle_point(cv);
|
||||||
Comparison_result res = parent.compare_z_at_xy_3_object()(mid, s1, s2);
|
return m_traits.compare_z_at_xy_3_object()(mid, s1, s2);
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -710,12 +752,12 @@ public:
|
||||||
const Xy_monotone_surface_3& s1,
|
const Xy_monotone_surface_3& s1,
|
||||||
const Xy_monotone_surface_3& s2) const {
|
const Xy_monotone_surface_3& s2) const {
|
||||||
// find the z coordinates of surface 1 over p
|
// 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
|
// 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);
|
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;
|
else return -res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -735,19 +777,19 @@ public:
|
||||||
Comparison_result
|
Comparison_result
|
||||||
compare_in_point_second_method(const Point_2& p,
|
compare_in_point_second_method(const Point_2& p,
|
||||||
const Xy_monotone_surface_3& s1,
|
const Xy_monotone_surface_3& s1,
|
||||||
const Xy_monotone_surface_3& s2) const
|
const Xy_monotone_surface_3& s2) const {
|
||||||
{
|
const Rat_point_3& p1 = s1.center();
|
||||||
Rat_point_3 p1 = s1.center();
|
const Rat_point_3& p2 = s2.center();
|
||||||
Rat_point_3 p2 = s2.center();
|
const Rational& a1 = p1.x();
|
||||||
const Rational a1 = p1.x();
|
const Rational& b1 = p1.y();
|
||||||
const Rational b1 = p1.y();
|
const Rational& c1 = p1.z();
|
||||||
const Rational c1 = p1.z();
|
const Rational& a2 = p2.x();
|
||||||
const Rational a2 = p2.x();
|
const Rational& b2 = p2.y();
|
||||||
const Rational b2 = p2.y();
|
const Rational& c2 = p2.z();
|
||||||
const Rational c2 = p2.z();
|
const Rational& sqr_r1 = s1.squared_radius();
|
||||||
const Rational sqr_r1 = s1.squared_radius();
|
const Rational& sqr_r2 = s2.squared_radius();
|
||||||
const Rational sqr_r2 = s2.squared_radius();
|
const Algebraic& x1 = p.x();
|
||||||
const Algebraic x1 = p.x(), y1 = p.y();
|
const Algebraic& y1 = p.y();
|
||||||
|
|
||||||
Rational c_diff = c1 - c2;
|
Rational c_diff = c1 - c2;
|
||||||
Algebraic x_diff1 = x1 - a1, y_diff1 = y1 - b1;
|
Algebraic x_diff1 = x1 - a1, y_diff1 = y1 - b1;
|
||||||
|
|
@ -773,17 +815,32 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! 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
|
||||||
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 {
|
class Compare_z_at_xy_above_3 {
|
||||||
protected:
|
protected:
|
||||||
const Self& parent;
|
using Traits_3 = Env_sphere_traits_3<Traits_2>;
|
||||||
|
|
||||||
|
//! 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<Traits_2>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Compare_z_at_xy_above_3(const Self* p) : parent(*p) {}
|
|
||||||
|
|
||||||
// check which of the surfaces is closer to the envelope on the points above
|
// 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
|
// the curve cv (i.e. lower if computing the lower envelope, or upper if
|
||||||
// computing the upper envelope)
|
// computing the upper envelope)
|
||||||
|
|
@ -795,35 +852,46 @@ public:
|
||||||
operator()(const X_monotone_curve_2& cv,
|
operator()(const X_monotone_curve_2& cv,
|
||||||
const Xy_monotone_surface_3& s1,
|
const Xy_monotone_surface_3& s1,
|
||||||
const Xy_monotone_surface_3& s2) const
|
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
|
||||||
compare_z_at_xy_above_3_object() const
|
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 {
|
class Compare_z_at_xy_below_3 {
|
||||||
protected:
|
protected:
|
||||||
const Self& parent;
|
using Traits_3 = Env_sphere_traits_3<Traits_2>;
|
||||||
|
|
||||||
|
//! 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_sphere_traits_3<Traits_2>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Compare_z_at_xy_below_3(const Self* p) : parent(*p) {}
|
Comparison_result operator()(const X_monotone_curve_2& cv,
|
||||||
|
const Xy_monotone_surface_3& s1,
|
||||||
Comparison_result
|
const Xy_monotone_surface_3& s2) const
|
||||||
operator()(const X_monotone_curve_2& cv,
|
{ return m_traits.compare_on_side(cv, s1, s2, true); }
|
||||||
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;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! 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
|
||||||
compare_z_at_xy_below_3_object() const
|
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 @@ public:
|
||||||
// checks if point is in the xy-range of surf
|
// checks if point is in the xy-range of surf
|
||||||
class Is_defined_over {
|
class Is_defined_over {
|
||||||
protected:
|
protected:
|
||||||
const Self& parent;
|
using Traits_3 = Env_sphere_traits_3<Traits_2>;
|
||||||
|
|
||||||
|
//! 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<Traits_2>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Is_defined_over(const Self* p) : parent(*p) {}
|
|
||||||
|
|
||||||
// checks if point is in the xy-range of surf
|
// checks if point is in the xy-range of surf
|
||||||
bool operator()(const Point_2& p, const Xy_monotone_surface_3& s) const {
|
bool operator()(const Point_2& p, const Xy_monotone_surface_3& s) const {
|
||||||
// project the surface on the plane
|
// 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());
|
Rat_circle_2 boundary(proj_center, s.squared_radius());
|
||||||
|
|
||||||
const auto gt_2 = parent.geometry_traits_2();
|
const Traits_2& gt2 = m_traits;
|
||||||
auto nt_traits = gt_2->nt_traits();
|
auto nt_traits = gt2.nt_traits();
|
||||||
Alg_point_2 aproj_center(proj_center.x(), proj_center.y());
|
Alg_point_2 aproj_center(proj_center.x(), proj_center.y());
|
||||||
Alg_circle_2 aboundary(aproj_center, nt_traits->convert(s.squared_radius()));
|
Alg_circle_2 aboundary(aproj_center, nt_traits->convert(s.squared_radius()));
|
||||||
|
|
||||||
// check if the projected point is inside the projected boundary
|
// 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));
|
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
|
Is_defined_over is_defined_over_object() const
|
||||||
{ return Is_defined_over(this); }
|
{ return Is_defined_over(*this); }
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
|
|
@ -867,8 +943,7 @@ public:
|
||||||
Comparison_result compare_on_side(const X_monotone_curve_2& cv,
|
Comparison_result compare_on_side(const X_monotone_curve_2& cv,
|
||||||
const Xy_monotone_surface_3& s1,
|
const Xy_monotone_surface_3& s1,
|
||||||
const Xy_monotone_surface_3& s2,
|
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
|
// 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)
|
// let p be the leftmost endpoint of cv, p=(x0, y0)
|
||||||
// the tangence of cv at p is a line. on the infinitesimal region
|
// the tangence of cv at p is a line. on the infinitesimal region
|
||||||
|
|
@ -881,7 +956,8 @@ public:
|
||||||
// since we assume that such point represents better what is going
|
// since we assume that such point represents better what is going
|
||||||
// on all internal curve points
|
// on all internal curve points
|
||||||
Point_2 cv_point = construct_middle_point(cv);
|
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
|
// 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
|
// in point p=(x0,y0) we get
|
||||||
|
|
@ -895,8 +971,12 @@ public:
|
||||||
// n != 0: y - y0 = y'(x-x0) ==> -y'x + y + (y'x0 - y0) = 0
|
// n != 0: y - y0 = y'(x-x0) ==> -y'x + y + (y'x0 - y0) = 0
|
||||||
// and in general we have:
|
// and in general we have:
|
||||||
// -m*x + n*y + (m*x0 -n*y0) = 0 (with integer coordinates)
|
// -m*x + n*y + (m*x0 -n*y0) = 0 (with integer coordinates)
|
||||||
const Rational r = cv.r(), s = cv.s(), t = cv.t(),
|
const Rational& r = cv.r();
|
||||||
u = cv.u(), v = cv.v(), w = cv.w();
|
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 m = -1 * (2*r*x0 + t*y0 + u);
|
||||||
Algebraic n = 2*s*y0 + t*x0 + v;
|
Algebraic n = 2*s*y0 + t*x0 + v;
|
||||||
// line coefficients: A3, B3, C3
|
// line coefficients: A3, B3, C3
|
||||||
|
|
@ -931,14 +1011,14 @@ public:
|
||||||
// Di = -(x0-ai)x0 - (y0-bi)y0 - (z0-ci)z0
|
// Di = -(x0-ai)x0 - (y0-bi)y0 - (z0-ci)z0
|
||||||
//
|
//
|
||||||
// and we solve the problem as for triangles
|
// and we solve the problem as for triangles
|
||||||
Rat_point_3 p1 = s1.center();
|
const Rat_point_3& p1 = s1.center();
|
||||||
Rat_point_3 p2 = s2.center();
|
const Rat_point_3& p2 = s2.center();
|
||||||
const Rational a1 = p1.x();
|
const Rational& a1 = p1.x();
|
||||||
const Rational b1 = p1.y();
|
const Rational& b1 = p1.y();
|
||||||
const Rational c1 = p1.z();
|
const Rational& c1 = p1.z();
|
||||||
const Rational a2 = p2.x();
|
const Rational& a2 = p2.x();
|
||||||
const Rational b2 = p2.y();
|
const Rational& b2 = p2.y();
|
||||||
const Rational c2 = p2.z();
|
const Rational& c2 = p2.z();
|
||||||
Algebraic A1 = x0 - a1, B1 = y0 - b1, C1 = z0 - c1;
|
Algebraic A1 = x0 - a1, B1 = y0 - b1, C1 = z0 - c1;
|
||||||
Algebraic A2 = x0 - a2, B2 = y0 - b2, C2 = z0 - c2;
|
Algebraic A2 = x0 - a2, B2 = y0 - b2, C2 = z0 - c2;
|
||||||
if (C1 != 0 && C2 != 0) {
|
if (C1 != 0 && C2 != 0) {
|
||||||
|
|
@ -971,6 +1051,7 @@ public:
|
||||||
return EQUAL;
|
return EQUAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
Rat_point_2 project(const Rat_point_3& p) const
|
Rat_point_2 project(const Rat_point_3& p) const
|
||||||
{ return Rat_point_2(p.x(), p.y()); }
|
{ return Rat_point_2(p.x(), p.y()); }
|
||||||
|
|
||||||
|
|
@ -979,15 +1060,15 @@ public:
|
||||||
// precondition: s is defined at p
|
// precondition: s is defined at p
|
||||||
Algebraic compute_envelope_z_in_point(const Point_2& p,
|
Algebraic compute_envelope_z_in_point(const Point_2& p,
|
||||||
const Xy_monotone_surface_3& s) const {
|
const Xy_monotone_surface_3& s) const {
|
||||||
Algebraic res;
|
|
||||||
|
|
||||||
// the point coordinates
|
// the point coordinates
|
||||||
const Algebraic x1 = p.x(), y1 = p.y();
|
const Algebraic x1 = p.x(), y1 = p.y();
|
||||||
|
|
||||||
// the surface equations
|
// the surface equations
|
||||||
Rat_point_3 center = s.center();
|
const Rat_point_3& center = s.center();
|
||||||
const Rational a = center.x(), b = center.y(), c = center.z();
|
const Rational& a = center.x();
|
||||||
const Rational sqr_r = s.squared_radius();
|
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
|
// we substitute x1 and y1 in the equation of s
|
||||||
// (x-a)^2 + (y-b)^2 + (z-c)^2 = r^2
|
// (x-a)^2 + (y-b)^2 + (z-c)^2 = r^2
|
||||||
|
|
@ -999,11 +1080,12 @@ public:
|
||||||
Algebraic B = -2*c;
|
Algebraic B = -2*c;
|
||||||
Algebraic C = x_diff*x_diff + y_diff*y_diff + c*c - sqr_r;
|
Algebraic C = x_diff*x_diff + y_diff*y_diff + c*c - sqr_r;
|
||||||
|
|
||||||
Algebraic zs[2];
|
Algebraic zs[2];
|
||||||
Algebraic* zs_end;
|
Algebraic* zs_end;
|
||||||
std::ptrdiff_t n_zs;
|
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);
|
zs_end = nt_traits->solve_quadratic_equation(A, B, C, zs);
|
||||||
n_zs = zs_end - zs;
|
n_zs = zs_end - zs;
|
||||||
|
|
||||||
|
|
@ -1013,6 +1095,7 @@ public:
|
||||||
if (n_zs == 1) return zs[0];
|
if (n_zs == 1) return zs[0];
|
||||||
CGAL_assertion(n_zs == 2);
|
CGAL_assertion(n_zs == 2);
|
||||||
|
|
||||||
|
Algebraic res;
|
||||||
Comparison_result comp = CGAL_NTS compare(zs[0], zs[1]);
|
Comparison_result comp = CGAL_NTS compare(zs[0], zs[1]);
|
||||||
if (m_is_lower) res = ((comp == SMALLER) ? zs[0] : zs[1]);
|
if (m_is_lower) res = ((comp == SMALLER) ? zs[0] : zs[1]);
|
||||||
else res = ((comp == LARGER) ? zs[0] : zs[1]);
|
else res = ((comp == LARGER) ? zs[0] : zs[1]);
|
||||||
|
|
@ -1021,8 +1104,10 @@ public:
|
||||||
|
|
||||||
// construct the point in the middle of cv
|
// construct the point in the middle of cv
|
||||||
Point_2 construct_middle_point(const X_monotone_curve_2& cv) const {
|
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
|
// 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_point_2 mid_x =
|
||||||
alg_kernel->construct_midpoint_2_object()(cv.source(), cv.target());
|
alg_kernel->construct_midpoint_2_object()(cv.source(), cv.target());
|
||||||
|
|
||||||
|
|
@ -1030,13 +1115,14 @@ public:
|
||||||
// maybe we want it there?
|
// maybe we want it there?
|
||||||
// if (cv.is_segment()) return mid_x;
|
// if (cv.is_segment()) return mid_x;
|
||||||
if (cv.is_vertical()) return Point_2(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
|
// for the test
|
||||||
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 {
|
||||||
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));
|
return Point_2(alg_kernel->construct_midpoint_2_object()(p1, p2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1044,7 +1130,7 @@ public:
|
||||||
// r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0
|
// r*x^2 + s*y^2 + t*xy + u*x + v*y + w = 0
|
||||||
// has real solutions
|
// has real solutions
|
||||||
// is_point is set to true if the equation represents just one point
|
// is_point is set to true if the equation represents just one point
|
||||||
template <class NT>
|
template <typename NT>
|
||||||
bool is_valid_conic_equation(const NT& r, const NT& s, const NT& t,
|
bool is_valid_conic_equation(const NT& r, const NT& s, const NT& t,
|
||||||
const NT& u, const NT& v, const NT& w,
|
const NT& u, const NT& v, const NT& w,
|
||||||
bool& is_point) const {
|
bool& is_point) const {
|
||||||
|
|
@ -1103,30 +1189,31 @@ public:
|
||||||
|
|
||||||
// for the test:
|
// for the test:
|
||||||
Point_2 vertical_ray_shoot_2(const Point_2& pt, const X_monotone_curve_2& cv)
|
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()) {
|
if (cv.is_vertical()) {
|
||||||
auto alg_kernel = m_geometry_traits_2->alg_kernel();
|
auto alg_kernel = gt2.alg_kernel();
|
||||||
if (! alg_kernel->less_y_2_object()(cv.left(), pt))
|
if (! alg_kernel->less_y_2_object()(cv.left(), pt)) return cv.left();
|
||||||
return cv.left();
|
|
||||||
else {
|
CGAL_assertion(alg_kernel->less_y_2_object()(cv.right(), pt));
|
||||||
CGAL_assertion(alg_kernel->less_y_2_object()(cv.right(), pt));
|
return cv.right();
|
||||||
return cv.right();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else return m_geometry_traits_2->point_at_x(cv, pt);
|
|
||||||
|
return gt2.point_at_x(cv, pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
template <typename OutputIterator>
|
template <typename OutputIterator>
|
||||||
OutputIterator add_curve_to_output(const Curve_2& c, OutputIterator oi) const {
|
OutputIterator add_curve_to_output(const Curve_2& c, OutputIterator oi) const {
|
||||||
std::variant<X_monotone_curve_2, Point_2> objs[2];
|
std::variant<X_monotone_curve_2, Point_2> objs[2];
|
||||||
|
|
||||||
std::variant<X_monotone_curve_2, Point_2>* p_obj = this->make_x_monotone_2_object()(c, objs);
|
std::variant<X_monotone_curve_2, Point_2>* p_obj =
|
||||||
for(std::variant<X_monotone_curve_2, Point_2>* o = objs; o != p_obj; ++o) {
|
this->make_x_monotone_2_object()(c, objs);
|
||||||
if(const X_monotone_curve_2* cv = std::get_if<X_monotone_curve_2>(o))
|
for (std::variant<X_monotone_curve_2, Point_2>* o = objs; o != p_obj; ++o) {
|
||||||
|
if (const auto* cv = std::get_if<X_monotone_curve_2>(o))
|
||||||
*oi++ = Intersection_curve(*cv, 1);
|
*oi++ = Intersection_curve(*cv, 1);
|
||||||
else {
|
else {
|
||||||
const Point_2* pt = std::get_if<Point_2>(o);
|
const auto* pt = std::get_if<Point_2>(o);
|
||||||
CGAL_assertion(pt!=nullptr);
|
CGAL_assertion(pt!=nullptr);
|
||||||
*oi++ = *pt;
|
*oi++ = *pt;
|
||||||
}
|
}
|
||||||
|
|
@ -1134,55 +1221,39 @@ public:
|
||||||
return oi;
|
return oi;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef std::shared_ptr<Traits_2> Shared_geometry_traits_2;
|
|
||||||
|
|
||||||
/*! Default constructor. */
|
/*! Default constructor. */
|
||||||
Env_sphere_traits_3() :
|
Env_sphere_traits_3() : m_is_lower(true) {}
|
||||||
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; }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
mutable bool m_is_lower;
|
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
|
||||||
* Compare two spheres: first compare their center points in an
|
* xyz-lexicographic order, then by their squared radii.
|
||||||
* xyz-lexicographic order, then by their radii.
|
*
|
||||||
|
* \todo This should be deprecated and instead the traits should provide this
|
||||||
|
* functionality.
|
||||||
*/
|
*/
|
||||||
template <typename Kernel>
|
template <typename Kernel>
|
||||||
bool operator<(const CGAL::Sphere_3<Kernel>& a, const CGAL::Sphere_3<Kernel>& b)
|
bool operator<(const CGAL::Sphere_3<Kernel>& a, const CGAL::Sphere_3<Kernel>& b)
|
||||||
{
|
{
|
||||||
Kernel k;
|
Kernel k;
|
||||||
Comparison_result res = k.compare_xyz_3_object()(a.center(), b.center());
|
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);
|
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 <typename Kernel>
|
template <typename Kernel>
|
||||||
bool operator== (const typename Kernel::Sphere_3& a,
|
bool operator==(const typename Kernel::Sphere_3& a,
|
||||||
const typename Kernel::Sphere_3& b) {
|
const typename Kernel::Sphere_3& b) {
|
||||||
Kernel k;
|
Kernel k;
|
||||||
if (! k.equal_3_object() (a.center(), b.center())) return (false);
|
if (! k.equal_3_object()(a.center(), b.center())) return (false);
|
||||||
return (CGAL::compare (a.squared_radius(), b.squared_radius()) == EQUAL);
|
return (CGAL::compare(a.squared_radius(), b.squared_radius()) == EQUAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
} //namespace CGAL
|
} //namespace CGAL
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,9 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Author(s) : Ron Wein <wein@post.tau.ac.il>
|
// Author(s) : Ron Wein <wein@post.tau.ac.il>
|
||||||
|
// Efi Fogel <efifogel@gmail.com>
|
||||||
|
|
||||||
#ifndef CGAL_ENV_SURFACE_DATA_TRAITS_3_H
|
#ifndef CGAL_ENV_SURFACE_DATA_TRAITS_3_H
|
||||||
#define 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.
|
* Definition of the env_surface_data_traits_3<> class template.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <CGAL/Arr_geometry_traits/Curve_data_aux.h>
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
#include <CGAL/Arr_geometry_traits/Curve_data_aux.h>
|
||||||
|
|
||||||
namespace CGAL {
|
namespace CGAL {
|
||||||
|
|
||||||
/*! \class
|
/*! \class
|
||||||
|
|
@ -31,95 +34,80 @@ namespace CGAL {
|
||||||
* It can attach data objects to Surface_3 and to Xy_monotone_surface_3 objects
|
* It can attach data objects to Surface_3 and to Xy_monotone_surface_3 objects
|
||||||
* (possibly of two different types).
|
* (possibly of two different types).
|
||||||
*/
|
*/
|
||||||
template <class Traits_, class XyMonotoneSurfaceData_,
|
template <typename Traits_, typename XyMonotoneSurfaceData,
|
||||||
class SurfaceData_ = XyMonotoneSurfaceData_,
|
typename SurfaceData = XyMonotoneSurfaceData,
|
||||||
class Convert_ = _Default_convert_func<SurfaceData_,
|
typename Convert_ = _Default_convert_func<SurfaceData,
|
||||||
XyMonotoneSurfaceData_> >
|
XyMonotoneSurfaceData>>
|
||||||
class Env_surface_data_traits_3 : public Traits_
|
class Env_surface_data_traits_3 : public Traits_ {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
|
using Base_traits_3 = Traits_;
|
||||||
|
using Xy_monotone_surface_data = XyMonotoneSurfaceData;
|
||||||
|
using Surface_data = SurfaceData;
|
||||||
|
using Convert = Convert_;
|
||||||
|
|
||||||
typedef Traits_ Base_traits_3;
|
using Base_surface_3 = typename Base_traits_3::Surface_3;
|
||||||
typedef XyMonotoneSurfaceData_ Xy_monotone_surface_data;
|
using Base_xy_monotone_surface_3 =
|
||||||
typedef SurfaceData_ Surface_data;
|
typename Base_traits_3::Xy_monotone_surface_3;
|
||||||
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;
|
|
||||||
|
|
||||||
// Representation of a surface with an additional data field:
|
// Representation of a surface with an additional data field:
|
||||||
typedef _Curve_data_ex<Base_surface_3, Surface_data> Surface_3;
|
using Surface_3 = _Curve_data_ex<Base_surface_3, Surface_data>;
|
||||||
|
|
||||||
// Representation of an xy-monotone surface with an additional data field:
|
// Representation of an xy-monotone surface with an additional data field:
|
||||||
typedef _Curve_data_ex<Base_xy_monotone_surface_3,
|
using Xy_monotone_surface_3 =
|
||||||
Xy_monotone_surface_data> Xy_monotone_surface_3;
|
_Curve_data_ex<Base_xy_monotone_surface_3, Xy_monotone_surface_data>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// \name Construction.
|
/// \name Construction.
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
/*! Default constructor. */
|
/*! Default constructor. */
|
||||||
Env_surface_data_traits_3 ()
|
Env_surface_data_traits_3() {}
|
||||||
{}
|
|
||||||
|
|
||||||
/*! Constructor from a base-traits class. */
|
/*! Constructor from a base-traits class. */
|
||||||
Env_surface_data_traits_3 (const Base_traits_3 & traits) :
|
Env_surface_data_traits_3(const Base_traits_3& traits) :
|
||||||
Base_traits_3 (traits)
|
Base_traits_3(traits)
|
||||||
{}
|
{}
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
/// \name Overridden functors.
|
/// \name Overridden functors.
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
class Make_xy_monotone_3
|
class Make_xy_monotone_3 {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
const Base_traits_3 * base;
|
const Base_traits_3* base;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/*! Constructor. */
|
/*! 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.
|
* to the given output iterator.
|
||||||
* \param S The surface.
|
* \param S The surface.
|
||||||
* \param oi The output iterator,
|
* \param oi The output iterator,
|
||||||
* whose value-type is Xy_monotone_surface_2.
|
* whose value-type is Xy_monotone_surface_2.
|
||||||
* \return The past-the-end iterator.
|
* \return The past-the-end iterator.
|
||||||
*/
|
*/
|
||||||
template<class OutputIterator>
|
template <typename OutputIterator>
|
||||||
OutputIterator operator() (const Surface_3& S, bool is_lower,
|
OutputIterator operator()(const Surface_3& S, bool is_lower,
|
||||||
OutputIterator oi) const
|
OutputIterator oi) const {
|
||||||
{
|
|
||||||
// Make the original surface xy-monotone.
|
// Make the original surface xy-monotone.
|
||||||
std::list<Base_xy_monotone_surface_3> xy_surfaces;
|
std::list<Base_xy_monotone_surface_3> xy_surfaces;
|
||||||
typename std::list<Base_xy_monotone_surface_3>::iterator xys_it;
|
typename std::list<Base_xy_monotone_surface_3>::iterator xys_it;
|
||||||
|
|
||||||
base->make_xy_monotone_3_object()
|
base->make_xy_monotone_3_object()(S, is_lower,
|
||||||
(S, is_lower, std::back_inserter (xy_surfaces));
|
std::back_inserter(xy_surfaces));
|
||||||
|
|
||||||
// Attach the data to each of the resulting xy-monotone 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)
|
for (xys_it = xy_surfaces.begin(); xys_it != xy_surfaces.end(); ++xys_it)
|
||||||
{
|
*oi++ = Xy_monotone_surface_3(*xys_it, Convert() (S.data()));
|
||||||
*oi = Xy_monotone_surface_3 (*xys_it,
|
|
||||||
Convert() (S.data()));
|
|
||||||
++oi;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (oi);
|
return oi;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! Get a Make_xy_monotone_3 functor object. */
|
/*! Get a Make_xy_monotone_3 functor object. */
|
||||||
Make_xy_monotone_3 make_xy_monotone_3_object() const
|
Make_xy_monotone_3 make_xy_monotone_3_object() const
|
||||||
{
|
{ return Make_xy_monotone_3(this); }
|
||||||
return Make_xy_monotone_3 (this);
|
|
||||||
}
|
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue