cgal/Polyhedron/demo/Polyhedron/Scene_nef_polyhedron_item.cpp

679 lines
21 KiB
C++

#include "Scene_nef_polyhedron_item.h"
#include "Scene_polyhedron_item.h"
#include "Nef_type.h"
#include "Polyhedron_type.h"
#include <CGAL/Polyhedron_incremental_builder_3.h>
// #include <CGAL/OFF_to_nef_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/IO/Nef_polyhedron_iostream_3.h>
#include <CGAL/Inverse_index.h>
#include <QObject>
#include <CGAL/minkowski_sum_3.h>
#include <CGAL/convex_decomposition_3.h>
#include <CGAL/Triangulation_2_filtered_projection_traits_3.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/Triangulation_face_base_with_info_2.h>
typedef Nef_polyhedron::Traits Traits;
typedef Nef_polyhedron::Halffacet Facet;
typedef CGAL::Triangulation_2_filtered_projection_traits_3<Traits> P_traits;
typedef Nef_polyhedron::Halfedge_const_handle Halfedge_handle;
struct Face_info {
Nef_polyhedron::Halfedge_const_handle e[3];
bool is_external;
};
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::No_intersection_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];
};
Scene_nef_polyhedron_item::Scene_nef_polyhedron_item()
: Scene_item(NbOfVbos,NbOfVaos),
nef_poly(new Nef_polyhedron)
{
is_selected = true;
nb_points = 0;
nb_lines = 0;
nb_facets = 0;
}
Scene_nef_polyhedron_item::Scene_nef_polyhedron_item(Nef_polyhedron* const p)
: Scene_item(NbOfVbos,NbOfVaos),
nef_poly(p)
{
is_selected = true;
nb_points = 0;
nb_lines = 0;
nb_facets = 0;
}
Scene_nef_polyhedron_item::Scene_nef_polyhedron_item(const Nef_polyhedron& p)
: Scene_item(NbOfVbos,NbOfVaos),
nef_poly(new Nef_polyhedron(p))
{
is_selected = true;
nb_points = 0;
nb_lines = 0;
nb_facets = 0;
}
Scene_nef_polyhedron_item::~Scene_nef_polyhedron_item()
{
delete nef_poly;
}
void Scene_nef_polyhedron_item::initialize_buffers(CGAL::Three::Viewer_interface *viewer) const
{
//vao for the facets
{
program = getShaderProgram(PROGRAM_WITH_LIGHT, viewer);
program->bind();
vaos[Facets]->bind();
buffers[Facets_vertices].bind();
buffers[Facets_vertices].allocate(positions_facets.data(),
static_cast<int>(positions_facets.size()*sizeof(double)));
program->enableAttributeArray("vertex");
program->setAttributeBuffer("vertex",GL_DOUBLE,0,3);
buffers[Facets_vertices].release();
buffers[Facets_normals].bind();
buffers[Facets_normals].allocate(normals.data(),
static_cast<int>(normals.size()*sizeof(double)));
program->enableAttributeArray("normals");
program->setAttributeBuffer("normals",GL_DOUBLE,0,3);
buffers[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);
program->release();
}
//vao for the edges
{
program = getShaderProgram(PROGRAM_WITHOUT_LIGHT, viewer);
program->bind();
vaos[Edges]->bind();
buffers[Edges_vertices].bind();
buffers[Edges_vertices].allocate(positions_lines.data(),
static_cast<int>(positions_lines.size()*sizeof(double)));
program->enableAttributeArray("vertex");
program->setAttributeBuffer("vertex",GL_DOUBLE,0,3);
buffers[Edges_vertices].release();
nb_lines = positions_lines.size();
positions_lines.resize(0);
std::vector<double>(positions_lines).swap(positions_lines);
vaos[Edges]->release();
program->release();
}
//vao for the points
{
program = getShaderProgram(PROGRAM_WITHOUT_LIGHT, viewer);
program->bind();
vaos[Points]->bind();
buffers[Points_vertices].bind();
buffers[Points_vertices].allocate(positions_points.data(),
static_cast<int>(positions_points.size()*sizeof(double)));
program->enableAttributeArray("vertex");
program->setAttributeBuffer("vertex",GL_DOUBLE,0,3);
buffers[Points_vertices].release();
vaos[Points]->release();
nb_points = positions_points.size();
positions_points.resize(0);
std::vector<double>(positions_points).swap(positions_points);
program->release();
}
are_buffers_filled = true;
}
void Scene_nef_polyhedron_item::compute_normals_and_vertices(void) const
{
int count = 0;
positions_facets.resize(0);
positions_points.resize(0);
normals.resize(0);
positions_lines.resize(0);
//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().is_external = false;
}
//check if the facet is external or internal
std::queue<CDT::Face_handle> face_queue;
face_queue.push(cdt.infinite_vertex()->face());
while(! face_queue.empty() ) {
CDT::Face_handle fh = face_queue.front();
face_queue.pop();
if(fh->info().is_external) continue;
fh->info().is_external = true;
for(int i = 0; i <3; ++i) {
if(!cdt.is_constrained(std::make_pair(fh, i)))
{
face_queue.push(fh->neighbor(i));
}
}
}
//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().is_external){ continue;}
for(int i = 0; i<3; i++)
{
positions_facets.push_back(CGAL::to_double(ffit->vertex(i)->point().x()));
positions_facets.push_back(CGAL::to_double(ffit->vertex(i)->point().y()));
positions_facets.push_back(CGAL::to_double(ffit->vertex(i)->point().z()));
}
Nef_polyhedron::Vector_3 v = f->plane().orthogonal_vector();
GLdouble normal[3];
normal[0] = CGAL::to_double(v.x());
normal[1] = CGAL::to_double(v.y());
normal[2] = CGAL::to_double(v.z());
GLdouble 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()));
positions_lines.push_back(CGAL::to_double(a.y()));
positions_lines.push_back(CGAL::to_double(a.z()));
positions_lines.push_back(CGAL::to_double(b.x()));
positions_lines.push_back(CGAL::to_double(b.y()));
positions_lines.push_back(CGAL::to_double(b.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()));
positions_points.push_back(CGAL::to_double(p.y()));
positions_points.push_back(CGAL::to_double(p.z()));
color_points.push_back(this->color().lighter(50).redF());
color_points.push_back(this->color().lighter(50).greenF());
color_points.push_back(this->color().lighter(50).blueF());
color_points.push_back(this->color().lighter(50).redF());
color_points.push_back(this->color().lighter(50).greenF());
color_points.push_back(this->color().lighter(50).blueF());
}
} //end points
}
Scene_nef_polyhedron_item*
Scene_nef_polyhedron_item::clone() const {
return new Scene_nef_polyhedron_item(*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;
*nef_poly = Nef_polyhedron(exact_poly);
// Polyhedron poly;
// in >> poly;
// *nef_poly = Nef_polyhedron(poly);
invalidate_OpenGLBuffers();
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 >> *nef_poly;
invalidate_OpenGLBuffers();
return (bool) in;
}
bool
Scene_nef_polyhedron_item::save(std::ostream& in) const
{
in << *nef_poly;
return (bool) in;
}
QString
Scene_nef_polyhedron_item::toolTip() const
{
if(!nef_poly)
return QString();
return QObject::tr("<p><b>%1</b> (mode: %5, color: %6)<br />"
"<i>Nef_3 polyhedron</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(nef_poly->number_of_vertices())
.arg(nef_poly->number_of_edges())
.arg(nef_poly->number_of_facets())
.arg(this->renderingModeName())
.arg(this->color().name())
.arg(nef_poly->number_of_volumes());
}
void Scene_nef_polyhedron_item::draw(CGAL::Three::Viewer_interface* viewer) const
{
if(!are_buffers_filled)
{
compute_normals_and_vertices();
initialize_buffers(viewer);
}
vaos[Facets]->bind();
// tells the GPU to use the program just created
program=getShaderProgram(PROGRAM_WITH_LIGHT);
attrib_buffers(viewer,PROGRAM_WITH_LIGHT);
program->bind();
program->setUniformValue("is_two_side", 1);
viewer->glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(nb_facets/3));
vaos[Facets]->release();
program->release();
GLfloat point_size;
viewer->glGetFloatv(GL_POINT_SIZE, &point_size);
viewer->glPointSize(10.f);
draw_points(viewer);
viewer->glPointSize(point_size);
}
void Scene_nef_polyhedron_item::draw_edges(CGAL::Three::Viewer_interface* viewer) const
{
if(!are_buffers_filled)
{
compute_normals_and_vertices();
initialize_buffers(viewer);
}
vaos[Edges]->bind();
program = getShaderProgram(PROGRAM_WITHOUT_LIGHT);
attrib_buffers(viewer ,PROGRAM_WITHOUT_LIGHT);
program->bind();
viewer->glDrawArrays(GL_LINES,0,static_cast<GLsizei>(nb_lines/3));
vaos[Edges]->release();
program->release();
if(renderingMode() == PointsPlusNormals)
{
GLfloat point_size;
viewer->glGetFloatv(GL_POINT_SIZE, &point_size);
viewer->glPointSize(10.f);
draw_points(viewer);
viewer->glPointSize(point_size);
}
}
void Scene_nef_polyhedron_item::draw_points(CGAL::Three::Viewer_interface* viewer) const
{
if(!are_buffers_filled)
{
compute_normals_and_vertices();
initialize_buffers(viewer);
}
vaos[Points]->bind();
program=getShaderProgram(PROGRAM_WITHOUT_LIGHT);
attrib_buffers(viewer ,PROGRAM_WITHOUT_LIGHT);
program->bind();
program->setAttributeValue("colors", this->color());
viewer->glDrawArrays(GL_POINTS,0,static_cast<GLsizei>(nb_points/3));
vaos[Points]->release();
program->release();
}
Nef_polyhedron*
Scene_nef_polyhedron_item::nef_polyhedron() {
return nef_poly;
}
bool
Scene_nef_polyhedron_item::isEmpty() const {
return (nef_poly == 0) || nef_poly->is_empty();
}
void
Scene_nef_polyhedron_item::compute_bbox() const {
if(isEmpty())
{
_bbox = Bbox();
return;
}
CGAL::Bbox_3 bbox(nef_poly->vertices_begin()->point().bbox());
for(Nef_polyhedron::Vertex_const_iterator it = nef_poly->vertices_begin();
it != nef_poly->vertices_end();
++it) {
bbox = bbox + it->point().bbox();
}
_bbox = Bbox(bbox.xmin(),bbox.ymin(),bbox.zmin(),
bbox.xmax(),bbox.ymax(),bbox.zmax());
}
// quick hacks to convert polyhedra from exact to inexact and vice-versa
template <class Polyhedron_input,
class Polyhedron_output>
struct Copy_polyhedron_to
: public CGAL::Modifier_base<typename Polyhedron_output::HalfedgeDS>
{
Copy_polyhedron_to(const Polyhedron_input& in_poly)
: in_poly(in_poly) {}
void operator()(typename Polyhedron_output::HalfedgeDS& out_hds)
{
typedef typename Polyhedron_output::HalfedgeDS Output_HDS;
CGAL::Polyhedron_incremental_builder_3<Output_HDS> builder(out_hds);
typedef typename Polyhedron_input::Vertex_const_iterator Vertex_const_iterator;
typedef typename Polyhedron_input::Facet_const_iterator Facet_const_iterator;
typedef typename Polyhedron_input::Halfedge_around_facet_const_circulator HFCC;
builder.begin_surface(in_poly.size_of_vertices(),
in_poly.size_of_facets(),
in_poly.size_of_halfedges());
for(Vertex_const_iterator
vi = in_poly.vertices_begin(), end = in_poly.vertices_end();
vi != end ; ++vi)
{
typename Polyhedron_output::Point_3 p(::CGAL::to_double( vi->point().x()),
::CGAL::to_double( vi->point().y()),
::CGAL::to_double( vi->point().z()));
builder.add_vertex(p);
}
typedef CGAL::Inverse_index<Vertex_const_iterator> Index;
Index index( in_poly.vertices_begin(), in_poly.vertices_end());
for(Facet_const_iterator
fi = in_poly.facets_begin(), end = in_poly.facets_end();
fi != end; ++fi)
{
HFCC hc = fi->facet_begin();
HFCC hc_end = hc;
// std::size_t n = circulator_size( hc);
// CGAL_assertion( n >= 3);
builder.begin_facet ();
do {
builder.add_vertex_to_facet(index[hc->vertex()]);
++hc;
} while( hc != hc_end);
builder.end_facet();
}
builder.end_surface();
} // end operator()(..)
private:
const Polyhedron_input& in_poly;
}; // end Copy_polyhedron_to<>
template <class Poly_A, class Poly_B>
void copy_to(const Poly_A& poly_a, Poly_B& poly_b)
{
Copy_polyhedron_to<Poly_A, Poly_B> modifier(poly_a);
poly_b.delegate(modifier);
}
void from_exact(Exact_polyhedron& in,
Polyhedron& out)
{
copy_to(in, out);
CGAL_assertion(out.is_valid());
}
void to_exact(Polyhedron& in,
Exact_polyhedron& out)
{
copy_to(in, out);
CGAL_assertion(out.is_valid());
}
bool Scene_nef_polyhedron_item::is_simple() const
{
return nef_poly->is_simple();
}
// [static]
Scene_nef_polyhedron_item*
Scene_nef_polyhedron_item::from_polyhedron(Scene_polyhedron_item* item)
{
Polyhedron* poly = item->polyhedron();
if(!poly) return 0;
Exact_polyhedron exact_poly;
to_exact(*poly, exact_poly);
Nef_polyhedron* nef_poly = new Nef_polyhedron(exact_poly);
exact_poly.clear();
return new Scene_nef_polyhedron_item(nef_poly);
}
Scene_polyhedron_item*
Scene_nef_polyhedron_item::convert_to_polyhedron() const {
Exact_polyhedron exact_poly;
nef_poly->convert_to_Polyhedron(exact_poly);
Polyhedron* poly = new Polyhedron;
from_exact(exact_poly, *poly);
exact_poly.clear();
return new Scene_polyhedron_item(poly);
}
Scene_nef_polyhedron_item&
Scene_nef_polyhedron_item::
operator+=(const Scene_nef_polyhedron_item& other)
{
(*nef_poly) += (*other.nef_poly);
return *this;
}
Scene_nef_polyhedron_item&
Scene_nef_polyhedron_item::
operator*=(const Scene_nef_polyhedron_item& other)
{
(*nef_poly) *= (*other.nef_poly);
return *this;
}
Scene_nef_polyhedron_item&
Scene_nef_polyhedron_item::
operator-=(const Scene_nef_polyhedron_item& other)
{
(*nef_poly) -= (*other.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.nef_poly,
*b.nef_poly));
}
void
Scene_nef_polyhedron_item::
convex_decomposition(std::list< Scene_polyhedron_item*>& convex_parts)
{
// copy the Nef polyhedron, as markers are added
Nef_polyhedron N(*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);
Polyhedron* poly = new Polyhedron;
from_exact(P, *poly);
Scene_polyhedron_item *spoly = new Scene_polyhedron_item(poly);
convex_parts.push_back(spoly);
spoly->invalidate_OpenGLBuffers();
}
}
}
void
Scene_nef_polyhedron_item::
invalidate_OpenGLBuffers()
{
compute_bbox();
Base::invalidate_OpenGLBuffers();
are_buffers_filled = false;
}
void
Scene_nef_polyhedron_item::selection_changed(bool p_is_selected)
{
if(p_is_selected != is_selected)
is_selected = p_is_selected;
}