00001 #ifndef _LEGEND_H_
00002 #define _LEGEND_H_
00003
00004 #include <string>
00005 #include <vector>
00006 #include <memory>
00007 #include "fv_config.h"
00008 #include "LegendValue.h"
00009 #include "MathHelper.h"
00010 #include "Color.h"
00011 #include "ColorBar.h"
00012 #include "GraphicElem.hpp"
00013
00014 namespace FemViewer {
00015
00016
00017
00018 enum LegendType
00019 {
00020
00021 SOLID = 0,
00022 GRADIENT = 1
00023 };
00024
00025 template<typename T>
00026 struct LegendData {
00027 fvmath::Vec3<T> color;
00028 int numBrreaks;
00029 T startValue;
00030 T deltaValue;
00031 };
00032
00033
00034 class Legend
00035 {
00036 private:
00037
00038 static const int _ncont = 20;
00039
00040 static const LegendType _dftype = GRADIENT;
00041
00042 std::shared_ptr<ColorBar> _hBar;
00043
00044 double _min, _max;
00045
00046 double _start, _end;
00047
00048 unsigned int _nranges;
00049
00050 LegendType _type;
00051
00052 bool _outsideBlack;
00053
00054 bool _ok;
00055
00056 std::vector<colormap_value> _colors;
00057
00058 public:
00059
00060 colormap_value color;
00061
00062 public:
00063
00064 explicit Legend();
00065 explicit Legend(const Legend & legend);
00066 explicit Legend(const std::string& path);
00067 ~Legend();
00068
00069 Legend & operator=(const Legend & legend);
00070 bool operator ==(const Legend& rhs) const;
00071 void Reset();
00072
00073 double GetMin() const { return _min; }
00074 double GetMax() const { return _max; }
00075 double GetStart() const { return _start; }
00076 double GetEnd() const { return _end; }
00077 unsigned int GetRangesNumber(void) const { return _nranges;}
00078 LegendType GetLegendType(void) const { return _type; }
00079 bool GetOutsideBlack(void) const {return this->_outsideBlack; };
00080 bool IsValid() const { return _ok; }
00081 std::vector<colormap_value>& GetColors() { return _colors; }
00082 const std::vector<colormap_value>& GetColors() const { return _colors; }
00083 template<typename T> int PackValuesIntoArray(T buffer[][4],const int max_size) const;
00084
00085
00086 void SetMin(double minValue) {
00087 if (_min != minValue)
00088 Set(minValue,_max,_start,_end,_nranges,_type,_outsideBlack);
00089 }
00090 void SetMax(double maxValue) {
00091 if (_max != maxValue)
00092 Set(_min,maxValue,_start,_end,_nranges,_type,_outsideBlack);
00093 }
00094 void SetStart(double startValue) {
00095 if (_start != startValue)
00096 Set(_min,_max,startValue,_end,_nranges,_type,_outsideBlack);
00097 }
00098 void SetEnd(double endValue) {
00099 if (_end != endValue)
00100 Set(_min,_max,_start,endValue,_nranges,_type,_outsideBlack);
00101 }
00102 void SetRange(unsigned int numRanges) {
00103 if (_nranges != numRanges)
00104 Set(_min,_max,_start,_end,numRanges,_type,_outsideBlack);
00105 }
00106 void SetType(LegendType type) {
00107 if (_type != type)
00108 Set(_min,_max,_start,_end,_nranges,type,_outsideBlack);
00109 }
00110 void SetOutsideBlack(bool outsideBlack) {
00111 if (_outsideBlack != outsideBlack)
00112 Set(_min,_max,_start,_end,_nranges,_type,outsideBlack);
00113 }
00114
00115 void Draw(void) { assert(_hBar); _hBar->Draw(); }
00116 void Update(void) { assert(_hBar); _hBar->Create(this); }
00117 void Create(void);
00118
00119 void Set(double minValue = 0.0,
00120 double maxValue = 1.0,
00121 double startValue = 0.0,
00122 double endValue = 1.0,
00123 unsigned int rangesNumber = _ncont,
00124 LegendType legendType = _dftype,
00125 bool outsideBlack = false);
00126
00127
00128
00130 int GetLiczbaGranic(void) const
00131 {
00132 if (_type == SOLID) {
00133 unsigned int a = _colors.size() - 1;
00134 a >>= 1;
00135 return ++a;
00136 }
00137 else if (_type == GRADIENT) {
00138 return (int)_colors.size();
00139 }
00140
00141 return(-1);
00142 }
00143
00145 double GetWartoscGranicy(const unsigned int &i) const
00146 {
00147
00148 if (_type == SOLID) {
00149 return _colors[(i << 1)].value;
00150 }
00151
00152 return _colors[i].value;
00153 }
00154
00155
00156
00158 int IsBorderNr(double value) const;
00159
00160
00161
00163 std::vector<ColorRGB> GetColors(const std::vector<double> & vValues);
00164
00166
00170
00171
00172
00173
00175
00176
00178
00182
00183 std::vector<unsigned int> GetRanges(const double & d) const;
00184
00186 int GetRanges(const double & v1, const double & v2) const;
00187
00189 void GetRangeValues(unsigned int i, double & v1, double & v2) const;
00190
00192 size_t GetRangesSize(void) const;
00193
00194
00196
00200 bool GetColor(const double & value, const unsigned int & range, ColorRGB & c) const;
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 public:
00220 void GetRange3(const unsigned int & range, double & sValue, ColorRGB & sColor, double & eValue, ColorRGB & eColor);
00221 protected:
00222 void GetRangeColor(const unsigned int & range, double & sValue, ColorRGB & sColor, double & eValue, ColorRGB & eColor);
00223 void GetRangeGradient(const unsigned int & range, double & sValue, ColorRGB & sColor, double & eValue, ColorRGB & eColor);
00224 public:
00225
00227
00237 void GetRange(const unsigned int & range, double & sValue, ColorRGB & sColor, double & eValue, ColorRGB & eColor)
00238 {
00239 if (range >= this->_colors.size())
00240 return;
00241
00242
00243 unsigned int rangeStart, rangeEnd;
00244
00245 rangeStart = range;
00246 rangeEnd = range+1;
00247
00248 sValue = _colors[rangeStart].value;
00249 eValue = _colors[rangeEnd].value;
00250
00251 if ( (_colors[rangeStart].type & INSIDE) && (_colors[rangeEnd].type & INSIDE) )
00252 {
00253
00254 #ifdef DEBUG2
00255 cout << endl << "*IN*" << endl;
00256 #endif
00257
00258
00259
00260
00261 if (_type == SOLID)
00262 {
00263
00264 sColor = _colors[rangeStart].GetColor();
00265 eColor = _colors[rangeStart].GetColor();
00266
00267
00268 }
00269 else if (_type == GRADIENT)
00270 {
00271
00272 sColor = _colors[rangeStart].GetColor();
00273 eColor = _colors[rangeEnd].GetColor();
00274
00275
00276 }
00277
00278
00279 }
00280 else if ( (_colors[rangeStart].type & OUTSIDE) && (_colors[rangeEnd].type & OUTSIDE) )
00281 {
00282 #ifdef DEBUG2
00283 cout << endl << "*OUT*" << endl;
00284 #endif
00285
00286
00287
00288 if (_outsideBlack)
00289 {
00290
00291 sColor = ColorRGB();
00292 eColor = ColorRGB();
00293 }
00294 else
00295 {
00296
00297
00298
00299
00300
00301 if ( ( _colors[rangeStart].value < _start ) && ( _colors[rangeEnd].value < _start) )
00302 {
00303 int i = GetStartIndex();
00304 sColor = _colors[i].GetColor();
00305 eColor = _colors[i].GetColor();
00306
00307 }
00308 else if ( ( _colors[rangeStart].value > _end ) && ( _colors[rangeEnd].value > _end) )
00309 {
00310 int i = GetEndIndex();
00311 sColor = _colors[i].GetColor();
00312 eColor = _colors[i].GetColor();
00313 }
00314 }
00315 }
00316 else
00317 {
00318 #ifdef DEBUG2
00319 cout << endl << "*INOUT*" << endl;
00320 #endif
00321
00322 if (_outsideBlack)
00323 {
00324
00325 sColor = ColorRGB(0.0, 0.0, 0.0);
00326 eColor = ColorRGB(0.0, 0.0, 0.0);
00327 }
00328 else
00329 {
00330
00331
00332
00333 if (_colors[rangeStart].type & INSIDE)
00334 {
00335 sColor = _colors[rangeStart].GetColor();
00336 eColor = _colors[rangeStart].GetColor();
00337 }
00338 else if (_colors[rangeEnd].type & INSIDE)
00339 {
00340 sColor = _colors[rangeEnd].GetColor();
00341 eColor = _colors[rangeEnd].GetColor();
00342 }
00343
00344 }
00345 }
00346 };
00347
00348
00349
00350
00351
00352
00353
00363 double GetInterp(double value);
00364
00376 double GetInterp(double a, double b, double value) const;
00377
00379 double GetValue(double a, double b, double interp) const;
00380
00381
00382
00383
00384
00385
00387 void GetBorders(const double &s, const double &e, std::vector<double> &vD) const
00388 {
00389
00390 double dTmp;
00391
00392 vD.clear();
00393
00394 vD.push_back(s);
00395
00396
00397 if ( fvmath::Compare(s,e) )
00398 {
00399 vD.push_back(e);
00400 return;
00401 }
00402
00403
00404 if ( GetRanges(s, e) >= 0 )
00405 {
00406 vD.push_back(e);
00407 return;
00408 }
00409
00410 if (s < e)
00411 {
00412
00413
00414
00415
00416 for (int i = 0; i < GetLiczbaGranic(); ++i)
00417 {
00418 dTmp = GetWartoscGranicy(i);
00419
00420 if ( (dTmp > s) && (dTmp < e) )
00421 vD.push_back(dTmp);
00422 }
00423
00424 }
00425 else if (s > e)
00426 {
00427
00428
00429
00430
00431
00432
00433 for (int i = GetLiczbaGranic(); i > 0; --i)
00434 {
00435 dTmp = GetWartoscGranicy(i-1);
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 if ( (dTmp < s) && (dTmp > e) )
00446 {
00447 vD.push_back(dTmp);
00448
00449
00450
00451 }
00452
00453 }
00454
00455
00456
00457 }
00458 vD.push_back(e);
00459
00460 };
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 protected:
00471
00472
00473
00474 public:
00476 bool GetRangesBorder(const double & value, double & s, double &e) const;
00477
00479 bool IsBorder2(double value) const;
00480
00481 bool IsBorder3(double value) const;
00482
00483 protected:
00484
00486
00492 void MinMaxPos(int & mi, int & mx);
00493
00495 void FillStartEndColor(void);
00496
00497 void FillStartEndGradient(void);
00498
00499 void AddMinMaxColor(void);
00500
00501 void AddMinMaxGradient(void);
00502
00503
00505
00506
00507
00508 public:
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00520
00535
00536
00537
00539
00540
00542
00544
00545
00546
00565
00566
00575
00576
00586 int GetIndexMax(void){return (int)_colors.size();};
00587
00596 void GetColor(double value);
00597
00598
00599 float GetColor3b(double value) {
00600 GetColor(value, color);
00601 return color.rgb.r + color.rgb.g*256.0 + color.rgb.b*256.0*256.0;
00602 }
00603
00604 double GetValue(const ColorRGB& rgb);
00605
00615 void GetColor(double value, colormap_value &lv);
00616
00625 bool IsBorder(double value);
00626
00627
00628
00637 bool IsInStartEnd(double value);
00638
00639
00641 int GetStartIndex(void)
00642 {
00643 for (unsigned int i = 0; i < _colors.size(); ++i)
00644 {
00645 if (_colors[i].type == START)
00646 return i;
00647 }
00648 return -1;
00649 }
00650
00652 int GetEndIndex(void)
00653 {
00654
00655 for (unsigned int i = 0; i < _colors.size(); ++i)
00656 {
00657 if (_colors[i].type == END)
00658 return i;
00659 }
00660 return -1;
00661
00662 };
00663
00664 public:
00665
00678 void GetInterval(double valueStart, double valueEnd);
00679
00680 #ifdef DEBUG
00681 void Dump()
00682 {
00683 std::cout << "Legend"
00684 << "\n\tColor:\t\t\t" << color.AsString()
00685 << "\n\tType:\t\t\t" << (_type ? "GRADIENT" : "SOLID")
00686 << "\n\tMin/Max value:\t\t" << _min << " | " << _max
00687 << "\n\tStart/End value:\t" << _start << " | " << _end
00688 << "\n\t# of ranges\t\t" << _nranges
00689 << "\n\tIs ou black:\t\t" << (_outsideBlack ? "TRUE" : "FALSE")
00690 << std::endl;
00691
00692
00693 }
00694 #endif
00695 public:
00696
00697
00698 };
00699
00700 template<typename T>
00701 int Legend::PackValuesIntoArray(T buffer[][4],const int max_size) const
00702 {
00703 if (buffer == nullptr) return(-1);
00704
00705 int num = static_cast<int>(_colors.size());
00706 num = num > max_size ? max_size : num;
00707 for (int i = 0; i < num; ++i) {
00708 buffer[i][0] = _colors[i].rgb.r;
00709 buffer[i][1] = _colors[i].rgb.g;
00710 buffer[i][2] = _colors[i].rgb.b;
00711 buffer[i][3] = static_cast<float>(_colors[i].value);
00712
00713
00714 }
00715 return num;
00716 }
00717
00718
00719
00720
00721 }
00722
00723 #endif
00724