From 8f00809a84ca43389ac7da19d50c55b9c51d7b9a Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Thu, 30 Mar 2017 19:37:19 +0100 Subject: [PATCH] GUI for boolean operations :-) --- Fltk/contextWindow.cpp | 9 ++- Fltk/graphicWindow.cpp | 116 ++++++++++++++++++++++++++++++++++++- Geo/GeoStringInterface.cpp | 25 ++++++++ Geo/GeoStringInterface.h | 5 ++ 4 files changed, 152 insertions(+), 3 deletions(-) diff --git a/Fltk/contextWindow.cpp b/Fltk/contextWindow.cpp index 8221a2431c..1201ede871 100644 --- a/Fltk/contextWindow.cpp +++ b/Fltk/contextWindow.cpp @@ -419,6 +419,8 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize) } group[8]->end(); } + + /* FIXME: TODO // 9: Torus { group[9] = new Fl_Group @@ -437,6 +439,7 @@ elementaryContextWindow::elementaryContextWindow(int deltaFontSize) (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Wedge"); group[11]->end(); } + */ tab2->end(); } @@ -482,9 +485,11 @@ void elementaryContextWindow::updatePoint(double pt[3], int which) void elementaryContextWindow::show(int pane) { - if(pane < 0 || pane > 10) return; + // FIXME: TODO + + if(pane < 0 || pane > 8) return; - for(int i = 0; i < 11; i++) + for(int i = 0; i < 9; i++) group[i]->hide(); if(pane < 6){ diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp index c0c0caf6b3..b4eb683e2e 100644 --- a/Fltk/graphicWindow.cpp +++ b/Fltk/graphicWindow.cpp @@ -1580,6 +1580,110 @@ static void geometry_elementary_delete_cb(Fl_Widget *w, void *data) action_point_line_surface_volume(6, 0, (const char*)data); } +static void geometry_elementary_boolean_cb(Fl_Widget *w, void *data) +{ + if(!data) return; + std::string mode((const char*)data); + bool selectObject = true; + std::vector<GEntity*> object, tool; + + if(GModel::current()->getDim() == 3) + opt_geometry_volumes(0, GMSH_SET | GMSH_GUI, 1); + else if(GModel::current()->getDim() == 2) + opt_geometry_surfaces(0, GMSH_SET | GMSH_GUI, 1); + + while(1) { + if(object.empty()) + Msg::StatusGl("Select object\n" + "[Press 'e' to end selection or 'q' to abort]"); + else if(selectObject) + Msg::StatusGl("Select object\n" + "[Press 'e' to end selection, 'u' to undo last selection or " + "'q' to abort]"); + else if(tool.empty()) + Msg::StatusGl("Select tool\n" + "[Press 'e' to end selection or 'q' to abort]"); + else + Msg::StatusGl("Select tool\n" + "[Press 'e' to end selection, 'u' to undo last selection or " + "'q' to abort]"); + + char ib = FlGui::instance()->selectEntity(ENT_ALL); + if(ib == 'l') { + for(unsigned int i = 0; i < FlGui::instance()->selectedEdges.size(); i++){ + if(FlGui::instance()->selectedEdges[i]->getSelection() != 1){ + FlGui::instance()->selectedEdges[i]->setSelection(1); + if(selectObject) + object.push_back(FlGui::instance()->selectedEdges[i]); + else + tool.push_back(FlGui::instance()->selectedEdges[i]); + } + } + for(unsigned int i = 0; i < FlGui::instance()->selectedFaces.size(); i++){ + if(FlGui::instance()->selectedFaces[i]->getSelection() != 1){ + FlGui::instance()->selectedFaces[i]->setSelection(1); + if(selectObject) + object.push_back(FlGui::instance()->selectedFaces[i]); + else + tool.push_back(FlGui::instance()->selectedFaces[i]); + } + } + for(unsigned int i = 0; i < FlGui::instance()->selectedRegions.size(); i++){ + if(FlGui::instance()->selectedRegions[i]->getSelection() != 1){ + FlGui::instance()->selectedRegions[i]->setSelection(1); + if(selectObject) + object.push_back(FlGui::instance()->selectedRegions[i]); + else + tool.push_back(FlGui::instance()->selectedRegions[i]); + } + } + } + if(ib == 'r') { + for(unsigned int i = 0; i < FlGui::instance()->selectedEdges.size(); i++) + FlGui::instance()->selectedEdges[i]->setSelection(0); + for(unsigned int i = 0; i < FlGui::instance()->selectedFaces.size(); i++) + FlGui::instance()->selectedFaces[i]->setSelection(0); + for(unsigned int i = 0; i < FlGui::instance()->selectedRegions.size(); i++) + FlGui::instance()->selectedRegions[i]->setSelection(0); + } + if(ib == 'u') { + if(selectObject && object.size()){ + object[object.size() - 1]->setSelection(0); + object.pop_back(); + } + else if(tool.size()){ + tool[tool.size() - 1]->setSelection(0); + tool.pop_back(); + } + } + if(ib == 'e') { + if(selectObject){ + if(object.empty()) + Msg::Error("At least one object must be selected"); + else + selectObject = false; + } + else if(tool.empty()){ + Msg::Error("At least one tool must be selected"); + } + else{ + apply_boolean(GModel::current()->getFileName(), mode, object, tool); + GModel::current()->setSelection(0); + selectObject = true; + object.clear(); + tool.clear(); + } + } + if(ib == 'q') { + GModel::current()->setSelection(0); + break; + } + } + + drawContext::global()->draw(); + Msg::StatusGl(""); +} + static void geometry_elementary_split_cb(Fl_Widget *w, void *data) { if(!data) return; @@ -3792,12 +3896,14 @@ static menuItem static_modules[] = { (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"Cylinder"} , {"0Modules/Geometry/Elementary entities/Add/Block", (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"Block"} , + /* FIXME: TODO {"0Modules/Geometry/Elementary entities/Add/Torus", (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"Torus"} , {"0Modules/Geometry/Elementary entities/Add/Cone", (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"Cone"} , {"0Modules/Geometry/Elementary entities/Add/Wedge", - (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"Wedge"} , + (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"Wedge"} , + */ {"0Modules/Geometry/Elementary entities/Add/Volume", (Fl_Callback *)geometry_elementary_add_new_cb, (void*)"Volume"} , {"0Modules/Geometry/Elementary entities/Translate/Point", @@ -3876,6 +3982,14 @@ static menuItem static_modules[] = { (Fl_Callback *)geometry_elementary_add_symmetry_cb, (void*)"Surface"} , {"0Modules/Geometry/Elementary entities/Symmetry/Duplicate volume", (Fl_Callback *)geometry_elementary_add_symmetry_cb, (void*)"Volume"} , + {"0Modules/Geometry/Elementary entities/Boolean/Intersection", + (Fl_Callback *)geometry_elementary_boolean_cb, (void*)"BooleanIntersection"} , + {"0Modules/Geometry/Elementary entities/Boolean/Union", + (Fl_Callback *)geometry_elementary_boolean_cb, (void*)"BooleanUnion"} , + {"0Modules/Geometry/Elementary entities/Boolean/Difference", + (Fl_Callback *)geometry_elementary_boolean_cb, (void*)"BooleanDifference"} , + {"0Modules/Geometry/Elementary entities/Boolean/Fragments", + (Fl_Callback *)geometry_elementary_boolean_cb, (void*)"BooleanFragments"} , {"0Modules/Geometry/Elementary entities/Delete/Point", (Fl_Callback *)geometry_elementary_delete_cb, (void*)"Point"} , {"0Modules/Geometry/Elementary entities/Delete/Line", diff --git a/Geo/GeoStringInterface.cpp b/Geo/GeoStringInterface.cpp index 6de77b79c7..94410d0ff4 100644 --- a/Geo/GeoStringInterface.cpp +++ b/Geo/GeoStringInterface.cpp @@ -591,3 +591,28 @@ void split_edge(int edge_id, List_T *vertices, const std::string &fileName) sstream << "Split Line(" << edge_id << ") {" << list2string(vertices) << "};"; add_infile(sstream.str(), fileName, true); } + +void apply_boolean(const std::string &fileName, const std::string &op, + const std::vector<GEntity*> &object, + const std::vector<GEntity*> &tool) +{ + std::ostringstream sstream; + sstream << op << "{ "; + for(unsigned int i = 0; i < object.size(); i++){ + switch(object[i]->dim()){ + case 3: sstream << "Volume{" << object[i]->tag() << "}; "; break; + case 2: sstream << "Surface{" << object[i]->tag() << "}; "; break; + case 1: sstream << "Line{" << object[i]->tag() << "}; "; break; + } + } + sstream << "Delete; }{ "; + for(unsigned int i = 0; i < tool.size(); i++){ + switch(tool[i]->dim()){ + case 3: sstream << "Volume{" << tool[i]->tag() << "}; "; break; + case 2: sstream << "Surface{" << tool[i]->tag() << "}; "; break; + case 1: sstream << "Line{" << tool[i]->tag() << "}; "; break; + } + } + sstream << "Delete; }"; + add_infile(sstream.str(), fileName); +} diff --git a/Geo/GeoStringInterface.h b/Geo/GeoStringInterface.h index 7672b9eb12..eb177c8941 100644 --- a/Geo/GeoStringInterface.h +++ b/Geo/GeoStringInterface.h @@ -10,6 +10,8 @@ #include <vector> #include "ListUtils.h" +class GEntity; + void coherence(const std::string &fileName); void delet(List_T *list, const std::string &fileName, const std::string &what); void add_infile(const std::string &text, const std::string &fileName, @@ -90,5 +92,8 @@ void protude(List_T *list, const std::string &fileName, const std::string &what, const std::string &px, const std::string &py, const std::string &pz, const std::string &angle); void split_edge(int edge_id, List_T *vertices, const std::string &fileName); +void apply_boolean(const std::string &fileName, const std::string &op, + const std::vector<GEntity*> &object, + const std::vector<GEntity*> &tool); #endif -- GitLab