![]() |
MechSys
1.0
Computing library for simulations in continuum and discrete mechanics
|
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