mirror of https://github.com/CGAL/cgal
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:
commit
cca666e28f
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Reference in New Issue