Merge pull request #2844 from maxGimeno/Orient_soup-Output_nm_edges_in_polyline-GF

Polyhedron demo: Make Polyline from non manifold edges
This commit is contained in:
Laurent Rineau 2018-03-06 16:24:16 +01:00
commit cca666e28f
4 changed files with 172 additions and 2 deletions

View File

@ -39,7 +39,7 @@ endif()
polyhedron_demo_plugin(orient_soup_plugin Orient_soup_plugin)
target_link_libraries(orient_soup_plugin PUBLIC scene_polygon_soup_item scene_polyhedron_item scene_surface_mesh_item)
target_link_libraries(orient_soup_plugin PUBLIC scene_polygon_soup_item scene_polyhedron_item scene_surface_mesh_item scene_polylines_item scene_points_with_normal_item)
polyhedron_demo_plugin(inside_out_plugin Inside_out_plugin)

View File

@ -3,13 +3,18 @@
#include <QList>
#include <QMainWindow>
#include <QMessageBox>
#include <QInputDialog>
#include <QtDebug>
#include "Scene_polygon_soup_item.h"
#include "Scene_polyhedron_item.h"
#include "Scene_polylines_item.h"
#include "Scene_surface_mesh_item.h"
#include "Scene_points_with_normal_item.h"
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
#include <CGAL/Polygon_mesh_processing/orient_polygon_soup.h>
#include <CGAL/array.h>
#include "Messages_interface.h"
using namespace CGAL::Three;
class Polyhedron_demo_orient_soup_plugin :
@ -45,17 +50,22 @@ public Q_SLOTS:
void orientSM();
void shuffle();
void displayNonManifoldEdges();
void createPointsAndPolyline();
private:
template<class Item>
void apply_shuffle(Item* item,
const CGAL::Three::Scene_interface::Item_id& index);
void getNMPoints(std::vector<std::size_t> &vertices_to_duplicate,
Scene_polygon_soup_item* item);
CGAL::Three::Scene_interface* scene;
Messages_interface* messages;
QMainWindow* mw;
QAction* actionOrientPoly;
QAction* actionOrientSM;
QAction* actionShuffle;
QAction* actionNMToPolyline;
QAction* actionDisplayNonManifoldEdges;
}; // end Polyhedron_demo_orient_soup_plugin
@ -88,6 +98,10 @@ void Polyhedron_demo_orient_soup_plugin::init(QMainWindow* mainWindow,
actionDisplayNonManifoldEdges->setProperty("subMenuName", "View");
connect(actionDisplayNonManifoldEdges, SIGNAL(triggered()),
this, SLOT(displayNonManifoldEdges()));
actionNMToPolyline = new QAction(tr("Extract Non Manifold Simplices"), mainWindow);
actionNMToPolyline->setProperty("subMenuName", "Polygon Mesh Processing");
connect(actionNMToPolyline, &QAction::triggered,
this, &Polyhedron_demo_orient_soup_plugin::createPointsAndPolyline);
}
QList<QAction*> Polyhedron_demo_orient_soup_plugin::actions() const {
@ -95,6 +109,7 @@ QList<QAction*> Polyhedron_demo_orient_soup_plugin::actions() const {
<< actionOrientPoly
<< actionOrientSM
<< actionShuffle
<< actionNMToPolyline
<< actionDisplayNonManifoldEdges;
}
@ -135,6 +150,11 @@ void Polyhedron_demo_orient_soup_plugin::orientPoly()
if(item)
{
int create_items = QMessageBox::question(mw, "Orient Mesh", "Do you wish to extract the eventual non manifold simplicies ?");
if(create_items == QMessageBox::Yes)
{
createPointsAndPolyline();
}
if(!item->orient()) {
QMessageBox::information(mw, tr("Not orientable without self-intersections"),
tr("The polygon soup \"%1\" is not directly orientable."
@ -175,7 +195,11 @@ void Polyhedron_demo_orient_soup_plugin::orientSM()
if(item)
{
// qDebug() << tr("I have the item %1\n").arg(item->name());
int create_items = QMessageBox::question(mw, "Orient Mesh", "Do you wish to extract the potential non manifold simplicies ?");
if(create_items == QMessageBox::Yes)
{
createPointsAndPolyline();
}
if(!item->orient()) {
QMessageBox::information(mw, tr("Not orientable without self-intersections"),
tr("The polygon soup \"%1\" is not directly orientable."
@ -271,5 +295,143 @@ void Polyhedron_demo_orient_soup_plugin::displayNonManifoldEdges()
QApplication::restoreOverrideCursor();
}
}
void Polyhedron_demo_orient_soup_plugin::createPointsAndPolyline()
{
const CGAL::Three::Scene_interface::Item_id index = scene->mainSelectionIndex();
Scene_polygon_soup_item* item =
qobject_cast<Scene_polygon_soup_item*>(scene->item(index));
if(item)
{
QApplication::setOverrideCursor(Qt::WaitCursor);
Scene_points_with_normal_item* points = new Scene_points_with_normal_item();
std::vector<std::size_t> nm_vertices;
getNMPoints(nm_vertices, item);
bool items_created = false;
if(nm_vertices.empty())
{
delete points;
messages->information(tr("There is no non-manifold vertex in this soup."));
}
else
{
items_created = true;
BOOST_FOREACH(std::size_t id, nm_vertices)
{
points->point_set()->insert(item->points()[id]);
}
points->setName(QString("Non Manifold Vertices of %1").arg(item->name()));
points->setColor(QColor(Qt::red));
scene->addItem(points);
}
Polygon_soup::Edges nm_edges = item->non_manifold_edges();
if(!nm_edges.empty())
{
Scene_polylines_item* poly =
new Scene_polylines_item();
BOOST_FOREACH(Polygon_soup::Edge edge, nm_edges)
{
Point_3 a(item->points()[edge[0]]), b(item->points()[edge[1]]);
Scene_polylines_item::Polyline new_edge;
new_edge.push_back(a);
new_edge.push_back(b);
poly->polylines.push_back(new_edge);
}
poly->setName(QString("Non Manifold Edges of %1").arg(item->name()));
poly->setColor(QColor(Qt::red));
scene->addItem(poly);
items_created = true;
}
else
{
messages->information(tr("There is no non-manifold edge in this soup."));
}
QApplication::restoreOverrideCursor();
if(!items_created)
QMessageBox::information(mw, "Nothing Non-manifold", "No non-manifold edge nor vertex was found.");
}
}
void Polyhedron_demo_orient_soup_plugin::getNMPoints(
std::vector<std::size_t > &vertices_to_duplicate,
Scene_polygon_soup_item* item)
{
typedef std::pair<std::size_t, std::size_t> V_ID_pair;
typedef std::map<V_ID_pair, boost::container::flat_set<std::size_t> > Edge_map;
typedef std::set<V_ID_pair> Marked_edges;
typedef CGAL::Polygon_mesh_processing::internal::Polygon_soup_orienter<Polygon_soup::Points,
Polygon_soup::Polygons> PSO;
Edge_map edges;
Marked_edges m_edges;
PSO::fill_edge_map(edges, m_edges, item->polygons());
// for each vertex, indicates the list of polygon containing it
std::vector< std::vector<std::size_t> > incident_polygons_per_vertex(item->points().size());
std::size_t nb_polygons=item->polygons().size();
for(std::size_t ip=0; ip<nb_polygons; ++ip)
{
BOOST_FOREACH(std::size_t iv, item->polygons()[ip])
incident_polygons_per_vertex[iv].push_back(ip);
}
std::size_t nbv = item->points().size();
for (std::size_t v_id = 0; v_id < nbv; ++v_id)
{
const std::vector< std::size_t >& incident_polygons = incident_polygons_per_vertex[v_id];
if ( incident_polygons.empty() ) continue; //isolated vertex
std::set<std::size_t> visited_polygons;
bool first_pass = true;
BOOST_FOREACH(std::size_t p_id, incident_polygons)
{
if ( !visited_polygons.insert(p_id).second ) continue; // already visited
if (!first_pass)
{
vertices_to_duplicate.push_back(v_id);
}
std::size_t nbv = item->polygons()[p_id].size(), pvid=0;
for (; pvid!=nbv; ++pvid)
if (v_id==item->polygons()[p_id][pvid]) break;
CGAL_assertion( pvid!=nbv );
std::size_t p = item->polygons()[p_id][ (pvid+nbv-1)%nbv ];
std::size_t n = item->polygons()[p_id][ (pvid+1)%nbv ];
const CGAL::cpp11::array<std::size_t,3>& neighbors = CGAL::make_array(p,v_id,n);
std::size_t next = neighbors[2];
do{
std::size_t other_p_id;
CGAL::cpp11::tie(next, other_p_id) = PSO::next_cw_vertex_around_source(v_id, next, item->polygons(), edges, m_edges);
if (next==v_id) break;
visited_polygons.insert(other_p_id);
}
while(next!=neighbors[0]);
if (next==v_id){
/// turn the otherway round
next = neighbors[0];
do{
std::size_t other_p_id;
CGAL::cpp11::tie(next, other_p_id) = PSO::next_ccw_vertex_around_target(next, v_id, item->polygons(), edges, m_edges);
if (next==v_id) break;
visited_polygons.insert(other_p_id);
}
while(true);
}
first_pass=false;
}
}
}
#include "Orient_soup_plugin.moc"

View File

@ -920,3 +920,9 @@ void Scene_polygon_soup_item::itemAboutToBeDestroyed(Scene_item *item)
}
}
}
const Polygon_soup::Edges&
Scene_polygon_soup_item::non_manifold_edges() const
{
return d->soup->non_manifold_edges;
}

View File

@ -108,6 +108,7 @@ public:
typedef Kernel::Point_3 Point_3;
typedef Polygon_soup::Points Points;
typedef Polygon_soup::Polygons Polygons;
typedef Polygon_soup::Edges Edges;
Scene_polygon_soup_item();
~Scene_polygon_soup_item();
@ -151,6 +152,7 @@ public:
const Points& points() const;
const Polygons& polygons() const;
const Edges& non_manifold_edges() const;
public Q_SLOTS:
void shuffle_orientations();