Skip to content

Commit ef23b63

Browse files
committed
Merge pull request #5166 from sgiraudot/Arrangement_2-Enhanced_ccb_merge-GF
Arrangement 2: Enhanced CCB Merging for Surface Sweep
2 parents 3407e3d + becf548 commit ef23b63

File tree

5 files changed

+184
-25
lines changed

5 files changed

+184
-25
lines changed

Arrangement_on_surface_2/include/CGAL/Arr_dcel_base.h

Lines changed: 103 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,18 @@ class Arr_halfedge : public H,
478478
const Inner_ccb* inner_ccb() const
479479
{
480480
CGAL_precondition(is_on_inner_ccb());
481-
return (reinterpret_cast<const Inner_ccb*>(_clean_pointer(this->p_comp)));
481+
482+
const Inner_ccb* out = reinterpret_cast<const Inner_ccb*>(_clean_pointer(this->p_comp));
483+
if (out->is_valid())
484+
return out;
485+
486+
// else reduce path and get valid iccb
487+
const Inner_ccb* valid = out->next();
488+
while (!valid->is_valid())
489+
valid = valid->next();
490+
const_cast<Inner_ccb*>(out)->set_next(const_cast<Inner_ccb*>(valid));
491+
const_cast<Halfedge*>(this)->set_inner_ccb(valid);
492+
return valid;
482493
}
483494

484495
/*! Get an incident inner CCB (non-const version).
@@ -487,11 +498,28 @@ class Arr_halfedge : public H,
487498
Inner_ccb* inner_ccb()
488499
{
489500
CGAL_precondition(is_on_inner_ccb());
490-
return (reinterpret_cast<Inner_ccb*>(_clean_pointer(this->p_comp)));
501+
502+
Inner_ccb* out = reinterpret_cast<Inner_ccb*>(_clean_pointer(this->p_comp));
503+
if (out->is_valid())
504+
return out;
505+
506+
// else reduce path and get valid iccb
507+
Inner_ccb* valid = out->next();
508+
while (!valid->is_valid())
509+
valid = valid->next();
510+
out->set_next(valid);
511+
set_inner_ccb(valid);
512+
return valid;
513+
}
514+
515+
Inner_ccb* inner_ccb_no_redirect()
516+
{
517+
CGAL_precondition(is_on_inner_ccb());
518+
return reinterpret_cast<Inner_ccb*>(_clean_pointer(this->p_comp));
491519
}
492520

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

770798
private:
771-
Face* p_f; // The face the contains the CCB in its interior.
799+
union
800+
{
801+
Face* f; // The face the contains the CCB in its interior.
802+
Arr_inner_ccb* icc; // next inner CCB in chain to valid icc
803+
} f_or_icc;
772804
Inner_ccb_iterator iter; // The inner CCB identifier.
773-
bool iter_is_not_singular;
805+
enum
806+
{
807+
ITER_IS_SINGULAR, // singular = default iterator, not initialized
808+
ITER_IS_NOT_SINGULAR, // not singular = iterator was assigned and is valid
809+
INVALID // invalid = the inner CCB is invalid and
810+
// only links to another inner CCB
811+
// in chain to valid CCB
812+
} status;
774813

775814
public:
776815
/*! Default constructor. */
777-
Arr_inner_ccb() : p_f(nullptr), iter_is_not_singular(false) {}
816+
Arr_inner_ccb() : status(ITER_IS_SINGULAR) { f_or_icc.f = nullptr; }
778817

779818
/*! Copy constructor. */
780819
Arr_inner_ccb(const Arr_inner_ccb& other) :
781-
p_f(other.p_f), iter_is_not_singular(other.iter_is_not_singular)
782-
{ if (other.iter_is_not_singular) iter = other.iter; }
820+
f_or_icc(other.f_or_icc), status(other.status)
821+
{ if (other.status == ITER_IS_NOT_SINGULAR) iter = other.iter; }
783822

784823
/*! Get a halfedge along the component (const version). */
785-
const Halfedge* halfedge() const { return (*iter); }
824+
const Halfedge* halfedge() const
825+
{
826+
CGAL_assertion (is_valid());
827+
return (*iter);
828+
}
786829

787830
/*! Get a halfedge along the component (non-const version). */
788-
Halfedge* halfedge() { return (*iter); }
831+
Halfedge* halfedge()
832+
{
833+
CGAL_assertion (is_valid());
834+
return (*iter);
835+
}
789836

790837
/*! Set a representative halfedge for the component. */
791-
void set_halfedge(Halfedge *he) { *iter = he; }
838+
void set_halfedge(Halfedge *he)
839+
{
840+
CGAL_assertion (is_valid());
841+
*iter = he;
842+
}
792843

793844
/*! Get the incident face (const version). */
794-
const Face* face() const { return (p_f); }
845+
const Face* face() const
846+
{
847+
CGAL_assertion (status != INVALID);
848+
return f_or_icc.f;
849+
}
795850

796851
/*! Get the incident face (non-const version). */
797-
Face* face() { return (p_f); }
852+
Face* face()
853+
{
854+
CGAL_assertion (status != INVALID);
855+
return f_or_icc.f;
856+
}
798857

799858
/*! Set the incident face. */
800-
void set_face(Face* f) { p_f = f; }
859+
void set_face(Face* f)
860+
{
861+
CGAL_assertion (status != INVALID);
862+
f_or_icc.f = f;
863+
}
801864

802865
/*! Get the iterator (const version). */
803866
Inner_ccb_iterator iterator() const
804867
{
805-
CGAL_assertion(iter_is_not_singular);
868+
CGAL_assertion(status == ITER_IS_NOT_SINGULAR);
806869
return (iter);
807870
}
808871

809872
/*! Get the iterator (non-const version). */
810873
Inner_ccb_iterator iterator()
811874
{
812-
CGAL_assertion(iter_is_not_singular);
875+
CGAL_assertion(status == ITER_IS_NOT_SINGULAR);
813876
return (iter);
814877
}
815878

816879
/*! Set the inner CCB iterator. */
817880
void set_iterator(Inner_ccb_iterator it)
818881
{
882+
CGAL_assertion (is_valid());
819883
iter = it;
820-
iter_is_not_singular = true;
884+
status = ITER_IS_NOT_SINGULAR;
885+
}
886+
887+
/*! Check validity */
888+
bool is_valid() const { return (status != INVALID); }
889+
890+
/*! Get the next CCB to primary chain. */
891+
Arr_inner_ccb* next() const
892+
{
893+
CGAL_assertion (status == INVALID);
894+
return f_or_icc.icc;
821895
}
896+
897+
/*! Set the next CCB to primary chain. */
898+
void set_next(Arr_inner_ccb* next)
899+
{
900+
status = INVALID;
901+
f_or_icc.icc = next;
902+
}
903+
822904
};
823905

824906
/*! \class
@@ -942,6 +1024,7 @@ class Arr_dcel_base {
9421024
typedef typename Face_list::iterator Face_iterator;
9431025
typedef CGAL::N_step_adaptor_derived<Halfedge_iterator, 2>
9441026
Edge_iterator;
1027+
typedef typename Inner_ccb_list::iterator Inner_ccb_iterator;
9451028

9461029
// Definitions of const iterators.
9471030
typedef typename Vertex_list::const_iterator Vertex_const_iterator;
@@ -1018,6 +1101,9 @@ class Arr_dcel_base {
10181101
{
10191102
return make_prevent_deref_range(edges_begin(), edges_end());
10201103
}
1104+
1105+
Inner_ccb_iterator inner_ccbs_begin() { return in_ccbs.begin(); }
1106+
Inner_ccb_iterator inner_ccbs_end() { return in_ccbs.end(); }
10211107
//@}
10221108

10231109
/// \name Obtaining constant iterators.

Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arrangement_on_surface_2_impl.h

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2739,14 +2739,24 @@ _insert_at_vertices(DHalfedge* he_to,
27392739
he1->set_inner_ccb(ic1);
27402740
he2->set_inner_ccb(ic1);
27412741

2742-
// Make all halfedges along ic2 to point to ic1.
2743-
DHalfedge* curr;
2744-
2745-
for (curr = he2->next(); curr != he1; curr = curr->next())
2746-
curr->set_inner_ccb(ic1);
2742+
if (m_sweep_mode)
2743+
{
2744+
// Inner CCB are obtained using Halfedge::inner_ccb() which
2745+
// performs path reduction and always return valid iCCB
2746+
CGAL_assertion(ic1->is_valid());
2747+
CGAL_assertion(ic2->is_valid());
2748+
ic2->set_next(ic1);
2749+
}
2750+
else
2751+
{
2752+
// Make all halfedges along ic2 to point to ic1.
2753+
DHalfedge* curr;
2754+
for (curr = he2->next(); curr != he1; curr = curr->next())
2755+
curr->set_inner_ccb(ic1);
27472756

2748-
// Delete the redundant inner CCB.
2749-
_dcel().delete_inner_ccb(ic2);
2757+
// Delete the redundant inner CCB.
2758+
_dcel().delete_inner_ccb(ic2);
2759+
}
27502760

27512761
// Notify the observers that we have merged the two inner CCBs.
27522762
_notify_after_merge_inner_ccb(fh, (Halfedge_handle(he1))->ccb());

Arrangement_on_surface_2/include/CGAL/Arrangement_on_surface_2.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -909,6 +909,14 @@ class Arrangement_on_surface_2 {
909909
bool m_own_traits; // inidicates whether the geometry
910910
// traits should be freed up.
911911

912+
bool m_sweep_mode = false;
913+
// sweep mode efficiently
914+
// merges inner CCB but
915+
// keeps invalid inner CCB
916+
// and memory overhead that
917+
// should be cleaned
918+
// afterwards
919+
912920
public:
913921
/// \name Constructors.
914922
//@{
@@ -939,6 +947,9 @@ class Arrangement_on_surface_2 {
939947
/*! Destructor. */
940948
virtual ~Arrangement_on_surface_2();
941949

