diff --git a/Fltk/classificationEditor.cpp b/Fltk/classificationEditor.cpp index 6e1c480d82117996e5f8b04199923b5ce207d1dc..4e130fd34acd8afc8e2f7b08fd6991c70a3c65d4 100644 --- a/Fltk/classificationEditor.cpp +++ b/Fltk/classificationEditor.cpp @@ -4,7 +4,7 @@ // bugs and problems to <gmsh@geuz.org>. #include <FL/Fl_Tabs.H> -#include <FL/Fl_Value_Input.H> +#include <FL/Fl_Box.H> #include "FlGui.h" #include "classificationEditor.h" #include "paletteWindow.h" @@ -19,184 +19,43 @@ #include "discreteEdge.h" #include "discreteFace.h" -static void NoElementsSelectedMode(classificationEditor *e) -{ - e->_buttons[CLASSBUTTON_DEL]->deactivate(); - e->_buttons[CLASSBUTTON_ADD]->deactivate(); - e->_buttons[CLASSBUTTON_CLEAR]->deactivate(); - // e->_buttons[CLASSBUTTON_OK]->deactivate(); - e->_togbuttons[CLASSTOGBUTTON_CLOS]->deactivate(); - e->_inputs[CLASSVALUE_ANGLE]->deactivate(); - - e->_buttons[CLASSBUTTON_SELECT]->activate(); - e->_togbuttons[CLASSTOGBUTTON_HIDE]->activate(); -} - -static void ElementsSelectedMode(classificationEditor *e) -{ - e->_buttons[CLASSBUTTON_DEL]->activate(); - e->_buttons[CLASSBUTTON_ADD]->activate(); - e->_buttons[CLASSBUTTON_CLEAR]->activate(); - e->_togbuttons[CLASSTOGBUTTON_CLOS]->activate(); - e->_inputs[CLASSVALUE_ANGLE]->activate(); - // e->_buttons[CLASSBUTTON_OK]->activate(); - - e->_buttons[CLASSBUTTON_SELECT]->deactivate(); - e->_togbuttons[CLASSTOGBUTTON_HIDE]->deactivate(); -} - -// we should -static void class_selectgface_cb(Fl_Widget *w, void *data) -{ - classificationEditor *e = (classificationEditor*)data; - std::vector<GFace*> temp; - - opt_geometry_surfaces(0, GMSH_SET | GMSH_GUI, 1); - - while(1) { - CTX::instance()->mesh.changed = ENT_ALL; - drawContext::global()->draw(); - - Msg::StatusBar(3, false, "Select Model Face\n" - "[Press 'e' to end selection or 'q' to abort]"); - - char ib = FlGui::instance()->selectEntity(ENT_SURFACE); - if(ib == 'l') { - for(unsigned int i = 0; i < FlGui::instance()->selectedFaces.size(); i++){ - FlGui::instance()->selectedFaces[i]->setSelection(1); - temp.push_back(FlGui::instance()->selectedFaces[i]); - } - } - // ok store the list of gfaces ! - if(ib == 'e') { - GModel::current()->setSelection(0); - for(unsigned int i = 0; i < temp.size(); i++){ - e->_faces.insert(temp[i]); - } - break; - } - // do nothing - if(ib == 'q') { - GModel::current()->setSelection(0); - break; - } - } - CTX::instance()->mesh.changed = ENT_ALL; - drawContext::global()->draw(); - Msg::StatusBar(3, false, ""); -} - -static void class_deleteedge_cb(Fl_Widget *w, void *data) +edge_angle::edge_angle(MVertex *_v1, MVertex *_v2, MElement *t1, MElement *t2) + : v1(_v1), v2(_v2) { - classificationEditor *e = (classificationEditor*)data; - std::vector<MLine*> ele; - - CTX::instance()->pickElements = 1; - - while(1) { - CTX::instance()->mesh.changed = ENT_ALL; - drawContext::global()->draw(); - - Msg::StatusBar(3, false, "Select Elements\n" - "[Press 'e' to end selection or 'q' to abort]"); - - char ib = FlGui::instance()->selectEntity(ENT_ALL); - if(ib == 'l') { - if(CTX::instance()->pickElements){ - for(unsigned int i = 0; i < FlGui::instance()->selectedElements.size(); i++){ - MElement *me = FlGui::instance()->selectedElements[i]; - if(me->getType() == TYPE_LIN && me->getVisibility() != 2){ - me->setVisibility(2); ele.push_back((MLine*)me); - } - } - } - } - if(ib == 'r') { - for(unsigned int i = 0; i < FlGui::instance()->selectedElements.size(); i++) - FlGui::instance()->selectedElements[i]->setVisibility(1); - } - // ok, we compute edges ! - if(ib == 'e') { - GModel::current()->setSelection(0); - break; - } - // do nothing - if(ib == 'q') { - GModel::current()->setSelection(0); - ele.clear(); - break; + if(!t2) angle = 0; + else{ + double c1[3]; + double c2[3]; + double c3[3]; + { + MVertex *p1 = t1->getVertex(0); + MVertex *p2 = t1->getVertex(1); + MVertex *p3 = t1->getVertex(2); + double a[3] = {p1->x() - p2->x(), p1->y() - p2->y(), p1->z() - p2->z()}; + double b[3] = {p1->x() - p3->x(), p1->y() - p3->y(), p1->z() - p3->z()}; + c1[2] = a[0] * b[1] - a[1] * b[0]; + c1[1] = -a[0] * b[2] + a[2] * b[0]; + c1[0] = a[1] * b[2] - a[2] * b[1]; } - } - - std::sort(ele.begin(),ele.end()); - // look in all temporary edges if a deleted one is present and delete it ! - std::vector<MLine*> temp = e->temporary->lines; - e->temporary->lines.clear(); - - for(unsigned int i = 0; i < temp.size(); i++){ - std::vector<MLine*>::iterator it = std::find(ele.begin(), ele.end(), temp[i]); - if(it != ele.end()){ - delete temp[i]; + { + MVertex *p1 = t2->getVertex(0); + MVertex *p2 = t2->getVertex(1); + MVertex *p3 = t2->getVertex(2); + double a[3] = {p1->x() - p2->x(), p1->y() - p2->y(), p1->z() - p2->z()}; + double b[3] = {p1->x() - p3->x(), p1->y() - p3->y(), p1->z() - p3->z()}; + c2[2] = a[0] * b[1] - a[1] * b[0]; + c2[1] = -a[0] * b[2] + a[2] * b[0]; + c2[0] = a[1] * b[2] - a[2] * b[1]; } - else e->temporary->lines.push_back(temp[i]); - } - - CTX::instance()->mesh.changed = ENT_ALL; - CTX::instance()->pickElements = 0; - drawContext::global()->draw(); - Msg::StatusBar(3, false, ""); -} - -static void class_save_cb(Fl_Widget *w, void *data) -{ - classificationEditor *e = (classificationEditor*)data; - - e->saved->lines.insert(e->saved->lines.end(), e->temporary->lines.begin(), - e->temporary->lines.end()); - e->temporary->lines.clear(); - e->_elements.clear(); - e->edges_detected.clear(); - - CTX::instance()->mesh.changed = ENT_ALL; - CTX::instance()->pickElements = 0; - NoElementsSelectedMode(e); - drawContext::global()->draw(); - Msg::StatusBar(3, false, ""); -} - -static void class_clear_cb(Fl_Widget *w, void *data) -{ - classificationEditor *e = (classificationEditor*)data; - - for(unsigned int i = 0; i < e->temporary->lines.size(); i++){ - delete e->temporary->lines[i]; + norme(c1); + norme(c2); + prodve(c1, c2, c3); + double cosa; prosca(c1, c2, &cosa); + double sina = norme(c3); + angle = atan2(sina, cosa); } - e->temporary->lines.clear(); - - CTX::instance()->mesh.changed = ENT_ALL; - CTX::instance()->pickElements = 0; - NoElementsSelectedMode(e); - drawContext::global()->draw(); - Msg::StatusBar(3, false, ""); } -static void class_ok_cb(Fl_Widget *w, void *data) -{ - classificationEditor *e = (classificationEditor*)data; - e->edge_detec->deactivate(); - e->edge_detec->hide(); - e->face_color->activate(); - e->face_color->show(); - class_save_cb(w,data); - opt_mesh_lines(0, GMSH_SET | GMSH_GUI, e->op[0]); - opt_mesh_surfaces_edges(0, GMSH_SET | GMSH_GUI, e->op[1]); - opt_mesh_surfaces_faces(0, GMSH_SET | GMSH_GUI, e->op[2]); - opt_mesh_line_width(0, GMSH_SET | GMSH_GUI, e->op[3]); - - Msg::StatusBar(3, false, ""); -} - - struct compareMLinePtr { bool operator () (MLine *l1, MLine *l2) const @@ -206,6 +65,23 @@ struct compareMLinePtr } }; +static void buildListOfEdgeAngle(e2t_cont adj, std::vector<edge_angle> &edges_detected, + std::vector<edge_angle> &edges_lonly) +{ + e2t_cont::iterator it = adj.begin(); + for(; it != adj.end(); ++it){ + if(it->second.second) + edges_detected.push_back(edge_angle(it->first.getVertex(0), + it->first.getVertex(1), + it->second.first, it->second.second)); + else + edges_lonly.push_back(edge_angle(it->first.getVertex(0), + it->first.getVertex(1), + it->second.first, it->second.second)); + } + std::sort(edges_detected.begin(), edges_detected.end()); +} + static void recurClassify(MTri3 *t, GFace *gf, std::map<MLine*, GEdge*, compareMLinePtr> &lines, std::map<MTriangle*, GFace*> &reverse) @@ -232,20 +108,19 @@ static GEdge *getNewModelEdge(GFace *gf1, GFace *gf2, { int t1 = gf1 ? gf1->tag() : -1; int t2 = gf2 ? gf2->tag() : -1; - int i1 = std::min(t1,t2); - int i2 = std::max(t1,t2); + int i1 = std::min(t1, t2); + int i2 = std::max(t1, t2); if(i1 == i2) return 0; std::map<std::pair<int, int>, GEdge*>::iterator it = newEdges.find(std::make_pair<int, int>(i1, i2)); if(it == newEdges.end()){ - discreteEdge *temporary = new discreteEdge + discreteEdge *ge = new discreteEdge (GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0); - //printf("add new edge gf1=%d gf2=%d \n", t1, t2); - GModel::current()->add(temporary); - newEdges[std::make_pair<int, int>(i1, i2)] = temporary; - return temporary; + GModel::current()->add(ge); + newEdges[std::make_pair<int, int>(i1, i2)] = ge; + return ge; } else return it->second; @@ -258,7 +133,6 @@ static void recurClassifyEdges(MTri3 *t, std::map<std::pair<int, int>, GEdge*> &newEdges) { if(!t->isDeleted()){ - t->setDeleted(true); GFace *gf1 = reverse[t->tri()]; for(int i = 0; i < 3; i++){ @@ -279,179 +153,62 @@ static void recurClassifyEdges(MTri3 *t, if(tn) recurClassifyEdges(tn, reverse, lines, touched, newEdges); } - } } -static void class_color_cb(Fl_Widget* w, void* data) +static void NoElementsSelectedMode(classificationEditor *e) { - classificationEditor *e = (classificationEditor*)data; - std::map<MLine*, GEdge*, compareMLinePtr> lines; - { - GModel::eiter it = GModel::current()->firstEdge(); - GModel::eiter ite = GModel::current()->lastEdge(); - for( ; it != ite; ++it){ - for(unsigned int i = 0; i < (*it)->lines.size();i++) - lines[(*it)->lines[i]] = *it; - } - } - - std::list<MTri3*> tris; - { - std::set<GFace*>::iterator it = e->_faces.begin(); - while(it != e->_faces.end()){ - GFace *gf = *it; - for(unsigned int i = 0; i < gf->triangles.size(); i++){ - tris.push_back(new MTri3(gf->triangles[i], 0)); - } - gf->triangles.clear(); - ++it; - } - } + e->buttons[CLASS_BUTTON_SELECT_ELEMENTS]->activate(); + e->buttons[CLASS_BUTTON_SELECT_ALL_ELEMENTS]->activate(); - if ( !tris.size() )return; - - - connectTriangles(tris); - - { - std::map<MTriangle*,GFace*> reverse; - - // color all triangles - std::list<MTri3*> ::iterator it = tris.begin(); - while(it != tris.end()){ - if(!(*it)->isDeleted()){ - discreteFace *temporary = new discreteFace - (GModel::current(), GModel::current()->maxFaceNum() + 1); - recurClassify(*it, temporary, lines, reverse); - GModel::current()->add(temporary); - } - ++it; - } - - // color some lines - it = tris.begin(); - while(it != tris.end()){ - (*it)->setDeleted(false); - ++it; - } - - it = tris.begin(); - - //classify edges that are bound by different GFaces - //-------------------------------------------------- - std::map<std::pair<int, int>, GEdge*> newEdges; - std::set<MLine*> touched; - recurClassifyEdges(*it, reverse, lines, touched, newEdges); - GModel::current()->remove(e->saved); - - //check if new edges should not be splitted - //splitted if composed of several open or closed edges - //----------------------------------------------------- - for (std::map<std::pair<int, int>, GEdge*>::iterator it = newEdges.begin() ; it != newEdges.end() ; ++it){ - - GEdge *ge = it->second; - //printf("NEW edge with tag = %d \n", ge->tag()); - - std::list<MLine*> segments; - for (unsigned int i = 0; i < ge->lines.size(); i++){ - segments.push_back(ge->lines[i]); - } + e->buttons[CLASS_BUTTON_DELETE_FROM_SELECTION]->deactivate(); + e->buttons[CLASS_BUTTON_RESET_SELECTION]->deactivate(); + e->toggles[CLASS_TOGGLE_BOUNDARY]->deactivate(); + e->inputs[CLASS_VALUE_ANGLE]->deactivate(); + e->buttons[CLASS_BUTTON_CLASSIFY]->deactivate(); - //for each actual GEdge - while (!segments.empty()) { - std::vector<MLine*> myLines; - std::list<MLine*>::iterator it = segments.begin(); - MVertex *vB = (*it)->getVertex(0); - MVertex *vE = (*it)->getVertex(1); - myLines.push_back(*it); - segments.erase(it); - it++; - //printf("***candidate mline %d %d of size %d \n", vB->getNum(), vE->getNum(), segments.size()); - - for (int i=0; i<2; i++) { - for (std::list<MLine*>::iterator it = segments.begin() ; it != segments.end(); ++it){ - MVertex *v1 = (*it)->getVertex(0); - MVertex *v2 = (*it)->getVertex(1); - //printf("mline %d %d \n", v1->getNum(), v2->getNum()); - std::list<MLine*>::iterator itp; - if ( v1 == vE ){ - //printf("->push back this mline \n"); - myLines.push_back(*it); - itp = it; - it++; - segments.erase(itp); - vE = v2; - i = -1; - } - else if ( v2 == vE){ - //printf("->push back this mline \n"); - myLines.push_back(*it); - itp = it; - it++; - segments.erase(itp); - vE = v1; - i=-1; - } - if (it == segments.end()) break; - } - if (vB == vE) break; - if (segments.empty()) break; - //printf("not found VB=%d vE=%d\n", vB->getNum(), vE->getNum()); - MVertex *temp = vB; - vB = vE; - vE = temp; - //printf("not found VB=%d vE=%d\n", vB->getNum(), vE->getNum()); - } - GEdge *newGe = new discreteEdge - (GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0); - newGe->lines.insert(newGe->lines.end(), myLines.begin(), myLines.end()); - GModel::current()->add(newGe); - }//end for each actual GEdge - } - //printf("end new edge with tag \n"); - - for (std::map<std::pair<int, int>, GEdge*>::iterator it = newEdges.begin(); - it != newEdges.end(); ++it){ - GEdge *ge = it->second; - GModel::current()->remove(ge); - } - - while(it != tris.end()){ - delete *it; - ++it; - } - } - CTX::instance()->mesh.changed = ENT_ALL; + CTX::instance()->pickElements = 0; drawContext::global()->draw(); Msg::StatusBar(3, false, ""); } -static void updateedges_cb(Fl_Widget* w, void* data) +static void ElementsSelectedMode(classificationEditor *e) +{ + e->buttons[CLASS_BUTTON_DELETE_FROM_SELECTION]->activate(); + e->buttons[CLASS_BUTTON_RESET_SELECTION]->activate(); + e->toggles[CLASS_TOGGLE_BOUNDARY]->activate(); + e->inputs[CLASS_VALUE_ANGLE]->activate(); + + e->buttons[CLASS_BUTTON_SELECT_ELEMENTS]->deactivate(); + e->buttons[CLASS_BUTTON_SELECT_ALL_ELEMENTS]->deactivate(); +} + +static void update_edges_cb(Fl_Widget *w, void *data) { classificationEditor *e = (classificationEditor*)data; + if(!e->selected) return; + printf("%d inside edges detected\n", (int)e->edges_detected.size()); - for(unsigned int i = 0; i < e->temporary->lines.size(); i++){ - delete e->temporary->lines[i]; - } - e->temporary->lines.clear(); + for(unsigned int i = 0; i < e->selected->lines.size(); i++) + delete e->selected->lines[i]; + e->selected->lines.clear(); for(unsigned int i = 0; i < e->edges_detected.size(); i++){ edge_angle ea = e->edges_detected[i]; // printf("angle = %g\n",ea.angle); - if(ea.angle <= e->_inputs[CLASSVALUE_ANGLE]->value() / 180 * M_PI) + if(ea.angle <= e->inputs[CLASS_VALUE_ANGLE]->value() / 180 * M_PI) break; - e->temporary->lines.push_back(new MLine(ea.v1, ea.v2)); + e->selected->lines.push_back(new MLine(ea.v1, ea.v2)); } printf("%d boundary edges detected\n", (int)e->edges_lonly.size()); - if(e->_togbuttons[CLASSTOGBUTTON_CLOS]->value()){ + if(e->toggles[CLASS_TOGGLE_BOUNDARY]->value()){ for(unsigned int i = 0 ; i < e->edges_lonly.size(); i++){ edge_angle ea = e->edges_lonly[i]; - e->temporary->lines.push_back(new MLine(ea.v1, ea.v2)); + e->selected->lines.push_back(new MLine(ea.v1, ea.v2)); //check if closed loop } } @@ -460,6 +217,91 @@ static void updateedges_cb(Fl_Widget* w, void* data) drawContext::global()->draw(); } +static void class_select_elements_cb(Fl_Widget *w, void *data) +{ + classificationEditor *e = (classificationEditor*)data; + std::vector<MTriangle*> &ele(e->elements); + + // allocate discrete edge to hold the selected mesh segments + if(!e->selected){ + e->selected = new discreteEdge + (GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0); + GModel::current()->add(e->selected); + } + + CTX::instance()->pickElements = 1; + + while(1) { + CTX::instance()->mesh.changed = ENT_ALL; + drawContext::global()->draw(); + + Msg::StatusBar(3, false, "Select elements\n" + "[Press 'e' to end selection or 'q' to abort]"); + + char ib = FlGui::instance()->selectEntity(ENT_ALL); + if(ib == 'l') { + for(unsigned int i = 0; i < FlGui::instance()->selectedElements.size(); i++){ + MElement *me = FlGui::instance()->selectedElements[i]; + if(me->getType() == TYPE_TRI && me->getVisibility() != 2){ + me->setVisibility(2); ele.push_back((MTriangle*)me); + } + } + } + if(ib == 'r') { + for(unsigned int i = 0; i < FlGui::instance()->selectedElements.size(); i++) + FlGui::instance()->selectedElements[i]->setVisibility(1); + } + if(ib == 'e') { // ok, compute the edges + GModel::current()->setSelection(0); + e2t_cont adj; + buildEdgeToTriangle(ele, adj); + buildListOfEdgeAngle(adj, e->edges_detected, e->edges_lonly); + ElementsSelectedMode(e); + break; + } + if(ib == 'q') { // do nothing + GModel::current()->setSelection(0); + ele.clear(); + break; + } + } + + update_edges_cb(0, data); + + CTX::instance()->mesh.changed = ENT_ALL; + CTX::instance()->pickElements = 0; + drawContext::global()->draw(); + Msg::StatusBar(3, false, ""); +} + +static void class_select_all_elements_cb(Fl_Widget *w, void *data) +{ + classificationEditor *e = (classificationEditor*)data; + + // allocate discrete edge to hold the selected mesh segments + if(!e->selected){ + e->selected = new discreteEdge + (GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0); + GModel::current()->add(e->selected); + } + + for(GModel::fiter it = GModel::current()->firstFace(); + it != GModel::current()->lastFace(); ++it) + e->elements.insert(e->elements.end(), (*it)->triangles.begin(), + (*it)->triangles.end()); + + e2t_cont adj; + buildEdgeToTriangle(e->elements, adj); + buildListOfEdgeAngle(adj, e->edges_detected, e->edges_lonly); + ElementsSelectedMode(e); + update_edges_cb(0, data); + + CTX::instance()->mesh.changed = ENT_ALL; + CTX::instance()->pickElements = 0; + drawContext::global()->draw(); + Msg::StatusBar(3, false, ""); +} + static void class_hide_cb(Fl_Widget *w, void *data) { CTX::instance()->hideUnselected = !CTX::instance()->hideUnselected; @@ -467,45 +309,45 @@ static void class_hide_cb(Fl_Widget *w, void *data) drawContext::global()->draw(); } -static void buildListOfEdgeAngle(e2t_cont adj, std::vector<edge_angle> &edges_detected, - std::vector<edge_angle> &edges_lonly) +static void show_only_edges_cb(Fl_Widget *w, void *data) { - e2t_cont::iterator it = adj.begin(); - for(; it != adj.end(); ++it){ - if(it->second.second) - edges_detected.push_back(edge_angle(it->first.getVertex(0), - it->first.getVertex(1), - it->second.first, it->second.second)); - else - edges_lonly.push_back(edge_angle(it->first.getVertex(0), - it->first.getVertex(1), - it->second.first, it->second.second)); + classificationEditor *e = (classificationEditor*)data; + static int old_sf = opt_mesh_surfaces_faces(0, GMSH_GET, 0.); + static int old_se = opt_mesh_surfaces_edges(0, GMSH_GET, 0.); + if(e->toggles[CLASS_TOGGLE_SHOW_ONLY_EDGES]->value()){ + opt_mesh_lines(0, GMSH_SET | GMSH_GUI, 1.); + opt_mesh_surfaces_faces(0, GMSH_SET | GMSH_GUI, 0.); + opt_mesh_surfaces_edges(0, GMSH_SET | GMSH_GUI, 0.); } - std::sort(edges_detected.begin(), edges_detected.end()); + else{ + opt_mesh_surfaces_faces(0, GMSH_SET | GMSH_GUI, old_sf); + opt_mesh_surfaces_edges(0, GMSH_SET | GMSH_GUI, old_se); + } + drawContext::global()->draw(); } -static void class_select_cb(Fl_Widget *w, void *data) +static void class_delete_edge_cb(Fl_Widget *w, void *data) { classificationEditor *e = (classificationEditor*)data; - std::vector<MTriangle*> &ele(e->getElements()); - CTX::instance()->pickElements = 1; + if(!e->selected) return; + CTX::instance()->pickElements = 1; + std::vector<MLine*> ele; + while(1) { CTX::instance()->mesh.changed = ENT_ALL; drawContext::global()->draw(); - Msg::StatusBar(3, false, "Select Elements\n" + Msg::StatusBar(3, false, "Select elements\n" "[Press 'e' to end selection or 'q' to abort]"); char ib = FlGui::instance()->selectEntity(ENT_ALL); if(ib == 'l') { - if(CTX::instance()->pickElements){ - for(unsigned int i = 0; i < FlGui::instance()->selectedElements.size(); i++){ - MElement *me = FlGui::instance()->selectedElements[i]; - if(me->getType() == TYPE_TRI && me->getVisibility() != 2){ - me->setVisibility(2); ele.push_back((MTriangle*)me); - } + for(unsigned int i = 0; i < FlGui::instance()->selectedElements.size(); i++){ + MElement *me = FlGui::instance()->selectedElements[i]; + if(me->getType() == TYPE_LIN && me->getVisibility() != 2){ + me->setVisibility(2); ele.push_back((MLine*)me); } } } @@ -516,10 +358,6 @@ static void class_select_cb(Fl_Widget *w, void *data) // ok, we compute edges ! if(ib == 'e') { GModel::current()->setSelection(0); - e2t_cont adj; - buildEdgeToTriangle(ele, adj); - buildListOfEdgeAngle(adj, e->edges_detected, e->edges_lonly); - ElementsSelectedMode(e); break; } // do nothing @@ -529,164 +367,366 @@ static void class_select_cb(Fl_Widget *w, void *data) break; } } - - updateedges_cb(0, data); + std::sort(ele.begin(), ele.end()); + + // look in all selected edges if a deleted one is present and delete it + std::vector<MLine*> temp = e->selected->lines; + e->selected->lines.clear(); + for(unsigned int i = 0; i < temp.size(); i++){ + std::vector<MLine*>::iterator it = std::find(ele.begin(), ele.end(), temp[i]); + if(it != ele.end()) + delete temp[i]; + else + e->selected->lines.push_back(temp[i]); + } + CTX::instance()->mesh.changed = ENT_ALL; CTX::instance()->pickElements = 0; drawContext::global()->draw(); Msg::StatusBar(3, false, ""); + + e->elements.clear(); + e->edges_detected.clear(); } -edge_angle::edge_angle(MVertex *_v1, MVertex *_v2, MElement *t1, MElement *t2) - : v1(_v1), v2(_v2) +static void class_reset_selection_cb(Fl_Widget *w, void *data) { - if(!t2) angle = 0; - else{ - double c1[3]; - double c2[3]; - double c3[3]; - { - MVertex *p1 = t1->getVertex(0); - MVertex *p2 = t1->getVertex(1); - MVertex *p3 = t1->getVertex(2); - double a[3] = {p1->x() - p2->x(), p1->y() - p2->y(), p1->z() - p2->z()}; - double b[3] = {p1->x() - p3->x(), p1->y() - p3->y(), p1->z() - p3->z()}; - c1[2] = a[0] * b[1] - a[1] * b[0]; - c1[1] = -a[0] * b[2] + a[2] * b[0]; - c1[0] = a[1] * b[2] - a[2] * b[1]; + classificationEditor *e = (classificationEditor*)data; + if(!e->selected) return; + for(unsigned int i = 0; i < e->selected->lines.size(); i++) + delete e->selected->lines[i]; + e->selected->lines.clear(); + e->selected->deleteVertexArrays(); + e->elements.clear(); + e->edges_detected.clear(); + NoElementsSelectedMode(e); +} + +static void class_select_surfaces_cb(Fl_Widget *w, void *data) +{ + classificationEditor *e = (classificationEditor*)data; + std::vector<GFace*> temp; + + opt_geometry_surfaces(0, GMSH_SET | GMSH_GUI, 1); + + while(1) { + CTX::instance()->mesh.changed = ENT_ALL; + drawContext::global()->draw(); + + Msg::StatusBar(3, false, "Select Surface\n" + "[Press 'e' to end selection or 'q' to abort]"); + + char ib = FlGui::instance()->selectEntity(ENT_SURFACE); + if(ib == 'l') { + for(unsigned int i = 0; i < FlGui::instance()->selectedFaces.size(); i++){ + FlGui::instance()->selectedFaces[i]->setSelection(1); + temp.push_back(FlGui::instance()->selectedFaces[i]); + } } - { - MVertex *p1 = t2->getVertex(0); - MVertex *p2 = t2->getVertex(1); - MVertex *p3 = t2->getVertex(2); - double a[3] = {p1->x() - p2->x(), p1->y() - p2->y(), p1->z() - p2->z()}; - double b[3] = {p1->x() - p3->x(), p1->y() - p3->y(), p1->z() - p3->z()}; - c2[2] = a[0] * b[1] - a[1] * b[0]; - c2[1] = -a[0] * b[2] + a[2] * b[0]; - c2[0] = a[1] * b[2] - a[2] * b[1]; + if(ib == 'e') { // store the list of gfaces + GModel::current()->setSelection(0); + for(unsigned int i = 0; i < temp.size(); i++){ + e->faces.insert(temp[i]); + } + break; } - norme(c1); - norme(c2); - prodve(c1, c2, c3); - double cosa; prosca(c1, c2, &cosa); - double sina = norme(c3); - angle = atan2(sina, cosa); + if(ib == 'q') { // do nothing + GModel::current()->setSelection(0); + break; + } + } + + if(e->faces.size()) + e->buttons[CLASS_BUTTON_CLASSIFY]->activate(); + + CTX::instance()->mesh.changed = ENT_ALL; + drawContext::global()->draw(); + Msg::StatusBar(3, false, ""); +} + +static void class_select_all_surfaces_cb(Fl_Widget *w, void *data) +{ + classificationEditor *e = (classificationEditor*)data; + + for(GModel::fiter it = GModel::current()->firstFace(); + it != GModel::current()->lastFace(); ++it) + e->faces.insert(*it); + + if(e->faces.size()) + e->buttons[CLASS_BUTTON_CLASSIFY]->activate(); + + CTX::instance()->mesh.changed = ENT_ALL; + drawContext::global()->draw(); + Msg::StatusBar(3, false, ""); +} + +static void class_classify_cb(Fl_Widget *w, void *data) +{ + classificationEditor *e = (classificationEditor*)data; + std::map<MLine*, GEdge*, compareMLinePtr> lines; + for(GModel::eiter it = GModel::current()->firstEdge(); + it != GModel::current()->lastEdge(); ++it){ + for(unsigned int i = 0; i < (*it)->lines.size();i++) + lines[(*it)->lines[i]] = *it; } + + std::list<MTri3*> tris; + { + std::set<GFace*>::iterator it = e->faces.begin(); + while(it != e->faces.end()){ + GFace *gf = *it; + for(unsigned int i = 0; i < gf->triangles.size(); i++) + tris.push_back(new MTri3(gf->triangles[i], 0)); + gf->triangles.clear(); + ++it; + } + } + if(tris.empty()) return; + + connectTriangles(tris); + + std::map<MTriangle*, GFace*> reverse; + // color all triangles + std::list<MTri3*> ::iterator it = tris.begin(); + while(it != tris.end()){ + if(!(*it)->isDeleted()){ + discreteFace *gf = new discreteFace + (GModel::current(), GModel::current()->maxFaceNum() + 1); + recurClassify(*it, gf, lines, reverse); + GModel::current()->add(gf); + } + ++it; + } + + // color some lines + it = tris.begin(); + while(it != tris.end()){ + (*it)->setDeleted(false); + ++it; + } + + it = tris.begin(); + + // classify edges that are bound by different GFaces + std::map<std::pair<int, int>, GEdge*> newEdges; + std::set<MLine*> touched; + recurClassifyEdges(*it, reverse, lines, touched, newEdges); + + // check if new edges should not be splitted + // splitted if composed of several open or closed edges + for (std::map<std::pair<int, int>, GEdge*>::iterator it = newEdges.begin(); + it != newEdges.end() ; ++it){ + GEdge *ge = it->second; + std::list<MLine*> segments; + for (unsigned int i = 0; i < ge->lines.size(); i++){ + segments.push_back(ge->lines[i]); + } + + // for each actual GEdge + while (!segments.empty()) { + std::vector<MLine*> myLines; + std::list<MLine*>::iterator it = segments.begin(); + MVertex *vB = (*it)->getVertex(0); + MVertex *vE = (*it)->getVertex(1); + myLines.push_back(*it); + segments.erase(it); + it++; + // printf("***candidate mline %d %d of size %d \n", + // vB->getNum(), vE->getNum(), segments.size()); + + for (int i=0; i<2; i++) { + for (std::list<MLine*>::iterator it = segments.begin(); + it != segments.end(); ++it){ + MVertex *v1 = (*it)->getVertex(0); + MVertex *v2 = (*it)->getVertex(1); + // printf("mline %d %d \n", v1->getNum(), v2->getNum()); + std::list<MLine*>::iterator itp; + if (v1 == vE){ + // printf("->push back this mline \n"); + myLines.push_back(*it); + itp = it; + it++; + segments.erase(itp); + vE = v2; + i = -1; + } + else if ( v2 == vE){ + //printf("->push back this mline \n"); + myLines.push_back(*it); + itp = it; + it++; + segments.erase(itp); + vE = v1; + i = -1; + } + if (it == segments.end()) break; + } + if (vB == vE) break; + if (segments.empty()) break; + // printf("not found VB=%d vE=%d\n", vB->getNum(), vE->getNum()); + MVertex *temp = vB; + vB = vE; + vE = temp; + // printf("not found VB=%d vE=%d\n", vB->getNum(), vE->getNum()); + } + GEdge *newGe = new discreteEdge + (GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0); + newGe->lines.insert(newGe->lines.end(), myLines.begin(), myLines.end()); + GModel::current()->add(newGe); + } //end for each actual GEdge + } + + //printf("end new edge with tag \n"); + + for (std::map<std::pair<int, int>, GEdge*>::iterator it = newEdges.begin(); + it != newEdges.end(); ++it){ + GEdge *ge = it->second; + GModel::current()->remove(ge); + } + + while(it != tris.end()){ + delete *it; + ++it; + } + + // remove selected, but do not delete its elements + if(e->selected){ + GModel::current()->remove(e->selected); + e->selected->lines.clear(); + delete e->selected; + e->selected = 0; + } + e->elements.clear(); + e->edges_detected.clear(); + NoElementsSelectedMode(e); } -classificationEditor::classificationEditor() +classificationEditor::classificationEditor() : selected(0) { - op[0] = opt_mesh_lines(0, GMSH_GET, 0.); - op[1] = opt_mesh_surfaces_edges(0, GMSH_GET, 0.); - op[2] = opt_mesh_surfaces_faces(0, GMSH_GET, 0.); - op[3] = opt_mesh_line_width(0, GMSH_SET | GMSH_GET,0.); - - opt_mesh_lines(0, GMSH_SET | GMSH_GUI, 1); - opt_mesh_surfaces_edges(0, GMSH_SET | GMSH_GUI, 0); - opt_mesh_surfaces_faces(0, GMSH_SET | GMSH_GUI, 1); - opt_mesh_line_width(0, GMSH_SET | GMSH_GUI, 1.5); - - // construct GUI in terms of standard sizes - int BBB = (int)(1.4 * BB); // labels too long - const int width = (int)(3.5 * BBB), height = 10 * BH; - - _window = new paletteWindow - (width, height, CTX::instance()->nonModalWindows ? true : false, "Classify"); + opt_mesh_lines(0, GMSH_SET | GMSH_GUI, 1.); + + drawContext::global()->draw(); + + int BBB = (int)(1.4 * BB); + const int width = (int)(3.15 * BBB), height = (int)(9.5 * BH); + + window = new paletteWindow + (width, height, CTX::instance()->nonModalWindows ? true : false, "Reclassify"); + window->box(GMSH_WINDOW_BOX); - new Fl_Tabs(WB, WB, width - 2 * WB, height - 2 * WB); + int x = WB, y = WB; { - Fl_Group *o = new Fl_Group - (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Edge Detection"); - edge_detec = o; + Fl_Box *b = new Fl_Box + (x, y, width, BH, "1. Select mesh elements on which to perform edge detection"); + b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); - _buttons[CLASSBUTTON_OK] = new Fl_Button - (4*WB+2*BBB, 7*WB+6*BH, BBB, BH, "OK"); - _buttons[CLASSBUTTON_OK]->callback(class_ok_cb, this); + x += WB; + y += BH; + buttons[CLASS_BUTTON_SELECT_ELEMENTS] = new Fl_Button + (x, y, BBB, BH, "Select elements"); + buttons[CLASS_BUTTON_SELECT_ELEMENTS]->callback(class_select_elements_cb, this); + + buttons[CLASS_BUTTON_SELECT_ALL_ELEMENTS] = new Fl_Button + (x + BBB + WB, y, (int)(0.5 * BBB) - WB, BH, "All"); + buttons[CLASS_BUTTON_SELECT_ALL_ELEMENTS]->callback(class_select_all_elements_cb, this); - _buttons[CLASSBUTTON_SELECT] = new Fl_Button - (2*WB, 2*WB+1*BH, BBB, BH, "Select Elements"); - _buttons[CLASSBUTTON_SELECT]->callback(class_select_cb, this); + toggles[CLASS_TOGGLE_HIDE] = new Fl_Check_Button + (x + 1.5 * BBB + WB, y, width - 1.5 * BBB - x - 2 * WB, BH, "Hide unselected elements"); + toggles[CLASS_TOGGLE_HIDE]->type(FL_TOGGLE_BUTTON); + toggles[CLASS_TOGGLE_HIDE]->callback(class_hide_cb, this); - _togbuttons[CLASSTOGBUTTON_HIDE] = new Fl_Toggle_Button - (3*WB+BBB, 2*WB+1*BH, BBB, BH, "Hide Unselected"); - _togbuttons[CLASSTOGBUTTON_HIDE]->callback(class_hide_cb,this); - - _togbuttons[CLASSTOGBUTTON_CLOS] = new Fl_Toggle_Button - (2*WB, 4*WB+3*BH, BBB, BH, "Include Closure"); - _togbuttons[CLASSTOGBUTTON_CLOS]->callback(updateedges_cb,this); + x -= WB; + } + { + y += BH / 2; + Fl_Box* b = new Fl_Box(x, y + BH - WB, width - 2 * WB, 2); + b->box(FL_ENGRAVED_FRAME); + b->labeltype(FL_NO_LABEL); + } + { + y += BH; + Fl_Box *b = new Fl_Box + (x, y, width, BH, "2. Fine-tune edge selection"); + b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); - _inputs[CLASSVALUE_ANGLE] = new Fl_Value_Input - (3*WB+BBB, 4*WB+3*BH, BBB, BH, "Treshold Angle"); - _inputs[CLASSVALUE_ANGLE]->value(40); - _inputs [CLASSVALUE_ANGLE]->maximum(90); - _inputs[CLASSVALUE_ANGLE]->minimum(0); - _inputs[CLASSVALUE_ANGLE]->align(FL_ALIGN_RIGHT); - _inputs[CLASSVALUE_ANGLE]->step(1); - _inputs[CLASSVALUE_ANGLE]->when(FL_WHEN_RELEASE); - _inputs[CLASSVALUE_ANGLE]->callback(updateedges_cb,this); - - _buttons[CLASSBUTTON_DEL] = new Fl_Button - (2*WB, 5*WB+4*BH, BBB, BH, "Delete Edge"); - _buttons[CLASSBUTTON_DEL]->callback(class_deleteedge_cb, this); - _buttons[CLASSBUTTON_DEL]->deactivate(); - - _buttons[CLASSBUTTON_ADD] = new Fl_Button - (2*WB, 6*WB+5*BH, BBB, BH, "Save Selection"); - _buttons[CLASSBUTTON_ADD]->callback(class_save_cb, this); - _buttons[CLASSBUTTON_ADD]->deactivate(); - - _buttons[CLASSBUTTON_CLEAR] = new Fl_Button - (2*WB, 7*WB+6*BH, BBB, BH, "Clear Selection"); - _buttons[CLASSBUTTON_CLEAR]->callback(class_clear_cb, this); - _buttons[CLASSBUTTON_CLEAR]->deactivate(); - o->end(); + x += WB; + y += BH; + inputs[CLASS_VALUE_ANGLE] = new Fl_Value_Input + (x, y, 2 * BBB / 3, BH, "Threshold angle"); + inputs[CLASS_VALUE_ANGLE]->value(40); + inputs[CLASS_VALUE_ANGLE]->maximum(180); + inputs[CLASS_VALUE_ANGLE]->minimum(0); + inputs[CLASS_VALUE_ANGLE]->align(FL_ALIGN_RIGHT); + inputs[CLASS_VALUE_ANGLE]->step(1); + inputs[CLASS_VALUE_ANGLE]->when(FL_WHEN_RELEASE); + inputs[CLASS_VALUE_ANGLE]->callback(update_edges_cb, this); + + toggles[CLASS_TOGGLE_SHOW_ONLY_EDGES] = new Fl_Check_Button + (x + 1.5 * BBB + WB, y, width - x - 1.5 * BBB - 2 * WB, BH, "Show only edges"); + toggles[CLASS_TOGGLE_SHOW_ONLY_EDGES]->type(FL_TOGGLE_BUTTON); + toggles[CLASS_TOGGLE_SHOW_ONLY_EDGES]->callback(show_only_edges_cb, this); + + y += BH; + toggles[CLASS_TOGGLE_BOUNDARY] = new Fl_Check_Button + (x, y, width - x - 2 * WB, BH, "Include edges on boundary (closure)"); + toggles[CLASS_TOGGLE_BOUNDARY]->type(FL_TOGGLE_BUTTON); + toggles[CLASS_TOGGLE_BOUNDARY]->callback(update_edges_cb, this); + + y += BH; + buttons[CLASS_BUTTON_DELETE_FROM_SELECTION] = new Fl_Button + (x, y, 1.5 * BBB, BH, "Delete edges from selection"); + buttons[CLASS_BUTTON_DELETE_FROM_SELECTION]->callback(class_delete_edge_cb, this); + buttons[CLASS_BUTTON_DELETE_FROM_SELECTION]->deactivate(); + + buttons[CLASS_BUTTON_RESET_SELECTION] = new Fl_Button + (x + 1.5 * BBB + WB, y, BBB, BH, "Reset selection"); + buttons[CLASS_BUTTON_RESET_SELECTION]->callback(class_reset_selection_cb, this); + buttons[CLASS_BUTTON_RESET_SELECTION]->deactivate(); + + x -= WB; } { - Fl_Group *o = new Fl_Group - (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Face Colouring"); - face_color = o; - o->deactivate(); - o->hide(); - _buttons[CLASSBUTTON_SELFAC] = new Fl_Button - (2*WB, 2*WB+1*BH, BBB, BH, "Select Model Face"); - _buttons[CLASSBUTTON_SELFAC]->callback(class_selectgface_cb, this); - _buttons[CLASSBUTTON_COLOR] = new Fl_Button - (2*WB, 3*WB+2*BH, BBB, BH, "Classify Mesh Faces"); - _buttons[CLASSBUTTON_COLOR]->callback(class_color_cb, this); - o->end(); + y += BH / 2; + Fl_Box* b = new Fl_Box(x, y + BH - WB, width - 2 * WB, 2); + b->box(FL_ENGRAVED_FRAME); + b->labeltype(FL_NO_LABEL); } { - Fl_Group *o = new Fl_Group - (WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Reparametrize Surfaces"); - reverse_eng = o; - o->hide(); - o->deactivate(); - o->end(); + y += BH; + Fl_Box *b = new Fl_Box + (x, y, width, BH, "3. Reclassify surfaces using selected edges"); + b->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); + + x += WB; + y += BH; + + buttons[CLASS_BUTTON_SELECT_SURFACES] = new Fl_Button + (x, y, BBB, BH, "Select surfaces"); + buttons[CLASS_BUTTON_SELECT_SURFACES]->callback(class_select_surfaces_cb, this); + + buttons[CLASS_BUTTON_SELECT_ALL_SURFACES] = new Fl_Button + (x + BBB + WB, y, (int)(0.5 * BBB) - WB, BH, "All"); + buttons[CLASS_BUTTON_SELECT_ALL_SURFACES]->callback(class_select_all_surfaces_cb, this); + + buttons[CLASS_BUTTON_CLASSIFY] = new Fl_Button + (x + 1.5 * BBB + WB, y, BBB, BH, "Reclassify"); + buttons[CLASS_BUTTON_CLASSIFY]->callback(class_classify_cb, this); + buttons[CLASS_BUTTON_CLASSIFY]->deactivate(); + + x -= WB; } - NoElementsSelectedMode(this); - // allocate detected edges - // temporary for the selection - // saved for the ones that have been saved by the user - // and that will be used for next step + window->end(); + window->hotspot(window); - temporary = new discreteEdge(GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0); - GModel::current()->add(temporary); - saved = new discreteEdge(GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0); - GModel::current()->add(saved); - - _window->end(); - _window->hotspot(_window); - _window->size_range(width, (int)(0.85 * height)); + NoElementsSelectedMode(this); } void mesh_classify_cb(Fl_Widget* w, void* data) { // create the (static) editor static classificationEditor *editor = 0; - if(!editor){ - editor = new classificationEditor(); - } + if(!editor) editor = new classificationEditor(); editor->show(); } diff --git a/Fltk/classificationEditor.h b/Fltk/classificationEditor.h index 55ba72a2db05307b27a9b1c281c2edb1b406e8b8..4bd2b2711ba745fee3ce509a23e2198fd6c55847 100644 --- a/Fltk/classificationEditor.h +++ b/Fltk/classificationEditor.h @@ -7,24 +7,26 @@ #define _CLASSIFICATION_EDITOR_H_ #include <vector> -#include <FL/Fl_Toggle_Button.H> -#include <FL/Fl_Round_Button.H> #include <FL/Fl_Window.H> +#include <FL/Fl_Check_Button.H> #include <FL/Fl_Value_Input.H> #include "GModel.h" #include "MElement.h" #include "ColorTable.h" -#define CLASSBUTTON_SELECT 0 -#define CLASSBUTTON_DEL 1 -#define CLASSBUTTON_ADD 2 -#define CLASSBUTTON_CLEAR 3 -#define CLASSBUTTON_OK 4 -#define CLASSBUTTON_COLOR 5 -#define CLASSBUTTON_SELFAC 6 -#define CLASSTOGBUTTON_HIDE 0 -#define CLASSTOGBUTTON_CLOS 1 -#define CLASSVALUE_ANGLE 0 +#define CLASS_BUTTON_SELECT_ELEMENTS 0 +#define CLASS_BUTTON_SELECT_ALL_ELEMENTS 1 +#define CLASS_BUTTON_DELETE_FROM_SELECTION 2 +#define CLASS_BUTTON_RESET_SELECTION 3 +#define CLASS_BUTTON_SELECT_SURFACES 4 +#define CLASS_BUTTON_SELECT_ALL_SURFACES 5 +#define CLASS_BUTTON_CLASSIFY 6 + +#define CLASS_TOGGLE_HIDE 0 +#define CLASS_TOGGLE_BOUNDARY 1 +#define CLASS_TOGGLE_SHOW_ONLY_EDGES 2 + +#define CLASS_VALUE_ANGLE 0 class edge_angle { public : @@ -40,21 +42,16 @@ class edge_angle { class classificationEditor { public: double op[10]; - std::vector<MTriangle*> _elements; - std::set<GFace*> _faces; - Fl_Window *_window; - Fl_Button *_buttons[10]; - Fl_Toggle_Button *_togbuttons[10]; - Fl_Value_Input *_inputs[10]; - GEdge *temporary; - GEdge *saved; - std::list<GFace *> tempFaces; - std::vector<edge_angle> edges_detected; - std::vector<edge_angle> edges_lonly; + std::vector<MTriangle*> elements; + std::set<GFace*> faces; + Fl_Window *window; + Fl_Button *buttons[10]; + Fl_Check_Button *toggles[10]; + Fl_Value_Input *inputs[10]; + GEdge *selected, *saved; + std::vector<edge_angle> edges_detected, edges_lonly; classificationEditor(); - void show(){ _window->show(); } - std::vector<MTriangle*> &getElements() { return _elements; } - Fl_Group *edge_detec, *face_color, *reverse_eng; + void show(){ window->show(); } }; void mesh_classify_cb(Fl_Widget* w, void* data); diff --git a/benchmarks/extrude/sphere_boundary_layer.geo b/benchmarks/extrude/sphere_boundary_layer.geo index dc79a3ccace52a9b98ca4c12fdf76d3c6259b446..e8498a641f4f0a6f417db830be0baf868fdb5bcb 100644 --- a/benchmarks/extrude/sphere_boundary_layer.geo +++ b/benchmarks/extrude/sphere_boundary_layer.geo @@ -1,4 +1,4 @@ -lc = .2; +lc = 1; Point(1) = {0.0,0.0,0.0,lc}; Point(2) = {1,0.0,0.0,lc}; @@ -37,9 +37,12 @@ Ruled Surface(26) = {25}; Line Loop(27) = {-4,12,-6}; Ruled Surface(28) = {27}; -Extrude { - Surface{14:28:2}; Layers{10, 0.2}; // Recombine; -} +old = Geometry.ExtrudeReturnLateralEntities; +Geometry.ExtrudeReturnLateralEntities = 0; +tmp[] = Extrude { + Surface{14:28:2}; Layers{5, 0.2}; Recombine; // 14:28:2 means itterate from 14 to 28 by steps of 2 +}; +Geometry.ExtrudeReturnLateralEntities = old; Point(100) = {-1.5,-1.5,-1.5, lc}; Point(101) = {-1.5,1.5,-1.5, lc}; @@ -74,10 +77,11 @@ Plane Surface(186) = {185}; Line Loop(187) = {172, 173, 174, 167}; Plane Surface(188) = {187}; -Surface Loop(1000) = {20, 22, 18, 14, 26, 16, 24, 28}; -Surface Loop(1001) = {45, 96, 113, 79, 62, 130, 147, 164}; -Surface Loop(1002) = {188, 186, 184, 180, 178, 182}; -Volume(1000) = {1000}; // inside -Volume(1001) = {1002, 1001}; // outside +Surface Loop(1000) = {14:28:2}; // the sphere (only need for internal mesh) +Surface Loop(1001) = {tmp[{0:14:2}]}; // The outside of the BL +Surface Loop(1002) = {188, 186, 184, 180, 178, 182}; // the box (entire farfield surface loop) + +//Volume(1000) = {1000}; /// inside the sphere +Volume(1001) = {1002, 1001}; /// FarField Mesh.Algorithm3D = 4; diff --git a/benchmarks/stl/coupe_geom.stl.gz b/benchmarks/stl/coupe_geom.stl.gz index ae299fdde2d37645c8dce300fd4075242009c319..ec014157e439ba7cfe120432d23cb73a5be82e26 100644 Binary files a/benchmarks/stl/coupe_geom.stl.gz and b/benchmarks/stl/coupe_geom.stl.gz differ