1 #include <QtCore/qglobal.h> 2 3 #include <CGAL/Three/Polyhedron_demo_plugin_interface.h> 4 #include <CGAL/Three/Polyhedron_demo_plugin_helper.h> 5 6 #include <CGAL/iterator.h> 7 #include <CGAL/utility.h> 8 #include <CGAL/property_map.h> 9 #include <CGAL/Surface_mesh.h> 10 11 #include <CGAL/Polygon_mesh_processing/smooth_mesh.h> 12 #include <CGAL/Polygon_mesh_processing/smooth_shape.h> 13 14 #include "Scene.h" 15 #include "Scene_surface_mesh_item.h" 16 #include "Scene_polyhedron_selection_item.h" 17 18 #include "ui_Smoothing_plugin.h" 19 20 #include <QElapsedTimer> 21 #include <QAction> 22 #include <QMainWindow> 23 #include <QApplication> 24 #include <QDockWidget> 25 #include <QString> 26 #include <QInputDialog> 27 #include <QtPlugin> 28 #include <QMessageBox> 29 30 using namespace CGAL::Polygon_mesh_processing; 31 using namespace CGAL::Three; 32 33 typedef Scene_surface_mesh_item Scene_face_graph_item; 34 typedef Scene_face_graph_item::Face_graph Face_graph; 35 36 typedef boost::graph_traits<Face_graph>::vertex_descriptor vertex_descriptor; 37 typedef boost::graph_traits<Face_graph>::edge_descriptor edge_descriptor; 38 typedef boost::graph_traits<Face_graph>::face_descriptor face_descriptor; 39 40 typedef CGAL::dynamic_vertex_property_t<bool> Vertex_bool_property; 41 typedef typename boost::property_map<Face_graph, Vertex_bool_property>::type VCMap; 42 43 class Polyhedron_demo_smothing_plugin 44 : public QObject, public Polyhedron_demo_plugin_helper 45 { 46 Q_OBJECT 47 Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface) 48 Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0") 49 50 public: init(QMainWindow * mainWindow,Scene_interface * scene_interface,Messages_interface *)51 void init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface*) 52 { 53 scene = scene_interface; 54 mw = mainWindow; 55 56 actionSmoothing_ = new QAction(tr("Mesh and Shape Smoothing"), mw); 57 actionSmoothing_->setProperty("subMenuName", "Polygon Mesh Processing"); 58 59 connect(actionSmoothing_, SIGNAL(triggered()), this, SLOT(smoothing_action())); 60 61 dock_widget = new QDockWidget("Smoothing", mw); 62 dock_widget->setVisible(false); 63 64 ui_widget.setupUi(dock_widget); 65 addDockWidget(dock_widget); 66 67 connect(ui_widget.area_smoothing_checkBox, SIGNAL(toggled(bool)), 68 ui_widget.flip_checkBox, SLOT(setEnabled(bool))); 69 70 connect(ui_widget.mesh_smoothing_button, SIGNAL(clicked()), this, SLOT(on_mesh_smoothing_clicked())); 71 connect(ui_widget.shape_smoothing_button, SIGNAL(clicked()), this, SLOT(on_shape_smoothing_clicked())); 72 } 73 actions() const74 QList<QAction*> actions() const 75 { 76 return QList<QAction*>() << actionSmoothing_; 77 } 78 applicable(QAction *) const79 bool applicable(QAction*) const 80 { 81 const Scene_interface::Item_id index = scene->mainSelectionIndex(); 82 if(qobject_cast<Scene_face_graph_item*>(scene->item(index))) 83 return true; 84 else if(qobject_cast<Scene_polyhedron_selection_item*>(scene->item(index))) 85 return true; 86 else 87 return false; 88 } 89 closure()90 virtual void closure() 91 { 92 dock_widget->hide(); 93 } 94 init_ui()95 void init_ui() 96 { 97 ui_widget.time_step_spinBox->setValue(0.00001); 98 ui_widget.time_step_spinBox->setMinimum(1e-6); 99 100 ui_widget.smooth_iter_spinBox->setValue(1); 101 ui_widget.projection_checkBox->setChecked(true); 102 103 ui_widget.area_smoothing_checkBox->setChecked(false); 104 ui_widget.flip_checkBox->setDisabled(true); 105 } 106 mark_border_vertices(const VCMap vcmap,const Face_graph & pmesh) const107 void mark_border_vertices(const VCMap vcmap, const Face_graph& pmesh) const 108 { 109 for(halfedge_descriptor h : halfedges(pmesh)) 110 { 111 if(CGAL::is_border(h, pmesh)) 112 put(vcmap, target(h, pmesh), true); 113 } 114 } 115 mark_selected_vertices(const VCMap vcmap,const Face_graph & pmesh,Scene_polyhedron_selection_item * selection_item) const116 void mark_selected_vertices(const VCMap vcmap, 117 const Face_graph& pmesh, 118 Scene_polyhedron_selection_item* selection_item) const 119 { 120 for(vertex_descriptor v : selection_item->selected_vertices) 121 put(vcmap, v, true); 122 123 for(edge_descriptor e : selection_item->selected_edges) 124 { 125 put(vcmap, source(e, pmesh), true); 126 put(vcmap, target(e, pmesh), true); 127 } 128 } 129 130 public Q_SLOTS: smoothing_action()131 void smoothing_action() 132 { 133 dock_widget->show(); 134 dock_widget->raise(); 135 136 const Scene_interface::Item_id index = scene->mainSelectionIndex(); 137 Scene_face_graph_item* poly_item = qobject_cast<Scene_face_graph_item*>(scene->item(index)); 138 139 Scene_polyhedron_selection_item* selection_item = 140 qobject_cast<Scene_polyhedron_selection_item*>(scene->item(index)); 141 142 if(poly_item || selection_item) 143 { 144 init_ui(); 145 } 146 } 147 on_mesh_smoothing_clicked()148 void on_mesh_smoothing_clicked() 149 { 150 const Scene_interface::Item_id index = scene->mainSelectionIndex(); 151 Scene_face_graph_item* poly_item = qobject_cast<Scene_face_graph_item*>(scene->item(index)); 152 Scene_polyhedron_selection_item* selection_item = qobject_cast<Scene_polyhedron_selection_item*>(scene->item(index)); 153 154 if(!poly_item && !selection_item) 155 return; 156 157 Face_graph& pmesh = (poly_item != nullptr) ? * poly_item->polyhedron() : * selection_item->polyhedron(); 158 159 const unsigned int nb_iter = ui_widget.smooth_iter_spinBox->value(); 160 const bool projection = ui_widget.projection_checkBox->isChecked(); 161 const bool use_safety_measures = ui_widget.sanity_checkBox->isChecked(); 162 const bool constrain_border_vertices = ui_widget.border_button->isChecked() && !CGAL::is_closed(pmesh); 163 const bool use_angle_smoothing = ui_widget.angle_smoothing_checkBox->isChecked(); 164 const bool use_area_smoothing = ui_widget.area_smoothing_checkBox->isChecked(); 165 const bool use_Delaunay_flips = ui_widget.flip_checkBox->isChecked(); 166 167 QApplication::setOverrideCursor(Qt::WaitCursor); 168 169 VCMap vcmap = get(Vertex_bool_property(), pmesh); 170 for(vertex_descriptor v : vertices(pmesh)) 171 put(vcmap, v, false); 172 173 if(constrain_border_vertices) 174 mark_border_vertices(vcmap, pmesh); 175 176 if(poly_item) 177 { 178 smooth_mesh(pmesh, parameters::do_project(projection) 179 .number_of_iterations(nb_iter) 180 .vertex_is_constrained_map(vcmap) 181 .use_safety_constraints(use_safety_measures) 182 .use_angle_smoothing(use_angle_smoothing) 183 .use_area_smoothing(use_area_smoothing) 184 .use_Delaunay_flips(use_Delaunay_flips)); 185 186 poly_item->invalidateOpenGLBuffers(); 187 poly_item->itemChanged(); 188 } 189 else if(selection_item) 190 { 191 mark_selected_vertices(vcmap, pmesh, selection_item); 192 193 // No faces selected --> use all faces 194 if(std::begin(selection_item->selected_facets) == std::end(selection_item->selected_facets)) 195 { 196 smooth_mesh(pmesh, parameters::do_project(projection) 197 .number_of_iterations(nb_iter) 198 .vertex_is_constrained_map(vcmap) 199 .edge_is_constrained_map(selection_item->constrained_edges_pmap()) 200 .use_safety_constraints(use_safety_measures) 201 .use_angle_smoothing(use_angle_smoothing) 202 .use_area_smoothing(use_area_smoothing) 203 .use_Delaunay_flips(use_Delaunay_flips)); 204 } 205 else // some faces exist in the selection 206 { 207 smooth_mesh(selection_item->selected_facets, pmesh, parameters::do_project(projection) 208 .number_of_iterations(nb_iter) 209 .vertex_is_constrained_map(vcmap) 210 .edge_is_constrained_map(selection_item->constrained_edges_pmap()) 211 .use_safety_constraints(use_safety_measures) 212 .use_angle_smoothing(use_angle_smoothing) 213 .use_area_smoothing(use_area_smoothing) 214 .use_Delaunay_flips(use_Delaunay_flips)); 215 } 216 217 selection_item->poly_item_changed(); 218 selection_item->changed_with_poly_item(); 219 } 220 221 QApplication::restoreOverrideCursor(); 222 } 223 on_shape_smoothing_clicked()224 void on_shape_smoothing_clicked() 225 { 226 const Scene_interface::Item_id index = scene->mainSelectionIndex(); 227 Scene_face_graph_item* poly_item = qobject_cast<Scene_face_graph_item*>(scene->item(index)); 228 Scene_polyhedron_selection_item* selection_item = qobject_cast<Scene_polyhedron_selection_item*>(scene->item(index)); 229 230 if(!poly_item && !selection_item) 231 return; 232 233 Face_graph& pmesh = (poly_item != nullptr) ? * poly_item->polyhedron() : * selection_item->polyhedron(); 234 235 const double time_step = ui_widget.time_step_spinBox->value(); 236 const unsigned int nb_iter = ui_widget.smooth_iter_spinBox->value(); 237 238 const bool constrain_border_vertices = ui_widget.border_button->isChecked() && !CGAL::is_closed(pmesh); 239 240 QApplication::setOverrideCursor(Qt::WaitCursor); 241 242 VCMap vcmap = get(Vertex_bool_property(), pmesh); 243 for(vertex_descriptor v : vertices(pmesh)) 244 put(vcmap, v, false); 245 246 if(constrain_border_vertices) 247 mark_border_vertices(vcmap, pmesh); 248 249 if(poly_item) 250 { 251 smooth_shape(pmesh, time_step, parameters::number_of_iterations(nb_iter) 252 .vertex_is_constrained_map(vcmap)); 253 254 poly_item->invalidateOpenGLBuffers(); 255 poly_item->itemChanged(); 256 } 257 else if(selection_item) 258 { 259 mark_selected_vertices(vcmap, pmesh, selection_item); 260 261 if(std::begin(selection_item->selected_facets) == std::end(selection_item->selected_facets)) 262 { 263 smooth_shape(pmesh, time_step, parameters::number_of_iterations(nb_iter) 264 .vertex_is_constrained_map(vcmap)); 265 } 266 else 267 { 268 smooth_shape(selection_item->selected_facets, pmesh, time_step, 269 parameters::number_of_iterations(nb_iter) 270 .vertex_is_constrained_map(vcmap)); 271 } 272 273 selection_item->poly_item_changed(); 274 selection_item->changed_with_poly_item(); 275 } 276 else 277 { 278 std::cerr << "Something's gone wrong.\n"; 279 CGAL_assertion(false); 280 } 281 282 QApplication::restoreOverrideCursor(); 283 } 284 285 private: 286 QAction* actionSmoothing_; 287 QDockWidget* dock_widget; 288 Ui::Smoothing ui_widget; 289 }; 290 291 #include "Smoothing_plugin.moc" 292