From ef7279aaeb258cccbc829eb5ec85459906af716a Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 24 Jul 2018 11:02:57 +0200 Subject: [PATCH 01/25] WIP --- .../Polyhedron/Plugins/PMP/CMakeLists.txt | 4 + .../Plugins/PMP/Engrave_dock_widget.ui | 73 +++++++ .../Plugins/PMP/Engrave_text_plugin.cpp | 186 ++++++++++++++++++ 3 files changed, 263 insertions(+) create mode 100644 Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui create mode 100644 Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt index a626bc567d9..757e710dd18 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt @@ -170,3 +170,7 @@ target_link_libraries(extrude_poly_plugin PUBLIC scene_polyhedron_item scene_pol polyhedron_demo_plugin(extrude_sm_plugin Extrude_plugin) target_link_libraries(extrude_sm_plugin PUBLIC scene_surface_mesh_item scene_surface_mesh_selection_item) target_compile_definitions(extrude_sm_plugin PUBLIC "-DUSE_SURFACE_MESH" ) + +qt5_wrap_ui( engravUI_FILES Engrave_dock_widget.ui ) +polyhedron_demo_plugin(engrave_text_plugin Engrave_text_plugin ${engravUI_FILES}) +target_link_libraries(engrave_text_plugin PUBLIC scene_surface_mesh_item scene_surface_mesh_selection_item scene_polylines_item) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui new file mode 100644 index 00000000000..fcbf8b313cd --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui @@ -0,0 +1,73 @@ + + + EngraveWidget + + + + 0 + 0 + 400 + 300 + + + + Engraving + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Visualize + + + + + + + An Example Text + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + false + + + Engrave + + + + + + + + + diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp new file mode 100644 index 00000000000..11f745b6fdd --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -0,0 +1,186 @@ +//General Plugin Data +#include +#include + +#include "ui_Engrave_dock_widget.h" +//Items +#include "Scene_surface_mesh_item.h" +#include "Scene_polyhedron_selection_item.h" +#include "Scene_polylines_item.h" + +//Actual code reqs +#include +#include + +#include +#include +#include +#include + +#include + + +using namespace CGAL::Three; + +class EngraveWidget : + public QDockWidget, + public Ui::EngraveWidget +{ +public: + EngraveWidget(QString name, QWidget *parent) + :QDockWidget(name,parent) + { + setupUi(this); + } +}; + +class Q_DECL_EXPORT Engrave_text_plugin : + public QObject, + public Polyhedron_demo_plugin_helper +{ + Q_OBJECT + Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface) + Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0") +public : + void init(QMainWindow* , CGAL::Three::Scene_interface* , Messages_interface*) Q_DECL_OVERRIDE{ + //get refs + this->scene = Three::scene(); + this->mw = Three::mainWindow(); + + //action + QAction* actionFitText= new QAction("Fit Text", mw); + if(actionFitText) { + connect(actionFitText, SIGNAL(triggered()), + this, SLOT(showWidget())); + _actions << actionFitText; + //widget + dock_widget = new EngraveWidget("Engraving", mw); + dock_widget->setVisible(false); // do not show at the beginning + addDockWidget(dock_widget); + connect(dock_widget->visualizeButton, &QPushButton::clicked, + this, &Engrave_text_plugin::visualize); + connect(dock_widget->engraveButton, &QPushButton::clicked, + this, &Engrave_text_plugin::engrave); + + //items + visu_item = NULL; + + } + } + bool applicable(QAction*) const Q_DECL_OVERRIDE + { + return qobject_cast + (scene->item(scene->mainSelectionIndex())); + } + QList actions() const Q_DECL_OVERRIDE{ + return _actions; + } +public Q_SLOTS: + void showWidget() + { + dock_widget->setVisible(!dock_widget->isVisible()); + } + + void visualize() { + + // read text file + std::vector< std::vector > polylines; + int nb_pts = 0; + while( text_in >> nb_pts) + { + polylines.push_back( std::vector() ); + polylines.back().reserve(nb_pts); + double x, y, z; + for (int i=0; i> x >> y >> z; + if (z!=0) + std::cerr << "z-coordinate of a point is not 0: " << z << "\n"; + polylines.back().push_back( Point_3(x,y,z) ); + } + } + dock_widget->engraveButton->setEnabled(true); + dock_widget->visualizeButton->setEnabled(false); + } + + void engrave() { + if(!visu_item) + return; + + namespace SMP = CGAL::Surface_mesh_parameterization; + typedef CGAL::Surface_mesh_shortest_path_traits SP_traits; + typedef CGAL::Surface_mesh_shortest_path Surface_mesh_shortest_path; + typedef Surface_mesh_shortest_path::Face_location Face_location; + typedef CGAL::AABB_face_graph_triangle_primitive Primitive; + typedef CGAL::AABB_traits Tree_traits; + typedef CGAL::AABB_tree Tree; + SMesh& sm = *qobject_cast + (scene->item(scene->mainSelectionIndex()))->polyhedron(); + SMesh::Halfedge_index hd = + CGAL::Polygon_mesh_processing::longest_border(sm).first; + SMesh::Property_map uv_map = + sm.add_property_map("v:uv").first; + + // Parameterized bool pmap + boost::unordered_set vs; + SMP::internal::Bool_property_map< boost::unordered_set > vpm(vs); + + // Parameterizer + SMP::ARAP_parameterizer_3 parameterizer; + + SMP::Error_code status = parameterizer.parameterize(sm, hd, uv_map, get(boost::vertex_index, sm), vpm); + if(status != SMP::OK) { + std::cout << "Encountered a problem: " << status << std::endl; + return ; + } + + std::cout << "Parameterized with ARAP (SM)!" << std::endl; + + SMesh::Property_map uv_map_3 = + sm.add_property_map("v:uv3").first; + for(SMesh::Vertex_index v : sm.vertices()) + uv_map_3[v] = Point_3(uv_map[v][0], uv_map[v] + [1], 0); + +/* // debug to print 2d mesh + std::ofstream out("param_out.off"); + out << "OFF\n" << sm.number_of_vertices() << " " << sm.number_of_faces() << " 0\n"; + for(Surface_mesh::Vertex_index v : sm.vertices()) + out << uv_map_3[v] << "\n"; + for(Surface_mesh::Face_index f : faces(sm)) + { + Surface_mesh::Halfedge_index h = sm.halfedge(f); + out << "3 " << (unsigned) sm.target(h) << " " + << (unsigned) sm.target(sm.next(h)) << " " + << (unsigned) sm.source(h) << "\n"; + } + */ + + + // build AABB-tree for face location queries + Tree aabb_tree(faces(sm).first, faces(sm).second, sm, uv_map_3); + + // compute 3D coordinates + BOOST_FOREACH(const std::vector& polyline, visu_item->polylines().front()); + { + BOOST_FOREACH(const Point_3& p, polyline) + { + Face_location loc = Surface_mesh_shortest_path::locate(p, aabb_tree, sm, uv_map_3); + } + } + + scene->erase(scene->item_id(visu_item)); + visu_item = NULL; + dock_widget->engraveButton->setEnabled(false); + dock_widget->visualizeButton->setEnabled(true); + } + void closure()Q_DECL_OVERRIDE + { + dock_widget->hide(); + } +private: + QList _actions; + EngraveWidget* dock_widget; + Scene_polylines_item* visu_item; +}; +#include "Engrave_text_plugin.moc" From 17b691b2d77344ebd602ed3aa7b16feef0f46a60 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 25 Jul 2018 09:38:47 +0200 Subject: [PATCH 02/25] WIP --- .../Plugins/PMP/Engrave_dock_widget.ui | 64 ++++-- .../Plugins/PMP/Engrave_text_plugin.cpp | 185 ++++++++++++------ 2 files changed, 172 insertions(+), 77 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui index fcbf8b313cd..3a9b866c170 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui @@ -15,7 +15,7 @@ - + Qt::Horizontal @@ -28,17 +28,13 @@ - - - - Visualize + + + + false - - - - - - An Example Text + + Engrave @@ -56,15 +52,51 @@ - - - false - + - Engrave + Visualize + + + + An Example Text + + + + + + + + + -> + + + + + + + <- + + + + + + + <-R + + + + + + + R-> + + + + + diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index 11f745b6fdd..8886941d1ec 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -18,6 +18,7 @@ #include #include +#include using namespace CGAL::Three; @@ -65,7 +66,31 @@ public : //items visu_item = NULL; + //transfo + angle = 0.0; + translation = EPICK::Vector_2(0,0); + connect(dock_widget->t_left_pushButton, &QPushButton::clicked, + [this](){ + translation -= EPICK::Vector_2(1,0); + visualize(); + }); + + connect(dock_widget->t_right_pushButton, &QPushButton::clicked, + [this](){ + translation += EPICK::Vector_2(1,0); + visualize(); + }); } + connect(dock_widget->r_right_pushButton, &QPushButton::clicked, + [this](){ + angle += 0.15; + visualize(); + }); + connect(dock_widget->r_left_pushButton, &QPushButton::clicked, + [this](){ + angle -= 0.15; + visualize(); + }); } bool applicable(QAction*) const Q_DECL_OVERRIDE { @@ -82,9 +107,14 @@ public Q_SLOTS: } void visualize() { - + + if(visu_item) + scene->erase(scene->item_id(visu_item)); + visu_item = NULL; + typedef EPICK::Point_3 Point_3; // read text file - std::vector< std::vector > polylines; + std::ifstream text_in("/home/gimeno/Data/Polylines/text.polylines.txt"); + Scene_polylines_item::Polylines_container polylines; int nb_pts = 0; while( text_in >> nb_pts) { @@ -99,13 +129,6 @@ public Q_SLOTS: polylines.back().push_back( Point_3(x,y,z) ); } } - dock_widget->engraveButton->setEnabled(true); - dock_widget->visualizeButton->setEnabled(false); - } - - void engrave() { - if(!visu_item) - return; namespace SMP = CGAL::Surface_mesh_parameterization; typedef CGAL::Surface_mesh_shortest_path_traits SP_traits; @@ -114,73 +137,113 @@ public Q_SLOTS: typedef CGAL::AABB_face_graph_triangle_primitive Primitive; typedef CGAL::AABB_traits Tree_traits; typedef CGAL::AABB_tree Tree; - SMesh& sm = *qobject_cast - (scene->item(scene->mainSelectionIndex()))->polyhedron(); + typedef EPICK::Point_3 Point_3; + Scene_polyhedron_selection_item* sel_item = + qobject_cast + (scene->item(scene->mainSelectionIndex())); + Point_3 basis_3[3]; + int i=0; + for(Scene_polyhedron_selection_item::Selection_set_vertex::iterator it + = sel_item->selected_vertices.begin(); + it != sel_item->selected_vertices.end(); + ++it) + { + basis_3[(i++)%3] = sel_item->polyhedron()->point( + *it); + } + SMesh sm; + sel_item->export_selected_facets_as_polyhedron(&sm); SMesh::Halfedge_index hd = - CGAL::Polygon_mesh_processing::longest_border(sm).first; - SMesh::Property_map uv_map = + CGAL::Polygon_mesh_processing::longest_border(sm).first; + SMesh::Property_map uv_map = sm.add_property_map("v:uv").first; - // Parameterized bool pmap - boost::unordered_set vs; - SMP::internal::Bool_property_map< boost::unordered_set > vpm(vs); + // Parameterized bool pmap + boost::unordered_set vs; + SMP::internal::Bool_property_map< boost::unordered_set > vpm(vs); - // Parameterizer - SMP::ARAP_parameterizer_3 parameterizer; + // Parameterizer + SMP::ARAP_parameterizer_3 parameterizer; - SMP::Error_code status = parameterizer.parameterize(sm, hd, uv_map, get(boost::vertex_index, sm), vpm); - if(status != SMP::OK) { - std::cout << "Encountered a problem: " << status << std::endl; - return ; + SMP::Error_code status = parameterizer.parameterize(sm, hd, uv_map, get(boost::vertex_index, sm), vpm); + if(status != SMP::OK) { + std::cout << "Encountered a problem: " << status << std::endl; + return ; + } + + std::cout << "Parameterized with ARAP (SM)!" << std::endl; + + + SMesh::Property_map uv_map_3 = + sm.add_property_map("v:uv3").first; + for(SMesh::Vertex_index v : sm.vertices()) + uv_map_3[v] = Point_3(uv_map[v][0], uv_map[v] + [1], 0); + // build AABB-tree for face location queries + Tree aabb_tree(faces(sm).first, faces(sm).second, sm, uv_map_3); + + //get 2D basis + EPICK::Vector_2 basis_2[3]; + for(int i=0; i<3; ++i) + { + Surface_mesh_shortest_path::Face_location coord = Surface_mesh_shortest_path::locate(basis_3[i], aabb_tree, sm, uv_map_3); + EPICK::Point_2 face_points[3]; + SMesh::Face_index f = SMesh::Face_index(coord.first); + face_points[0] = uv_map[source(halfedge(f,sm),sm)]; + face_points[1] = uv_map[target(halfedge(f,sm),sm)]; + face_points[2] = uv_map[target(next(halfedge(f,sm),sm),sm)]; + + basis_2[i] = EPICK::Vector_2( + coord.second[0]*face_points[0].x() + +coord.second[1]*face_points[1].x() + +coord.second[2]*face_points[2].x(), + coord.second[0]*face_points[0].y() + +coord.second[1]*face_points[1].y() + +coord.second[2]*face_points[2].y()); + } + + Scene_polylines_item* visu_item = new Scene_polylines_item; + // compute 3D coordinates + EPICK::Aff_transformation_2 transfo = + EPICK::Aff_transformation_2(CGAL::ROTATION,sin(angle), cos(angle)) * EPICK::Aff_transformation_2(CGAL::TRANSLATION, translation); + BOOST_FOREACH(const std::vector& polyline, polylines) + { + visu_item->polylines.push_back(std::vector()); + BOOST_FOREACH(const Point_3& p, polyline) + { + EPICK::Vector_2 p_2 = transfo.transform(basis_2[0]+basis_2[1]*p.x()+basis_2[2]*p.y()); + + Face_location loc = Surface_mesh_shortest_path::locate( + Point_3(p_2.x(), p_2.y(), 0), + aabb_tree, sm, uv_map_3); + visu_item->polylines.back().push_back(Surface_mesh_shortest_path::point(loc.first, loc.second, sm, sm.points())); } + } + visu_item->setName("Text"); + visu_item->setColor(QColor(Qt::red)); + scene->addItem(visu_item); + //dock_widget->engraveButton->setEnabled(true); + //dock_widget->visualizeButton->setEnabled(false); + } + + void engrave() { + if(!visu_item) + return; - std::cout << "Parameterized with ARAP (SM)!" << std::endl; - SMesh::Property_map uv_map_3 = - sm.add_property_map("v:uv3").first; - for(SMesh::Vertex_index v : sm.vertices()) - uv_map_3[v] = Point_3(uv_map[v][0], uv_map[v] - [1], 0); - -/* // debug to print 2d mesh - std::ofstream out("param_out.off"); - out << "OFF\n" << sm.number_of_vertices() << " " << sm.number_of_faces() << " 0\n"; - for(Surface_mesh::Vertex_index v : sm.vertices()) - out << uv_map_3[v] << "\n"; - for(Surface_mesh::Face_index f : faces(sm)) - { - Surface_mesh::Halfedge_index h = sm.halfedge(f); - out << "3 " << (unsigned) sm.target(h) << " " - << (unsigned) sm.target(sm.next(h)) << " " - << (unsigned) sm.source(h) << "\n"; - } - */ - - - // build AABB-tree for face location queries - Tree aabb_tree(faces(sm).first, faces(sm).second, sm, uv_map_3); - - // compute 3D coordinates - BOOST_FOREACH(const std::vector& polyline, visu_item->polylines().front()); - { - BOOST_FOREACH(const Point_3& p, polyline) - { - Face_location loc = Surface_mesh_shortest_path::locate(p, aabb_tree, sm, uv_map_3); - } - } - - scene->erase(scene->item_id(visu_item)); - visu_item = NULL; dock_widget->engraveButton->setEnabled(false); dock_widget->visualizeButton->setEnabled(true); } void closure()Q_DECL_OVERRIDE - { - dock_widget->hide(); - } + { + dock_widget->hide(); + } private: QList _actions; EngraveWidget* dock_widget; Scene_polylines_item* visu_item; + double angle; + EPICK::Vector_2 translation; }; #include "Engrave_text_plugin.moc" + From 91610ccf3f488f1ff900c6b232706ebef8ad6961 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 30 Jul 2018 09:47:49 +0200 Subject: [PATCH 03/25] WIP Create Text Polyline --- .../Plugins/PMP/Engrave_text_plugin.cpp | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index 8886941d1ec..8c2a5aaede4 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -19,7 +19,7 @@ #include #include - +#include using namespace CGAL::Three; @@ -107,8 +107,23 @@ public Q_SLOTS: } void visualize() { - - if(visu_item) + Viewer_interface* viewer = static_cast(CGAL::QGLViewer::QGLViewerPool().first()); + QPainterPath path; + QFont font; + font.setPointSize(15); + path.addText(QPointF(viewer->width()/2,viewer->height()/2), font, dock_widget->lineEdit->text()); + viewer->getPainter()->begin(viewer); + viewer->getPainter()->drawPath(path); + viewer->getPainter()->end(); + QPolygonF poly = path.toFillPolygon(); + Scene_polylines_item* new_poly = new Scene_polylines_item(); + new_poly->polylines.push_back(Scene_polylines_item::Polyline()); + Q_FOREACH(QPointF pf, poly) + { + new_poly->polylines.front().push_back(Point_3(pf.x(), pf.y(), 0)); + } + scene->addItem(new_poly); + /* if(visu_item) scene->erase(scene->item_id(visu_item)); visu_item = NULL; typedef EPICK::Point_3 Point_3; @@ -224,6 +239,7 @@ public Q_SLOTS: scene->addItem(visu_item); //dock_widget->engraveButton->setEnabled(true); //dock_widget->visualizeButton->setEnabled(false); + */ } void engrave() { From 8c438f882152d72d3f03de1c0cbacad96604d875 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 30 Jul 2018 14:44:37 +0200 Subject: [PATCH 04/25] WIP positionning text --- .../Plugins/PMP/Engrave_text_plugin.cpp | 163 +++++++++--------- 1 file changed, 82 insertions(+), 81 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index 8c2a5aaede4..1472456e337 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -11,7 +11,7 @@ //Actual code reqs #include #include - +#include #include #include #include @@ -70,24 +70,24 @@ public : angle = 0.0; translation = EPICK::Vector_2(0,0); connect(dock_widget->t_left_pushButton, &QPushButton::clicked, - [this](){ - translation -= EPICK::Vector_2(1,0); + this, [this](){ + translation -= EPICK::Vector_2(0.1,0); visualize(); }); connect(dock_widget->t_right_pushButton, &QPushButton::clicked, - [this](){ - translation += EPICK::Vector_2(1,0); + this, [this](){ + translation += EPICK::Vector_2(0.1,0); visualize(); }); } connect(dock_widget->r_right_pushButton, &QPushButton::clicked, - [this](){ + this, [this](){ angle += 0.15; visualize(); }); connect(dock_widget->r_left_pushButton, &QPushButton::clicked, - [this](){ + this, [this](){ angle -= 0.15; visualize(); }); @@ -107,43 +107,16 @@ public Q_SLOTS: } void visualize() { - Viewer_interface* viewer = static_cast(CGAL::QGLViewer::QGLViewerPool().first()); - QPainterPath path; - QFont font; - font.setPointSize(15); - path.addText(QPointF(viewer->width()/2,viewer->height()/2), font, dock_widget->lineEdit->text()); - viewer->getPainter()->begin(viewer); - viewer->getPainter()->drawPath(path); - viewer->getPainter()->end(); - QPolygonF poly = path.toFillPolygon(); - Scene_polylines_item* new_poly = new Scene_polylines_item(); - new_poly->polylines.push_back(Scene_polylines_item::Polyline()); - Q_FOREACH(QPointF pf, poly) - { - new_poly->polylines.front().push_back(Point_3(pf.x(), pf.y(), 0)); - } - scene->addItem(new_poly); - /* if(visu_item) + Scene_polyhedron_selection_item* sel_item = + qobject_cast + (scene->item(scene->mainSelectionIndex())); + if(!sel_item) + return; + if(sel_item->selected_facets.empty()) + return; + if(visu_item) scene->erase(scene->item_id(visu_item)); visu_item = NULL; - typedef EPICK::Point_3 Point_3; - // read text file - std::ifstream text_in("/home/gimeno/Data/Polylines/text.polylines.txt"); - Scene_polylines_item::Polylines_container polylines; - int nb_pts = 0; - while( text_in >> nb_pts) - { - polylines.push_back( std::vector() ); - polylines.back().reserve(nb_pts); - double x, y, z; - for (int i=0; i> x >> y >> z; - if (z!=0) - std::cerr << "z-coordinate of a point is not 0: " << z << "\n"; - polylines.back().push_back( Point_3(x,y,z) ); - } - } namespace SMP = CGAL::Surface_mesh_parameterization; typedef CGAL::Surface_mesh_shortest_path_traits SP_traits; @@ -153,19 +126,6 @@ public Q_SLOTS: typedef CGAL::AABB_traits Tree_traits; typedef CGAL::AABB_tree Tree; typedef EPICK::Point_3 Point_3; - Scene_polyhedron_selection_item* sel_item = - qobject_cast - (scene->item(scene->mainSelectionIndex())); - Point_3 basis_3[3]; - int i=0; - for(Scene_polyhedron_selection_item::Selection_set_vertex::iterator it - = sel_item->selected_vertices.begin(); - it != sel_item->selected_vertices.end(); - ++it) - { - basis_3[(i++)%3] = sel_item->polyhedron()->point( - *it); - } SMesh sm; sel_item->export_selected_facets_as_polyhedron(&sm); SMesh::Halfedge_index hd = @@ -187,37 +147,78 @@ public Q_SLOTS: } std::cout << "Parameterized with ARAP (SM)!" << std::endl; - - SMesh::Property_map uv_map_3 = sm.add_property_map("v:uv3").first; + float xmin(std::numeric_limits::max()), xmax(std::numeric_limits::min()), + ymin(std::numeric_limits::max()), ymax(std::numeric_limits::min()); for(SMesh::Vertex_index v : sm.vertices()) + { uv_map_3[v] = Point_3(uv_map[v][0], uv_map[v] [1], 0); + if(uv_map[v][0] > xmax) + xmax = uv_map[v][0]; + if(uv_map[v][0] < xmin) + xmin = uv_map[v][0]; + + if(uv_map[v][1] > ymax) + ymax = uv_map[v][1]; + if(uv_map[v][1] < ymin) + ymin = uv_map[v][1]; + } + std::cout<<"xmax = "<(CGAL::QGLViewer::QGLViewerPool().first()); + QPainterPath path; + QFont font; + font.setPointSize(15); + + path.addText(QPoint(xmin,-ymin), font, dock_widget->lineEdit->text()); + viewer->getPainter()->begin(viewer); + viewer->getPainter()->drawPath(path); + viewer->getPainter()->end(); + QTransform trans; + + QList polys = path.toFillPolygons(); + //Scene_polylines_item* new_poly = new Scene_polylines_item(); + Scene_polylines_item::Polylines_container polylines; + QFontMetrics fm(font); + int width=fm.width(dock_widget->lineEdit->text()); + int height=fm.height(); + std::cout<<"width = "<addItem(visu_item); //dock_widget->engraveButton->setEnabled(true); //dock_widget->visualizeButton->setEnabled(false); - */ } void engrave() { From d7c67dfcdf9a1ac47307f2f12db8724d0582a4b3 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 30 Jul 2018 16:04:47 +0200 Subject: [PATCH 05/25] WIP engrave --- .../Plugins/PMP/Engrave_dock_widget.ui | 36 ++- .../Plugins/PMP/Engrave_text_plugin.cpp | 220 ++++++++++++++++-- 2 files changed, 222 insertions(+), 34 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui index 3a9b866c170..63aa67f94a5 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui @@ -67,13 +67,6 @@ - - - - -> - - - @@ -81,17 +74,38 @@ - + + + + R-> + + + + + + + -> + + + + <-R - - + + - R-> + ^ + + + + + + + V diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index 1472456e337..d4ddd028b6f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -16,6 +16,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -70,24 +77,36 @@ public : angle = 0.0; translation = EPICK::Vector_2(0,0); connect(dock_widget->t_left_pushButton, &QPushButton::clicked, - this, [this](){ - translation -= EPICK::Vector_2(0.1,0); + this, [this](){ + translation -= EPICK::Vector_2(0.05,0); + visualize(); + }); + + connect(dock_widget->t_up_pushButton, &QPushButton::clicked, + this, [this](){ + translation -= EPICK::Vector_2(0,-0.05); + visualize(); + }); + + connect(dock_widget->t_down_pushButton, &QPushButton::clicked, + this, [this](){ + translation -= EPICK::Vector_2(0,0.05); visualize(); }); connect(dock_widget->t_right_pushButton, &QPushButton::clicked, - this, [this](){ - translation += EPICK::Vector_2(0.1,0); + this, [this](){ + translation += EPICK::Vector_2(0.05,0); visualize(); }); } connect(dock_widget->r_right_pushButton, &QPushButton::clicked, - this, [this](){ + this, [this](){ angle += 0.15; visualize(); }); connect(dock_widget->r_left_pushButton, &QPushButton::clicked, - this, [this](){ + this, [this](){ angle -= 0.15; visualize(); }); @@ -150,7 +169,7 @@ public Q_SLOTS: SMesh::Property_map uv_map_3 = sm.add_property_map("v:uv3").first; float xmin(std::numeric_limits::max()), xmax(std::numeric_limits::min()), - ymin(std::numeric_limits::max()), ymax(std::numeric_limits::min()); + ymin(std::numeric_limits::max()), ymax(std::numeric_limits::min()); for(SMesh::Vertex_index v : sm.vertices()) { uv_map_3[v] = Point_3(uv_map[v][0], uv_map[v] @@ -168,16 +187,16 @@ public Q_SLOTS: std::cout<<"xmax = "<getPainter()->end(); QTransform trans; - QList polys = path.toFillPolygons(); + QList polys = path.toSubpathPolygons(); //Scene_polylines_item* new_poly = new Scene_polylines_item(); Scene_polylines_item::Polylines_container polylines; QFontMetrics fm(font); @@ -221,7 +240,7 @@ public Q_SLOTS: visu_item = new Scene_polylines_item; // compute 3D coordinates EPICK::Aff_transformation_2 transfo = - EPICK::Aff_transformation_2(CGAL::ROTATION,sin(angle), cos(angle)) * EPICK::Aff_transformation_2(CGAL::TRANSLATION, translation); + EPICK::Aff_transformation_2(CGAL::ROTATION,sin(angle), cos(angle)) * EPICK::Aff_transformation_2(CGAL::TRANSLATION, translation); BOOST_FOREACH(const std::vector& polyline, polylines) { visu_item->polylines.push_back(std::vector()); @@ -232,22 +251,86 @@ public Q_SLOTS: Face_location loc = Surface_mesh_shortest_path::locate( Point_3(p_2.x(), p_2.y(), 0), aabb_tree, sm, uv_map_3); - visu_item->polylines.back().push_back(//Point_3(p_2.x(), p_2.y(), 0)); - Surface_mesh_shortest_path::point(loc.first, loc.second, sm, sm.points())); + visu_item->polylines.back().push_back(//p); + Surface_mesh_shortest_path::point(loc.first, loc.second, sm, sm.points())); } } visu_item->setName("Text"); visu_item->setColor(QColor(Qt::red)); scene->addItem(visu_item); - //dock_widget->engraveButton->setEnabled(true); - //dock_widget->visualizeButton->setEnabled(false); + dock_widget->engraveButton->setEnabled(true); + dock_widget->visualizeButton->setEnabled(false); } void engrave() { if(!visu_item) return; + typedef CGAL::Projection_traits_xy_3 Gt; + typedef CGAL::Delaunay_mesh_vertex_base_2 Vb; + typedef CGAL::Delaunay_mesh_face_base_2 Fm; + typedef CGAL::Triangulation_face_base_with_info_2 Fb; + typedef CGAL::Triangulation_data_structure_2 TDS; + typedef CGAL::No_intersection_tag Tag; + typedef CGAL::Constrained_Delaunay_triangulation_2 CDT; + typedef CGAL::Delaunay_mesh_size_criteria_2 Criteria; + typedef CGAL::Delaunay_mesher_2 Mesher; + + CDT cdt; + try{ + Q_FOREACH(const std::vector& points, + visu_item->polylines) + cdt.insert_constraint(points.begin(),points.end()); + }catch(std::runtime_error&) + { + QApplication::restoreOverrideCursor(); + throw; + } + if (cdt.dimension()!=2){ + QApplication::restoreOverrideCursor(); + std::cout << "Triangulation is not of dimension 2" << std::endl; + return; + } + Scene_item::Bbox bbox= visu_item->bbox(); + float diag = CGAL::sqrt( + (bbox.xmax()-bbox.xmin())*(bbox.xmax()-bbox.xmin()) + +(bbox.ymax()-bbox.ymin())*(bbox.ymax()-bbox.ymin()) + +(bbox.zmax()-bbox.zmax()) *(bbox.zmax()-bbox.zmax()) + ); + float zmax = bbox.zmax(), + zmin = bbox.zmin(); + //project to z=zmin for mesh_2 + BOOST_FOREACH(Scene_polylines_item::Polyline poly, visu_item->polylines) + { + BOOST_FOREACH(EPICK::Point_3& p, poly) + { + p = EPICK::Point_3(p.x(), p.y(), zmin); + } + } + // start by marking the domain to mesh + Criteria criteria(0.125, 0.05 * diag); + Mesher mesher(cdt, criteria); + + mark_nested_domains(cdt); + for(typename CDT::All_faces_iterator fit=cdt.all_faces_begin(), + fit_end=cdt.all_faces_end(); + fit!=fit_end;++fit) + { + fit->set_in_domain(fit->info().in_domain()); + } + mesher.init(true); + mesher.refine_mesh(); + SMesh text_mesh_bottom, text_mesh_complete; + cdt2_to_face_graph(cdt, + text_mesh_bottom, + 2, + zmin); + PMP::extrude_mesh(text_mesh_bottom, text_mesh_complete,EPICK::Vector_3(0,0,zmax-zmin)); + + Scene_surface_mesh_item* text_item = new Scene_surface_mesh_item(text_mesh_complete); + text_item->setColor(QColor(Qt::green)); + scene->addItem(text_item); dock_widget->engraveButton->setEnabled(false); dock_widget->visualizeButton->setEnabled(true); } @@ -256,6 +339,97 @@ public Q_SLOTS: dock_widget->hide(); } private: + + struct FaceInfo2 + { + FaceInfo2(){} + int nesting_level; + bool in_domain(){ + return nesting_level%2 == 1; + } + }; + + template + void + mark_domains(CDT& ct, + typename CDT::Face_handle start, + int index, + std::list& border ) + { + if(start->info().nesting_level != -1){ + return; + } + std::list queue; + queue.push_back(start); + while(! queue.empty()){ + typename 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++){ + typename CDT::Edge e(fh,i); + typename 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); + } + } + } + } + } + + + template + void + mark_nested_domains(CDT& cdt) + { + for(typename CDT::All_faces_iterator it = cdt.all_faces_begin(); it != cdt.all_faces_end(); ++it){ + it->info().nesting_level = -1; + } + std::list border; + mark_domains(cdt, cdt.infinite_face(), 0, border); + while(! border.empty()){ + typename CDT::Edge e = border.front(); + border.pop_front(); + typename 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); + } + } + } + + template + void cdt2_to_face_graph(const CDT& cdt, TriangleMesh& tm, int constant_coordinate_index, double constant_coordinate) + { + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + + typedef std::map Map; + Map descriptors; + for (typename CDT::Finite_faces_iterator fit=cdt.finite_faces_begin(), + fit_end=cdt.finite_faces_end(); + fit!=fit_end; ++fit) + { + if (!fit->is_in_domain()) continue; + CGAL::cpp11::array vds; + for(int i=0; i<3; ++i) + { + typename Map::iterator it; + bool insert_ok; + boost::tie(it,insert_ok) = + descriptors.insert(std::make_pair(fit->vertex(i),vertex_descriptor())); + if (insert_ok){ + const Kernel::Point_3& pt=fit->vertex(i)->point(); + double coords[3] = {pt[0], pt[1], pt[2]}; + coords[2]=constant_coordinate; + it->second = add_vertex(Kernel::Point_3(coords[0],coords[1],coords[2]), tm); + } + vds[i]=it->second; + } + + CGAL::Euler::add_face(vds, tm); + } + } + QList _actions; EngraveWidget* dock_widget; Scene_polylines_item* visu_item; From 01bef6fa22986a80212f9004dd1c56719354a26b Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 30 Jul 2018 16:43:51 +0200 Subject: [PATCH 06/25] WIP engraving --- .../Plugins/PMP/Engrave_text_plugin.cpp | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index d4ddd028b6f..b668767af9b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -7,20 +7,24 @@ #include "Scene_surface_mesh_item.h" #include "Scene_polyhedron_selection_item.h" #include "Scene_polylines_item.h" +#include "Nef_type.h" //Actual code reqs +#include + #include #include #include +#include +#include #include #include #include #include -#include +#include #include #include #include -#include #include #include @@ -133,6 +137,8 @@ public Q_SLOTS: return; if(sel_item->selected_facets.empty()) return; + if(!CGAL::is_closed(*sel_item->polyhedron())) + return; if(visu_item) scene->erase(scene->item_id(visu_item)); visu_item = NULL; @@ -259,12 +265,22 @@ public Q_SLOTS: visu_item->setColor(QColor(Qt::red)); scene->addItem(visu_item); dock_widget->engraveButton->setEnabled(true); - dock_widget->visualizeButton->setEnabled(false); + // dock_widget->visualizeButton->setEnabled(false); } void engrave() { if(!visu_item) return; + Scene_polyhedron_selection_item* sel_item = + qobject_cast + (scene->item(scene->mainSelectionIndex())); + if(!sel_item) + return; + if(sel_item->selected_facets.empty()) + return; + if(!CGAL::is_closed(*sel_item->polyhedron())) + return; + typedef CGAL::Projection_traits_xy_3 Gt; typedef CGAL::Delaunay_mesh_vertex_base_2 Vb; typedef CGAL::Delaunay_mesh_face_base_2 Fm; @@ -324,13 +340,21 @@ public Q_SLOTS: SMesh text_mesh_bottom, text_mesh_complete; cdt2_to_face_graph(cdt, text_mesh_bottom, - 2, zmin); PMP::extrude_mesh(text_mesh_bottom, text_mesh_complete,EPICK::Vector_3(0,0,zmax-zmin)); - Scene_surface_mesh_item* text_item = new Scene_surface_mesh_item(text_mesh_complete); - text_item->setColor(QColor(Qt::green)); - scene->addItem(text_item); + CGAL::Surface_mesh exact_text, + exact_target; + CGAL::copy_face_graph(text_mesh_complete, exact_text); + CGAL::copy_face_graph(*sel_item->polyhedron(), exact_target); + Nef_polyhedron nef_text(exact_text); + Nef_polyhedron nef_target(exact_target); + Nef_polyhedron new_nef = nef_target - nef_text; + SMesh result; + CGAL::convert_nef_polyhedron_to_polygon_mesh(new_nef, result); + CGAL::Polygon_mesh_processing::triangulate_faces(result); + Scene_surface_mesh_item* result_item = new Scene_surface_mesh_item(result); + scene->addItem(result_item); dock_widget->engraveButton->setEnabled(false); dock_widget->visualizeButton->setEnabled(true); } @@ -399,7 +423,7 @@ private: } template - void cdt2_to_face_graph(const CDT& cdt, TriangleMesh& tm, int constant_coordinate_index, double constant_coordinate) + void cdt2_to_face_graph(const CDT& cdt, TriangleMesh& tm, double constant_coordinate) { typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; From 70f2d2d7b31993a0e97d7323509f9b9105a59015 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 31 Jul 2018 08:45:36 +0200 Subject: [PATCH 07/25] WIP --- .../Plugins/PMP/Engrave_dock_widget.ui | 126 +++-- .../Plugins/PMP/Engrave_text_plugin.cpp | 434 ++++++++++++++---- 2 files changed, 398 insertions(+), 162 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui index 63aa67f94a5..8062175b83e 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui @@ -6,67 +6,24 @@ 0 0 - 400 - 300 + 278 + 372 Engraving - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - - Engrave - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Visualize - - - - - - - An Example Text - - - + + + + + V + + + @@ -81,6 +38,13 @@ + + + + ^ + + + @@ -95,22 +59,56 @@ - - - - ^ + + + + + + An Example Text + + + + + + + + + Qt::Horizontal - + + + 40 + 20 + + + - - - - V - - + + + + + + Visualize + + + + + + + false + + + Engrave + + + + + + + diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index b668767af9b..02a687407fb 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -30,9 +30,207 @@ #include #include + #include +#include +#include + +#include using namespace CGAL::Three; +namespace SMP = CGAL::Surface_mesh_parameterization; +typedef EPICK::Point_2 Point_2; + +typedef boost::graph_traits:: +edge_descriptor edge_descriptor; +typedef boost::graph_traits:: +halfedge_descriptor halfedge_descriptor; +typedef boost::graph_traits:: +vertex_descriptor vertex_descriptor; + +typedef boost::unordered_set:: +face_descriptor> Component; + +struct FaceInfo2 +{ + FaceInfo2(){} + int nesting_level; + bool in_domain(){ + return nesting_level%2 == 1; + } +}; + +typedef EPICK Gt; +typedef CGAL::Delaunay_mesh_vertex_base_2 Vb; +typedef CGAL::Delaunay_mesh_face_base_2 Fm; +typedef CGAL::Triangulation_face_base_with_info_2 Fb; +typedef CGAL::Triangulation_data_structure_2 TDS; +typedef CGAL::No_intersection_tag Tag; +typedef CGAL::Constrained_Delaunay_triangulation_2 CDT; +typedef CGAL::Delaunay_mesh_size_criteria_2 Criteria; +typedef CGAL::Delaunay_mesher_2 Mesher; + +//Parameterization and text displaying +class ParamItem : public QGraphicsItem +{ +public : + ParamItem(Component* component, + const std::vector > &polylines, + EPICK::Aff_transformation_2 transfo, + SMesh* graph, + QRectF brect) + : + QGraphicsItem(), + bounding_rect(brect), + component(component), + polylines(polylines), + graph(graph), + transfo(transfo){} + + ~ParamItem() + { + delete component; + delete graph; + } + + QRectF boundingRect() const + { + return bounding_rect; + } + + void set_transfo(EPICK::Aff_transformation_2 t){ transfo = t;} + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) + { + QPen pen; + QBrush brush; + brush.setColor(QColor(100, 100, 255)); + brush.setStyle(Qt::SolidPattern); + pen.setColor(Qt::black); + pen.setWidth(0); + painter->setPen(pen); + painter->setBrush(brush); + SMesh::Property_map > uv; + uv = graph->add_property_map >("h:uv",std::make_pair(0.0f,0.0f)).first; + for( Component::iterator + fi = component->begin(); + fi != component->end(); + ++fi) + { + boost::graph_traits::face_descriptor f(*fi); + QPointF points[3]; + boost::graph_traits::halfedge_descriptor h = halfedge(f, *graph);; + points[0] = QPointF(get(uv, h).first, get(uv, h).second); + h = next(halfedge(f, *graph), *graph); + points[1] = QPointF(get(uv, h).first, get(uv, h).second); + h = next(next(halfedge(f, *graph), *graph), *graph); + points[2] = QPointF(get(uv, h).first, get(uv, h).second); + painter->drawPolygon(points,3); + } + + pen.setColor(Qt::red); + pen.setWidth(0); + painter->setPen(pen); + for(std::size_t i =0; i points; + points.reserve(polylines[i].size()); + for(std::size_t j =0; jdrawPolyline(points.data(), points.size()); + } + + + + } + +private: + QString texMesh_name; + QRectF bounding_rect; + Component* component; + const std::vector >& polylines; + SMesh* graph; + EPICK::Aff_transformation_2 transfo; +}; + +class Navigation : public CGAL::Qt::GraphicsViewNavigation +{ +public: + Navigation() + :CGAL::Qt::GraphicsViewNavigation(), + prev_pos(QPoint(0,0)) + { } + +protected: + bool eventFilter(QObject *obj, QEvent *ev) + { + QGraphicsView* v = qobject_cast(obj); + if(v == NULL) { + QWidget* viewport = qobject_cast(obj); + if(viewport == NULL) { + return false; + } + v = qobject_cast(viewport->parent()); + if(v == NULL) { + return false; + } + } + switch(ev->type()) + { + case QEvent::MouseMove: { + QMouseEvent* me = static_cast(ev); + if(is_dragging) + { + qreal dir[2] = {v->mapToScene(me->pos()).x() - prev_pos.x(), + v->mapToScene(me->pos()).y() - prev_pos.y()}; + + v->translate(dir[0],dir[1]); + v->update(); + } + prev_pos = v->mapToScene(me->pos()); + break; + } + + case QEvent::MouseButtonPress: { + is_dragging = true; + break; + } + case QEvent::MouseButtonRelease: { + is_dragging = false; + break; + } + case QEvent::Wheel: { + QWheelEvent* event = static_cast(ev); + QPointF old_pos = v->mapToScene(event->pos()); + if(event->delta() <0) + v->scale(1.2, 1.2); + else + v->scale(0.8, 0.8); + QPointF new_pos = v->mapToScene(event->pos()); + QPointF delta = new_pos - old_pos; + v->translate(delta.x(), delta.y()); + v->update(); + break; + } + + case QEvent::MouseButtonDblClick: { + v->fitInView(v->scene()->itemsBoundingRect(), Qt::KeepAspectRatio); + break; + } + default: + CGAL::Qt::GraphicsViewNavigation::eventFilter(obj, ev); + } + return false; + } +private: + bool is_dragging; + QPointF prev_pos; +}; + class EngraveWidget : public QDockWidget, @@ -53,7 +251,18 @@ class Q_DECL_EXPORT Engrave_text_plugin : Q_OBJECT Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface) Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0") + +private: + typedef CGAL::Surface_mesh_shortest_path_traits SP_traits; + typedef CGAL::Surface_mesh_shortest_path Surface_mesh_shortest_path; + typedef Surface_mesh_shortest_path::Face_location Face_location; + typedef CGAL::AABB_face_graph_triangle_primitive Primitive; + typedef CGAL::AABB_traits Tree_traits; + typedef CGAL::AABB_tree Tree; + typedef EPICK::Point_3 Point_3; + public : + void init(QMainWindow* , CGAL::Three::Scene_interface* , Messages_interface*) Q_DECL_OVERRIDE{ //get refs this->scene = Three::scene(); @@ -76,6 +285,7 @@ public : //items visu_item = NULL; + sel_item = NULL; //transfo angle = 0.0; @@ -83,37 +293,49 @@ public : connect(dock_widget->t_left_pushButton, &QPushButton::clicked, this, [this](){ translation -= EPICK::Vector_2(0.05,0); + scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); connect(dock_widget->t_up_pushButton, &QPushButton::clicked, this, [this](){ - translation -= EPICK::Vector_2(0,-0.05); + translation -= EPICK::Vector_2(0,0.05); + scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); connect(dock_widget->t_down_pushButton, &QPushButton::clicked, this, [this](){ - translation -= EPICK::Vector_2(0,0.05); + translation += EPICK::Vector_2(0,0.05); + scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); connect(dock_widget->t_right_pushButton, &QPushButton::clicked, this, [this](){ translation += EPICK::Vector_2(0.05,0); + scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); } connect(dock_widget->r_right_pushButton, &QPushButton::clicked, this, [this](){ angle += 0.15; + scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); connect(dock_widget->r_left_pushButton, &QPushButton::clicked, this, [this](){ angle -= 0.15; + scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); + graphics_scene = new QGraphicsScene(dock_widget); + dock_widget->graphicsView->setScene(graphics_scene); + dock_widget->graphicsView->setRenderHints(QPainter::Antialiasing); + navigation = new Navigation(); + dock_widget->graphicsView->installEventFilter(navigation); + dock_widget->graphicsView->viewport()->installEventFilter(navigation); } bool applicable(QAction*) const Q_DECL_OVERRIDE { @@ -130,33 +352,27 @@ public Q_SLOTS: } void visualize() { - Scene_polyhedron_selection_item* sel_item = - qobject_cast - (scene->item(scene->mainSelectionIndex())); + if(!sel_item) + sel_item = + qobject_cast + (scene->item(scene->mainSelectionIndex())); if(!sel_item) return; if(sel_item->selected_facets.empty()) return; if(!CGAL::is_closed(*sel_item->polyhedron())) - return; + return; if(visu_item) scene->erase(scene->item_id(visu_item)); visu_item = NULL; - namespace SMP = CGAL::Surface_mesh_parameterization; - typedef CGAL::Surface_mesh_shortest_path_traits SP_traits; - typedef CGAL::Surface_mesh_shortest_path Surface_mesh_shortest_path; - typedef Surface_mesh_shortest_path::Face_location Face_location; - typedef CGAL::AABB_face_graph_triangle_primitive Primitive; - typedef CGAL::AABB_traits Tree_traits; - typedef CGAL::AABB_tree Tree; - typedef EPICK::Point_3 Point_3; - SMesh sm; - sel_item->export_selected_facets_as_polyhedron(&sm); + + SMesh *sm = new SMesh(); + sel_item->export_selected_facets_as_polyhedron(sm); SMesh::Halfedge_index hd = - CGAL::Polygon_mesh_processing::longest_border(sm).first; + CGAL::Polygon_mesh_processing::longest_border(*sm).first; SMesh::Property_map uv_map = - sm.add_property_map("v:uv").first; + sm->add_property_map("v:uv").first; // Parameterized bool pmap boost::unordered_set vs; @@ -165,18 +381,18 @@ public Q_SLOTS: // Parameterizer SMP::ARAP_parameterizer_3 parameterizer; - SMP::Error_code status = parameterizer.parameterize(sm, hd, uv_map, get(boost::vertex_index, sm), vpm); + SMP::Error_code status = parameterizer.parameterize(*sm, hd, uv_map, get(boost::vertex_index, *sm), vpm); if(status != SMP::OK) { std::cout << "Encountered a problem: " << status << std::endl; return ; } std::cout << "Parameterized with ARAP (SM)!" << std::endl; - SMesh::Property_map uv_map_3 = - sm.add_property_map("v:uv3").first; + uv_map_3 = + sm->add_property_map("v:uv3").first; float xmin(std::numeric_limits::max()), xmax(std::numeric_limits::min()), ymin(std::numeric_limits::max()), ymax(std::numeric_limits::min()); - for(SMesh::Vertex_index v : sm.vertices()) + for(SMesh::Vertex_index v : sm->vertices()) { uv_map_3[v] = Point_3(uv_map[v][0], uv_map[v] [1], 0); @@ -193,15 +409,15 @@ public Q_SLOTS: std::cout<<"xmax = "<number_of_vertices() << " " << sm->number_of_faces() << " 0\n"; + for(SMesh::Vertex_index v : sm->vertices()) out << uv_map_3[v] << "\n"; - for(SMesh::Face_index f : faces(sm)) + for(SMesh::Face_index f : faces(*sm)) { - SMesh::Halfedge_index h = sm.halfedge(f); - out << "3 " << (unsigned) sm.target(h) << " " - << (unsigned) sm.target(sm.next(h)) << " " - << (unsigned) sm.source(h) << "\n"; + SMesh::Halfedge_index h = sm->halfedge(f); + out << "3 " << (unsigned) sm->target(h) << " " + << (unsigned) sm->target(sm->next(h)) << " " + << (unsigned) sm->source(h) << "\n"; } @@ -219,53 +435,89 @@ public Q_SLOTS: QTransform trans; QList polys = path.toSubpathPolygons(); - //Scene_polylines_item* new_poly = new Scene_polylines_item(); - Scene_polylines_item::Polylines_container polylines; QFontMetrics fm(font); int width=fm.width(dock_widget->lineEdit->text()); int height=fm.height(); std::cout<<"width = "<setColor(QColor(Qt::red)); scene->addItem(visu_item); dock_widget->engraveButton->setEnabled(true); - // dock_widget->visualizeButton->setEnabled(false); + + if(graphics_scene->items().empty()) + { + Component* component = new Component(); + face_iterator bfit; + for(bfit = faces(*sm).begin(); + bfit != faces(*sm).end(); + ++bfit) + { + component->insert(*bfit); + } + SMesh::Property_map > uv; + uv = sm->add_property_map >( + "h:uv",std::make_pair(0.0f,0.0f)).first; + SMesh::Halfedge_iterator it; + for(it = sm->halfedges_begin(); + it != sm->halfedges_end(); + ++it) + { + halfedge_descriptor hd(*it); + EPICK::FT u = uv_map[target(hd, *sm)].x(); + EPICK::FT v = uv_map[target(hd, *sm)].y(); + put(uv, *it, std::make_pair(static_cast(u),static_cast(v))); + } + + //ParamItem takes ownership of text_mesh_bottom + ParamItem *param_item= new ParamItem(component, polylines, transfo, sm, + QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax))); + graphics_scene->addItem(param_item); + dock_widget->graphicsView->fitInView(param_item->boundingRect(), Qt::KeepAspectRatio); + } + else + { + ParamItem* param_item = static_cast(graphics_scene->items().first()); + param_item->set_transfo(transfo); + dock_widget->graphicsView->activateWindow(); + graphics_scene->update(); + } + // dock_widget->visualizeButton->setEnabled(false); } void engrave() { @@ -279,22 +531,12 @@ public Q_SLOTS: if(sel_item->selected_facets.empty()) return; if(!CGAL::is_closed(*sel_item->polyhedron())) - return; + return; - typedef CGAL::Projection_traits_xy_3 Gt; - typedef CGAL::Delaunay_mesh_vertex_base_2 Vb; - typedef CGAL::Delaunay_mesh_face_base_2 Fm; - typedef CGAL::Triangulation_face_base_with_info_2 Fb; - typedef CGAL::Triangulation_data_structure_2 TDS; - typedef CGAL::No_intersection_tag Tag; - typedef CGAL::Constrained_Delaunay_triangulation_2 CDT; - typedef CGAL::Delaunay_mesh_size_criteria_2 Criteria; - typedef CGAL::Delaunay_mesher_2 Mesher; - - CDT cdt; + /* CDT cdt; try{ - Q_FOREACH(const std::vector& points, - visu_item->polylines) + Q_FOREACH(const std::vector& points, + polylines) cdt.insert_constraint(points.begin(),points.end()); }catch(std::runtime_error&) { @@ -306,22 +548,16 @@ public Q_SLOTS: std::cout << "Triangulation is not of dimension 2" << std::endl; return; } - Scene_item::Bbox bbox= visu_item->bbox(); + CGAL::Bbox_2 bbox= CGAL::bbox_2(polylines.front().begin(), polylines.front().end(), EPICK()); + Q_FOREACH(const std::vector& points, + polylines) + { + bbox += CGAL::bbox_2(points.begin(), points.end(), EPICK()); + } float diag = CGAL::sqrt( (bbox.xmax()-bbox.xmin())*(bbox.xmax()-bbox.xmin()) +(bbox.ymax()-bbox.ymin())*(bbox.ymax()-bbox.ymin()) - +(bbox.zmax()-bbox.zmax()) *(bbox.zmax()-bbox.zmax()) ); - float zmax = bbox.zmax(), - zmin = bbox.zmin(); - //project to z=zmin for mesh_2 - BOOST_FOREACH(Scene_polylines_item::Polyline poly, visu_item->polylines) - { - BOOST_FOREACH(EPICK::Point_3& p, poly) - { - p = EPICK::Point_3(p.x(), p.y(), zmin); - } - } // start by marking the domain to mesh Criteria criteria(0.125, 0.05 * diag); Mesher mesher(cdt, criteria); @@ -337,13 +573,13 @@ public Q_SLOTS: mesher.refine_mesh(); - SMesh text_mesh_bottom, text_mesh_complete; + SMesh* text_mesh_bottom = new SMesh(); cdt2_to_face_graph(cdt, - text_mesh_bottom, - zmin); - PMP::extrude_mesh(text_mesh_bottom, text_mesh_complete,EPICK::Vector_3(0,0,zmax-zmin)); + sm, + *text_mesh_bottom);*/ + // PMP::extrude_mesh(text_mesh_bottom, text_mesh_complete,EPICK::Vector_3(0,0,0.3)); - CGAL::Surface_mesh exact_text, + /*CGAL::Surface_mesh exact_text, exact_target; CGAL::copy_face_graph(text_mesh_complete, exact_text); CGAL::copy_face_graph(*sel_item->polyhedron(), exact_target); @@ -352,9 +588,10 @@ public Q_SLOTS: Nef_polyhedron new_nef = nef_target - nef_text; SMesh result; CGAL::convert_nef_polyhedron_to_polygon_mesh(new_nef, result); - CGAL::Polygon_mesh_processing::triangulate_faces(result); - Scene_surface_mesh_item* result_item = new Scene_surface_mesh_item(result); - scene->addItem(result_item); + CGAL::Polygon_mesh_processing::triangulate_faces(result);*/ + //Scene_surface_mesh_item* result_item = new Scene_surface_mesh_item(text_mesh_bottom); + //result); + //scene->addItem(result_item); dock_widget->engraveButton->setEnabled(false); dock_widget->visualizeButton->setEnabled(true); } @@ -364,15 +601,6 @@ public Q_SLOTS: } private: - struct FaceInfo2 - { - FaceInfo2(){} - int nesting_level; - bool in_domain(){ - return nesting_level%2 == 1; - } - }; - template void mark_domains(CDT& ct, @@ -423,15 +651,19 @@ private: } template - void cdt2_to_face_graph(const CDT& cdt, TriangleMesh& tm, double constant_coordinate) + void cdt2_to_face_graph(const CDT& cdt, + SMesh sm, + TriangleMesh& tm) { + + Tree aabb_tree(faces(sm).first, faces(sm).second, sm, uv_map_3); typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - + typedef std::map Map; Map descriptors; for (typename CDT::Finite_faces_iterator fit=cdt.finite_faces_begin(), - fit_end=cdt.finite_faces_end(); - fit!=fit_end; ++fit) + fit_end=cdt.finite_faces_end(); + fit!=fit_end; ++fit) { if (!fit->is_in_domain()) continue; CGAL::cpp11::array vds; @@ -440,16 +672,17 @@ private: typename Map::iterator it; bool insert_ok; boost::tie(it,insert_ok) = - descriptors.insert(std::make_pair(fit->vertex(i),vertex_descriptor())); + descriptors.insert(std::make_pair(fit->vertex(i),vertex_descriptor())); if (insert_ok){ - const Kernel::Point_3& pt=fit->vertex(i)->point(); - double coords[3] = {pt[0], pt[1], pt[2]}; - coords[2]=constant_coordinate; - it->second = add_vertex(Kernel::Point_3(coords[0],coords[1],coords[2]), tm); + const Kernel::Point_2& pt=fit->vertex(i)->point(); + Face_location loc = Surface_mesh_shortest_path::locate( + Point_3(pt.x(), pt.y(), 0), + aabb_tree, sm, uv_map_3); + it->second = add_vertex(Surface_mesh_shortest_path::point(loc.first, loc.second, sm, sm.points()), tm); } vds[i]=it->second; } - + CGAL::Euler::add_face(vds, tm); } } @@ -457,8 +690,13 @@ private: QList _actions; EngraveWidget* dock_widget; Scene_polylines_item* visu_item; + Scene_polyhedron_selection_item* sel_item; double angle; EPICK::Vector_2 translation; + std::vector > polylines; + SMesh::Property_map uv_map_3; + QGraphicsScene *graphics_scene; + Navigation* navigation; }; #include "Engrave_text_plugin.moc" From 433bd7499c40d60d256f56bee26676240e9d4ce5 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 31 Jul 2018 15:50:21 +0200 Subject: [PATCH 08/25] Working version --- .../Plugins/PMP/Engrave_dock_widget.ui | 50 ++-- .../Plugins/PMP/Engrave_text_plugin.cpp | 214 ++++++++++++------ 2 files changed, 171 insertions(+), 93 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui index 8062175b83e..53e9d44e056 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui @@ -14,7 +14,7 @@ Engraving - + @@ -24,20 +24,6 @@ - - - - <- - - - - - - - R-> - - - @@ -45,10 +31,10 @@ - - + + - -> + <- @@ -59,6 +45,34 @@ + + + + R-> + + + + + + + -> + + + + + + + ->.<- + + + + + + + <-.-> + + + diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index 02a687407fb..89dda6bd452 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -60,6 +60,33 @@ struct FaceInfo2 } }; +template +struct Bot +{ + Bot(MAP map):map(map){} + template + void operator()(const T&,VD vd) const + { + put(map, vd, get(map, vd)+Kernel::Vector_3(0.0,0.0,-0.01)); + } + MAP map; + +}; + +template +struct Top +{ + Top(MAP map):map(map){} + + template + void operator()(const T&, VD vd) const + { + put(map, vd, get(map, vd)+Kernel::Vector_3(0.0,0.0,0.01)); + } + + MAP map; +}; + typedef EPICK Gt; typedef CGAL::Delaunay_mesh_vertex_base_2 Vb; typedef CGAL::Delaunay_mesh_face_base_2 Fm; @@ -127,7 +154,7 @@ public : points[2] = QPointF(get(uv, h).first, get(uv, h).second); painter->drawPolygon(points,3); } - + pen.setColor(Qt::red); pen.setWidth(0); painter->setPen(pen); @@ -143,9 +170,13 @@ public : } painter->drawPolyline(points.data(), points.size()); } - - - + pen.setColor(Qt::green); + pen.setWidth(0); + painter->setPen(pen); + painter->drawPoint(QPointF(0,0)); + + + } private: @@ -270,54 +301,68 @@ public : //action QAction* actionFitText= new QAction("Fit Text", mw); - if(actionFitText) { - connect(actionFitText, SIGNAL(triggered()), - this, SLOT(showWidget())); - _actions << actionFitText; - //widget - dock_widget = new EngraveWidget("Engraving", mw); - dock_widget->setVisible(false); // do not show at the beginning - addDockWidget(dock_widget); - connect(dock_widget->visualizeButton, &QPushButton::clicked, - this, &Engrave_text_plugin::visualize); - connect(dock_widget->engraveButton, &QPushButton::clicked, - this, &Engrave_text_plugin::engrave); - - //items - visu_item = NULL; - sel_item = NULL; - - //transfo - angle = 0.0; - translation = EPICK::Vector_2(0,0); - connect(dock_widget->t_left_pushButton, &QPushButton::clicked, - this, [this](){ - translation -= EPICK::Vector_2(0.05,0); - scene->setSelectedItem(scene->item_id(sel_item)); - visualize(); - }); - - connect(dock_widget->t_up_pushButton, &QPushButton::clicked, - this, [this](){ - translation -= EPICK::Vector_2(0,0.05); - scene->setSelectedItem(scene->item_id(sel_item)); - visualize(); - }); - - connect(dock_widget->t_down_pushButton, &QPushButton::clicked, - this, [this](){ - translation += EPICK::Vector_2(0,0.05); - scene->setSelectedItem(scene->item_id(sel_item)); - visualize(); - }); - - connect(dock_widget->t_right_pushButton, &QPushButton::clicked, - this, [this](){ - translation += EPICK::Vector_2(0.05,0); - scene->setSelectedItem(scene->item_id(sel_item)); - visualize(); - }); - } + connect(actionFitText, SIGNAL(triggered()), + this, SLOT(showWidget())); + _actions << actionFitText; + //widget + dock_widget = new EngraveWidget("Engraving", mw); + dock_widget->setVisible(false); // do not show at the beginning + addDockWidget(dock_widget); + connect(dock_widget->visualizeButton, &QPushButton::clicked, + this, &Engrave_text_plugin::visualize); + connect(dock_widget->engraveButton, &QPushButton::clicked, + this, &Engrave_text_plugin::engrave); + + //items + visu_item = nullptr; + sel_item = nullptr; + sm = nullptr; + + //transfo + angle = 0.0; + scaling=1.0; + translation = EPICK::Vector_2(0,0); + connect(dock_widget->t_left_pushButton, &QPushButton::clicked, + this, [this](){ + translation -= EPICK::Vector_2(0.05,0); + scene->setSelectedItem(scene->item_id(sel_item)); + visualize(); + }); + + connect(dock_widget->s_large_pushButton, &QPushButton::clicked, + this, [this](){ + scaling += 0.1; + scene->setSelectedItem(scene->item_id(sel_item)); + visualize(); + }); + + connect(dock_widget->s_small_pushButton, &QPushButton::clicked, + this, [this](){ + scaling -= 0.1; + scene->setSelectedItem(scene->item_id(sel_item)); + visualize(); + }); + + connect(dock_widget->t_up_pushButton, &QPushButton::clicked, + this, [this](){ + translation -= EPICK::Vector_2(0,0.05); + scene->setSelectedItem(scene->item_id(sel_item)); + visualize(); + }); + + connect(dock_widget->t_down_pushButton, &QPushButton::clicked, + this, [this](){ + translation += EPICK::Vector_2(0,0.05); + scene->setSelectedItem(scene->item_id(sel_item)); + visualize(); + }); + + connect(dock_widget->t_right_pushButton, &QPushButton::clicked, + this, [this](){ + translation += EPICK::Vector_2(0.05,0); + scene->setSelectedItem(scene->item_id(sel_item)); + visualize(); + }); connect(dock_widget->r_right_pushButton, &QPushButton::clicked, this, [this](){ angle += 0.15; @@ -366,9 +411,11 @@ public Q_SLOTS: scene->erase(scene->item_id(visu_item)); visu_item = NULL; - - SMesh *sm = new SMesh(); - sel_item->export_selected_facets_as_polyhedron(sm); + if(!sm) + { + sm = new SMesh(); + sel_item->export_selected_facets_as_polyhedron(sm); + } SMesh::Halfedge_index hd = CGAL::Polygon_mesh_processing::longest_border(*sm).first; SMesh::Property_map uv_map = @@ -438,7 +485,7 @@ public Q_SLOTS: QFontMetrics fm(font); int width=fm.width(dock_widget->lineEdit->text()); int height=fm.height(); - std::cout<<"width = "< vs; - SMP::internal::Bool_property_map< boost::unordered_set > vpm(vs); - - // Parameterizer - SMP::ARAP_parameterizer_3 parameterizer; - - SMP::Error_code status = parameterizer.parameterize(*sm, hd, uv_map, get(boost::vertex_index, *sm), vpm); - if(status != SMP::OK) { - std::cout << "Encountered a problem: " << status << std::endl; - return ; - } - - std::cout << "Parameterized with ARAP (SM)!" << std::endl; - uv_map_3 = - sm->add_property_map("v:uv3").first; - float xmin(std::numeric_limits::max()), xmax(std::numeric_limits::min()), - ymin(std::numeric_limits::max()), ymax(std::numeric_limits::min()); - for(SMesh::Vertex_index v : sm->vertices()) - { - uv_map_3[v] = Point_3(uv_map[v][0], uv_map[v] - [1], 0); - if(uv_map[v][0] > xmax) - xmax = uv_map[v][0]; - if(uv_map[v][0] < xmin) - xmin = uv_map[v][0]; + SMesh::Halfedge_index hd = + CGAL::Polygon_mesh_processing::longest_border(*sm).first; + SMesh::Property_map uv_map = + sm->add_property_map("v:uv").first; - if(uv_map[v][1] > ymax) - ymax = uv_map[v][1]; - if(uv_map[v][1] < ymin) - ymin = uv_map[v][1]; - } - std::cout<<"xmax = "<number_of_vertices() << " " << sm->number_of_faces() << " 0\n"; - for(SMesh::Vertex_index v : sm->vertices()) - out << uv_map_3[v] << "\n"; - for(SMesh::Face_index f : faces(*sm)) - { - SMesh::Halfedge_index h = sm->halfedge(f); - out << "3 " << (unsigned) sm->target(h) << " " - << (unsigned) sm->target(sm->next(h)) << " " - << (unsigned) sm->source(h) << "\n"; - } - - + // Parameterized bool pmap + boost::unordered_set vs; + SMP::internal::Bool_property_map< boost::unordered_set > vpm(vs); + + // Parameterizer + SMP::ARAP_parameterizer_3 parameterizer; + + SMP::Error_code status = parameterizer.parameterize(*sm, hd, uv_map, get(boost::vertex_index, *sm), vpm); + if(status != SMP::OK) { + std::cout << "Encountered a problem: " << status << std::endl; + return ; + } + + std::cout << "Parameterized with ARAP (SM)!" << std::endl; + xmin = std::numeric_limits::max(); + xmax = std::numeric_limits::min(); + ymin = std::numeric_limits::max(); + ymax = std::numeric_limits::min(); + uv_map_3 = + sm->add_property_map("v:uv3").first; + for(SMesh::Vertex_index v : sm->vertices()) + { + uv_map_3[v] = Point_3(uv_map[v][0], uv_map[v] + [1], 0); + if(uv_map[v][0] > xmax) + xmax = uv_map[v][0]; + if(uv_map[v][0] < xmin) + xmin = uv_map[v][0]; + + if(uv_map[v][1] > ymax) + ymax = uv_map[v][1]; + if(uv_map[v][1] < ymin) + ymin = uv_map[v][1]; + } + + + } //create Text Polyline - typedef EPICK::Point_3 Point_3; - Viewer_interface* viewer = static_cast(CGAL::QGLViewer::QGLViewerPool().first()); QPainterPath path; QFont font; font.setPointSize(15); path.addText(QPoint(xmin,-ymin), font, dock_widget->lineEdit->text()); - viewer->getPainter()->begin(viewer); - viewer->getPainter()->drawPath(path); - viewer->getPainter()->end(); - QTransform trans; - QList polys = path.toSubpathPolygons(); QFontMetrics fm(font); int width=fm.width(dock_widget->lineEdit->text()); int height=fm.height(); - + polylines.clear(); Q_FOREACH(QPolygonF poly, polys){ polylines.push_back(std::vector()); Q_FOREACH(QPointF pf, poly) @@ -497,8 +472,6 @@ public Q_SLOTS: } } - - // build AABB-tree for face location queries Tree aabb_tree(faces(*sm).first, faces(*sm).second, *sm, uv_map_3); @@ -521,8 +494,8 @@ public Q_SLOTS: Face_location loc = Surface_mesh_shortest_path::locate( Point_3(p_2.x(), p_2.y(), 0), aabb_tree, *sm, uv_map_3); - visu_item->polylines.back().push_back(//p); - Surface_mesh_shortest_path::point(loc.first, loc.second, *sm, sm->points())); + visu_item->polylines.back().push_back( + Surface_mesh_shortest_path::point(loc.first, loc.second, *sm, sm->points())); } } visu_item->setName("Text"); @@ -544,6 +517,8 @@ public Q_SLOTS: uv = sm->add_property_map >( "h:uv",std::make_pair(0.0f,0.0f)).first; SMesh::Halfedge_iterator it; + SMesh::Property_map uv_map = + sm->property_map("v:uv").first; for(it = sm->halfedges_begin(); it != sm->halfedges_end(); ++it) @@ -554,9 +529,9 @@ public Q_SLOTS: put(uv, *it, std::make_pair(static_cast(u),static_cast(v))); } - //ParamItem takes ownership of text_mesh_bottom + //ParamItem does not take ownership of text_mesh_bottom ParamItem *param_item= new ParamItem(component, polylines, transfo, sm, - QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax))); + QRectF(QPointF(xmin, -ymax), QPointF(xmax, -ymin))); graphics_scene->addItem(param_item); dock_widget->graphicsView->fitInView(param_item->boundingRect(), Qt::KeepAspectRatio); } @@ -573,16 +548,13 @@ public Q_SLOTS: void engrave() { if(!visu_item) return; - Scene_polyhedron_selection_item* sel_item = - qobject_cast - (scene->item(scene->mainSelectionIndex())); if(!sel_item) return; if(sel_item->selected_facets.empty()) return; if(!CGAL::is_closed(*sel_item->polyhedron())) return; - + QApplication::setOverrideCursor(Qt::WaitCursor); CDT cdt; try{ for(std::size_t i = 0; @@ -651,8 +623,16 @@ public Q_SLOTS: CGAL::Polygon_mesh_processing::triangulate_faces(result); Scene_surface_mesh_item* result_item = new Scene_surface_mesh_item( - result); + result); scene->addItem(result_item); + graphics_scene->clear(); + scene->erase(scene->item_id(sel_item)); + sel_item =nullptr; + delete sm; + sm = nullptr; + scene->erase(scene->item_id(visu_item)); + visu_item = nullptr; + QApplication::restoreOverrideCursor(); dock_widget->engraveButton->setEnabled(false); dock_widget->visualizeButton->setEnabled(true); } @@ -758,6 +738,7 @@ private: std::vector > polylines; SMesh::Property_map uv_map_3; SMesh* sm; + float xmin, xmax, ymin, ymax; QGraphicsScene *graphics_scene; Navigation* navigation; From 6fe03d37d4b5b385f34fa9a0916965b06ff1ec69 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 31 Jul 2018 17:36:49 +0200 Subject: [PATCH 10/25] Better UI and fix bug nef_3. (just find n appropriate normal instead of always Z) --- .../Plugins/PMP/Engrave_dock_widget.ui | 120 ++++++++++++++---- .../Plugins/PMP/Engrave_text_plugin.cpp | 51 ++++---- 2 files changed, 123 insertions(+), 48 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui index 53e9d44e056..6d11dcf77ca 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui @@ -6,8 +6,8 @@ 0 0 - 278 - 372 + 295 + 421 @@ -16,60 +16,127 @@ - - - - - V + + + + + -179 + + + 179 + + + Qt::Horizontal + + + + + + + 300 + + + 1 + + + 100 + + + 100 + + + Qt::Horizontal - ^ + + + + + :/cgal/icons/resources/up.png:/cgal/icons/resources/up.png - <- + + + + + :/cgal/icons/resources/left_arrow.png:/cgal/icons/resources/left_arrow.png - - + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + - <-R + Rotation degree: - - + + - R-> + Scaling factor: + + + + + + + + + + + :/cgal/icons/resources/down.png:/cgal/icons/resources/down.png - -> + + + + + :/cgal/icons/resources/right_arrow.png:/cgal/icons/resources/right_arrow.png - - - - ->.<- + + + + 6 + + + 0.000000000000000 + + + 0.100000000000000 - - + + - <-.-> + Engraving depth: @@ -126,6 +193,11 @@ - + + + + + + diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index db60335ba4e..bedf874738e 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -17,7 +17,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -64,12 +66,18 @@ struct FaceInfo2 template struct Bot { - Bot(MAP map):map(map){} + Bot(const EPICK::Vector_3& n, + double d, + MAP map):d(d), + n(n), + map(map){} template void operator()(const T&,VD vd) const { - put(map, vd, get(map, vd)+Kernel::Vector_3(0.0,0.0,-0.01)); + put(map, vd, get(map, vd)-d*n); } + double d; + const EPICK::Vector_3& n; MAP map; }; @@ -77,14 +85,15 @@ struct Bot template struct Top { - Top(MAP map):map(map){} + Top(const EPICK::Vector_3& n, + MAP map):n(n),map(map){} template void operator()(const T&, VD vd) const { - put(map, vd, get(map, vd)+Kernel::Vector_3(0.0,0.0,0.01)); + put(map, vd, get(map, vd)+0.01*n); } - + const EPICK::Vector_3& n; MAP map; }; @@ -322,16 +331,9 @@ public : visualize(); }); - connect(dock_widget->s_large_pushButton, &QPushButton::clicked, + connect(dock_widget->scal_slider, &QSlider::valueChanged, this, [this](){ - scaling += 0.1; - scene->setSelectedItem(scene->item_id(sel_item)); - visualize(); - }); - - connect(dock_widget->s_small_pushButton, &QPushButton::clicked, - this, [this](){ - scaling -= 0.1; + scaling = dock_widget->scal_slider->value()/100.0; scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); @@ -356,15 +358,9 @@ public : scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); - connect(dock_widget->r_right_pushButton, &QPushButton::clicked, + connect(dock_widget->rot_slider, &QSlider::valueChanged, this, [this](){ - angle += 0.15; - scene->setSelectedItem(scene->item_id(sel_item)); - visualize(); - }); - connect(dock_widget->r_left_pushButton, &QPushButton::clicked, - this, [this](){ - angle -= 0.15; + angle = dock_widget->rot_slider->value() * CGAL_PI/180.0; scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); @@ -607,8 +603,15 @@ public Q_SLOTS: cdt2_to_face_graph(cdt, text_mesh_bottom); typedef typename boost::property_map::type VPMap; - Bot bot(get(CGAL::vertex_point, text_mesh_complete)); - Top top(get(CGAL::vertex_point, text_mesh_complete)); + EPICK::Vector_3 normal(0,0,0); + BOOST_FOREACH(face_descriptor f, sel_item->selected_facets) + { + normal += CGAL::Polygon_mesh_processing::compute_face_normal(f, *sel_item->polyhedron()); + } + normal/=CGAL::sqrt(normal.squared_length()); + + Bot bot(normal, dock_widget->depth_spinBox->value(),get(CGAL::vertex_point, text_mesh_complete)); + Top top(normal, get(CGAL::vertex_point, text_mesh_complete)); PMP::extrude_mesh(text_mesh_bottom, text_mesh_complete, bot, top); CGAL::Surface_mesh exact_text, From 9213f46d92376f793eeff20afabed966f7d5f283 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 2 Aug 2018 15:51:32 +0200 Subject: [PATCH 11/25] Fix rotation and enhance initial position of the text if the parameterization is globally vertical. --- .../Plugins/PMP/Engrave_dock_widget.ui | 264 +++++++++--------- .../Plugins/PMP/Engrave_text_plugin.cpp | 141 +++++++--- 2 files changed, 244 insertions(+), 161 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui index 6d11dcf77ca..9a8276089d8 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui @@ -15,133 +15,6 @@ - - - - - - -179 - - - 179 - - - Qt::Horizontal - - - - - - - 300 - - - 1 - - - 100 - - - 100 - - - Qt::Horizontal - - - - - - - - - - - :/cgal/icons/resources/up.png:/cgal/icons/resources/up.png - - - - - - - - - - - :/cgal/icons/resources/left_arrow.png:/cgal/icons/resources/left_arrow.png - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Rotation degree: - - - - - - - Scaling factor: - - - - - - - - - - - :/cgal/icons/resources/down.png:/cgal/icons/resources/down.png - - - - - - - - - - - :/cgal/icons/resources/right_arrow.png:/cgal/icons/resources/right_arrow.png - - - - - - - 6 - - - 0.000000000000000 - - - 0.100000000000000 - - - - - - - Engraving depth: - - - - - @@ -183,10 +56,147 @@ + + + + Reset + + + + + + + + + Scaling factor: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + :/cgal/icons/resources/left_arrow.png:/cgal/icons/resources/left_arrow.png + + + + + + + + + + + :/cgal/icons/resources/up.png:/cgal/icons/resources/up.png + + + + + + + 300 + + + 1 + + + 100 + + + 100 + + + Qt::Horizontal + + + + + + + + + + + :/cgal/icons/resources/right_arrow.png:/cgal/icons/resources/right_arrow.png + + + + + + + -179 + + + 179 + + + Qt::Horizontal + + + + + + + Rotation degree: + + + + + + + Engraving depth: + + + + + + + + + + + :/cgal/icons/resources/down.png:/cgal/icons/resources/down.png + + + + + + + 6 + + + 0.000001000000000 + + + 0.100000000000000 + + + 0.010000000000000 + + + + + diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index bedf874738e..9ecaa9a0737 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -323,38 +323,42 @@ public : //transfo angle = 0.0; scaling=1.0; - translation = EPICK::Vector_2(0,0); - connect(dock_widget->t_left_pushButton, &QPushButton::clicked, - this, [this](){ - translation -= EPICK::Vector_2(0.05,0); - scene->setSelectedItem(scene->item_id(sel_item)); - visualize(); - }); - + translation = EPICK::Vector_2(0,0); connect(dock_widget->scal_slider, &QSlider::valueChanged, this, [this](){ scaling = dock_widget->scal_slider->value()/100.0; scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); + connect(dock_widget->reset_button, &QPushButton::clicked, + this, [this](){ + cleanup(); + }); connect(dock_widget->t_up_pushButton, &QPushButton::clicked, this, [this](){ - translation += EPICK::Vector_2(0,0.05); + translation += EPICK::Vector_2(0,0.005); scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); connect(dock_widget->t_down_pushButton, &QPushButton::clicked, this, [this](){ - translation -= EPICK::Vector_2(0,0.05); + translation -= EPICK::Vector_2(0,0.005); scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); connect(dock_widget->t_right_pushButton, &QPushButton::clicked, this, [this](){ - translation += EPICK::Vector_2(0.05,0); + translation += EPICK::Vector_2(0.005,0); + scene->setSelectedItem(scene->item_id(sel_item)); + visualize(); + }); + + connect(dock_widget->t_left_pushButton, &QPushButton::clicked, + this, [this](){ + translation -= EPICK::Vector_2(0.005,0); scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); @@ -393,12 +397,18 @@ public Q_SLOTS: if(!sel_item) return; if(sel_item->selected_facets.empty()) + { + cleanup(); return; + } if(!CGAL::is_closed(*sel_item->polyhedron())) + { + cleanup(); return; + } if(visu_item) scene->erase(scene->item_id(visu_item)); - visu_item = NULL; + visu_item = nullptr; if(!sm) { @@ -419,6 +429,7 @@ public Q_SLOTS: SMP::Error_code status = parameterizer.parameterize(*sm, hd, uv_map, get(boost::vertex_index, *sm), vpm); if(status != SMP::OK) { std::cout << "Encountered a problem: " << status << std::endl; + cleanup(); return ; } @@ -445,41 +456,75 @@ public Q_SLOTS: } - } + } //create Text Polyline QPainterPath path; QFont font; font.setPointSize(15); - - path.addText(QPoint(xmin,-ymin), font, dock_widget->lineEdit->text()); + path.addText(QPoint(xmin,ymin), font, dock_widget->lineEdit->text()); QList polys = path.toSubpathPolygons(); - QFontMetrics fm(font); - int width=fm.width(dock_widget->lineEdit->text()); - int height=fm.height(); polylines.clear(); + float pxmin(8000),pxmax(-8000), + pymin(8000), pymax(-8000); + Q_FOREACH(QPolygonF poly, polys){ - polylines.push_back(std::vector()); Q_FOREACH(QPointF pf, poly) { EPICK::Point_2 v = EPICK::Point_2(pf.x(),-pf.y()); - polylines.back().push_back(EPICK::Point_2(v.x()*(xmax-xmin)/width +xmin , - v.y()*(ymax-ymin)/height+ymin - )); + if(v.x() < pxmin) + pxmin = v.x(); + if(v.x() > pxmax) + pxmax = v.x(); + if(v.y() < pymin) + pymin = v.y(); + if(v.y() > pymax) + pymax = v.y(); + } + } + if(ymax-ymin > xmax - xmin) + { + Q_FOREACH(QPolygonF poly, polys){ + polylines.push_back(std::vector()); + Q_FOREACH(QPointF pf, poly) + { + EPICK::Point_2 v = EPICK::Point_2(pf.x(),-pf.y()); + polylines.back().push_back(EPICK::Point_2(v.x()*(xmax-xmin)/(pxmax-pxmin) +xmin , + v.y()*(ymax-ymin)/(pymax-pymin)+ymin + )); + } + } + } + else + { + EPICK::Aff_transformation_2 rota = EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2((pxmax+pxmin)/2, + (pymax+pymin)/2)) + * EPICK::Aff_transformation_2(CGAL::ROTATION,1,0) + * EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2(-(pxmax+pxmin)/2, + -(pymax+pymin)/2)); + + Q_FOREACH(QPolygonF poly, polys){ + polylines.push_back(std::vector()); + Q_FOREACH(QPointF pf, poly) + { + EPICK::Point_2 v = rota.transform(EPICK::Point_2(pf.x(),-pf.y())); + polylines.back().push_back(EPICK::Point_2(v.x()*(xmax-xmin)/(pxmax-pxmin) +xmin , + v.y()*(ymax-ymin)/(pymax-pymin)+ymin + )); + } } } - // build AABB-tree for face location queries Tree aabb_tree(faces(*sm).first, faces(*sm).second, *sm, uv_map_3); visu_item = new Scene_polylines_item; // compute 3D coordinates transfo = - EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2((xmax-xmin)/2, - (ymax-ymin)/2)+ translation) + EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2((xmax-xmin)/2+xmin, + (ymax-ymin)/2+ymin)+ translation) * EPICK::Aff_transformation_2(CGAL::SCALING,scaling) * EPICK::Aff_transformation_2(CGAL::ROTATION,sin(angle), cos(angle)) - * EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2(-(xmax-xmin)/2, - -(ymax-ymin)/2)); + * EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2(-(xmax-xmin)/2-xmin, + -(ymax-ymin)/2-ymin)); BOOST_FOREACH(const std::vector& polyline, polylines) { visu_item->polylines.push_back(std::vector()); @@ -609,7 +654,20 @@ public Q_SLOTS: normal += CGAL::Polygon_mesh_processing::compute_face_normal(f, *sel_item->polyhedron()); } normal/=CGAL::sqrt(normal.squared_length()); - + while(normal == EPICK::Vector_3(0,0,0)) + { + QDialog dialog; + QLayout *layout = dialog.layout(); + QDoubleSpinBox xbox, ybox, zbox; + layout->addWidget(&xbox); + layout->addWidget(&ybox); + layout->addWidget(&zbox); + dialog.setLayout(layout); + dialog.exec(); + normal = EPICK::Vector_3(xbox.value(), + ybox.value(), + zbox.value()); + } Bot bot(normal, dock_widget->depth_spinBox->value(),get(CGAL::vertex_point, text_mesh_complete)); Top top(normal, get(CGAL::vertex_point, text_mesh_complete)); PMP::extrude_mesh(text_mesh_bottom, text_mesh_complete, bot, top); @@ -629,12 +687,7 @@ public Q_SLOTS: result); scene->addItem(result_item); graphics_scene->clear(); - scene->erase(scene->item_id(sel_item)); - sel_item =nullptr; - delete sm; - sm = nullptr; - scene->erase(scene->item_id(visu_item)); - visu_item = nullptr; + cleanup(); QApplication::restoreOverrideCursor(); dock_widget->engraveButton->setEnabled(false); dock_widget->visualizeButton->setEnabled(true); @@ -730,6 +783,26 @@ private: } } + void cleanup() + { + graphics_scene->clear(); + if(sel_item) + { + scene->erase(scene->item_id(sel_item)); + sel_item =nullptr; + } + if(sm) + { + delete sm; + sm = nullptr; + } + if(visu_item) + { + scene->erase(scene->item_id(visu_item)); + visu_item = nullptr; + } + + } QList _actions; EngraveWidget* dock_widget; Scene_polylines_item* visu_item; From 86580763d47584d0b949968709579e153c31a921 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 3 Aug 2018 11:10:43 +0200 Subject: [PATCH 12/25] Small Enhancements --- .../demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui | 6 +++--- .../demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp | 8 ++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui index 9a8276089d8..400a30c9cc7 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui @@ -114,16 +114,16 @@ - 300 + 2000 1 - 100 + 1000 - 100 + 1000 Qt::Horizontal diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index 9ecaa9a0737..2909f30c1ab 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -326,7 +326,7 @@ public : translation = EPICK::Vector_2(0,0); connect(dock_widget->scal_slider, &QSlider::valueChanged, this, [this](){ - scaling = dock_widget->scal_slider->value()/100.0; + scaling = dock_widget->scal_slider->value()/1000.0; scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); @@ -481,7 +481,7 @@ public Q_SLOTS: pymax = v.y(); } } - if(ymax-ymin > xmax - xmin) + if(ymax-ymin <= xmax - xmin) { Q_FOREACH(QPolygonF poly, polys){ polylines.push_back(std::vector()); @@ -785,6 +785,10 @@ private: void cleanup() { + dock_widget->scal_slider->setValue(1000); + dock_widget->rot_slider->setValue(0); + translation = EPICK::Vector_2(0,0); + uv_map_3.reset(); graphics_scene->clear(); if(sel_item) { From 0e32abf5d6e46150039b962d83128a8ca6cac057 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 3 Aug 2018 11:49:28 +0200 Subject: [PATCH 13/25] Split Scaling in X and Y to get better customization with longer texts. --- .../Plugins/PMP/Engrave_dock_widget.ui | 149 ++++++++++-------- .../Plugins/PMP/Engrave_text_plugin.cpp | 27 +++- 2 files changed, 105 insertions(+), 71 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui index 400a30c9cc7..b25fd5b6328 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui @@ -6,7 +6,7 @@ 0 0 - 295 + 305 421 @@ -69,37 +69,6 @@ - - - - Scaling factor: - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - :/cgal/icons/resources/left_arrow.png:/cgal/icons/resources/left_arrow.png - - - @@ -111,19 +80,20 @@ - - + + + + Engraving depth: + + + + + + + -179 + - 2000 - - - 1 - - - 1000 - - - 1000 + 179 Qt::Horizontal @@ -141,30 +111,35 @@ - - - - -179 - - - 179 - + + Qt::Horizontal - - - - - - Rotation degree: + + + 40 + 20 + - + - - - - Engraving depth: + + + + 2000 + + + 1 + + + 1000 + + + 1000 + + + Qt::Horizontal @@ -179,6 +154,31 @@ + + + + Scaling factor in X: + + + + + + + + + + + :/cgal/icons/resources/left_arrow.png:/cgal/icons/resources/left_arrow.png + + + + + + + Rotation degree: + + + @@ -195,6 +195,29 @@ + + + + 2000 + + + 10 + + + 1000 + + + Qt::Horizontal + + + + + + + Scaling factor in Y: + + + diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index 2909f30c1ab..cf812cad6f0 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -322,11 +322,18 @@ public : //transfo angle = 0.0; - scaling=1.0; + scalX=1.0; + scalY=1.0; translation = EPICK::Vector_2(0,0); - connect(dock_widget->scal_slider, &QSlider::valueChanged, + connect(dock_widget->scalX_slider, &QSlider::valueChanged, this, [this](){ - scaling = dock_widget->scal_slider->value()/1000.0; + scalX = dock_widget->scalX_slider->value()/1000.0; + scene->setSelectedItem(scene->item_id(sel_item)); + visualize(); + }); + connect(dock_widget->scalY_slider, &QSlider::valueChanged, + this, [this](){ + scalY = dock_widget->scalY_slider->value()/1000.0; scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); @@ -517,12 +524,14 @@ public Q_SLOTS: Tree aabb_tree(faces(*sm).first, faces(*sm).second, *sm, uv_map_3); visu_item = new Scene_polylines_item; + + // compute 3D coordinates transfo = EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2((xmax-xmin)/2+xmin, (ymax-ymin)/2+ymin)+ translation) - * EPICK::Aff_transformation_2(CGAL::SCALING,scaling) - * EPICK::Aff_transformation_2(CGAL::ROTATION,sin(angle), cos(angle)) + * EPICK::Aff_transformation_2(CGAL::ROTATION,sin(angle), cos(angle)) + * EPICK::Aff_transformation_2(scalX, 0.0,0.0,scalY) * EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2(-(xmax-xmin)/2-xmin, -(ymax-ymin)/2-ymin)); BOOST_FOREACH(const std::vector& polyline, polylines) @@ -785,7 +794,8 @@ private: void cleanup() { - dock_widget->scal_slider->setValue(1000); + dock_widget->scalX_slider->setValue(1000); + dock_widget->scalY_slider->setValue(1000); dock_widget->rot_slider->setValue(0); translation = EPICK::Vector_2(0,0); uv_map_3.reset(); @@ -805,14 +815,15 @@ private: scene->erase(scene->item_id(visu_item)); visu_item = nullptr; } - } + QList _actions; EngraveWidget* dock_widget; Scene_polylines_item* visu_item; Scene_polyhedron_selection_item* sel_item; double angle; - double scaling; + double scalX; + double scalY; EPICK::Vector_2 translation; EPICK::Aff_transformation_2 transfo; std::vector > polylines; From f84bbca9a6ed5719ae3e5cdcdf01badf3914741f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 20 Aug 2018 11:44:42 +0200 Subject: [PATCH 14/25] add missing include directive --- Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index cf812cad6f0..d809fd88b76 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include From 5782c9b6c2fae2cdb0af690b3685bec045ee02e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 20 Aug 2018 13:24:35 +0200 Subject: [PATCH 15/25] using corefinement instead of Nef + check for preconditions --- .../Plugins/PMP/Engrave_text_plugin.cpp | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index d809fd88b76..fa7ab190e7d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -7,10 +7,7 @@ #include "Scene_surface_mesh_item.h" #include "Scene_polyhedron_selection_item.h" #include "Scene_polylines_item.h" -#include "Nef_type.h" - -//Actual code reqs -#include +#include "Messages_interface.h" #include #include @@ -18,6 +15,8 @@ #include #include #include +#include +#include #include #include #include @@ -294,14 +293,16 @@ private: typedef CGAL::AABB_traits Tree_traits; typedef CGAL::AABB_tree Tree; typedef EPICK::Point_3 Point_3; + Messages_interface* messages; public : - void init(QMainWindow* , CGAL::Three::Scene_interface* , Messages_interface*) Q_DECL_OVERRIDE{ + void init(QMainWindow* , CGAL::Three::Scene_interface* , Messages_interface* m) Q_DECL_OVERRIDE{ //get refs this->scene = Three::scene(); this->mw = Three::mainWindow(); - + messages = m; + //action QAction* actionFitText= new QAction("Fit Text", mw); connect(actionFitText, SIGNAL(triggered()), @@ -441,7 +442,7 @@ public Q_SLOTS: return ; } - std::cout << "Parameterized with ARAP (SM)!" << std::endl; + std::cout << "Parameterized with ARAP (SM) computed." << std::endl; xmin = std::numeric_limits::max(); xmax = std::numeric_limits::min(); ymin = std::numeric_limits::max(); @@ -682,15 +683,23 @@ public Q_SLOTS: Top top(normal, get(CGAL::vertex_point, text_mesh_complete)); PMP::extrude_mesh(text_mesh_bottom, text_mesh_complete, bot, top); - CGAL::Surface_mesh exact_text, - exact_target; - CGAL::copy_face_graph(text_mesh_complete, exact_text); - CGAL::copy_face_graph(*sel_item->polyhedron(), exact_target); - Nef_polyhedron nef_text(exact_text); - Nef_polyhedron nef_target(exact_target); - Nef_polyhedron new_nef = nef_target - nef_text; + if (PMP::does_self_intersect(text_mesh_complete)) + { + QApplication::restoreOverrideCursor(); + messages->information("Error: text mesh self-intersects!"); + return; + } + SMesh result; - CGAL::convert_nef_polyhedron_to_polygon_mesh(new_nef, result); + CGAL::copy_face_graph(*sel_item->polyhedron(), result); + bool OK = PMP::corefine_and_compute_difference(result, text_mesh_complete, result); + + if (!OK) + { + QApplication::restoreOverrideCursor(); + messages->information("Error: the output mesh is not manifold!"); + return; + } CGAL::Polygon_mesh_processing::triangulate_faces(result); Scene_surface_mesh_item* result_item = new Scene_surface_mesh_item( From 6e060e499df62f7421c021b4998219aa00ed72bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 20 Aug 2018 13:36:53 +0200 Subject: [PATCH 16/25] no need for Mesh_2 --- .../Plugins/PMP/Engrave_text_plugin.cpp | 36 ++++--------------- 1 file changed, 7 insertions(+), 29 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index fa7ab190e7d..6befbf2be8a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -24,10 +24,7 @@ #include #include #include -#include -#include -#include -#include +#include #include #include @@ -98,14 +95,12 @@ struct Top }; typedef EPICK Gt; -typedef CGAL::Delaunay_mesh_vertex_base_2 Vb; -typedef CGAL::Delaunay_mesh_face_base_2 Fm; -typedef CGAL::Triangulation_face_base_with_info_2 Fb; +typedef CGAL::Triangulation_vertex_base_2 Vb; +typedef CGAL::Triangulation_face_base_with_info_2 Fbb; +typedef CGAL::Constrained_triangulation_face_base_2 Fb; typedef CGAL::Triangulation_data_structure_2 TDS; typedef CGAL::No_intersection_tag Tag; typedef CGAL::Constrained_Delaunay_triangulation_2 CDT; -typedef CGAL::Delaunay_mesh_size_criteria_2 Criteria; -typedef CGAL::Delaunay_mesher_2 Mesher; //Parameterization and text displaying class ParamItem : public QGraphicsItem @@ -636,25 +631,8 @@ public Q_SLOTS: { bbox += CGAL::bbox_2(points.begin(), points.end(), EPICK()); } - float diag = CGAL::sqrt( - (bbox.xmax()-bbox.xmin())*(bbox.xmax()-bbox.xmin()) - +(bbox.ymax()-bbox.ymin())*(bbox.ymax()-bbox.ymin()) - ); - // start by marking the domain to mesh - Criteria criteria(0.125, 0.05 * diag); - Mesher mesher(cdt, criteria); - mark_nested_domains(cdt); - for(typename CDT::All_faces_iterator fit=cdt.all_faces_begin(), - fit_end=cdt.all_faces_end(); - fit!=fit_end;++fit) - { - fit->set_in_domain(fit->info().in_domain()); - } - mesher.init(true); - - - mesher.refine_mesh(); + SMesh text_mesh_bottom, text_mesh_complete; cdt2_to_face_graph(cdt, text_mesh_bottom); @@ -700,7 +678,7 @@ public Q_SLOTS: messages->information("Error: the output mesh is not manifold!"); return; } - + CGAL::Polygon_mesh_processing::triangulate_faces(result); Scene_surface_mesh_item* result_item = new Scene_surface_mesh_item( result); @@ -780,7 +758,7 @@ private: fit_end=cdt.finite_faces_end(); fit!=fit_end; ++fit) { - if (!fit->is_in_domain()) continue; + if (!fit->info().in_domain()) continue; CGAL::cpp11::array vds; for(int i=0; i<3; ++i) { From da57904ccdd4877368ce073f545224f1f058f042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 20 Aug 2018 13:40:06 +0200 Subject: [PATCH 17/25] remove trailing whitespaces --- .../Plugins/PMP/Engrave_text_plugin.cpp | 126 +++++++++--------- 1 file changed, 63 insertions(+), 63 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index 6befbf2be8a..541a82d9d30 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -76,7 +76,7 @@ struct Bot double d; const EPICK::Vector_3& n; MAP map; - + }; template @@ -84,7 +84,7 @@ struct Top { Top(const EPICK::Vector_3& n, MAP map):n(n),map(map){} - + template void operator()(const T&, VD vd) const { @@ -118,19 +118,19 @@ public : polylines(polylines), graph(graph), transfo(transfo){} - + ~ParamItem() { delete component; } - + QRectF boundingRect() const { return bounding_rect; } - + void set_transfo(EPICK::Aff_transformation_2 t){ transfo = t;} - + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { QPen pen; @@ -158,7 +158,7 @@ public : points[2] = QPointF(get(uv, h).first, -get(uv, h).second); painter->drawPolygon(points,3); } - + pen.setColor(Qt::red); pen.setWidth(0); painter->setPen(pen); @@ -169,13 +169,13 @@ public : for(std::size_t j =0; jdrawPolyline(points.data(), points.size()); } } - + private: QString texMesh_name; QRectF bounding_rect; @@ -192,7 +192,7 @@ public: :CGAL::Qt::GraphicsViewNavigation(), prev_pos(QPoint(0,0)) { } - + protected: bool eventFilter(QObject *obj, QEvent *ev) { @@ -215,14 +215,14 @@ protected: { qreal dir[2] = {v->mapToScene(me->pos()).x() - prev_pos.x(), v->mapToScene(me->pos()).y() - prev_pos.y()}; - + v->translate(dir[0],dir[1]); v->update(); } prev_pos = v->mapToScene(me->pos()); break; } - + case QEvent::MouseButtonPress: { is_dragging = true; break; @@ -244,7 +244,7 @@ protected: v->update(); break; } - + case QEvent::MouseButtonDblClick: { v->fitInView(v->scene()->itemsBoundingRect(), Qt::KeepAspectRatio); break; @@ -279,7 +279,7 @@ class Q_DECL_EXPORT Engrave_text_plugin : Q_OBJECT Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface) Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0") - + private: typedef CGAL::Surface_mesh_shortest_path_traits SP_traits; typedef CGAL::Surface_mesh_shortest_path Surface_mesh_shortest_path; @@ -289,9 +289,9 @@ private: typedef CGAL::AABB_tree Tree; typedef EPICK::Point_3 Point_3; Messages_interface* messages; - + public : - + void init(QMainWindow* , CGAL::Three::Scene_interface* , Messages_interface* m) Q_DECL_OVERRIDE{ //get refs this->scene = Three::scene(); @@ -311,17 +311,17 @@ public : this, &Engrave_text_plugin::visualize); connect(dock_widget->engraveButton, &QPushButton::clicked, this, &Engrave_text_plugin::engrave); - + //items visu_item = nullptr; sel_item = nullptr; sm = nullptr; - + //transfo angle = 0.0; scalX=1.0; scalY=1.0; - translation = EPICK::Vector_2(0,0); + translation = EPICK::Vector_2(0,0); connect(dock_widget->scalX_slider, &QSlider::valueChanged, this, [this](){ scalX = dock_widget->scalX_slider->value()/1000.0; @@ -338,28 +338,28 @@ public : this, [this](){ cleanup(); }); - + connect(dock_widget->t_up_pushButton, &QPushButton::clicked, this, [this](){ translation += EPICK::Vector_2(0,0.005); scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); - + connect(dock_widget->t_down_pushButton, &QPushButton::clicked, this, [this](){ translation -= EPICK::Vector_2(0,0.005); scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); - + connect(dock_widget->t_right_pushButton, &QPushButton::clicked, this, [this](){ translation += EPICK::Vector_2(0.005,0); scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); - + connect(dock_widget->t_left_pushButton, &QPushButton::clicked, this, [this](){ translation -= EPICK::Vector_2(0.005,0); @@ -392,10 +392,10 @@ public Q_SLOTS: { dock_widget->setVisible(!dock_widget->isVisible()); } - + void visualize() { if(!sel_item) - sel_item = + sel_item = qobject_cast (scene->item(scene->mainSelectionIndex())); if(!sel_item) @@ -413,7 +413,7 @@ public Q_SLOTS: if(visu_item) scene->erase(scene->item_id(visu_item)); visu_item = nullptr; - + if(!sm) { sm = new SMesh(); @@ -422,21 +422,21 @@ public Q_SLOTS: CGAL::Polygon_mesh_processing::longest_border(*sm).first; SMesh::Property_map uv_map = sm->add_property_map("v:uv").first; - + // Parameterized bool pmap boost::unordered_set vs; SMP::internal::Bool_property_map< boost::unordered_set > vpm(vs); - + // Parameterizer SMP::ARAP_parameterizer_3 parameterizer; - + SMP::Error_code status = parameterizer.parameterize(*sm, hd, uv_map, get(boost::vertex_index, *sm), vpm); if(status != SMP::OK) { std::cout << "Encountered a problem: " << status << std::endl; cleanup(); return ; } - + std::cout << "Parameterized with ARAP (SM) computed." << std::endl; xmin = std::numeric_limits::max(); xmax = std::numeric_limits::min(); @@ -452,14 +452,14 @@ public Q_SLOTS: xmax = uv_map[v][0]; if(uv_map[v][0] < xmin) xmin = uv_map[v][0]; - + if(uv_map[v][1] > ymax) ymax = uv_map[v][1]; if(uv_map[v][1] < ymin) ymin = uv_map[v][1]; } - - + + } //create Text Polyline QPainterPath path; @@ -470,7 +470,7 @@ public Q_SLOTS: polylines.clear(); float pxmin(8000),pxmax(-8000), pymin(8000), pymax(-8000); - + Q_FOREACH(QPolygonF poly, polys){ Q_FOREACH(QPointF pf, poly) { @@ -493,7 +493,7 @@ public Q_SLOTS: { EPICK::Point_2 v = EPICK::Point_2(pf.x(),-pf.y()); polylines.back().push_back(EPICK::Point_2(v.x()*(xmax-xmin)/(pxmax-pxmin) +xmin , - v.y()*(ymax-ymin)/(pymax-pymin)+ymin + v.y()*(ymax-ymin)/(pymax-pymin)+ymin )); } } @@ -502,29 +502,29 @@ public Q_SLOTS: { EPICK::Aff_transformation_2 rota = EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2((pxmax+pxmin)/2, (pymax+pymin)/2)) - * EPICK::Aff_transformation_2(CGAL::ROTATION,1,0) + * EPICK::Aff_transformation_2(CGAL::ROTATION,1,0) * EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2(-(pxmax+pxmin)/2, -(pymax+pymin)/2)); - + Q_FOREACH(QPolygonF poly, polys){ polylines.push_back(std::vector()); Q_FOREACH(QPointF pf, poly) { EPICK::Point_2 v = rota.transform(EPICK::Point_2(pf.x(),-pf.y())); polylines.back().push_back(EPICK::Point_2(v.x()*(xmax-xmin)/(pxmax-pxmin) +xmin , - v.y()*(ymax-ymin)/(pymax-pymin)+ymin + v.y()*(ymax-ymin)/(pymax-pymin)+ymin )); } } } // build AABB-tree for face location queries Tree aabb_tree(faces(*sm).first, faces(*sm).second, *sm, uv_map_3); - + visu_item = new Scene_polylines_item; - - + + // compute 3D coordinates - transfo = + transfo = EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2((xmax-xmin)/2+xmin, (ymax-ymin)/2+ymin)+ translation) * EPICK::Aff_transformation_2(CGAL::ROTATION,sin(angle), cos(angle)) @@ -537,7 +537,7 @@ public Q_SLOTS: BOOST_FOREACH(const EPICK::Point_2& p, polyline) { EPICK::Point_2 p_2 = transfo.transform(p); - + Face_location loc = Surface_mesh_shortest_path::locate( Point_3(p_2.x(), p_2.y(), 0), aabb_tree, *sm, uv_map_3); @@ -549,7 +549,7 @@ public Q_SLOTS: visu_item->setColor(QColor(Qt::red)); scene->addItem(visu_item); dock_widget->engraveButton->setEnabled(true); - + if(graphics_scene->items().empty()) { Component* component = new Component(); @@ -575,10 +575,10 @@ public Q_SLOTS: EPICK::FT v = uv_map[target(hd, *sm)].y(); put(uv, *it, std::make_pair(static_cast(u),static_cast(v))); } - + //ParamItem does not take ownership of text_mesh_bottom ParamItem *param_item= new ParamItem(component, polylines, transfo, sm, - QRectF(QPointF(xmin, -ymax), QPointF(xmax, -ymin))); + QRectF(QPointF(xmin, -ymax), QPointF(xmax, -ymin))); graphics_scene->addItem(param_item); dock_widget->graphicsView->fitInView(param_item->boundingRect(), Qt::KeepAspectRatio); } @@ -591,7 +591,7 @@ public Q_SLOTS: } // dock_widget->visualizeButton->setEnabled(false); } - + void engrave() { if(!visu_item) return; @@ -619,7 +619,7 @@ public Q_SLOTS: { QApplication::restoreOverrideCursor(); throw; - } + } if (cdt.dimension()!=2){ QApplication::restoreOverrideCursor(); std::cout << "Triangulation is not of dimension 2" << std::endl; @@ -645,7 +645,7 @@ public Q_SLOTS: normal/=CGAL::sqrt(normal.squared_length()); while(normal == EPICK::Vector_3(0,0,0)) { - QDialog dialog; + QDialog dialog; QLayout *layout = dialog.layout(); QDoubleSpinBox xbox, ybox, zbox; layout->addWidget(&xbox); @@ -653,14 +653,14 @@ public Q_SLOTS: layout->addWidget(&zbox); dialog.setLayout(layout); dialog.exec(); - normal = EPICK::Vector_3(xbox.value(), + normal = EPICK::Vector_3(xbox.value(), ybox.value(), zbox.value()); } Bot bot(normal, dock_widget->depth_spinBox->value(),get(CGAL::vertex_point, text_mesh_complete)); Top top(normal, get(CGAL::vertex_point, text_mesh_complete)); PMP::extrude_mesh(text_mesh_bottom, text_mesh_complete, bot, top); - + if (PMP::does_self_intersect(text_mesh_complete)) { QApplication::restoreOverrideCursor(); @@ -694,7 +694,7 @@ public Q_SLOTS: dock_widget->hide(); } private: - + template void mark_domains(CDT& ct, @@ -723,8 +723,8 @@ private: } } } - - + + template void mark_nested_domains(CDT& cdt) @@ -743,15 +743,15 @@ private: } } } - + template - void cdt2_to_face_graph(const CDT& cdt, + void cdt2_to_face_graph(const CDT& cdt, TriangleMesh& tm) { - + Tree aabb_tree(faces(*sm).first, faces(*sm).second, *sm, uv_map_3); typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - + typedef std::map Map; Map descriptors; for (typename CDT::Finite_faces_iterator fit=cdt.finite_faces_begin(), @@ -775,11 +775,11 @@ private: } vds[i]=it->second; } - + CGAL::Euler::add_face(vds, tm); } } - + void cleanup() { dock_widget->scalX_slider->setValue(1000); @@ -804,7 +804,7 @@ private: visu_item = nullptr; } } - + QList _actions; EngraveWidget* dock_widget; Scene_polylines_item* visu_item; @@ -818,9 +818,9 @@ private: SMesh::Property_map uv_map_3; SMesh* sm; float xmin, xmax, ymin, ymax; - + QGraphicsScene *graphics_scene; Navigation* navigation; -}; +}; #include "Engrave_text_plugin.moc" From a5dd34acf4d8e1122915f1a086e734b4c0c38c21 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 22 Aug 2018 10:29:23 +0200 Subject: [PATCH 18/25] Use one normal per vertex for extrusion --- .../Plugins/PMP/Engrave_text_plugin.cpp | 76 +++++++++---------- 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index 541a82d9d30..60e15bdfeea 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -60,38 +60,44 @@ struct FaceInfo2 } }; -template +template struct Bot { - Bot(const EPICK::Vector_3& n, + Bot(NMAP nmap, double d, - MAP map):d(d), - n(n), - map(map){} + PMAP pmap):d(d), + pmap(pmap), + nmap(nmap){} template - void operator()(const T&,VD vd) const + void operator()(const T& v1,VD v2) const { - put(map, vd, get(map, vd)-d*n); + put(pmap, v2, get(pmap, v2)-d*get(nmap, v1)); } double d; - const EPICK::Vector_3& n; - MAP map; + PMAP pmap; + NMAP nmap; }; -template +template struct Top { - Top(const EPICK::Vector_3& n, - MAP map):n(n),map(map){} + Top(NMAP nmap, + PMAP pmap, + double d):d(d), + nmap(nmap), + pmap(pmap){} template - void operator()(const T&, VD vd) const + void operator()(const T& v1, VD v2) const { - put(map, vd, get(map, vd)+0.01*n); + put(pmap, v2, get(pmap, v2)+(std::min)(0.01, d)*get(nmap, v1)); } - const EPICK::Vector_3& n; - MAP map; + double d; + NMAP nmap; + PMAP pmap; }; typedef EPICK Gt; @@ -636,31 +642,21 @@ public Q_SLOTS: SMesh text_mesh_bottom, text_mesh_complete; cdt2_to_face_graph(cdt, text_mesh_bottom); - typedef typename boost::property_map::type VPMap; - EPICK::Vector_3 normal(0,0,0); - BOOST_FOREACH(face_descriptor f, sel_item->selected_facets) - { - normal += CGAL::Polygon_mesh_processing::compute_face_normal(f, *sel_item->polyhedron()); - } - normal/=CGAL::sqrt(normal.squared_length()); - while(normal == EPICK::Vector_3(0,0,0)) - { - QDialog dialog; - QLayout *layout = dialog.layout(); - QDoubleSpinBox xbox, ybox, zbox; - layout->addWidget(&xbox); - layout->addWidget(&ybox); - layout->addWidget(&zbox); - dialog.setLayout(layout); - dialog.exec(); - normal = EPICK::Vector_3(xbox.value(), - ybox.value(), - zbox.value()); - } - Bot bot(normal, dock_widget->depth_spinBox->value(),get(CGAL::vertex_point, text_mesh_complete)); - Top top(normal, get(CGAL::vertex_point, text_mesh_complete)); + typedef boost::property_map::type VPMap; + typedef SMesh::Property_map NPMAP; + NPMAP vnormals = + text_mesh_bottom.add_property_map("v:normal").first; + + + CGAL::Polygon_mesh_processing::compute_vertex_normals(text_mesh_bottom, vnormals); + + + Bot bot(vnormals, dock_widget->depth_spinBox->value(), + get(CGAL::vertex_point, text_mesh_complete)); + Top top(vnormals, get(CGAL::vertex_point, text_mesh_complete), + dock_widget->depth_spinBox->value()); PMP::extrude_mesh(text_mesh_bottom, text_mesh_complete, bot, top); - if (PMP::does_self_intersect(text_mesh_complete)) { QApplication::restoreOverrideCursor(); From ca2fa5e4215b6046e47ed9ff8437c55102eb55e2 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 22 Aug 2018 12:04:36 +0200 Subject: [PATCH 19/25] Fix transformation of polylines and add option to generate text_mesh_item. --- .../Plugins/PMP/Engrave_dock_widget.ui | 10 + .../Plugins/PMP/Engrave_text_plugin.cpp | 199 +++++++++++------- 2 files changed, 128 insertions(+), 81 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui index b25fd5b6328..c848d03e71d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui @@ -56,6 +56,16 @@ + + + + false + + + Generate Text Mesh + + + diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index 60e15bdfeea..bb0cb7610cd 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -68,7 +68,7 @@ struct Bot double d, PMAP pmap):d(d), pmap(pmap), - nmap(nmap){} + nmap(nmap){} template void operator()(const T& v1,VD v2) const { @@ -77,7 +77,7 @@ struct Bot double d; PMAP pmap; NMAP nmap; - + }; template void operator()(const T& v1, VD v2) const { @@ -124,19 +124,19 @@ public : polylines(polylines), graph(graph), transfo(transfo){} - + ~ParamItem() { delete component; } - + QRectF boundingRect() const { return bounding_rect; } - + void set_transfo(EPICK::Aff_transformation_2 t){ transfo = t;} - + void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { QPen pen; @@ -148,7 +148,8 @@ public : painter->setPen(pen); painter->setBrush(brush); SMesh::Property_map > uv; - uv = graph->add_property_map >("h:uv",std::make_pair(0.0f,0.0f)).first; + uv = graph->add_property_map > + ("h:uv",std::make_pair(0.0f,0.0f)).first; for( Component::iterator fi = component->begin(); fi != component->end(); @@ -164,7 +165,7 @@ public : points[2] = QPointF(get(uv, h).first, -get(uv, h).second); painter->drawPolygon(points,3); } - + pen.setColor(Qt::red); pen.setWidth(0); painter->setPen(pen); @@ -181,7 +182,7 @@ public : painter->drawPolyline(points.data(), points.size()); } } - + private: QString texMesh_name; QRectF bounding_rect; @@ -198,7 +199,7 @@ public: :CGAL::Qt::GraphicsViewNavigation(), prev_pos(QPoint(0,0)) { } - + protected: bool eventFilter(QObject *obj, QEvent *ev) { @@ -221,14 +222,14 @@ protected: { qreal dir[2] = {v->mapToScene(me->pos()).x() - prev_pos.x(), v->mapToScene(me->pos()).y() - prev_pos.y()}; - + v->translate(dir[0],dir[1]); v->update(); } prev_pos = v->mapToScene(me->pos()); break; } - + case QEvent::MouseButtonPress: { is_dragging = true; break; @@ -250,7 +251,7 @@ protected: v->update(); break; } - + case QEvent::MouseButtonDblClick: { v->fitInView(v->scene()->itemsBoundingRect(), Qt::KeepAspectRatio); break; @@ -285,7 +286,7 @@ class Q_DECL_EXPORT Engrave_text_plugin : Q_OBJECT Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface) Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0") - + private: typedef CGAL::Surface_mesh_shortest_path_traits SP_traits; typedef CGAL::Surface_mesh_shortest_path Surface_mesh_shortest_path; @@ -295,15 +296,17 @@ private: typedef CGAL::AABB_tree Tree; typedef EPICK::Point_3 Point_3; Messages_interface* messages; - + public : - - void init(QMainWindow* , CGAL::Three::Scene_interface* , Messages_interface* m) Q_DECL_OVERRIDE{ + + void init(QMainWindow*, + CGAL::Three::Scene_interface*, + Messages_interface* m) Q_DECL_OVERRIDE{ //get refs this->scene = Three::scene(); this->mw = Three::mainWindow(); messages = m; - + //action QAction* actionFitText= new QAction("Fit Text", mw); connect(actionFitText, SIGNAL(triggered()), @@ -317,12 +320,14 @@ public : this, &Engrave_text_plugin::visualize); connect(dock_widget->engraveButton, &QPushButton::clicked, this, &Engrave_text_plugin::engrave); - + connect(dock_widget->text_meshButton, &QPushButton::clicked, + this, &Engrave_text_plugin::generateTextItem); + //items visu_item = nullptr; sel_item = nullptr; sm = nullptr; - + //transfo angle = 0.0; scalX=1.0; @@ -344,28 +349,28 @@ public : this, [this](){ cleanup(); }); - + connect(dock_widget->t_up_pushButton, &QPushButton::clicked, this, [this](){ translation += EPICK::Vector_2(0,0.005); scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); - + connect(dock_widget->t_down_pushButton, &QPushButton::clicked, this, [this](){ translation -= EPICK::Vector_2(0,0.005); scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); - + connect(dock_widget->t_right_pushButton, &QPushButton::clicked, this, [this](){ translation += EPICK::Vector_2(0.005,0); scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); - + connect(dock_widget->t_left_pushButton, &QPushButton::clicked, this, [this](){ translation -= EPICK::Vector_2(0.005,0); @@ -398,7 +403,7 @@ public Q_SLOTS: { dock_widget->setVisible(!dock_widget->isVisible()); } - + void visualize() { if(!sel_item) sel_item = @@ -419,7 +424,7 @@ public Q_SLOTS: if(visu_item) scene->erase(scene->item_id(visu_item)); visu_item = nullptr; - + if(!sm) { sm = new SMesh(); @@ -428,21 +433,22 @@ public Q_SLOTS: CGAL::Polygon_mesh_processing::longest_border(*sm).first; SMesh::Property_map uv_map = sm->add_property_map("v:uv").first; - + // Parameterized bool pmap boost::unordered_set vs; SMP::internal::Bool_property_map< boost::unordered_set > vpm(vs); - + // Parameterizer SMP::ARAP_parameterizer_3 parameterizer; - - SMP::Error_code status = parameterizer.parameterize(*sm, hd, uv_map, get(boost::vertex_index, *sm), vpm); + + SMP::Error_code status = parameterizer.parameterize(*sm, hd, uv_map, + get(boost::vertex_index, *sm), vpm); if(status != SMP::OK) { std::cout << "Encountered a problem: " << status << std::endl; cleanup(); return ; } - + std::cout << "Parameterized with ARAP (SM) computed." << std::endl; xmin = std::numeric_limits::max(); xmax = std::numeric_limits::min(); @@ -458,25 +464,25 @@ public Q_SLOTS: xmax = uv_map[v][0]; if(uv_map[v][0] < xmin) xmin = uv_map[v][0]; - + if(uv_map[v][1] > ymax) ymax = uv_map[v][1]; if(uv_map[v][1] < ymin) ymin = uv_map[v][1]; } - - + + } //create Text Polyline QPainterPath path; QFont font; font.setPointSize(15); - path.addText(QPoint(xmin,ymin), font, dock_widget->lineEdit->text()); + path.addText(QPoint(xmin,ymin), font, dock_widget->lineEdit->text()); QList polys = path.toSubpathPolygons(); polylines.clear(); float pxmin(8000),pxmax(-8000), pymin(8000), pymax(-8000); - + Q_FOREACH(QPolygonF poly, polys){ Q_FOREACH(QPointF pf, poly) { @@ -498,7 +504,7 @@ public Q_SLOTS: Q_FOREACH(QPointF pf, poly) { EPICK::Point_2 v = EPICK::Point_2(pf.x(),-pf.y()); - polylines.back().push_back(EPICK::Point_2(v.x()*(xmax-xmin)/(pxmax-pxmin) +xmin , + polylines.back().push_back(EPICK::Point_2(v.x()*(xmax-xmin)/(pxmax-pxmin) +xmin, v.y()*(ymax-ymin)/(pymax-pymin)+ymin )); } @@ -506,12 +512,13 @@ public Q_SLOTS: } else { - EPICK::Aff_transformation_2 rota = EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2((pxmax+pxmin)/2, - (pymax+pymin)/2)) - * EPICK::Aff_transformation_2(CGAL::ROTATION,1,0) - * EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2(-(pxmax+pxmin)/2, - -(pymax+pymin)/2)); - + EPICK::Aff_transformation_2 rota = + EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2((pxmax+pxmin)/2, + (pymax+pymin)/2)) + * EPICK::Aff_transformation_2(CGAL::ROTATION,1,0) + * EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2(-(pxmax+pxmin)/2, + -(pymax+pymin)/2)); + Q_FOREACH(QPolygonF poly, polys){ polylines.push_back(std::vector()); Q_FOREACH(QPointF pf, poly) @@ -525,25 +532,27 @@ public Q_SLOTS: } // build AABB-tree for face location queries Tree aabb_tree(faces(*sm).first, faces(*sm).second, *sm, uv_map_3); - + visu_item = new Scene_polylines_item; - - + + // compute 3D coordinates transfo = - EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2((xmax-xmin)/2+xmin, - (ymax-ymin)/2+ymin)+ translation) + EPICK::Aff_transformation_2(CGAL::TRANSLATION, + EPICK::Vector_2((xmax-xmin)/2+xmin, + (ymax-ymin)/2+ymin)+ translation) * EPICK::Aff_transformation_2(CGAL::ROTATION,sin(angle), cos(angle)) * EPICK::Aff_transformation_2(scalX, 0.0,0.0,scalY) - * EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2(-(xmax-xmin)/2-xmin, - -(ymax-ymin)/2-ymin)); + * EPICK::Aff_transformation_2(CGAL::TRANSLATION, + EPICK::Vector_2(-(xmax-xmin)/2-xmin, + -(ymax-ymin)/2-ymin)); BOOST_FOREACH(const std::vector& polyline, polylines) { visu_item->polylines.push_back(std::vector()); BOOST_FOREACH(const EPICK::Point_2& p, polyline) { EPICK::Point_2 p_2 = transfo.transform(p); - + Face_location loc = Surface_mesh_shortest_path::locate( Point_3(p_2.x(), p_2.y(), 0), aabb_tree, *sm, uv_map_3); @@ -555,7 +564,8 @@ public Q_SLOTS: visu_item->setColor(QColor(Qt::red)); scene->addItem(visu_item); dock_widget->engraveButton->setEnabled(true); - + dock_widget->text_meshButton->setEnabled(true); + if(graphics_scene->items().empty()) { Component* component = new Component(); @@ -581,7 +591,7 @@ public Q_SLOTS: EPICK::FT v = uv_map[target(hd, *sm)].y(); put(uv, *it, std::make_pair(static_cast(u),static_cast(v))); } - + //ParamItem does not take ownership of text_mesh_bottom ParamItem *param_item= new ParamItem(component, polylines, transfo, sm, QRectF(QPointF(xmin, -ymax), QPointF(xmax, -ymin))); @@ -597,8 +607,9 @@ public Q_SLOTS: } // dock_widget->visualizeButton->setEnabled(false); } - - void engrave() { + + void create_text_mesh(SMesh& text_mesh) + { if(!visu_item) return; if(!sel_item) @@ -607,13 +618,15 @@ public Q_SLOTS: return; if(!CGAL::is_closed(*sel_item->polyhedron())) return; - QApplication::setOverrideCursor(Qt::WaitCursor); CDT cdt; + //polylines is duplicated so the transformation is only performed once + std::vector > local_polylines + = polylines; try{ for(std::size_t i = 0; - i < polylines.size(); ++i) + i < local_polylines.size(); ++i) { - std::vector& points = polylines[i]; + std::vector& points = local_polylines[i]; for(std::size_t j = 0; j< points.size(); ++j) { Point_2 &p = points[j]; @@ -631,15 +644,17 @@ public Q_SLOTS: std::cout << "Triangulation is not of dimension 2" << std::endl; return; } - CGAL::Bbox_2 bbox= CGAL::bbox_2(polylines.front().begin(), polylines.front().end(), EPICK()); + CGAL::Bbox_2 bbox= CGAL::bbox_2(local_polylines.front().begin(), + local_polylines.front().end(), + EPICK()); Q_FOREACH(const std::vector& points, - polylines) + local_polylines) { bbox += CGAL::bbox_2(points.begin(), points.end(), EPICK()); } mark_nested_domains(cdt); - - SMesh text_mesh_bottom, text_mesh_complete; + + SMesh text_mesh_bottom; cdt2_to_face_graph(cdt, text_mesh_bottom); typedef boost::property_map::type VPMap; @@ -653,28 +668,35 @@ public Q_SLOTS: Bot bot(vnormals, dock_widget->depth_spinBox->value(), - get(CGAL::vertex_point, text_mesh_complete)); - Top top(vnormals, get(CGAL::vertex_point, text_mesh_complete), + get(CGAL::vertex_point, text_mesh)); + Top top(vnormals, get(CGAL::vertex_point, text_mesh), dock_widget->depth_spinBox->value()); - PMP::extrude_mesh(text_mesh_bottom, text_mesh_complete, bot, top); + PMP::extrude_mesh(text_mesh_bottom, text_mesh, bot, top); + } + + void engrave() { + QApplication::setOverrideCursor(Qt::WaitCursor); + SMesh text_mesh_complete; + create_text_mesh(text_mesh_complete); + if (PMP::does_self_intersect(text_mesh_complete)) { QApplication::restoreOverrideCursor(); messages->information("Error: text mesh self-intersects!"); return; } - + SMesh result; CGAL::copy_face_graph(*sel_item->polyhedron(), result); bool OK = PMP::corefine_and_compute_difference(result, text_mesh_complete, result); - + if (!OK) { QApplication::restoreOverrideCursor(); messages->information("Error: the output mesh is not manifold!"); return; } - + CGAL::Polygon_mesh_processing::triangulate_faces(result); Scene_surface_mesh_item* result_item = new Scene_surface_mesh_item( result); @@ -683,14 +705,27 @@ public Q_SLOTS: cleanup(); QApplication::restoreOverrideCursor(); dock_widget->engraveButton->setEnabled(false); + dock_widget->text_meshButton->setEnabled(false); dock_widget->visualizeButton->setEnabled(true); } + + void generateTextItem() + { + QApplication::setOverrideCursor(Qt::WaitCursor); + SMesh text_mesh; + create_text_mesh(text_mesh); + Scene_surface_mesh_item* textMesh = new Scene_surface_mesh_item(text_mesh); + textMesh->setName("Extruded Text"); + scene->addItem(textMesh); + QApplication::restoreOverrideCursor(); + } + void closure()Q_DECL_OVERRIDE { dock_widget->hide(); } + private: - template void mark_domains(CDT& ct, @@ -719,13 +754,14 @@ private: } } } - - + + template void mark_nested_domains(CDT& cdt) { - for(typename CDT::All_faces_iterator it = cdt.all_faces_begin(); it != cdt.all_faces_end(); ++it){ + for(typename CDT::All_faces_iterator it = cdt.all_faces_begin(); it != + cdt.all_faces_end(); ++it){ it->info().nesting_level = -1; } std::list border; @@ -739,15 +775,15 @@ private: } } } - + template void cdt2_to_face_graph(const CDT& cdt, TriangleMesh& tm) { - + Tree aabb_tree(faces(*sm).first, faces(*sm).second, *sm, uv_map_3); typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - + typedef std::map Map; Map descriptors; for (typename CDT::Finite_faces_iterator fit=cdt.finite_faces_begin(), @@ -767,15 +803,16 @@ private: Face_location loc = Surface_mesh_shortest_path::locate( Point_3(pt.x(), pt.y(), 0), aabb_tree, *sm, uv_map_3); - it->second = add_vertex(Surface_mesh_shortest_path::point(loc.first, loc.second, *sm, sm->points()), tm); + it->second = add_vertex(Surface_mesh_shortest_path::point(loc.first, loc.second, + *sm, sm->points()), tm); } vds[i]=it->second; } - + CGAL::Euler::add_face(vds, tm); } } - + void cleanup() { dock_widget->scalX_slider->setValue(1000); @@ -800,7 +837,7 @@ private: visu_item = nullptr; } } - + QList _actions; EngraveWidget* dock_widget; Scene_polylines_item* visu_item; @@ -814,7 +851,7 @@ private: SMesh::Property_map uv_map_3; SMesh* sm; float xmin, xmax, ymin, ymax; - + QGraphicsScene *graphics_scene; Navigation* navigation; }; From 625b5cb586d862058229fa5ce7ee409e03b9d2a1 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 22 Aug 2018 12:34:07 +0200 Subject: [PATCH 20/25] Edit existing textmesh item if possible. --- .../Plugins/PMP/Engrave_text_plugin.cpp | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index bb0cb7610cd..d8b18c1a5f3 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -326,6 +326,7 @@ public : //items visu_item = nullptr; sel_item = nullptr; + textMesh = nullptr; sm = nullptr; //transfo @@ -703,6 +704,10 @@ public Q_SLOTS: scene->addItem(result_item); graphics_scene->clear(); cleanup(); + if(textMesh) + { + textMesh->setVisible(false); + } QApplication::restoreOverrideCursor(); dock_widget->engraveButton->setEnabled(false); dock_widget->text_meshButton->setEnabled(false); @@ -712,11 +717,24 @@ public Q_SLOTS: void generateTextItem() { QApplication::setOverrideCursor(Qt::WaitCursor); - SMesh text_mesh; - create_text_mesh(text_mesh); - Scene_surface_mesh_item* textMesh = new Scene_surface_mesh_item(text_mesh); - textMesh->setName("Extruded Text"); - scene->addItem(textMesh); + + if(textMesh) + { + textMesh->face_graph()->clear(); + create_text_mesh(*textMesh->face_graph()); + textMesh->invalidateOpenGLBuffers(); + } + else + { + SMesh text_mesh; + create_text_mesh(text_mesh); + textMesh = new Scene_surface_mesh_item(text_mesh); + connect(textMesh, &Scene_surface_mesh_item::aboutToBeDestroyed, + this, [this](){ + textMesh = nullptr;}); + textMesh->setName("Extruded Text"); + scene->addItem(textMesh); + } QApplication::restoreOverrideCursor(); } @@ -842,6 +860,7 @@ private: EngraveWidget* dock_widget; Scene_polylines_item* visu_item; Scene_polyhedron_selection_item* sel_item; + Scene_surface_mesh_item* textMesh; double angle; double scalX; double scalY; From ebf374970a4eeca0bcbdacd06bcd98094b54a514 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 22 Aug 2018 16:23:53 +0200 Subject: [PATCH 21/25] Enhancements --- .../Plugins/PMP/Engrave_dock_widget.ui | 199 ++++++++++++------ .../Plugins/PMP/Engrave_text_plugin.cpp | 78 ++++--- 2 files changed, 179 insertions(+), 98 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui index c848d03e71d..ca5772821a9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui @@ -6,23 +6,23 @@ 0 0 - 305 - 421 + 282 + 488 Engraving - - + + An Example Text - + @@ -90,14 +90,7 @@ - - - - Engraving depth: - - - - + -179 @@ -134,7 +127,43 @@ - + + + + + + + + :/cgal/icons/resources/down.png:/cgal/icons/resources/down.png + + + + + + + Scaling factor in X: + + + + + + + + + + + :/cgal/icons/resources/left_arrow.png:/cgal/icons/resources/left_arrow.png + + + + + + + Rotation degree: + + + + 2000 @@ -153,59 +182,7 @@ - - - - - - - - :/cgal/icons/resources/down.png:/cgal/icons/resources/down.png - - - - - - - Scaling factor in X: - - - - - - - - - - - :/cgal/icons/resources/left_arrow.png:/cgal/icons/resources/left_arrow.png - - - - - - - Rotation degree: - - - - - - - 6 - - - 0.000001000000000 - - - 0.100000000000000 - - - 0.010000000000000 - - - - + 2000 @@ -221,18 +198,104 @@ - + Scaling factor in Y: + + + + 1 + + + 15 + + + Qt::Horizontal + + + + + + + Text Precision + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Engraving Depth + + + + + + Inside depth: + + + + + + + Outside depth: + + + + + + + 10000 + + + 1000 + + + Qt::Horizontal + + + + + + + 10000 + + + 1000 + + + Qt::Horizontal + + + + + + + + diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index d8b18c1a5f3..5c97fd4dcdf 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -93,7 +94,7 @@ struct Top template void operator()(const T& v1, VD v2) const { - put(pmap, v2, get(pmap, v2)+(std::min)(0.01, d)*get(nmap, v1)); + put(pmap, v2, get(pmap, v2)+d*get(nmap, v1)); } double d; NMAP nmap; @@ -334,6 +335,14 @@ public : scalX=1.0; scalY=1.0; translation = EPICK::Vector_2(0,0); + pointsize = 15; + locked = false; + connect(dock_widget->text_prec_slider, &QSlider::valueChanged, + this, [this](){ + pointsize = dock_widget->text_prec_slider->value(); + scene->setSelectedItem(scene->item_id(sel_item)); + visualize(); + }); connect(dock_widget->scalX_slider, &QSlider::valueChanged, this, [this](){ scalX = dock_widget->scalX_slider->value()/1000.0; @@ -346,6 +355,19 @@ public : scene->setSelectedItem(scene->item_id(sel_item)); visualize(); }); + + connect(dock_widget->bot_slider, &QSlider::valueChanged, + this, [this](){ + if(textMesh) + generateTextItem(); + }); + + connect(dock_widget->top_slider, &QSlider::valueChanged, + this, [this](){ + if(textMesh) + generateTextItem(); + }); + connect(dock_widget->reset_button, &QPushButton::clicked, this, [this](){ cleanup(); @@ -381,8 +403,11 @@ public : connect(dock_widget->rot_slider, &QSlider::valueChanged, this, [this](){ angle = dock_widget->rot_slider->value() * CGAL_PI/180.0; - scene->setSelectedItem(scene->item_id(sel_item)); - visualize(); + if(!locked) + { + scene->setSelectedItem(scene->item_id(sel_item)); + visualize(); + } }); graphics_scene = new QGraphicsScene(dock_widget); dock_widget->graphicsView->setScene(graphics_scene); @@ -472,12 +497,25 @@ public Q_SLOTS: ymin = uv_map[v][1]; } + CGAL::linear_least_squares_fitting_2( + uv_map.begin(), + uv_map.end(), + bf_line, + CGAL::Dimension_tag<0>()); + Kernel::Vector_2 A(bf_line.to_vector()), + B(Kernel::Point_2(0,0), + Kernel::Point_2(0,1)); + double cosangle = CGAL::scalar_product(A,B)/CGAL::sqrt(A.squared_length()); + + locked = true; + dock_widget->rot_slider->setSliderPosition(acos(abs(cosangle))*180.0/CGAL_PI); + locked = false; } //create Text Polyline QPainterPath path; QFont font; - font.setPointSize(15); + font.setPointSize(pointsize); path.addText(QPoint(xmin,ymin), font, dock_widget->lineEdit->text()); QList polys = path.toSubpathPolygons(); polylines.clear(); @@ -498,39 +536,17 @@ public Q_SLOTS: pymax = v.y(); } } - if(ymax-ymin <= xmax - xmin) - { Q_FOREACH(QPolygonF poly, polys){ polylines.push_back(std::vector()); Q_FOREACH(QPointF pf, poly) { EPICK::Point_2 v = EPICK::Point_2(pf.x(),-pf.y()); - polylines.back().push_back(EPICK::Point_2(v.x()*(xmax-xmin)/(pxmax-pxmin) +xmin, - v.y()*(ymax-ymin)/(pymax-pymin)+ymin - )); - } - } - } - else - { - EPICK::Aff_transformation_2 rota = - EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2((pxmax+pxmin)/2, - (pymax+pymin)/2)) - * EPICK::Aff_transformation_2(CGAL::ROTATION,1,0) - * EPICK::Aff_transformation_2(CGAL::TRANSLATION, EPICK::Vector_2(-(pxmax+pxmin)/2, - -(pymax+pymin)/2)); - - Q_FOREACH(QPolygonF poly, polys){ - polylines.push_back(std::vector()); - Q_FOREACH(QPointF pf, poly) - { - EPICK::Point_2 v = rota.transform(EPICK::Point_2(pf.x(),-pf.y())); polylines.back().push_back(EPICK::Point_2(v.x()*(xmax-xmin)/(pxmax-pxmin) +xmin , v.y()*(ymax-ymin)/(pymax-pymin)+ymin )); } } - } + // build AABB-tree for face location queries Tree aabb_tree(faces(*sm).first, faces(*sm).second, *sm, uv_map_3); @@ -668,10 +684,10 @@ public Q_SLOTS: CGAL::Polygon_mesh_processing::compute_vertex_normals(text_mesh_bottom, vnormals); - Bot bot(vnormals, dock_widget->depth_spinBox->value(), + Bot bot(vnormals, dock_widget->bot_slider->value()/100000.0, get(CGAL::vertex_point, text_mesh)); Top top(vnormals, get(CGAL::vertex_point, text_mesh), - dock_widget->depth_spinBox->value()); + dock_widget->top_slider->value()/100000.0); PMP::extrude_mesh(text_mesh_bottom, text_mesh, bot, top); } @@ -870,7 +886,9 @@ private: SMesh::Property_map uv_map_3; SMesh* sm; float xmin, xmax, ymin, ymax; - + int pointsize; + bool locked; + Kernel::Line_2 bf_line; QGraphicsScene *graphics_scene; Navigation* navigation; }; From adafa919576e1df9cfbdfbedd706b45daaf42a54 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 22 Aug 2018 17:18:18 +0200 Subject: [PATCH 22/25] Add a mode for uniform normals per letter. --- .../Plugins/PMP/Engrave_dock_widget.ui | 39 +++++++++++-------- .../Plugins/PMP/Engrave_text_plugin.cpp | 39 +++++++++++++++++-- 2 files changed, 58 insertions(+), 20 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui index ca5772821a9..a893a256196 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_dock_widget.ui @@ -6,8 +6,8 @@ 0 0 - 282 - 488 + 293 + 515 @@ -251,20 +251,6 @@ Engraving Depth - - - - Inside depth: - - - - - - - Outside depth: - - - @@ -291,6 +277,27 @@ + + + + Inside depth: + + + + + + + Outside depth: + + + + + + + Uniform letter mode + + + diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index 5c97fd4dcdf..91c26c38eaa 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -30,6 +30,8 @@ #include #include +#include + #include #include #include @@ -323,6 +325,8 @@ public : this, &Engrave_text_plugin::engrave); connect(dock_widget->text_meshButton, &QPushButton::clicked, this, &Engrave_text_plugin::generateTextItem); + connect(dock_widget->letter_checkBox, &QCheckBox::toggled, + this, &Engrave_text_plugin::generateTextItem); //items visu_item = nullptr; @@ -680,10 +684,37 @@ public Q_SLOTS: text_mesh_bottom.add_property_map("v:normal").first; - - CGAL::Polygon_mesh_processing::compute_vertex_normals(text_mesh_bottom, vnormals); - - + if(!dock_widget->letter_checkBox->isChecked()) + { + CGAL::Polygon_mesh_processing::compute_vertex_normals(text_mesh_bottom, vnormals); + } + else{ + // \todo Computing normals before the final + // mesh would be better. + + //foreach CC + SMesh::Property_map fcmap = + text_mesh_bottom.add_property_map("f:cc", 0).first; + std::size_t nb_cc = PMP::connected_components(text_mesh_bottom, + fcmap); + for(std::size_t cc = 0; cc fmesh(text_mesh_bottom, + cc, + fcmap); + BOOST_FOREACH(vertex_descriptor vd, vertices(fmesh)) + { + normal += CGAL::Polygon_mesh_processing::compute_vertex_normal(vd, fmesh); + } + normal /= CGAL::sqrt(normal.squared_length()); + BOOST_FOREACH(vertex_descriptor vd, vertices(fmesh)) + { + put(vnormals, vd, normal); + } + } + } Bot bot(vnormals, dock_widget->bot_slider->value()/100000.0, get(CGAL::vertex_point, text_mesh)); Top top(vnormals, get(CGAL::vertex_point, text_mesh), From 9291d7aefbb1df9759b620329e50a4f5d1cf1c54 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 22 Aug 2018 18:26:35 +0200 Subject: [PATCH 23/25] Fix rotation init --- .../Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index 91c26c38eaa..36e13a32c58 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -191,6 +191,7 @@ private: QRectF bounding_rect; Component* component; const std::vector >& polylines; + SMesh* graph; EPICK::Aff_transformation_2 transfo; }; @@ -406,9 +407,9 @@ public : }); connect(dock_widget->rot_slider, &QSlider::valueChanged, this, [this](){ - angle = dock_widget->rot_slider->value() * CGAL_PI/180.0; if(!locked) { + angle = dock_widget->rot_slider->value() * CGAL_PI/180.0; scene->setSelectedItem(scene->item_id(sel_item)); visualize(); } @@ -509,11 +510,14 @@ public Q_SLOTS: Kernel::Vector_2 A(bf_line.to_vector()), B(Kernel::Point_2(0,0), - Kernel::Point_2(0,1)); - double cosangle = CGAL::scalar_product(A,B)/CGAL::sqrt(A.squared_length()); + Kernel::Point_2(1,0)); + if (A.x()<0) A=-A; + angle = std::acos(A.x()/CGAL::sqrt(A.squared_length())); + if ( A.y()<0 ) angle+=3*CGAL_PI/2.; + if (angle>2*CGAL_PI) angle-=CGAL_PI; locked = true; - dock_widget->rot_slider->setSliderPosition(acos(abs(cosangle))*180.0/CGAL_PI); + dock_widget->rot_slider->setSliderPosition(angle*180.0/CGAL_PI); locked = false; } //create Text Polyline From 3434244ca5cf55dcdce96f0b24ab185c0af176b1 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 23 Aug 2018 10:04:45 +0200 Subject: [PATCH 24/25] Fix modulo in init --- Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index 36e13a32c58..08d6199826d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -514,7 +514,7 @@ public Q_SLOTS: if (A.x()<0) A=-A; angle = std::acos(A.x()/CGAL::sqrt(A.squared_length())); if ( A.y()<0 ) angle+=3*CGAL_PI/2.; - if (angle>2*CGAL_PI) angle-=CGAL_PI; + if (angle>2*CGAL_PI) angle-=2*CGAL_PI; locked = true; dock_widget->rot_slider->setSliderPosition(angle*180.0/CGAL_PI); From aabd798126d0b25a740b81d7665a171d42721038 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 20 Nov 2018 10:47:37 +0100 Subject: [PATCH 25/25] Fix warnings std::size_t to int --- .../demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index 737311166b6..6cad4ed03c9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -182,7 +182,7 @@ public : points.push_back(QPointF(transfo_point.x(), -transfo_point.y())); } - painter->drawPolyline(points.data(), points.size()); + painter->drawPolyline(points.data(), static_cast(points.size())); } } @@ -706,7 +706,7 @@ public Q_SLOTS: //compute the average normal for the cc give it to every vertex EPICK::Vector_3 normal(0,0,0); CGAL::Face_filtered_graph fmesh(text_mesh_bottom, - cc, + static_cast(cc), fcmap); BOOST_FOREACH(vertex_descriptor vd, vertices(fmesh)) {