Merge pull request #5699 from GilesBathgate/Nef_3-snc_decorator_deduplication-GilesBathgate

Remove duplicate code in SNC_const_decorator/SNC_decorator
This commit is contained in:
Sébastien Loriot 2021-06-25 09:47:59 +02:00
commit 142fac63b5
3 changed files with 129 additions and 376 deletions

View File

@ -142,8 +142,8 @@ public:
{ return Segment_3(e->source()->point(),
e->twin()->source()->point()); }
template <typename Visitor>
void visit_shell_objects(SFace_const_handle f, Visitor& V) const;
template <typename Visitor, typename Traits = Self::Decorator_traits>
void visit_shell_objects(typename Traits::SFace_handle f, Visitor& V) const;
Vertex_const_iterator vertices_begin() const {
return this->sncp()->vertices_begin(); }
@ -237,10 +237,9 @@ public:
Infi_box::set_size_of_infimaximal_box(size);
}
typedef CGAL::SM_point_locator<SM_const_decorator> SM_point_locator;
Halffacet_const_handle get_visible_facet( const Vertex_const_handle v,
const Ray_3& ray) const
template <typename Traits = Self::Decorator_traits>
typename Traits::Halffacet_handle get_visible_facet( const typename Traits::Vertex_handle v,
const Ray_3& ray) const
/*{\Mop when one shoot a ray |ray| in order to find the facet below to
an object, and vertex |v| is hit, we need to choose one of the facets
in the adjacency list of |v| such that it could be 'seen' from the
@ -248,9 +247,17 @@ public:
locating the sphere facet |sf| pierced by |ray| and taking the adjacent
facet to one of the sphere segments on the boundary of |sf|.
\precondition |ray| target is on |v| and the intersection between
|ray| and the 2-skeleton incident to v is empty. }*/ {
|ray| and the 2-skeleton incident to v is empty. }*/
{
Halffacet_const_handle f_visible;
typedef typename Traits::Halffacet_handle Halffacet_handle;
typedef typename Traits::SFace_handle SFace_handle;
typedef typename Traits::SHalfedge_handle SHalfedge_handle;
typedef typename Traits::SFace_cycle_iterator SFace_cycle_iterator;
typedef typename Traits::SHalfloop_handle SHalfloop_handle;
typedef CGAL::SM_point_locator<typename Traits::SM_decorator> SM_point_locator;
Halffacet_handle f_visible;
CGAL_assertion( ray.source() != v->point());
CGAL_assertion( ray.has_on(v->point()));
Sphere_point sp(ray.source() - v->point());
@ -264,28 +271,21 @@ public:
SM_point_locator L(&*v);
Object_handle o = L.locate(sp);
SFace_const_handle sf;
SFace_handle sf;
if(!CGAL::assign(sf,o)) {
SHalfedge_const_handle se;
if(CGAL::assign(se,o))
std::cerr << "on sedge " << PH(se)
<< " on facet " << se->facet()->plane() << std::endl;
SVertex_const_handle sv;
if(CGAL::assign(sv,o))
std::cerr << "on svertex " << sv->point() << std::endl;
CGAL_error_msg( "it is not possible to decide which one is a visible facet (if any)");
return Halffacet_const_handle();
return Halffacet_handle();
}
SFace_cycle_const_iterator fc = sf->sface_cycles_begin(),
SFace_cycle_iterator fc = sf->sface_cycles_begin(),
fce = sf->sface_cycles_end();
if( is_empty_range( fc, fce)) {
CGAL_NEF_TRACEN( "no adjacent facet found.");
f_visible = Halffacet_const_handle();
f_visible = Halffacet_handle();
}
else {
if (fc.is_shalfedge()) {
SHalfedge_const_handle se(fc);
SHalfedge_handle se(fc);
CGAL_NEF_TRACEN( "adjacent facet found (SEdges cycle).");
CGAL_NEF_TRACEN("se"<<PH(se));
CGAL_NEF_TRACEN(se->facet()->plane() <<"/"<<
@ -295,8 +295,7 @@ public:
CGAL_NEF_TRACEN("f_visible"<< f_visible->plane());
}
else if (fc.is_shalfloop()) {
SHalfloop_const_handle sl(fc);
SM_const_decorator SD;
SHalfloop_handle sl(fc);
CGAL_NEF_TRACEN( "adjacent facet found (SHalfloop cycle)."<< sl->circle()
<< " with facet "<< sl->facet()->plane());
f_visible = sl->twin()->facet();
@ -309,7 +308,7 @@ public:
++fc; while( fc != fce) { CGAL_assertion( fc.is_svertex()); ++fc; }
CGAL_NEF_TRACEN( "no adjacent facets were found (but incident edge(s)).");
#endif
f_visible = Halffacet_const_handle();
f_visible = Halffacet_handle();
}
else
CGAL_error_msg("Damn wrong handle");
@ -317,17 +316,22 @@ public:
return f_visible;
}
Halffacet_const_handle get_visible_facet( const Halfedge_const_handle e,
const Ray_3& ray) const {
template <typename Traits = Self::Decorator_traits>
typename Traits::Halffacet_handle get_visible_facet( const typename Traits::Halfedge_handle e,
const Ray_3& ray) const
//{\Mop when one shoot a ray |ray| in order to find the facet below to
// an object, and an edge |e| is hit, we need to choose one of the two
// facets in the adjacency list of |e| that could be 'seen' from the
// piercing point of the |ray| on the local (virtual) view of |e|
// \precondition |ray| target belongs to |e|. }
{
typedef typename Traits::SM_decorator SM_decorator;
typedef typename Traits::Halffacet_handle Halffacet_handle;
typedef typename Traits::SHalfedge_around_svertex_circulator SHalfedge_around_svertex_circulator;
SM_const_decorator SD(&*e->source());
SM_decorator SD(&*e->source());
if( SD.is_isolated(e))
return Halffacet_const_handle();
return Halffacet_handle();
// We search for the plane in the adjacency list of e, which is closest
// to the ray. The cross product of the direction of e and the orthogonal
@ -335,8 +339,8 @@ public:
// and orthogonal to e, pointing inside of the facet.
Vector_3 ev(segment(e).to_vector()), rv(ray.to_vector());
SHalfedge_around_svertex_const_circulator sh(SD.first_out_edge(e));
Halffacet_const_handle res = sh->facet();
SHalfedge_around_svertex_circulator sh(SD.first_out_edge(e));
Halffacet_handle res = sh->facet();
Vector_3 vec0(cross_product(ev,res->plane().orthogonal_vector()));
/* // probably incorrect assertion
CGAL_assertion_code
@ -345,7 +349,7 @@ public:
SD.circle(sh)));
CGAL_assertion( _ess.has_on(vec0));
*/
SHalfedge_around_svertex_const_circulator send(sh);
SHalfedge_around_svertex_circulator send(sh);
CGAL_NEF_TRACEN("initial face candidate "<< res->plane()<<" with vector "<<vec0);
// We compare the vectors vec0/vec1 of the facets. The one that is nearest
@ -395,16 +399,19 @@ public:
return res; // never reached
}
Halffacet_const_handle get_visible_facet(Halffacet_const_handle f,
const Ray_3& ray) const
template <typename Traits = Self::Decorator_traits>
typename Traits::Halffacet_handle get_visible_facet( const typename Traits::Halffacet_handle f,
const Ray_3& ray) const
/*{\Mop when one shoot a ray |ray| in order to find the facet below to
an object, and a facet |f| is hit, we need to choose the right facet
from the halffacet pair |f| that could be 'seen' from the
piercing point of the |ray| on the local (virtual) view of |f|.
\precondition |ray| target belongs to |f| and the intersection between
|ray| and is not coplanar with |f|. }*/ {
|ray| and is not coplanar with |f|. }*/
{
typedef typename Traits::Halffacet_handle Halffacet_handle;
Halffacet_const_handle f_visible = f;
Halffacet_handle f_visible = f;
if( f_visible->plane().has_on_negative_side(ray.source()))
f_visible = f_visible->twin();
CGAL_assertion( f_visible->plane().has_on_positive_side(ray.source()));
@ -429,84 +436,116 @@ public:
}
};
/* visiting shell objects:
Objects are marked as done, when placed in the output list. We have
to maintain a stack of sface candidates (the spherical rubber sectors
that provide connectivity at the local graphs of vertices) and facet
candiates (the plane pieces in three space also providing
connectivity). Note that we have to take care about the orientation of
sobjects and facets. We have to take care that (1) the search along
the shell extends along the whole shell structure (2) does not visit
any object twice, and (3) all 3-space objects have to be reported and
this also just once.
The facets and sfaces are marked |done| when they are put into their
corresponding queues thus each such object is visited exactly once
when taken out of the queue.
When an sface |sf| is taken out of the queue |SFaceCandiates| its
boundary structure is examined and all 2-skeleton objects (vertices
and edges of 3-space) that are incident to the volume represented by
|sf| are reported. Facets are reported when they are taken out of
|FacetCandiates|.
*/
template <typename EW>
template <typename Visitor>
template <typename Visitor, typename Traits>
void SNC_const_decorator<EW>::
visit_shell_objects(SFace_const_handle f, Visitor& V) const
visit_shell_objects(typename Traits::SFace_handle f, Visitor& V) const
{
std::list<SFace_const_handle> SFaceCandidates;
std::list<Halffacet_const_handle> FacetCandidates;
CGAL::Unique_hash_map<SFace_const_handle,bool> DoneSF(false);
CGAL::Unique_hash_map<Vertex_const_handle,bool> DoneV(false);
CGAL::Unique_hash_map<SVertex_const_handle,bool> DoneSV(false);
CGAL::Unique_hash_map<Halffacet_const_handle,bool> DoneF(false);
SFaceCandidates.push_back(f); DoneSF[f] = true;
typedef typename Traits::Halffacet_cycle_iterator Halffacet_cycle_iterator;
typedef typename Traits::Halffacet_handle Halffacet_handle;
typedef typename Traits::SFace_cycle_iterator SFace_cycle_iterator;
typedef typename Traits::SFace_handle SFace_handle;
typedef typename Traits::SHalfedge_around_facet_circulator SHalfedge_around_facet_circulator;
typedef typename Traits::SHalfedge_around_sface_circulator SHalfedge_around_sface_circulator;
typedef typename Traits::SHalfedge_handle SHalfedge_handle;
typedef typename Traits::SHalfloop_handle SHalfloop_handle;
typedef typename Traits::SM_decorator SM_decorator;
typedef typename Traits::SVertex_handle SVertex_handle;
std::list<SFace_handle> SFaceCandidates;
std::list<Halffacet_handle> FacetCandidates;
CGAL::Generic_handle_map<bool> Done(false);
SFaceCandidates.push_back(f); Done[f] = true;
while ( true ) {
if ( SFaceCandidates.empty() && FacetCandidates.empty() ) break;
if ( !FacetCandidates.empty() ) {
Halffacet_const_handle f = *FacetCandidates.begin();
Halffacet_handle f = *FacetCandidates.begin();
FacetCandidates.pop_front();
V.visit(f); // report facet
Halffacet_cycle_const_iterator fc;
Halffacet_cycle_iterator fc;
CGAL_forall_facet_cycles_of(fc,f) {
if (fc.is_shalfedge() ) {
SHalfedge_const_handle e(fc);
SHalfedge_const_handle she;
SHalfedge_around_facet_const_circulator ec(e),ee(e);
SHalfedge_handle e(fc);
SHalfedge_handle she;
SHalfedge_around_facet_circulator ec(e),ee(e);
CGAL_For_all(ec,ee) { she = ec->twin();
if ( DoneSF[she->incident_sface()] ) continue;
if ( Done[she->incident_sface()] ) continue;
SFaceCandidates.push_back(she->incident_sface());
DoneSF[she->incident_sface()] = true;
Done[she->incident_sface()] = true;
}
} else if (fc.is_shalfloop() ) {
SHalfloop_const_handle l(fc);
SHalfloop_const_handle ll = l->twin();
if ( DoneSF[ll->incident_sface()] ) continue;
SHalfloop_handle l(fc);
SHalfloop_handle ll = l->twin();
if ( Done[ll->incident_sface()] ) continue;
SFaceCandidates.push_back(ll->incident_sface());
DoneSF[ll->incident_sface()] = true;
Done[ll->incident_sface()] = true;
} else CGAL_error_msg("Damn wrong handle.");
}
}
if ( !SFaceCandidates.empty() ) {
SFace_const_handle sf = *SFaceCandidates.begin();
SFace_handle sf = *SFaceCandidates.begin();
SFaceCandidates.pop_front();
V.visit(sf);
if ( !DoneV[sf->center_vertex()] )
if ( !Done[sf->center_vertex()] )
V.visit(sf->center_vertex()); // report vertex
DoneV[sf->center_vertex()] = true;
Done[sf->center_vertex()] = true;
// SVertex_const_handle sv;
SM_const_decorator SD(&*sf->center_vertex());
SM_decorator SD(&*sf->center_vertex());
/*
CGAL_forall_svertices(sv,SD){
if(SD.is_isolated(sv) && !DoneSV[sv])
V.visit(sv);
}
*/
SFace_cycle_const_iterator fc;
SFace_cycle_iterator fc;
CGAL_forall_sface_cycles_of(fc,sf) {
if (fc.is_shalfedge() ) {
SHalfedge_const_handle e(fc);
SHalfedge_around_sface_const_circulator ec(e),ee(e);
SHalfedge_handle e(fc);
SHalfedge_around_sface_circulator ec(e),ee(e);
CGAL_For_all(ec,ee) {
V.visit(SHalfedge_const_handle(ec));
SVertex_const_handle vv = ec->twin()->source();
if ( !SD.is_isolated(vv) && !DoneSV[vv] ) {
V.visit(SHalfedge_handle(ec));
SVertex_handle vv = ec->twin()->source();
if ( !SD.is_isolated(vv) && !Done[vv] ) {
V.visit(vv); // report edge
DoneSV[vv] = DoneSV[vv->twin()] = true;
Done[vv] = Done[vv->twin()] = true;
}
Halffacet_const_handle f = ec->twin()->facet();
if ( DoneF[f] ) continue;
FacetCandidates.push_back(f); DoneF[f] = true;
Halffacet_handle f = ec->twin()->facet();
if ( Done[f] ) continue;
FacetCandidates.push_back(f); Done[f] = true;
}
} else if (fc.is_svertex() ) {
SVertex_const_handle v(fc);
if ( DoneSV[v] ) continue;
SVertex_handle v(fc);
if ( Done[v] ) continue;
V.visit(v); // report edge
V.visit(v->twin());
DoneSV[v] = DoneSV[v->twin()] = true;
Done[v] = Done[v->twin()] = true;
CGAL_assertion(SD.is_isolated(v));
SFaceCandidates.push_back(v->twin()->incident_sface());
DoneSF[v->twin()->incident_sface()]=true;
Done[v->twin()->incident_sface()]=true;
// note that v is isolated, thus twin(v) is isolated too
// SM_const_decorator SD;
// SFace_const_handle fo;
@ -518,11 +557,11 @@ visit_shell_objects(SFace_const_handle f, Visitor& V) const
fo = v->twin()->incident_sface();
*/
} else if (fc.is_shalfloop() ) {
SHalfloop_const_handle l(fc);
SHalfloop_handle l(fc);
V.visit(l);
Halffacet_const_handle f = l->twin()->facet();
if ( DoneF[f] ) continue;
FacetCandidates.push_back(f); DoneF[f] = true;
Halffacet_handle f = l->twin()->facet();
if ( Done[f] ) continue;
FacetCandidates.push_back(f); Done[f] = true;
} else CGAL_error_msg("Damn wrong handle.");
}
}

View File

@ -344,170 +344,15 @@ class SNC_decorator : public SNC_const_decorator<Map> {
Halffacet_handle get_visible_facet( const Vertex_handle v,
const Ray_3& ray) const
/*{\Mop when one shoot a ray |ray| in order to find the facet below to
an object, and vertex |v| is hit, we need to choose one of the facets
in the adjacency list of |v| such that it could be 'seen' from the
piercing point of the |ray| on the sphere map on |v|. We make it just
locating the sphere facet |sf| pierced by |ray| and taking the adjacent
facet to one of the sphere segments on the boundary of |sf|.
\precondition |ray| target is on |v| and the intersection between
|ray| and the 2-skeleton incident to v is empty. }*/ {
Halffacet_handle f_visible;
CGAL_assertion( ray.source() != v->point());
CGAL_assertion( ray.has_on(v->point()));
Sphere_point sp(ray.source() - v->point());
CGAL_NEF_TRACEN( "Locating "<<sp <<" in "<< v->point());
CGAL_assertion(Infi_box::degree(sp.hx()) < 2 &&
Infi_box::degree(sp.hy()) < 2 &&
Infi_box::degree(sp.hz()) < 2 &&
Infi_box::degree(sp.hw()) == 0);
sp = Infi_box::simplify(sp);
CGAL_NEF_TRACEN( "Locating "<<sp <<" in "<< v->point());
SM_point_locator L(&*v);
Object_handle o = L.locate(sp);
SFace_handle sf;
if(!CGAL::assign(sf,o)) {
CGAL_error_msg( "it is not possible to decide which one is a visible facet (if any)");
return Halffacet_handle();
}
SFace_cycle_iterator fc = sf->sface_cycles_begin(),
fce = sf->sface_cycles_end();
if( is_empty_range( fc, fce)) {
CGAL_NEF_TRACEN( "no adjacent facet found.");
f_visible = Halffacet_handle();
}
else {
if ( fc.is_shalfedge()) {
SHalfedge_handle se(fc);
CGAL_NEF_TRACEN( "adjacent facet found (SEdges cycle).");
CGAL_NEF_TRACEN("se"<<PH(se));
CGAL_NEF_TRACEN(se->facet()->plane() <<"/"<<
se->snext()->facet()->plane() <<"/"<<
se->snext()->snext()->facet()->plane());
f_visible = se->twin()->facet();
CGAL_NEF_TRACEN("f_visible"<<f_visible->plane());
}
else if ( fc.is_shalfloop()) {
SHalfloop_handle sl(fc);
CGAL_NEF_TRACEN( "adjacent facet found (SHalfloop cycle)."<< sl->circle()
<< " with facet "<<sl->facet()->plane());
f_visible = sl->twin()->facet();
CGAL_NEF_TRACEN("f_visible"<<f_visible->plane());
}
else if(fc.is_svertex()) {
#ifdef CGAL_NEF_DEBUG
// TODO: is there any warranty that the outter facet cycle enty point is always at first
// in the cycles list?
++fc; while( fc != fce) { CGAL_assertion( fc.is_svertex()); ++fc; }
#endif
CGAL_NEF_TRACEN( "no adjacent facets were found (but incident edge(s)).");
f_visible = Halffacet_handle();
}
else
CGAL_error_msg("Damn wrong handle");
}
return f_visible;
}
{ return Base::template get_visible_facet<Decorator_traits>(v, ray); }
Halffacet_handle get_visible_facet( const Halfedge_handle e,
const Ray_3& ray) const {
//{\Mop when one shoot a ray |ray| in order to find the facet below to
// an object, and an edge |e| is hit, we need to choose one of the two
// facets in the adjacency list of |e| that could be 'seen' from the
// piercing point of the |ray| on the local (virtual) view of |e|
// \precondition |ray| target belongs to |e|. }
SM_decorator SD(&*e->source());
if( SD.is_isolated(e))
return Halffacet_handle();
// We search for the plane in the adjacency list of e, which is closest
// to the ray. The cross product of the direction of e and the orthogonal
// vector of a plane gives us a vector vec0/vec1 on the plane of the facet
// and orthogonal to e, pointing inside of the facet.
Vector_3 ev(segment(e).to_vector()), rv(ray.to_vector());
SHalfedge_around_svertex_circulator sh(SD.first_out_edge(e));
Halffacet_handle res = sh->facet();
Vector_3 vec0(cross_product(ev,res->plane().orthogonal_vector()));
/* // probably incorrect assertion
CGAL_assertion_code
(Sphere_segment _ess( sh->source()->source()->point(),
sh->next()->source()->source()->point(),
sh->circle());
CGAL_assertion( _ess.has_on(vec0));
*/
SHalfedge_around_svertex_circulator send(sh);
CGAL_NEF_TRACEN("initial face candidate "<< res->plane()<<" with vector "<<vec0);
// We compare the vectors vec0/vec1 of the facets. The one that is nearest
// to pointing in the opposite direction of the ray, is chosen. The
// respective facet is the nearest to the ray.
sh++;
CGAL_For_all(sh,send) {
Vector_3 vec1(cross_product(ev,sh->facet()->plane().orthogonal_vector()));
CGAL_NEF_TRACEN("test face candidate "<< sh->facet()->plane()<<" with vector "<<vec1);
FT sk0(rv*vec0), sk1(rv*vec1);
if(sk0<=FT(0) && sk1>=FT(0))
continue;
if(sk0>=FT(0) && sk1<=FT(0)) {
res = sh->facet();
vec0 = vec1;
continue;
}
// We have to comapare the two skalar products sk0 and sk1. Therefore
// we have to normalize the input vectors vec0 and vec1, which means
// that we have to divide them by their lengths len0 and len1.
// To cicumvent irrational numbers, we sqaure the whole inequality.
FT len0 = vec0.x()*vec0.x()+vec0.y()*vec0.y()+vec0.z()*vec0.z();
FT len1 = vec1.x()*vec1.x()+vec1.y()*vec1.y()+vec1.z()*vec1.z();
FT diff = len0*sk1*sk1 - len1*sk0*sk0;
// if sk0<0 (and therefore sk1<0) both vectors point in a good direction.
// Therefore we take the one pointing more in the good direction.
// if sk0>0 (and therefore sk1>0) both vectors point in a bad direction.
// Therefore we take the one pointing less in the bad direction.
if((sk0>FT(0) && diff<FT(0)) || (sk0<FT(0) && diff>FT(0))) {
res = sh->facet();
vec0 = vec1;
}
}
// We have to check which of the two halffacet is visible from
// the ray.
if(rv*res->plane().orthogonal_vector() > FT(0))
res = res->twin();
CGAL_NEF_TRACEN("return "<<res->plane());
return res; // never reached
}
const Ray_3& ray) const
{ return Base::template get_visible_facet<Decorator_traits>(e, ray); }
Halffacet_handle get_visible_facet( const Halffacet_handle f,
const Ray_3& ray) const
/*{\Mop when one shoot a ray |ray| in order to find the facet below to
an object, and a facet |f| is hit, we need to choose the right facet
from the halffacet pair |f| that could be 'seen' from the
piercing point of the |ray| on the local (virtual) view of |f|.
\precondition |ray| target belongs to |f| and the intersection between
|ray| and is not coplanar with |f|. }*/ {
CGAL_NEF_TRACEN("get visible facet " << ray << ", " << f->plane()
<< " has on source " << f->plane().has_on(ray.source()));
Halffacet_handle f_visible = f;
// CGAL_assertion( !f_visible->plane().has_on(ray.source()));
if( f_visible->plane().has_on_negative_side(ray.source()))
f_visible = f->twin();
CGAL_assertion( f_visible->plane().has_on_positive_side(ray.source()));
return f_visible;
}
{ return Base::template get_visible_facet<Decorator_traits>(f, ray); }
bool is_valid( bool verb = false, int level = 0) {
@ -703,7 +548,8 @@ class SNC_decorator : public SNC_const_decorator<Map> {
}
template <typename Visitor>
void visit_shell_objects(SFace_handle f, Visitor& V) const;
void visit_shell_objects(SFace_handle f, Visitor& V) const
{ Base::template visit_shell_objects<Visitor,Decorator_traits>(f, V); }
Vertex_iterator vertices_begin() { return sncp()->vertices_begin(); }
Vertex_iterator vertices_end() { return sncp()->vertices_end(); }
@ -729,146 +575,14 @@ class SNC_decorator : public SNC_const_decorator<Map> {
return c->shells_end();
}
Size_type number_of_vertices() const
{ return sncp()->number_of_vertices(); }
Size_type number_of_halfedges() const
{ return sncp()->number_of_halfedges(); }
Size_type number_of_edges() const
{ return sncp()->number_of_edges(); }
Size_type number_of_halffacets() const
{ return sncp()->number_of_halffacets();}
Size_type number_of_facets() const
{ return sncp()->number_of_facets();}
Size_type number_of_volumes() const
{ return sncp()->number_of_volumes();}
using Base::number_of_vertices;
using Base::number_of_halfedges;
using Base::number_of_edges;
using Base::number_of_halffacets;
using Base::number_of_facets;
using Base::number_of_volumes;
};
/* visiting shell objects:
Objects are marked as done, when placed in the output list. We have
to maintain a stack of sface candidates (the spherical rubber sectors
that provide connectivity at the local graphs of vertices) and facet
candiates (the plane pieces in three space also providing
connectivity). Note that we have to take care about the orientation of
sobjects and facets. We have to take care that (1) the search along
the shell extends along the whole shell structure (2) does not visit
any object twice, and (3) all 3-space objects have to be reported and
this also just once.
The facets and sfaces are marked |done| when they are put into their
corresponding queues thus each such object is visited exactly once
when taken out of the queue.
When an sface |sf| is taken out of the queue |SFaceCandiates| its
boundary structure is examined and all 2-skeleton objects (vertices
and edges of 3-space) that are incident to the volume represented by
|sf| are reported. Facets are reported when they are taken out of
|FacetCandiates|.
*/
template <typename EW>
template <typename Visitor>
void SNC_decorator<EW>::
visit_shell_objects(SFace_handle f, Visitor& V) const
{
typedef typename SM_decorator::SHalfedge_around_sface_circulator
SHalfedge_around_sface_circulator;
std::list<SFace_handle> SFaceCandidates;
std::list<Halffacet_handle> FacetCandidates;
CGAL::Generic_handle_map<bool> Done(false);
SFaceCandidates.push_back(f); Done[f] = true;
while ( true ) {
if ( SFaceCandidates.empty() && FacetCandidates.empty() ) break;
if ( !FacetCandidates.empty() ) {
Halffacet_handle f = *FacetCandidates.begin();
FacetCandidates.pop_front();
V.visit(f); // report facet
Halffacet_cycle_iterator fc;
CGAL_forall_facet_cycles_of(fc,f) {
if (fc.is_shalfedge() ) {
SHalfedge_handle e(fc);
SHalfedge_around_facet_circulator ec(e),ee(e);
CGAL_For_all(ec,ee) { e = ec->twin();
if ( Done[e->incident_sface()] ) continue;
SFaceCandidates.push_back(e->incident_sface());
Done[e->incident_sface()] = true;
}
} else if (fc.is_shalfloop()) {
SHalfloop_handle l(fc);
l = l->twin();
if ( Done[l->incident_sface()] ) continue;
SFaceCandidates.push_back(l->incident_sface());
Done[l->incident_sface()] = true;
} else CGAL_error_msg("Damn wrong handle.");
}
}
if ( !SFaceCandidates.empty() ) {
SFace_handle sf = *SFaceCandidates.begin();
SFaceCandidates.pop_front();
V.visit(sf); // report sface
if ( !Done[sf->center_vertex()] )
V.visit(sf->center_vertex()); // report vertex
Done[sf->center_vertex()] = true;
// SVertex_handle sv;
SM_decorator SD(&*sf->center_vertex());
/*
CGAL_forall_svertices(sv,SD){
if(SD.is_isolated(sv) && !Done[sv])
V.visit(sv);
}
*/
SFace_cycle_iterator fc;
CGAL_forall_sface_cycles_of(fc,sf) {
if ( fc.is_shalfedge() ) {
SHalfedge_handle e(fc);
SHalfedge_around_sface_circulator ec(e),ee(e);
CGAL_For_all(ec,ee) {
V.visit(SHalfedge_handle(ec));
SVertex_handle v = ec->twin()->source();
if ( !SD.is_isolated(v) && !Done[v] ) {
V.visit(v); // report edge
Done[v] = Done[v->twin()] = true;
}
Halffacet_handle f = ec->twin()->facet();
if ( Done[f] ) continue;
FacetCandidates.push_back(f); Done[f] = true;
}
} else if ( fc.is_svertex() ) {
SVertex_handle v(fc);
if ( Done[v] ) continue;
V.visit(v); // report edge
V.visit(v->twin());
Done[v] = Done[v->twin()] = true;
CGAL_assertion(SD.is_isolated(v));
SFaceCandidates.push_back(v->twin()->incident_sface());
Done[v->twin()->incident_sface()]=true;
// note that v is isolated, thus v->twin() is isolated too
// SM_decorator SD;
// SFace_handle fo;
// fo = v->twin()->incident_sface();
/*
if(SD.is_isolated(v))
fo = v->source()->sfaces_begin();
else
fo = v->twin()->incident_sface();
*/
// if ( Done[fo] ) continue;
// SFaceCandidates.push_back(fo); Done[fo] = true;
} else if (fc.is_shalfloop()) {
SHalfloop_handle l(fc);
V.visit(l);
Halffacet_handle f = l->twin()->facet();
if ( Done[f] ) continue;
FacetCandidates.push_back(f); Done[f] = true;
} else CGAL_error_msg("Damn wrong handle.");
}
}
}
}
} //namespace CGAL
#endif //CGAL_SNC_DECORATOR_H

View File

@ -37,11 +37,11 @@ public:
template <class H>
const I& operator[](H h) const
{ return Base::operator[](&*h); }
{ return Base::operator[]((void*)&*h); }
template <class H>
I& operator[](H h)
{ return Base::operator[](&*h); }
{ return Base::operator[]((void*)&*h); }
};