950+
/*! Change mode. */
951+
void set_sweep_mode (bool mode) { m_sweep_mode = mode; }
952+
942953
/*! Clear the arrangement. */
943954
virtual void clear();
944955
//@}
@@ -1516,6 +1527,39 @@ class Arrangement_on_surface_2 {
15161527

15171528
//@}
15181529

1530+
/*!
1531+
* Cleans the inner CCB if sweep mode was used, by removing all
1532+
* non-valid inner CCBs
1533+
*/
1534+
void clean_inner_ccbs_after_sweep()
1535+
{
1536+
for (DHalfedge_iter he = _dcel().halfedges_begin();
1537+
he != _dcel().halfedges_end(); ++ he)
1538+
{
1539+
if (!he->is_on_inner_ccb())
1540+
continue;
1541+
1542+
DInner_ccb* ic1 = he->inner_ccb_no_redirect();
1543+
if (ic1->is_valid())
1544+
continue;
1545+
1546+
// Calling Halfedge::inner_ccb() reduces the path and makes the
1547+
// halfedge point to a correct CCB
1548+
DInner_ccb* ic2 = he->inner_ccb();
1549+
CGAL_USE(ic2);
1550+
CGAL_assertion (ic2->halfedge()->is_on_inner_ccb()
1551+
&& ic2->halfedge()->inner_ccb_no_redirect() == ic2);
1552+
}
1553+
1554+
typename Dcel::Inner_ccb_iterator it = _dcel().inner_ccbs_begin();
1555+
while (it != _dcel().inner_ccbs_end())
1556+
{
1557+
typename Dcel::Inner_ccb_iterator current = it ++;
1558+
if (!current->is_valid())
1559+
_dcel().delete_inner_ccb(&*current);
1560+
}
1561+
}
1562+
15191563
protected:
15201564
/// \name Determining the boundary-side conditions.
15211565
//@{

Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_construction_ss_visitor.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ class Arr_construction_ss_visitor :
142142
/* A notification issued before the sweep process starts. */
143143
inline void before_sweep();
144144

145+
/* A notification issued after the sweep process stops. */
146+
inline void after_sweep();
147+
145148
/*!
146149
* A notification invoked before the sweep-line starts handling the given
147150
* event.
@@ -267,7 +270,21 @@ class Arr_construction_ss_visitor :
267270
// Notifies the helper that the sweep process now starts.
268271
template <typename Hlpr, typename Vis>
269272
void Arr_construction_ss_visitor<Hlpr, Vis>::before_sweep()
270-
{ m_helper.before_sweep(); }
273+
{
274+
m_helper.before_sweep();
275+
m_arr->set_sweep_mode(true);
276+
}
277+
278+
279+
//-----------------------------------------------------------------------------
280+
// A notification issued after the sweep process stops.
281+
template <typename Hlpr, typename Vis>
282+
void Arr_construction_ss_visitor<Hlpr, Vis>::after_sweep()
283+
{
284+
m_arr->clean_inner_ccbs_after_sweep();
285+
m_arr->set_sweep_mode(false);
286+
}
287+
271288

272289
//-----------------------------------------------------------------------------
273290
// A notification invoked before the sweep-line starts handling the given

Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_overlay_ss_visitor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,8 @@ Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::update_event(Event* e,
552552
template <typename OvlHlpr, typename OvlTr, typename Vis>
553553
void Arr_overlay_ss_visitor<OvlHlpr, OvlTr, Vis>::after_sweep()
554554
{
555+
Base::after_sweep();
556+
555557
// Notify boundary vertices:
556558
typename Vertex_map::iterator it;
557559
for (it = m_vertices_map.begin(); it != m_vertices_map.end(); ++it) {

0 commit comments

Comments
 (0)