mirror of https://github.com/CGAL/cgal
Merge pull request #7494 from MaelRL/Polyhedron_demo-Bbox-GF
AABB / OBB plugins improvements
This commit is contained in:
commit
0f57af63a4
|
|
@ -361,7 +361,7 @@ void oriented_bounding_box(const PointRange& points,
|
|||
// @todo handle those cases (or call min_rectangle_2 with a projection)
|
||||
if(points.size() <= 3)
|
||||
{
|
||||
std::cerr << "The oriented bounding box cannot (yet) be computed for a mesh with fewer than 4 vertices!\n";
|
||||
std::cerr << "The oriented bounding box cannot be computed with fewer than 4 vertices!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,9 +25,10 @@ polyhedron_demo_plugin(create_bbox_mesh_plugin Create_bbox_mesh_plugin)
|
|||
target_link_libraries(create_bbox_mesh_plugin PUBLIC scene_surface_mesh_item)
|
||||
|
||||
polyhedron_demo_plugin(create_obb_mesh_plugin Create_obb_mesh_plugin)
|
||||
target_link_libraries(
|
||||
create_obb_mesh_plugin PUBLIC scene_surface_mesh_item scene_selection_item
|
||||
scene_points_with_normal_item)
|
||||
target_link_libraries(create_obb_mesh_plugin PUBLIC scene_surface_mesh_item
|
||||
scene_polygon_soup_item
|
||||
scene_selection_item
|
||||
scene_points_with_normal_item)
|
||||
|
||||
qt5_wrap_ui(volumesUI_FILES Basic_generator_widget.ui)
|
||||
polyhedron_demo_plugin(
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
#include "Scene_surface_mesh_item.h"
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
|
||||
|
||||
|
||||
using namespace CGAL::Three;
|
||||
|
||||
class Create_bbox_mesh_plugin :
|
||||
|
|
@ -24,96 +23,135 @@ class Create_bbox_mesh_plugin :
|
|||
|
||||
public:
|
||||
void init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface*);
|
||||
|
||||
QList<QAction*> actions() const;
|
||||
bool applicable(QAction*) const {
|
||||
if(scene->mainSelectionIndex() != -1
|
||||
&& scene->item(scene->mainSelectionIndex())->isFinite())
|
||||
return true;
|
||||
return false;}
|
||||
|
||||
bool applicable(QAction*) const
|
||||
{
|
||||
bool at_least_one_non_empty = false;
|
||||
Q_FOREACH(int index, scene->selectionIndices())
|
||||
{
|
||||
Scene_item* item = scene->item(index);
|
||||
if(!item->isFinite())
|
||||
return false;
|
||||
if(!item->isEmpty())
|
||||
at_least_one_non_empty = true;
|
||||
}
|
||||
|
||||
return at_least_one_non_empty;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool bbox(bool extended = false);
|
||||
|
||||
public Q_SLOTS:
|
||||
void createBbox() {
|
||||
void createBbox()
|
||||
{
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
if(!bbox())
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
QMessageBox::warning(mw, "Error", "Bbox couldn't be computed, so there is no mesh created.");
|
||||
}
|
||||
else
|
||||
QApplication::restoreOverrideCursor();
|
||||
const bool res = bbox();
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
if(!res)
|
||||
QMessageBox::warning(mw, "Error", "Failed to compute the bounding box.");
|
||||
}
|
||||
void createExtendedBbox() {
|
||||
|
||||
void createExtendedBbox()
|
||||
{
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
if(!bbox(true))
|
||||
{
|
||||
QApplication::restoreOverrideCursor();
|
||||
QMessageBox::warning(mw, "Error", "Bbox couldn't be computed, so there is no mesh created.");
|
||||
}
|
||||
else
|
||||
QApplication::restoreOverrideCursor();
|
||||
const bool res = bbox(true);
|
||||
QApplication::restoreOverrideCursor();
|
||||
|
||||
if(!res)
|
||||
QMessageBox::warning(mw, "Error", "Failed to compute the extended bounding box");
|
||||
}
|
||||
|
||||
private:
|
||||
Scene_interface* scene;
|
||||
QMainWindow* mw;
|
||||
|
||||
QAction* actionBbox;
|
||||
QAction* actionExtendedBbox;
|
||||
};
|
||||
|
||||
}; // end Create_bbox_mesh_plugin
|
||||
|
||||
void Create_bbox_mesh_plugin::init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface*)
|
||||
void
|
||||
Create_bbox_mesh_plugin::
|
||||
init(QMainWindow* mainWindow,
|
||||
Scene_interface* scene_interface,
|
||||
Messages_interface*)
|
||||
{
|
||||
scene = scene_interface;
|
||||
mw = mainWindow;
|
||||
actionBbox = new QAction(tr("Create &Bbox Mesh"), mainWindow);
|
||||
|
||||
actionBbox = new QAction(tr("Create &Bounding Box"), mainWindow);
|
||||
actionBbox->setObjectName("createBboxMeshAction");
|
||||
connect(actionBbox, SIGNAL(triggered()),
|
||||
this, SLOT(createBbox()));
|
||||
actionExtendedBbox = new QAction(tr("Create &Extended Bbox Mesh"), mainWindow);
|
||||
|
||||
actionExtendedBbox = new QAction(tr("Create &Extended Bounding Box"), mainWindow);
|
||||
actionExtendedBbox->setObjectName("createExtendedBboxMeshAction");
|
||||
connect(actionExtendedBbox, SIGNAL(triggered()),
|
||||
this, SLOT(createExtendedBbox()));
|
||||
}
|
||||
|
||||
QList<QAction*> Create_bbox_mesh_plugin::actions() const {
|
||||
QList<QAction*>
|
||||
Create_bbox_mesh_plugin::
|
||||
actions() const
|
||||
{
|
||||
return QList<QAction*>() << actionBbox << actionExtendedBbox;
|
||||
}
|
||||
|
||||
bool Create_bbox_mesh_plugin::bbox(bool extended)
|
||||
bool
|
||||
Create_bbox_mesh_plugin::
|
||||
bbox(bool extended)
|
||||
{
|
||||
Scene_interface::Bbox bbox;
|
||||
bool initialized = false;
|
||||
int item_count = 0;
|
||||
QString name;
|
||||
|
||||
Q_FOREACH(int index, scene->selectionIndices()) {
|
||||
Q_FOREACH(int index, scene->selectionIndices())
|
||||
{
|
||||
Scene_item* item = scene->item(index);
|
||||
if(item->isFinite() && ! item->isEmpty()) {
|
||||
if(initialized) {
|
||||
if(item->isFinite() && !item->isEmpty())
|
||||
{
|
||||
if(item_count > 0)
|
||||
{
|
||||
bbox = bbox + item->bbox();
|
||||
} else {
|
||||
bbox = item->bbox();
|
||||
initialized = true;
|
||||
if(item_count == 1)
|
||||
name = name + " and others";
|
||||
}
|
||||
else
|
||||
{
|
||||
bbox = item->bbox();
|
||||
name = item->name();
|
||||
}
|
||||
++item_count;
|
||||
}
|
||||
}
|
||||
std::cerr << "bbox dimensions: " << bbox.xmax() - bbox.xmin()
|
||||
<< "\n " << bbox.ymax() - bbox.ymin()
|
||||
<< "\n " << bbox.zmax() - bbox.zmin()
|
||||
|
||||
if(item_count == 0)
|
||||
return false;
|
||||
|
||||
std::cout << "bbox: " << bbox.xmin() << " | " << bbox.xmax()
|
||||
<< "\n " << bbox.ymin() << " | " << bbox.ymax()
|
||||
<< "\n " << bbox.zmin() << " | " << bbox.zmax()
|
||||
<< std::endl;
|
||||
|
||||
if(extended) {
|
||||
if(extended)
|
||||
{
|
||||
const double delta_x = ( bbox.xmax() - bbox.xmin() ) / 20.;
|
||||
const double delta_y = ( bbox.ymax() - bbox.ymin() ) / 20.;
|
||||
const double delta_z = ( bbox.zmax() - bbox.zmin() ) / 20.;
|
||||
bbox = Scene_interface::Bbox(
|
||||
bbox.xmin() - delta_x,
|
||||
bbox.ymin() - delta_y,
|
||||
bbox.zmin() - delta_z,
|
||||
bbox.xmax() + delta_x,
|
||||
bbox.ymax() + delta_y,
|
||||
bbox.zmax() + delta_z);
|
||||
bbox = Scene_interface::Bbox(bbox.xmin() - delta_x,
|
||||
bbox.ymin() - delta_y,
|
||||
bbox.zmin() - delta_z,
|
||||
bbox.xmax() + delta_x,
|
||||
bbox.ymax() + delta_y,
|
||||
bbox.zmax() + delta_z);
|
||||
|
||||
std::cout << "extended bbox: " << bbox.xmin() << " | " << bbox.xmax()
|
||||
<< "\n " << bbox.ymin() << " | " << bbox.ymax()
|
||||
<< "\n " << bbox.zmin() << " | " << bbox.zmax()
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
if((bbox.min)(0) > (bbox.max)(0) ||
|
||||
|
|
@ -122,15 +160,18 @@ bool Create_bbox_mesh_plugin::bbox(bool extended)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Scene_item* item;
|
||||
EPICK::Iso_cuboid_3 ic(bbox);
|
||||
SMesh* p = new SMesh;
|
||||
CGAL::make_hexahedron(ic[0], ic[1], ic[2], ic[3], ic[4], ic[5], ic[6], ic[7],*p);
|
||||
CGAL::make_hexahedron(ic[0], ic[1], ic[2], ic[3], ic[4], ic[5], ic[6], ic[7], *p);
|
||||
|
||||
item = new Scene_surface_mesh_item(p);
|
||||
item->setName("Scene bbox mesh");
|
||||
item->setName(name + (extended ? " (Extended Bbox)" : " (Bbox)"));
|
||||
item->setRenderingMode(Wireframe);
|
||||
item->setColor(Qt::black);
|
||||
scene->addItem(item);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <QApplication>
|
||||
|
||||
#include "Scene_surface_mesh_item.h"
|
||||
#include "Scene_polygon_soup_item.h"
|
||||
#include "Scene_polyhedron_selection_item.h"
|
||||
#include "Scene_points_with_normal_item.h"
|
||||
|
||||
|
|
@ -20,9 +21,9 @@ using namespace CGAL::Three;
|
|||
|
||||
typedef Scene_surface_mesh_item Scene_facegraph_item;
|
||||
|
||||
class Create_obb_mesh_plugin :
|
||||
public QObject,
|
||||
public CGAL::Three::Polyhedron_demo_plugin_interface
|
||||
class Create_obb_mesh_plugin
|
||||
: public QObject,
|
||||
public CGAL::Three::Polyhedron_demo_plugin_interface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
|
||||
|
|
@ -30,32 +31,36 @@ class Create_obb_mesh_plugin :
|
|||
|
||||
public:
|
||||
void init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface*);
|
||||
|
||||
QList<QAction*> actions() const;
|
||||
|
||||
bool applicable(QAction*) const
|
||||
{
|
||||
if(scene->mainSelectionIndex() != -1
|
||||
&& scene->item(scene->mainSelectionIndex())->isFinite())
|
||||
bool at_least_one_non_empty = false;
|
||||
Q_FOREACH(int index, scene->selectionIndices())
|
||||
{
|
||||
const Scene_interface::Item_id index = scene->mainSelectionIndex();
|
||||
|
||||
Scene_facegraph_item* item = qobject_cast<Scene_facegraph_item*>(scene->item(index));
|
||||
|
||||
Scene_polyhedron_selection_item* selection_item =
|
||||
qobject_cast<Scene_polyhedron_selection_item*>(scene->item(index));
|
||||
|
||||
Scene_points_with_normal_item* point_set_item =
|
||||
qobject_cast<Scene_points_with_normal_item*>(scene->item(index));
|
||||
if(!item && !selection_item && !point_set_item)
|
||||
Scene_item* item = scene->item(index);
|
||||
if(!item->isFinite())
|
||||
return false;
|
||||
return true;
|
||||
|
||||
Scene_facegraph_item* sm_item = qobject_cast<Scene_facegraph_item*>(item);
|
||||
Scene_polygon_soup_item* ps_item = qobject_cast<Scene_polygon_soup_item*>(item);
|
||||
Scene_polyhedron_selection_item* selection_item = qobject_cast<Scene_polyhedron_selection_item*>(item);
|
||||
Scene_points_with_normal_item* pts_item = qobject_cast<Scene_points_with_normal_item*>(item);
|
||||
if(!sm_item && !ps_item && !selection_item && !pts_item)
|
||||
return false;
|
||||
|
||||
if(!item->isEmpty())
|
||||
at_least_one_non_empty = true;
|
||||
}
|
||||
return false;
|
||||
|
||||
return at_least_one_non_empty;
|
||||
}
|
||||
|
||||
protected:
|
||||
void gather_mesh_points(std::vector<Point_3>& points);
|
||||
void obb();
|
||||
int dimensionality(const std::vector<Point_3>& points);
|
||||
bool obb();
|
||||
|
||||
public Q_SLOTS:
|
||||
void createObb()
|
||||
|
|
@ -69,87 +74,166 @@ private:
|
|||
Scene_interface* scene;
|
||||
QMainWindow* mw;
|
||||
QAction* actionObb;
|
||||
}; // end Create_obb_mesh_plugin class
|
||||
};
|
||||
|
||||
void Create_obb_mesh_plugin::init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface*)
|
||||
void
|
||||
Create_obb_mesh_plugin::
|
||||
init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface*)
|
||||
{
|
||||
scene = scene_interface;
|
||||
mw = mainWindow;
|
||||
actionObb = new QAction(tr("Create &Optimal Bbox Mesh"), mainWindow);
|
||||
actionObb = new QAction(tr("Create &Optimal Bounding Box"), mainWindow);
|
||||
actionObb->setObjectName("createObbMeshAction");
|
||||
connect(actionObb, SIGNAL(triggered()), this, SLOT(createObb()));
|
||||
}
|
||||
|
||||
QList<QAction*> Create_obb_mesh_plugin::actions() const
|
||||
QList<QAction*>
|
||||
Create_obb_mesh_plugin::
|
||||
actions() const
|
||||
{
|
||||
return QList<QAction*>() << actionObb;
|
||||
}
|
||||
|
||||
void Create_obb_mesh_plugin::gather_mesh_points(std::vector<Point_3>& points)
|
||||
int
|
||||
Create_obb_mesh_plugin::
|
||||
dimensionality(const std::vector<Point_3>& points)
|
||||
{
|
||||
const Scene_interface::Item_id index = scene->mainSelectionIndex();
|
||||
if(points.empty())
|
||||
return -1;
|
||||
|
||||
Scene_facegraph_item* item = qobject_cast<Scene_facegraph_item*>(scene->item(index));
|
||||
int d = 0;
|
||||
Point_3 p0 = points[0], p1, p2;
|
||||
|
||||
Scene_polyhedron_selection_item* selection_item =
|
||||
qobject_cast<Scene_polyhedron_selection_item*>(scene->item(index));
|
||||
|
||||
Scene_points_with_normal_item* point_set_item =
|
||||
qobject_cast<Scene_points_with_normal_item*>(scene->item(index));
|
||||
|
||||
if(item || selection_item)
|
||||
auto it = std::cbegin(points), end = std::cend(points);
|
||||
while(it != end)
|
||||
{
|
||||
typedef typename boost::property_map<FaceGraph, boost::vertex_point_t>::type PointPMap;
|
||||
typedef typename boost::graph_traits<FaceGraph>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename boost::graph_traits<FaceGraph>::face_descriptor face_descriptor;
|
||||
|
||||
std::vector<vertex_descriptor> selected_vertices;
|
||||
|
||||
if(item != nullptr)
|
||||
if(p0 != *it)
|
||||
{
|
||||
FaceGraph& pmesh = *item->polyhedron();
|
||||
selected_vertices.assign(vertices(pmesh).begin(), vertices(pmesh).end());
|
||||
PointPMap pmap = get(CGAL::vertex_point, pmesh);
|
||||
for(vertex_descriptor v : selected_vertices)
|
||||
points.push_back(get(pmap, v));
|
||||
|
||||
p1 = *it;
|
||||
d = 1;
|
||||
break;
|
||||
}
|
||||
else if(selection_item != nullptr) // using selection of faces
|
||||
{
|
||||
FaceGraph& pmesh = *selection_item->polyhedron();
|
||||
for(face_descriptor f : selection_item->selected_facets)
|
||||
{
|
||||
for(vertex_descriptor v : vertices_around_face(halfedge(f, pmesh), pmesh))
|
||||
selected_vertices.push_back(v);
|
||||
}
|
||||
|
||||
PointPMap pmap = get(CGAL::vertex_point, pmesh);
|
||||
for(vertex_descriptor v : selected_vertices)
|
||||
points.push_back(get(pmap, v));
|
||||
}
|
||||
|
||||
CGAL_assertion(points.size() >= 3);
|
||||
++it;
|
||||
}
|
||||
|
||||
if(point_set_item)
|
||||
while(it != end)
|
||||
{
|
||||
Point_set* points_set = point_set_item->point_set();
|
||||
if(points_set == nullptr)
|
||||
return;
|
||||
if(!collinear(p0, p1, *it))
|
||||
{
|
||||
p2 = *it;
|
||||
d = 2;
|
||||
break;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
std::cout << "points_set->size()= " << points_set->size() << std::endl;
|
||||
for(const Point_3& p : points_set->points())
|
||||
points.push_back(p);
|
||||
while(it != end)
|
||||
{
|
||||
if(!coplanar(p0, p1, p2, *it))
|
||||
{
|
||||
d = 3;
|
||||
break;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
void
|
||||
Create_obb_mesh_plugin::
|
||||
gather_mesh_points(std::vector<Point_3>& points)
|
||||
{
|
||||
Q_FOREACH(int index, scene->selectionIndices())
|
||||
{
|
||||
Scene_item* item = scene->item(index);
|
||||
|
||||
// Surface Mesh
|
||||
Scene_facegraph_item* sm_item = qobject_cast<Scene_facegraph_item*>(item);
|
||||
if(sm_item)
|
||||
{
|
||||
FaceGraph* sm_ptr = sm_item->polyhedron();
|
||||
if(sm_ptr == nullptr)
|
||||
continue;
|
||||
|
||||
for(auto v : vertices(*sm_ptr))
|
||||
points.push_back(get(CGAL::vertex_point, *sm_ptr, v));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Polygon soup
|
||||
Scene_polygon_soup_item* ps_item = qobject_cast<Scene_polygon_soup_item*>(item);
|
||||
if(ps_item)
|
||||
{
|
||||
for(const Point_3& p : ps_item->points())
|
||||
points.push_back(p);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Selection
|
||||
Scene_polyhedron_selection_item* selection_item = qobject_cast<Scene_polyhedron_selection_item*>(item);
|
||||
if(selection_item != nullptr)
|
||||
{
|
||||
FaceGraph* sm_ptr = selection_item->polyhedron();
|
||||
if(sm_ptr == nullptr)
|
||||
continue;
|
||||
|
||||
auto vpm = get(CGAL::vertex_point, *sm_ptr);
|
||||
|
||||
for(auto f : selection_item->selected_facets)
|
||||
{
|
||||
// @todo avoid duplication
|
||||
for(auto v : vertices_around_face(halfedge(f, *sm_ptr), *sm_ptr))
|
||||
points.push_back(get(vpm, v));
|
||||
}
|
||||
|
||||
for(auto e : selection_item->selected_edges)
|
||||
{
|
||||
points.push_back(get(vpm, source(e, *sm_ptr)));
|
||||
points.push_back(get(vpm, target(e, *sm_ptr)));
|
||||
}
|
||||
|
||||
for(auto v : selection_item->selected_vertices)
|
||||
points.push_back(get(vpm, v));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Point set
|
||||
Scene_points_with_normal_item* pts_item = qobject_cast<Scene_points_with_normal_item*>(item);
|
||||
if(pts_item)
|
||||
{
|
||||
Point_set* pts_ptr = pts_item->point_set();
|
||||
if(pts_ptr == nullptr)
|
||||
return;
|
||||
|
||||
for(const Point_3& p : pts_ptr->points())
|
||||
points.push_back(p);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Create_obb_mesh_plugin::obb()
|
||||
bool
|
||||
Create_obb_mesh_plugin::
|
||||
obb()
|
||||
{
|
||||
// gather point coordinates
|
||||
std::vector<Point_3> points;
|
||||
gather_mesh_points(points);
|
||||
|
||||
// find obb
|
||||
const int d = dimensionality(points);
|
||||
if(d != 3)
|
||||
{
|
||||
std::cerr << "Dimensionality of the point set is: " << d << std::endl;
|
||||
QMessageBox::warning(mw, "Error", "At least 4 non-coplanar points are required to compute an OBB.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// compute the OBB
|
||||
std::array<Point_3, 8> obb_points;
|
||||
CGAL::oriented_bounding_box(points, obb_points);
|
||||
|
||||
|
|
@ -157,11 +241,36 @@ void Create_obb_mesh_plugin::obb()
|
|||
SMesh* p = new SMesh;
|
||||
CGAL::make_hexahedron(obb_points[0], obb_points[1], obb_points[2], obb_points[3],
|
||||
obb_points[4], obb_points[5], obb_points[6], obb_points[7], *p);
|
||||
item = new Scene_facegraph_item(p);
|
||||
|
||||
item->setName("Optimal bbox mesh");
|
||||
std::cout << "Optimal bounding box: " << obb_points[0]
|
||||
<< "\n " << obb_points[7]
|
||||
<< std::endl;
|
||||
|
||||
QString name;
|
||||
Q_FOREACH(int index, scene->selectionIndices())
|
||||
{
|
||||
Scene_item* item = scene->item(index);
|
||||
if(!item->isEmpty())
|
||||
{
|
||||
if(name.size() > 0)
|
||||
{
|
||||
name = name + " and others";
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
name = item->name();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item = new Scene_facegraph_item(p);
|
||||
item->setName(name + " (OBB)");
|
||||
item->setRenderingMode(Wireframe);
|
||||
item->setColor(Qt::black);
|
||||
scene->addItem(item);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "Create_obb_mesh_plugin.moc"
|
||||
|
|
|
|||
Loading…
Reference in New Issue