From 8d9a85f55f132502c212024565c4df8ca7cc1dbe Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Mon, 12 Dec 2011 10:04:55 +0000 Subject: [PATCH] automagic 2D graphs with onelab --- Fltk/graphicWindow.cpp | 18 ++++++ Fltk/inputRange.h | 116 ++++++++++++++++++++++++++---------- Fltk/onelabWindow.cpp | 132 ++++++++++++++++++++++++++++++----------- Post/PView.cpp | 8 +-- 4 files changed, 204 insertions(+), 70 deletions(-) diff --git a/Fltk/graphicWindow.cpp b/Fltk/graphicWindow.cpp index 2ac53c8588..d1f0b9d9fc 100644 --- a/Fltk/graphicWindow.cpp +++ b/Fltk/graphicWindow.cpp @@ -110,6 +110,22 @@ static void gmsh_gear(Fl_Color c) fl_line_style(FL_SOLID); } +static void gmsh_graph_x(Fl_Color c) +{ + fl_color(c); + fl_begin_line(); vv(-0.8,0.8); vv(0.8,0.8); fl_end_line(); + fl_begin_polygon(); vv(0.8,0.8); vv(0.2,1.1); vv(0.2,0.5); fl_end_polygon(); + fl_begin_line(); vv(-0.8,0.3); vv(-0.2,-0.2); vv(0.3,0.1); vv(0.8,-0.4); fl_end_line(); +} + +static void gmsh_graph_y(Fl_Color c) +{ + fl_color(c); + fl_begin_line(); vv(-0.8,-0.8); vv(-0.8,0.8); fl_end_line(); + fl_begin_polygon(); vv(-0.8,-1.1); vv(-1.1, -0.5); vv(-0.5, -0.5); fl_end_polygon(); + fl_begin_line(); vv(-0.8,0.3); vv(-0.2,-0.2); vv(0.3,0.1); vv(0.8,-0.4); fl_end_line(); +} + #undef vv #undef bl #undef el @@ -487,6 +503,8 @@ graphicWindow::graphicWindow(bool main, int numTiles) fl_add_symbol("gmsh_models", gmsh_models, 1); fl_add_symbol("gmsh_clscale", gmsh_clscale, 1); fl_add_symbol("gmsh_gear", gmsh_gear, 1); + fl_add_symbol("gmsh_graph_x", gmsh_graph_x, 1); + fl_add_symbol("gmsh_graph_y", gmsh_graph_y, 1); first = false; } diff --git a/Fltk/inputRange.h b/Fltk/inputRange.h index 383686ee81..ed5ec0b118 100644 --- a/Fltk/inputRange.h +++ b/Fltk/inputRange.h @@ -16,7 +16,8 @@ class inputRange : public Fl_Group { private: Fl_Value_Input *_input; Fl_Input *_range; - Fl_Toggle_Button *_range_butt, *_loop_butt; + Fl_Toggle_Button *_range_butt, *_loop_butt, *_graph_butt[2]; + std::string _loop_val, _graph_val[2]; double _min, _max, _step, _max_number; std::vector<double> _choices; void _values2string() @@ -123,60 +124,104 @@ class inputRange : public Fl_Group { } void _set_loop_value(const std::string &val) { + _loop_val = val; if(val == "1"){ - _loop_butt->label("1"); + //_loop_butt->label("1"); _loop_butt->selection_color(FL_GREEN); _loop_butt->value(1); } else if(val == "2"){ - _loop_butt->label("2"); + //_loop_butt->label("2"); _loop_butt->selection_color(FL_BLUE); _loop_butt->value(1); } else if(val == "3"){ - _loop_butt->label("3"); + //_loop_butt->label("3"); _loop_butt->selection_color(FL_RED); _loop_butt->value(1); } else{ - _loop_butt->label("@-1gmsh_rotate"); + //_loop_butt->label("@-1gmsh_rotate"); _loop_butt->selection_color(_loop_butt->color()); _loop_butt->value(0); } + _loop_butt->redraw(); + } + void _set_graph_value(int axis, const std::string &val) + { + _graph_val[axis] = val; + if(val == "1"){ + //_graph_butt[axis]->label("1"); + _graph_butt[axis]->selection_color(FL_GREEN); + _graph_butt[axis]->value(1); + } + else if(val == "2"){ + //_graph_butt[axis]->label("2"); + _graph_butt[axis]->selection_color(FL_BLUE); + _graph_butt[axis]->value(1); + } + else if(val == "3"){ + //_graph_butt[axis]->label("3"); + _graph_butt[axis]->selection_color(FL_RED); + _graph_butt[axis]->value(1); + } + else{ + //_graph_butt[axis]->label(axis == 0 ? "@-1gmsh_graph_x" : "@-1gmsh_graph_y"); + _graph_butt[axis]->selection_color(_graph_butt[axis]->color()); + _graph_butt[axis]->value(0); + } + _graph_butt[axis]->redraw(); } static void _input_cb(Fl_Widget *w, void *data) { - ((inputRange*)data)->do_callback(); + inputRange *b = (inputRange*)data; + b->do_callback(); } static void _range_cb(Fl_Widget *w, void *data) { - ((inputRange*)data)->_string2values(); - ((inputRange*)data)->do_callback(); + inputRange *b = (inputRange*)data; + b->_string2values(); + b->do_callback(); } static void _range_butt_cb(Fl_Widget *w, void *data) { - ((inputRange*)data)->_show_range(); + inputRange *b = (inputRange*)data; + b->_show_range(); } static void _loop_butt_cb(Fl_Widget *w, void *data) { - Fl_Toggle_Button *b = (Fl_Toggle_Button*)w; - if(std::string(b->label()) == "1") - ((inputRange*)data)->_set_loop_value("2"); - else if(std::string(b->label()) == "2") - ((inputRange*)data)->_set_loop_value("3"); - else if(std::string(b->label()) == "3") - ((inputRange*)data)->_set_loop_value("0"); - else - ((inputRange*)data)->_set_loop_value("1"); - ((inputRange*)data)->do_callback(); + inputRange *b = (inputRange*)data; + if(b->_loop_val == "1") b->_set_loop_value("2"); + else if(b->_loop_val == "2") b->_set_loop_value("3"); + else if(b->_loop_val == "3") b->_set_loop_value("0"); + else b->_set_loop_value("1"); + b->do_callback(); + } + static void _graph_butt_x_cb(Fl_Widget *w, void *data) + { + inputRange *b = (inputRange*)data; + if(b->_graph_val[0] == "1") b->_set_graph_value(0, "2"); + else if(b->_graph_val[0] == "2") b->_set_graph_value(0, "3"); + else if(b->_graph_val[0] == "3") b->_set_graph_value(0, "0"); + else b->_set_graph_value(0, "1"); + b->do_callback(); + } + static void _graph_butt_y_cb(Fl_Widget *w, void *data) + { + inputRange *b = (inputRange*)data; + if(b->_graph_val[1] == "1") b->_set_graph_value(1, "2"); + else if(b->_graph_val[1] == "2") b->_set_graph_value(1, "3"); + else if(b->_graph_val[1] == "3") b->_set_graph_value(1, "0"); + else b->_set_graph_value(1, "1"); + b->do_callback(); } public: inputRange(int x, int y, int w, int h, double max_number, const char *l=0) : Fl_Group(x,y,w,h,l), _min(-max_number), _max(max_number), _step(1.), _max_number(max_number) { - int dot_w = FL_NORMAL_SIZE - 2, loop_w = FL_NORMAL_SIZE + 6; - int input_w = w - dot_w - loop_w; + int dot_w = FL_NORMAL_SIZE - 2, loop_w = FL_NORMAL_SIZE + 6, graph_w = loop_w; + int input_w = w - dot_w - loop_w - 2 * graph_w; int range_w = input_w / 2; _input = new Fl_Value_Input(x, y, input_w, h); @@ -198,6 +243,20 @@ class inputRange : public Fl_Group { _loop_butt->callback(_loop_butt_cb, this); _loop_butt->tooltip("Loop over range when computing"); + _graph_butt[0] = new Fl_Toggle_Button + (x + input_w + dot_w + loop_w, y, graph_w, h); + _graph_butt[0]->label("@-1gmsh_graph_x"); + _graph_butt[0]->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE); + _graph_butt[0]->callback(_graph_butt_x_cb, this); + _graph_butt[0]->tooltip("Use range as abscissa of X-Y graph"); + + _graph_butt[1] = new Fl_Toggle_Button + (x + input_w + dot_w + loop_w + graph_w, y, graph_w, h); + _graph_butt[1]->label("@-1gmsh_graph_y"); + _graph_butt[1]->align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE); + _graph_butt[1]->callback(_graph_butt_y_cb, this); + _graph_butt[1]->tooltip("Use range as ordinate of X-Y graph"); + end(); // close the group resizable(_input); } @@ -211,13 +270,10 @@ class inputRange : public Fl_Group { double maximum() { return _max; } void step(double val) { _step = val; _values2string(); } double step() { return _step; } - void loop(const std::string &val) - { - _set_loop_value(val); - } - std::string loop() - { - if(!_loop_butt->value()) return "0"; - else return _loop_butt->label(); - } + void loop(const std::string &val){ _set_loop_value(val); } + std::string loop(){ return _loop_val; } + void graph_x(const std::string &val){ _set_graph_value(0, val); } + std::string graph_x(){ return _graph_val[0]; } + void graph_y(const std::string &val){ _set_graph_value(1, val); } + std::string graph_y(){ return _graph_val[1]; } }; diff --git a/Fltk/onelabWindow.cpp b/Fltk/onelabWindow.cpp index 9da6aba9da..ec961b282c 100644 --- a/Fltk/onelabWindow.cpp +++ b/Fltk/onelabWindow.cpp @@ -23,6 +23,7 @@ #include "CreateFile.h" #include "drawContext.h" #include "PView.h" +#include "PViewData.h" #include "PViewOptions.h" #include "FlGui.h" #include "paletteWindow.h" @@ -181,34 +182,27 @@ bool onelab::localNetworkClient::run(const std::string &what) break; case GmshSocket::GMSH_PARAMETER_QUERY: { - std::string type, name; + std::string type, name, reply; onelab::parameter::getTypeAndNameFromChar(message, type, name); if(type == "number"){ std::vector<onelab::number> par; get(par, name); - if(par.size() == 1){ - std::string reply = par[0].toChar(); - server->SendMessage(GmshSocket::GMSH_PARAMETER, reply.size(), &reply[0]); - } - else{ - std::string reply = "Parameter (number) " + name + " not found"; - server->SendMessage(GmshSocket::GMSH_INFO, reply.size(), &reply[0]); - } + if(par.size() == 1) reply = par[0].toChar(); } else if(type == "string"){ std::vector<onelab::string> par; get(par, name); - if(par.size() == 1){ - std::string reply = par[0].toChar(); - server->SendMessage(GmshSocket::GMSH_PARAMETER, reply.size(), &reply[0]); - } - else{ - std::string reply = "Parameter (string) " + name + " not found"; - server->SendMessage(GmshSocket::GMSH_INFO, reply.size(), &reply[0]); - } + if(par.size() == 1) reply = par[0].toChar(); } else Msg::Error("FIXME query not done for this parameter type"); + if(reply.size()){ + server->SendMessage(GmshSocket::GMSH_PARAMETER, reply.size(), &reply[0]); + } + else{ + reply = "Parameter '" + name + "' not found"; + server->SendMessage(GmshSocket::GMSH_INFO, reply.size(), &reply[0]); + } } break; case GmshSocket::GMSH_PROGRESS: @@ -429,6 +423,83 @@ static bool stopOnError(const std::string &client) return false; } +static std::vector<double> getRange(onelab::number &p) +{ + std::vector<double> v; + if(p.getChoices().size()){ + v = p.getChoices(); + } + else if(p.getMin() != -onelab::parameter::maxNumber() && + p.getMax() != onelab::parameter::maxNumber() && p.getStep()){ + for(double d = p.getMin(); d <= p.getMax(); d += p.getStep()) + v.push_back(d); + } + return v; +} + +static std::string getShortName(const std::string &name, const std::string &ok="") +{ + if(ok.size()) return ok; + std::string s = name; + // remove path + std::string::size_type last = name.find_last_of('/'); + if(last != std::string::npos) + s = name.substr(last + 1); + // remove starting numbers + while(s.size() && s[0] >= '0' && s[0] <= '9') + s = s.substr(1); + return s; +} + +static void updateOnelabGraph(std::string num) +{ + bool changed = false; + for(unsigned int i = 0; i < PView::list.size(); i++){ + if(PView::list[i]->getData()->getFileName() == "ONELAB" + num){ + delete PView::list[i]; + changed = true; + break; + } + } + + std::vector<double> x, y; + std::string xName, yName; + std::vector<onelab::number> numbers; + onelab::server::instance()->get(numbers); + for(unsigned int i = 0; i < numbers.size(); i++){ + if(numbers[i].getAttribute("graph_x") == num){ + x = getRange(numbers[i]); + xName = getShortName(numbers[i].getName(), numbers[i].getShortHelp()); + } + if(numbers[i].getAttribute("graph_y") == num){ + y = getRange(numbers[i]); + yName = getShortName(numbers[i].getName(), numbers[i].getShortHelp()); + } + } + if(x.size() != y.size()){ + x.clear(); xName.clear(); + for(unsigned int i = 0; i < y.size(); i++) x.push_back(i); + } + if(y.size()){ + PView *v = new PView(xName, yName, x, y); + v->getData()->setFileName("ONELAB" + num); + v->getOptions()->intervalsType = PViewOptions::Discrete; + changed = true; + } + + if(changed){ + FlGui::instance()->updateViews(); + drawContext::global()->draw(); + } +} + +static void updateOnelabGraphs() +{ + updateOnelabGraph("1"); + updateOnelabGraph("2"); + updateOnelabGraph("3"); +} + void onelab_cb(Fl_Widget *w, void *data) { if(!data) return; @@ -538,6 +609,7 @@ void onelab_cb(Fl_Widget *w, void *data) if(stop) break; } + updateOnelabGraphs(); FlGui::instance()->onelab->rebuildTree(); } while(action == "compute" && incrementLoop() && !stop); @@ -573,7 +645,10 @@ static void onelab_input_range_cb(Fl_Widget *w, void *data) numbers[0].setStep(o->step()); numbers[0].setChoices(o->choices()); numbers[0].setAttribute("loop", o->loop()); + numbers[0].setAttribute("graph_x", o->graph_x()); + numbers[0].setAttribute("graph_y", o->graph_y()); onelab::server::instance()->set(numbers[0]); + updateOnelabGraphs(); } } @@ -658,7 +733,7 @@ onelabWindow::onelabWindow(int deltaFontSize) _gear->align(FL_ALIGN_LEFT | FL_ALIGN_INSIDE); _gear->add("Reset database", 0, onelab_cb, (void*)"reset"); _gear->add("Print database", 0, onelab_dump_cb); - _gear->add("Remesh automatically", 0, 0, 0, FL_MENU_TOGGLE); + _gear->add("_Remesh automatically", 0, 0, 0, FL_MENU_TOGGLE); ((Fl_Menu_Item*)_gear->menu())[2].set(); _gearFrozenMenuSize = _gear->menu()->size(); @@ -675,19 +750,6 @@ onelabWindow::onelabWindow(int deltaFontSize) FL_NORMAL_SIZE += deltaFontSize; } -static std::string getShortName(const std::string &name) -{ - std::string s = name; - // remove path - std::string::size_type last = name.find_last_of('/'); - if(last != std::string::npos) - s = name.substr(last + 1); - // remove starting numbers - while(s.size() && s[0] >= '0' && s[0] <= '9') - s = s.substr(1); - return s; -} - void onelabWindow::rebuildTree() { int width = (int)(0.5 * _tree->w()); @@ -705,8 +767,7 @@ void onelabWindow::rebuildTree() for(unsigned int i = 0; i < numbers.size(); i++){ Fl_Tree_Item *n = _tree->add(numbers[i].getName().c_str()); n->labelsize(FL_NORMAL_SIZE + 5); - std::string label = numbers[i].getShortHelp(); - if(label.empty()) label = getShortName(numbers[i].getName()); + std::string label = getShortName(numbers[i].getName(), numbers[i].getShortHelp()); _tree->begin(); if(numbers[i].getChoices().size() == 2 && numbers[i].getChoices()[0] == 0 && numbers[i].getChoices()[1] == 1){ @@ -728,6 +789,8 @@ void onelabWindow::rebuildTree() but->step(numbers[i].getStep()); but->choices(numbers[i].getChoices()); but->loop(numbers[i].getAttribute("loop")); + but->graph_x(numbers[i].getAttribute("graph_x")); + but->graph_y(numbers[i].getAttribute("graph_y")); but->align(FL_ALIGN_RIGHT); but->callback(onelab_input_range_cb, (void*)n); but->when(FL_WHEN_RELEASE | FL_WHEN_ENTER_KEY); @@ -741,8 +804,7 @@ void onelabWindow::rebuildTree() for(unsigned int i = 0; i < strings.size(); i++){ Fl_Tree_Item *n = _tree->add(strings[i].getName().c_str()); n->labelsize(FL_NORMAL_SIZE + 5); - std::string label = strings[i].getShortHelp(); - if(label.empty()) label = getShortName(strings[i].getName()); + std::string label = getShortName(strings[i].getName(), strings[i].getShortHelp()); _tree->begin(); Fl_Input_Choice *but = new Fl_Input_Choice(1, 1, width, 1); _treeWidgets.push_back(but); diff --git a/Post/PView.cpp b/Post/PView.cpp index 8cc88c76f2..5e5b65f237 100644 --- a/Post/PView.cpp +++ b/Post/PView.cpp @@ -86,17 +86,15 @@ PView::PView(std::string xname, std::string yname, _init(); PViewDataList *data = new PViewDataList(); for(unsigned int i = 0; i < y.size(); i++){ - double d; if(x.size() == y.size()){ data->SP.push_back(x[i]); } else{ - d = y.size() > 1 ? (double)i / (double)(y.size() - 1) : 0.; + double d = y.size() > 1 ? (double)i / (double)(y.size() - 1) : 0.; data->SP.push_back(d); } - d = 0.; - data->SP.push_back(d); - data->SP.push_back(d); + data->SP.push_back(0.); + data->SP.push_back(0.); data->SP.push_back(y[i]); data->NbSP++; } -- GitLab