mirror of https://github.com/CGAL/cgal
Merge branch '5.1.x-branch'
This commit is contained in:
commit
d08d6ca552
|
|
@ -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); }
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue