Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 103 additions & 17 deletions Arrangement_on_surface_2/include/CGAL/Arr_dcel_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,18 @@ class Arr_halfedge : public H,
const Inner_ccb* inner_ccb() const
{
CGAL_precondition(is_on_inner_ccb());
return (reinterpret_cast<const Inner_ccb*>(_clean_pointer(this->p_comp)));

const Inner_ccb* out = reinterpret_cast<const Inner_ccb*>(_clean_pointer(this->p_comp));
if (out->is_valid())
return out;

// else reduce path and get valid iccb
const Inner_ccb* valid = out->next();
while (!valid->is_valid())
valid = valid->next();
const_cast<Inner_ccb*>(out)->set_next(const_cast<Inner_ccb*>(valid));
const_cast<Halfedge*>(this)->set_inner_ccb(valid);
return valid;
}

/*! Get an incident inner CCB (non-const version).
Expand All @@ -487,11 +498,28 @@ class Arr_halfedge : public H,
Inner_ccb* inner_ccb()
{
CGAL_precondition(is_on_inner_ccb());
return (reinterpret_cast<Inner_ccb*>(_clean_pointer(this->p_comp)));

Inner_ccb* out = reinterpret_cast<Inner_ccb*>(_clean_pointer(this->p_comp));
if (out->is_valid())
return out;

// else reduce path and get valid iccb
Inner_ccb* valid = out->next();
while (!valid->is_valid())
valid = valid->next();
out->set_next(valid);
set_inner_ccb(valid);
return valid;
}

Inner_ccb* inner_ccb_no_redirect()
{
CGAL_precondition(is_on_inner_ccb());
return reinterpret_cast<Inner_ccb*>(_clean_pointer(this->p_comp));
}

/*! Set the incident inner CCB. */
void set_inner_ccb(Inner_ccb *ic)
void set_inner_ccb(const Inner_ccb *ic)
{
// Set the component pointer and set its LSB.
this->p_comp = _set_lsb(ic);
Expand Down Expand Up @@ -768,57 +796,111 @@ class Arr_inner_ccb : public In_place_list_base<Arr_inner_ccb<V,H,F> >
typedef typename Face::Inner_ccb_iterator Inner_ccb_iterator;

private:
Face* p_f; // The face the contains the CCB in its interior.
union
{
Face* f; // The face the contains the CCB in its interior.
Arr_inner_ccb* icc; // next inner CCB in chain to valid icc
} f_or_icc;
Inner_ccb_iterator iter; // The inner CCB identifier.
bool iter_is_not_singular;
enum
{
ITER_IS_SINGULAR, // singular = default iterator, not initialized
ITER_IS_NOT_SINGULAR, // not singular = iterator was assigned and is valid
INVALID // invalid = the inner CCB is invalid and
// only links to another inner CCB
// in chain to valid CCB
} status;

public:
/*! Default constructor. */
Arr_inner_ccb() : p_f(nullptr), iter_is_not_singular(false) {}
Arr_inner_ccb() : status(ITER_IS_SINGULAR) { f_or_icc.f = nullptr; }

/*! Copy constructor. */
Arr_inner_ccb(const Arr_inner_ccb& other) :
p_f(other.p_f), iter_is_not_singular(other.iter_is_not_singular)
{ if (other.iter_is_not_singular) iter = other.iter; }
f_or_icc(other.f_or_icc), status(other.status)
{ if (other.status == ITER_IS_NOT_SINGULAR) iter = other.iter; }

/*! Get a halfedge along the component (const version). */
const Halfedge* halfedge() const { return (*iter); }
const Halfedge* halfedge() const
{
CGAL_assertion (is_valid());
return (*iter);
}

/*! Get a halfedge along the component (non-const version). */
Halfedge* halfedge() { return (*iter); }
Halfedge* halfedge()
{
CGAL_assertion (is_valid());
return (*iter);
}

/*! Set a representative halfedge for the component. */
void set_halfedge(Halfedge *he) { *iter = he; }
void set_halfedge(Halfedge *he)
{
CGAL_assertion (is_valid());
*iter = he;
}

/*! Get the incident face (const version). */
const Face* face() const { return (p_f); }
const Face* face() const
{
CGAL_assertion (status != INVALID);
return f_or_icc.f;
}

/*! Get the incident face (non-const version). */
Face* face() { return (p_f); }
Face* face()
{
CGAL_assertion (status != INVALID);
return f_or_icc.f;
}

/*! Set the incident face. */
void set_face(Face* f) { p_f = f; }
void set_face(Face* f)
{
CGAL_assertion (status != INVALID);
f_or_icc.f = f;
}

/*! Get the iterator (const version). */
Inner_ccb_iterator iterator() const
{
CGAL_assertion(iter_is_not_singular);
CGAL_assertion(status == ITER_IS_NOT_SINGULAR);
return (iter);
}

/*! Get the iterator (non-const version). */
Inner_ccb_iterator iterator()
{
CGAL_assertion(iter_is_not_singular);
CGAL_assertion(status == ITER_IS_NOT_SINGULAR);
return (iter);
}

/*! Set the inner CCB iterator. */
void set_iterator(Inner_ccb_iterator it)
{
CGAL_assertion (is_valid());
iter = it;
iter_is_not_singular = true;
status = ITER_IS_NOT_SINGULAR;
}

/*! Check validity */
bool is_valid() const { return (status != INVALID); }

/*! Get the next CCB to primary chain. */
Arr_inner_ccb* next() const
{
CGAL_assertion (status == INVALID);
return f_or_icc.icc;
}

/*! Set the next CCB to primary chain. */
void set_next(Arr_inner_ccb* next)
{
status = INVALID;
f_or_icc.icc = next;
}

};

/*! \class
Expand Down Expand Up @@ -942,6 +1024,7 @@ class Arr_dcel_base {
typedef typename Face_list::iterator Face_iterator;
typedef CGAL::N_step_adaptor_derived<Halfedge_iterator, 2>
Edge_iterator;
typedef typename Inner_ccb_list::iterator Inner_ccb_iterator;

// Definitions of const iterators.
typedef typename Vertex_list::const_iterator Vertex_const_iterator;
Expand Down Expand Up @@ -1018,6 +1101,9 @@ class Arr_dcel_base {
{
return make_prevent_deref_range(edges_begin(), edges_end());
}

Inner_ccb_iterator inner_ccbs_begin() { return in_ccbs.begin(); }
Inner_ccb_iterator inner_ccbs_end() { return in_ccbs.end(); }
//@}

/// \name Obtaining constant iterators.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2739,14 +2739,24 @@ _insert_at_vertices(DHalfedge* he_to,
he1->set_inner_ccb(ic1);
he2->set_inner_ccb(ic1);

// Make all halfedges along ic2 to point to ic1.
DHalfedge* curr;

for (curr = he2->next(); curr != he1; curr = curr->next())
curr->set_inner_ccb(ic1);
if (m_sweep_mode)
{
// Inner CCB are obtained using Halfedge::inner_ccb() which
// performs path reduction and always return valid iCCB
CGAL_assertion(ic1->is_valid());
CGAL_assertion(ic2->is_valid());
ic2->set_next(ic1);
}
else
{
// Make all halfedges along ic2 to point to ic1.
DHalfedge* curr;
for (curr = he2->next(); curr != he1; curr = curr->next())
curr->set_inner_ccb(ic1);

// Delete the redundant inner CCB.
_dcel().delete_inner_ccb(ic2);
// Delete the redundant inner CCB.
_dcel().delete_inner_ccb(ic2);
}

// Notify the observers that we have merged the two inner CCBs.
_notify_after_merge_inner_ccb(fh, (Halfedge_handle(he1))->ccb());
Expand Down
44 changes: 44 additions & 0 deletions Arrangement_on_surface_2/include/CGAL/Arrangement_on_surface_2.h
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,14 @@ class Arrangement_on_surface_2 {
bool m_own_traits; // inidicates whether the geometry
// traits should be freed up.

bool m_sweep_mode = false;
// sweep mode efficiently
// merges inner CCB but
// keeps invalid inner CCB
// and memory overhead that
// should be cleaned
// afterwards

public:
/// \name Constructors.
//@{
Expand Down Expand Up @@ -939,6 +947,9 @@ class Arrangement_on_surface_2 {
/*! Destructor. */
virtual ~Arrangement_on_surface_2();

/*! Change mode. */
void set_sweep_mode (bool mode) { m_sweep_mode = mode; }

/*! Clear the arrangement. */
virtual void clear();
//@}
Expand Down Expand Up @@ -1516,6 +1527,39 @@ class Arrangement_on_surface_2 {

//@}

/*!
* Cleans the inner CCB if sweep mode was used, by removing all
* non-valid inner CCBs
*/
void clean_inner_ccbs_after_sweep()
{
for (DHalfedge_iter he = _dcel().halfedges_begin();
he != _dcel().halfedges_end(); ++ he)
{
if (!he->is_on_inner_ccb())
continue;

DInner_ccb* ic1 = he->inner_ccb_no_redirect();
if (ic1->is_valid())
continue;

// Calling Halfedge::inner_ccb() reduces the path and makes the
// halfedge point to a correct CCB
DInner_ccb* ic2 = he->inner_ccb();
CGAL_USE(ic2);
CGAL_assertion (ic2->halfedge()->is_on_inner_ccb()
&& ic2->halfedge()->inner_ccb_no_redirect() == ic2);
}

typename Dcel::Inner_ccb_iterator it = _dcel().inner_ccbs_begin();
while (it != _dcel().inner_ccbs_end())
{
typename Dcel::Inner_ccb_iterator current = it ++;
if (!current->is_valid())
_dcel().delete_inner_ccb(&*current);
}
}

protected:
/// \name Determining the boundary-side conditions.
//@{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ class Arr_construction_ss_visitor :
/* A notification issued before the sweep process starts. */
inline void before_sweep();

/* A notification issued after the sweep process stops. */
inline void after_sweep();

/*!
* A notification invoked before the sweep-line starts handling the given
* event.
Expand Down Expand Up @@ -267,7 +270,21 @@ class Arr_construction_ss_visitor :
// Notifies the helper that the sweep process now starts.
template <typename Hlpr, typename Vis>
void Arr_construction_ss_visitor<Hlpr, Vis>::before_sweep()
{ m_helper.before_sweep(); }
{
m_helper.before_sweep();
m_arr->set_sweep_mode(true);
}


//-----------------------------------------------------------------------------
// A notification issued after the sweep process stops.
template <typename Hlpr, typename Vis>
void Arr_construction_ss_visitor<Hlpr, Vis>::after_sweep()
{
m_arr->clean_inner_ccbs_after_sweep();
m_arr->set_sweep_mode(false);
}


//-----------------------------------------------------------------------------
// A notification invoked before the sweep-line starts handling the given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,8 @@ Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::update_event(Event* e,
template <typename OvlHlpr, typename OvlTr, typename Vis>
void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::after_sweep()
{
Base::after_sweep();

// Notify boundary vertices:
typename Vertex_map::iterator it;
for (it = m_vertices_map.begin(); it != m_vertices_map.end(); ++it) {
Expand Down