Skip to content
Snippets Groups Projects
Commit 2f2267c2 authored by Christophe Geuzaine's avatar Christophe Geuzaine
Browse files

rewrote classificationEditor

parent 6a865af9
Branches
Tags
No related merge requests found
......@@ -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,90 +19,331 @@
#include "discreteEdge.h"
#include "discreteFace.h"
edge_angle::edge_angle(MVertex *_v1, MVertex *_v2, MElement *t1, MElement *t2)
: v1(_v1), v2(_v2)
{
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];
}
{
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];
}
norme(c1);
norme(c2);
prodve(c1, c2, c3);
double cosa; prosca(c1, c2, &cosa);
double sina = norme(c3);
angle = atan2(sina, cosa);
}
}
struct compareMLinePtr
{
bool operator () (MLine *l1, MLine *l2) const
{
static Less_Edge le;
return le(l1->getEdge(0), l2->getEdge(0));
}
};
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)
{
if(!t->isDeleted()){
gf->triangles.push_back(t->tri());
reverse[t->tri()] = gf;
t->setDeleted(true);
for(int i = 0; i < 3; i++){
MTri3 *tn = t->getNeigh(i);
if(tn){
edgeXface exf(t, i);
MLine ml(exf.v[0], exf.v[1]);
std::map<MLine*, GEdge*, compareMLinePtr>::iterator it = lines.find(&ml);
if(it == lines.end())
recurClassify(tn, gf, lines, reverse);
}
}
}
}
static GEdge *getNewModelEdge(GFace *gf1, GFace *gf2,
std::map<std::pair<int, int>, GEdge* > &newEdges)
{
int t1 = gf1 ? gf1->tag() : -1;
int t2 = gf2 ? gf2->tag() : -1;
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 *ge = new discreteEdge
(GModel::current(), GModel::current()->maxEdgeNum() + 1, 0, 0);
GModel::current()->add(ge);
newEdges[std::make_pair<int, int>(i1, i2)] = ge;
return ge;
}
else
return it->second;
}
static void recurClassifyEdges(MTri3 *t,
std::map<MTriangle*, GFace*> &reverse,
std::map<MLine*, GEdge*, compareMLinePtr> &lines,
std::set<MLine*> &touched,
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++){
GFace *gf2 = 0;
MTri3 *tn = t->getNeigh(i);
if(tn)
gf2 = reverse[tn->tri()];
edgeXface exf(t, i);
MLine ml(exf.v[0], exf.v[1]);
std::map<MLine*, GEdge*, compareMLinePtr>::iterator it = lines.find(&ml);
if(it != lines.end()){
if(touched.find(it->first) == touched.end()){
GEdge *ge = getNewModelEdge(gf1, gf2, newEdges);
if(ge) ge->lines.push_back(it->first);
touched.insert(it->first);
}
}
if(tn)
recurClassifyEdges(tn, reverse, lines, touched, newEdges);
}
}
}
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[CLASS_BUTTON_SELECT_ELEMENTS]->activate();
e->buttons[CLASS_BUTTON_SELECT_ALL_ELEMENTS]->activate();
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();
e->_buttons[CLASSBUTTON_SELECT]->activate();
e->_togbuttons[CLASSTOGBUTTON_HIDE]->activate();
CTX::instance()->mesh.changed = ENT_ALL;
CTX::instance()->pickElements = 0;
drawContext::global()->draw();
Msg::StatusBar(3, false, "");
}
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[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[CLASSBUTTON_SELECT]->deactivate();
e->_togbuttons[CLASSTOGBUTTON_HIDE]->deactivate();
e->buttons[CLASS_BUTTON_SELECT_ELEMENTS]->deactivate();
e->buttons[CLASS_BUTTON_SELECT_ALL_ELEMENTS]->deactivate();
}
// we should
static void class_selectgface_cb(Fl_Widget *w, void *data)
static void update_edges_cb(Fl_Widget *w, void *data)
{
classificationEditor *e = (classificationEditor*)data;
std::vector<GFace*> temp;
opt_geometry_surfaces(0, GMSH_SET | GMSH_GUI, 1);
if(!e->selected) return;
printf("%d inside edges detected\n", (int)e->edges_detected.size());
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[CLASS_VALUE_ANGLE]->value() / 180 * M_PI)
break;
e->selected->lines.push_back(new MLine(ea.v1, ea.v2));
}
printf("%d boundary edges detected\n", (int)e->edges_lonly.size());
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->selected->lines.push_back(new MLine(ea.v1, ea.v2));
//check if closed loop
}
}
CTX::instance()->mesh.changed = ENT_ALL;
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 Model Face\n"
Msg::StatusBar(3, false, "Select elements\n"
"[Press 'e' to end selection or 'q' to abort]");
char ib = FlGui::instance()->selectEntity(ENT_SURFACE);
char ib = FlGui::instance()->selectEntity(ENT_ALL);
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]);
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);
}
}
// 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]);
}
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;
}
// do nothing
if(ib == 'q') {
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_deleteedge_cb(Fl_Widget *w, void *data)
static void class_select_all_elements_cb(Fl_Widget *w, void *data)
{
classificationEditor *e = (classificationEditor*)data;
std::vector<MLine*> ele;
// 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;
CTX::instance()->mesh.changed = ENT_ALL;
drawContext::global()->draw();
}
static void show_only_edges_cb(Fl_Widget *w, void *data)
{
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.);
}
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_delete_edge_cb(Fl_Widget *w, void *data)
{
classificationEditor *e = (classificationEditor*)data;
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_LIN && me->getVisibility() != 2){
......@@ -110,7 +351,6 @@ static void class_deleteedge_cb(Fl_Widget *w, void *data)
}
}
}
}
if(ib == 'r') {
for(unsigned int i = 0; i < FlGui::instance()->selectedElements.size(); i++)
FlGui::instance()->selectedElements[i]->setVisibility(1);
......@@ -129,202 +369,132 @@ static void class_deleteedge_cb(Fl_Widget *w, void *data)
}
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();
// 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()){
if(it != ele.end())
delete temp[i];
}
else e->temporary->lines.push_back(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();
}
static void class_save_cb(Fl_Widget *w, void *data)
static void class_reset_selection_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();
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();
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)
static void class_select_surfaces_cb(Fl_Widget *w, void *data)
{
classificationEditor *e = (classificationEditor*)data;
std::vector<GFace*> temp;
for(unsigned int i = 0; i < e->temporary->lines.size(); i++){
delete e->temporary->lines[i];
}
e->temporary->lines.clear();
opt_geometry_surfaces(0, GMSH_SET | GMSH_GUI, 1);
while(1) {
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, "Select Surface\n"
"[Press 'e' to end selection or 'q' to abort]");
Msg::StatusBar(3, false, "");
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]);
}
struct compareMLinePtr
{
bool operator () (MLine *l1, MLine *l2) const
{
static Less_Edge le;
return le(l1->getEdge(0), l2->getEdge(0));
}
};
static void recurClassify(MTri3 *t, GFace *gf,
std::map<MLine*, GEdge*, compareMLinePtr> &lines,
std::map<MTriangle*, GFace*> &reverse)
{
if(!t->isDeleted()){
gf->triangles.push_back(t->tri());
reverse[t->tri()] = gf;
t->setDeleted(true);
for(int i = 0; i < 3; i++){
MTri3 *tn = t->getNeigh(i);
if(tn){
edgeXface exf(t, i);
MLine ml(exf.v[0], exf.v[1]);
std::map<MLine*, GEdge*, compareMLinePtr>::iterator it = lines.find(&ml);
if(it == lines.end())
recurClassify(tn, gf, lines, reverse);
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;
}
if(ib == 'q') { // do nothing
GModel::current()->setSelection(0);
break;
}
}
static GEdge *getNewModelEdge(GFace *gf1, GFace *gf2,
std::map<std::pair<int, int>, GEdge* > &newEdges)
{
int t1 = gf1 ? gf1->tag() : -1;
int t2 = gf2 ? gf2->tag() : -1;
int i1 = std::min(t1,t2);
int i2 = std::max(t1,t2);
if(i1 == i2) return 0;
if(e->faces.size())
e->buttons[CLASS_BUTTON_CLASSIFY]->activate();
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
(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;
}
else
return it->second;
CTX::instance()->mesh.changed = ENT_ALL;
drawContext::global()->draw();
Msg::StatusBar(3, false, "");
}
static void recurClassifyEdges(MTri3 *t,
std::map<MTriangle*, GFace*> &reverse,
std::map<MLine*, GEdge*, compareMLinePtr> &lines,
std::set<MLine*> &touched,
std::map<std::pair<int, int>, GEdge*> &newEdges)
static void class_select_all_surfaces_cb(Fl_Widget *w, void *data)
{
if(!t->isDeleted()){
classificationEditor *e = (classificationEditor*)data;
t->setDeleted(true);
GFace *gf1 = reverse[t->tri()];
for(int i = 0; i < 3; i++){
GFace *gf2 = 0;
MTri3 *tn = t->getNeigh(i);
if(tn)
gf2 = reverse[tn->tri()];
edgeXface exf(t, i);
MLine ml(exf.v[0], exf.v[1]);
std::map<MLine*, GEdge*, compareMLinePtr>::iterator it = lines.find(&ml);
if(it != lines.end()){
if(touched.find(it->first) == touched.end()){
GEdge *ge = getNewModelEdge(gf1, gf2, newEdges);
if(ge) ge->lines.push_back(it->first);
touched.insert(it->first);
}
}
if(tn)
recurClassifyEdges(tn, reverse, lines, touched, newEdges);
}
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_color_cb(Fl_Widget* w, void* data)
static void class_classify_cb(Fl_Widget *w, void *data)
{
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(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()){
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++){
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.size() )return;
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 *temporary = new discreteFace
discreteFace *gf = new discreteFace
(GModel::current(), GModel::current()->maxFaceNum() + 1);
recurClassify(*it, temporary, lines, reverse);
GModel::current()->add(temporary);
recurClassify(*it, gf, lines, reverse);
GModel::current()->add(gf);
}
++it;
}
......@@ -339,20 +509,15 @@ static void class_color_cb(Fl_Widget* w, void* data)
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){
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]);
......@@ -367,10 +532,12 @@ static void class_color_cb(Fl_Widget* w, void* data)
myLines.push_back(*it);
segments.erase(it);
it++;
//printf("***candidate mline %d %d of size %d \n", vB->getNum(), vE->getNum(), segments.size());
// 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){
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());
......@@ -409,6 +576,7 @@ static void class_color_cb(Fl_Widget* w, void* data)
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();
......@@ -421,272 +589,144 @@ static void class_color_cb(Fl_Widget* w, void* data)
delete *it;
++it;
}
}
CTX::instance()->mesh.changed = ENT_ALL;
drawContext::global()->draw();
Msg::StatusBar(3, false, "");
// 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;
}
static void updateedges_cb(Fl_Widget* w, void* data)
{
classificationEditor *e = (classificationEditor*)data;
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->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)
break;
e->temporary->lines.push_back(new MLine(ea.v1, ea.v2));
e->elements.clear();
e->edges_detected.clear();
NoElementsSelectedMode(e);
}
printf("%d boundary edges detected\n", (int)e->edges_lonly.size());
if(e->_togbuttons[CLASSTOGBUTTON_CLOS]->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));
//check if closed loop
}
}
classificationEditor::classificationEditor() : selected(0)
{
opt_mesh_lines(0, GMSH_SET | GMSH_GUI, 1.);
CTX::instance()->mesh.changed = ENT_ALL;
drawContext::global()->draw();
}
static void class_hide_cb(Fl_Widget *w, void *data)
{
CTX::instance()->hideUnselected = !CTX::instance()->hideUnselected;
CTX::instance()->mesh.changed = ENT_ALL;
drawContext::global()->draw();
}
int BBB = (int)(1.4 * BB);
const int width = (int)(3.15 * BBB), height = (int)(9.5 * BH);
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());
}
window = new paletteWindow
(width, height, CTX::instance()->nonModalWindows ? true : false, "Reclassify");
window->box(GMSH_WINDOW_BOX);
static void class_select_cb(Fl_Widget *w, void *data)
int x = WB, y = WB;
{
classificationEditor *e = (classificationEditor*)data;
std::vector<MTriangle*> &ele(e->getElements());
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);
CTX::instance()->pickElements = 1;
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);
while(1) {
CTX::instance()->mesh.changed = ENT_ALL;
drawContext::global()->draw();
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);
Msg::StatusBar(3, false, "Select Elements\n"
"[Press 'e' to end selection or 'q' to abort]");
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);
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);
}
}
}
}
if(ib == 'r') {
for(unsigned int i = 0; i < FlGui::instance()->selectedElements.size(); i++)
FlGui::instance()->selectedElements[i]->setVisibility(1);
x -= WB;
}
// 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
if(ib == 'q') {
GModel::current()->setSelection(0);
ele.clear();
break;
}
}
updateedges_cb(0, data);
CTX::instance()->mesh.changed = ENT_ALL;
CTX::instance()->pickElements = 0;
drawContext::global()->draw();
Msg::StatusBar(3, false, "");
}
edge_angle::edge_angle(MVertex *_v1, MVertex *_v2, MElement *t1, MElement *t2)
: v1(_v1), v2(_v2)
{
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];
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);
}
{
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];
}
norme(c1);
norme(c2);
prodve(c1, c2, c3);
double cosa; prosca(c1, c2, &cosa);
double sina = norme(c3);
angle = atan2(sina, cosa);
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);
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;
}
{
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);
}
classificationEditor::classificationEditor()
{
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.);
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);
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);
x += WB;
y += BH;
// 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;
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);
_window = new paletteWindow
(width, height, CTX::instance()->nonModalWindows ? true : false, "Classify");
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);
new Fl_Tabs(WB, WB, width - 2 * WB, height - 2 * WB);
{
Fl_Group *o = new Fl_Group
(WB, WB + BH, width - 2 * WB, height - 2 * WB - BH, "Edge Detection");
edge_detec = o;
_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);
_buttons[CLASSBUTTON_SELECT] = new Fl_Button
(2*WB, 2*WB+1*BH, BBB, BH, "Select Elements");
_buttons[CLASSBUTTON_SELECT]->callback(class_select_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);
_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();
}
{
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();
}
{
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();
}
NoElementsSelectedMode(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();
// 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
x -= WB;
}
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->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();
}
......@@ -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);
......
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;
No preview for this file type
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment