mirror of https://github.com/CGAL/cgal
use PMP for corefinement and intersection plugins
This commit is contained in:
parent
6368ae3784
commit
6ac45f820a
|
|
@ -336,9 +336,9 @@ boolean_operation( TriangleMesh& tm1,
|
|||
Corefinement::No_mark<TriangleMesh>//default
|
||||
> ::type Ecm2;
|
||||
|
||||
Ecm1 ecm1 = boost::choose_param( get_param(np1, edge_is_constrained),
|
||||
Ecm1 ecm1 = boost::choose_param( boost::get_param(np1, edge_is_constrained),
|
||||
Corefinement::No_mark<TriangleMesh>() );
|
||||
Ecm2 ecm2 = boost::choose_param( get_param(np2, edge_is_constrained),
|
||||
Ecm2 ecm2 = boost::choose_param( boost::get_param(np2, edge_is_constrained),
|
||||
Corefinement::No_mark<TriangleMesh>() );
|
||||
|
||||
typedef Corefinement::Ecm_bind<TriangleMesh, Ecm1, Ecm2> Ecm_in;
|
||||
|
|
|
|||
|
|
@ -237,10 +237,6 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND AND QGLVIEWER_FOUND)
|
|||
# special
|
||||
target_link_libraries(scene_polyhedron_transform_item scene_polyhedron_item)
|
||||
|
||||
add_item(scene_combinatorial_map_item Plugins/Operations_on_polyhedra/Scene_combinatorial_map_item.cpp)
|
||||
# special
|
||||
target_link_libraries(scene_combinatorial_map_item scene_polyhedron_item)
|
||||
|
||||
add_item(scene_polylines_item Scene_polylines_item.cpp)
|
||||
target_link_libraries(scene_polylines_item scene_basic_objects)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,5 @@ include( polyhedron_demo_macros )
|
|||
qt5_wrap_ui( clip_polyhedronUI_FILES Clip_polyhedron_plugin.ui )
|
||||
polyhedron_demo_plugin(clip_polyhedron_plugin Clip_polyhedron_plugin ${clip_polyhedronUI_FILES})
|
||||
target_link_libraries(clip_polyhedron_plugin scene_polyhedron_item scene_basic_objects)
|
||||
polyhedron_demo_plugin(corefinement_plugin Corefinement_plugin)
|
||||
target_link_libraries(corefinement_plugin scene_polyhedron_item scene_combinatorial_map_item scene_polylines_item)
|
||||
polyhedron_demo_plugin(intersection_plugin Intersection_plugin)
|
||||
target_link_libraries(intersection_plugin scene_polyhedron_item scene_polylines_item)
|
||||
polyhedron_demo_plugin(point_set_from_vertices_plugin Point_set_from_vertices_plugin)
|
||||
target_link_libraries(point_set_from_vertices_plugin scene_polyhedron_item scene_polygon_soup_item scene_points_with_normal_item)
|
||||
|
|
|
|||
|
|
@ -1,181 +0,0 @@
|
|||
#define CGAL_COREFINEMENT_DO_REPORT_SELF_INTERSECTIONS
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/corefinement_operations.h>
|
||||
#include <CGAL/bounding_box.h>
|
||||
#include "Scene_polyhedron_item.h"
|
||||
#include "Scene_combinatorial_map_item.h"
|
||||
#include "Polyhedron_type.h"
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
|
||||
|
||||
#include "Scene_polylines_item.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
#include <QMainWindow>
|
||||
#include <QApplication>
|
||||
#include <QTime>
|
||||
#include <QMessageBox>
|
||||
|
||||
//#define PRINT_EACH_VOLUME
|
||||
using namespace CGAL::Three;
|
||||
class Polyhedron_demo_corefinement_plugin :
|
||||
public QObject,
|
||||
public Polyhedron_demo_plugin_interface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
|
||||
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0")
|
||||
|
||||
public:
|
||||
|
||||
bool applicable(QAction*) const {
|
||||
return qobject_cast<Scene_polyhedron_item*>(scene->item(scene->mainSelectionIndex()));
|
||||
}
|
||||
|
||||
QList<QAction*> actions() const {
|
||||
return QList<QAction*>() << actionPolyhedronCorefinement_3;
|
||||
}
|
||||
|
||||
void init(QMainWindow* mw, CGAL::Three::Scene_interface* scene_interface, Messages_interface*) {
|
||||
this->scene = scene_interface;
|
||||
actionPolyhedronCorefinement_3 = new QAction("Polyhedra Corefinement (A/B)", mw);
|
||||
actionPolyhedronCorefinement_3->setProperty("subMenuName", "Operations on Polyhedra");
|
||||
if(actionPolyhedronCorefinement_3) {
|
||||
connect(actionPolyhedronCorefinement_3, SIGNAL(triggered()),
|
||||
this, SLOT(corefinement()));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
QAction* actionPolyhedronCorefinement_3;
|
||||
Scene_interface *scene;
|
||||
|
||||
public Q_SLOTS:
|
||||
void corefinement();
|
||||
|
||||
}; // end class Polyhedron_demo_corefinement_plugin
|
||||
|
||||
|
||||
struct Is_on_polyline{
|
||||
bool operator()(Polyhedron::Halfedge_handle he) const {
|
||||
return he->is_feature_edge();
|
||||
}
|
||||
};
|
||||
|
||||
struct Set_vertex_corner{
|
||||
template <typename Info>
|
||||
void add_info_to_node(int, Polyhedron*,const Info&) {
|
||||
}
|
||||
|
||||
void operator()(Polyhedron::Vertex_handle v, int, Polyhedron*) {
|
||||
++v->nb_of_feature_edges;
|
||||
}
|
||||
};
|
||||
|
||||
void Polyhedron_demo_corefinement_plugin::corefinement()
|
||||
{
|
||||
int indexA = scene->selectionAindex();
|
||||
int indexB = scene->selectionBindex();
|
||||
|
||||
Scene_polyhedron_item* itemA =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(indexA));
|
||||
Scene_polyhedron_item* itemB =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(indexB));
|
||||
if(!itemA || !itemB || itemA == itemB)
|
||||
{
|
||||
Q_FOREACH(int index, scene->selectionIndices()) {
|
||||
Scene_polyhedron_item* item =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(index));
|
||||
if(!item)
|
||||
return;
|
||||
}
|
||||
if(scene->selectionIndices().size() == 2) {
|
||||
indexA = scene->selectionIndices()[0];
|
||||
indexB = scene->selectionIndices()[1];
|
||||
itemA =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(indexA));
|
||||
itemB =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(indexB));
|
||||
}
|
||||
}
|
||||
std::vector<Polyhedron*> poly_ptrs;
|
||||
Q_FOREACH(int index, scene->selectionIndices()) {
|
||||
Scene_polyhedron_item* item =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(index));
|
||||
if(!item)
|
||||
return;
|
||||
else if(item != itemA) {
|
||||
poly_ptrs.push_back(item->polyhedron());
|
||||
if(poly_ptrs.back() == 0) return;
|
||||
}
|
||||
}
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
if(itemA && itemB && itemA != itemB) {
|
||||
|
||||
// perform Boolean operation
|
||||
QTime time;
|
||||
time.start();
|
||||
|
||||
//since the visitor modify input polyhedra, we make copies.
|
||||
Polyhedron A( *itemA->polyhedron() );
|
||||
Polyhedron B( *itemB->polyhedron() );
|
||||
|
||||
itemA->setVisible(false);
|
||||
itemB->setVisible(false);
|
||||
|
||||
Scene_polylines_item* new_item = new Scene_polylines_item();
|
||||
|
||||
#ifdef _COREFINEMENT_OUTPUT_IS_POLYHEDRON
|
||||
typedef CGAL::Polyhedron_corefinement<Polyhedron> Corefinement;
|
||||
Corefinement corefinement;
|
||||
|
||||
typedef std::list<std::pair<Polyhedron*,int> > Decomposition;
|
||||
Decomposition decomposition;
|
||||
|
||||
#ifndef PRINT_EACH_VOLUME
|
||||
int features=Corefinement::Join_tag+Corefinement::Intersection_tag+Corefinement::P_minus_Q_tag+Corefinement::Q_minus_P_tag;
|
||||
#else
|
||||
int features=Corefinement::Decomposition_tag;
|
||||
#endif
|
||||
corefinement(A, B, std::back_inserter(new_item->polylines),std::back_inserter(decomposition),features);
|
||||
|
||||
|
||||
for (Decomposition::iterator it=decomposition.begin();it!=decomposition.end();++it)
|
||||
{
|
||||
Polyhedron* new_poly=it->first;
|
||||
Scene_polyhedron_item* new_item_bool= new Scene_polyhedron_item(new_poly);
|
||||
new_item_bool->setName(
|
||||
QString::fromStdString(
|
||||
corefinement.get_type_str(itemA->name().toStdString(),itemB->name().toStdString(),it->second)
|
||||
)
|
||||
);
|
||||
scene->addItem(new_item_bool);
|
||||
}
|
||||
#else
|
||||
Scene_combinatorial_map_item* cmap_item = new Scene_combinatorial_map_item(scene,static_cast<void*>(&A));
|
||||
typedef CGAL::Corefinement::Combinatorial_map_output_builder<Polyhedron,Kernel> Output_builder;
|
||||
typedef CGAL::Node_visitor_refine_polyhedra<Polyhedron,Output_builder,Kernel> Split_visitor;
|
||||
cmap_item->m_combinatorial_map=boost::shared_ptr<Combinatorial_map_3>( new Combinatorial_map_3() );
|
||||
Split_visitor visitor( Output_builder(cmap_item->m_combinatorial_map) );
|
||||
CGAL::Intersection_of_Polyhedra_3<Polyhedron,Kernel,Split_visitor> polyline_intersections(visitor);
|
||||
polyline_intersections(A, B, std::back_inserter(new_item->polylines));
|
||||
cmap_item->setName(QString("%1_and_%2_corefined").arg(itemA->name()).arg(itemB->name()));
|
||||
scene->addItem(cmap_item);
|
||||
#endif
|
||||
new_item->setName(tr("boundary intersection"));
|
||||
new_item->setColor(Qt::green);
|
||||
new_item->setRenderingMode(Wireframe);
|
||||
scene->addItem(new_item);
|
||||
new_item->invalidateOpenGLBuffers();
|
||||
std::cout << "ok (" << time.elapsed() << " ms)" << std::endl;
|
||||
|
||||
}
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
#include "Corefinement_plugin.moc"
|
||||
|
|
@ -1,223 +0,0 @@
|
|||
#define CGAL_COREFINEMENT_DO_REPORT_SELF_INTERSECTIONS
|
||||
#define CGAL_USE_SEGMENT_APPROACH
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#ifdef CGAL_USE_SEGMENT_APPROACH
|
||||
#include <CGAL/intersection_of_Polyhedra_3.h>
|
||||
#else
|
||||
#include <CGAL/intersection_Polyhedron_3_Polyhedron_3.h>
|
||||
#endif
|
||||
#include <CGAL/iterator.h>
|
||||
#include <CGAL/bounding_box.h>
|
||||
#include "Scene_polyhedron_item.h"
|
||||
#include "Polyhedron_type.h"
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
|
||||
|
||||
#include "Scene_polylines_item.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <QString>
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
#include <QMainWindow>
|
||||
#include <QApplication>
|
||||
#include <QTime>
|
||||
#include <QMessageBox>
|
||||
using namespace CGAL::Three;
|
||||
class Polyhedron_demo_intersection_plugin :
|
||||
public QObject,
|
||||
public Polyhedron_demo_plugin_interface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
|
||||
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0")
|
||||
|
||||
public:
|
||||
|
||||
bool applicable(QAction*) const {
|
||||
return qobject_cast<Scene_polyhedron_item*>(scene->item(scene->mainSelectionIndex()));
|
||||
}
|
||||
|
||||
QList<QAction*> actions() const {
|
||||
return QList<QAction*>() << actionPolyhedronIntersection_3;
|
||||
}
|
||||
|
||||
void init(QMainWindow* mw, CGAL::Three::Scene_interface* scene_interface, Messages_interface*) {
|
||||
this->scene = scene_interface;
|
||||
actionPolyhedronIntersection_3 = new QAction("Intersect Polyhedra (A/B)", mw);
|
||||
actionPolyhedronIntersection_3->setProperty("subMenuName", "Operations on Polyhedra");
|
||||
if(actionPolyhedronIntersection_3) {
|
||||
connect(actionPolyhedronIntersection_3, SIGNAL(triggered()),
|
||||
this, SLOT(intersection()));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
QAction* actionPolyhedronIntersection_3;
|
||||
Scene_interface *scene;
|
||||
|
||||
public Q_SLOTS:
|
||||
void intersection();
|
||||
|
||||
}; // end class Polyhedron_demo_intersection_plugin
|
||||
|
||||
|
||||
#ifdef CGAL_USE_SEGMENT_APPROACH
|
||||
struct Is_on_polyline{
|
||||
bool operator()(Polyhedron::Halfedge_handle he) const {
|
||||
return he->is_feature_edge();
|
||||
}
|
||||
};
|
||||
|
||||
struct Set_vertex_corner{
|
||||
template <typename Info>
|
||||
void add_info_to_node(int, Polyhedron*,const Info&) {
|
||||
}
|
||||
|
||||
void operator()(Polyhedron::Vertex_handle v, int, Polyhedron*) {
|
||||
++v->nb_of_feature_edges;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
void Polyhedron_demo_intersection_plugin::intersection()
|
||||
{
|
||||
int indexA = scene->selectionAindex();
|
||||
int indexB = scene->selectionBindex();
|
||||
|
||||
Scene_polyhedron_item* itemA =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(indexA));
|
||||
Scene_polyhedron_item* itemB =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(indexB));
|
||||
if(!itemA || !itemB || itemA == itemB)
|
||||
{
|
||||
Q_FOREACH(int index, scene->selectionIndices()) {
|
||||
Scene_polyhedron_item* item =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(index));
|
||||
if(!item)
|
||||
return;
|
||||
}
|
||||
if(scene->selectionIndices().size() == 2) {
|
||||
indexA = scene->selectionIndices()[0];
|
||||
indexB = scene->selectionIndices()[1];
|
||||
itemA =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(indexA));
|
||||
itemB =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(indexB));
|
||||
}
|
||||
}
|
||||
#ifndef CGAL_USE_SEGMENT_APPROACH
|
||||
if(!itemA || !itemB || itemA == itemB)
|
||||
return;
|
||||
#else
|
||||
std::vector<Polyhedron*> poly_ptrs;
|
||||
Q_FOREACH(int index, scene->selectionIndices()) {
|
||||
Scene_polyhedron_item* item =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(index));
|
||||
if(!item)
|
||||
return;
|
||||
else if(item != itemA) {
|
||||
poly_ptrs.push_back(item->polyhedron());
|
||||
if(poly_ptrs.back() == 0) return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
Scene_polylines_item* new_item = new Scene_polylines_item();
|
||||
// perform Boolean operation
|
||||
QTime time;
|
||||
time.start();
|
||||
|
||||
#ifdef CGAL_USE_SEGMENT_APPROACH
|
||||
typedef CGAL::Node_visitor_for_polyline_split<Polyhedron,
|
||||
Is_on_polyline, Set_vertex_corner> Split_visitor;
|
||||
|
||||
CGAL::Intersection_of_Polyhedra_3<Polyhedron,
|
||||
Kernel,
|
||||
Split_visitor> polyline_intersections;
|
||||
|
||||
typedef std::pair<Polyhedron::Facet_handle,
|
||||
Polyhedron::Facet_handle> Pair_of_facet_handles;
|
||||
typedef std::vector<Pair_of_facet_handles> Polyline_info;
|
||||
typedef std::vector<Polyline_info> Polylines_infos;
|
||||
Polylines_infos polylines_infos;
|
||||
|
||||
typedef Scene_polylines_item::Polylines_container Polylines_container;
|
||||
typedef std::back_insert_iterator<Polylines_container> To_container;
|
||||
typedef std::back_insert_iterator<Polylines_infos> To_infos;
|
||||
To_container to_container(new_item->polylines);
|
||||
To_infos to_infos(polylines_infos);
|
||||
CGAL::Dispatch_output_iterator<
|
||||
CGAL::cpp11::tuple<Polylines_container::value_type,
|
||||
Polyline_info>,
|
||||
CGAL::cpp11::tuple<To_container,
|
||||
To_infos> > out_iterator(to_container,
|
||||
to_infos);
|
||||
|
||||
if(itemA && itemB && itemA != itemB) {
|
||||
Polyhedron* A = itemA->polyhedron();
|
||||
Polyhedron* B = itemB->polyhedron();
|
||||
polyline_intersections(*A, *B, out_iterator);
|
||||
} else {
|
||||
if(itemA) {
|
||||
Polyhedron* A = itemA->polyhedron();
|
||||
polyline_intersections(*A,
|
||||
poly_ptrs.begin(),
|
||||
poly_ptrs.end(),
|
||||
out_iterator,
|
||||
0);
|
||||
} else {
|
||||
polyline_intersections(poly_ptrs.begin(),
|
||||
poly_ptrs.end(),
|
||||
out_iterator,
|
||||
0);
|
||||
}
|
||||
}
|
||||
QStringList polylines_metadata;
|
||||
BOOST_FOREACH(Polyline_info& info, polylines_infos) {
|
||||
std::set<int> indices;
|
||||
BOOST_FOREACH(Pair_of_facet_handles p, info)
|
||||
{
|
||||
indices.insert(p.first->patch_id());
|
||||
indices.insert(p.second->patch_id());
|
||||
}
|
||||
QString metadata;
|
||||
BOOST_FOREACH(int index, indices) {
|
||||
metadata = metadata + QString(" %1").arg(index);
|
||||
}
|
||||
std::cerr << "new polyline metadata: " << qPrintable(metadata) << "\n";
|
||||
polylines_metadata << metadata;
|
||||
}
|
||||
new_item->setProperty("polylines metadata", polylines_metadata);
|
||||
new_item->setName(tr("intersection"));
|
||||
#else
|
||||
Polyhedron* A = itemA->polyhedron();
|
||||
Polyhedron* B = itemB->polyhedron();
|
||||
CGAL::intersection_Polyhedron_3_Polyhedron_3(*A, *B, std::back_inserter(new_item->polylines));
|
||||
|
||||
QString name = tr("%1 intersection %2");
|
||||
|
||||
new_item->setName(name.arg(itemA->name(), itemB->name()));
|
||||
itemA->setRenderingMode(Wireframe);
|
||||
itemB->setRenderingMode(Wireframe);
|
||||
scene->itemChanged(indexA);
|
||||
scene->itemChanged(indexB);
|
||||
#endif
|
||||
std::cout << "ok (" << time.elapsed() << " ms)" << std::endl;
|
||||
|
||||
if (new_item->polylines.empty())
|
||||
delete new_item;
|
||||
else{
|
||||
new_item->setColor(Qt::green);
|
||||
new_item->setRenderingMode(Wireframe);
|
||||
scene->addItem(new_item);
|
||||
new_item->invalidateOpenGLBuffers();
|
||||
}
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
#include "Intersection_plugin.moc"
|
||||
|
|
@ -1,579 +0,0 @@
|
|||
#include "Scene_combinatorial_map_item.h"
|
||||
#include "Scene_polyhedron_item.h"
|
||||
#include <CGAL/Three/Scene_interface.h>
|
||||
#include <CGAL/Three/Viewer_interface.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
#include <QtDebug>
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QKeyEvent>
|
||||
#include <CGAL/corefinement_operations.h>
|
||||
|
||||
struct Scene_combinatorial_map_item_priv
|
||||
{
|
||||
Scene_combinatorial_map_item_priv(CGAL::Three::Scene_interface* scene, void* ad_A, Scene_combinatorial_map_item* parent)
|
||||
:last_known_scene(scene),volume_to_display(0),exportSelectedVolume(NULL),address_of_A(ad_A)
|
||||
{
|
||||
item = parent;
|
||||
item->are_buffers_filled = false;
|
||||
nb_points = 0;
|
||||
nb_lines =0;
|
||||
nb_facets =0;
|
||||
}
|
||||
|
||||
Kernel::Vector_3 compute_face_normal(Combinatorial_map_3::Dart_const_handle adart) const;
|
||||
|
||||
template <class Predicate>
|
||||
void export_as_polyhedron(Predicate,const QString&) const;
|
||||
void initialize_buffers(CGAL::Three::Viewer_interface *viewer) const;
|
||||
void compute_elements(void) const;
|
||||
|
||||
Scene_combinatorial_map_item *item;
|
||||
enum VAOs {
|
||||
Edges = 0,
|
||||
Points,
|
||||
Facets,
|
||||
NbOfVaos
|
||||
};
|
||||
enum VBOs {
|
||||
Edges_vertices = 0,
|
||||
Points_vertices,
|
||||
Facets_vertices,
|
||||
Facets_normals,
|
||||
NbOfVbos
|
||||
};
|
||||
|
||||
CGAL::Three::Scene_interface* last_known_scene;
|
||||
std::size_t volume_to_display;
|
||||
QAction* exportSelectedVolume;
|
||||
void* address_of_A;
|
||||
|
||||
mutable QOpenGLShaderProgram *program;
|
||||
mutable std::vector<double> positions_lines;
|
||||
mutable std::vector<double> positions_points;
|
||||
mutable std::vector<double> positions_facets;
|
||||
mutable std::vector<double> normals;
|
||||
mutable std::size_t nb_lines;
|
||||
mutable std::size_t nb_points;
|
||||
mutable std::size_t nb_facets;
|
||||
};
|
||||
Scene_combinatorial_map_item::Scene_combinatorial_map_item(CGAL::Three::Scene_interface* scene,void* address){d = new Scene_combinatorial_map_item_priv(scene, address, this);}
|
||||
Scene_combinatorial_map_item::~Scene_combinatorial_map_item(){delete d;}
|
||||
|
||||
Scene_combinatorial_map_item* Scene_combinatorial_map_item::clone() const{return NULL;}
|
||||
|
||||
Kernel::Vector_3 Scene_combinatorial_map_item_priv::compute_face_normal(Combinatorial_map_3::Dart_const_handle adart) const
|
||||
{
|
||||
typedef Combinatorial_map_3::Dart_of_orbit_const_range<1> Dart_in_facet_range;
|
||||
typedef Kernel::Vector_3 Vector_3;
|
||||
Vector_3 normal = CGAL::NULL_VECTOR;
|
||||
|
||||
Dart_in_facet_range vertices=item->combinatorial_map().darts_of_orbit<1>(adart);
|
||||
Kernel::Point_3 points[3];
|
||||
int index=0;
|
||||
Dart_in_facet_range::const_iterator pit=vertices.begin();
|
||||
for (;pit!=vertices.end() && index!=3;++pit,++index ){
|
||||
points[index]=item->combinatorial_map().attribute<0>(pit)->point();
|
||||
}
|
||||
|
||||
if (index!=3) return normal;
|
||||
|
||||
do{
|
||||
Vector_3 n = CGAL::cross_product(points[2]-points[1],points[0]-points[1]);
|
||||
if (n != Vector_3(0,0,0) )
|
||||
normal = normal + (n / std::sqrt(n*n));
|
||||
points[0]=points[1];
|
||||
points[1]=points[2];
|
||||
if ( pit==vertices.end() ) break;
|
||||
|
||||
points[2]=item->combinatorial_map().attribute<0>(pit)->point();
|
||||
++pit;
|
||||
}while(true);
|
||||
|
||||
return normal == Vector_3(0,0,0)? normal : normal / std::sqrt(normal * normal);
|
||||
}
|
||||
|
||||
void Scene_combinatorial_map_item::set_next_volume(){
|
||||
//Update des vectors faits ici
|
||||
++d->volume_to_display;
|
||||
d->volume_to_display=d->volume_to_display%(combinatorial_map().attributes<3>().size()+1);
|
||||
are_buffers_filled = false;
|
||||
invalidateOpenGLBuffers();
|
||||
Q_EMIT itemChanged();
|
||||
|
||||
if (d->exportSelectedVolume!=NULL && ( d->volume_to_display==1 || d->volume_to_display==0 ) )
|
||||
d->exportSelectedVolume->setEnabled(!d->exportSelectedVolume->isEnabled());
|
||||
}
|
||||
|
||||
|
||||
template <class Predicate>
|
||||
void Scene_combinatorial_map_item_priv::export_as_polyhedron(Predicate pred,const QString& name) const {
|
||||
typedef Combinatorial_map_3::Dart_const_handle Dart_handle;
|
||||
typedef Combinatorial_map_3::One_dart_per_cell_range<3> One_dart_per_vol_range;
|
||||
typedef CGAL::internal::Import_volume_as_polyhedron<Polyhedron::HalfedgeDS> Volume_import_modifier;
|
||||
|
||||
std::vector<Dart_handle> darts;
|
||||
One_dart_per_vol_range cell_range=item->combinatorial_map().template one_dart_per_cell<3>();
|
||||
|
||||
|
||||
for (One_dart_per_vol_range::const_iterator it = cell_range.begin();it!= cell_range.end() ; ++it )
|
||||
if ( pred(it) ){
|
||||
darts.push_back(it);
|
||||
if (Predicate::only_one_run) break;
|
||||
}
|
||||
|
||||
if (!darts.empty())
|
||||
{
|
||||
Volume_import_modifier modifier=Predicate::swap_orientation?
|
||||
Volume_import_modifier(item->combinatorial_map(),darts.begin(),darts.end(),Predicate::swap_orientation):
|
||||
Volume_import_modifier(item->combinatorial_map(),darts.begin(),darts.end());
|
||||
|
||||
Polyhedron* new_poly=new Polyhedron();
|
||||
new_poly->delegate(modifier);
|
||||
Scene_polyhedron_item* new_item = new Scene_polyhedron_item(new_poly);
|
||||
new_item->setName(name);
|
||||
last_known_scene->addItem(new_item);
|
||||
}
|
||||
}
|
||||
|
||||
struct Select_volume{
|
||||
static const bool only_one_run=true;
|
||||
static const bool swap_orientation=false;
|
||||
Select_volume(std::size_t i):volume_to_select(i),index(0){}
|
||||
template <class Dart_handle>
|
||||
bool operator() (Dart_handle){
|
||||
return ++index==volume_to_select;
|
||||
}
|
||||
private:
|
||||
std::size_t volume_to_select;
|
||||
std::size_t index;
|
||||
};
|
||||
|
||||
void Scene_combinatorial_map_item::export_current_volume_as_polyhedron() const {
|
||||
if (d->volume_to_display==0) return; //no volume selected
|
||||
|
||||
Select_volume predicate(d->volume_to_display);
|
||||
d->export_as_polyhedron(predicate,QString("%1_%2").arg(this->name()).arg(d->volume_to_display-1));
|
||||
}
|
||||
|
||||
struct Select_union{
|
||||
const Combinatorial_map_3& map;
|
||||
Select_union(const Combinatorial_map_3& m) : map(m) {}
|
||||
static const bool only_one_run=false;
|
||||
static const bool swap_orientation=true;
|
||||
template <class Dart_handle>
|
||||
bool operator() (Dart_handle d){ return map.template attribute<3>(d)->info().outside.size()==2; }
|
||||
};
|
||||
|
||||
struct Select_inter{
|
||||
const Combinatorial_map_3& map;
|
||||
Select_inter(const Combinatorial_map_3& m) : map(m) {}
|
||||
static const bool only_one_run=false;
|
||||
static const bool swap_orientation=false;
|
||||
template <class Dart_handle>
|
||||
bool operator() (Dart_handle d){ return map.template attribute<3>(d)->info().inside.size()==2; }
|
||||
};
|
||||
|
||||
struct Select_A_minus_B{
|
||||
const Combinatorial_map_3& map;
|
||||
static const bool only_one_run=false;
|
||||
static const bool swap_orientation=false;
|
||||
Select_A_minus_B(const Combinatorial_map_3& m, void* address):map(m), address_of_A(address){}
|
||||
template <class Dart_handle>
|
||||
bool operator() (Dart_handle d){
|
||||
return map.template attribute<3>(d)->info().inside.size()==1 &&
|
||||
static_cast<void*>(*map.template attribute<3>(d)->info().inside.begin())==address_of_A;
|
||||
}
|
||||
private:
|
||||
void* address_of_A;
|
||||
};
|
||||
|
||||
struct Select_B_minus_A{
|
||||
const Combinatorial_map_3& map;
|
||||
static const bool only_one_run=false;
|
||||
static const bool swap_orientation=false;
|
||||
Select_B_minus_A(const Combinatorial_map_3& m, void* address):map(m), address_of_A(address){}
|
||||
template <class Dart_handle>
|
||||
bool operator() (Dart_handle d){
|
||||
return map.template attribute<3>(d)->info().inside.size()==1 &&
|
||||
static_cast<void*>(*map.template attribute<3>(d)->info().inside.begin())!=address_of_A;
|
||||
}
|
||||
private:
|
||||
void* address_of_A;
|
||||
};
|
||||
|
||||
void Scene_combinatorial_map_item::export_union_as_polyhedron() const {
|
||||
d->export_as_polyhedron(Select_union(this->combinatorial_map()),QString("%1_union_%2").arg("A").arg("B"));
|
||||
}
|
||||
void Scene_combinatorial_map_item::export_intersection_as_polyhedron() const{
|
||||
d->export_as_polyhedron(Select_inter(this->combinatorial_map()),QString("%1_inter_%2").arg("A").arg("B"));
|
||||
}
|
||||
void Scene_combinatorial_map_item::export_A_minus_B_as_polyhedron() const{
|
||||
Select_A_minus_B predicate(this->combinatorial_map(),d->address_of_A);
|
||||
d->export_as_polyhedron(predicate,QString("%1_minus_%2").arg("A").arg("B"));
|
||||
}
|
||||
void Scene_combinatorial_map_item::export_B_minus_A_as_polyhedron() const{
|
||||
Select_B_minus_A predicate(this->combinatorial_map(),d->address_of_A);
|
||||
d->export_as_polyhedron(predicate,QString("%1_minus_%2").arg("B").arg("A"));
|
||||
}
|
||||
|
||||
QMenu* Scene_combinatorial_map_item::contextMenu()
|
||||
{
|
||||
const char* prop_name = "Menu modified by Scene_combinatorial_map_item.";
|
||||
|
||||
QMenu* menu = Scene_item::contextMenu();
|
||||
|
||||
// Use dynamic properties:
|
||||
// http://doc.qt.io/qt-5/qobject.html#property
|
||||
bool menuChanged = menu->property(prop_name).toBool();
|
||||
|
||||
if(!menuChanged) {
|
||||
QAction* actionSelectNextVolume =
|
||||
menu->addAction(tr("Iterate over volumes"));
|
||||
actionSelectNextVolume->setObjectName("actionSelectNextVolume");
|
||||
connect(actionSelectNextVolume, SIGNAL(triggered()),this, SLOT(set_next_volume()));
|
||||
|
||||
d->exportSelectedVolume =
|
||||
menu->addAction(tr("Export current volume as polyhedron"));
|
||||
d->exportSelectedVolume->setObjectName("exportSelectedVolume");
|
||||
connect(d->exportSelectedVolume, SIGNAL(triggered()),this, SLOT(export_current_volume_as_polyhedron()));
|
||||
d->exportSelectedVolume->setEnabled(d->volume_to_display!=0);
|
||||
menu->setProperty(prop_name, true);
|
||||
|
||||
if(is_from_corefinement()){
|
||||
//Export union as polyhedron
|
||||
QAction* exportUnion =
|
||||
menu->addAction(tr("Export union as polyhedron"));
|
||||
exportUnion->setObjectName("exportUnion");
|
||||
connect(exportUnion, SIGNAL(triggered()),this, SLOT(export_union_as_polyhedron()));
|
||||
|
||||
//Export intersection as polyhedron
|
||||
QAction* exportIntersection =
|
||||
menu->addAction(tr("Export intersection as polyhedron"));
|
||||
exportIntersection->setObjectName("exportIntersection");
|
||||
connect(exportIntersection, SIGNAL(triggered()),this, SLOT(export_intersection_as_polyhedron()));
|
||||
|
||||
//Export A minus B as polyhedron
|
||||
QAction* exportAMinusB =
|
||||
menu->addAction(tr("Export A minus B as polyhedron"));
|
||||
exportAMinusB->setObjectName("exportAMinusB");
|
||||
connect(exportAMinusB, SIGNAL(triggered()),this, SLOT(export_A_minus_B_as_polyhedron()));
|
||||
|
||||
//Export B minus A as polyhedron
|
||||
QAction* exportBMinusA =
|
||||
menu->addAction(tr("Export B minus A as polyhedron"));
|
||||
exportBMinusA->setObjectName("exportBMinusA");
|
||||
connect(exportBMinusA, SIGNAL(triggered()),this, SLOT(export_B_minus_A_as_polyhedron()));
|
||||
|
||||
}
|
||||
}
|
||||
return menu;
|
||||
}
|
||||
|
||||
bool Scene_combinatorial_map_item::keyPressEvent(QKeyEvent* e){
|
||||
if (e->key()==Qt::Key_N){
|
||||
set_next_volume();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Scene_combinatorial_map_item_priv::compute_elements(void) const{
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
positions_facets.resize(0);
|
||||
normals.resize(0);
|
||||
positions_lines.resize(0);
|
||||
positions_points.resize(0);
|
||||
|
||||
//Facets
|
||||
{
|
||||
std::size_t index = 0;
|
||||
Combinatorial_map_3::size_type voltreated
|
||||
= item->combinatorial_map().get_new_mark();
|
||||
Combinatorial_map_3::size_type facetreated
|
||||
= item->combinatorial_map().get_new_mark();
|
||||
Combinatorial_map_3::Dart_const_range::const_iterator
|
||||
darts_it=item->combinatorial_map().darts().begin(), darts_end=item->combinatorial_map().darts().end();
|
||||
for( ; darts_it!=darts_end; ++darts_it)
|
||||
{
|
||||
if ( !item->combinatorial_map().is_marked(darts_it,voltreated) )
|
||||
{
|
||||
++index;
|
||||
//iterate over all the darts of the volume
|
||||
Combinatorial_map_3::Dart_of_cell_const_range<3>::const_iterator
|
||||
vol_it=item->combinatorial_map().darts_of_cell<3>(darts_it).begin(),
|
||||
vol_end=item->combinatorial_map().darts_of_cell<3>(darts_it).end();
|
||||
if ( volume_to_display!=0 && index!=volume_to_display )
|
||||
{
|
||||
//only mark darts if the volume is not the one to display
|
||||
for ( ;vol_it!=vol_end; ++vol_it )
|
||||
{
|
||||
item->combinatorial_map().mark(vol_it,facetreated);
|
||||
item->combinatorial_map().mark(vol_it, voltreated);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( ;vol_it!=vol_end; ++vol_it )
|
||||
{
|
||||
if ( !item->combinatorial_map().is_marked(vol_it,facetreated) )
|
||||
{
|
||||
Kernel::Vector_3 normal = compute_face_normal(vol_it);
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
normals.push_back(normal.x());
|
||||
normals.push_back(normal.y());
|
||||
normals.push_back(normal.z());
|
||||
}
|
||||
|
||||
//iterate over all darts of facets
|
||||
for ( Combinatorial_map_3::Dart_of_orbit_const_range<1>::const_iterator
|
||||
face_it=item->combinatorial_map().darts_of_orbit<1>(vol_it).begin(),
|
||||
face_end=item->combinatorial_map().darts_of_orbit<1>(vol_it).end();
|
||||
face_it!=face_end; ++face_it)
|
||||
{
|
||||
const Kernel::Point_3& p= item->combinatorial_map().attribute<0>(face_it)->point();
|
||||
positions_facets.push_back(p.x());
|
||||
positions_facets.push_back(p.y());
|
||||
positions_facets.push_back(p.z());
|
||||
item->combinatorial_map().mark(face_it,facetreated);
|
||||
item->combinatorial_map().mark(face_it, voltreated);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( index==volume_to_display ) break;
|
||||
}
|
||||
}
|
||||
//mark remaining darts to have an O(1) free_mark
|
||||
for( ; darts_it!=darts_end; ++darts_it)
|
||||
{
|
||||
item->combinatorial_map().mark(darts_it, facetreated);
|
||||
item->combinatorial_map().mark(darts_it, voltreated);
|
||||
}
|
||||
|
||||
item->combinatorial_map().free_mark(facetreated);
|
||||
item->combinatorial_map().free_mark(voltreated);
|
||||
}
|
||||
|
||||
//edges
|
||||
{
|
||||
|
||||
typedef Combinatorial_map_3::One_dart_per_cell_range<1,3> Edge_darts;
|
||||
Edge_darts darts=item->combinatorial_map().one_dart_per_cell<1>();
|
||||
for (Edge_darts::const_iterator dit=darts.begin();dit!=darts.end();++dit){
|
||||
CGAL_assertion(!item->combinatorial_map().is_free(dit,1));
|
||||
const Kernel::Point_3& a = item->combinatorial_map().attribute<0>(dit)->point();
|
||||
const Kernel::Point_3& b = item->combinatorial_map().attribute<0>(item->combinatorial_map().beta(dit,1))->point();
|
||||
positions_lines.push_back(a.x());
|
||||
positions_lines.push_back(a.y());
|
||||
positions_lines.push_back(a.z());
|
||||
|
||||
positions_lines.push_back(b.x());
|
||||
positions_lines.push_back(b.y());
|
||||
positions_lines.push_back(b.z());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//points
|
||||
{
|
||||
typedef Combinatorial_map_3::Attribute_const_range<0>::type Point_range;
|
||||
const Point_range& points=item->combinatorial_map().attributes<0>();
|
||||
for(Point_range::const_iterator pit=boost::next(points.begin());pit!=points.end();++pit){
|
||||
const Kernel::Point_3& p=pit->point();
|
||||
positions_points.push_back(p.x());
|
||||
positions_points.push_back(p.y());
|
||||
positions_points.push_back(p.z());
|
||||
}
|
||||
|
||||
}
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
|
||||
|
||||
void Scene_combinatorial_map_item_priv::initialize_buffers(CGAL::Three::Viewer_interface *viewer) const
|
||||
{
|
||||
//vao for the edges
|
||||
{
|
||||
program = item->getShaderProgram(Scene_combinatorial_map_item::PROGRAM_WITHOUT_LIGHT, viewer);
|
||||
program->bind();
|
||||
|
||||
item->vaos[Scene_combinatorial_map_item_priv::Edges]->bind();
|
||||
item->buffers[Scene_combinatorial_map_item_priv::Edges_vertices].bind();
|
||||
item->buffers[Scene_combinatorial_map_item_priv::Edges_vertices].allocate(positions_lines.data(),
|
||||
static_cast<int>(positions_lines.size()*sizeof(double)));
|
||||
program->enableAttributeArray("vertex");
|
||||
program->setAttributeBuffer("vertex",GL_DOUBLE,0,3);
|
||||
item->buffers[Scene_combinatorial_map_item_priv::Edges_vertices].release();
|
||||
nb_lines = positions_lines.size();
|
||||
positions_lines.resize(0);
|
||||
std::vector<double>(positions_lines).swap(positions_lines);
|
||||
item->vaos[Scene_combinatorial_map_item_priv::Edges]->release();
|
||||
program->release();
|
||||
}
|
||||
//vao for the points
|
||||
{
|
||||
program = item->getShaderProgram(Scene_combinatorial_map_item::PROGRAM_WITHOUT_LIGHT, viewer);
|
||||
program->bind();
|
||||
|
||||
item->vaos[Scene_combinatorial_map_item_priv::Points]->bind();
|
||||
item->buffers[Scene_combinatorial_map_item_priv::Points_vertices].bind();
|
||||
item->buffers[Scene_combinatorial_map_item_priv::Points_vertices].allocate(positions_points.data(),
|
||||
static_cast<int>(positions_points.size()*sizeof(double)));
|
||||
program->enableAttributeArray("vertex");
|
||||
program->setAttributeBuffer("vertex",GL_DOUBLE,0,3);
|
||||
item->buffers[Scene_combinatorial_map_item_priv::Points_vertices].release();
|
||||
item->vaos[Scene_combinatorial_map_item_priv::Points]->release();
|
||||
nb_points = positions_points.size();
|
||||
positions_points.resize(0);
|
||||
std::vector<double>(positions_points).swap(positions_points);
|
||||
program->release();
|
||||
}
|
||||
//vao for the facets
|
||||
{
|
||||
program = item->getShaderProgram(Scene_combinatorial_map_item::PROGRAM_WITH_LIGHT, viewer);
|
||||
program->bind();
|
||||
|
||||
item->vaos[Scene_combinatorial_map_item_priv::Facets]->bind();
|
||||
item->buffers[Scene_combinatorial_map_item_priv::Facets_vertices].bind();
|
||||
item->buffers[Scene_combinatorial_map_item_priv::Facets_vertices].allocate(positions_facets.data(),
|
||||
static_cast<int>(positions_facets.size()*sizeof(double)));
|
||||
program->enableAttributeArray("vertex");
|
||||
program->setAttributeBuffer("vertex",GL_DOUBLE,0,3);
|
||||
item->buffers[Scene_combinatorial_map_item_priv::Facets_vertices].release();
|
||||
|
||||
item->buffers[Scene_combinatorial_map_item_priv::Facets_normals].bind();
|
||||
item->buffers[Scene_combinatorial_map_item_priv::Facets_normals].allocate(normals.data(),
|
||||
static_cast<int>(normals.size()*sizeof(double)));
|
||||
program->enableAttributeArray("normals");
|
||||
program->setAttributeBuffer("normals",GL_DOUBLE,0,3);
|
||||
item->buffers[Scene_combinatorial_map_item_priv::Facets_normals].release();
|
||||
nb_facets = positions_facets.size();
|
||||
positions_facets.resize(0);
|
||||
std::vector<double>(positions_facets).swap(positions_facets);
|
||||
normals.resize(0);
|
||||
std::vector<double>(normals).swap(normals);
|
||||
item->vaos[Scene_combinatorial_map_item_priv::Facets]->release();
|
||||
program->release();
|
||||
}
|
||||
item->are_buffers_filled = true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool Scene_combinatorial_map_item::isEmpty() const {return combinatorial_map().number_of_darts()==0;}
|
||||
|
||||
void
|
||||
Scene_combinatorial_map_item::compute_bbox() const {
|
||||
typedef Combinatorial_map_3::Attribute_const_range<0>::type Point_range;
|
||||
const Point_range& points=combinatorial_map().attributes<0>();
|
||||
CGAL::Bbox_3 bbox=points.begin()->point().bbox();
|
||||
for(Point_range::const_iterator pit=boost::next(points.begin());pit!=points.end();++pit)
|
||||
bbox=bbox+pit->point().bbox();
|
||||
_bbox = Bbox(bbox.xmin(),bbox.ymin(),bbox.zmin(),
|
||||
bbox.xmax(),bbox.ymax(),bbox.zmax());
|
||||
}
|
||||
|
||||
|
||||
QString Scene_combinatorial_map_item::toolTip() const{
|
||||
if(!m_combinatorial_map)
|
||||
return QString();
|
||||
|
||||
std::vector<unsigned int> cells(5);
|
||||
for (unsigned int i=0; i<=4; ++i)
|
||||
cells[i]=i;
|
||||
std::vector<unsigned int> res = combinatorial_map().count_cells(cells);
|
||||
if (d->volume_to_display==0)
|
||||
return QObject::tr("<p>Combinatorial_map_3 <b>%1</b> (mode: %8, color: %9)</p>"
|
||||
"<p>Number of darts: %2<br />"
|
||||
"Number of vertices: %3<br />"
|
||||
"Number of edges: %4<br />"
|
||||
"Number of facets: %5<br />"
|
||||
"Number of volumes: %6<br />"
|
||||
"Number of connected components: %7</p>")
|
||||
.arg(this->name())
|
||||
.arg(combinatorial_map().number_of_darts())
|
||||
.arg(res[0])
|
||||
.arg(res[1])
|
||||
.arg(res[2])
|
||||
.arg(res[3])
|
||||
.arg(res[4])
|
||||
.arg(this->renderingModeName())
|
||||
.arg(this->color().name());
|
||||
return QObject::tr("<p>Combinatorial_map_3 <b>%1</b> (mode: %8, color: %9)</p>"
|
||||
"<p>Number of darts: %2<br />"
|
||||
"Number of vertices: %3<br />"
|
||||
"Number of edges: %4<br />"
|
||||
"Number of facets: %5<br />"
|
||||
"Number of volumes: %6<br />"
|
||||
"Number of connected components: %7 <br />"
|
||||
"Currently Displaying facets of volume: %10 </p>")
|
||||
.arg(this->name())
|
||||
.arg(combinatorial_map().number_of_darts())
|
||||
.arg(res[0])
|
||||
.arg(res[1])
|
||||
.arg(res[2])
|
||||
.arg(res[3])
|
||||
.arg(res[4])
|
||||
.arg(this->renderingModeName())
|
||||
.arg(this->color().name())
|
||||
.arg(d->volume_to_display-1);
|
||||
}
|
||||
|
||||
|
||||
void Scene_combinatorial_map_item::draw(CGAL::Three::Viewer_interface* viewer) const
|
||||
{
|
||||
if(!are_buffers_filled)
|
||||
{
|
||||
d->compute_elements();
|
||||
d->initialize_buffers(viewer);
|
||||
}
|
||||
vaos[Scene_combinatorial_map_item_priv::Facets]->bind();
|
||||
d->program=getShaderProgram(PROGRAM_WITH_LIGHT);
|
||||
attribBuffers(viewer,PROGRAM_WITH_LIGHT);
|
||||
d->program->bind();
|
||||
d->program->setAttributeValue("colors", this->color());
|
||||
viewer->glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(d->nb_facets/3));
|
||||
vaos[Scene_combinatorial_map_item_priv::Facets]->release();
|
||||
d->program->release();
|
||||
}
|
||||
void Scene_combinatorial_map_item::drawEdges(CGAL::Three::Viewer_interface* viewer) const
|
||||
{
|
||||
if(!are_buffers_filled)
|
||||
{
|
||||
d->compute_elements();
|
||||
d->initialize_buffers(viewer);
|
||||
}
|
||||
vaos[Scene_combinatorial_map_item_priv::Edges]->bind();
|
||||
d->program=getShaderProgram(PROGRAM_WITHOUT_LIGHT);
|
||||
attribBuffers(viewer,PROGRAM_WITHOUT_LIGHT);
|
||||
d->program->bind();
|
||||
d->program->setAttributeValue("colors", this->color());
|
||||
viewer->glDrawArrays(GL_LINES, 0, static_cast<GLsizei>(d->nb_lines/3));
|
||||
vaos[Scene_combinatorial_map_item_priv::Edges]->release();
|
||||
d->program->release();
|
||||
|
||||
}
|
||||
void Scene_combinatorial_map_item::drawPoints(CGAL::Three::Viewer_interface* viewer) const
|
||||
{
|
||||
if(!are_buffers_filled)
|
||||
{
|
||||
d->compute_elements();
|
||||
d->initialize_buffers(viewer);
|
||||
}
|
||||
vaos[Scene_combinatorial_map_item_priv::Points]->bind();
|
||||
d->program=getShaderProgram(PROGRAM_WITHOUT_LIGHT);
|
||||
attribBuffers(viewer,PROGRAM_WITHOUT_LIGHT);
|
||||
d->program->bind();
|
||||
d->program->setAttributeValue("colors", this->color());
|
||||
viewer->glDrawArrays(GL_POINTS, 0, static_cast<GLsizei>(d->nb_points/3));
|
||||
vaos[Scene_combinatorial_map_item_priv::Points]->release();
|
||||
d->program->release();
|
||||
}
|
||||
|
||||
bool Scene_combinatorial_map_item::is_from_corefinement() const{return d->address_of_A!=NULL;}
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
#ifndef SCENE_COMBINATORIAL_MAP_ITEM_H
|
||||
#define SCENE_COMBINATORIAL_MAP_ITEM_H
|
||||
|
||||
//=========
|
||||
#include <CGAL/internal/corefinement/Combinatorial_map_for_corefinement.h>
|
||||
#include "Scene_combinatorial_map_item_config.h"
|
||||
#include <iostream>
|
||||
#include <QOpenGLBuffer>
|
||||
#include <QOpenGLShader>
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include "Polyhedron_type.h"
|
||||
#include <CGAL/Three/Scene_item.h>
|
||||
typedef CGAL::internal_IOP::Item_with_points_and_volume_info<Kernel,Polyhedron> Items;
|
||||
typedef CGAL::Combinatorial_map<3,Items> Combinatorial_map_3;
|
||||
//=========
|
||||
struct Scene_combinatorial_map_item_priv;
|
||||
class QMenu;
|
||||
class QAction;
|
||||
namespace CGAL { namespace Three{
|
||||
class Scene_interface;
|
||||
}}
|
||||
class Scene_polyhedron_item;
|
||||
class Viewer_interface;
|
||||
|
||||
class SCENE_COMBINATORIAL_MAP_ITEM_EXPORT Scene_combinatorial_map_item
|
||||
: public CGAL::Three::Scene_item
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Scene_combinatorial_map_item(CGAL::Three::Scene_interface*,void* ad_A=NULL);
|
||||
~Scene_combinatorial_map_item();
|
||||
|
||||
Scene_combinatorial_map_item* clone() const;
|
||||
// Function to override the context menu
|
||||
QMenu* contextMenu();
|
||||
|
||||
// bool load(std::istream& in);
|
||||
// void load(Scene_polyhedron_item*);
|
||||
// bool save(std::ostream& out) const;
|
||||
|
||||
QString toolTip() const;
|
||||
|
||||
// Indicate if rendering mode is supported
|
||||
virtual bool supportsRenderingMode(RenderingMode m) const { return (m != Gouraud && m!=PointsPlusNormals && m!=Splatting && m!=ShadedPoints); } // CHECK THIS!
|
||||
//Event handling
|
||||
virtual bool keyPressEvent(QKeyEvent*);
|
||||
//drawing of the scene
|
||||
virtual void drawEdges(CGAL::Three::Viewer_interface* viewer) const;
|
||||
virtual void drawPoints(CGAL::Three::Viewer_interface*) const;
|
||||
virtual void draw(CGAL::Three::Viewer_interface*) const;
|
||||
|
||||
bool isFinite() const { return true; }
|
||||
bool is_from_corefinement() const;
|
||||
bool isEmpty() const;
|
||||
void compute_bbox() const;
|
||||
|
||||
const Combinatorial_map_3& combinatorial_map() const
|
||||
{
|
||||
return *m_combinatorial_map;
|
||||
}
|
||||
|
||||
Combinatorial_map_3& combinatorial_map()
|
||||
{
|
||||
return *m_combinatorial_map;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Combinatorial_map_3> m_combinatorial_map;
|
||||
|
||||
|
||||
public Q_SLOTS:
|
||||
void set_next_volume();
|
||||
void export_current_volume_as_polyhedron() const;
|
||||
void export_union_as_polyhedron() const;
|
||||
void export_intersection_as_polyhedron() const;
|
||||
void export_A_minus_B_as_polyhedron() const;
|
||||
void export_B_minus_A_as_polyhedron() const;
|
||||
protected:
|
||||
friend struct Scene_combinatorial_map_item_priv;
|
||||
Scene_combinatorial_map_item_priv* d;
|
||||
|
||||
}; // end class Scene_combinatorial_map_item
|
||||
|
||||
#endif // SCENE_COMBINATORIAL_MAP_ITEM_H
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef SCENE_COMBINATORIAL_MAP_ITEM_CONFIG_H
|
||||
#define SCENE_COMBINATORIAL_MAP_ITEM_CONFIG_H
|
||||
|
||||
#ifdef scene_combinatorial_map_item_EXPORTS
|
||||
# define SCENE_COMBINATORIAL_MAP_ITEM_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
# define SCENE_COMBINATORIAL_MAP_ITEM_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
#endif // SCENE_COMBINATORIAL_MAP_ITEM_CONFIG_H
|
||||
|
|
@ -69,6 +69,12 @@ target_link_libraries(self_intersection_plugin scene_polyhedron_item scene_polyh
|
|||
polyhedron_demo_plugin(triangulate_facets_plugin Triangulate_facets_plugin)
|
||||
target_link_libraries(triangulate_facets_plugin scene_polyhedron_item)
|
||||
|
||||
polyhedron_demo_plugin(corefinement_plugin Corefinement_plugin)
|
||||
target_link_libraries(corefinement_plugin scene_polyhedron_item)
|
||||
|
||||
polyhedron_demo_plugin(surface_intersection_plugin Surface_intersection_plugin)
|
||||
target_link_libraries(surface_intersection_plugin scene_polyhedron_item scene_polylines_item)
|
||||
|
||||
polyhedron_demo_plugin(repair_polyhedron_plugin Repair_polyhedron_plugin)
|
||||
target_link_libraries(repair_polyhedron_plugin scene_polyhedron_item)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,228 @@
|
|||
#include <QApplication>
|
||||
#include <QMainWindow>
|
||||
#include <QAction>
|
||||
#include "Messages_interface.h"
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_helper.h>
|
||||
#include "Scene_polyhedron_item.h"
|
||||
#include "Polyhedron_type.h"
|
||||
|
||||
#include <CGAL/Polygon_mesh_processing/corefinement.h>
|
||||
|
||||
using namespace CGAL::Three;
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
class Polyhedron_demo_corefinement_plugin :
|
||||
public QObject,
|
||||
public Polyhedron_demo_plugin_helper
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
|
||||
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0")
|
||||
|
||||
enum bool_op {CRF_UNION, CRF_INTER, CRF_MINUS, CRF_MINUS_OP};
|
||||
|
||||
public:
|
||||
|
||||
void init(QMainWindow* mainWindow,
|
||||
CGAL::Three::Scene_interface* scene_interface,
|
||||
Messages_interface* m) {
|
||||
this->scene = scene_interface;
|
||||
this->mw = mainWindow;
|
||||
this->messages = m;
|
||||
actionCorefine = new QAction("Corefine", mw);
|
||||
actionCorefine->setProperty("subMenuName","Polygon Mesh Processing/Corefinement");
|
||||
if(actionCorefine)
|
||||
connect(actionCorefine, SIGNAL(triggered()), this, SLOT(corefine()));
|
||||
|
||||
actionUnion = new QAction("Compute Union", mw);
|
||||
actionUnion->setProperty("subMenuName","Polygon Mesh Processing/Corefinement");
|
||||
if(actionUnion)
|
||||
connect(actionUnion, SIGNAL(triggered()), this, SLOT(corefine_and_union()));
|
||||
|
||||
actionInter = new QAction("Compute Intersection", mw);
|
||||
actionInter->setProperty("subMenuName","Polygon Mesh Processing/Corefinement");
|
||||
if(actionInter)
|
||||
connect(actionInter, SIGNAL(triggered()), this, SLOT(corefine_and_inter()));
|
||||
|
||||
actionDiff = new QAction("Compute Difference", mw);
|
||||
actionDiff->setProperty("subMenuName","Polygon Mesh Processing/Corefinement");
|
||||
if(actionDiff)
|
||||
connect(actionDiff, SIGNAL(triggered()), this, SLOT(corefine_and_diff()));
|
||||
|
||||
actionDiffRev = new QAction("Compute Opposite Difference", mw);
|
||||
actionDiffRev->setProperty("subMenuName","Polygon Mesh Processing/Corefinement");
|
||||
if(actionDiffRev)
|
||||
connect(actionDiffRev, SIGNAL(triggered()), this, SLOT(corefine_and_diff_rev()));
|
||||
};
|
||||
|
||||
QList<QAction*> actions() const {
|
||||
return QList<QAction*>() << actionCorefine
|
||||
<< actionUnion
|
||||
<< actionInter
|
||||
<< actionDiff
|
||||
<< actionDiffRev;
|
||||
}
|
||||
|
||||
bool applicable(QAction*) const {
|
||||
int nb_selected=0;
|
||||
Q_FOREACH(CGAL::Three::Scene_interface::Item_id index, scene->selectionIndices())
|
||||
if ( qobject_cast<Scene_polyhedron_item*>(scene->item(index)) )
|
||||
++nb_selected;
|
||||
return nb_selected==2;
|
||||
}
|
||||
|
||||
public Q_SLOTS:
|
||||
void corefine() {
|
||||
Scene_polyhedron_item* first_item = NULL;
|
||||
Q_FOREACH(CGAL::Three::Scene_interface::Item_id index, scene->selectionIndices())
|
||||
{
|
||||
Scene_polyhedron_item* item =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(index));
|
||||
|
||||
if(item)
|
||||
{
|
||||
if (first_item==NULL)
|
||||
{
|
||||
first_item = item;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!first_item->polyhedron()->is_pure_triangle()) {
|
||||
messages->warning(tr("The polyhedron \"%1\" is not triangulated.")
|
||||
.arg(first_item->name()));
|
||||
return;
|
||||
}
|
||||
if(!item->polyhedron()->is_pure_triangle()) {
|
||||
messages->warning(tr("The polyhedron \"%1\" is not triangulated.")
|
||||
.arg(item->name()));
|
||||
return;
|
||||
}
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
PMP::corefine(*first_item->polyhedron(), *item->polyhedron());
|
||||
first_item->invalidateOpenGLBuffers();
|
||||
item->invalidateOpenGLBuffers();
|
||||
scene->itemChanged(item);
|
||||
scene->itemChanged(first_item);
|
||||
// default cursor
|
||||
QApplication::restoreOverrideCursor();
|
||||
break;
|
||||
} // end of if(item)
|
||||
} // end of the loop on the selected items
|
||||
}
|
||||
|
||||
|
||||
void corefine_and_bool_op(bool_op op)
|
||||
{
|
||||
Scene_polyhedron_item* first_item = NULL;
|
||||
Q_FOREACH(CGAL::Three::Scene_interface::Item_id index, scene->selectionIndices())
|
||||
{
|
||||
Scene_polyhedron_item* item =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(index));
|
||||
|
||||
if(item)
|
||||
{
|
||||
if (first_item==NULL)
|
||||
{
|
||||
first_item = item;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!first_item->polyhedron()->is_pure_triangle()) {
|
||||
messages->warning(tr("The polyhedron \"%1\" is not triangulated.")
|
||||
.arg(first_item->name()));
|
||||
return;
|
||||
}
|
||||
if(!item->polyhedron()->is_pure_triangle()) {
|
||||
messages->warning(tr("The polyhedron \"%1\" is not triangulated.")
|
||||
.arg(item->name()));
|
||||
return;
|
||||
}
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
Polyhedron* new_poly = new Polyhedron();
|
||||
QString str_op;
|
||||
Polyhedron P, Q;
|
||||
switch(op)
|
||||
{
|
||||
case CRF_UNION:
|
||||
P = *first_item->polyhedron(), Q = *item->polyhedron();
|
||||
if (! PMP::corefine_and_compute_union(P, Q, *new_poly) )
|
||||
{
|
||||
delete new_poly;
|
||||
messages->warning(tr("The result of the requested operation is not manifold and has not been computed."));
|
||||
return;
|
||||
}
|
||||
str_op = "Union";
|
||||
break;
|
||||
case CRF_INTER:
|
||||
P = *first_item->polyhedron(), Q = *item->polyhedron();
|
||||
if (! PMP::corefine_and_compute_intersection(P, Q, *new_poly) )
|
||||
{
|
||||
delete new_poly;
|
||||
messages->warning(tr("The result of the requested operation is not manifold and has not been computed."));
|
||||
return;
|
||||
}
|
||||
str_op = "Intersection";
|
||||
break;
|
||||
case CRF_MINUS_OP:
|
||||
std::swap(first_item, item);
|
||||
case CRF_MINUS:
|
||||
P = *first_item->polyhedron(), Q = *item->polyhedron();
|
||||
if (! PMP::corefine_and_compute_difference(P, Q, *new_poly) )
|
||||
{
|
||||
delete new_poly;
|
||||
messages->warning(tr("The result of the requested operation is not manifold and has not been computed."));
|
||||
return;
|
||||
}
|
||||
str_op = "Difference";
|
||||
break;
|
||||
}
|
||||
|
||||
first_item->invalidateOpenGLBuffers();
|
||||
item->invalidateOpenGLBuffers();
|
||||
scene->itemChanged(item);
|
||||
scene->itemChanged(first_item);
|
||||
|
||||
Scene_polyhedron_item* new_item = new Scene_polyhedron_item(new_poly);
|
||||
new_item->setName(QString("%1 of %2 and %3").arg(str_op).arg(first_item->name()).arg(item->name()));
|
||||
new_item->setColor(first_item->color());
|
||||
new_item->setRenderingMode(first_item->renderingMode());
|
||||
new_item->setVisible(first_item->visible());
|
||||
scene->addItem(new_item);
|
||||
new_item->invalidateOpenGLBuffers();
|
||||
|
||||
// default cursor
|
||||
QApplication::restoreOverrideCursor();
|
||||
break;
|
||||
} // end of if(item)
|
||||
} // end of the loop on the selected items
|
||||
}
|
||||
|
||||
void corefine_and_union()
|
||||
{
|
||||
corefine_and_bool_op(CRF_UNION);
|
||||
}
|
||||
void corefine_and_inter()
|
||||
{
|
||||
corefine_and_bool_op(CRF_INTER);
|
||||
}
|
||||
void corefine_and_diff()
|
||||
{
|
||||
corefine_and_bool_op(CRF_MINUS);
|
||||
}
|
||||
void corefine_and_diff_rev()
|
||||
{
|
||||
corefine_and_bool_op(CRF_MINUS_OP);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
QAction* actionCorefine;
|
||||
QAction* actionUnion;
|
||||
QAction* actionInter;
|
||||
QAction* actionDiff;
|
||||
QAction* actionDiffRev;
|
||||
Messages_interface* messages;
|
||||
};
|
||||
|
||||
#include "Corefinement_plugin.moc"
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Polygon_mesh_processing/intersection.h>
|
||||
#include "Scene_polyhedron_item.h"
|
||||
#include "Polyhedron_type.h"
|
||||
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
|
||||
|
||||
#include "Scene_polylines_item.h"
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#include <QString>
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
#include <QMainWindow>
|
||||
#include <QApplication>
|
||||
#include <QTime>
|
||||
#include <QMessageBox>
|
||||
|
||||
using namespace CGAL::Three;
|
||||
namespace PMP = CGAL::Polygon_mesh_processing;
|
||||
|
||||
class Polyhedron_demo_intersection_plugin :
|
||||
public QObject,
|
||||
public Polyhedron_demo_plugin_interface
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface)
|
||||
Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0")
|
||||
|
||||
public:
|
||||
|
||||
bool applicable(QAction*) const {
|
||||
int nb_selected=0;
|
||||
Q_FOREACH(CGAL::Three::Scene_interface::Item_id index, scene->selectionIndices())
|
||||
if ( qobject_cast<Scene_polyhedron_item*>(scene->item(index)) )
|
||||
++nb_selected;
|
||||
return nb_selected==2;
|
||||
}
|
||||
|
||||
QList<QAction*> actions() const {
|
||||
return QList<QAction*>() << actionPolyhedronIntersection_3;
|
||||
}
|
||||
|
||||
void init(QMainWindow* mw, CGAL::Three::Scene_interface* scene_interface, Messages_interface*) {
|
||||
this->scene = scene_interface;
|
||||
actionPolyhedronIntersection_3 = new QAction("Surface Intersection", mw);
|
||||
actionPolyhedronIntersection_3->setProperty("subMenuName", "Polygon Mesh Processing");
|
||||
if(actionPolyhedronIntersection_3) {
|
||||
connect(actionPolyhedronIntersection_3, SIGNAL(triggered()),
|
||||
this, SLOT(intersection()));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
QAction* actionPolyhedronIntersection_3;
|
||||
Scene_interface *scene;
|
||||
|
||||
public Q_SLOTS:
|
||||
void intersection();
|
||||
|
||||
}; // end class Polyhedron_demo_intersection_plugin
|
||||
|
||||
void Polyhedron_demo_intersection_plugin::intersection()
|
||||
{
|
||||
Scene_polyhedron_item* itemA = NULL;
|
||||
Q_FOREACH(CGAL::Three::Scene_interface::Item_id index, scene->selectionIndices())
|
||||
{
|
||||
Scene_polyhedron_item* itemB =
|
||||
qobject_cast<Scene_polyhedron_item*>(scene->item(index));
|
||||
|
||||
if(itemB)
|
||||
{
|
||||
if (itemA==NULL)
|
||||
{
|
||||
itemA = itemB;
|
||||
continue;
|
||||
}
|
||||
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
|
||||
Scene_polylines_item* new_item = new Scene_polylines_item();
|
||||
// perform Boolean operation
|
||||
QTime time;
|
||||
time.start();
|
||||
|
||||
try{
|
||||
PMP::surface_intersection(*itemA->polyhedron(),
|
||||
*itemB->polyhedron(),
|
||||
std::back_inserter(new_item->polylines),
|
||||
true);
|
||||
}
|
||||
catch(CGAL::Corefinement::Self_intersection_exception)
|
||||
{
|
||||
QMessageBox::warning((QWidget*)NULL,
|
||||
tr("Self-intersections Found"),
|
||||
tr("Some self-intersections were found amongst intersecting facets"));
|
||||
delete new_item;
|
||||
QApplication::restoreOverrideCursor();
|
||||
return;
|
||||
}
|
||||
|
||||
QString name = tr("%1 intersection %2");
|
||||
|
||||
new_item->setName(name.arg(itemA->name(), itemB->name()));
|
||||
std::cout << "ok (" << time.elapsed() << " ms)" << std::endl;
|
||||
|
||||
if (new_item->polylines.empty())
|
||||
delete new_item;
|
||||
else{
|
||||
new_item->setColor(Qt::green);
|
||||
new_item->setRenderingMode(Wireframe);
|
||||
scene->addItem(new_item);
|
||||
new_item->invalidateOpenGLBuffers();
|
||||
}
|
||||
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "Surface_intersection_plugin.moc"
|
||||
Loading…
Reference in New Issue