fix a bug when removing redundant edges after an overlay for a boolean operation

inner ccbs and outer ccb were reused to avoid a reallocation. However,
since the face field of inner/outer ccbs are needed will reassign them,
we now delay the setting of the new face for the ccbs to avoid
overwritting the face field
This commit is contained in:
Sébastien Loriot 2017-03-27 16:28:37 +02:00
parent d615e610c1
commit 09f5a176b6
1 changed files with 23 additions and 5 deletions

View File

@ -1184,6 +1184,13 @@ protected:
// accessor for low-level arrangement fonctionalities
CGAL::Arr_accessor<Aos_2> accessor(*arr);
// the face field of outer and inner ccb are used in the loop to access the old face an halfedge
// used to contribute to. These two vectors are used to delay the association to the new face to
// avoid overwriting a field that is still needed
typedef std::pair<typename Aos_2::Dcel::Outer_ccb*, typename Aos_2::Dcel::Face*> Outer_ccb_and_face;
typedef std::pair<typename Aos_2::Dcel::Inner_ccb*, typename Aos_2::Dcel::Face*> Inner_ccb_and_face;
std::vector<Outer_ccb_and_face> outer_ccb_and_new_face_pairs;
std::vector<Inner_ccb_and_face> inner_ccb_and_new_face_pairs;
// update halfedge ccb pointers
for (Halfedge_iterator itr = arr->halfedges_begin(); itr != arr->halfedges_end(); ++itr)
{
@ -1205,11 +1212,12 @@ protected:
f = *(face_handles[
(*uf_faces.find(face_handles[f->id()]))->id()
]);
if (h->flag()==ON_INNER_CCB || h->flag()==NOT_VISITED)
if (h->flag()==ON_INNER_CCB)
{
typename Aos_2::Dcel::Inner_ccb* inner_ccb = inner_ccbs_to_remove.empty()?
bool reuse_inner_ccb = !inner_ccbs_to_remove.empty();
typename Aos_2::Dcel::Inner_ccb* inner_ccb = !reuse_inner_ccb?
accessor.new_inner_ccb():inner_ccbs_to_remove.back();
if ( !inner_ccbs_to_remove.empty() ) inner_ccbs_to_remove.pop_back();
if ( reuse_inner_ccb ) inner_ccbs_to_remove.pop_back();
Halfedge_handle hstart=h;
do{
@ -1219,9 +1227,13 @@ protected:
}while(hstart!=h);
f->add_inner_ccb(inner_ccb,_halfedge(h));
inner_ccb->set_halfedge(_halfedge(h));
inner_ccb->set_face(f);
if (!reuse_inner_ccb)
inner_ccb->set_face(f);
else
inner_ccb_and_new_face_pairs.push_back( std::make_pair(inner_ccb, f) );
}
else{
// we never create more outer ccb than what was available
CGAL_assertion(!outer_ccbs_to_remove.empty());
typename Aos_2::Dcel::Outer_ccb* outer_ccb = outer_ccbs_to_remove.back();
outer_ccbs_to_remove.pop_back();
@ -1233,11 +1245,17 @@ protected:
}while(hstart!=h);
f->add_outer_ccb(outer_ccb,_halfedge(h));
outer_ccb->set_halfedge(_halfedge(h));
outer_ccb->set_face(f);
outer_ccb_and_new_face_pairs.push_back( std::make_pair(outer_ccb, f) );
}
}
}
// now set the new face for all ccbs
BOOST_FOREACH(Outer_ccb_and_face& ccb_and_face, outer_ccb_and_new_face_pairs)
ccb_and_face.first->set_face(ccb_and_face.second);
BOOST_FOREACH(Inner_ccb_and_face& ccb_and_face, inner_ccb_and_new_face_pairs)
ccb_and_face.first->set_face(ccb_and_face.second);
//remove no longer used edges, vertices and faces
accessor.delete_vertices( vertices_to_remove );
accessor.delete_edges( edges_to_remove );