mirror of https://github.com/CGAL/cgal
401 lines
15 KiB
C++
401 lines
15 KiB
C++
#include "Scene_combinatorial_map_item.h"
|
|
#include "Scene_polyhedron_item.h"
|
|
#include "Scene_interface.h"
|
|
|
|
#include <QObject>
|
|
#include <QMenu>
|
|
#include <QAction>
|
|
#include <QtDebug>
|
|
#include <QKeyEvent>
|
|
#include <CGAL/corefinement_operations.h>
|
|
|
|
Scene_combinatorial_map_item::Scene_combinatorial_map_item(Scene_interface* scene,void* address):last_known_scene(scene),volume_to_display(0),exportSelectedVolume(NULL),address_of_A(address){m_combinatorial_map=NULL;}
|
|
Scene_combinatorial_map_item::~Scene_combinatorial_map_item(){if (m_combinatorial_map!=NULL) delete m_combinatorial_map;}
|
|
|
|
Scene_combinatorial_map_item* Scene_combinatorial_map_item::clone() const{return NULL;}
|
|
|
|
Kernel::Vector_3 Scene_combinatorial_map_item::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=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]=pit->attribute<0>()->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]=pit->attribute<0>()->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(){
|
|
++volume_to_display;
|
|
volume_to_display=volume_to_display%(combinatorial_map().attributes<3>().size()+1);
|
|
emit itemChanged();
|
|
|
|
if (exportSelectedVolume!=NULL && ( volume_to_display==1 || volume_to_display==0 ) )
|
|
exportSelectedVolume->setEnabled(!exportSelectedVolume->isEnabled());
|
|
}
|
|
|
|
|
|
template <class Predicate>
|
|
void Scene_combinatorial_map_item::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_const_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=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(combinatorial_map(),darts.begin(),darts.end(),Predicate::swap_orientation):
|
|
Volume_import_modifier(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 (volume_to_display==0) return; //no volume selected
|
|
|
|
Select_volume predicate(volume_to_display);
|
|
export_as_polyhedron(predicate,QString("%1_%2").arg(this->name()).arg(volume_to_display-1));
|
|
}
|
|
|
|
struct Select_union{
|
|
static const bool only_one_run=false;
|
|
static const bool swap_orientation=true;
|
|
template <class Dart_handle>
|
|
bool operator() (Dart_handle d){ return d->template attribute<3>()->info().outside.size()==2; }
|
|
};
|
|
|
|
struct Select_inter{
|
|
static const bool only_one_run=false;
|
|
static const bool swap_orientation=false;
|
|
template <class Dart_handle>
|
|
bool operator() (Dart_handle d){ return d->template attribute<3>()->info().inside.size()==2; }
|
|
};
|
|
|
|
struct Select_A_minus_B{
|
|
static const bool only_one_run=false;
|
|
static const bool swap_orientation=false;
|
|
Select_A_minus_B(void* address):address_of_A(address){}
|
|
template <class Dart_handle>
|
|
bool operator() (Dart_handle d){
|
|
return d->template attribute<3>()->info().inside.size()==1 &&
|
|
static_cast<void*>(*d->template attribute<3>()->info().inside.begin())==address_of_A;
|
|
}
|
|
private:
|
|
void* address_of_A;
|
|
};
|
|
|
|
struct Select_B_minus_A{
|
|
static const bool only_one_run=false;
|
|
static const bool swap_orientation=false;
|
|
Select_B_minus_A(void* address):address_of_A(address){}
|
|
template <class Dart_handle>
|
|
bool operator() (Dart_handle d){
|
|
return d->template attribute<3>()->info().inside.size()==1 &&
|
|
static_cast<void*>(*d->template attribute<3>()->info().inside.begin())!=address_of_A;
|
|
}
|
|
private:
|
|
void* address_of_A;
|
|
};
|
|
|
|
void Scene_combinatorial_map_item::export_union_as_polyhedron() const {
|
|
export_as_polyhedron(Select_union(),QString("%1_union_%2").arg("A").arg("B"));
|
|
}
|
|
void Scene_combinatorial_map_item::export_intersection_as_polyhedron() const{
|
|
export_as_polyhedron(Select_inter(),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(address_of_A);
|
|
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(address_of_A);
|
|
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.trolltech.com/lastest/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()));
|
|
|
|
exportSelectedVolume =
|
|
menu->addAction(tr("Export current volume as polyhedron"));
|
|
exportSelectedVolume->setObjectName("exportSelectedVolume");
|
|
connect(exportSelectedVolume, SIGNAL(triggered()),this, SLOT(export_current_volume_as_polyhedron()));
|
|
exportSelectedVolume->setEnabled(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::direct_draw() const {
|
|
#if 0
|
|
typedef Combinatorial_map_3::One_dart_per_cell_const_range<3> Volume_dart_range;
|
|
typedef Combinatorial_map_3::One_dart_per_incident_cell_const_range<2,3> Facet_in_volume_drange;
|
|
typedef Combinatorial_map_3::Dart_of_orbit_const_range<1> Dart_in_facet_range;
|
|
Volume_dart_range dart_per_volume_range = combinatorial_map().one_dart_per_cell<3>();
|
|
|
|
std::size_t index = 0;
|
|
for (Volume_dart_range::const_iterator vit=dart_per_volume_range.begin();vit!=dart_per_volume_range.end();++vit)
|
|
{
|
|
if (++index!=volume_to_display && volume_to_display!=0) continue;
|
|
Facet_in_volume_drange facet_range=combinatorial_map().one_dart_per_incident_cell<2,3>(vit);
|
|
|
|
for(Facet_in_volume_drange::const_iterator fit=facet_range.begin();fit!=facet_range.end();++fit){
|
|
Dart_in_facet_range vertices=combinatorial_map().darts_of_orbit<1>(fit);
|
|
Kernel::Vector_3 normal = compute_face_normal(fit);
|
|
|
|
::glBegin(GL_POLYGON);
|
|
::glNormal3d(normal.x(),normal.y(),normal.z());
|
|
|
|
for (Dart_in_facet_range::const_iterator pit=vertices.begin();pit!=vertices.end();++pit ){
|
|
const Kernel::Point_3& p= pit->attribute<0>()->point();
|
|
::glVertex3d(p.x(),p.y(),p.z());
|
|
}
|
|
::glEnd();
|
|
}
|
|
}
|
|
#else
|
|
std::size_t index = 0;
|
|
int voltreated = combinatorial_map().get_new_mark();
|
|
int facetreated = combinatorial_map().get_new_mark();
|
|
Combinatorial_map_3::Dart_const_range::const_iterator
|
|
darts_it=combinatorial_map().darts().begin(), darts_end=combinatorial_map().darts().end();
|
|
for( ; darts_it!=darts_end; ++darts_it)
|
|
{
|
|
if ( !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=combinatorial_map().darts_of_cell<3>(darts_it).begin(),
|
|
vol_end=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 )
|
|
{
|
|
combinatorial_map().mark(vol_it,facetreated);
|
|
combinatorial_map().mark(vol_it, voltreated);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for ( ;vol_it!=vol_end; ++vol_it )
|
|
{
|
|
if ( !combinatorial_map().is_marked(vol_it,facetreated) )
|
|
{
|
|
Kernel::Vector_3 normal = compute_face_normal(vol_it);
|
|
::glBegin(GL_POLYGON);
|
|
::glNormal3d(normal.x(),normal.y(),normal.z());
|
|
|
|
//iterate over all darts of facets
|
|
for ( Combinatorial_map_3::Dart_of_orbit_const_range<1>::const_iterator
|
|
face_it=combinatorial_map().darts_of_orbit<1>(vol_it).begin(),
|
|
face_end=combinatorial_map().darts_of_orbit<1>(vol_it).end();
|
|
face_it!=face_end; ++face_it)
|
|
{
|
|
const Kernel::Point_3& p= face_it->attribute<0>()->point();
|
|
::glVertex3d(p.x(),p.y(),p.z());
|
|
combinatorial_map().mark(face_it,facetreated);
|
|
combinatorial_map().mark(face_it, voltreated);
|
|
}
|
|
::glEnd();
|
|
}
|
|
}
|
|
}
|
|
if ( index==volume_to_display ) break;
|
|
}
|
|
}
|
|
//mark remaining darts to have an O(1) free_mark
|
|
for( ; darts_it!=darts_end; ++darts_it)
|
|
{
|
|
combinatorial_map().mark(darts_it, facetreated);
|
|
combinatorial_map().mark(darts_it, voltreated);
|
|
}
|
|
|
|
combinatorial_map().free_mark(facetreated);
|
|
combinatorial_map().free_mark(voltreated);
|
|
#endif
|
|
}
|
|
|
|
void Scene_combinatorial_map_item::direct_draw_edges() const {
|
|
typedef Combinatorial_map_3::One_dart_per_cell_const_range<1> Edge_darts;
|
|
Edge_darts darts=combinatorial_map().one_dart_per_cell<1>();
|
|
::glBegin(GL_LINES);
|
|
for (Edge_darts::const_iterator dit=darts.begin();dit!=darts.end();++dit){
|
|
CGAL_assertion(!dit->is_free(1));
|
|
const Kernel::Point_3& a = dit->attribute<0>()->point();
|
|
const Kernel::Point_3& b = dit->beta(1)->attribute<0>()->point();
|
|
::glVertex3d(a.x(),a.y(),a.z());
|
|
::glVertex3d(b.x(),b.y(),b.z());
|
|
}
|
|
::glEnd();
|
|
}
|
|
|
|
void Scene_combinatorial_map_item::draw_points() const{
|
|
typedef Combinatorial_map_3::Attribute_const_range<0>::type Point_range;
|
|
const Point_range& points=combinatorial_map().attributes<0>();
|
|
::glBegin(GL_POINTS);
|
|
for(Point_range::const_iterator pit=boost::next(points.begin());pit!=points.end();++pit){
|
|
const Kernel::Point_3& p=pit->point();
|
|
::glVertex3d(p.x(),p.y(),p.z());
|
|
}
|
|
::glEnd();
|
|
}
|
|
|
|
bool Scene_combinatorial_map_item::isEmpty() const {return combinatorial_map().number_of_darts()==0;}
|
|
|
|
Scene_combinatorial_map_item::Bbox
|
|
Scene_combinatorial_map_item::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();
|
|
return 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 (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(volume_to_display-1);
|
|
}
|
|
|
|
|
|
#include "Scene_combinatorial_map_item.moc"
|