diff --git a/Polyhedron/demo/Polyhedron/CMakeLists.txt b/Polyhedron/demo/Polyhedron/CMakeLists.txt index 02ba16e1e10..a89f5d5552b 100644 --- a/Polyhedron/demo/Polyhedron/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/CMakeLists.txt @@ -301,7 +301,9 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND AND OPENGL_FOUND ) add_item(scene_polylines_item Scene_polylines_item.cpp) target_link_libraries(scene_polylines_item PUBLIC scene_basic_objects scene_points_with_normal_item) - + + add_item(scene_lcc_item Scene_lcc_item.cpp) + foreach( lib demo_framework scene_basic_objects diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt index a65f18e106e..5a0289798e6 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt @@ -26,6 +26,8 @@ target_link_libraries(stl_plugin PUBLIC scene_surface_mesh_item scene_polygon_so polyhedron_demo_plugin(surf_io_plugin Surf_io_plugin KEYWORDS IO) target_link_libraries(surf_io_plugin PUBLIC scene_surface_mesh_item) +polyhedron_demo_plugin(lcc_io_plugin lcc_io_plugin KEYWORDS IO) +target_link_libraries(lcc_io_plugin PUBLIC scene_lcc_item) find_package(VTK QUIET COMPONENTS diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/lcc_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/lcc_io_plugin.cpp new file mode 100644 index 00000000000..e566ed6172e --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/lcc_io_plugin.cpp @@ -0,0 +1,74 @@ +#include +#include +#include +#include + +#include "Scene_lcc_item.h" + +#include +#include + +class LCC_io_plugin : + public QObject, + public CGAL::Three::Polyhedron_demo_io_plugin_interface +{ + Q_OBJECT + Q_INTERFACES(CGAL::Three::Polyhedron_demo_io_plugin_interface) + Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.IOPluginInterface/1.0" FILE "lcc_io_plugin.json") + +public: + bool isDefaultLoader(const CGAL::Three::Scene_item *item) const + { + if(qobject_cast(item)) + return true; + return false; + } + QString name() const { return "lcc_plugin"; } + QString nameFilters() const { return + "OFF files (*.off);;" + "3-map files (*.3map)"; } + + QString saveNameFilters() const { + return + "3-map files (*.3map)"; + } + + bool canLoad() const { return true; } + CGAL::Three::Scene_item* load(QFileInfo fileinfo){ + // Open file + std::ifstream ifs(fileinfo.filePath().toUtf8()); + if(!ifs) { + std::cerr << "Error! Cannot open file " << (const char*)fileinfo.filePath().toUtf8() << std::endl; + return nullptr; + } + + Scene_lcc_item::LCC lcc; + QString ext = fileinfo.suffix(); + bool res = true; + if(ext == "off") + CGAL::import_from_polyhedron_3_flux < Scene_lcc_item::LCC > (lcc, ifs); + else + { + res = CGAL::load_combinatorial_map(ifs, lcc); + } + if(!res) + { + return nullptr; + } + Scene_lcc_item* new_item = new Scene_lcc_item(lcc); + new_item->setName(fileinfo.fileName()); + new_item->invalidateOpenGLBuffers(); + return new_item; + } + + + bool canSave(const CGAL::Three::Scene_item*){return true;} + bool save(const CGAL::Three::Scene_item*, QFileInfo fileinfo){ + qDebug() << fileinfo.fileName() << "Implement me, you fool !"; + return false; + } + +}; + + +#include "lcc_io_plugin.moc" diff --git a/Polyhedron/demo/Polyhedron/Scene_lcc_item.cpp b/Polyhedron/demo/Polyhedron/Scene_lcc_item.cpp new file mode 100644 index 00000000000..b75dcca3bd3 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Scene_lcc_item.cpp @@ -0,0 +1,502 @@ +#include +#include +#include +#include +#include +#include + +#include "Scene_lcc_item.h" +using namespace CGAL::Three; +typedef Triangle_container Tri; +typedef Edge_container Ec; +typedef Point_container Pc; +typedef Viewer_interface Vi; + +typedef Scene_lcc_item::LCC::Dart_handle Dart_handle; +typedef Scene_lcc_item::LCC::Point Point; + +struct lcc_priv{ + typedef Scene_lcc_item::LCC::Dart_const_handle Dart_const_handle; + Scene_lcc_item::LCC lcc; + std::vector faces; + std::vector lines; + std::vector vertices; + + std::size_t nb_lines, nb_vertices, nb_faces; + + lcc_priv(const Scene_lcc_item::LCC& lcc) + :lcc(lcc){} + + void compute_face(Dart_const_handle dh) + { + // We fill only closed faces. + Dart_const_handle cur=dh; + Dart_const_handle min=dh; + do + { + if (!lcc.is_next_exist(cur)) return; // open face=>not filled + if (cur pts_in_face; + do + { + pts_in_face.push_back(lcc.point(cur)); + cur=lcc.next(cur); + } + while(cur!=dh); + Scene_lcc_item::LCC::Vector normal(0,0,0); + + for (std::size_t i = 0; i < pts_in_face.size() ; ++ i){ + const Point& pa = pts_in_face[i]; + const Point& pb = pts_in_face[(i+1)%pts_in_face.size()]; + double x = normal.x() + (pa.y()-pb.y())*(pa.z()+pb.z()); + double y = normal.y() + (pa.z()-pb.z())*(pa.x()+pb.x()); + 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) + { + for(auto pt = pts_in_face.begin(); + pt != pts_in_face.end(); + ++pt) + { + faces.push_back(pt->x()); + faces.push_back(pt->y()); + faces.push_back(pt->z()); + } + } + else if (CGAL::Buffer_for_vao::is_facet_convex(pts_in_face,normal)) + { + if (pts_in_face.size()==4) + { + Point p = pts_in_face[0]; + faces.push_back(p.x()); + faces.push_back(p.y()); + faces.push_back(p.z()); + p = pts_in_face[1]; + faces.push_back(p.x()); + faces.push_back(p.y()); + faces.push_back(p.z()); + p = pts_in_face[2]; + faces.push_back(p.x()); + faces.push_back(p.y()); + faces.push_back(p.z()); + + p = pts_in_face[0]; + faces.push_back(p.x()); + faces.push_back(p.y()); + faces.push_back(p.z()); + p = pts_in_face[2]; + faces.push_back(p.x()); + faces.push_back(p.y()); + faces.push_back(p.z()); + p = pts_in_face[3]; + faces.push_back(p.x()); + faces.push_back(p.y()); + faces.push_back(p.z()); + } + else + { + for(std::size_t i=1; i 4 vertices + } + else + { + struct Vertex_info + { + Scene_lcc_item::LCC::Vector v; + std::size_t index; + }; + + struct Face_info + { + bool exist_edge[3]; + bool is_external; + bool is_process; + }; + + typedef CGAL::Triangulation_2_projection_traits_3 P_traits; + typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; + typedef CGAL::Triangulation_face_base_with_info_2 Fb1; + typedef CGAL::Constrained_triangulation_face_base_2 Fb; + typedef CGAL::Triangulation_data_structure_2 TDS; + typedef CGAL::Exact_predicates_tag Itag; + typedef CGAL::Constrained_Delaunay_triangulation_2 CDT; + + P_traits cdt_traits(normal); + CDT cdt(cdt_traits); + // (1) We insert all the edges as contraint in the CDT. + typename CDT::Vertex_handle previous=NULL, first=NULL; + for (unsigned int i=0; iinfo().v=normal; + + if(previous!=NULL && previous!=vh) + { cdt.insert_constraint(previous, vh); } + previous=vh; + } + + if (previous!=NULL && previous!=first) + { cdt.insert_constraint(previous, first); } + + // (2) We mark all external triangles + // (2.1) We initialize is_external and is_process values + for(typename CDT::All_faces_iterator fit = cdt.all_faces_begin(), + fitend = cdt.all_faces_end(); fit!=fitend; ++fit) + { + fit->info().is_external = true; + fit->info().is_process = false; + } + // (2.2) We check if the facet is external or internal + std::queue face_queue; + typename CDT::Face_handle face_internal = NULL; + if (cdt.infinite_vertex()->face()!=NULL) + { face_queue.push(cdt.infinite_vertex()->face()); } + while(!face_queue.empty()) + { + typename CDT::Face_handle fh = face_queue.front(); + face_queue.pop(); + if(!fh->info().is_process) + { + fh->info().is_process = true; + for(int i=0; i<3; ++i) + { + if(!cdt.is_constrained(std::make_pair(fh, i))) + { + if (fh->neighbor(i)!=NULL) + { face_queue.push(fh->neighbor(i)); } + } + else if (face_internal==NULL) + { + face_internal = fh->neighbor(i); + } + } + } + } + + if ( face_internal!=NULL ) + { face_queue.push(face_internal); } + + while(!face_queue.empty()) + { + typename CDT::Face_handle fh = face_queue.front(); + face_queue.pop(); + if(!fh->info().is_process) + { + fh->info().is_process = true; + fh->info().is_external = false; + for(unsigned int i=0; i<3; ++i) + { + if(!cdt.is_constrained(std::make_pair(fh, i))) + { + if (fh->neighbor(i)!=NULL) + { face_queue.push(fh->neighbor(i)); } + } + } + } + } + + // (3) Now we iterates on the internal faces to add the vertices + // and the normals to the appropriate vectors + for(typename CDT::Finite_faces_iterator ffit=cdt.finite_faces_begin(), + ffitend = cdt.finite_faces_end(); ffit!=ffitend; ++ffit) + { + if(!ffit->info().is_external) + { + for(unsigned int i=0; i<3; ++i) + { + Point p = ffit->vertex(i)->point(); + faces.push_back(p.x()); + faces.push_back(p.y()); + faces.push_back(p.z()); + } + } + } + } + + } + +}; + +Scene_lcc_item::Scene_lcc_item(const LCC& lcc) + :d(new lcc_priv(lcc)) +{ + d->nb_faces = 0; + d->nb_lines = 0; + d->nb_vertices = 0; + setTriangleContainer(0, + new Tri(Three::mainViewer()->isOpenGL_4_3() ? Vi::PROGRAM_FLAT + : Vi::PROGRAM_OLD_FLAT, false)); + + setEdgeContainer(0, + new Ec(Three::mainViewer()->isOpenGL_4_3() ? Vi::PROGRAM_SOLID_WIREFRAME + : Vi::PROGRAM_NO_SELECTION + , false)); + setPointContainer(0, + new Pc(Vi::PROGRAM_NO_SELECTION, false)); +} + +Scene_lcc_item::~Scene_lcc_item() +{ + delete d; +} + +Scene_lcc_item* Scene_lcc_item::clone() const +{ + Scene_lcc_item* item = new Scene_lcc_item(d->lcc); + return item; +} + +bool Scene_lcc_item::supportsRenderingMode(RenderingMode m) const +{ + return m==FlatPlusEdges; +} + +QString Scene_lcc_item::toolTip() const +{ + return QString(); +} + +void Scene_lcc_item::compute_bbox() const +{ + Scene_item::Bbox bb; + for (LCC::Dart_range::const_iterator it=d->lcc.darts().begin(), + itend=d->lcc.darts().end(); it!=itend; ++it ) + { + bb+=d->lcc.point(it).bbox(); + } + this->setBbox(bb); +} + + +void Scene_lcc_item::draw(CGAL::Three::Viewer_interface* viewer) const +{ + if(!isInit()) + initGL(); + if ( getBuffersFilled() && + ! getBuffersInit(viewer)) + { + initializeBuffers(viewer); + setBuffersInit(viewer, true); + } + if(!getBuffersFilled()) + { + computeElements(); + initializeBuffers(viewer); + } + + getTriangleContainer(0)->setColor(this->color()); + getTriangleContainer(0)->draw(viewer, true); +} + +void Scene_lcc_item::drawEdges(CGAL::Three::Viewer_interface* viewer) const +{ + if(!isInit()) + initGL(); + if ( getBuffersFilled() && + ! getBuffersInit(viewer)) + { + initializeBuffers(viewer); + setBuffersInit(viewer, true); + } + if(!getBuffersFilled()) + { + computeElements(); + initializeBuffers(viewer); + } + GLfloat offset_factor; + GLfloat offset_units; + viewer->glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &offset_factor); + viewer->glGetFloatv(GL_POLYGON_OFFSET_UNITS, &offset_units); + viewer->glEnable(GL_POLYGON_OFFSET_LINE); + viewer->glPolygonOffset(0.3f, 0.3f); + if(viewer->isOpenGL_4_3()) + { + QVector2D vp(viewer->width(), viewer->height()); + + getEdgeContainer(0)->setViewport(vp); + getEdgeContainer(0)->setWidth(2); + } + getEdgeContainer(0)->setColor(QColor(Qt::black)); + getEdgeContainer(0)->draw(viewer, true); + drawPoints(viewer); + viewer->glDisable(GL_POLYGON_OFFSET_LINE); + viewer->glPolygonOffset(offset_factor, offset_units); +} + +void Scene_lcc_item::drawPoints(CGAL::Three::Viewer_interface* viewer) const +{ + if(!visible()) + return; + if(!isInit()) + initGL(); + if ( getBuffersFilled() && + ! getBuffersInit(viewer)) + { + initializeBuffers(viewer); + setBuffersInit(viewer, true); + } + GLfloat point_size; + viewer->glGetFloatv(GL_POINT_SIZE, &point_size); + viewer->setGlPointSize(GLfloat(5)); + if(!getBuffersFilled()) + { + computeElements(); + initializeBuffers(viewer); + } + + getPointContainer(0)->setColor(QColor(Qt::black)); + getPointContainer(0)->draw(viewer, true); + viewer->setGlPointSize(point_size); +} + +void Scene_lcc_item::computeElements() const +{ + CGAL::Three::Three::CursorScopeGuard guard(QCursor(Qt::WaitCursor)); + + typename LCC::size_type markvolumes = 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 markvertices = d->lcc.get_new_mark(); + + for (typename LCC::Dart_range::const_iterator it=d->lcc.darts().begin(), + itend=d->lcc.darts().end(); it!=itend; ++it ) + { + if (!d->lcc.is_marked(it, markvolumes)) + { + for (typename LCC::template Dart_of_cell_basic_range<3>:: + const_iterator itv=d->lcc.template darts_of_cell_basic<3>(it, markvolumes).begin(), + itvend=d->lcc.template darts_of_cell_basic<3>(it, markvolumes).end(); + itv!=itvend; ++itv) + { + 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)) + { + d->compute_face(itv); + for (typename LCC::template Dart_of_cell_basic_range<2>:: + 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(); + itf!=itfend; ++itf) + { + d->lcc.mark(itf, markfaces); // To be sure that all darts of the basic iterator will be marked + if ( !d->lcc.is_marked(itf, markedges)) + { + Point p1 = d->lcc.point(itf); + LCC::Dart_const_handle d2 = d->lcc.other_extremity(itf); + Point p2 = d->lcc.point(d2); + d->lines.push_back(p1.x()); + d->lines.push_back(p1.y()); + d->lines.push_back(p1.z()); + + d->lines.push_back(p2.x()); + d->lines.push_back(p2.y()); + d->lines.push_back(p2.z()); + + for (typename LCC::template Dart_of_cell_basic_range<1>:: + const_iterator ite=d->lcc.template darts_of_cell_basic<1>(itf, markedges).begin(), + iteend=d->lcc.template darts_of_cell_basic<1>(itf, markedges).end(); + ite!=iteend; ++ite) + { + d->lcc.mark(ite, markedges); // To be sure that all darts of the basic iterator will be marked + if ( !d->lcc.is_marked(ite, markvertices)) + { + Point p1 = d->lcc.point(ite); + d->vertices.push_back(p1.x()); + d->vertices.push_back(p1.y()); + d->vertices.push_back(p1.z()); + CGAL::mark_cell(d->lcc, ite, markvertices); + } + } + } + } + } + } + } + } + + for (typename LCC::Dart_range::const_iterator it=d->lcc.darts().begin(), + itend=d->lcc.darts().end(); it!=itend; ++it ) + { + d->lcc.unmark(it, markvertices); + d->lcc.unmark(it, markedges); + d->lcc.unmark(it, markfaces); + d->lcc.unmark(it, markvolumes); + + } + + d->lcc.free_mark(markvolumes); + d->lcc.free_mark(markfaces); + d->lcc.free_mark(markedges); + d->lcc.free_mark(markvertices); + + getTriangleContainer(0)->allocate( + Tri::Flat_vertices, d->faces.data(), + static_cast(d->faces.size()*sizeof(float))); + + getEdgeContainer(0)->allocate( + Ec::Vertices, d->lines.data(), + static_cast(d->lines.size()*sizeof(float))); + + getPointContainer(0)->allocate( + Pc::Vertices, d->vertices.data(), + static_cast(d->vertices.size()*sizeof(float))); + + setBuffersFilled(true); + d->nb_faces = d->faces.size(); + d->nb_lines = d->lines.size(); + d->nb_vertices= d->vertices.size(); +} +void Scene_lcc_item::initializeBuffers(CGAL::Three::Viewer_interface *viewer) const +{ + getTriangleContainer(0)->initializeBuffers(viewer); + getTriangleContainer(0)->setFlatDataSize(d->nb_faces); + getEdgeContainer(0)->initializeBuffers(viewer); + getEdgeContainer(0)->setFlatDataSize(d->nb_lines); + getPointContainer(0)->initializeBuffers(viewer); + getPointContainer(0)->setFlatDataSize(d->nb_vertices); + + d->faces.clear(); + d->faces.shrink_to_fit(); + d->lines.clear(); + d->lines.shrink_to_fit(); + d->vertices.clear(); + d->vertices.shrink_to_fit(); +} + +void Scene_lcc_item::invalidateOpenGLBuffers() +{ + setBuffersFilled(false); + getTriangleContainer(0)->reset_vbos(ALL); + getEdgeContainer(0)->reset_vbos(ALL); + getPointContainer(0)->reset_vbos(ALL); + compute_bbox(); +} + +bool Scene_lcc_item::isEmpty() const +{ + return false; +} diff --git a/Polyhedron/demo/Polyhedron/Scene_lcc_item.h b/Polyhedron/demo/Polyhedron/Scene_lcc_item.h new file mode 100644 index 00000000000..c15fae6d751 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Scene_lcc_item.h @@ -0,0 +1,53 @@ +#ifndef SCENE_LCC_ITEM_H +#define SCENE_LCC_ITEM_H + +#include +#include + +#ifdef scene_lcc_item_EXPORTS +# define SCENE_LCC_ITEM_EXPORT Q_DECL_EXPORT +#else +# define SCENE_LCC_ITEM_EXPORT Q_DECL_IMPORT +#endif + +struct lcc_priv; +namespace CGAL{ +namespace Three{ +class Viewer_interface; +} +} + +class SCENE_LCC_ITEM_EXPORT Scene_lcc_item : public CGAL::Three::Scene_item_rendering_helper +{ + Q_OBJECT +public: + typedef CGAL::Linear_cell_complex_for_combinatorial_map<3> LCC; + Scene_lcc_item(const LCC &lcc); + ~Scene_lcc_item(); + + bool isEmpty()const; + bool isFinite() const { return true; } + + Scene_lcc_item* clone() const Q_DECL_OVERRIDE ; + bool supportsRenderingMode(RenderingMode m) const Q_DECL_OVERRIDE ; + QString toolTip() const Q_DECL_OVERRIDE ; + void compute_bbox()const; + + + void draw(CGAL::Three::Viewer_interface*) const Q_DECL_OVERRIDE ; + void drawEdges(CGAL::Three::Viewer_interface*) const Q_DECL_OVERRIDE ; + void drawPoints(CGAL::Three::Viewer_interface*) const Q_DECL_OVERRIDE ; + + void computeElements() const Q_DECL_OVERRIDE; + void initializeBuffers(CGAL::Three::Viewer_interface *) const Q_DECL_OVERRIDE; + +public Q_SLOTS: + void invalidateOpenGLBuffers() Q_DECL_OVERRIDE; + +private: + friend struct lcc_priv; + lcc_priv* d; +}; + +#endif // SCENE_LCC_ITEM_H +