From 56ebc88ed88ef6fa929f21e2cb2d4c21d5502f8a Mon Sep 17 00:00:00 2001 From: Jean-Francois Remacle <jean-francois.remacle@uclouvain.be> Date: Thu, 25 Sep 2008 15:27:58 +0000 Subject: [PATCH] complete field documentation and made it availble in the GUI --- Common/Options.cpp | 6 +- Fltk/Callbacks.cpp | 4 -- Fltk/GUI.cpp | 39 +++++++++---- Fltk/GUI.h | 1 + Mesh/Field.cpp | 142 ++++++++++++++++++++++++++++++++++++--------- Mesh/Field.h | 24 ++++---- 6 files changed, 162 insertions(+), 54 deletions(-) diff --git a/Common/Options.cpp b/Common/Options.cpp index 3389da0605..79dcf62f77 100644 --- a/Common/Options.cpp +++ b/Common/Options.cpp @@ -863,7 +863,11 @@ void Print_OptionsDoc() for(std::map<std::string, FieldOption*>::iterator it2 = f->options.begin(); it2 != f->options.end(); it2++){ fprintf(file, "@item %s\n", it2->first.c_str()); - fprintf(file, "%s\n", it2->second->get_help().c_str()); + std::string val; + it2->second->get_text_representation(val); + fprintf(file, "%s (type: %s; default value: %s)\n", + it2->second->get_description().c_str(), + it2->second->get_type_name().c_str(),val.c_str()); } fprintf(file, "@end table\n"); } diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp index 2185833b9d..841a8c3c82 100644 --- a/Fltk/Callbacks.cpp +++ b/Fltk/Callbacks.cpp @@ -4378,10 +4378,6 @@ void view_field_put_on_view_cb(CALLBACK_ARGS) { Fl_Menu_Button* mb = ((Fl_Menu_Button*)w); Field *field = (Field*)WID->field_editor_group->user_data(); - if(mb->value()==0){ - WID->load_field_view_list(); - return; - } int iView; sscanf(mb->text(), "View [%i]", &iView); if(iView<PView::list.size()){ diff --git a/Fltk/GUI.cpp b/Fltk/GUI.cpp index 1f8d46fd2f..4fe2e9e744 100644 --- a/Fltk/GUI.cpp +++ b/Fltk/GUI.cpp @@ -1563,6 +1563,7 @@ void GUI::update_views() reset_plugin_view_browser(); reset_clip_browser(); reset_external_view_list(); + load_field_view_list(); } // Set animation button @@ -3740,6 +3741,7 @@ void GUI::create_plugin_window(int numview) } // field window + void GUI::update_fields(){ edit_field(GModel::current()->getFields()->get(field_selected_id)); } @@ -3754,7 +3756,7 @@ void GUI::load_field_list(){ Field *field=it->second; std::ostringstream sstream; if(it->first==fields.background_field) - sstream<<"*"; + sstream<<"@b"; sstream<<it->first<<" "<<field->get_name(); field_browser->add(sstream.str().c_str(),field); if(it->second==selected_field) @@ -3857,13 +3859,15 @@ void GUI::load_field_options(){ void GUI::load_field_view_list(){ field_put_on_view_btn->clear(); - field_put_on_view_btn->add("refresh view list"); - if(PView::list.size()){ + if(PView::list.size()>0){ + field_put_on_view_btn->activate(); for(unsigned int i = 0; i < PView::list.size(); i++) { std::ostringstream s; s<<"View ["<<i<<"]"; field_put_on_view_btn->add(s.str().c_str()); } + }else{ + field_put_on_view_btn->deactivate(); } } @@ -3886,8 +3890,15 @@ void GUI::edit_field(Field *f){ field_options_scroll->begin(); int x=field_options_scroll->x(); int yy=field_options_scroll->y()+WB; + field_help_display->clear(); + add_multiline_in_browser(field_help_display,"",f->get_description().c_str()); + field_help_display->add("\n"); + field_help_display->add("@b@cOptions"); for(std::map<std::string,FieldOption*>::iterator it=f->options.begin();it!=f->options.end();it++){ - Fl_Widget *input; + Fl_Widget *input; + field_help_display->add(("@b"+it->first).c_str()); + field_help_display->add(("@i"+it->second->get_type_name()).c_str()); + add_multiline_in_browser(field_help_display,"",it->second->get_description().c_str()); switch(it->second->get_type()){ case FIELD_OPTION_INT: case FIELD_OPTION_DOUBLE: @@ -3921,12 +3932,12 @@ void GUI::edit_field(Field *f){ input->align(FL_ALIGN_RIGHT); field_options_widget.push_back(input); yy+=WB+BH; - } + } field_options_scroll->end(); load_field_options(); field_options_scroll->damage(1); - load_field_view_list(); - field_put_on_view_btn->activate(); + if(PView::list.size()>0) + field_put_on_view_btn->activate(); field_delete_btn->activate(); load_field_list(); } @@ -3967,6 +3978,7 @@ void GUI::create_field_window() y+=BH+WB; h-=BH+WB; field_title->labelfont(FL_BOLD); + field_title->labelsize(18); Fl_Tabs *tabs = new Fl_Tabs(x, y , w, h); y+=BH; h-=BH; @@ -3975,23 +3987,28 @@ void GUI::create_field_window() Fl_Group *options_tab= new Fl_Group(x, y, w, h, "Options"); Fl_Scroll *options_scroll = new Fl_Scroll(x, y,w,h-BH-2*WB); field_options_scroll=options_scroll; - options_tab->resizable(options_scroll); options_scroll->end(); Fl_Button* apply_btn = new Fl_Return_Button(x+w - BB ,y+h-BH-WB, BB, BH, "Apply"); Fl_Button *revert_btn = new Fl_Button(x+w-2*BB-WB ,y+h-BH-WB, BB, BH, "Revert"); - field_background_btn = new Fl_Check_Button(x,y+h-BH-WB,(int)(1.5*BB),BH,"Background size"); + field_background_btn = new Fl_Check_Button(x,y+h-BH-WB,(int)(1.5*BB),BH,"Background mesh size"); apply_btn->callback(view_field_apply_cb,this); revert_btn->callback(view_field_revert_cb,this); options_tab->end(); Fl_Group *help_tab= new Fl_Group(x, y, w, h, "Help"); - Fl_Browser *help_browser = new Fl_Browser(x, y+WB, w, h); + field_help_display = new Fl_Browser(x, y+WB, w, h-2*WB); help_tab->end(); tabs->end(); field_editor_group->end(); - field_window->resizable(options_tab); + field_window->resizable(new Dummy_Box(1.5*BB+2*WB,BH+2*WB,width-3*WB-1.5*BB,height-3*BH-5*WB)); + field_editor_group->resizable(tabs); + tabs->resizable(options_tab); + options_tab->resizable(new Dummy_Box(3*BB+4*WB,BH+2*WB,width-9*WB-5*BB,height-3*BH-5*WB)); + /*options_tab->resizable(options_scroll); + field_window->resizable(field_editor_group);*/ field_window->size_range(width0, height0); field_window->position(CTX.field_position[0], CTX.field_position[1]); field_window->end(); + load_field_view_list(); edit_field(NULL); } diff --git a/Fltk/GUI.h b/Fltk/GUI.h index 84e82b1c17..7602f69c3c 100644 --- a/Fltk/GUI.h +++ b/Fltk/GUI.h @@ -209,6 +209,7 @@ public: Fl_Box *field_title; Fl_Check_Button *field_background_btn; Fl_Menu_Button *field_put_on_view_btn; + Fl_Browser *field_help_display; Fl_Button *field_delete_btn; int field_selected_id; diff --git a/Mesh/Field.cpp b/Mesh/Field.cpp index 1876472f33..7cfd2ef31d 100644 --- a/Mesh/Field.cpp +++ b/Mesh/Field.cpp @@ -217,10 +217,27 @@ class StructuredField : public Field &update_needed); text_format = false; options["TextFormat"] = new FieldOptionBool(text_format, "True for ASCII input " - "files, false for binary files", + "files, false for binary files\n" + "(4 bite signed integers for n, double precision floating points for v, D and O)", &update_needed); data = 0; } + std::string get_description(){ + return "Linearly interpolate between data provided on a 3D rectangular unstructured grid.\n" + "The format of the input file is :\n" + "Ox Oy Oz\n" + "Dx Dy Dz\n" + "nx ny nz\n" + "v(0,0,0) v(0,0,1) v(0,0,2) ...\n" + "v(0,1,0) v(0,1,1) v(0,1,2) ...\n" + "v(0,2,0) v(0,2,1) v(0,2,2) ...\n" + "... ... ...\n" + "v(1,0,0) ... ...\n" + "where O are the coordinates of the first node,\n" + "D are the distances between nodes in each direction,\n" + "n are the numbers of nodes in each directions,\n" + "and v are the values on each nodes\n"; + } const char *get_name() { return "Structured"; @@ -306,12 +323,17 @@ class UTMField : public Field double a, b, n, n2, n3, n4, n5, e, e2, e1, e12, e13, e14, J1, J2, J3, J4, Ap, Bp, Cp, Dp, Ep, e4, e6, ep, ep2, ep4, k0, mu_fact; public: + std::string get_description(){ + return "Evaluate Field[IField] in Universal Transverse Mercator coordinates.\n" + "The formulas for the coordinates transformation are taken from\n" + "http://www.uwgb.edu/dutchs/UsefulData/UTMFormulas.HTM\n"; + } UTMField() { field_id = 1; zone = 0; - options["IField"] = new FieldOptionInt(field_id, "Field index"); - options["Zone"] = new FieldOptionInt(zone, ""); + options["IField"] = new FieldOptionInt(field_id, "Index of the field to evaluate"); + options["Zone"] = new FieldOptionInt(zone, "Zone of the UTM projection"); a = 6378137; /* Equatorial Radius */ b = 6356752.3142; /* Rayon Polar Radius */ /* see http://www.uwgb.edu/dutchs/UsefulData/UTMFormulas.HTM */ @@ -384,10 +406,14 @@ class LonLatField : public Field { int field_id; public: + std::string get_description(){ + return "Evaluate Field[IField] in geographic coordinates (longitude,latitude).\n" + "F = Field[IField](arctan(y/x),arcsin(z/sqrt(x^2+y^2+z^2))\n"; + } LonLatField() { field_id = 1; - options["IField"] = new FieldOptionInt(field_id, "Field index"); + options["IField"] = new FieldOptionInt(field_id, "Index of the field to evaluate."); } const char *get_name() { @@ -405,11 +431,15 @@ class BoxField : public Field { double v_in, v_out, x_min, x_max, y_min, y_max, z_min, z_max; public: + std::string get_description(){ + return "The value of this field is VIn inside the box, VOut outside the box.\n" + "The box is given by Xmin<=x<=XMax && YMin<=y<=YMax && ZMin<=z<=ZMax\n"; + } BoxField() { v_in = v_out = x_min = x_max = y_min = y_max = z_min = z_max = 0; - options["VIn"] = new FieldOptionDouble(v_in, "Element size inside the box"); - options["VOut"] = new FieldOptionDouble(v_out, "Element size outside the box"); + options["VIn"] = new FieldOptionDouble(v_in, "Value inside the box"); + options["VOut"] = new FieldOptionDouble(v_out, "Value outside the box"); options["XMin"] = new FieldOptionDouble(x_min, "Minimum X coordinate of the box"); options["XMax"] = new FieldOptionDouble(x_max, "Maximum X coordinate of the box"); options["YMin"] = new FieldOptionDouble(y_min, "Minimum Y coordinate of the box"); @@ -438,6 +468,11 @@ class ThresholdField : public Field { return "Threshold"; } + std::string get_description(){ + return "F = LCMin if Field[IField] <= DistMin\n" + "F = LCMax if Field[IField] >= DistMax\n" + "F = Interpolation between LcMin and LcMax if DistMin<Field[IField]<DistMax\n"; + } ThresholdField() { iField = 0; @@ -447,7 +482,7 @@ class ThresholdField : public Field lcmax = 1; sigmoid = false; stopAtDistMax = false; - options["IField"] = new FieldOptionInt(iField, "Field index"); + options["IField"] = new FieldOptionInt(iField, "Index of the field to evaluate"); options["DistMin"] = new FieldOptionDouble(dmin, "Distance from entity up to which " "element size will be LcMin"); options["DistMax"] = new FieldOptionDouble(dmax, "Distance from entity after which" @@ -458,7 +493,7 @@ class ThresholdField : public Field "and LcMax using a sigmoid, false to " "interpolate linearly"); options["StopAtDistMax"] = new FieldOptionBool(stopAtDistMax, "True to not impose " - "element size outside DistMax"); + "element size outside DistMax (i.e. F = a very big value if Field[IField]>DistMax)"); } double operator() (double x, double y, double z) { @@ -490,14 +525,18 @@ class GradientField : public Field { return "Gradient"; } + std::string get_description(){ + return "Compute the finite difference gradient of Field[IField].\n" + "F = (Field[IField](X + Delta/2) - Field[IField](X - Delta/2))/Delta\n"; + } GradientField() : iField(0), kind(3), delta(CTX.lc / 1e4) { iField = 1; kind = 0; delta = 0.; options["IField"] = new FieldOptionInt(iField, "Field index"); - options["Kind"] = new FieldOptionInt(kind, "0 for X, 1 for Y, 2 for Z, 3 for norm"); - options["Delta"] = new FieldOptionDouble(delta, ""); + options["Kind"] = new FieldOptionInt(kind, "Component of the gradient to evaluate : 0 for X, 1 for Y, 2 for Z, 3 for the norm"); + options["Delta"] = new FieldOptionDouble(delta, "Finite difference step"); } double operator() (double x, double y, double z) { @@ -542,12 +581,16 @@ class CurvatureField : public Field { return "Curvature"; } + std::string get_description(){ + return "Compute the curvature of Field[IField].\n" + "F = divergence( || grad( Field[IField] ) || )"; + } CurvatureField() : iField(0), delta(CTX.lc / 1e4) { iField = 1; delta = 0.; options["IField"] = new FieldOptionInt(iField, "Field index"); - options["Delta"] = new FieldOptionDouble(delta, ""); + options["Delta"] = new FieldOptionDouble(delta, "Step of the finite differences"); } void grad_norm(Field &f,double x,double y,double z, double *g) { @@ -590,12 +633,18 @@ class MaxEigenHessianField : public Field { return "MaxEigenHessian"; } + std::string get_description(){ + return "Compute the maximum eigen value of the Hessian matrix of Field[IField].\n" + "F = max ( eigenvalues ( grad ( grad ( Field[IField] ) ) ) )\n" + "Gradients are evaluated by finite differences,\n" + "eigenvalues are computed using the GSL library.\n"; + } MaxEigenHessianField() : iField(0), delta(CTX.lc / 1e4) { iField = 1; delta = 0.; options["IField"] = new FieldOptionInt(iField, "Field index"); - options["Delta"] = new FieldOptionDouble(delta, ""); + options["Delta"] = new FieldOptionDouble(delta, "Step used for the finite differences"); gslwork = gsl_eigen_symm_alloc(3); eigenvalues = gsl_vector_alloc(3); gslmat = gsl_matrix_alloc(3, 3); @@ -650,12 +699,19 @@ class LaplacianField : public Field { return "Laplacian"; } + std::string get_description(){ + return "Compute finite difference the Laplacian of Field[IField].\n" + "F = divergence(gradient(Field[IField]))\n" + "F = G(x+d,y,z)+G(x-d,y,z)+G(x,y+d,z)+G(x,y-d,z)+\n" + "\t+G(x,y,z+d)+G(x,y,z-d)-6*G(x,y,z)\n" + "where G=Field[IField] and d=delta\n"; + } LaplacianField() : iField(0), delta(CTX.lc / 1e4) { iField = 1; - delta = 0.; + delta = 0.1; options["IField"] = new FieldOptionInt(iField, "Field index"); - options["Delta"] = new FieldOptionDouble(delta, ""); + options["Delta"] = new FieldOptionDouble(delta, "Finite difference step"); } double operator() (double x, double y, double z) { @@ -677,12 +733,18 @@ class MeanField : public Field { return "Mean"; } + std::string get_description(){ + return "Very simple smoother.\n" + "F = (G(x+delta,y,z)+G(x-delta,y,z)\n" + "\t+G(x,y+delta,z)+G(x,y-delta,z)\n" + "\t+G(x,y,z+delta)+G(x,y,z-delta)\n" + "\t+G(x,y,z))/7\n" + "where G=Field[IField]\n"; + } MeanField() : iField(0), delta(CTX.lc / 1e4) { - iField = 1; - delta = 0.; options["IField"] = new FieldOptionInt(iField, "Field index"); - options["Delta"] = new FieldOptionDouble(delta, ""); + options["Delta"] = new FieldOptionDouble(delta, "Distance used to compute the mean value"); } double operator() (double x, double y, double z) { @@ -691,7 +753,7 @@ class MeanField : public Field return ((*field) (x + delta , y, z) + (*field) (x - delta, y, z) + (*field) (x, y + delta, z) + (*field) (x, y - delta, z) + (*field) (x, y, z + delta) + (*field) (x, y, z - delta) - + (*field) (x, y, z)) / 5; + + (*field) (x, y, z)) / 7; } }; @@ -794,9 +856,8 @@ class MathEvalField : public Field public: MathEvalField() { - options["F"] = new FieldOptionString(f, "Mathematical function (possible arguments: " - "x, y, z for spatial coordinates or F0, F1, " - "..., for field values)", &update_needed); + options["F"] = new FieldOptionString(f, "Mathematical function to evaluate.", &update_needed); + f="F2 + Sin(z)\n"; } double operator() (double x, double y, double z) { @@ -812,6 +873,13 @@ class MathEvalField : public Field { return "MathEval"; } + std::string get_description(){ + return "Evaluate a mathematical expression.\n" + "The expression can contains x, y, z for spatial coordinates, F0, F1, ... for field values,\n" + "and the mathematical functions supported by the gmsh parser.\n" + "Example : F2 + Sin(z)\n" + "This evaluator is based on a modified version of the GNU libmatheval library."; + } }; class ParametricField : public Field @@ -831,6 +899,11 @@ class ParametricField : public Field options["FZ"] = new FieldOptionString(f[2], "Z component of parametric function", &update_needed); } + std::string get_description(){ + return "Evaluate Field IField in parametric coordinate\n" + "F = Field[IField](FX,FY,FZ)\n" + "See MathEval Field help to get a description of valid FX, FY and FZ expression\n"; + } double operator() (double x, double y, double z) { if(update_needed) { @@ -902,6 +975,9 @@ class PostViewField : public Field { return "PostView"; } + std::string get_description(){ + return "Evaluate the post processing view IView\n"; + } PostViewField() { octree = 0; @@ -926,6 +1002,9 @@ class MinField : public Field options["FieldsList"] = new FieldOptionList(idlist, "Field indices", &update_needed); } + std::string get_description(){ + return "Take the minimum value of a list of fields.\n"; + } double operator() (double x, double y, double z) { double v = MAX_LC; @@ -950,6 +1029,9 @@ class MaxField : public Field options["FieldsList"] = new FieldOptionList(idlist, "Field indices", &update_needed); } + std::string get_description(){ + return "Take the maximum value of a list of fields.\n"; + } double operator() (double x, double y, double z) { double v = -MAX_LC; @@ -981,14 +1063,14 @@ class AttractorField : public Field index = new ANNidx[1]; dist = new ANNdist[1]; n_nodes_by_edge = 20; - options["NodesList"] = new FieldOptionList(nodes_id, "Identification numbers of " - "points in the model", + options["NodesList"] = new FieldOptionList(nodes_id, "Indices of " + "nodes in the geomtric model", &update_needed); - options["EdgesList"] = new FieldOptionList(edges_id, "Identification numbers of " - "curves in the model", + options["EdgesList"] = new FieldOptionList(edges_id, "Indices of " + "curves in the geometric model", &update_needed); - options["NNodesByEdge"] = new FieldOptionInt(n_nodes_by_edge, "Number of attractor " - "nodes per curve", + options["NNodesByEdge"] = new FieldOptionInt(n_nodes_by_edge, "Number of nodes " + "used to discetized each curve", &update_needed); } ~AttractorField() @@ -1004,6 +1086,12 @@ class AttractorField : public Field { return "Attractor"; } + std::string get_description(){ + return "Compute the distance from the nearest node in a list.\n" + "It can also be used to compute distance from curves, in this case each curve is replaced" + "by NNodesByEdge equidistant nodes and the distance from those nodes is computed.\n" + "The ANN library is used to find the nearest node : http://www.cs.umd.edu/~mount/ANN/\n"; + } virtual double operator() (double X, double Y, double Z) { if(update_needed) { diff --git a/Mesh/Field.h b/Mesh/Field.h index a9c905a6a3..af6966a25d 100644 --- a/Mesh/Field.h +++ b/Mesh/Field.h @@ -37,19 +37,18 @@ class FieldOption { virtual ~FieldOption() {} virtual FieldOptionType get_type() = 0; virtual void get_text_representation(std::string & v_str) = 0; - virtual std::string get_help() - { - std::string val, typ; - get_text_representation(val); + virtual std::string get_description(){ + return _help; + } + std::string get_type_name(){ switch(get_type()){ - case FIELD_OPTION_INT: typ = "integer"; break; - case FIELD_OPTION_DOUBLE: typ = "float"; break; - case FIELD_OPTION_BOOL: typ = "boolean"; break; - case FIELD_OPTION_PATH: typ = "path"; break; - case FIELD_OPTION_STRING: typ = "string"; break; - case FIELD_OPTION_LIST: typ = "list"; break; + case FIELD_OPTION_INT: return "integer"; break; + case FIELD_OPTION_DOUBLE: return "float"; break; + case FIELD_OPTION_BOOL: return "boolean"; break; + case FIELD_OPTION_PATH: return "path"; break; + case FIELD_OPTION_STRING: return "string"; break; + case FIELD_OPTION_LIST: return "list"; break; } - return _help + " (type: " + typ + "; default value: " + val + ")"; } virtual void numerical_value(double val) { throw(1); } virtual double numerical_value() const { throw(1); } @@ -71,6 +70,9 @@ class Field { #if !defined(HAVE_NO_POST) void put_on_view(PView * view, int comp = -1); #endif + virtual std::string get_description(){ + return ""; + } }; class FieldFactory { -- GitLab