#include #include "AbsAxis_p.h" namespace YSG { Q_Ptr_cpp(AbsAxis) PROP_P(AbsAxis, int, x) PROP_P(AbsAxis, int, y) PROP_P(AbsAxis, Qt::Orientation, orientation) PROP_P(AbsAxis, size_t, pixelSize) PROP_P(AbsAxis, int, tickLength) PROP_P(AbsAxis, int, subTickLength) PROP_P(AbsAxis, QColor, color) PROP_P(AbsAxis, QChar, formatChar) PROP_P(AbsAxis, QLocale, locale) PROP_P(AbsAxis, QString, unitText) PROP_P(AbsAxis, QFont, unitTextFont) PROP_P(AbsAxis, QPen, unitTextPen) PROP_P(AbsAxis, QBrush, unitTextBackgroundBrush) PROP_P(AbsAxis, int, rotate) // 不旋转 double AbsAxis::pixelToCoord(double pixel, SRC src) { return d()->pixelToCoord(pixel, src); } double AbsAxis::coordToPixel(double coord, SRC src) { return d()->coordToPixel(coord, src); } QVector AbsAxisPrivate::createTickVector(double tickStep, const Range &range) { double mTickOrigin = renderState()->coordStart; QVector result; // Generate tick positions according to tickStep: // do not use qFloor here, or we'll lose 64 bit precision // qDebug() << "tickStep:" << tickStep; // auto firstStep = qint64(floor(qAbs((range.lower-mTickOrigin)/tickStep))); auto lastStep = qint64(ceil((qAbs(range.upper-mTickOrigin)/tickStep))); int tickcount = int(qAbs(lastStep-firstStep)+1); if (tickcount < 0) tickcount = 0; if(range.lower > range.upper) tickStep = -tickStep; result.resize(tickcount); for (int i=0; i AbsAxisPrivate::createLabelVector(const QVector &ticks, SRC src) { QVector result; result.reserve(ticks.size()); foreach (double tickCoord, ticks) result.append(getTickLabel(tickCoord, src)); return result; } QVector AbsAxisPrivate::createSubTickVector(int subTickCount, const QVector &ticks, const Range& range) { QVector result; if (subTickCount <= 0 || ticks.size() < 2) return result; result.reserve((ticks.size()-1)*subTickCount); for (int i=1; i 0.2 substep case 2: result = 3; break; // 2.0 -> 0.5 substep case 3: result = 2; break; // 3.0 -> 1.0 substep case 4: result = 3; break; // 4.0 -> 1.0 substep case 5: result = 4; break; // 5.0 -> 1.0 substep case 6: result = 2; break; // 6.0 -> 2.0 substep case 7: result = 6; break; // 7.0 -> 1.0 substep case 8: result = 3; break; // 8.0 -> 2.0 substep case 9: result = 2; break; // 9.0 -> 3.0 substep } } else { // handle cases with significantly fractional mantissa: if (qAbs(fracPart-0.5) < epsilon) // *.5 mantissa { switch (intPart) { case 1: result = 2; break; // 1.5 -> 0.5 substep case 2: result = 4; break; // 2.5 -> 0.5 substep case 3: result = 4; break; // 3.5 -> 0.7 substep case 4: result = 2; break; // 4.5 -> 1.5 substep case 5: result = 4; break; // 5.5 -> 1.1 substep (won't occur with default getTickStep from here on) case 6: result = 4; break; // 6.5 -> 1.3 substep case 7: result = 2; break; // 7.5 -> 2.5 substep case 8: result = 4; break; // 8.5 -> 1.7 substep case 9: result = 4; break; // 9.5 -> 1.9 substep } } // if mantissa fraction isn't 0.0 or 0.5, don't bother finding good sub tick marks, leave default } return result; } double AbsAxisPrivate::getMantissa(double input, double *magnitude) { const double mag = std::pow(10.0, std::floor(std::log10(input))); if (magnitude) *magnitude = mag; return input / mag; } double AbsAxisPrivate::cleanMantissa(double input) { double magnitude; const double mantissa = getMantissa(input, &magnitude); return pickClosest(mantissa, QVector() << 1.0 << 2.0 << 2.5 << 5.0 << 10.0)*magnitude; } double AbsAxisPrivate::pickClosest(double target, const QVector &candidates) { if (candidates.size() == 1) return candidates.first(); QVector::const_iterator it = std::lower_bound(candidates.constBegin(), candidates.constEnd(), target); if (it == candidates.constEnd()) return *(it - 1); else if (it == candidates.constBegin()) return *it; else return target - *(it - 1) < *it - target ? *(it - 1) : *it; } QString AbsAxisPrivate::getTickLabel(double tick, SRC src) { auto renderState = reinterpret_cast(state(src)); return renderState->locale.toString(tick, renderState->formatChar.toLatin1(), renderState->numberPrecision); } double AbsAxis::startCoord(SRC src) { INIT_GET(AbsAxis) return renderState->coordStart; } double AbsAxis::endCoord(SRC src) { INIT_GET(AbsAxis) return renderState->coordStart + renderState->coordLength; } Range AbsAxis::coordRange(SRC src) { INIT_GET(AbsAxis) return {renderState->coordStart, renderState->coordStart + renderState->coordLength}; } int AbsAxis::getPixelPointSize(Range range, SRC src) { INIT_GET(AbsAxis) return static_cast(qAbs(range.length()/coordRange(src).length()) * renderState->pixelSize); } int AbsAxis::getPixelPointSize(SRC src) { INIT_GET(AbsAxis) return qAbs(renderState->pixelSize); } double AbsAxis::getTickStep(const Range &range) {return d()->getTickStep(range);} int AbsAxis::getSubTickCount(double tickStep) {return d()->getSubTickCount(tickStep);} QString AbsAxis::getTickLabel(double tick, SRC src) { INIT_GET(AbsAxis) return d()->getTickLabel(tick, src); } QVector AbsAxis::createLabelVector(const QVector &ticks, SRC src) { INIT_GET(AbsAxis) return d()->createLabelVector(ticks, src); } QVector AbsAxis::createTickVector(double tickStep, const Range &range) { return d()->createTickVector(tickStep, range); } QVector AbsAxis::createSubTickVector(int subTickCount, const QVector &ticks, const Range& range) { return d()->createSubTickVector(subTickCount, ticks, range); } }