summaryrefslogtreecommitdiffstats
path: root/lib/tqwtplot3d/src/qwt3d_scale.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tqwtplot3d/src/qwt3d_scale.cpp')
-rw-r--r--lib/tqwtplot3d/src/qwt3d_scale.cpp304
1 files changed, 304 insertions, 0 deletions
diff --git a/lib/tqwtplot3d/src/qwt3d_scale.cpp b/lib/tqwtplot3d/src/qwt3d_scale.cpp
new file mode 100644
index 0000000..ecac454
--- /dev/null
+++ b/lib/tqwtplot3d/src/qwt3d_scale.cpp
@@ -0,0 +1,304 @@
+#include "qwt3d_scale.h"
+
+using namespace Qwt3D;
+
+Scale::Scale()
+: start_p(0.), stop_p(0.),
+ majorintervals_p(0), minorintervals_p(0),
+ mstart_p(0.), mstop_p(0.)
+{
+}
+
+/*! The function maps the double value at tic-position idx to a final
+representation. The default return value is simply the tic values QString
+representation. Overwrite this function, if you plan to transform the value
+in some way. See e.g. LogScale::ticLabel.
+\param idx the current major tic index
+\return The QString representation for the value corresponding to a valid index,
+an empty QString else.
+*/
+QString Scale::ticLabel(unsigned int idx) const
+{
+ if (idx<majors_p.size())
+ {
+ return QString::number(majors_p[idx]);
+ }
+ return QString("");
+}
+
+//! Sets start and stop value for the scale;
+void Scale::setLimits(double start, double stop)
+{
+ if (start < stop)
+ {
+ start_p = start;
+ stop_p = stop;
+ return;
+ }
+ start_p = stop;
+ stop_p = start;
+}
+
+//! Sets value of first major tic
+void Scale::setMajorLimits(double start, double stop)
+{
+ if (start < stop)
+ {
+ mstart_p = start;
+ mstop_p = stop;
+ return;
+ }
+ mstart_p = stop;
+ mstop_p = start;
+}
+
+/*!
+ \param a First major tic after applying autoscaling
+ \param b Last major tic after applying autoscaling
+ \param start Scale begin
+ \param stop Scale end
+ \param ivals Requested number of major intervals
+ \return Number of major intervals after autoscaling\n
+
+ The default implementation sets a=start, b=stop and returns ivals.
+*/
+int Scale::autoscale(double& a, double& b, double start, double stop, int ivals)
+{
+ a = start;
+ b = stop;
+ return ivals;
+}
+
+/***************************
+*
+* linear scales
+*
+***************************/
+
+
+//! Applies LinearAutoScaler::execute()
+int LinearScale::autoscale(double& a, double& b, double start, double stop, int ivals)
+{
+ return autoscaler_p.execute(a, b, start, stop, ivals);
+}
+
+//! Creates the major and minor vector for the scale
+void LinearScale::calculate()
+{
+ majors_p.clear();
+ minors_p.clear();
+
+ double interval = mstop_p-mstart_p;
+
+ double runningval;
+ int i=0;
+
+ // majors
+
+ // first tic
+// if (mstart_p<start_p || mstop_p>stop_p)
+// return;
+
+ majors_p.push_back(mstart_p);
+
+ // remaining tics
+ for (i = 1; i <= majorintervals_p; ++i)
+ {
+ double t = double(i) / majorintervals_p;
+ runningval = mstart_p + t * interval;
+ if (runningval>stop_p)
+ break;
+ if (isPracticallyZero(mstart_p, -t*interval)) // prevent rounding errors near 0
+ runningval = 0.0;
+ majors_p.push_back(runningval);
+ }
+ majorintervals_p = majors_p.size();
+ if (majorintervals_p)
+ --majorintervals_p;
+
+
+ // minors
+
+ if (!majorintervals_p || !minorintervals_p) // no valid interval
+ {
+ minorintervals_p = 0;
+ return;
+ }
+
+ // start_p mstart_p
+ // |_____________|_____ _ _ _
+
+ double step = (majors_p[1]-majors_p[0]) / minorintervals_p;
+ if (isPracticallyZero(step))
+ return;
+
+ runningval = mstart_p-step;
+ while (runningval>start_p)
+ {
+ minors_p.push_back(runningval);
+ runningval -= step;
+ }
+
+ // mstart_p mstop_p
+ // ________|_____ _ _ _ _ _ ___|__________
+
+ for (i=0; i!=majorintervals_p; ++i)
+ {
+ runningval = majors_p[i] + step;
+ for (int j=0; j!=minorintervals_p; ++j)
+ {
+ minors_p.push_back(runningval);
+ runningval += step;
+ }
+ }
+
+ // mstop_p stop_p
+ // _ _ _|_____________|
+
+ runningval = mstop_p + step;
+ while (runningval<stop_p)
+ {
+ minors_p.push_back(runningval);
+ runningval += step;
+ }
+}
+
+void LogScale::setupCounter(double& k, int& step)
+{
+ switch(minorintervals_p)
+ {
+ case 9:
+ k=9;
+ step=1;
+ break;
+ case 5:
+ k=8;
+ step=2;
+ break;
+ case 3:
+ k=5;
+ step=3;
+ break;
+ case 2:
+ k=5;
+ step=5;
+ break;
+ default:
+ k=9;
+ step=1;
+ }
+}
+
+/*! Creates major and minor vectors for the scale.
+\warning If the interval is too small, the scale becomes empty
+or will contain only a single major tic. There is no automatism
+(also not planned for now) for an 'intelligent' guess, what to do.
+Better switch manually to linear to scales in such cases.
+*/
+void LogScale::calculate()
+{
+ majors_p.clear();
+ minors_p.clear();
+
+ if (start_p < DBL_MIN_10_EXP)
+ start_p = DBL_MIN_10_EXP;
+ if (stop_p > DBL_MAX_10_EXP)
+ stop_p = DBL_MAX_10_EXP;
+
+ double interval = stop_p-start_p;
+ if (interval<=0)
+ return;
+
+ double runningval = floor(start_p);
+ while(runningval<=stop_p)
+ {
+ if (runningval>=start_p)
+ majors_p.push_back(runningval);
+ ++runningval;
+ }
+ majorintervals_p = majors_p.size();
+ if (majorintervals_p)
+ --majorintervals_p;
+
+ if (majors_p.size()<1) // not even a single major tic
+ {
+ return;
+ }
+
+
+ // minors
+
+ // start_p mstart_p
+ // |_____________|_____ _ _ _
+
+ double k;
+ int step;
+ setupCounter(k,step);
+ runningval = log10(k)+(majors_p[0]-1);
+ while (runningval>start_p && k>1)
+ {
+ minors_p.push_back(runningval);
+ k -=step;
+ runningval = log10(k)+(majors_p[0]-1);
+ }
+
+ // mstart_p mstop_p
+ // ________|_____ _ _ _ _ _ ___|__________
+
+ for (int i=0; i!=majorintervals_p; ++i)
+ {
+ setupCounter(k,step);
+ runningval = log10(k)+(majors_p[i]);
+ while (k>1)
+ {
+ minors_p.push_back(runningval);
+ k-=step;
+ runningval = log10(k)+(majors_p[i]);
+ }
+ }
+
+ // mstop_p stop_p
+ // _ _ _|_____________|
+
+ setupCounter(k,step);
+ runningval = log10(k)+(majors_p.back());
+ do
+ {
+ k-=step;
+ runningval = log10(k)+(majors_p.back());
+ }
+ while(runningval>=stop_p);
+ while (k>1)
+ {
+ minors_p.push_back(runningval);
+ k-=step;
+ runningval = log10(k)+(majors_p.back());
+ }
+}
+
+/*!
+Sets the minor intervals for the logarithmic scale. Only values of 9,5,3 or 2
+are accepted as arguments. They will produce mantissa sets of {2,3,4,5,6,7,8,9},
+{2,4,6,8}, {2,5} or {5} respectively.
+*/
+void LogScale::setMinors(int val)
+{
+ if ((val == 2) || (val == 3) || (val == 5) || (val == 9))
+ minorintervals_p = val;
+}
+
+LogScale::LogScale()
+{
+ minorintervals_p = 9;
+}
+
+//! Returns a power of 10 associated to the major value at index idx.
+QString LogScale::ticLabel(unsigned int idx) const
+{
+ if (idx<majors_p.size())
+ {
+ double val = majors_p[idx];
+ return QString::number(pow(double(10), val));
+ }
+ return QString("");
+}