RulerTicks.hxx
Go to the documentation of this file.00001 #ifndef RulerTicks_hxx
00002 #define RulerTicks_hxx
00003
00004 #include <cmath>
00005 #include "Assert.hxx"
00006 namespace CLAM
00007 {
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 class RulerTicks
00024 {
00025 mutable bool _needsUpdate;
00026
00027 double _min;
00028 double _max;
00029 double _minGap;
00030 double _width;
00031
00032 mutable double _markOffset;
00033 mutable double _markGap;
00034 public:
00035 RulerTicks()
00036 : _needsUpdate(true)
00037 , _min(0)
00038 , _max(1)
00039 , _minGap(5)
00040 , _width(100)
00041 , _markOffset(666)
00042 , _markGap(69)
00043 {
00044 }
00046 void setRange(double min, double max)
00047 {
00048 CLAM_ASSERT(min<max, "RulerTicks: Empty or inverse order range");
00049 _min = min;
00050 _max = max;
00051 _needsUpdate = true;
00052 }
00054 void setWidth(double width)
00055 {
00056 CLAM_ASSERT(width>0, "RulerTicks: Pixel width should be greater than zero");
00057 _width = width;
00058 _needsUpdate = true;
00059 }
00061 void setMinGap(double minGap)
00062 {
00063 _minGap = minGap;
00064 _needsUpdate = true;
00065 }
00066 double markOffset() const
00067 {
00068 if (_needsUpdate) update();
00069 return _markOffset;
00070 }
00071 double markGap() const
00072 {
00073 if (_needsUpdate) update();
00074 return _markGap;
00075 }
00076 void update() const
00077 {
00078 double mappedMinGap = std::fabs(_minGap*(_max-_min)/_width);
00079 _markGap=1;
00080 if (mappedMinGap>=1)
00081 {
00082 while (true)
00083 {
00084 if (_markGap>=mappedMinGap) break;
00085 if (_markGap*2>=mappedMinGap) {_markGap*=2; break;}
00086 if (_markGap*5>=mappedMinGap) {_markGap*=5; break;}
00087 _markGap*=10;
00088 }
00089 }
00090 else
00091 {
00092 while (true)
00093 {
00094 if (_markGap<1e-8) {_markGap=1e-8; break;}
00095 if (_markGap<mappedMinGap) {break;}
00096 if (_markGap/2<mappedMinGap) {_markGap/=2; break;}
00097 if (_markGap/5<mappedMinGap) {_markGap/=5; break;}
00098 _markGap/=10;
00099 }
00100 }
00101 double ceil = std::ceil(_min/_markGap);
00102 _markOffset = (std::fabs(ceil)<1e-5)? 0. : ceil*_markGap;
00103
00104 _needsUpdate = false;
00105 }
00107 double tickValue(unsigned i) const
00108 {
00109 if (_needsUpdate) update();
00110 return _markOffset+_markGap*i;
00111 }
00113 double pixelTickPos(unsigned i) const
00114 {
00115 return toPixel(tickValue(i));
00116 }
00117
00118 double toPixel(double value) const
00119 {
00120 return (value-_min)*_width/(_max-_min);
00121 }
00122
00123 unsigned nTicks() const
00124 {
00125 if (_needsUpdate) update();
00126 return std::ceil((_max-_markOffset)/_markGap);
00127 }
00128 };
00129
00130 }
00131
00132 #endif//RulerTicks_hxx
00133