mirror of https://github.com/CGAL/cgal
extend the visitor to report non-manifold vertex in an umbrella without nm edge
This commit is contained in:
parent
bc1fe892d8
commit
b539d4a301
|
|
@ -17,11 +17,23 @@ public:
|
|||
|
||||
/// called each time an edge appears in more than two polygons.
|
||||
/// `id1` and `id2` are the vertex ids of the endpoints of the edge.
|
||||
void non_manifold_edge(std::size_t id1, std::size_t id2);
|
||||
/// `nb_polygons` indicates the number of polygons containing that edge.
|
||||
void non_manifold_edge(std::size_t id1, std::size_t id2, std::size_t nb_polygons);
|
||||
|
||||
/// called each time a non-manifold vertex is detected.
|
||||
/// `id` is the id of the vertex has is non-manifold.
|
||||
void non_manifold_vertex(std::size_t id);
|
||||
/// `vid` is the id of the vertex that is non-manifold.
|
||||
/// `nb_link_ccs` is the number of edge connected components of vertices
|
||||
/// in the link of the corresponding vertex.
|
||||
void non_manifold_vertex(std::size_t vid, std::size_t nb_link_ccs);
|
||||
|
||||
/// called during the detection of a non-manifold vertex, one time
|
||||
/// per incident edge connected component of vertices in the link of the vertex with id `vid`.
|
||||
/// `id` is the id of the vertex that is non-manifold.
|
||||
/// `polygon_ids` contains the ids of the polygon in such a connected component.
|
||||
/// This function is called a number of times exactly equal to the parameter `nb_link_ccs`
|
||||
/// for the same vertex in `non_manifold_vertex()`. Note that the aforementioned function is
|
||||
/// called after all the calls to this function are done.
|
||||
void link_connected_polygons(std::size_t vid, const std::vector<std::size_t>& polygon_ids){}
|
||||
|
||||
/// @}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,26 +16,27 @@
|
|||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
typedef CGAL::Polyhedron_3<K, CGAL::Polyhedron_items_with_id_3> Polyhedron;
|
||||
|
||||
//Optional visitor for orientation to demonstrate usage
|
||||
// Optional visitor for orientating a polygon soup to demonstrate usage for some functions.
|
||||
// inherits from the default class as some functions are not overloaded
|
||||
struct Visitor : public CGAL::Polygon_mesh_processing::Default_orientation_visitor
|
||||
{
|
||||
void non_manifold_edge(std::size_t id1, std::size_t id2) final
|
||||
void non_manifold_edge(std::size_t id1, std::size_t id2, std::size_t nb_poly)
|
||||
{
|
||||
std::cout << "The edge " << id1 << ", " << id2 << " is not manifold." << std::endl;
|
||||
std::cout << "The edge " << id1 << ", " << id2 << " is not manifold: " << nb_poly << " incident polygons." << std::endl;
|
||||
}
|
||||
void non_manifold_vertex(const std::size_t & id) final
|
||||
void non_manifold_vertex(std::size_t id, std::size_t nb_cycles)
|
||||
{
|
||||
std::cout << "The vertex " << id << " is not manifold." << std::endl;
|
||||
std::cout << "The vertex " << id << " is not manifold: " << nb_lcc<< " connected components of vertices in the link." << std::endl;
|
||||
}
|
||||
void duplicated_vertex(std::size_t v1, std::size_t v2) final
|
||||
void duplicated_vertex(std::size_t v1, std::size_t v2)
|
||||
{
|
||||
std::cout << "The vertex " << v1 << " has been duplicated, its new id is " << v2 << "." << std::endl;
|
||||
}
|
||||
void vertex_id_in_polygon_replaced(std::size_t p_id, std::size_t i1, std::size_t i2) final
|
||||
void vertex_id_in_polygon_replaced(std::size_t p_id, std::size_t i1, std::size_t i2)
|
||||
{
|
||||
std::cout << "In the polygon " << p_id << ", the index " << i1 << " has been replaced by " << i2 << "." << std::endl;
|
||||
}
|
||||
void polygon_orientation_reversed(std::size_t p_id) final
|
||||
void polygon_orientation_reversed(std::size_t p_id)
|
||||
{
|
||||
std::cout << "The polygon " << p_id << " has been reversed." << std::endl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,11 +45,12 @@ namespace Polygon_mesh_processing {
|
|||
* overridden.
|
||||
*/
|
||||
struct Default_orientation_visitor{
|
||||
inline virtual void non_manifold_edge(std::size_t, std::size_t){}
|
||||
inline virtual void non_manifold_vertex(std::size_t){}
|
||||
inline virtual void duplicated_vertex(std::size_t, std::size_t){}
|
||||
inline virtual void vertex_id_in_polygon_replaced(std::size_t, std::size_t, std::size_t){}
|
||||
inline virtual void polygon_orientation_reversed(std::size_t) {}
|
||||
void non_manifold_edge(std::size_t, std::size_t, std::size_t){}
|
||||
void non_manifold_vertex(std::size_t,std::size_t){}
|
||||
void duplicated_vertex(std::size_t, std::size_t){}
|
||||
void vertex_id_in_polygon_replaced(std::size_t, std::size_t, std::size_t){}
|
||||
void polygon_orientation_reversed(std::size_t) {}
|
||||
void link_connected_polygons(std::size_t, const std::vector<std::size_t>&){}
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
|
@ -80,7 +81,7 @@ struct Polygon_soup_orienter
|
|||
Edge_map edges; //< the set of edges of the input polygons
|
||||
Marked_edges marked_edges; //< the set of singular edges or edges incident
|
||||
//< to non-compatible orientation polygons
|
||||
Visitor visitor;
|
||||
Visitor& visitor;
|
||||
|
||||
/// for each polygon referenced by its position in `polygons`, indicates
|
||||
/// the connected component it belongs too after orientation.
|
||||
|
|
@ -168,18 +169,12 @@ struct Polygon_soup_orienter
|
|||
}
|
||||
}
|
||||
|
||||
Polygon_soup_orienter(Points& points, Polygons& polygons, Visitor visitor)
|
||||
Polygon_soup_orienter(Points& points, Polygons& polygons, Visitor& visitor)
|
||||
: points(points), polygons(polygons), edges(points.size()), visitor(visitor)
|
||||
{}
|
||||
|
||||
Polygon_soup_orienter(Points& points, Polygons& polygons)
|
||||
: points(points), polygons(polygons), edges(points.size())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//filling containers
|
||||
static void fill_edge_map(Edge_map& edges, Marked_edges& marked_edges, const Polygons& polygons, Visitor visitor) {
|
||||
static void fill_edge_map(Edge_map& edges, Marked_edges& marked_edges, const Polygons& polygons, Visitor& visitor) {
|
||||
// Fill edges
|
||||
for (P_ID i = 0; i < polygons.size(); ++i)
|
||||
{
|
||||
|
|
@ -208,7 +203,7 @@ struct Polygon_soup_orienter
|
|||
|
||||
if (nb_edges > 2)
|
||||
{
|
||||
visitor.non_manifold_edge(i0, i1);
|
||||
visitor.non_manifold_edge(i0, i1, nb_edges);
|
||||
set_edge_marked(i0, i1, marked_edges);
|
||||
}
|
||||
}
|
||||
|
|
@ -357,24 +352,31 @@ struct Polygon_soup_orienter
|
|||
if ( incident_polygons.empty() ) continue; //isolated vertex
|
||||
std::set<P_ID> visited_polygons;
|
||||
|
||||
bool first_pass = true;
|
||||
bool is_nm = false;
|
||||
std::size_t nb_link_ccs=0;
|
||||
for(P_ID p_id : incident_polygons)
|
||||
{
|
||||
if ( !visited_polygons.insert(p_id).second ) continue; // already visited
|
||||
|
||||
if (!first_pass)
|
||||
if (++nb_link_ccs != 1)
|
||||
{
|
||||
// the vertex is non-manifold
|
||||
vertices_to_duplicate.push_back(std::pair<V_ID, std::vector<P_ID> >());
|
||||
vertices_to_duplicate.back().first=v_id;
|
||||
is_nm = true;
|
||||
|
||||
// call the visitor only if the function has been overridden
|
||||
if (nb_link_ccs==2 && &Visitor::link_connected_polygons != &Default_orientation_visitor::link_connected_polygons)
|
||||
{
|
||||
std::vector<std::size_t> tmp(visited_polygons.begin(), visited_polygons.end());
|
||||
tmp.erase(std::remove(tmp.begin(), tmp.end(), p_id), tmp.end());
|
||||
visitor.link_connected_polygons(v_id, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
const std::array<V_ID,3>& neighbors = get_neighbor_vertices(v_id,p_id,polygons);
|
||||
|
||||
V_ID next = neighbors[2];
|
||||
|
||||
if( !first_pass)
|
||||
if(nb_link_ccs != 1)
|
||||
vertices_to_duplicate.back().second.push_back(p_id);
|
||||
|
||||
do{
|
||||
|
|
@ -382,7 +384,7 @@ struct Polygon_soup_orienter
|
|||
std::tie(next, other_p_id) = next_cw_vertex_around_source(v_id, next, polygons, edges, marked_edges);
|
||||
if (next==v_id) break;
|
||||
visited_polygons.insert(other_p_id);
|
||||
if( !first_pass)
|
||||
if(nb_link_ccs != 1)
|
||||
vertices_to_duplicate.back().second.push_back(other_p_id);
|
||||
}
|
||||
while(next!=neighbors[0]);
|
||||
|
|
@ -395,17 +397,15 @@ struct Polygon_soup_orienter
|
|||
std::tie(next, other_p_id) = next_ccw_vertex_around_target(next, v_id, polygons, edges, marked_edges);
|
||||
if (next==v_id) break;
|
||||
visited_polygons.insert(other_p_id);
|
||||
if( !first_pass)
|
||||
if(nb_link_ccs != 1)
|
||||
vertices_to_duplicate.back().second.push_back(other_p_id);
|
||||
}
|
||||
while(true);
|
||||
}
|
||||
first_pass=false;
|
||||
}
|
||||
if (is_nm)
|
||||
{
|
||||
visitor.non_manifold_vertex(v_id);
|
||||
if (nb_link_ccs != 1)
|
||||
visitor.link_connected_polygons(v_id, vertices_to_duplicate.back().second);
|
||||
}
|
||||
if (nb_link_ccs != 1) visitor.non_manifold_vertex(v_id, nb_link_ccs);
|
||||
}
|
||||
|
||||
/// now duplicate the vertices
|
||||
|
|
|
|||
|
|
@ -64,7 +64,8 @@ duplicate_non_manifold_edges_in_polygon_soup(PointRange& points,
|
|||
typedef CGAL::Polygon_mesh_processing::internal::
|
||||
Polygon_soup_orienter<PointRange, PolygonRange> Orienter;
|
||||
|
||||
Orienter orienter(points, polygons);
|
||||
Default_orientation_visitor visitor;
|
||||
Orienter orienter(points, polygons, visitor);
|
||||
orienter.fill_edge_map();
|
||||
// make edges to duplicate
|
||||
for(std::size_t i1=0;i1<points.size();++i1)
|
||||
|
|
|
|||
|
|
@ -254,25 +254,8 @@ void Polyhedron_demo_orient_soup_plugin::createPointsAndPolyline(std::vector<std
|
|||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
Scene_points_with_normal_item* points = nullptr;
|
||||
|
||||
//remove vertices already in NM edges
|
||||
|
||||
std::unordered_set<std::size_t> check_set;
|
||||
for(Scene_polygon_soup_item::Edge edge : item->non_manifold_edges())
|
||||
{
|
||||
check_set.insert(edge[0]);
|
||||
check_set.insert(edge[1]);
|
||||
}
|
||||
|
||||
std::set<std::size_t> nm_vertices;
|
||||
for(const auto& v : nm_points)
|
||||
{
|
||||
if(check_set.insert(v).second)
|
||||
{
|
||||
nm_vertices.insert(v);
|
||||
}
|
||||
}
|
||||
bool items_created = false;
|
||||
if(nm_vertices.empty() && warn)
|
||||
if(nm_points.empty() && warn)
|
||||
{
|
||||
delete points;
|
||||
CGAL::Three::Three::information(tr("There is no non-manifold vertex in this soup."));
|
||||
|
|
@ -281,7 +264,7 @@ void Polyhedron_demo_orient_soup_plugin::createPointsAndPolyline(std::vector<std
|
|||
{
|
||||
points = new Scene_points_with_normal_item();
|
||||
items_created = true;
|
||||
for(std::size_t id : nm_vertices)
|
||||
for(std::size_t id : nm_points)
|
||||
{
|
||||
points->point_set()->insert(item->points()[id]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -424,14 +424,45 @@ Scene_polygon_soup_item::orient(std::vector<std::size_t>& non_manifold_vertices)
|
|||
{
|
||||
struct Visitor : public CGAL::Polygon_mesh_processing::Default_orientation_visitor
|
||||
{
|
||||
std::vector<std::size_t>& nm_vertices;
|
||||
const Polygon_soup::Polygons& polygons;
|
||||
std::set<std::size_t>& nm_vertices;
|
||||
std::set< std::pair<std::size_t, std::size_t> > nm_edges;
|
||||
|
||||
Visitor(std::vector<std::size_t>& nm_vertices)
|
||||
:nm_vertices(nm_vertices){}
|
||||
Visitor(const Polygon_soup::Polygons& polygons,
|
||||
std::set<std::size_t>& nm_vertices)
|
||||
: polygons(polygons)
|
||||
, nm_vertices(nm_vertices)
|
||||
{}
|
||||
|
||||
void non_manifold_vertex(std::size_t v) final
|
||||
void non_manifold_edge(std::size_t v1, std::size_t v2, std::size_t)
|
||||
{
|
||||
nm_vertices.push_back(v);
|
||||
nm_edges.insert(CGAL::make_sorted_pair(v1, v2));
|
||||
}
|
||||
|
||||
void link_connected_polygons(std::size_t v, const std::vector<std::size_t>& polygons_in_current_cycle)
|
||||
{
|
||||
// check if the current components of polygon incident to the link of the vertex contains
|
||||
// a non-manifold edge. If no, then it is a "pure" non-manifold vertex in this component
|
||||
if (!nm_edges.empty())
|
||||
for(std::size_t pid : polygons_in_current_cycle)
|
||||
{
|
||||
for (std::size_t i=0; i<polygons[pid].size(); ++i)
|
||||
{
|
||||
if (polygons[pid][i]==v)
|
||||
{
|
||||
std::size_t vn1 = i==0?(polygons[pid].size()-1):(i-1);
|
||||
std::size_t vn2 = i+1;
|
||||
if (vn2==polygons[pid].size()) vn2=0;
|
||||
|
||||
if (nm_edges.count(CGAL::make_sorted_pair(polygons[pid][i], polygons[pid][vn1]))==1) return;
|
||||
if (nm_edges.count(CGAL::make_sorted_pair(polygons[pid][i], polygons[pid][vn2]))==1) return;
|
||||
break;
|
||||
}
|
||||
else
|
||||
CGAL_assertion(i!=polygons[pid].size()-1); // the vertex is incident to the polygon
|
||||
}
|
||||
}
|
||||
nm_vertices.insert(v);
|
||||
}
|
||||
};
|
||||
if(isEmpty() || d->oriented)
|
||||
|
|
@ -460,10 +491,12 @@ Scene_polygon_soup_item::orient(std::vector<std::size_t>& non_manifold_vertices)
|
|||
d->soup->polygons.swap(valid_polygons);
|
||||
|
||||
bool res;
|
||||
Visitor visitor(non_manifold_vertices);
|
||||
std::set<std::size_t> nm_v_set;
|
||||
Visitor visitor(valid_polygons, nm_v_set);
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
res = CGAL::Polygon_mesh_processing::
|
||||
orient_polygon_soup(d->soup->points, d->soup->polygons, CGAL::parameters::visitor(visitor));
|
||||
non_manifold_vertices.assign(nm_v_set.begin(), nm_v_set.end());
|
||||
QApplication::restoreOverrideCursor();
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue