MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/mpm/plotxy.h
Go to the documentation of this file.
00001 /************************************************************************
00002  * MechSys - Open Library for Mechanical Systems                        *
00003  * Copyright (C) 2005 Dorival M. Pedroso                                *
00004  *                                                                      *
00005  * This program is free software: you can redistribute it and/or modify *
00006  * it under the terms of the GNU General Public License as published by *
00007  * the Free Software Foundation, either version 3 of the License, or    *
00008  * any later version.                                                   *
00009  *                                                                      *
00010  * This program is distributed in the hope that it will be useful,      *
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the         *
00013  * GNU General Public License for more details.                         *
00014  *                                                                      *
00015  * You should have received a copy of the GNU General Public License    *
00016  * along with this program. If not, see <http://www.gnu.org/licenses/>  *
00017  ************************************************************************/
00018 
00019 /* plot-xy - Copyright (C) 2007 Dorival de Moraes Pedroso */
00020 
00021 #ifndef MPM_PLOTXY_H
00022 #define MPM_PLOTXY_H
00023 
00024 // STL
00025 #include <cmath>   // for ceil and floor
00026 #include <cfloat>  // for DBL_EPSILON
00027 #include <cstring> // for strncpy
00028 #include <iostream>
00029 
00030 // FLTK
00031 #include <FL/Fl.H>
00032 #include <FL/Fl_Group.H>
00033 #include <FL/fl_draw.H>
00034 #include <FL/Enumerations.H> // for Fl_Color
00035 
00036 // MechSys
00037 #include <mechsys/util/array.h>
00038 #include <mechsys/util/fatal.h>
00039 
00040 // Local
00041 #include <mechsys/mpm/defs.h>
00042 
00043 namespace MPM {
00044 
00045 /* Plot XY. */
00046 class PlotXY : public Fl_Group
00047 {
00048 public:
00049     // Constants
00050     static double MINZERO; 
00051     
00052     /* Constructor. */
00053     PlotXY (int xmin, int ymin, int width, int height, char const * Title=NULL, char const * Xlbl=NULL, char const * Ylbl=NULL); // Screen coordinates
00054 
00055     /* Destructor. */
00056     virtual ~PlotXY () {}
00057 
00058     // Methods
00059     void         AddCurve   (char const * Name);                                                   
00060     void         AddCurve   (Array<double> const * X, Array<double> const * Y, char const * Name); 
00061     void         SetXY      (size_t i, Array<double> const * X, Array<double> const * Y);             
00062     void         DelCurve   (size_t i);                                                               
00063     CurveProps & SetCurve   (size_t i);
00064     void         CalcSF     ();                                                                    
00065     void         DrawRulers ();                                                                    
00066     void         DrawLegend ();                                                                    
00067 
00068     // Set methods
00069     PlotXY & EqScales     (bool EQScales=true) { _eqsf=EQScales;  return (*this); } 
00070     PlotXY & RecalcSF     (bool REcalcSF=true) { _recsf=REcalcSF; return (*this); } 
00071     PlotXY & WithFrame    (bool WFrame  =true) { _wframe=WFrame;  return (*this); } 
00072     PlotXY & BRuler       (bool Visible =true, int nTicks=10);                      
00073     PlotXY & LRuler       (bool Visible =true, int nTicks=10);                      
00074     PlotXY & SetBTicksFmt (char const * Fmt="%4.1f", int Size=5);                   
00075     PlotXY & SetLTicksFmt (char const * Fmt="%3.1f", int Size=5);                   
00076 
00077     /* Draw method (internal). */
00078     void draw ();
00079 
00080 private:
00081     // Data
00082     double _sfX;        
00083     double _sfY;        
00084     bool   _eqsf;       
00085     bool   _recsf;      
00086     bool   _sfok;       
00087     bool   _wframe;     
00088     double _Xmin;       
00089     double _Ymin;       
00090     double _Xmax;       
00091     double _Ymax;       
00092     int    _lrt;        
00093     int    _rrt;        
00094     int    _brt;        
00095     int    _trt;        
00096     int    _hb;         
00097     int    _vb;         
00098     int    _bnt;        
00099     int    _lnt;        
00100     int    _ticfsz;     
00101     int    _lblfsz;     
00102     int    _titfsz;     
00103     char   _btifmt[16]; 
00104     char   _ltifmt[16]; 
00105     char   _title[256]; 
00106     char   _blbl[64];   
00107     char   _llbl[64];   
00108     int    _blegh;      
00109     int    _rlegw;      
00110     int    _bhpad;      
00111     int    _bvpad;      
00112     int    _pahpad;     
00113     int    _pavpad;     
00114     bool   _legatbot;   
00115     bool   _cptbr;      
00116 
00117     // Curves
00118     Array<Array<double> const*> _X; 
00119     Array<Array<double> const*> _Y; 
00120     Array<CurveProps>           _C; 
00121 
00122     // Private Methods
00123     int  _x      (double X) const { return static_cast<int>((x()+1+_lrt+_hb)              +_sfX*(X-_Xmin)); } 
00124     int  _y      (double Y) const { return static_cast<int>((y()+1+_trt+_vb)+(h()-_pavpad)-_sfY*(Y-_Ymin)); } 
00125     int  _l      (double L) const { return static_cast<int>((_sfX>_sfY?_sfY:_sfX)*L); } 
00126     void _pretty (double Lo, double Hi, int nDiv, Array<double> & Vals);                
00127 
00128 }; // class PlotXY
00129 
00130 double PlotXY::MINZERO = sqrt(DBL_EPSILON);
00131 
00132 
00134 
00135 
00136 /* public */
00137 
00138 inline PlotXY::PlotXY(int xmin, int ymin, int width, int height, char const * Title, char const * Xlbl, char const * Ylbl)
00139     : Fl_Group (xmin,ymin,width,height,0),
00140       _sfX      (1.0),
00141       _sfY      (1.0),
00142       _eqsf     (false),
00143       _recsf    (true),
00144       _sfok     (false),
00145       _wframe   (true),
00146       _Xmin     (0.0),
00147       _Ymin     (0.0),
00148       _Xmax     (1.0),
00149       _Ymax     (1.0),
00150       _hb       (6),
00151       _vb       (6),
00152       _bnt      (5),
00153       _lnt      (5),
00154       _ticfsz   (10),
00155       _lblfsz   (12),
00156       _titfsz   (14),
00157       _blegh    (16),
00158       _rlegw    (0),
00159       _legatbot (true),
00160       _cptbr    (true)
00161 {
00162     end();
00163 
00164     // Set dependent constants
00165     _lrt    = 40;                     // left ruler
00166     _rrt    = 0+5;                    // +5 to account for the width of the bottom tick text
00167     _brt    = (_cptbr?20:20+_ticfsz); // +_ticfsz to account for the label
00168     _trt    = 18;                     // area for the title
00169     _bhpad  = _lrt+_rrt+_rlegw;       // border horizontal padding
00170     _bvpad  = _brt+_trt+_blegh;       // border vertical padding
00171     _pahpad = _bhpad+2+2*_hb;         // plot-area horizontal padding
00172     _pavpad = _bvpad+2+2*_vb;         // plot-area vertical padding
00173 
00174     // Set tick number formats
00175     strncpy (_btifmt, "%g", 2);  _btifmt[2]='\0';
00176     strncpy (_ltifmt, "%g", 2);  _ltifmt[2]='\0';
00177 
00178     // Set title
00179     if (Title==NULL) { strncpy (_title, "X-Y plot", 8); _title[8]='\0'; }
00180     else               strncpy (_title, Title, 256);
00181 
00182     // Set x-label
00183     if (Xlbl==NULL) { strncpy (_blbl, "X", 1); _blbl[1]='\0'; }
00184     else              strncpy (_blbl, Xlbl, 64);
00185 
00186     // Set y-label
00187     if (Ylbl==NULL) { strncpy (_llbl, "Y", 1);  _llbl[1]='\0'; }
00188     else              strncpy (_llbl, Ylbl, 64);
00189     
00190 }
00191 
00192 inline void PlotXY::AddCurve(char const * Name)
00193 {
00194     // Default properties
00195     CurveProps cp = { CT_POINTS, FL_BLACK, FL_SOLID, 1, 1, _hb*2 };
00196     snprintf (cp.Nam, 256, "%s", Name);
00197 
00198     // Add curve
00199     _X.Push(NULL);
00200     _Y.Push(NULL);
00201     _C.Push(cp);
00202 }
00203 
00204 inline void PlotXY::AddCurve(Array<double> const * X, Array<double> const * Y, char const * Name)
00205 {
00206     // Check
00207     if (Y->Size()!=X->Size())
00208         throw new Fatal("PlotXY::AddCurve: X (sz=%d) and Y (sz=%d) arrays must have the same size",X->Size(), Y->Size());
00209 
00210     // Default properties
00211     CurveProps cp = { CT_POINTS, FL_BLACK, FL_SOLID, 1, 1, _hb*2 };
00212     snprintf (cp.Nam, 256, "%s", Name);
00213 
00214     // Add curve
00215     _X.Push(X);
00216     _Y.Push(Y);
00217     _C.Push(cp);
00218 }
00219 
00220 inline void PlotXY::SetXY(size_t i, Array<double> const * X, Array<double> const * Y)
00221 {
00222     // Check
00223     if (i<0 || i>=_X.Size())
00224         throw new Fatal("PlotXY::SetXY: There is no Curve # %d added to this object",i);
00225 
00226     // Check
00227     if (X!=NULL && Y!=NULL)
00228     {
00229         if (Y->Size()!=X->Size())
00230             throw new Fatal("PlotXY::SetXY: X (sz=%d) and Y (sz=%d) arrays must have the same size",X->Size(), Y->Size());
00231     }
00232 
00233     // Set curve
00234     _X[i] = X;
00235     _Y[i] = Y;
00236 }
00237 
00238 inline void PlotXY::DelCurve(size_t i)
00239 {
00240     // Check
00241     if (i<0 || i>=_X.Size())
00242         throw new Fatal("PlotXY::DelCurve: There is no Curve # %d added to this object",i);
00243 
00244     // Remove
00245     _X.DelItem(i);
00246     _Y.DelItem(i);
00247     _C.DelItem(i);
00248 }
00249 
00250 inline CurveProps & PlotXY::SetCurve(size_t i)
00251 {
00252     // Check
00253     if (i<0 || i>=_X.Size())
00254         throw new Fatal("PlotXY::SetCurve: There is no Curve # %d added to this object",i);
00255     
00256     // Return properties
00257     return _C[i];
00258 }
00259 
00260 inline void PlotXY::CalcSF()
00261 {
00262     _Xmin = 0.0;
00263     _Ymin = 0.0;
00264     _Xmax = 1.0;
00265     _Ymax = 1.0;
00266     size_t k = 0;
00267     while (k<_X.Size())
00268     {
00269         // Check input
00270         if (_X[k]==NULL)     break;
00271         if (_Y[k]==NULL)     break;
00272         if (_X[k]->Size()<2) break;
00273         if (_Y[k]->Size()<2) break;
00274 
00275         // Bounding box
00276         if (k==0)
00277         {
00278             _Xmin = (*_X[k])[0];
00279             _Ymin = (*_Y[k])[0];
00280             _Xmax = (*_X[k])[1];
00281             _Ymax = (*_Y[k])[1];
00282         }
00283         for (size_t i=0; i<_X[k]->Size(); ++i)
00284         {
00285             if ((*_X[k])[i]<_Xmin) _Xmin = (*_X[k])[i];
00286             if ((*_Y[k])[i]<_Ymin) _Ymin = (*_Y[k])[i];
00287             if ((*_X[k])[i]>_Xmax) _Xmax = (*_X[k])[i];
00288             if ((*_Y[k])[i]>_Ymax) _Ymax = (*_Y[k])[i];
00289         }
00290 
00291         // Next curve
00292         k++;
00293     }
00294 
00295     // Scale factors
00296     if (fabs(_Xmax-_Xmin)<=DBL_EPSILON)
00297     {
00298         Array<double> lim;
00299         _pretty (_Xmin, _Xmax, 3, lim);
00300         _Xmin = lim[0];
00301         _Xmax = lim[lim.Size()-1];
00302     }
00303     if (fabs(_Ymax-_Ymin)<=DBL_EPSILON)
00304     {
00305         Array<double> lim;
00306         _pretty (_Ymin, _Ymax, 3, lim);
00307         _Ymin = lim[0];
00308         _Ymax = lim[lim.Size()-1];
00309     }
00310     _sfX = static_cast<double>((w()-_pahpad)/(_Xmax-_Xmin));
00311     _sfY = static_cast<double>((h()-_pavpad)/(_Ymax-_Ymin));
00312     if (_eqsf)
00313     {
00314         double sf = (_sfX>_sfY ? _sfY : _sfX);
00315         _sfX = sf;
00316         _sfY = sf;
00317     }
00318 }
00319 
00320 inline void PlotXY::DrawRulers()
00321 {
00322     if (_brt>0) // bottom ruler
00323     {
00324         // variables
00325         int yi = y()+h()-_brt-_blegh;  // initial y-position (screen coordinates)
00326         int X  = x()+_lrt;             // position
00327         int W  = w()-_rlegw-_lrt-_rrt; // width
00328 
00329         // background
00330         fl_color (FL_WHITE);
00331         fl_rectf (x(), yi, w(), _brt);
00332 
00333         // ticks
00334         const int     len = 9;                     // tick length
00335         Array<double> ticks;                       // ticks position
00336         char          buf[256];                    // buffer for ticks text
00337         _pretty       (_Xmin, _Xmax, _bnt, ticks); // find ticks position
00338         fl_color      (FL_BLACK);                  // set color
00339         fl_line_style (FL_SOLID, 1);               // set line style
00340         fl_font       (0,_ticfsz);                 // set font for ticks
00341         for (size_t i=0; i<ticks.Size(); ++i)
00342         {
00343             int xi = _x(ticks[i]);                  // tick initial x-position (screen coordinates)
00344             if (xi>=X && xi<=X+W)
00345             {
00346                 snprintf (buf, 256, _btifmt, ticks[i]); // format text
00347                 fl_line  (xi, yi, xi, yi+len);          // draw tick mark
00348                 fl_draw  (buf, xi, yi+len+_ticfsz/2+1, 0, 0, FL_ALIGN_CENTER); // draw tick text
00349             }
00350         }
00351 
00352         // label 
00353         if (!_cptbr) fl_draw (_blbl, X+W/2, yi+len+3*_ticfsz/2+1, 0, 0, FL_ALIGN_CENTER); // draw label
00354     }
00355     if (_lrt>0) // left ruler
00356     {
00357         // variables
00358         int Y = y()+_trt;             // position
00359         int H = h()-_trt-_brt-_blegh; // height
00360 
00361         // background
00362         fl_color (FL_WHITE);
00363         fl_rectf (x(), Y, _lrt, H);
00364 
00365         // ticks
00366         const int     len = 9;                     // tick length
00367         Array<double> ticks;                       // ticks position
00368         char          buf[256];                    // buffer for ticks text
00369         _pretty       (_Ymin, _Ymax, _lnt, ticks); // find ticks position
00370         fl_color      (FL_BLACK);                  // set color
00371         fl_line_style (FL_SOLID, 1);               // set line style
00372         fl_font       (0,_ticfsz);                 // set font for ticks
00373         for (size_t i=0; i<ticks.Size(); ++i)
00374         {
00375             int xi = x()+_lrt-len;                  // tick initial x-position (screen coordinates)
00376             int yi = _y(ticks[i]);                  // tick initial y-position (screen coordinates)
00377             if (yi>=Y && yi<=Y+H)
00378             {
00379                 snprintf (buf, 256, _ltifmt, ticks[i]); // format text
00380                 fl_line  (xi, yi, xi+len, yi);          // draw tick mark
00381                 fl_draw  (buf, x()+_lrt-len-2, yi, 0, 0, FL_ALIGN_RIGHT); // draw tick text
00382             }
00383         }
00384     }
00385     if (_trt>0) // top ruler
00386     {
00387         // background
00388         fl_color (FL_WHITE);
00389         fl_rectf (x(), y(), w(), _trt); // (x()+_lrt, y(), w()-_rrt-_lrt, _trt)
00390 
00391         // left ruler label and title
00392         fl_color (FL_BLACK);                 // set color
00393         fl_font  (0,_lblfsz);                // set font for label
00394         fl_draw  (_llbl, x()+2, y()+_trt-2); // draw left label
00395         fl_font  (0,_titfsz);                // set font for title
00396         fl_draw  (_title, x()+w()/2, y()+_trt-_titfsz/2-2, 0, 0, FL_ALIGN_CENTER); // draw title
00397     }
00398     if (_rrt>0) // right ruler
00399     {
00400         // background
00401         fl_color (FL_WHITE);
00402         fl_rectf (x()+w()-_rrt-_rlegw, y()+_trt, _rrt, h()-_trt-_brt-_blegh);
00403     }
00404 }
00405 
00406 inline void PlotXY::DrawLegend()
00407 {
00408     // Variables
00409     char buf[256];
00410     int  xi   = x()+5;
00411     int  yi   = y()+h()-_blegh/2;
00412     int  len  = 30; // line length
00413     int  tlen = 30; // text width
00414     int  nc   = _X.Size(); // number of curves
00415     int  ilen = 5+len+2+tlen; // icon length
00416     int  dx   = (_cptbr ? 20 : static_cast<int>(static_cast<double>(w()-ilen*nc)/static_cast<double>(nc-1)));
00417     int  xf   = xi+30;
00418 
00419     // Draw legend
00420     fl_font (0,_lblfsz); // set font for labels
00421     if (_legatbot) // bottom legend
00422     {
00423         // background
00424         fl_color (FL_WHITE);
00425         fl_rectf (x(), y()+h()-_blegh, w(), _blegh);
00426 
00427         // Draw legend
00428         if (_X.Size()>=1 && _Y.Size()>=1)
00429         {
00430             size_t k = 0;
00431             while (k<_X.Size())
00432             {
00433                 // Check
00434                 if (_X[k]==NULL || _Y[k]==NULL) return;
00435                 if (_X[k]->Size()!=_Y[k]->Size())
00436                     throw new Fatal("PlotXY::DrawLegend(): (%s) X(%s)[%d] and Y(%s)[%d] must have the same size",_title,_blbl,_X[k]->Size(),_llbl,_Y[k]->Size());
00437                 
00438                 // Draw points
00439                 if (_C[k].Typ==CT_POINTS || _C[k].Typ==CT_BOTH)
00440                 {
00441                     fl_color      (_C[k].Clr);
00442                     fl_line_style (FL_SOLID, 1);
00443                     if (_C[k].Pch==1) // Open circle
00444                     {
00445                         fl_circle (xi+len/2, yi, _C[k].Psz/2);
00446                     }
00447                     else if (_C[k].Pch==16) // Filled circle
00448                     {
00449                         int r = _C[k].Psz/2;
00450                         for (size_t i=0; i<_X[k]->Size(); ++i)
00451                             fl_pie (xi+len/2-r, yi-r, 2*r+1, 2*r+1, 0,360);
00452                     }
00453                 }
00454 
00455                 // Draw lines
00456                 if (_C[k].Typ==CT_LINES || _C[k].Typ==CT_BOTH)
00457                 {
00458                     if (_X[k]->Size()>1)
00459                     {
00460                         fl_color      (_C[k].Clr);
00461                         fl_line_style (_C[k].Lty, _C[k].Lwd);
00462                         fl_line       (xi, yi, xf, yi);
00463                     }
00464                 }
00465 
00466                 // Draw names
00467                 snprintf (buf, 256, "%s", _C[k].Nam); // format text
00468                 fl_color (FL_BLACK);
00469                 fl_draw  (buf, xf+2, yi, 0, 0, FL_ALIGN_LEFT); // draw name
00470 
00471                 // Next curve
00472                 xi += ilen+dx;
00473                 xf  = xi+len;
00474                 k++;
00475             }
00476         }
00477         if (_cptbr) fl_draw (_blbl, x()+w()-3, y()+h()-_ticfsz/2-3, 0, 0, FL_ALIGN_RIGHT); // draw label
00478     }
00479     else
00480     {
00481     }
00482 }
00483 
00484 inline PlotXY & PlotXY::BRuler(bool Visible, int nTicks)
00485 {
00486     _brt = (Visible ? 27+12 : 0); // +12 to account for the label
00487     _bnt = nTicks;
00488     return (*this);
00489 }
00490 
00491 inline PlotXY & PlotXY::LRuler(bool Visible, int nTicks)
00492 {
00493     _lrt = (Visible ? 27 : 0);
00494     _lnt = nTicks;
00495     return (*this);
00496 }
00497 
00498 inline PlotXY & PlotXY::SetBTicksFmt(char const * Fmt, int Size)
00499 {
00500     strncpy (_btifmt, Fmt, Size);  _btifmt[Size]='\0';
00501     return (*this);
00502 }
00503 
00504 inline PlotXY & PlotXY::SetLTicksFmt(char const * Fmt, int Size)
00505 {
00506     strncpy (_ltifmt, Fmt, Size);  _ltifmt[Size]='\0';
00507     return (*this);
00508 }
00509 
00510 inline void PlotXY::draw()
00511 {
00512     // Clear the background
00513     fl_color (FL_WHITE);
00514     fl_rectf (x()+_lrt, y()+_trt, w()-_bhpad, h()-_bvpad);
00515 
00516     // Set clipping in order to avoid drawing outside drawing area
00517     fl_push_clip (x(), y(), w(), h());
00518 
00519     // Calculate scale factors and draw rulers
00520     if (_recsf || !_sfok)
00521     {
00522         CalcSF     ();
00523         DrawRulers ();
00524         DrawLegend ();
00525         _sfok = true;
00526     }
00527 
00528     // Draw Curves
00529     if (_X.Size()>=1 && _Y.Size()>=1)
00530     {
00531         size_t k = 0;
00532         while (k<_X.Size())
00533         {
00534             // Check
00535             if (_X[k]==NULL || _Y[k]==NULL) break;
00536             if (_X[k]->Size()!=_Y[k]->Size())
00537                 throw new Fatal("PlotXY::draw(): (%s) X(%s)[%d] and Y(%s)[%d] must have the same size",_title,_blbl,_X[k]->Size(),_llbl,_Y[k]->Size());
00538             
00539             // Draw points
00540             if (_C[k].Typ==CT_POINTS || _C[k].Typ==CT_BOTH)
00541             {
00542                 fl_color      (_C[k].Clr);
00543                 fl_line_style (FL_SOLID, 1);
00544                 if (_C[k].Pch==1) // Open circle
00545                 {
00546                     for (size_t i=0; i<_X[k]->Size(); ++i)
00547                         fl_circle (_x((*_X[k])[i]), _y((*_Y[k])[i]), _C[k].Psz/2);
00548                 }
00549                 else if (_C[k].Pch==16) // Filled circle
00550                 {
00551                     int r = _C[k].Psz/2;
00552                     for (size_t i=0; i<_X[k]->Size(); ++i)
00553                         fl_pie (_x((*_X[k])[i])-r, _y((*_Y[k])[i])-r, 2*r+1, 2*r+1, 0,360);
00554                 }
00555             }
00556 
00557             // Draw lines
00558             if (_C[k].Typ==CT_LINES || _C[k].Typ==CT_BOTH)
00559             {
00560                 if (_X[k]->Size()>1)
00561                 {
00562                     fl_color      (_C[k].Clr);
00563                     fl_line_style (_C[k].Lty, _C[k].Lwd);
00564                     for (size_t i=0; i<_X[k]->Size()-1; ++i)
00565                         fl_line (_x((*_X[k])[i]), _y((*_Y[k])[i]), _x((*_X[k])[i+1]), _y((*_Y[k])[i+1]));
00566 
00567 
00568                     char buf[256];
00569                     //snprintf (buf, 250, "%g, %g", (*_X[k])[_X[k]->Size()-1], (*_Y[k])[_X[k]->Size()-1]);
00570                     snprintf (buf, 250, "y=%g", (*_Y[k])[_X[k]->Size()-1]);
00571                     fl_color (FL_BLACK);
00572                     fl_font  (0, 10);
00573                     fl_draw  (buf, _x((*_X[k])[_X[k]->Size()-1]), _y((*_Y[k])[_X[k]->Size()-1]), 0,0, FL_ALIGN_RIGHT);
00574 
00575 
00576                 }
00577             }
00578 
00579             // Next curve
00580             k++;
00581         }
00582     }
00583 
00584     // Draw border
00585     fl_color      (FL_BLACK);
00586     fl_line_style (FL_SOLID, 1);
00587     fl_rect       (x()+_lrt, y()+_trt, w()-_bhpad, h()-_bvpad);
00588 
00589     // Draw an all-around frame
00590     if (_wframe) fl_rect (x(), y(), w(), h());
00591 
00592     // Pop clipping
00593     fl_pop_clip ();
00594 }
00595 
00596 
00597 /* private */
00598 inline void PlotXY::_pretty(double Lo, double Hi, int nDiv, Array<double> & Vals)
00599 {
00600     // Constants
00601     const double rounding_eps   = 1.0e-7;
00602     const double eps_correction = 0.0;
00603     const double shrink_sml     = 0.75;
00604     const double h              = 1.5;
00605     const double h5             = 0.5+1.5*h;
00606 
00607     // Local variables
00608     int    min_n = static_cast<int>(nDiv)/static_cast<int>(3);
00609     double lo    = Lo;
00610     double hi    = Hi;
00611     double dx    = hi-lo;
00612     double cell  = 1;    // cell := "scale" here
00613     double ub    = 0;    // upper bound on cell/unit
00614     bool   isml  = true; // is small ?
00615 
00616     // Check range
00617     if (!(dx==0 && hi==0)) // hi=lo=0
00618     {
00619         cell = (fabs(lo)>fabs(hi) ? fabs(lo) : fabs(hi));
00620         ub   = (1+(h5>=1.5*h+.5) ? 1/(1+h) : 1.5/(1+h5));
00621         isml = (dx<cell*ub*(nDiv>1 ? nDiv : 1)*DBL_EPSILON*3); // added times 3, as several calculations here
00622     }
00623 
00624     // Set cell
00625     if (isml)
00626     {
00627         if (cell>10) cell = 9 + cell/10;
00628         cell *= shrink_sml;
00629         if (min_n>1) cell /= min_n;
00630     }
00631     else 
00632     {
00633         cell = dx;
00634         if (nDiv>1) cell /= nDiv;
00635     }
00636     if      (cell<20*DBL_MIN) cell = 20*DBL_MIN; // very small range.. corrected
00637     else if (cell*10>DBL_MAX) cell = .1*DBL_MAX; // very large range.. corrected
00638 
00639     // Find base and unit
00640     double base = pow(10., floor(log10(cell))); // base <= cell < 10*base
00641     double unit = base;
00642     if ((ub = 2*base)-cell <  h*(cell-unit)) { unit = ub;
00643     if ((ub = 5*base)-cell < h5*(cell-unit)) { unit = ub;
00644     if ((ub =10*base)-cell <  h*(cell-unit))   unit = ub; }}
00645 
00646     // Find number of 
00647     double ns = floor (lo/unit+rounding_eps);
00648     double nu = ceil  (hi/unit-rounding_eps);
00649     if (eps_correction && (eps_correction>1 || !isml))
00650     {
00651         if (lo) lo *= (1-DBL_EPSILON); else lo = -DBL_MIN;
00652         if (hi) hi *= (1+DBL_EPSILON); else hi = +DBL_MIN;
00653     }
00654     while (ns*unit>lo+rounding_eps*unit) ns--;
00655     while (nu*unit<hi-rounding_eps*unit) nu++;
00656 
00657     // Find number of divisions
00658     int ndiv = static_cast<int>(.5+nu-ns);
00659     if (ndiv<min_n)
00660     {
00661         int k = min_n-ndiv;
00662         if (ns>=0.0)
00663         {
00664             nu += k/2;
00665             ns -= k/2 + k%2;
00666         } 
00667         else
00668         {
00669             ns -= k/2;
00670             nu += k/2 + k%2;
00671         }
00672         ndiv = min_n;
00673     }
00674     ndiv++;
00675 
00676     // Ensure that result covers original range
00677     if (ns*unit<lo) lo = ns * unit;
00678     if (nu*unit>hi) hi = nu * unit;
00679 
00680     // Fill array
00681     Vals.Resize(ndiv);
00682     Vals[0] = lo;
00683     for (int i=1; i<ndiv; ++i)
00684     {
00685         Vals[i] = Vals[i-1]+unit;
00686         if (fabs(Vals[i])<MINZERO) Vals[i] = 0.0;
00687     }
00688 
00689 }
00690 
00691 }; // namespace MPM
00692 
00693 
00694 #endif // MPM_PLOTXY_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines