Merge branch '5.1.x-branch'

This commit is contained in:
Laurent Rineau 2020-10-23 16:06:55 +02:00
commit d08d6ca552
5 changed files with 413 additions and 3 deletions

View File

@ -91,6 +91,11 @@ public:
/*! Destructor. */
virtual ~Arr_vertex_base() {}
// Access/modification for pointer squatting
void* inc() const { return p_inc; }
void set_inc(void * inc) const
{ const_cast<Arr_vertex_base&>(*this).p_inc = inc; }
/*! Check if the point pointer is nullptr. */
bool has_null_point() const { return (p_pt == nullptr); }

View File

@ -40,6 +40,89 @@
namespace CGAL {
template <typename Arr1, typename Arr2, typename Curve>
class Indexed_sweep_accessor
{
const Arr1& arr1;
const Arr2& arr2;
mutable std::vector<void*> backup_inc;
public:
Indexed_sweep_accessor (const Arr1& arr1, const Arr2& arr2)
: arr1(arr1), arr2(arr2) { }
std::size_t nb_vertices() const
{
return arr1.number_of_vertices() + arr2.number_of_vertices();
}
std::size_t min_end_index (const Curve& c) const
{
if (c.red_halfedge_handle() != typename Curve::HH_red())
return reinterpret_cast<std::size_t>(c.red_halfedge_handle()->target()->inc());
// else
CGAL_assertion (c.blue_halfedge_handle() != typename Curve::HH_blue());
return reinterpret_cast<std::size_t>(c.blue_halfedge_handle()->target()->inc());
}
std::size_t max_end_index (const Curve& c) const
{
if (c.red_halfedge_handle() != typename Curve::HH_red())
return reinterpret_cast<std::size_t>(c.red_halfedge_handle()->source()->inc());
// else
CGAL_assertion (c.blue_halfedge_handle() != typename Curve::HH_blue());
return reinterpret_cast<std::size_t>(c.blue_halfedge_handle()->source()->inc());
}
const Curve& curve (const Curve& c) const
{
return c;
}
// Initializes indices by squatting Vertex::inc();
void before_init() const
{
std::size_t idx = 0;
backup_inc.resize (nb_vertices());
for (typename Arr1::Vertex_const_iterator vit = arr1.vertices_begin();
vit != arr1.vertices_end(); ++vit, ++idx)
{
CGAL_assertion (idx < backup_inc.size());
backup_inc[idx] = vit->inc();
vit->set_inc (reinterpret_cast<void*>(idx));
}
for (typename Arr2::Vertex_const_iterator vit = arr2.vertices_begin();
vit != arr2.vertices_end(); ++vit, ++idx)
{
CGAL_assertion (idx < backup_inc.size());
backup_inc[idx] = vit->inc();
vit->set_inc (reinterpret_cast<void*>(idx));
}
}
// Restores state of arrangements before index squatting
void after_init() const
{
std::size_t idx = 0;
for (typename Arr1::Vertex_const_iterator vit = arr1.vertices_begin();
vit != arr1.vertices_end(); ++vit, ++idx)
{
CGAL_assertion (idx < backup_inc.size());
vit->set_inc (backup_inc[idx]);
}
for (typename Arr2::Vertex_const_iterator vit = arr2.vertices_begin();
vit != arr2.vertices_end(); ++vit, ++idx)
{
CGAL_assertion (idx < backup_inc.size());
vit->set_inc (backup_inc[idx]);
}
}
private:
};
/*! Compute the overlay of two input arrangements.
* \tparam GeometryTraitsA_2 the geometry traits of the first arrangement.
* \tparam GeometryTraitsB_2 the geometry traits of the second arrangement.
@ -183,7 +266,14 @@ overlay(const Arrangement_on_surface_2<GeometryTraitsA_2, TopologyTraitsA>& arr1
if (total_iso_verts == 0) {
// Clear the result arrangement and perform the sweep to construct it.
arr.clear();
surface_sweep.sweep(xcvs_vec.begin(), xcvs_vec.end());
if (std::is_same<typename Agt2::Bottom_side_category,
Arr_contracted_side_tag>::value)
surface_sweep.sweep (xcvs_vec.begin(), xcvs_vec.end());
else
surface_sweep.indexed_sweep (xcvs_vec,
Indexed_sweep_accessor
<Arr_a, Arr_b, Ovl_x_monotone_curve_2>
(arr1, arr2));
xcvs_vec.clear();
return;
}
@ -215,8 +305,16 @@ overlay(const Arrangement_on_surface_2<GeometryTraitsA_2, TopologyTraitsA>& arr1
// Clear the result arrangement and perform the sweep to construct it.
arr.clear();
surface_sweep.sweep(xcvs_vec.begin(), xcvs_vec.end(),
pts_vec.begin(), pts_vec.end());
if (std::is_same<typename Agt2::Bottom_side_category,
Arr_contracted_side_tag>::value)
surface_sweep.sweep(xcvs_vec.begin(), xcvs_vec.end(),
pts_vec.begin(), pts_vec.end());
else
surface_sweep.indexed_sweep (xcvs_vec,
Indexed_sweep_accessor
<Arr_a, Arr_b, Ovl_x_monotone_curve_2>
(arr1, arr2),
pts_vec.begin(), pts_vec.end());
xcvs_vec.clear();
pts_vec.clear();
}

View File

@ -133,6 +133,8 @@ public:
class Ex_x_monotone_curve_2 {
public:
typedef Base_x_monotone_curve_2 Base;
typedef Halfedge_handle_red HH_red;
typedef Halfedge_handle_blue HH_blue;
protected:
Base m_base_xcv; // The base curve.

View File

@ -309,6 +309,77 @@ public:
m_visitor->after_sweep();
}
/*!
runs the indexed sweep-line algorithm on a given range of
x-monotone curves and accessor. The main difference from the
original `sweep()` function is that the accessor allows to get
indices of end-points and avoid checking several times in the
event queue when the same vertex has several incident edges.
\param edges A range of edges
\param accessor An object providing, for a value_type `e` of
range `edges`, the following methods:
- size_t min_end_index(e) -> the index of the min end of curve c
- size_t max_end_index(e) -> the index of the max end of curve c
- X_monotone_curve_2 curve(e) -> the x-monotone curve associated to e
- size_t nb_vertices() -> the total number of points/events
- void before_init() -> called before initialization
- void after_init() -> called after initialization
*/
template <typename EdgeRange, typename Accessor>
void indexed_sweep (const EdgeRange& edges,
const Accessor& accessor)
{
m_visitor->before_sweep();
accessor.before_init();
_init_indexed_sweep(edges, accessor);
accessor.after_init();
_sweep();
_complete_sweep();
m_visitor->after_sweep();
}
/*!
runs the indexed sweep-line algorithm on a given range of
x-monotone curves and accessor. The main difference from the
original `sweep()` function is that the accessor allows to get
indices of end-points and avoid checking several times in the
event queue when the same vertex has several incident edges.
Variant with action event points (if a curve passed through an
action point, it will be split).
\param edges A range of edges
\param accessor An object providing, for a value_type `e` of
range `edges`, the following methods:
- size_t min_end_index(e) -> the index of the min end of curve c
- size_t max_end_index(e) -> the index of the max end of curve c
- X_monotone_curve_2 curve(e) -> the x-monotone curve associated to e
- size_t nb_vertices() -> the total number of points/events
- void before_init() -> called before initialization
- void after_init() -> called after initialization
\param points_begin An iterator for the first point in the range.
\param points_end A past-the-end iterator for this range.
\pre The value-type of PointInputIterator is the
traits-class Point_2.
*/
template <typename EdgeRange, typename Accessor,
typename PointInputIterator>
void indexed_sweep (const EdgeRange& edges,
const Accessor& accessor,
PointInputIterator action_points_begin,
PointInputIterator action_points_end)
{
m_visitor->before_sweep();
accessor.before_init();
_init_indexed_sweep(edges, accessor);
accessor.after_init();
_init_points(action_points_begin, action_points_end, Event::ACTION);
_sweep();
_complete_sweep();
m_visitor->after_sweep();
}
/*! Get an iterator for the first subcurve in the status line. */
Status_line_iterator status_line_begin() { return m_statusLine.begin(); }
@ -376,6 +447,32 @@ protected:
_init_curve(*cit, index);
}
/*! Create a Subcurve object and two Event objects for each curve. */
template <typename EdgeRange, typename Accessor>
void _init_indexed_curves(const EdgeRange& edges,
const Accessor& accessor)
{
std::vector<Event_queue_iterator> events (accessor.nb_vertices());
unsigned int index = 0;
for (const auto& e : edges)
{
std::size_t max_end = accessor.max_end_index(e);
std::size_t min_end = accessor.min_end_index(e);
const X_monotone_curve_2& curve = accessor.curve (e);
// Construct and initialize a subcurve object.
std::allocator_traits<Subcurve_alloc>::construct(m_subCurveAlloc, m_subCurves + index, m_masterSubcurve );
(m_subCurves + index)->set_hint(this->m_statusLine.end());
(m_subCurves + index)->init (curve);
_init_curve_end(curve, ARR_MAX_END, m_subCurves + index, events, max_end);
_init_curve_end(curve, ARR_MIN_END, m_subCurves + index, events, min_end);
++ index;
}
}
/*! Initiliaze the sweep algorithm. */
template <typename CurveInputIterator>
void _init_sweep(CurveInputIterator curves_begin,
@ -387,6 +484,17 @@ protected:
_init_curves(curves_begin, curves_end); // initialize the curves
}
/*! Initiliaze the sweep algorithm. */
template <typename EdgeRange, typename Accessor>
void _init_indexed_sweep(const EdgeRange& edges,
const Accessor& accessor)
{
m_num_of_subCurves =
static_cast<unsigned int>(std::distance(edges.begin(), edges.end()));
_init_structures();
_init_indexed_curves(edges, accessor); // initialize the curves
}
/*! Initialize the data structures for the sweep-line algorithm. */
virtual void _init_structures();
@ -413,6 +521,11 @@ protected:
void _init_curve_end(const X_monotone_curve_2& cv, Arr_curve_end ind,
Subcurve* sc);
// Variant keeping track of indexed events
void _init_curve_end(const X_monotone_curve_2& cv, Arr_curve_end ind,
Subcurve* sc,
std::vector<Event_queue_iterator>& events, std::size_t index);
/*! Handle the subcurves that are to the left of the event point (i.e.,
* subcurves that we are done with).
*/
@ -485,6 +598,14 @@ protected:
Arr_parameter_space ps_y,
Subcurve* sc = nullptr);
// Variant keeping track of indexed events
std::pair<Event*, bool> _push_event(const Point_2& pt, Attribute type,
Arr_parameter_space ps_x,
Arr_parameter_space ps_y,
Subcurve* sc,
std::vector<Event_queue_iterator>& events,
std::size_t index);
/*! Push an event point associated with a curve end into the event queue.
* \param cv The x-monotone curve.
* \param ind The relevant curve end.
@ -503,6 +624,17 @@ protected:
Arr_parameter_space ps_y,
Subcurve* sc = nullptr);
// Variant keeping track of indexed events
std::pair<Event*, bool> _push_event(const X_monotone_curve_2& cv,
Arr_curve_end ind,
Attribute type,
Arr_parameter_space ps_x,
Arr_parameter_space ps_y,
Subcurve* sc,
const Point_2& pt,
std::vector<Event_queue_iterator>& events,
std::size_t index);
void _update_event_at_open_boundary(Event* e,
const X_monotone_curve_2& cv,
Arr_curve_end ind,

View File

@ -301,6 +301,47 @@ _init_curve_end(const X_monotone_curve_2& cv, Arr_curve_end ind, Subcurve* sc)
}
}
template <typename Vis>
void No_intersection_surface_sweep_2<Vis>::
_init_curve_end(const X_monotone_curve_2& cv, Arr_curve_end ind, Subcurve* sc,
std::vector<Event_queue_iterator>& events, std::size_t index)
{
// Get the boundary conditions of the curve end.
const Attribute end_attr =
(ind == ARR_MIN_END) ? Event::LEFT_END : Event::RIGHT_END;
Arr_parameter_space ps_x = m_traits->parameter_space_in_x_2_object()(cv, ind);
Arr_parameter_space ps_y = m_traits->parameter_space_in_y_2_object()(cv, ind);
// Create the corresponding event and push it into the event queue.
std::pair<Event*, bool> pair_res;
if (m_traits->is_closed_2_object()(cv, ind)) {
// The curve end is closed and thus associated with a valid endpoint.
const Point_2& pt = (ind == ARR_MIN_END) ?
m_traits->construct_min_vertex_2_object()(cv) :
m_traits->construct_max_vertex_2_object()(cv);
pair_res = ((ps_x == ARR_INTERIOR) && (ps_y == ARR_INTERIOR)) ?
_push_event(pt, end_attr, ps_x, ps_y, sc, events, index) :
_push_event(cv, ind, end_attr, ps_x, ps_y, sc, pt, events, index);
// Inform the visitor in case we updated an existing event.
Event* e = pair_res.first;
CGAL_assertion(e->is_closed());
m_visitor->update_event(e, pt, cv, ind, pair_res.second);
}
else {
// The curve end is open, insert it into the event queue.
pair_res = _push_event(cv, ind, end_attr, ps_x, ps_y, sc);
// Inform the visitor in case we updated an existing event.
Event* e = pair_res.first;
CGAL_assertion(! e->is_closed());
_update_event_at_open_boundary(e, cv, ind, pair_res.second);
}
}
//-----------------------------------------------------------------------------
// Handle the subcurves to the left of the current event point.
//
@ -673,6 +714,72 @@ No_intersection_surface_sweep_2<Vis>::_push_event(const Point_2& pt,
return (std::make_pair(e, !exist));
}
template <typename Vis>
std::pair<typename No_intersection_surface_sweep_2<Vis>::Event*, bool>
No_intersection_surface_sweep_2<Vis>::_push_event(const Point_2& pt,
Attribute type,
Arr_parameter_space ps_x,
Arr_parameter_space ps_y,
Subcurve* sc,
std::vector<Event_queue_iterator>& events,
std::size_t index)
{
Event* e;
std::pair<Event_queue_iterator, bool>
pair_res = std::make_pair (events[index], true);
// If event does not exist
if (events[index] == Event_queue_iterator())
{
// Still look for the curve end in the event queue in case two
// point are the the same in the vertex range
m_queueEventLess.set_parameter_space_in_x(ps_x);
m_queueEventLess.set_parameter_space_in_y(ps_y);
pair_res = m_queue->find_lower(pt, m_queueEventLess);
}
bool exist = pair_res.second;
if (! exist) {
// The point is not found in the event queue - create a new event and
// insert it into the queue.
e = _allocate_event(pt, type, ps_x, ps_y);
}
else {
events[index] = pair_res.first;
// The event associated with the given point already exists in the queue,
// so we just have to update it.
e = *(pair_res.first);
CGAL_assertion(e->is_closed());
e->set_attribute(type);
}
// If we are given a subcurve that the event represents one of its
// endpoints, update the event and the subcurve records accordingly.
// Note that this must be done before we actually insert the new event
// into the event queue.
_add_curve(e, sc, type);
// Insert the new event into the queue using the hint we got when we
// looked for it.
if (! exist)
events[index] = m_queue->insert_before(pair_res.first, e);
#ifdef CGAL_SS_VERBOSE
if (! exist) {
CGAL_SS_PRINT_NEW_EVENT(pt, e);
}
else {
CGAL_SS_PRINT_UPDATE_EVENT(pt, e);
}
#endif
// Return the resulting event and a flag indicating whether we have created
// a new event.
return (std::make_pair(e, !exist));
}
//-----------------------------------------------------------------------------
// Push an event point associated with a curve end into the event queue.
//
@ -736,6 +843,72 @@ No_intersection_surface_sweep_2<Vis>::_push_event(const X_monotone_curve_2& cv,
return (std::make_pair(e, !exist));
}
template <typename Vis>
std::pair<typename No_intersection_surface_sweep_2<Vis>::Event*, bool>
No_intersection_surface_sweep_2<Vis>::_push_event(const X_monotone_curve_2& cv,
Arr_curve_end ind,
Attribute type,
Arr_parameter_space ps_x,
Arr_parameter_space ps_y,
Subcurve* sc,
const Point_2& pt,
std::vector<Event_queue_iterator>& events,
std::size_t index)
{
Event* e;
std::pair<Event_queue_iterator, bool>
pair_res = std::make_pair (events[index], true);
// If event does not exist
if (events[index] == Event_queue_iterator())
{
// Still look for the curve end in the event queue in case two
// point are the the same in the vertex range
m_queueEventLess.set_parameter_space_in_x(ps_x);
m_queueEventLess.set_parameter_space_in_y(ps_y);
m_queueEventLess.set_index(ind);
pair_res =
m_queue->find_lower(cv, m_queueEventLess);
}
bool exist = pair_res.second;
if (! exist) {
// The curve end is not found in the event queue - create a new event and
// insert it into the queue.
// The curve end is closed and so it is associated with a valid
// point.
e = _allocate_event(pt, type, ps_x, ps_y);
}
else {
events[index] = pair_res.first;
// The event associated with the given curve end already exists in the
// queue, so we just have to update it.
e = *(pair_res.first);
CGAL_assertion((e->parameter_space_in_x() == ps_x) &&
(e->parameter_space_in_y() == ps_y));
e->set_attribute(type);
}
// If we are given a subcurve that the event represents one of its
// endpoints, update the event and the subcurve records accordingly.
// Note that this must be done before we actually insert the new event
// into the event queue.
_add_curve(e, sc, type);
// Insert the new event into the queue using the hint we got when we
// looked for it.
if (! exist)
events[index] = m_queue->insert_before(pair_res.first, e);
return (std::make_pair(e, !exist));
}
//-----------------------------------------------------------------------------
// add a curve as a right curve or left curve when the event is created
// or updated.