From 61366f3b102ed39f651297aac06d3bf2c0ca7f15 Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Sat, 1 Apr 2017 09:00:15 +0100 Subject: [PATCH] GUI for Fillet + Fillet now deletes the original shape --- Fltk/contextWindow.cpp | 19 ++++++-- Fltk/graphicWindow.cpp | 93 ++++++++++++++++++++++++++++++++++++-- Geo/GModelIO_OCC.cpp | 26 ++++++----- Geo/GModelIO_OCC.h | 3 +- Geo/GeoStringInterface.cpp | 9 ++++ Geo/GeoStringInterface.h | 2 + Parser/Gmsh.tab.cpp | 4 +- Parser/Gmsh.y | 2 +- demos/boolean/fillet.geo | 6 --- demos/boolean/fillet2.geo | 2 - demos/boolean/fillet3.geo | 2 - 11 files changed, 135 insertions(+), 33 deletions(-) diff --git a/Fltk/contextWindow.cpp b/Fltk/contextWindow.cpp index bebdccf86e..3155cb726b 100644 --- a/Fltk/contextWindow.cpp +++ b/Fltk/contextWindow.cpp @@ -663,7 +663,7 @@ transformContextWindow::transformContextWindow(int deltaFontSize) { FL_NORMAL_SIZE -= deltaFontSize; - int width = 31 * FL_NORMAL_SIZE; + int width = 34 * FL_NORMAL_SIZE; int height = 5 * WB + 10 * BH; win = new paletteWindow(width, height, CTX::instance()->nonModalWindows ? true : false, @@ -776,13 +776,22 @@ transformContextWindow::transformContextWindow(int deltaFontSize) butt[5]->value(1); group[4]->end(); } - // 5: Delete + // 5: Fillet { group[5] = new Fl_Group + (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Fillet"); + input[18] = new Fl_Input(2 * WB, 2 * WB + 1 * BH, IW, BH, "Radius"); + input[18]->value("0.1"); + input[18]->align(FL_ALIGN_RIGHT); + group[5]->end(); + } + // 6: Delete + { + group[6] = new Fl_Group (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Delete"); butt[6] = new Fl_Check_Button(2 * WB, 2 * WB + 1 * BH, IW, BH, "Recursive"); butt[6]->value(1); - group[5]->end(); + group[6]->end(); } o->end(); } @@ -800,8 +809,8 @@ transformContextWindow::transformContextWindow(int deltaFontSize) void transformContextWindow::show(int pane, bool extrude) { - if(pane < 0 || pane > 5) return; - for(int i = 0; i < 6; i++) + if(pane < 0 || pane > 6) return; + for(int i = 0; i < 7; i++) group[i]->hide(); for(int i = 0; i < 4; i++){ if(extrude) butt[i]->deactivate(); diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp index 71e3295f03..b19b394f1f 100644 --- a/Fltk/graphicWindow.cpp +++ b/Fltk/graphicWindow.cpp @@ -1536,7 +1536,7 @@ static void geometry_elementary_extrude_rotate_cb(Fl_Widget *w, void *data) static void geometry_elementary_delete_cb(Fl_Widget *w, void *data) { - FlGui::instance()->transformContext->show(5); + FlGui::instance()->transformContext->show(6); action_point_line_surface_volume(6); } @@ -1653,6 +1653,91 @@ static void geometry_elementary_boolean_cb(Fl_Widget *w, void *data) Msg::StatusGl(""); } +static void geometry_elementary_fillet_cb(Fl_Widget *w, void *data) +{ + opt_geometry_volumes(0, GMSH_SET | GMSH_GUI, 1); + opt_geometry_lines(0, GMSH_SET | GMSH_GUI, 1); + + FlGui::instance()->transformContext->show(5); + + bool selectRegions = true; + std::vector<int> regions, edges; + + while(1) { + if(regions.empty()) + Msg::StatusGl("Select volume\n" + "[Press 'e' to end selection or 'q' to abort]"); + else if(selectRegions) + Msg::StatusGl("Select volume\n" + "[Press 'e' to end selection, 'u' to undo last selection or " + "'q' to abort]"); + else if(edges.empty()) + Msg::StatusGl("Select line\n" + "[Press 'e' to end selection or 'q' to abort]"); + else + Msg::StatusGl("Select line\n" + "[Press 'e' to end selection, 'u' to undo last selection or " + "'q' to abort]"); + + char ib = FlGui::instance()->selectEntity(selectRegions ? ENT_VOLUME : ENT_LINE); + 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); + edges.push_back(FlGui::instance()->selectedEdges[i]->tag()); + } + } + for(unsigned int i = 0; i < FlGui::instance()->selectedRegions.size(); i++){ + if(FlGui::instance()->selectedRegions[i]->getSelection() != 1){ + FlGui::instance()->selectedRegions[i]->setSelection(1); + regions.push_back(FlGui::instance()->selectedRegions[i]->tag()); + } + } + } + if(ib == 'r') { + Msg::Warning("Entity de-selection not supported yet during boolean operation"); + } + if(ib == 'u') { + if(selectRegions && regions.size()){ + GRegion *ge = GModel::current()->getRegionByTag(regions.back()); + if(ge) ge->setSelection(0); + regions.pop_back(); + } + else if(edges.size()){ + GEdge *ge = GModel::current()->getEdgeByTag(edges.back()); + if(ge) ge->setSelection(0); + edges.pop_back(); + } + } + if(ib == 'e') { + if(selectRegions){ + if(regions.empty()) + Msg::Error("At least one volume must be selected"); + else + selectRegions = false; + } + else if(edges.empty()){ + Msg::Error("At least one line must be selected"); + } + else{ + apply_fillet(GModel::current()->getFileName(), regions, edges, + FlGui::instance()->transformContext->input[18]->value()); + GModel::current()->setSelection(0); + selectRegions = true; + regions.clear(); + edges.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; @@ -3921,8 +4006,6 @@ static menuItem static_modules[] = { (Fl_Callback *)geometry_elementary_scale_cb} , {"0Modules/Geometry/Elementary entities/Transform/Symmetry", (Fl_Callback *)geometry_elementary_symmetry_cb} , - {"0Modules/Geometry/Elementary entities/Transform/Split line", - (Fl_Callback *)geometry_elementary_split_cb,(void*)"Line"}, {"0Modules/Geometry/Elementary entities/Extrude/Translate", (Fl_Callback *)geometry_elementary_extrude_translate_cb} , {"0Modules/Geometry/Elementary entities/Extrude/Rotate", @@ -3935,6 +4018,10 @@ static menuItem static_modules[] = { (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/Fillet", + (Fl_Callback *)geometry_elementary_fillet_cb}, + {"0Modules/Geometry/Elementary entities/Split line", + (Fl_Callback *)geometry_elementary_split_cb, (void*)"Line"}, {"0Modules/Geometry/Elementary entities/Delete", (Fl_Callback *)geometry_elementary_delete_cb} , {"0Modules/Geometry/Elementary entities/Coherence", diff --git a/Geo/GModelIO_OCC.cpp b/Geo/GModelIO_OCC.cpp index 4b8bdd2739..208928cf31 100644 --- a/Geo/GModelIO_OCC.cpp +++ b/Geo/GModelIO_OCC.cpp @@ -1711,8 +1711,18 @@ bool OCC_Internals::addPipe(const std::vector<std::pair<int, int> > &inDimTags, bool OCC_Internals::fillet(const std::vector<int> ®ionTags, const std::vector<int> &edgeTags, double radius, - std::vector<std::pair<int, int> > &outDimTags) + std::vector<std::pair<int, int> > &outDimTags, + bool removeRegion) { + std::vector<TopoDS_Edge> edges; + for(unsigned int i = 0; i < edgeTags.size(); i++){ + if(!_tagEdge.IsBound(edgeTags[i])){ + Msg::Error("Unknown OpenCASCADE edge with tag %d", edgeTags[i]); + return false; + } + edges.push_back(TopoDS::Edge(_tagEdge.Find(edgeTags[i]))); + } + // build a single compound shape BRep_Builder b; TopoDS_Compound c; @@ -1724,21 +1734,15 @@ bool OCC_Internals::fillet(const std::vector<int> ®ionTags, } TopoDS_Shape shape = find(3, regionTags[i]); b.Add(c, shape); + if(removeRegion) unbind(shape, 3, regionTags[i], true); // recursive } TopoDS_Shape result; try{ BRepFilletAPI_MakeFillet f(c); - for(unsigned int i = 0; i < edgeTags.size(); i++){ - if(!_tagEdge.IsBound(edgeTags[i])){ - Msg::Error("Unknown OpenCASCADE edge with tag %d", edgeTags[i]); - return false; - } - TopoDS_Edge edge = TopoDS::Edge(_tagEdge.Find(edgeTags[i])); - f.Add(edge); - } - for(int i = 1; i <= f.NbContours(); i++){ + for(unsigned int i = 0; i < edges.size(); i++) + f.Add(edges[i]); + for(int i = 1; i <= f.NbContours(); i++) f.SetRadius(radius, i, 1); - } f.Build(); if(!f.IsDone()) { Msg::Error("Could not compute fillet"); diff --git a/Geo/GModelIO_OCC.h b/Geo/GModelIO_OCC.h index cdc425420c..8868ff2ed9 100644 --- a/Geo/GModelIO_OCC.h +++ b/Geo/GModelIO_OCC.h @@ -206,7 +206,8 @@ class OCC_Internals { // fillet bool fillet(const std::vector<int> ®ionTags, const std::vector<int> &edgeTags, - double radius, std::vector<std::pair<int, int> > &ouDimTags); + double radius, std::vector<std::pair<int, int> > &ouDimTags, + bool removeRegion); // apply boolean operator bool applyBooleanOperator(int tag, BooleanOperator op, diff --git a/Geo/GeoStringInterface.cpp b/Geo/GeoStringInterface.cpp index 1323e1aab5..5cb64f8ae4 100644 --- a/Geo/GeoStringInterface.cpp +++ b/Geo/GeoStringInterface.cpp @@ -669,6 +669,15 @@ void apply_boolean(const std::string &fileName, const std::string &op, add_infile(sstream.str(), fileName); } +void apply_fillet(const std::string &fileName, const std::vector<int> ®ions, + const std::vector<int> &edges, const std::string &radius) +{ + std::ostringstream sstream; + sstream << "Fillet{" << vector2String(regions) << "}{" + << vector2String(edges) << "}{" << radius << "}"; + add_infile(sstream.str(), fileName); +} + void coherence(const std::string &fileName) { add_infile("Coherence;", fileName); diff --git a/Geo/GeoStringInterface.h b/Geo/GeoStringInterface.h index 9e41ceda06..a66a8a2734 100644 --- a/Geo/GeoStringInterface.h +++ b/Geo/GeoStringInterface.h @@ -101,6 +101,8 @@ void apply_boolean(const std::string &fileName, const std::string &op, const std::vector<std::pair<int, int> > &object, const std::vector<std::pair<int, int> > &tool, int deleteObject, int deleteTool); +void apply_fillet(const std::string &fileName, const std::vector<int> ®ions, + const std::vector<int> &edges, const std::string &radius); void coherence(const std::string &fileName); void delete_entities(const std::string &fileName, const std::vector<std::pair<int, int> > &l, diff --git a/Parser/Gmsh.tab.cpp b/Parser/Gmsh.tab.cpp index 7fd4b2379e..ea3f6e91fc 100644 --- a/Parser/Gmsh.tab.cpp +++ b/Parser/Gmsh.tab.cpp @@ -10652,7 +10652,7 @@ yyreduce: ListOfDouble2Vector((yyvsp[(3) - (10)].l), regions); ListOfDouble2Vector((yyvsp[(6) - (10)].l), edges); std::vector<std::pair<int, int> > outDimTags; r = GModel::current()->getOCCInternals()->fillet - (regions, edges, radius, outDimTags); + (regions, edges, radius, outDimTags, true); VectorOfPairs2ListOfShapes(outDimTags, (yyval.l)); } else{ @@ -14742,7 +14742,7 @@ int NEWPHYSICAL() if(CTX::instance()->geom.oldNewreg) return NEWREG(); else - return (GModel::current()->getGEOInternals()->getMaxPhysicalTag() + 1); + return GModel::current()->getGEOInternals()->getMaxPhysicalTag() + 1; } diff --git a/Parser/Gmsh.y b/Parser/Gmsh.y index 15ebb184fc..20fedd2ddb 100644 --- a/Parser/Gmsh.y +++ b/Parser/Gmsh.y @@ -3834,7 +3834,7 @@ Extrude : ListOfDouble2Vector($3, regions); ListOfDouble2Vector($6, edges); std::vector<std::pair<int, int> > outDimTags; r = GModel::current()->getOCCInternals()->fillet - (regions, edges, radius, outDimTags); + (regions, edges, radius, outDimTags, true); VectorOfPairs2ListOfShapes(outDimTags, $$); } else{ diff --git a/demos/boolean/fillet.geo b/demos/boolean/fillet.geo index 9daa1a956c..c2eed50f22 100644 --- a/demos/boolean/fillet.geo +++ b/demos/boolean/fillet.geo @@ -8,9 +8,3 @@ f() = Abs(Boundary{ Volume{1}; }); e() = Unique(Abs(Boundary{ Surface{f()}; })); Fillet{1}{e()}{0.2} - -tmp2() = Fillet{1}{1,2,4}{0.05}; - -Translate{2,0,0} { Volume{tmp2(0)}; } - -Recursive Delete{ Volume{1}; } diff --git a/demos/boolean/fillet2.geo b/demos/boolean/fillet2.geo index 51c4fe22ce..22701a34b0 100644 --- a/demos/boolean/fillet2.geo +++ b/demos/boolean/fillet2.geo @@ -9,5 +9,3 @@ f() = Abs(Boundary{ Volume{a()}; }); e() = Unique(Abs(Boundary{ Surface{f()}; })); Fillet{a()}{e()}{1} - -Recursive Delete{ Volume{a()}; } diff --git a/demos/boolean/fillet3.geo b/demos/boolean/fillet3.geo index d83202da2f..46d7fadecf 100644 --- a/demos/boolean/fillet3.geo +++ b/demos/boolean/fillet3.geo @@ -14,7 +14,6 @@ v_ = v_out; f_[] = Abs(Boundary{ Volume{v_}; }); e_[] = Unique( Abs(Boundary{ Surface{f_[]}; }) ); v_out = Fillet{v_}{e_[2-1], e_[4-1], e_[6-1], e_[8-1]}{r_out}; -Recursive Delete{ Volume{v_}; } v_in = newv; Block(v_in) = { @@ -25,6 +24,5 @@ v_ = v_in; f_[] = Abs(Boundary{ Volume{v_}; }); e_[] = Unique( Abs(Boundary{ Surface{f_[]}; }) ); v_in = Fillet{v_}{e_[2-1], e_[4-1], e_[6-1], e_[8-1]}{r_in}; -Recursive Delete{ Volume{v_}; } BooleanDifference { Volume{v_out}; Delete; }{ Volume{v_in}; Delete; } -- GitLab