cgal/Polyhedron/demo/Polyhedron/Scene_nef_polyhedron_item.cpp

727 lines
21 KiB
C++

#include "Scene_nef_polyhedron_item.h"
#include <CGAL/Three/Viewer_interface.h>
#include <CGAL/Three/Three.h>
#include <CGAL/Three/Triangle_container.h>
#include <CGAL/Three/Edge_container.h>
#include <CGAL/Three/Point_container.h>
#include "Scene_surface_mesh_item.h"
#include "Nef_type.h"
#include "SMesh_type.h"
#include <CGAL/Polyhedron_incremental_builder_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/IO/Nef_polyhedron_iostream_3.h>
#include <CGAL/Inverse_index.h>
#include <QObject>
#include <QApplication>
#include <CGAL/minkowski_sum_3.h>
#include <CGAL/convex_decomposition_3.h>
#include <CGAL/Triangulation_2_projection_traits_3.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/Triangulation_face_base_with_info_2.h>
#include <CGAL/boost/graph/convert_nef_polyhedron_to_polygon_mesh.h>
#include <CGAL/boost/graph/copy_face_graph.h>
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
using namespace CGAL::Three;
typedef Viewer_interface Vi;
typedef Triangle_container Tc;
typedef Edge_container Ec;
typedef Point_container Pc;
typedef Nef_polyhedron::Traits Traits;
typedef Nef_polyhedron::Halffacet Facet;
typedef CGAL::Triangulation_2_projection_traits_3<Traits> P_traits;
typedef Nef_polyhedron::Halfedge_const_handle Halfedge_handle;
struct Face_info {
Nef_polyhedron::Halfedge_const_handle e[3];
int nesting_level;
};
typedef CGAL::Triangulation_vertex_base_with_info_2<Halfedge_handle,
P_traits> Vb;
typedef CGAL::Triangulation_face_base_with_info_2<Face_info,
P_traits> Fb1;
typedef CGAL::Constrained_triangulation_face_base_2<P_traits, Fb1> Fb;
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> TDS;
typedef CGAL::Exact_predicates_tag Itag;
typedef CGAL::Constrained_Delaunay_triangulation_2<P_traits,
TDS,
Itag> CDTbase;
typedef CGAL::Constrained_triangulation_plus_2<CDTbase> CDT;
struct DPoint {
DPoint(GLdouble x, GLdouble y, GLdouble z)
{
coords[0] = x;
coords[1] = y;
coords[2] = z;
}
GLdouble coords[3];
};
struct Scene_nef_polyhedron_item_priv
{
typedef CGAL::Three::Scene_item Base;
typedef std::vector<QColor> Color_vector;
Scene_nef_polyhedron_item_priv(Scene_nef_polyhedron_item* parent)
:nef_poly(new Nef_polyhedron)
{
item = parent;
nb_points = 0;
nb_lines = 0;
nb_facets = 0;
}
Scene_nef_polyhedron_item_priv(Nef_polyhedron* const p, Scene_nef_polyhedron_item *parent)
:nef_poly(p)
{
item = parent;
nb_points = 0;
nb_lines = 0;
nb_facets = 0;
}
Scene_nef_polyhedron_item_priv(const Nef_polyhedron& p, Scene_nef_polyhedron_item* parent)
:nef_poly(new Nef_polyhedron(p))
{
item = parent;
nb_points = 0;
nb_lines = 0;
nb_facets = 0;
}
~Scene_nef_polyhedron_item_priv()
{
delete nef_poly;
}
void mark_domains(CDT& ct,
CDT::Face_handle start,
int index,
std::list<CDT::Edge>& border ) const;
void compute_normals_and_vertices(void) const;
Nef_polyhedron* nef_poly;
mutable std::vector<float> positions_lines;
mutable std::vector<float> positions_facets;
mutable std::vector<float> positions_points;
mutable std::vector<float> normals;
mutable std::vector<float> color_lines;
mutable std::vector<float> color_facets;
mutable std::vector<float> color_points;
mutable std::size_t nb_points;
mutable std::size_t nb_lines;
mutable std::size_t nb_facets;
Scene_nef_polyhedron_item *item;
};
void Scene_nef_polyhedron_item::common_constructor()
{
setTriangleContainer(0, new Tc(
Vi::PROGRAM_WITH_LIGHT, false));
setEdgeContainer(0, new Ec(
Vi::PROGRAM_NO_SELECTION, false));
setPointContainer(0, new Pc(
Vi::PROGRAM_NO_SELECTION, false));
}
Scene_nef_polyhedron_item::Scene_nef_polyhedron_item()
{
is_selected = true;
d = new Scene_nef_polyhedron_item_priv(this);
common_constructor();
}
Scene_nef_polyhedron_item::Scene_nef_polyhedron_item(Nef_polyhedron* const p)
{
is_selected = true;
d = new Scene_nef_polyhedron_item_priv(p, this);
common_constructor();
}
Scene_nef_polyhedron_item::Scene_nef_polyhedron_item(const Nef_polyhedron& p)
{
is_selected = true;
d = new Scene_nef_polyhedron_item_priv(p, this);
common_constructor();
}
Scene_nef_polyhedron_item::~Scene_nef_polyhedron_item()
{
delete d;
}
void
Scene_nef_polyhedron_item_priv::mark_domains(CDT& ct,
CDT::Face_handle start,
int index,
std::list<CDT::Edge>& border ) const
{
if(start->info().nesting_level != -1){
return;
}
std::list<CDT::Face_handle> queue;
queue.push_back(start);
while(! queue.empty()){
CDT::Face_handle fh = queue.front();
queue.pop_front();
if(fh->info().nesting_level == -1){
fh->info().nesting_level = index;
for(int i = 0; i < 3; i++){
CDT::Edge e(fh,i);
CDT::Face_handle n = fh->neighbor(i);
if(n->info().nesting_level == -1){
if(ct.is_constrained(e)) border.push_back(e);
else queue.push_back(n);
}
}
}
}
}
void Scene_nef_polyhedron_item_priv::compute_normals_and_vertices(void) const
{
QApplication::setOverrideCursor(Qt::WaitCursor);
int count = 0;
positions_facets.resize(0);
positions_points.resize(0);
normals.resize(0);
positions_lines.resize(0);
const CGAL::qglviewer::Vec offset = Three::mainViewer()->offset();
//The Facets
{
for(Nef_polyhedron::Halffacet_const_iterator
f = nef_poly->halffacets_begin (),
end = nef_poly->halffacets_end();
f != end; ++f)
{
if(f->is_twin()) continue;
count++;
Nef_polyhedron::Vector_3 v = f->plane().orthogonal_vector();
P_traits cdt_traits(v);
CDT cdt(cdt_traits);
for(Nef_polyhedron::Halffacet_cycle_const_iterator
fc = f->facet_cycles_begin(),
end = f->facet_cycles_end();
fc != end; ++fc)
{
if ( fc.is_shalfedge() )
{
Nef_polyhedron::SHalfedge_const_handle h = fc;
Nef_polyhedron::SHalfedge_around_facet_const_circulator hc(h), he(hc);
CDT::Vertex_handle previous, first;
do {
Nef_polyhedron::SVertex_const_handle v = hc->source();
const Nef_polyhedron::Point_3& point = v->source()->point();
CDT::Vertex_handle vh = cdt.insert(point);
if(first == 0) {
first = vh;
}
vh->info() = hc->source();
if(previous != 0 && previous != vh) {
cdt.insert_constraint(previous, vh);
}
previous = vh;
} while( ++hc != he );
cdt.insert_constraint(previous, first);
}
}
// sets mark is_external
for(CDT::All_faces_iterator
fit = cdt.all_faces_begin(),
end = cdt.all_faces_end();
fit != end; ++fit)
{
fit->info().nesting_level = -1;
}
//check if the facet is external or internal
std::queue<CDT::Face_handle> face_queue;
face_queue.push(cdt.infinite_vertex()->face());
std::list<CDT::Edge> border;
mark_domains(cdt, cdt.infinite_face(), 0, border);
while(! border.empty()){
CDT::Edge e = border.front();
border.pop_front();
CDT::Face_handle n = e.first->neighbor(e.second);
if(n->info().nesting_level == -1){
mark_domains(cdt, n, e.first->info().nesting_level+1, border);
}
}
//iterates on the internal faces to add the vertices to the positions
//and the normals to the appropriate vectors
for(CDT::Finite_faces_iterator
ffit = cdt.finite_faces_begin(),
end = cdt.finite_faces_end();
ffit != end; ++ffit)
{
if(ffit->info().nesting_level%2 != 1){ continue;}
for(int i = 0; i<3; i++)
{
positions_facets.push_back(CGAL::to_double(ffit->vertex(i)->point().x())+offset.x);
positions_facets.push_back(CGAL::to_double(ffit->vertex(i)->point().y())+offset.y);
positions_facets.push_back(CGAL::to_double(ffit->vertex(i)->point().z())+offset.z);
}
Nef_polyhedron::Vector_3 v = f->plane().orthogonal_vector();
if(f->plane().a() != 0)
v /= f->plane().a();
else if(f->plane().b() != 0)
v /= f->plane().b();
else if(f->plane().c() != 0)
v /= f->plane().c();
else if(f->plane().d() != 0)
v /= f->plane().d();
GLfloat normal[3];
normal[0] = CGAL::to_double(v.x());
normal[1] = CGAL::to_double(v.y());
normal[2] = CGAL::to_double(v.z());
GLfloat norm = normal[0]*normal[0]
+ normal[1]*normal[1]
+ normal[2]*normal[2];
norm = CGAL::sqrt(norm);
normal[0] /= norm;
normal[1] /= norm;
normal[2] /= norm;
normals.push_back(normal[0]);
normals.push_back(normal[1]);
normals.push_back(normal[2]);
normals.push_back(normal[0]);
normals.push_back(normal[1]);
normals.push_back(normal[2]);
normals.push_back(normal[0]);
normals.push_back(normal[1]);
normals.push_back(normal[2]);
}
}
} // end facets
//The Lines
{
for(Nef_polyhedron::Halfedge_const_iterator
e = nef_poly->halfedges_begin(),
end = nef_poly->halfedges_end();
e != end; ++e)
{
if (e->is_twin()) continue;
const Nef_polyhedron::Vertex_const_handle& s = e->source();
const Nef_polyhedron::Vertex_const_handle& t = e->twin()->source();
const Nef_polyhedron::Point_3& a = s->point();
const Nef_polyhedron::Point_3& b = t->point();
positions_lines.push_back(CGAL::to_double(a.x())+offset.x);
positions_lines.push_back(CGAL::to_double(a.y())+offset.y);
positions_lines.push_back(CGAL::to_double(a.z())+offset.z);
positions_lines.push_back(CGAL::to_double(b.x())+offset.x);
positions_lines.push_back(CGAL::to_double(b.y())+offset.y);
positions_lines.push_back(CGAL::to_double(b.z())+offset.z);
}
}
//The points
{
for(Nef_polyhedron::Vertex_const_iterator
v = nef_poly->vertices_begin(),
end = nef_poly->vertices_end();
v != end; ++v)
{
const Nef_polyhedron::Point_3& p = v->point();
positions_points.push_back(CGAL::to_double(p.x())+offset.x);
positions_points.push_back(CGAL::to_double(p.y())+offset.y);
positions_points.push_back(CGAL::to_double(p.z())+offset.z);
color_points.push_back(item->color().lighter(50).redF());
color_points.push_back(item->color().lighter(50).greenF());
color_points.push_back(item->color().lighter(50).blueF());
color_points.push_back(item->color().lighter(50).redF());
color_points.push_back(item->color().lighter(50).greenF());
color_points.push_back(item->color().lighter(50).blueF());
}
} //end points
QApplication::restoreOverrideCursor();
}
Scene_nef_polyhedron_item*
Scene_nef_polyhedron_item::clone() const {
return new Scene_nef_polyhedron_item(*d->nef_poly);
}
bool
Scene_nef_polyhedron_item::load_from_off(std::istream& in)
{
// const std::size_t discarded = CGAL::OFF_to_nef_3(in, *nef_poly);
// return discarded != 0;
Exact_polyhedron exact_poly;
in >> exact_poly;
*d->nef_poly = Nef_polyhedron(exact_poly);
// Polyhedron poly;
// in >> poly;
// *nef_poly = Nef_polyhedron(poly);
invalidateOpenGLBuffers();
return (bool) in;
}
QFont
Scene_nef_polyhedron_item::font() const {
QFont font;
font.setItalic(!font.italic());
return font;
}
bool
Scene_nef_polyhedron_item::load(std::istream& in)
{
in >> *d->nef_poly;
invalidateOpenGLBuffers();
return (bool) in;
}
bool
Scene_nef_polyhedron_item::save(std::ostream& in) const
{
in << *d->nef_poly;
return (bool) in;
}
QString
Scene_nef_polyhedron_item::toolTip() const
{
if(!d->nef_poly)
return QString();
return QObject::tr("<p><b>%1</b> (mode: %5, color: %6)<br />"
"<i>Nef_polyhedron_3</i></p>"
"<p>Number of vertices: %2<br />"
"Number of edges: %3<br />"
"Number of facets: %4<br />"
"number of volumes: %7</p>")
.arg(this->name())
.arg(d->nef_poly->number_of_vertices())
.arg(d->nef_poly->number_of_edges())
.arg(d->nef_poly->number_of_facets())
.arg(this->renderingModeName())
.arg(this->color().name())
.arg(d->nef_poly->number_of_volumes());
}
void Scene_nef_polyhedron_item::draw(CGAL::Three::Viewer_interface* viewer) const
{
if(!isInit(viewer))
initGL(viewer);
if ( getBuffersFilled() &&
! getBuffersInit(viewer))
{
initializeBuffers(viewer);
setBuffersInit(viewer, true);
}
if(!getBuffersFilled())
{
computeElements();
initializeBuffers(viewer);
}
Tc* tc = getTriangleContainer(0);
tc->setColor(this->color());
tc->getVao(viewer)->bind();
tc->getVao(viewer)->program->setUniformValue("is_two_side", 1);
tc->getVao(viewer)->release();
tc->draw(viewer, true);
drawPoints(viewer);
}
void Scene_nef_polyhedron_item::drawEdges(CGAL::Three::Viewer_interface* viewer) const
{
if(!isInit(viewer))
initGL(viewer);
if ( getBuffersFilled() &&
! getBuffersInit(viewer))
{
initializeBuffers(viewer);
setBuffersInit(viewer, true);
}
if(!getBuffersFilled())
{
computeElements();
initializeBuffers(viewer);
}
Ec* ec = getEdgeContainer(0);
ec->setColor(QColor(Qt::black));
ec->draw(viewer, true);
if(renderingMode() == PointsPlusNormals)
{
drawPoints(viewer);
}
}
void Scene_nef_polyhedron_item::drawPoints(CGAL::Three::Viewer_interface* viewer) const
{
if(!isInit(viewer))
initGL(viewer);
if ( getBuffersFilled() &&
! getBuffersInit(viewer))
{
initializeBuffers(viewer);
setBuffersInit(viewer, true);
}
if(!getBuffersFilled())
{
computeElements();
initializeBuffers(viewer);
}
GLfloat point_size;
viewer->glGetFloatv(GL_POINT_SIZE, &point_size);
viewer->setGlPointSize(10.f);
Pc* pc = getPointContainer(0);
pc->setColor(this->color().lighter(50));
pc->draw(viewer, true);
viewer->setGlPointSize(point_size);
}
Nef_polyhedron*
Scene_nef_polyhedron_item::nef_polyhedron() {
return d->nef_poly;
}
Nef_polyhedron*
Scene_nef_polyhedron_item::nef_polyhedron()const {
return d->nef_poly;
}
bool
Scene_nef_polyhedron_item::isEmpty() const {
return (d->nef_poly == 0) || d->nef_poly->is_empty();
}
void
Scene_nef_polyhedron_item::compute_bbox() const {
if(isEmpty())
{
setBbox(Bbox());
return;
}
CGAL::Bbox_3 bbox(d->nef_poly->vertices_begin()->point().bbox());
for(Nef_polyhedron::Vertex_const_iterator it = d->nef_poly->vertices_begin();
it != d->nef_poly->vertices_end();
++it) {
bbox = bbox + it->point().bbox();
}
setBbox(Bbox(bbox.xmin(),bbox.ymin(),bbox.zmin(),
bbox.xmax(),bbox.ymax(),bbox.zmax()));
}
template <class Poly_A, class Poly_B>
void copy_to(const Poly_A& poly_a, Poly_B& poly_b)
{
CGAL::copy_face_graph(poly_a, poly_b);
}
void from_exact(Exact_polyhedron& in,
SMesh& out)
{
copy_to(in, out);
CGAL_assertion(out.is_valid());
}
void to_exact(SMesh& in,
Exact_polyhedron& out)
{
copy_to(in, out);
CGAL_assertion(out.is_valid());
}
bool Scene_nef_polyhedron_item::is_simple() const
{
return d->nef_poly->is_simple();
}
template<typename FaceGraph>
struct Halfedge_index_pmap
{
};
template<typename FaceGraph>
struct Face_index_pmap
{
};
// [static]
Scene_nef_polyhedron_item*
Scene_nef_polyhedron_item::from_polygon_mesh(Scene_surface_mesh_item* item)
{
SMesh* sm = item->polyhedron();
if(!sm) return 0;
CGAL::Surface_mesh<Exact_Kernel::Point_3> exact_sm;
CGAL::copy_face_graph(*sm, exact_sm);
Nef_polyhedron* nef_poly = new Nef_polyhedron(exact_sm);
return new Scene_nef_polyhedron_item(nef_poly);
}
Scene_surface_mesh_item* Scene_nef_polyhedron_item::convert_to_surface_mesh() const
{
SMesh* poly = new SMesh();
CGAL::convert_nef_polyhedron_to_polygon_mesh(*this->nef_polyhedron(), *poly);
CGAL::Polygon_mesh_processing::triangulate_faces(*poly);
return new Scene_surface_mesh_item(poly);
}
Scene_nef_polyhedron_item&
Scene_nef_polyhedron_item::
operator+=(const Scene_nef_polyhedron_item& other)
{
(*d->nef_poly) += (*other.d->nef_poly);
return *this;
}
Scene_nef_polyhedron_item&
Scene_nef_polyhedron_item::
operator*=(const Scene_nef_polyhedron_item& other)
{
(*d->nef_poly) *= (*other.d->nef_poly);
return *this;
}
Scene_nef_polyhedron_item&
Scene_nef_polyhedron_item::
operator-=(const Scene_nef_polyhedron_item& other)
{
(*d->nef_poly) -= (*other.d->nef_poly);
return *this;
}
Scene_nef_polyhedron_item*
Scene_nef_polyhedron_item::
sum(const Scene_nef_polyhedron_item& a,
const Scene_nef_polyhedron_item& b)
{
return new Scene_nef_polyhedron_item(CGAL::minkowski_sum_3(*a.d->nef_poly,
*b.d->nef_poly));
}
void
Scene_nef_polyhedron_item::
convex_decomposition(std::list< Scene_surface_mesh_item*>& convex_parts)
{
// copy the Nef polyhedron, as markers are added
Nef_polyhedron N(*d->nef_poly);
CGAL::convex_decomposition_3(N);
typedef Nef_polyhedron::Volume_const_iterator Volume_const_iterator;
Volume_const_iterator ci = ++N.volumes_begin();
for( ; ci != N.volumes_end(); ++ci) {
if(ci->mark()) {
Exact_polyhedron P;
N.convert_inner_shell_to_polyhedron(ci->shells_begin(), P);
SMesh* poly = new SMesh;
from_exact(P, *poly);
Scene_surface_mesh_item *spoly = new Scene_surface_mesh_item(poly);
convex_parts.push_back(spoly);
spoly->invalidateOpenGLBuffers();
}
}
}
void
Scene_nef_polyhedron_item::
invalidateOpenGLBuffers()
{
compute_bbox();
setBuffersFilled(false);
getTriangleContainer(0)->reset_vbos(ALL);
getEdgeContainer(0)->reset_vbos(ALL);
getPointContainer(0)->reset_vbos(ALL);
}
void
Scene_nef_polyhedron_item::selection_changed(bool p_is_selected)
{
if(p_is_selected != is_selected)
is_selected = p_is_selected;
}
void Scene_nef_polyhedron_item::computeElements() const
{
d->compute_normals_and_vertices();
Tc* tc = getTriangleContainer(0);
tc->allocate(
Tc::Flat_vertices,
d->positions_facets.data(),
static_cast<int>(d->positions_facets.size()*sizeof(float)));
tc->allocate(
Tc::Flat_normals,
d->normals.data(),
static_cast<int>(d->normals.size()*sizeof(float)));
d->nb_facets = d->positions_facets.size();
getEdgeContainer(0)->allocate(
Ec::Vertices,
d->positions_lines.data(),
static_cast<int>(d->positions_lines.size()*sizeof(float)));
d->nb_lines = d->positions_lines.size();
getPointContainer(0)->allocate(
Pc::Vertices,
d->positions_points.data(),
static_cast<int>(d->positions_points.size()*sizeof(float)));
d->nb_points = d->positions_points.size();
setBuffersFilled(true);
}
void Scene_nef_polyhedron_item::initializeBuffers(Viewer_interface *v) const
{
getTriangleContainer(0)->initializeBuffers(v);
getEdgeContainer(0)->initializeBuffers(v);
getPointContainer(0)->initializeBuffers(v);
getTriangleContainer(0)->setFlatDataSize(d->nb_facets);
getEdgeContainer(0)->setFlatDataSize(d->nb_lines);
getPointContainer(0)->setFlatDataSize(d->nb_points);
d->positions_facets.clear();
d->positions_facets.shrink_to_fit();
d->normals.clear();
d->normals.shrink_to_fit();
d->positions_lines.clear();
d->positions_lines.shrink_to_fit();
d->positions_points.clear();
d->positions_points.shrink_to_fit();
}