avoid using a std::set and a std::vector for container storing at most 2 elements

Thanks @afabri
This commit is contained in:
Sébastien Loriot 2016-12-12 22:29:05 +01:00
parent 12fea568f0
commit 55c3e1ad61
1 changed files with 89 additions and 38 deletions

View File

@ -96,6 +96,49 @@ struct Default_surface_intersection_visitor{
static const bool do_need_vertex_graph = false; static const bool do_need_vertex_graph = false;
}; };
struct Node_id_set {
typedef std::size_t Node_id;
Node_id first;
Node_id second;
std::size_t size_;
Node_id_set()
: size_(0)
{}
void insert(std::size_t v){
if(size_ == 0){
first = v;
++size_;
}
else if((size_ == 1) && (v != first)){
if(v < first){
second = first;
first = v;
} else {
second = v;
}
++size_;
}
else{
CGAL_assertion((size_ == 2) && ((v == first) || (v == second)));
}
}
std::size_t size() const
{
return size_;
}
std::size_t operator[](std::size_t i) const
{
CGAL_assertion( (i < size) && (i == 0 || i == 1));
return (i == 0)? first : second;
}
};
template< class TriangleMesh, template< class TriangleMesh,
class VertexPointMap, class VertexPointMap,
class Node_visitor=Default_surface_intersection_visitor<TriangleMesh> class Node_visitor=Default_surface_intersection_visitor<TriangleMesh>
@ -124,7 +167,7 @@ class Intersection_of_triangle_meshes
// we use Face_pair_and_int and not Face_pair to handle coplanar case. // we use Face_pair_and_int and not Face_pair to handle coplanar case.
// Indeed the boundary of the intersection of two coplanar triangles // Indeed the boundary of the intersection of two coplanar triangles
// may contain several segments. // may contain several segments.
typedef std::map< Face_pair_and_int, std::set<Node_id> > Faces_to_nodes_map; typedef std::map< Face_pair_and_int, Node_id_set > Faces_to_nodes_map;
// data members // data members
@ -256,33 +299,30 @@ class Intersection_of_triangle_meshes
return std::pair<Node_id,bool>(res.first->second, false); return std::pair<Node_id,bool>(res.first->second, false);
} }
template <class Output_iterator>
void get_incident_faces(halfedge_descriptor edge,
const TriangleMesh& tm,
Output_iterator out)
{
if (!is_border(edge,tm)) *out++=face(edge,tm);
edge=opposite(edge,tm);
if (!is_border(edge,tm)) *out++=face(edge,tm);
}
void add_intersection_point_to_face_and_all_edge_incident_faces(face_descriptor f_1, void add_intersection_point_to_face_and_all_edge_incident_faces(face_descriptor f_1,
halfedge_descriptor e_2, halfedge_descriptor e_2,
const TriangleMesh& tm1, const TriangleMesh& tm1,
const TriangleMesh& tm2, const TriangleMesh& tm2,
Node_id node_id) Node_id node_id)
{ {
std::vector<face_descriptor> incident_faces_2; if (!is_border(e_2, tm2))
get_incident_faces(e_2,tm2,std::back_inserter(incident_faces_2));
BOOST_FOREACH(face_descriptor f_2, incident_faces_2)
{ {
face_descriptor f_2 = face(e_2, tm2);
Face_pair face_pair = &tm1<&tm2 Face_pair face_pair = &tm1<&tm2
? Face_pair(f_1,f_2) ? Face_pair(f_1,f_2)
: Face_pair(f_2,f_1); : Face_pair(f_2,f_1);
if ( coplanar_faces.count(face_pair) ) continue; if ( coplanar_faces.count(face_pair)==0 )
typename Faces_to_nodes_map::iterator it_list= f_to_node[Face_pair_and_int(face_pair,0)].insert(node_id);
f_to_node.insert( std::make_pair( Face_pair_and_int(face_pair,0),std::set<Node_id>()) ).first; }
it_list->second.insert(node_id); e_2 = opposite(e_2, tm2);
if (!is_border(e_2, tm2))
{
face_descriptor f_2 = face(e_2, tm2);
Face_pair face_pair = &tm1<&tm2
? Face_pair(f_1,f_2)
: Face_pair(f_2,f_1);
if ( coplanar_faces.count(face_pair) == 0 )
f_to_node[Face_pair_and_int(face_pair,0)].insert(node_id);
} }
} }
@ -295,13 +335,20 @@ class Intersection_of_triangle_meshes
{ {
//associate the intersection point to all faces incident to the intersected edge using edge //associate the intersection point to all faces incident to the intersected edge using edge
std::vector<face_descriptor> incident_faces; std::vector<face_descriptor> incident_faces;
get_incident_faces(edge_intersected,tm2,std::back_inserter(incident_faces));
BOOST_FOREACH(face_descriptor f_2, incident_faces) if (!is_border(edge_intersected, tm2))
{ {
face_descriptor f_2 = face(edge_intersected, tm2);
add_intersection_point_to_face_and_all_edge_incident_faces(f_2,e_1,tm2,tm1,node_id);
if (fset!=NULL) fset->erase(f_2);
}
edge_intersected = opposite(edge_intersected, tm2);
if (!is_border(edge_intersected, tm2))
{
face_descriptor f_2 = face(edge_intersected, tm2);
add_intersection_point_to_face_and_all_edge_incident_faces(f_2,e_1,tm2,tm1,node_id); add_intersection_point_to_face_and_all_edge_incident_faces(f_2,e_1,tm2,tm1,node_id);
if (fset!=NULL) fset->erase(f_2); if (fset!=NULL) fset->erase(f_2);
} }
incident_faces.clear();
//associate the intersection point to all faces incident to edge using the intersected edge //associate the intersection point to all faces incident to edge using the intersected edge
//at least one pair of faces is already handle above //at least one pair of faces is already handle above
@ -313,12 +360,19 @@ class Intersection_of_triangle_meshes
typename Edge_to_faces::iterator it_fset=tm2_edge_to_tm1_faces.find(edge(edge_intersected,tm2)); typename Edge_to_faces::iterator it_fset=tm2_edge_to_tm1_faces.find(edge(edge_intersected,tm2));
if (it_fset==tm2_edge_to_tm1_faces.end()) return; if (it_fset==tm2_edge_to_tm1_faces.end()) return;
Face_set& fset_bis=it_fset->second; Face_set& fset_bis=it_fset->second;
get_incident_faces(e_1,tm1,std::back_inserter(incident_faces));
BOOST_FOREACH(face_descriptor f_1, incident_faces) if (!is_border(e_1, tm1))
{ {
//the following call is not needed, it is already done in the first loop //the following call is not needed, it is already done in the first loop
//add_intersection_point_to_face_and_all_edge_incident_faces(f_1,edge_intersected,tm1,tm2,node_id); //add_intersection_point_to_face_and_all_edge_incident_faces(f_1,edge_intersected,tm1,tm2,node_id);
fset_bis.erase(f_1); fset_bis.erase(face(e_1, tm1));
}
e_1 = opposite(e_1, tm1);
if (!is_border(e_1, tm1))
{
//the following call is not needed, it is already done in the first loop
//add_intersection_point_to_face_and_all_edge_incident_faces(f_1,edge_intersected,tm1,tm2,node_id);
fset_bis.erase(face(e_1, tm1));
} }
} }
@ -494,19 +548,16 @@ class Intersection_of_triangle_meshes
case 0: break; case 0: break;
case 1: case 1:
{ {
typename Faces_to_nodes_map::iterator it_list= f_to_node[Face_pair_and_int(face_pair,1)].insert(cpln_nodes[0]);
f_to_node.insert( std::make_pair( Face_pair_and_int(face_pair,1),std::set<Node_id>()) ).first;
it_list->second.insert(cpln_nodes[0]);
} }
break; break;
default: default:
{ {
std::size_t stop=nb_pts + (nb_pts<3?-1:0); std::size_t stop=nb_pts + (nb_pts<3?-1:0);
for (std::size_t k=0;k<stop;++k){ for (std::size_t k=0;k<stop;++k){
typename Faces_to_nodes_map::iterator it_list= Node_id_set& node_id_set = f_to_node[Face_pair_and_int(face_pair,static_cast<int>(k+1))];
f_to_node.insert( std::make_pair( Face_pair_and_int(face_pair,static_cast<int>(k+1)),std::set<Node_id>()) ).first; node_id_set.insert( cpln_nodes[k] );
it_list->second.insert( cpln_nodes[k] ); node_id_set.insert( cpln_nodes[(k+1)%nb_pts] );
it_list->second.insert( cpln_nodes[(k+1)%nb_pts] );
} }
} }
} }
@ -692,11 +743,11 @@ class Intersection_of_triangle_meshes
//counts the number of time each node has been seen //counts the number of time each node has been seen
bool isolated_point_seen=false; bool isolated_point_seen=false;
for (typename Faces_to_nodes_map::iterator it=f_to_node.begin();it!=f_to_node.end();++it){ for (typename Faces_to_nodes_map::iterator it=f_to_node.begin();it!=f_to_node.end();++it){
const std::set<Node_id>& segment=it->second; const Node_id_set& segment=it->second;
CGAL_assertion(segment.size()==2 || segment.size()==1); CGAL_assertion(segment.size()==2 || segment.size()==1);
if (segment.size()==2){ if (segment.size()==2){
Node_id i=*segment.begin(); Node_id i=segment.first;
Node_id j=*boost::next(segment.begin()); Node_id j=segment.second;
graph[i].insert(j); graph[i].insert(j);
graph[j].insert(i); graph[j].insert(i);
} }
@ -800,11 +851,11 @@ class Intersection_of_triangle_meshes
{ {
if (it->second.size()==1) continue; if (it->second.size()==1) continue;
CGAL_precondition(it->second.size()==2); CGAL_precondition(it->second.size()==2);
CGAL_assertion(*(it->second.begin())<*cpp11::next(it->second.begin())); CGAL_assertion((it->second.first)< (it->second.second));
//it->second is a set so node ids are already sorted //it->second is a set so node ids are already sorted
bool is_new=already_seen.insert( std::make_pair( bool is_new=already_seen.insert( std::make_pair(
*(it->second.begin()), it->second.first,
*cpp11::next(it->second.begin()) ) it->second.second )
).second; ).second;
if (!is_new) if (!is_new)