Merge pull request #3970 from maxGimeno/Demo-LCC_plugin-GF

3D Demo: Lcc IO plugin
This commit is contained in:
Laurent Rineau 2019-06-05 11:20:13 +02:00
commit 4719bac98e
2 changed files with 164 additions and 46 deletions

View File

@ -5,65 +5,82 @@
#include <CGAL/Three/Three.h> #include <CGAL/Three/Three.h>
#include <CGAL/Buffer_for_vao.h> #include <CGAL/Buffer_for_vao.h>
#include "Color_map.h"
#include "Scene_lcc_item.h" #include "Scene_lcc_item.h"
//todo : create a struct for facets containing useful infos for drawing and their volume, and fill it during computeElements().
using namespace CGAL::Three; using namespace CGAL::Three;
typedef Triangle_container Tri; typedef Triangle_container Tri;
typedef Edge_container Ec; typedef Edge_container Ec;
typedef Point_container Pc; typedef Point_container Pc;
typedef Viewer_interface Vi; typedef Viewer_interface Vi;
typedef Scene_lcc_item::LCC::Dart_const_handle Dart_const_handle;
typedef Scene_lcc_item::LCC::Dart_handle Dart_handle; typedef Scene_lcc_item::LCC::Dart_handle Dart_handle;
typedef Scene_lcc_item::LCC::Point Point; typedef Scene_lcc_item::LCC::Point Point;
struct Facet{
Facet():normal(Scene_lcc_item::LCC::Vector(0,0,0)){}
Dart_const_handle f_handle;
std::vector<Point> points;
Scene_lcc_item::LCC::Vector normal;
std::size_t volume_id;
std::size_t size() { return points.size(); }
};
struct lcc_priv{ struct lcc_priv{
typedef Scene_lcc_item::LCC::Dart_const_handle Dart_const_handle;
Scene_lcc_item::LCC lcc; Scene_lcc_item::LCC lcc;
std::vector<float> faces; std::vector<float> faces;
std::vector<float> lines; std::vector<float> lines;
std::vector<float> vertices; std::vector<float> vertices;
std::vector<float> colors;
std::vector<Facet> facets;
std::size_t nb_volumes;
bool is_mono_color;
std::size_t nb_lines, nb_vertices, nb_faces; std::size_t nb_lines, nb_vertices, nb_faces;
lcc_priv(const Scene_lcc_item::LCC& lcc) lcc_priv(const Scene_lcc_item::LCC& lcc)
:lcc(lcc){} :lcc(lcc), is_mono_color(true){}
void compute_face(Dart_const_handle dh) bool compute_face(Dart_const_handle dh, Facet& f)
{ {
f.f_handle = dh;
const CGAL::qglviewer::Vec offset = static_cast<CGAL::Three::Viewer_interface*>(CGAL::QGLViewer::QGLViewerPool().first())->offset(); const CGAL::qglviewer::Vec offset = static_cast<CGAL::Three::Viewer_interface*>(CGAL::QGLViewer::QGLViewerPool().first())->offset();
// We fill only closed faces. // We fill only closed faces.
Dart_const_handle cur=dh; Dart_const_handle cur=dh;
Dart_const_handle min=dh; Dart_const_handle min=dh;
do do
{ {
if (!lcc.is_next_exist(cur)) return; // open face=>not filled if (!lcc.is_next_exist(cur)) return false; // open face=>not filled
if (cur<min) min=cur; if (cur<min) min=cur;
cur=lcc.next(cur); cur=lcc.next(cur);
} }
while(cur!=dh); while(cur!=dh);
cur=dh; cur=dh;
std::vector<Point> pts_in_face;
do do
{ {
pts_in_face.push_back(lcc.point(cur)); f.points.push_back(lcc.point(cur));
cur=lcc.next(cur); cur=lcc.next(cur);
} }
while(cur!=dh); while(cur!=dh);
Scene_lcc_item::LCC::Vector normal(0,0,0); for (std::size_t i = 0; i < f.size() ; ++ i){
const Point& pa = f.points[i];
for (std::size_t i = 0; i < pts_in_face.size() ; ++ i){ const Point& pb = f.points[(i+1)%f.size()];
const Point& pa = pts_in_face[i]; double x = f.normal.x() + (pa.y()-pb.y())*(pa.z()+pb.z());
const Point& pb = pts_in_face[(i+1)%pts_in_face.size()]; double y = f.normal.y() + (pa.z()-pb.z())*(pa.x()+pb.x());
double x = normal.x() + (pa.y()-pb.y())*(pa.z()+pb.z()); double z = f.normal.z() + (pa.x()-pb.x())*(pa.y()+pb.y());
double y = normal.y() + (pa.z()-pb.z())*(pa.x()+pb.x()); f.normal = Scene_lcc_item::LCC::Vector(x,y,z);
double z = normal.z() + (pa.x()-pb.x())*(pa.y()+pb.y());
normal = Scene_lcc_item::LCC::Vector(x,y,z);
} }
if (pts_in_face.size()==3) if (f.size()==3)
{ {
for(auto pt = pts_in_face.begin(); for(auto pt = f.points.begin();
pt != pts_in_face.end(); pt != f.points.end();
++pt) ++pt)
{ {
faces.push_back(pt->x() + offset.x); faces.push_back(pt->x() + offset.x);
@ -71,43 +88,43 @@ struct lcc_priv{
faces.push_back(pt->z() + offset.z); faces.push_back(pt->z() + offset.z);
} }
} }
else if (CGAL::Buffer_for_vao<float, std::size_t>::is_facet_convex(pts_in_face,normal)) else if (CGAL::Buffer_for_vao<float, std::size_t>::is_facet_convex(f.points,f.normal))
{ {
if (pts_in_face.size()==4) if (f.size()==4)
{ {
Point p = pts_in_face[0]; Point p = f.points[0];
faces.push_back(p.x() + offset.x); faces.push_back(p.x() + offset.x);
faces.push_back(p.y() + offset.y); faces.push_back(p.y() + offset.y);
faces.push_back(p.z() + offset.z); faces.push_back(p.z() + offset.z);
p = pts_in_face[1]; p = f.points[1];
faces.push_back(p.x() + offset.x); faces.push_back(p.x() + offset.x);
faces.push_back(p.y() + offset.y); faces.push_back(p.y() + offset.y);
faces.push_back(p.z() + offset.z); faces.push_back(p.z() + offset.z);
p = pts_in_face[2]; p = f.points[2];
faces.push_back(p.x() + offset.x); faces.push_back(p.x() + offset.x);
faces.push_back(p.y() + offset.y); faces.push_back(p.y() + offset.y);
faces.push_back(p.z() + offset.z); faces.push_back(p.z() + offset.z);
p = pts_in_face[0]; p = f.points[0];
faces.push_back(p.x() + offset.x); faces.push_back(p.x() + offset.x);
faces.push_back(p.y() + offset.y); faces.push_back(p.y() + offset.y);
faces.push_back(p.z() + offset.z); faces.push_back(p.z() + offset.z);
p = pts_in_face[2]; p = f.points[2];
faces.push_back(p.x() + offset.x); faces.push_back(p.x() + offset.x);
faces.push_back(p.y() + offset.y); faces.push_back(p.y() + offset.y);
faces.push_back(p.z() + offset.z); faces.push_back(p.z() + offset.z);
p = pts_in_face[3]; p = f.points[3];
faces.push_back(p.x() + offset.x); faces.push_back(p.x() + offset.x);
faces.push_back(p.y() + offset.y); faces.push_back(p.y() + offset.y);
faces.push_back(p.z() + offset.z); faces.push_back(p.z() + offset.z);
} }
else else
{ {
for(std::size_t i=1; i<pts_in_face.size()-1; ++i) for(std::size_t i=1; i<f.size()-1; ++i)
{ {
Point& p0 = pts_in_face[0]; Point& p0 = f.points[0];
Point& p1 = pts_in_face[i]; Point& p1 = f.points[i];
Point& p2 = pts_in_face[i+1]; Point& p2 = f.points[i+1];
// (1) add points // (1) add points
faces.push_back(p0.x() + offset.x); faces.push_back(p0.x() + offset.x);
@ -145,16 +162,16 @@ struct lcc_priv{
typedef CGAL::Exact_predicates_tag Itag; typedef CGAL::Exact_predicates_tag Itag;
typedef CGAL::Constrained_Delaunay_triangulation_2<P_traits, TDS, Itag> CDT; typedef CGAL::Constrained_Delaunay_triangulation_2<P_traits, TDS, Itag> CDT;
P_traits cdt_traits(normal); P_traits cdt_traits(f.normal);
CDT cdt(cdt_traits); CDT cdt(cdt_traits);
// (1) We insert all the edges as contraint in the CDT. // (1) We insert all the edges as contraint in the CDT.
typename CDT::Vertex_handle previous=NULL, first=NULL; typename CDT::Vertex_handle previous=NULL, first=NULL;
for (unsigned int i=0; i<pts_in_face.size(); ++i) for (unsigned int i=0; i<f.size(); ++i)
{ {
typename CDT::Vertex_handle vh = cdt.insert(pts_in_face[i]); typename CDT::Vertex_handle vh = cdt.insert(f.points[i]);
if(first==NULL) if(first==NULL)
{ first=vh; } { first=vh; }
vh->info().v=normal; vh->info().v=f.normal;
if(previous!=NULL && previous!=vh) if(previous!=NULL && previous!=vh)
{ cdt.insert_constraint(previous, vh); } { cdt.insert_constraint(previous, vh); }
@ -238,9 +255,8 @@ struct lcc_priv{
} }
} }
} }
return true;
} }
}; };
Scene_lcc_item::Scene_lcc_item(const LCC& lcc) Scene_lcc_item::Scene_lcc_item(const LCC& lcc)
@ -249,11 +265,12 @@ Scene_lcc_item::Scene_lcc_item(const LCC& lcc)
d->nb_faces = 0; d->nb_faces = 0;
d->nb_lines = 0; d->nb_lines = 0;
d->nb_vertices = 0; d->nb_vertices = 0;
d->nb_volumes = 0;
setTriangleContainer(0, setTriangleContainer(0,
new Tri(Three::mainViewer()->isOpenGL_4_3() ? Vi::PROGRAM_FLAT new Tri(Three::mainViewer()->isOpenGL_4_3() ? Vi::PROGRAM_FLAT
: Vi::PROGRAM_OLD_FLAT, false)); : Vi::PROGRAM_OLD_FLAT, false));
setEdgeContainer(0, setEdgeContainer(0,
new Ec(Three::mainViewer()->isOpenGL_4_3() ? Vi::PROGRAM_SOLID_WIREFRAME new Ec(Three::mainViewer()->isOpenGL_4_3() ? Vi::PROGRAM_SOLID_WIREFRAME
: Vi::PROGRAM_NO_SELECTION : Vi::PROGRAM_NO_SELECTION
, false)); , false));
@ -309,9 +326,9 @@ void Scene_lcc_item::draw(CGAL::Three::Viewer_interface* viewer) const
computeElements(); computeElements();
initializeBuffers(viewer); initializeBuffers(viewer);
} }
if(d->is_mono_color)
getTriangleContainer(0)->setColor(this->color()); getTriangleContainer(0)->setColor(this->color());
getTriangleContainer(0)->draw(viewer, true); getTriangleContainer(0)->draw(viewer, d->is_mono_color);
} }
void Scene_lcc_item::drawEdges(CGAL::Three::Viewer_interface* viewer) const void Scene_lcc_item::drawEdges(CGAL::Three::Viewer_interface* viewer) const
@ -378,12 +395,13 @@ void Scene_lcc_item::drawPoints(CGAL::Three::Viewer_interface* viewer) const
void Scene_lcc_item::computeElements() const void Scene_lcc_item::computeElements() const
{ {
CGAL::Three::Three::CursorScopeGuard guard{QCursor(Qt::WaitCursor)}; CGAL::Three::Three::CursorScopeGuard guard{QCursor(Qt::WaitCursor)};
d->facets.clear();
const CGAL::qglviewer::Vec offset = CGAL::Three::Three::mainViewer()->offset(); const CGAL::qglviewer::Vec offset = CGAL::Three::Three::mainViewer()->offset();
typename LCC::size_type markvolumes = d->lcc.get_new_mark(); typename LCC::size_type markvolumes = d->lcc.get_new_mark();
typename LCC::size_type markfaces = d->lcc.get_new_mark(); typename LCC::size_type markfaces = d->lcc.get_new_mark();
typename LCC::size_type markedges = d->lcc.get_new_mark(); typename LCC::size_type markedges = d->lcc.get_new_mark();
typename LCC::size_type markvertices = d->lcc.get_new_mark(); typename LCC::size_type markvertices = d->lcc.get_new_mark();
std::size_t volume_id = 0;
for (typename LCC::Dart_range::const_iterator it=d->lcc.darts().begin(), for (typename LCC::Dart_range::const_iterator it=d->lcc.darts().begin(),
itend=d->lcc.darts().end(); it!=itend; ++it ) itend=d->lcc.darts().end(); it!=itend; ++it )
{ {
@ -397,7 +415,10 @@ void Scene_lcc_item::computeElements() const
d->lcc.mark(itv, markvolumes); // To be sure that all darts of the basic iterator will be marked d->lcc.mark(itv, markvolumes); // To be sure that all darts of the basic iterator will be marked
if (!d->lcc.is_marked(itv, markfaces)) if (!d->lcc.is_marked(itv, markfaces))
{ {
d->compute_face(itv); Facet f;
if(d->compute_face(itv, f))
d->facets.push_back(f);
d->facets.back().volume_id = volume_id;
for (typename LCC::template Dart_of_cell_basic_range<2>:: for (typename LCC::template Dart_of_cell_basic_range<2>::
const_iterator itf=d->lcc.template darts_of_cell_basic<2>(itv, markfaces).begin(), const_iterator itf=d->lcc.template darts_of_cell_basic<2>(itv, markfaces).begin(),
itfend=d->lcc.template darts_of_cell_basic<2>(itv, markfaces).end(); itfend=d->lcc.template darts_of_cell_basic<2>(itv, markfaces).end();
@ -436,9 +457,10 @@ void Scene_lcc_item::computeElements() const
} }
} }
} }
++volume_id;
} }
} }
d->nb_volumes = volume_id;
for (typename LCC::Dart_range::const_iterator it=d->lcc.darts().begin(), for (typename LCC::Dart_range::const_iterator it=d->lcc.darts().begin(),
itend=d->lcc.darts().end(); it!=itend; ++it ) itend=d->lcc.darts().end(); it!=itend; ++it )
{ {
@ -457,7 +479,14 @@ void Scene_lcc_item::computeElements() const
getTriangleContainer(0)->allocate( getTriangleContainer(0)->allocate(
Tri::Flat_vertices, d->faces.data(), Tri::Flat_vertices, d->faces.data(),
static_cast<int>(d->faces.size()*sizeof(float))); static_cast<int>(d->faces.size()*sizeof(float)));
if(!d->is_mono_color)
{
getTriangleContainer(0)->allocate(Tri::FColors, d->colors.data(),
static_cast<int>(d->colors.size()*sizeof(float)));
}
else
getTriangleContainer(0)->allocate(Tri::FColors, 0, 0);
getEdgeContainer(0)->allocate( getEdgeContainer(0)->allocate(
Ec::Vertices, d->lines.data(), Ec::Vertices, d->lines.data(),
static_cast<int>(d->lines.size()*sizeof(float))); static_cast<int>(d->lines.size()*sizeof(float)));
@ -501,3 +530,86 @@ bool Scene_lcc_item::isEmpty() const
{ {
return false; return false;
} }
void Scene_lcc_item::randomFaceColors()
{
d->is_mono_color = false;
d->colors.resize(d->nb_faces);
for(std::size_t i=0; i< d->colors.size()-3; i+=3)
{
QColor col = generate_random_color();
d->colors[i] = col.redF();
d->colors[i+1] = col.greenF();
d->colors[i+2] = col.blueF();
}
invalidateOpenGLBuffers();
redraw();
}
void Scene_lcc_item::randomVolumeColors()
{
d->is_mono_color = false;
d->colors.resize(d->nb_faces);
std::vector<QColor> colors(d->nb_volumes);
for(std::size_t i = 0; i<d->nb_volumes; ++i)
{
colors[i] = generate_random_color();
}
std::size_t color_id = 0;
for(auto f : d->facets)//filled in the same order as GL faces
{
QColor col = colors[f.volume_id];
//3 points per face.
for(std::size_t j = 0; j < 3; ++j)
{
d->colors[color_id+j*3] = col.redF();
d->colors[color_id+j*3+1] = col.greenF();
d->colors[color_id+j*3+2] = col.blueF();
}
color_id += 9;
}
invalidateOpenGLBuffers();
redraw();
}
void Scene_lcc_item::resetColors()
{
d->is_mono_color = true;
invalidateOpenGLBuffers();
redraw();
}
QMenu* Scene_lcc_item::contextMenu()
{
const char* prop_name = "Menu modified by Scene_lcc_item.";
QMenu* menu = Scene_item::contextMenu();
// Use dynamic properties:
// https://doc.qt.io/qt-5/qobject.html#property
bool menuChanged = menu->property(prop_name).toBool();
if(!menuChanged) {
menu->addSeparator();
QAction* action = menu->addAction(tr("Set Random Colors for Faces."));
action->setObjectName("actionRandomFaceColors");
connect(action, &QAction::triggered,
this, &Scene_lcc_item::randomFaceColors);
action = menu->addAction(tr("Set Random Colors for Volumes."));
action->setObjectName("actionRandomVolumeColors");
connect(action, &QAction::triggered,
this, &Scene_lcc_item::randomVolumeColors);
menu->setProperty(prop_name, true);
}
QAction* action = menu->findChild<QAction*>("actionResetColors");
if(!action)
{
action = menu->addAction(tr("Reset Colors."));
action->setObjectName("actionResetColors");
connect(action, &QAction::triggered,
this, &Scene_lcc_item::resetColors);
}
action->setVisible(!d->is_mono_color);
return menu;
}

View File

@ -4,6 +4,8 @@
#include <CGAL/Three/Scene_item_rendering_helper.h> #include <CGAL/Three/Scene_item_rendering_helper.h>
#include <CGAL/Linear_cell_complex_for_combinatorial_map.h> #include <CGAL/Linear_cell_complex_for_combinatorial_map.h>
#include <QMenu>
#ifdef scene_lcc_item_EXPORTS #ifdef scene_lcc_item_EXPORTS
# define SCENE_LCC_ITEM_EXPORT Q_DECL_EXPORT # define SCENE_LCC_ITEM_EXPORT Q_DECL_EXPORT
#else #else
@ -40,10 +42,14 @@ public:
void computeElements() const Q_DECL_OVERRIDE; void computeElements() const Q_DECL_OVERRIDE;
void initializeBuffers(CGAL::Three::Viewer_interface *) const Q_DECL_OVERRIDE; void initializeBuffers(CGAL::Three::Viewer_interface *) const Q_DECL_OVERRIDE;
QMenu* contextMenu() Q_DECL_OVERRIDE ;
public Q_SLOTS: public Q_SLOTS:
void invalidateOpenGLBuffers() Q_DECL_OVERRIDE; void invalidateOpenGLBuffers() Q_DECL_OVERRIDE;
void randomFaceColors();
void randomVolumeColors();
void resetColors();
private: private:
friend struct lcc_priv; friend struct lcc_priv;
lcc_priv* d; lcc_priv* d;