/* Copyright (c) 2008-2022 Jan W. Krieger () This software is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License (LGPL) as published by the Free Software Foundation, either version 2.1 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License (LGPL) for more details. You should have received a copy of the GNU Lesser General Public License (LGPL) along with this program. If not, see . */ #include "jkqtplotter/jkqtpcoordinateaxes.h" #include "jkqtplotter/jkqtpbaseplotter.h" #include "jkqtcommon/jkqtpdrawingtools.h" #include "jkqtcommon/jkqtpgeometrytools.h" #include "jkqtcommon/jkqtpmathtools.h" #include #include #include #include #if __cplusplus >= 202002L # include # ifdef __cpp_lib_format # include # endif #endif //#undef SHOW_JKQTPLOTTER_DEBUG //#define SHOW_JKQTPLOTTER_DEBUG JKQTPCoordinateAxis::JKQTPCoordinateAxis(JKQTBasePlotter* _parent): QObject(_parent), paramsChanged(true), doUpdateScaling(true), tickLabels(), parent(_parent), axismin(-10), axismax(10), axisabsoultemin(-DBL_MAX/100.), axisabsoultemax(DBL_MAX/100.0), axisStyle(), axisMinWidth(-1), width(20), scale(0), offset(0), inverted(false), tickStart(1), autoAxisSpacing(true), logAxis(false), logAxisBase(10), userTickSpacing(1), userLogTickSpacing(10), tickSpacing(0), tickSpacingLog(10), axisLabel(), tickUnitFactor(1), tickUnitName(""), axisPrefix(), scaleSign(1) { } JKQTPCoordinateAxis::~JKQTPCoordinateAxis() { } void JKQTPCoordinateAxis::setParent(JKQTBasePlotter* parent) { this->parent=parent; QObject::setParent(parent); } void JKQTPCoordinateAxis::redrawPlot() { calcPlotScaling(); if (parent) { parent->updateSecondaryAxes(); parent->redrawPlot(); } } JKQTMathText* JKQTPCoordinateAxis::getParentMathText() { if (!parent) return nullptr; return parent->getMathText(); } const JKQTMathText* JKQTPCoordinateAxis::getParentMathText() const { if (!parent) return nullptr; return parent->getMathText(); } void JKQTPCoordinateAxis::clearAxisTickLabels() { tickLabels.clear(); redrawPlot(); } void JKQTPCoordinateAxis::addAxisTickLabel(double x, const QString& label) { tickLabels.append(qMakePair(x, label)); redrawPlot(); } void JKQTPCoordinateAxis::addAxisTickLabels(const QVector &x, const QStringList &label) { for (int i=0; i &x, const QString *label) { for (int i=0; i=0) { expo=res.mid(expIdx); res=res.left(expIdx); } while (res.size()>0 && res[res.size()-1]=='0') { res=res.left(res.size()-1); } if (res.size()>0 && res[res.size()-1]==loc.decimalPoint()) res=res.left(res.size()-1); res=res+expo; } return res; } QString JKQTPCoordinateAxis::floattostringWithFormat(double data, char format, int past_comma, bool remove_trail0) const { QLocale loc=QLocale::system(); loc.setNumberOptions(QLocale::OmitGroupSeparator); return floattostringWithFormat(loc, data, format, past_comma, remove_trail0); } QString JKQTPCoordinateAxis::floattolabel(double data) const { const int past_comma=axisStyle.labelDigits; return floattolabel(data, past_comma); } QString JKQTPCoordinateAxis::floattolabel(double data, int past_comma) const { const bool remove_trail0=true; QLocale loc= QLocale::system(); loc.setNumberOptions(QLocale::OmitGroupSeparator); double belowIsZero=1e-300; if (!getLogAxis()) { belowIsZero=fabs(getMax()-getMin())*1e-6; } data=data/tickUnitFactor; auto addTickUnit=[&](const QString& s) { if (tickUnitName.isEmpty()) return s; bool ok=false; const double d=s.toDouble(&ok); if (s=="0" || (ok && fabs(d)<1e-300)) return s; if (s=="1" || (ok && d==1.0)) return tickUnitName; return s+tickUnitName; }; switch(axisStyle.tickLabelType) { case JKQTPCALTcount: return ""; case JKQTPCALTdefault: return addTickUnit(floattostringWithFormat(loc, data, 'f', past_comma, remove_trail0)); case JKQTPCALTscientific: return addTickUnit(floattostringWithFormat(loc, data, 'e', past_comma, remove_trail0)); case JKQTPCALTexponent: return addTickUnit(QString(jkqtp_floattolatexstr(data, past_comma, remove_trail0, belowIsZero, pow(10, -past_comma), pow(10, past_comma+1)).c_str())); case JKQTPCALTexponentCharacter: return addTickUnit(QString(jkqtp_floattolatexunitstr(data, past_comma, remove_trail0).c_str())); case JKQTPCALTintfrac: case JKQTPCALTintsfrac: case JKQTPCALTintslashfrac: case JKQTPCALTfrac: case JKQTPCALTsfrac: case JKQTPCALTslashfrac: { uint64_t num=0; uint64_t denom=0; uint64_t intpart=0; int sign=+1; const double powfac=pow(10,past_comma); const double rounded=round(data*powfac)/powfac; jkqtp_estimateFraction(rounded, sign, intpart, num, denom); //std::cout<<"\n"< "<0) { num=num+denom*intpart; intpart=0; } } //std::cout< "<0 && res[res.size()-1].isDigit()) { if (sign<0) res+="-"; else res+="+"; } if (axisStyle.tickLabelType==JKQTPCALTintslashfrac || axisStyle.tickLabelType==JKQTPCALTslashfrac) { res+=QString("%1/%2").arg(num).arg(denom); if (intpart!=0 && !tickUnitName.isEmpty()) res="("+res+")"; } } } } else { res=addTickUnit(res); } } //std::cout< "<= 202002L # ifdef __cpp_lib_format case JKQTPCALTformat: { return QString::fromStdString(std::vformat(axisStyle.tickFormatFormat.toStdString(), std::make_format_args(data, tickUnitName.toStdString()))); }; break; /** \copydoc JKQTPCoordinateAxisStyle::tickFormatFormat */ void setTickFormatFormat(const QString& __value); # endif #endif } return QString(); } int JKQTPCoordinateAxis::calcLinearUnitDigits() { if (!axisStyle.autoLabelDigits) return axisStyle.labelDigits; int unitdigits=-1; double minval=tickStart; bool equals=true; /*for (int i=0; i<20; i++) { equals=equals || (floattolabel((minval+static_cast(i)*tickSpacing), unitdigits)== floattolabel((minval+static_cast(i+1)*tickSpacing), unitdigits)); }*/ while ((unitdigits<20) && equals) { unitdigits++; equals=false; for (int i=-10; i<10; i++) { QString l1=floattolabel((minval+static_cast(i)*tickSpacing), unitdigits+2); QString l2=floattolabel((minval+static_cast(i+1.0)*tickSpacing), unitdigits+2); //qDebug()<<"unitdigits="<axismax) { std::swap(axismin, axismax); } else if (axismax==axismin) { axismax=axismin+1.0; } if (isLogAxis()) { if (axismin<0) { if (axismax>0) axismin=axismax/(logAxisBase*logAxisBase); else axismin=1e-5; } if (axismax<=axismin) axismax=axismin*logAxisBase*logAxisBase; //if (axismax<0) axismax=pow(10.0, ceil(log10(axismax-axismin)+1.0)); if (axismin<=0) axismin=1e-5; if (axismax<=0) axismax=axismin+pow(10.0, static_cast(log10(axismin))); if (axismax(log10(axismin))); } } if (axismin>axismax) { std::swap(axismin, axismax); } else if (axismax==axismin) { axismax=axismin+1.0; } // this is the x- and y-range spanned by the plot width=fabs(axismax-axismin); //qDebug()<<"calcPlotScaling():\n"; //qDebug()<<" width="<objectName()<<": inverted = "<objectName()<<": plotOffset = "<objectName()<<": plotWidth = "<0) { offset=plotOffset-log(axismin)/log(logAxisBase)*scale; } else { offset=plotOffset+log(axismax)/log(logAxisBase)*scale; } } else { scale=getParentPlotWidth()/width; if (scaleSign>0) { offset=plotOffset-axismin*scale; } else { offset=plotOffset+axismax*scale; } } #ifdef SHOW_JKQTPLOTTER_DEBUG //qDebug()<objectName()<<": offset = "<objectName()<<": scale = "<objectName()<<": scaleSign = "<paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::loadCurrentAxisStyle(const QSettings &settings, const QString &group) { axisStyle.loadSettings(settings, group); this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::saveCurrentAxisStyle(QSettings &settings, const QString &group) const { axisStyle.saveSettings(settings, group); } void JKQTPCoordinateAxis::setRange(double aamin, double aamax) { const double oldamin=axismin; const double oldamax=axismax; double amin=std::min(aamin, aamax); double amax=std::max(aamin, aamax); if (axisMinWidth>0 && fabs(amax-amin)axisabsoultemax) axismax=axisabsoultemax; if (isLogAxis()) { if (axismin<=0) axismin=1e-306; if (axismax<=0) axismax=1e-306; if (fabs(axismin-axismax)<1e-306) { axismax=10; axismin=0.1; } } if (axisMinWidth>0 && fabs(axismax-axismin)tickSpacing = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setAxisMinWidth(double __value) { this->axisMinWidth = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setAutoAxisSpacing(bool __value) { this->autoAxisSpacing = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setMinorTickLabelsEnabled(bool __value) { this->axisStyle.minorTickLabelsEnabled = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setLogAxis(bool __value) { this->logAxis = __value; this->paramsChanged=true; if (this->isLogAxis()) { if (axismin<0) axismin=pow(10.0, floor(log(axismax-axismin)/JKQTPSTATISTICS_LN10-1.0)); if (axismax<0) axismax=pow(10.0, floor(log(axismax-axismin)/JKQTPSTATISTICS_LN10+1.0)); } redrawPlot(); } void JKQTPCoordinateAxis::setLogAxisBase(double __value) { this->logAxisBase = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setUserTickSpacing(double __value) { this->userTickSpacing = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setUserLogTickSpacing(double __value) { this->userLogTickSpacing = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setTickLabelType(JKQTPCALabelType __value) { this->axisStyle.tickLabelType = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setTickMode(JKQTPLabelTickMode __value) { this->axisStyle.tickMode = __value; this->paramsChanged=true; setLogAxis(this->logAxis); } void JKQTPCoordinateAxis::setTickMode(int __value) { setTickMode(JKQTPLabelTickMode(__value)); } void JKQTPCoordinateAxis::setAxisLabel(const QString& __value) { this->axisLabel = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setTickUnitName(const QString &__value) { this->tickUnitName = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setTickUnitFactor(double __value) { this->tickUnitFactor = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setTickUnit(double factor, const QString &name) { this->tickUnitFactor = factor; this->tickUnitName = name; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setTickUnitPi() { setTickUnit(JKQTPSTATISTICS_PI, "\\;\\pi"); } void JKQTPCoordinateAxis::resetTickUnit() { setTickUnit(1, ""); } void JKQTPCoordinateAxis::setLabelPosition(JKQTPLabelPosition __value) { this->axisStyle.labelPosition = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setLabelFontSize(double __value) { this->axisStyle.labelFontSize = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setTickTimeFormat(const QString& __value) { this->axisStyle.tickTimeFormat = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setTickDateFormat(const QString& __value) { this->axisStyle.tickDateFormat = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setTickDateTimeFormat(const QString& __value) { this->axisStyle.tickDateTimeFormat = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setTickPrintfFormat(const QString& __value) { this->axisStyle.tickPrintfFormat = __value; this->paramsChanged=true; redrawPlot(); } #if __cplusplus >= 202002L # ifdef __cpp_lib_format void JKQTPCoordinateAxis::setTickFormatFormat(const QString &__value) { this->axisStyle.tickFormatFormat = __value; this->paramsChanged=true; redrawPlot(); } # endif #endif void JKQTPCoordinateAxis::setTickLabelFontSize(double __value) { this->axisStyle.tickLabelFontSize = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setMinorTickLabelFontSize(double __value) { this->axisStyle.minorTickLabelFontSize = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setMinorTickLabelFullNumber(bool __value) { this->axisStyle.minorTickLabelFullNumber = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setMinTicks(unsigned int __value) { this->axisStyle.minTicks = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setMinorTicks(unsigned int __value) { this->axisStyle.minorTicks = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setMinorTicks(int __value) { this->axisStyle.minorTicks = qMax(int(0), __value); this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setTickOutsideLength(double __value) { this->axisStyle.tickOutsideLength = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setMinorTickOutsideLength(double __value) { this->axisStyle.minorTickOutsideLength = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setTickInsideLength(double __value) { this->axisStyle.tickInsideLength = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setMinorTickInsideLength(double __value) { this->axisStyle.minorTickInsideLength = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setAxisColor(const QColor& __value) { this->axisStyle.axisColor = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setShowZeroAxis(bool __value) { this->axisStyle.showZeroAxis = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setInverted(bool __value) { this->inverted = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setGridColor(const QColor& __value) { this->axisStyle.majorGridStyle.lineColor = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setGridColor(const QColor &__value, double alpha) { this->axisStyle.majorGridStyle.lineColor = __value; this->axisStyle.majorGridStyle.lineColor.setAlphaF(alpha); this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setMinorGridColor(const QColor& __value) { this->axisStyle.minorGridStyle.lineColor = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setMinorGridColor(const QColor& __value, double alpha) { this->axisStyle.minorGridStyle.lineColor = __value; this->axisStyle.minorGridStyle.lineColor.setAlphaF(alpha); this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setGridWidth(double __value) { this->axisStyle.majorGridStyle.lineWidth = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setGridStyle(Qt::PenStyle __value) { this->axisStyle.majorGridStyle.lineStyle = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setMinorGridWidth(double __value) { this->axisStyle.minorGridStyle.lineWidth = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setMinorGridStyle(Qt::PenStyle __value) { this->axisStyle.minorGridStyle.lineStyle = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setDrawMode1(JKQTPCADrawMode __value) { this->axisStyle.drawMode1 = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setDrawMode0(JKQTPCADrawMode __value) { this->axisStyle.drawMode0 = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setDrawMode2(JKQTPCADrawMode __value) { this->axisStyle.drawMode2 = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setMinorTickWidth(double __value) { this->axisStyle.minorTickWidth = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setTickWidth(double __value) { this->axisStyle.tickWidth = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setLineWidth(double __value) { this->axisStyle.lineWidth = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setLineWidthZeroAxis(double __value) { this->axisStyle.lineWidthZeroAxis = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setTickLabelDistance(double __value) { this->axisStyle.tickLabelDistance = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setLabelDistance(double __value) { this->axisStyle.labelDistance = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setLabelDigits(int __value) { this->axisStyle.labelDigits = __value; this->paramsChanged=true; this->axisStyle.autoLabelDigits=false; redrawPlot(); } void JKQTPCoordinateAxis::setDrawGrid(bool __value) { this->axisStyle.majorGridStyle.enabled = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setDrawMinorGrid(bool __value) { this->axisStyle.minorGridStyle.enabled = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setTickLabelAngle(double __value) { this->axisStyle.tickLabelAngle = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setArrowSizeFactor(double f) { axisStyle.arrowSizeFactor=f; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setLabelColor(QColor c) { axisStyle.labelColor=c; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setMinorTickColor(QColor c) { axisStyle.minorTickColor=c; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setMinorTickLabelColor(QColor c) { axisStyle.minorTickLabelColor=c; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setTickColor(QColor c) { axisStyle.tickColor=c; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setTickLabelColor(QColor c) { axisStyle.tickLabelColor=c=c; this->paramsChanged=true; redrawPlot(); } void JKQTPCoordinateAxis::setColor(QColor c) { setAxisColor(c); setGridColor(c.lighter()); setMinorGridColor(c.lighter()); setLabelColor(c); setMinorTickColor(c); setMinorTickLabelColor(c); setTickColor(c); setTickLabelColor(c); } JKQTPCoordinateAxis::Axis0ElementsSizeDescription JKQTPCoordinateAxis::getSize0(JKQTPEnhancedPainter &/*painter*/) { return JKQTPCoordinateAxis::Axis0ElementsSizeDescription(); } void JKQTPCoordinateAxis::setAbsoluteRange(double amin, double amax) { axisabsoultemin=std::min(amin, amax); axisabsoultemax=std::max(amin, amax); if (axisabsoultemin==axisabsoultemax) { axisabsoultemax=axisabsoultemin+1; } // ensure that the actual axis range is within the absolute range setRange(axismin, axismax); } double JKQTPCoordinateAxis::getNextLabelDistance(double x) { if (axisStyle.tickMode==JKQTPLTMLinOrPower) { if (logAxis) { return x*tickSpacingLog; } else { return tickSpacing; } } else if (axisStyle.tickMode==JKQTPLTMLin) { return tickSpacing; } else if (axisStyle.tickMode==JKQTPLTMPower) { return x*tickSpacingLog; } return 0; } bool JKQTPCoordinateAxis::getNextLabel(double& x, QString& label, bool init) { //qDebug()<<"start JKQTPCoordinateAxis::getNextLabel("<=axismin && x<=axismax) { label=floattolabel(x); } return (x<=axismax); } else { if (init) { if (tickLabels.size()>0) { x=tickLabels[0].first; label=tickLabels[0].second; } return (tickLabels.size()>0); } else { for (int i=0; i=axismin && x<=axismax); } } } } return false; } QSizeF JKQTPCoordinateAxis::getMaxTickLabelSize(JKQTPEnhancedPainter& painter, double* ascent, double* descent) { double w=0, h=0, a=0; calcPlotScaling(); double x=tickStart; QString label=""; getNextLabel(x, label, true); QFont f; f.setFamily(JKQTMathTextFontSpecifier::fromFontSpec(getParent()->getCurrentPlotterStyle().defaultFontName).fontName()); f.setPointSizeF(this->axisStyle.tickLabelFontSize*parent->getFontSizeMultiplier()); bool first=true; int cnt=0; while (getNextLabel(x, label, first) && cnt<50) { double width, ascent, descent, strikeoutPos; parent->getTextSizeDetail(f, label, painter, width, ascent, descent, strikeoutPos); if (width>w) w=width; if (ascent+descent>h) h=ascent+descent; if (ascent>a) a=ascent; first=false; cnt++; } //qDebug()<<"getMaxTickLabelSize() = ["<getAxes(false); for (const auto ax: axlist){ if (ax==this) return true; } } return false; } JKQTPVerticalAxisBase::JKQTPVerticalAxisBase(JKQTBasePlotter* parent): JKQTPCoordinateAxis(parent) { //axisPrefix="yaxis_"; scaleSign=-1; if (parent) { axisStyle=parent->getCurrentPlotterStyle().yAxisStyle; } else { axisStyle=JKQTPGetSystemDefaultBaseStyle().yAxisStyle; } } JKQTPCoordinateAxis::Axis0ElementsSizeDescription JKQTPVerticalAxisBase::getSize0(JKQTPEnhancedPainter& painter) { if (axisStyle.drawMode0==JKQTPCADMnone) return Axis0ElementsSizeDescription(); Axis0ElementsSizeDescription res; double ptwidth=0; double ptwidth_r=0; const double arrowSize=((axisStyle.drawMode0&(JKQTPCADMMinArrow|JKQTPCADMMinFilledArrow|JKQTPCADMMaxArrow|JKQTPCADMMaxFilledArrow))!=int(0))?(axisStyle.getArrowSize(painter, parent)/2.0):0.0; double labwidth=0; if (axisStyle.drawMode0.testFlag(JKQTPCADMTicks)) { ptwidth+=axisStyle.tickOutsideLength; ptwidth_r+=axisStyle.tickInsideLength; } if (axisStyle.drawMode0.testFlag(JKQTPCADMTickLabels)) { ptwidth+=axisStyle.tickLabelDistance; const QSizeF maxLabelSize=getMaxTickLabelSize(painter); if (getTickLabelAngle()<-0.0000001) res.elongateMin=maxLabelSize.height()+2; else if (getTickLabelAngle()<0.0000001) res.elongateMin=maxLabelSize.height()*0.6+2; if (getTickLabelAngle()>0.0000001) res.elongateMax=maxLabelSize.height()+2; else if (getTickLabelAngle()>-0.0000001) res.elongateMax=maxLabelSize.height()*0.6+2; // find out the maximum width over all visible plot labels labwidth+=maxLabelSize.width(); } if (axisStyle.drawMode0.testFlag(JKQTPCADMAxisLabel)) { const auto labSize=parent->getTextSizeDetail(getParent()->getCurrentPlotterStyle().defaultFontName, axisStyle.labelFontSize*parent->getFontSizeMultiplier(), axisLabel, painter); if (axisStyle.labelPosition==JKQTPLabelMinBesides) { labwidth=qMax(labwidth, labSize.width/2.0+2); res.elongateMin=qMax(res.elongateMin, parent->pt2px(painter, axisStyle.labelDistance)*1.5+labSize.overallHeight); } else if (axisStyle.labelPosition==JKQTPLabelMaxBesides) { labwidth=qMax(labwidth, labSize.width/2.0+2); res.elongateMax=qMax(res.elongateMax, parent->pt2px(painter, axisStyle.labelDistance)*1.5+labSize.overallHeight); } else { ptwidth+=axisStyle.labelDistance; // find out size of axis label labwidth+=labSize.overallHeight; } } const double zaxispos=getZeroAxisPos(); const double bottom=x2p(axismin); const double bottom_offset=(bottom-zaxispos); const double top=x2p(axismax); const double top_offset=(zaxispos-top); res.requiredSize=qMax(0.0,qMax(parent->pt2px(painter, ptwidth)+labwidth, arrowSize)-bottom_offset); res.requiredSizeOpposite=qMax(0.0,qMax(parent->pt2px(painter, ptwidth_r), arrowSize)-top_offset); //qDebug()<<"JKQTPVerticalAxis::getSize0(): s1="<pt2px(painter, axisStyle.majorGridStyle.lineWidth*parent->getLineWidthMultiplier()))); pg.setStyle(axisStyle.majorGridStyle.lineStyle); QPen pmg=painter.pen(); pmg.setColor(axisStyle.minorGridStyle.lineColor); pmg.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, axisStyle.minorGridStyle.lineWidth*parent->getLineWidthMultiplier()))); pmg.setStyle(axisStyle.minorGridStyle.lineStyle); //double top=x2p(axismax); //double bottom=x2p(axismin); double left=0; double right=0; if (getParentOtheraxisInverted()) { left=getParentOtheraxisOffset()-getParentOtheraxisWidth();//; right=getParentOtheraxisOffset();//; } else { left=getParentOtheraxisOffset();//; right=getParentOtheraxisOffset()+getParentOtheraxisWidth();//; } double x=tickStart; QString label=""; bool first=true; // loop through all labels, as they are at the major ticks, do not draw more than 200 labels (prevent hang ups) int cnt=0; QVector lines_pg; QVector lines_pmg; while (getNextLabel(x, label, first) && (cnt<200)) { double w=getNextLabelDistance(x); double mtdist=w/static_cast(axisStyle.minorTicks+1); double xx=x2p(x); //qDebug()<<" tick @ x="<axismin) && (fabs(left-right)>0)) { QLineF l(left, xx, right, xx); if (l.length()>0) lines_pg.append(l);//painter.drawLine(l); } //qDebug()<<" 2"; //painter.setPen(pmg); //qDebug()<<" 3"; if ((tickLabels.size()<=0) && axisStyle.minorGridStyle.enabled && (axisStyle.minorTicks>0) && (fabs(right-left)>0)) { //qDebug()<<" 3.1"; double mx=x+mtdist; //qDebug()<<" 3.2"; for (int i=0; i(axisStyle.minorTicks); i++) { //qDebug()<<" 3.2.1"; double mxx=x2p(mx); //qDebug()<<" 3.2.2"; if ((mxaxismin) && (fabs(right-left)>0)) { QLineF l(left, mxx, right, mxx); if (l.length()>0) lines_pmg.append(l);//painter.drawLine(l); } //qDebug()<<" 3.2.3"; mx=mx+mtdist; //qDebug()<<" 3.2.4"; } } first=false; cnt++; } painter.setPen(pg); painter.drawLines(lines_pg); painter.setPen(pmg); painter.drawLines(lines_pmg); //qDebug()<<" end JKQTPVerticalAxis::drawGrids("; } void JKQTPVerticalAxisBase::drawTickLabel1(JKQTPEnhancedPainter &painter, double xx, double yy, double labelOffset, const QString& label, double fontSize, bool isMinor) { getParentMathText()->setFontSize(fontSize*parent->getFontSizeMultiplier()); getParentMathText()->setFontSpecial(getParent()->getCurrentPlotterStyle().defaultFontName); getParentMathText()->setFontColor(axisStyle.tickLabelColor); if (isMinor) getParentMathText()->setFontColor(axisStyle.minorTickLabelColor); getParentMathText()->parse(label); double width, ascent, descent, strikeoutPos; getParentMathText()->getSizeDetail(painter, width, ascent, descent, strikeoutPos); double lx=xx-parent->pt2px(painter, labelOffset)-width; if (axisStyle.tickLabelAngle==90) { painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); painter.translate(lx+width-1.25*strikeoutPos, yy-width/2.0); painter.rotate(axisStyle.tickLabelAngle); getParentMathText()->draw(painter, 0,0, parent->getCurrentPlotterStyle().debugShowTextBoxes); } else if (axisStyle.tickLabelAngle==-90) { painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); painter.translate(lx+width-0.25*strikeoutPos, yy+width/2.0); painter.rotate(axisStyle.tickLabelAngle); getParentMathText()->draw(painter, 0,0, parent->getCurrentPlotterStyle().debugShowTextBoxes); } else if (axisStyle.tickLabelAngle!=0) { painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); if (axisStyle.tickLabelAngle>0) { painter.translate(lx-strikeoutPos+(width)*(1.0-cos(fabs(axisStyle.tickLabelAngle)/180.0*JKQTPSTATISTICS_PI)), yy+strikeoutPos-width*sin(fabs(axisStyle.tickLabelAngle)/180.0*JKQTPSTATISTICS_PI)); painter.rotate(axisStyle.tickLabelAngle); } else { painter.translate(lx+strikeoutPos+(width-strikeoutPos)*(1.0-cos(fabs(axisStyle.tickLabelAngle)/180.0*JKQTPSTATISTICS_PI)), yy+strikeoutPos+width*sin(fabs(axisStyle.tickLabelAngle)/180.0*JKQTPSTATISTICS_PI)); painter.rotate(axisStyle.tickLabelAngle); } getParentMathText()->draw(painter, 0,0, parent->getCurrentPlotterStyle().debugShowTextBoxes); } else { getParentMathText()->draw(painter, lx, yy+strikeoutPos, parent->getCurrentPlotterStyle().debugShowTextBoxes); } } void JKQTPVerticalAxisBase::drawTickLabel2(JKQTPEnhancedPainter &painter, double xx, double yy, double labelOffset, const QString &label, double fontSize, bool isMinor) { getParentMathText()->setFontSize(fontSize*parent->getFontSizeMultiplier()); getParentMathText()->setFontSpecial(getParent()->getCurrentPlotterStyle().defaultFontName); getParentMathText()->setFontColor(axisStyle.tickLabelColor); if (isMinor) getParentMathText()->setFontColor(axisStyle.minorTickLabelColor); getParentMathText()->parse(label); double width, ascent, descent, strikeoutPos; getParentMathText()->getSizeDetail(painter, width, ascent, descent, strikeoutPos); double lx=xx+parent->pt2px(painter, labelOffset); if (axisStyle.tickLabelAngle==90) { painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); painter.translate(lx+descent, yy-width/2.0); painter.rotate(axisStyle.tickLabelAngle); getParentMathText()->draw(painter, 0,0, parent->getCurrentPlotterStyle().debugShowTextBoxes); } else if (axisStyle.tickLabelAngle==-90) { painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); painter.translate(lx+ascent, yy+width/2.0); painter.rotate(axisStyle.tickLabelAngle); getParentMathText()->draw(painter, 0,0, parent->getCurrentPlotterStyle().debugShowTextBoxes); } else if (axisStyle.tickLabelAngle!=0) { painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); double shiftx=0; if (axisStyle.tickLabelAngle>0) { shiftx=strikeoutPos*sin(fabs(axisStyle.tickLabelAngle)/180.0*JKQTPSTATISTICS_PI); } else { } painter.translate(lx+shiftx, yy+strikeoutPos); painter.rotate(-axisStyle.tickLabelAngle); getParentMathText()->draw(painter, 0,0, parent->getCurrentPlotterStyle().debugShowTextBoxes); } else { getParentMathText()->draw(painter, lx, yy+strikeoutPos, parent->getCurrentPlotterStyle().debugShowTextBoxes); } } void JKQTPVerticalAxisBase::drawAxisLabel1(JKQTPEnhancedPainter &painter, double left, double bottom, QSizeF labelMax, JKQTPCADrawMode drawMode) { const double labelOffset0=parent->pt2px(painter, axisStyle.labelDistance); double labelOffset=labelOffset0; if (drawMode.testFlag(JKQTPCADMTicks)) labelOffset+=parent->pt2px(painter, axisStyle.tickOutsideLength); if (drawMode.testFlag(JKQTPCADMTickLabels)) { labelOffset+=parent->pt2px(painter, axisStyle.tickLabelDistance); labelOffset+=labelMax.width();//+labelMax.height(); } getParentMathText()->setFontSize(axisStyle.labelFontSize*parent->getFontSizeMultiplier()); getParentMathText()->setFontSpecial(getParent()->getCurrentPlotterStyle().defaultFontName); getParentMathText()->setFontColor(axisStyle.labelColor); getParentMathText()->parse(axisLabel); const auto labSize=getParentMathText()->getSizeDetail(painter); QRectF rect(0,0, getParentPlotWidth(), labSize.overallHeight); QPointF pos0(left-labelOffset-rect.height(), bottom); Qt::Alignment align=Qt::AlignBottom|Qt::AlignHCenter; double rot=-90; if (axisStyle.labelPosition==JKQTPLabelMaxBesides) { rect=QRectF(0,0, labSize.width, labSize.overallHeight); pos0=QPointF(left-labSize.width/2.0, bottom-getParentPlotWidth()-labelOffset0-labSize.overallHeight); align=Qt::AlignBottom|Qt::AlignLeft; rot=0; } else if (axisStyle.labelPosition==JKQTPLabelMinBesides) { rect=QRectF(0,0, labSize.width, labSize.overallHeight); pos0=QPointF(left-labSize.width/2.0, bottom+labelOffset0); align=Qt::AlignBottom|Qt::AlignRight; rot=0; } else if (axisStyle.labelPosition==JKQTPLabelMin) { align=Qt::AlignBottom|Qt::AlignLeft; } else if (axisStyle.labelPosition==JKQTPLabelMax) { align=Qt::AlignBottom|Qt::AlignRight; } else if (axisStyle.labelPosition==JKQTPLabelCenter) { align=Qt::AlignBottom|Qt::AlignHCenter; } painter.save(); auto __finalpaintinner=JKQTPFinally([&painter]() {painter.restore();}); painter.translate(pos0); painter.rotate(rot); getParentMathText()->draw(painter, align, rect, parent->getCurrentPlotterStyle().debugShowTextBoxes); if (getParent()->getCurrentPlotterStyle().debugShowRegionBoxes) { painter.save(); auto __finalpaintinnerif=JKQTPFinally([&painter]() {painter.restore();}); QPen p("magenta"); QColor col=p.color(); col.setAlphaF(0.8f); p.setColor(col); p.setWidthF(getParent()->getCurrentPlotterStyle().debugRegionLineWidth/2.0); painter.setPen(p); painter.setBrush(QBrush(QColor(Qt::transparent))); painter.drawRect(rect); } painter.resetTransform(); } void JKQTPVerticalAxisBase::drawAxisLabel2(JKQTPEnhancedPainter &painter, double right, double bottom, QSizeF labelMax, JKQTPCADrawMode drawMode) { const double labelOffset0=parent->pt2px(painter, axisStyle.labelDistance); double labelOffset=labelOffset0; if (drawMode.testFlag(JKQTPCADMTicks)) labelOffset+=parent->pt2px(painter, axisStyle.tickOutsideLength); if (drawMode.testFlag(JKQTPCADMTickLabels)) { labelOffset+=parent->pt2px(painter, axisStyle.tickLabelDistance); labelOffset+=labelMax.width();//+labelMax.height(); } getParentMathText()->setFontSize(axisStyle.labelFontSize*parent->getFontSizeMultiplier()); getParentMathText()->setFontSpecial(getParent()->getCurrentPlotterStyle().defaultFontName); getParentMathText()->setFontColor(axisStyle.labelColor); getParentMathText()->parse(axisLabel); const auto labSize=getParentMathText()->getSizeDetail(painter); QRectF rect(0,0, getParentPlotWidth(), labSize.overallHeight); QPointF pos0(right+labelOffset, bottom); Qt::Alignment align=Qt::AlignBottom|Qt::AlignHCenter; double rot=-90; if (axisStyle.labelPosition==JKQTPLabelMaxBesides) { rect=QRectF(0,0, labSize.width, labSize.overallHeight); pos0=QPointF(right-labSize.width/2.0, bottom-getParentPlotWidth()-labelOffset0-labSize.overallHeight); align=Qt::AlignBottom|Qt::AlignLeft; rot=0; } else if (axisStyle.labelPosition==JKQTPLabelMinBesides) { rect=QRectF(0,0, labSize.width, labSize.overallHeight); pos0=QPointF(right-labSize.width/2.0, bottom+labelOffset0); align=Qt::AlignBottom|Qt::AlignRight; rot=0; } else if (axisStyle.labelPosition==JKQTPLabelMin) { align=Qt::AlignBottom|Qt::AlignLeft; } else if (axisStyle.labelPosition==JKQTPLabelMax) { align=Qt::AlignBottom|Qt::AlignRight; } else if (axisStyle.labelPosition==JKQTPLabelCenter) { align=Qt::AlignBottom|Qt::AlignHCenter; } painter.save(); auto __finalpaintinner=JKQTPFinally([&painter]() {painter.restore();}); painter.translate(pos0); painter.rotate(rot); getParentMathText()->draw(painter, align, rect, parent->getCurrentPlotterStyle().debugShowTextBoxes); if (getParent()->getCurrentPlotterStyle().debugShowRegionBoxes) { painter.save(); auto __finalpaintinnerif=JKQTPFinally([&painter]() {painter.restore();}); QPen p("magenta"); QColor col=p.color(); col.setAlphaF(0.8f); p.setColor(col); p.setWidthF(getParent()->getCurrentPlotterStyle().debugRegionLineWidth/2.0); painter.setPen(p); painter.setBrush(QBrush(QColor(Qt::transparent))); painter.drawRect(rect); } painter.resetTransform(); } void JKQTPVerticalAxisBase::drawAxes(JKQTPEnhancedPainter& painter, int move1, int move2) { #ifdef JKQTBP_AUTOTIMER JKQTPAutoOutputTimer jkaat(QString("JKQTPEnhancedPainter[%1]::drawAxes()").arg(objectName())); #endif const bool isSecondAxis=isSecondaryAxis(); // correct move1,move2 for the length of inside ticks for secondary axes double moveForTicks1=0, moveForTicks2=0; if (isSecondAxis && axisStyle.drawMode1.testFlag(JKQTPCADMTicks)) moveForTicks1=qMax(axisStyle.minorTickInsideLength,axisStyle.tickInsideLength); if (isSecondAxis && axisStyle.drawMode2.testFlag(JKQTPCADMTicks)) moveForTicks2=qMax(axisStyle.minorTickInsideLength,axisStyle.tickInsideLength); // make shure all parameters are calculated correctly calcPlotScaling(); // determine pixel coordinates of important positions double top=x2p(axismax); double bottom=x2p(axismin); double left=0; double right=0; if (inverted) { qSwap(top, bottom); } if (getParentOtheraxisInverted()) { left=getParentOtheraxisOffset()-getParentOtheraxisWidth();//; right=getParentOtheraxisOffset();//; } else { left=getParentOtheraxisOffset();//; right=getParentOtheraxisOffset()+getParentOtheraxisWidth();//; } // move axes outside plot rectangle, if required left-=parent->pt2px(painter, axisStyle.axisLineOffset)+move1+moveForTicks1; right+=parent->pt2px(painter, axisStyle.axisLineOffset)+move2+moveForTicks2; double ticklabelOffset1PT=axisStyle.tickLabelDistance; // offset of tick labels from axis 1 double minorticklabelOffset1PT=axisStyle.tickLabelDistance; // offset ofminor tick labels from axis 1 if (axisStyle.drawMode1.testFlag(JKQTPCADMTicks)) { ticklabelOffset1PT+=axisStyle.tickOutsideLength; minorticklabelOffset1PT+=axisStyle.minorTickOutsideLength; } double ticklabelOffset2PT=axisStyle.tickLabelDistance; // offset of tick labels from axis 2 double minorticklabelOffset2PT=axisStyle.tickLabelDistance; // offset ofminor tick labels from axis 2 if (axisStyle.drawMode2.testFlag(JKQTPCADMTicks)) { ticklabelOffset2PT+=axisStyle.tickOutsideLength; minorticklabelOffset2PT+=axisStyle.minorTickOutsideLength; } double ticklabelOffset0PT=axisStyle.tickLabelDistance; // offset of tick labels from axis 0 double minorticklabelOffset0PT=axisStyle.tickLabelDistance; // offset ofminor tick labels from axis 0 if (axisStyle.drawMode0.testFlag(JKQTPCADMTicks)) { ticklabelOffset0PT+=axisStyle.tickOutsideLength; minorticklabelOffset0PT+=axisStyle.minorTickOutsideLength; } //qDebug()<<"JKQTPVerticalAxis:"; //qDebug()<<" left="<setFontSize(this->axisStyle.tickLabelFontSize*parent->getFontSizeMultiplier()); getParentMathText()->setFontSpecial(getParent()->getCurrentPlotterStyle().defaultFontName); getParentMathText()->setFontColor(axisStyle.axisColor); // plot thick axis at y==0 if (axisStyle.showZeroAxis && (0>=axismin) && (0<=axismax)) { #ifdef JKQTBP_AUTOTIMER JKQTPAutoOutputTimer jkaati(QString("JKQTPEnhancedPainter[%1]::drawAxes(): 0Axis").arg(objectName())); #endif const QPen pmain1=axisStyle.getZeroAxisPen(painter, parent); painter.setPen(pmain1); const QLineF l(left, x2p(0), right, x2p(0)); if (l.length()>0) painter.drawLine(l); } // axis 0 properties bool drawZeroAxis=false; const double zeroaxispos=getZeroAxisPos(&drawZeroAxis); painter.setPen(pmain); painter.setBrush(pmain.color()); // draw thick axis lines, left and/or right with optional arrows, but wihtou ticks if ( axisStyle.drawMode1.testFlag(JKQTPCADMLine)) { const QLineF l(left, x2p(axismin), left, x2p(axismax)); drawAxisLine(painter, l, axisStyle.drawMode1); } if (axisStyle.drawMode2.testFlag(JKQTPCADMLine)) { const QLineF l(right, x2p(axismin), right, x2p(axismax)); drawAxisLine(painter, l, axisStyle.drawMode1); } if (axisStyle.drawMode0.testFlag(JKQTPCADMLine)) { const QLineF l(zeroaxispos, x2p(axismin), zeroaxispos, x2p(axismax)); drawAxisLine(painter, l, axisStyle.drawMode0); } painter.setBrush(Qt::NoBrush); // plot minor and major ticks + tick labels const QSizeF labelMax=getMaxTickLabelSize(painter); double y=tickStart; QString label=""; bool first=true; // loop through all labels, as they are at the major ticks int cnt=0; const double arrowFreeSpace=axisStyle.getArrowSize(painter, parent)*1.2; QVector lines_ptick, lines_ptick2, lines_ptick0; QVector lines_pmtick, lines_pmtick2, lines_pmtick0; { #ifdef JKQTBP_AUTOTIMER JKQTPAutoOutputTimer jkaatii(QString("JKQTPEnhancedPainter[%1]::drawAxes(): calcLabels").arg(objectName())); #endif while (getNextLabel(y, label, first) && cnt<200) { const double mtdist=getNextLabelDistance(y)/static_cast(axisStyle.minorTicks+1); // distance of minor ticks const double yy=x2p(y); // y tick position //qDebug()<<" tick @ x="< "<=axismin) { // calculate minor tick lines, axis 1 if (axisStyle.minorTicks>0&&axisStyle.drawMode1.testFlag(JKQTPCADMTicks)) { const QLineF l(left-parent->pt2px(painter, axisStyle.minorTickOutsideLength), my_pix, left+parent->pt2px(painter, axisStyle.minorTickInsideLength), my_pix); if (l.length()>0) lines_pmtick.append(l); } // calculate minor tick lines, axis 2 if (axisStyle.minorTicks>0&&axisStyle.drawMode2.testFlag(JKQTPCADMTicks)) { const QLineF l(right+parent->pt2px(painter, axisStyle.minorTickOutsideLength), my_pix, right-parent->pt2px(painter, axisStyle.minorTickInsideLength), my_pix); if (l.length()>0) lines_pmtick2.append(l); } // calculate minor tick lines, axis 0 if (axisStyle.minorTicks>0&&axisStyle.drawMode0.testFlag(JKQTPCADMTicks)) { const QLineF l(zeroaxispos-parent->pt2px(painter, axisStyle.minorTickOutsideLength), my_pix, zeroaxispos+parent->pt2px(painter, axisStyle.minorTickInsideLength), my_pix); if (l.length()>0) lines_pmtick0.append(l); } // draw minor tick label, axis 1 if (axisStyle.minorTickLabelsEnabled&&axisStyle.minorTicks>0&&(axisStyle.drawMode1.testFlag(JKQTPCADMTickLabels)||axisStyle.drawMode2.testFlag(JKQTPCADMTickLabels)||axisStyle.drawMode0.testFlag(JKQTPCADMTickLabels))) { double val= my/pow(logAxisBase,floor(log(my)/log(logAxisBase))); if (axisStyle.minorTickLabelFullNumber) val=my; const QString minorlabel=floattolabel(val); if (axisStyle.drawMode0.testFlag(JKQTPCADMTickLabels)) drawTickLabel1(painter, zeroaxispos, my_pix, minorticklabelOffset0PT, minorlabel, axisStyle.minorTickLabelFontSize, true); if (axisStyle.drawMode1.testFlag(JKQTPCADMTickLabels)) drawTickLabel1(painter, left, my_pix, minorticklabelOffset1PT, minorlabel, axisStyle.minorTickLabelFontSize, true); if (axisStyle.drawMode2.testFlag(JKQTPCADMTickLabels)) drawTickLabel2(painter, right, my_pix, minorticklabelOffset2PT, minorlabel, axisStyle.minorTickLabelFontSize, true); } } my=my+mtdist; } } } if (!label.isEmpty() && (y<=axismax && y>=axismin)) { if (axisStyle.drawMode0.testFlag(JKQTPCADMTickLabels)) drawTickLabel1(painter, zeroaxispos, yy, ticklabelOffset0PT, label, this->axisStyle.tickLabelFontSize, false); if (axisStyle.drawMode1.testFlag(JKQTPCADMTickLabels)) drawTickLabel1(painter, left, yy, ticklabelOffset1PT, label, this->axisStyle.tickLabelFontSize, false); if (axisStyle.drawMode2.testFlag(JKQTPCADMTickLabels)) drawTickLabel2(painter, right, yy, ticklabelOffset2PT, label, this->axisStyle.tickLabelFontSize, false); } } first=false; cnt++; } } { #ifdef JKQTBP_AUTOTIMER JKQTPAutoOutputTimer jkaati(QString("JKQTPEnhancedPainter[%1]::drawAxes(): drawLines").arg(objectName())); #endif if (axisStyle.drawMode1.testFlag(JKQTPCADMTicks)) { painter.setPen(ptick); painter.drawLines(lines_ptick); painter.setPen(pmtick); painter.drawLines(lines_pmtick); } if (axisStyle.drawMode2.testFlag(JKQTPCADMTicks)) { painter.setPen(ptick); painter.drawLines(lines_ptick2); painter.setPen(pmtick); painter.drawLines(lines_pmtick2); } if (axisStyle.drawMode0.testFlag(JKQTPCADMTicks)) { painter.setPen(ptick); painter.drawLines(lines_ptick0); painter.setPen(pmtick); painter.drawLines(lines_pmtick0); } } // plot axis label if (!axisLabel.isEmpty() && axisStyle.drawMode1.testFlag(JKQTPCADMAxisLabel)) { #ifdef JKQTBP_AUTOTIMER JKQTPAutoOutputTimer jkaati(QString("JKQTPEnhancedPainter[%1]::drawAxes(): axisLabel1").arg(objectName())); #endif drawAxisLabel1(painter, left, bottom, labelMax, axisStyle.drawMode1); } if (!axisLabel.isEmpty() && axisStyle.drawMode0.testFlag(JKQTPCADMAxisLabel)) { #ifdef JKQTBP_AUTOTIMER JKQTPAutoOutputTimer jkaati(QString("JKQTPEnhancedPainter[%1]::drawAxes(): axisLabel0").arg(objectName())); #endif drawAxisLabel1(painter, zeroaxispos, bottom, labelMax,axisStyle.drawMode0); } if (!axisLabel.isEmpty() && axisStyle.drawMode2.testFlag(JKQTPCADMAxisLabel)) { #ifdef JKQTBP_AUTOTIMER JKQTPAutoOutputTimer jkaati(QString("JKQTPEnhancedPainter[%1]::drawAxes(): axisLabel2").arg(objectName())); #endif drawAxisLabel2(painter, right, bottom, labelMax,axisStyle.drawMode2); } if (getParent()->getCurrentPlotterStyle().debugShowRegionBoxes) { painter.save(); auto __finalpaintif=JKQTPFinally([&painter]() {painter.restore();}); QPen p("cyan"); if (isSecondAxis) p=QPen("darkcyan"); p.setWidthF(getParent()->getCurrentPlotterStyle().debugRegionLineWidth); QColor col=p.color(); col.setAlphaF(0.6f); p.setColor(col); painter.setPen(p); painter.setBrush(QBrush(QColor(Qt::transparent))); const QSizeF s1(getSize1(painter).requiredSize, getParentPlotWidth()); const QSizeF s2(getSize2(painter).requiredSize, getParentPlotWidth()); painter.drawRect(QRectF(QPointF(left+moveForTicks1-s1.width(), top), s1)); painter.drawRect(QRectF(QPointF(right-moveForTicks2, top), s2)); } //qDebug()<<" end JKQTPVerticalAxis::drawAxes("; } JKQTPVerticalAxis::JKQTPVerticalAxis(JKQTBasePlotter* parent, JKQTPCoordinateAxisRef otherAxisRef_): JKQTPVerticalAxisBase(parent), otherAxisRef(otherAxisRef_) { //axisPrefix="yaxis_"; scaleSign=-1; if (parent) { axisStyle=parent->getCurrentPlotterStyle().yAxisStyle; } else { axisStyle=JKQTPGetSystemDefaultBaseStyle().yAxisStyle; } } double JKQTPVerticalAxis::getParentPlotWidth() const { return parent->getPlotHeight(); } double JKQTPVerticalAxis::getParentPlotOffset() const { return parent->getInternalPlotBorderTop(); } double JKQTPVerticalAxis::getParentOtheraxisOffset() const { return getOtherAxis()->x2p(getOtherAxis()->getMin()); } double JKQTPVerticalAxis::parentOtherAxisX2P(double x) const { return getOtherAxis()->x2p(x); } JKQTPCoordinateAxisRef JKQTPVerticalAxis::getOtherAxisRef() const { return otherAxisRef; } const JKQTPCoordinateAxis *JKQTPVerticalAxis::getOtherAxis() const { return parent->getXAxis(otherAxisRef); } double JKQTPVerticalAxis::getParentOtheraxisWidth() const { return fabs(getOtherAxis()->x2p(getOtherAxis()->getMax())-getOtherAxis()->x2p(getOtherAxis()->getMin())); } bool JKQTPVerticalAxis::getParentOtheraxisInverted() const { return getOtherAxis()->getInverted(); } JKQTPVerticalIndependentAxis::JKQTPVerticalIndependentAxis(double _axisOffset, double _axisWidth, double _otherAxisOffset, double _otherAxisWidth, JKQTBasePlotter* parent): JKQTPVerticalAxisBase(parent), axisOffset(_axisOffset), axisWidth(_axisWidth), otherAxisWidth(_otherAxisOffset), otherAxisOffset(_otherAxisWidth), otherAxisInverted(false) { if (parent) { axisStyle=parent->getCurrentPlotterStyle().rightColorbarAxisStyle; } else { axisStyle=JKQTPGetSystemDefaultBaseStyle().rightColorbarAxisStyle; } } void JKQTPVerticalIndependentAxis::setAxisOffset(double __value) { this->axisOffset = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPVerticalIndependentAxis::setAxisWidth(double __value) { this->axisWidth = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPVerticalIndependentAxis::setOtherAxisOffset(double __value) { this->otherAxisOffset = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPVerticalIndependentAxis::setOtherAxisWidth(double __value) { this->otherAxisWidth = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPVerticalIndependentAxis::setOtherAxisInverted(bool __value) { this->otherAxisInverted = __value; this->paramsChanged=true; redrawPlot(); } double JKQTPVerticalIndependentAxis::getParentPlotWidth() const { return axisWidth; } double JKQTPVerticalIndependentAxis::getParentPlotOffset() const { return axisOffset; } double JKQTPVerticalIndependentAxis::getParentOtheraxisWidth() const { return otherAxisWidth; } bool JKQTPVerticalIndependentAxis::getParentOtheraxisInverted() const { return otherAxisInverted; } double JKQTPVerticalIndependentAxis::getParentOtheraxisOffset() const { return otherAxisOffset; } double JKQTPVerticalIndependentAxis::parentOtherAxisX2P(double /*x*/) const { return qQNaN(); } JKQTPHorizontalAxisBase::JKQTPHorizontalAxisBase(JKQTBasePlotter* parent): JKQTPCoordinateAxis(parent) { //axisPrefix="xaxis_"; scaleSign=1; if (parent) { axisStyle=parent->getCurrentPlotterStyle().xAxisStyle; } else { axisStyle=JKQTPGetSystemDefaultBaseStyle().xAxisStyle; } } JKQTPCoordinateAxis::Axis0ElementsSizeDescription JKQTPHorizontalAxisBase::getSize0(JKQTPEnhancedPainter& painter) { if (axisStyle.drawMode0==JKQTPCADMnone) return Axis0ElementsSizeDescription(); Axis0ElementsSizeDescription res; double ptheight=0; double ptheight_t=0; const double arrowSize=((axisStyle.drawMode0&(JKQTPCADMMinArrow|JKQTPCADMMinFilledArrow|JKQTPCADMMaxArrow|JKQTPCADMMaxFilledArrow))!=int(0))?(axisStyle.getArrowSize(painter, parent)/2.0):0.0; double labheight=0; if (axisStyle.drawMode0.testFlag(JKQTPCADMTicks)) { ptheight+=axisStyle.tickOutsideLength; ptheight_t+=axisStyle.tickOutsideLength; } if (axisStyle.drawMode0.testFlag(JKQTPCADMTickLabels)) { ptheight+=axisStyle.tickLabelDistance; // find out the maximum width over all visible plot labels const QSizeF maxLabelSize=getMaxTickLabelSize(painter); if (getTickLabelAngle()<-0.0000001) res.elongateMin=maxLabelSize.width()+2; else if (getTickLabelAngle()<0.0000001) res.elongateMin=maxLabelSize.width()*0.6+2; if (getTickLabelAngle()>0.0000001) res.elongateMax=maxLabelSize.width()+2; else if (getTickLabelAngle()>-0.0000001) res.elongateMax=maxLabelSize.width()*0.6+2; labheight+=maxLabelSize.height(); } if (axisStyle.drawMode0.testFlag(JKQTPCADMAxisLabel)) { const auto labSize=parent->getTextSizeDetail(getParent()->getCurrentPlotterStyle().defaultFontName, axisStyle.labelFontSize*parent->getFontSizeMultiplier(), axisLabel, painter); if (axisStyle.labelPosition==JKQTPLabelMinBesides) { labheight=qMax(labheight, labSize.getDescent()); res.elongateMin=qMax(res.elongateMin, parent->pt2px(painter, axisStyle.labelDistance)*1.5+labSize.width); } else if (axisStyle.labelPosition==JKQTPLabelMaxBesides) { labheight=qMax(labheight, labSize.getDescent()); res.elongateMax=qMax(res.elongateMax, parent->pt2px(painter, axisStyle.labelDistance)*1.5+labSize.width); } else { ptheight+=axisStyle.labelDistance; // find out size of axis label labheight+=labSize.overallHeight; } } const double zaxispos=getZeroAxisPos(); const double left=x2p(axismin); const double left_offset=zaxispos-left; const double right=x2p(axismax); const double right_offset=right-zaxispos; res.requiredSize=qMax(0.0,qMax(arrowSize,parent->pt2px(painter, ptheight)+labheight)-left_offset); res.requiredSizeOpposite=qMax(0.0,qMax(arrowSize,parent->pt2px(painter, ptheight_t))-right_offset); return res; } JKQTPCoordinateAxis::AxisElementsSizeDescription JKQTPHorizontalAxisBase::getSize1(JKQTPEnhancedPainter& painter) { const double insidefactor=(isSecondaryAxis()) ? 1.0 : 0.0; AxisElementsSizeDescription res; if (axisStyle.drawMode1!=JKQTPCADMnone) { double ptheight=axisStyle.axisLineOffset; const double arrowSize=((axisStyle.drawMode1&(JKQTPCADMMinArrow|JKQTPCADMMinFilledArrow|JKQTPCADMMaxArrow|JKQTPCADMMaxFilledArrow))!=int(0))?(axisStyle.getArrowSize(painter, parent)/2.0):0.0; double labheight=0; if (axisStyle.drawMode1.testFlag(JKQTPCADMTicks)) ptheight+=qMax(axisStyle.tickOutsideLength,axisStyle.minorTickOutsideLength)+insidefactor*qMax(axisStyle.minorTickInsideLength,axisStyle.tickInsideLength); if (axisStyle.drawMode1.testFlag(JKQTPCADMTickLabels)) { ptheight+=axisStyle.tickLabelDistance; // find out the maximum width over all visible plot labels const QSizeF maxLabelSize=getMaxTickLabelSize(painter); if (getTickLabelAngle()<-0.0000001) res.elongateMin=maxLabelSize.width()+2; else if (getTickLabelAngle()<0.0000001) res.elongateMin=maxLabelSize.width()*0.6+2; if (getTickLabelAngle()>0.0000001) res.elongateMax=maxLabelSize.width()+2; else if (getTickLabelAngle()>-0.0000001) res.elongateMax=maxLabelSize.width()*0.6+2; labheight+=maxLabelSize.height(); } if (axisStyle.drawMode1.testFlag(JKQTPCADMAxisLabel)) { const auto labSize=parent->getTextSizeDetail(getParent()->getCurrentPlotterStyle().defaultFontName, axisStyle.labelFontSize*parent->getFontSizeMultiplier(), axisLabel, painter); if (axisStyle.labelPosition==JKQTPLabelMinBesides) { labheight=qMax(labheight, labSize.getDescent()); res.elongateMin=qMax(res.elongateMin, parent->pt2px(painter, axisStyle.labelDistance)*1.5+labSize.width); } else if (axisStyle.labelPosition==JKQTPLabelMaxBesides) { labheight=qMax(labheight, labSize.getDescent()); res.elongateMax=qMax(res.elongateMax, parent->pt2px(painter, axisStyle.labelDistance)*1.5+labSize.width); } else { ptheight+=axisStyle.labelDistance; // find out size of axis label labheight+=labSize.overallHeight; } } res.requiredSize=qMax(arrowSize,parent->pt2px(painter, ptheight)+labheight); } const auto size0=getSize0(painter); res.elongateMax=qMax(res.elongateMax, size0.elongateMax); res.elongateMin=qMax(res.elongateMin, size0.elongateMin); res.requiredSize=qMax(res.requiredSize, size0.requiredSize); return res; } QSizeF JKQTPHorizontalAxisBase::getQSize1(JKQTPEnhancedPainter &painter) { return QSizeF(getParentPlotWidth(), getSize1(painter).requiredSize); } JKQTPCoordinateAxis::AxisElementsSizeDescription JKQTPHorizontalAxisBase::getSize2(JKQTPEnhancedPainter& painter) { const double insidefactor=(isSecondaryAxis()) ? 1.0 : 0.0; AxisElementsSizeDescription res; if (axisStyle.drawMode2!=JKQTPCADMnone) { double ptheight=axisStyle.axisLineOffset; const double arrowSize=((axisStyle.drawMode2&(JKQTPCADMMinArrow|JKQTPCADMMinFilledArrow|JKQTPCADMMaxArrow|JKQTPCADMMaxFilledArrow))!=int(0))?(axisStyle.getArrowSize(painter, parent)/2.0):0.0; double labheight=0; if (axisStyle.drawMode2.testFlag(JKQTPCADMTicks)) ptheight+=qMax(axisStyle.tickOutsideLength,axisStyle.minorTickOutsideLength)+insidefactor*qMax(axisStyle.minorTickInsideLength,axisStyle.tickInsideLength); if (axisStyle.drawMode2.testFlag(JKQTPCADMTickLabels)) { ptheight+=axisStyle.tickLabelDistance; // find out the maximum width over all visible plot labels const QSizeF maxLabelSize=getMaxTickLabelSize(painter); if (getTickLabelAngle()<-0.0000001) res.elongateMin=maxLabelSize.width()+2; else if (getTickLabelAngle()<0.0000001) res.elongateMin=maxLabelSize.width()*0.6+2; if (getTickLabelAngle()>0.0000001) res.elongateMax=maxLabelSize.width()+2; else if (getTickLabelAngle()>-0.0000001) res.elongateMax=maxLabelSize.width()*0.6+2; labheight+=maxLabelSize.height(); } if (axisStyle.drawMode2.testFlag(JKQTPCADMAxisLabel)) { const auto labSize=parent->getTextSizeDetail(getParent()->getCurrentPlotterStyle().defaultFontName, axisStyle.labelFontSize*parent->getFontSizeMultiplier(), axisLabel, painter); if (axisStyle.labelPosition==JKQTPLabelMinBesides) { labheight=qMax(labheight, labSize.getAscent()); res.elongateMin=qMax(res.elongateMin, parent->pt2px(painter, axisStyle.labelDistance)*1.5+labSize.width); } else if (axisStyle.labelPosition==JKQTPLabelMaxBesides) { labheight=qMax(labheight, labSize.getAscent()); res.elongateMax=qMax(res.elongateMax, parent->pt2px(painter, axisStyle.labelDistance)*1.5+labSize.width); } else { ptheight+=axisStyle.labelDistance; // find out size of axis label labheight+=labSize.overallHeight; } } res.requiredSize=qMax(arrowSize,parent->pt2px(painter, ptheight)+labheight); } const auto size0=getSize0(painter); res.elongateMax=qMax(res.elongateMax, size0.elongateMax); res.elongateMin=qMax(res.elongateMin, size0.elongateMin); res.requiredSize=qMax(res.requiredSize, size0.requiredSizeOpposite); return res; } QSizeF JKQTPHorizontalAxisBase::getQSize2(JKQTPEnhancedPainter &painter) { return QSizeF(getParentPlotWidth(), getSize2(painter).requiredSize); } void JKQTPHorizontalAxisBase::drawGrids(JKQTPEnhancedPainter& painter) { painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); //double right=x2p(axismax); //double left=x2p(axismin); double bottom=0; double top=0; if (getParentOtheraxisInverted()) { top=getParentOtheraxisOffset()-getParentOtheraxisWidth();//; bottom=getParentOtheraxisOffset();//; } else { top=getParentOtheraxisOffset();//; bottom=getParentOtheraxisOffset()+getParentOtheraxisWidth();//; } QPen pg=painter.pen(); pg.setColor(axisStyle.majorGridStyle.lineColor); pg.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.majorGridStyle.lineWidth*parent->getFontSizeMultiplier()))); pg.setStyle(axisStyle.majorGridStyle.lineStyle); QPen pmg=painter.pen(); pmg.setColor(axisStyle.minorGridStyle.lineColor); pmg.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.minorGridStyle.lineWidth*parent->getLineWidthMultiplier()))); pmg.setStyle(axisStyle.minorGridStyle.lineStyle); double x=tickStart; QString label=""; bool first=true; // loop through all labels, as they are at the major ticks int cnt=0; QVector lines_pg; QVector lines_pmg; while (getNextLabel(x, label, first) && cnt<200) { double mtdist=getNextLabelDistance(x)/static_cast(axisStyle.minorTicks+1); double xx=x2p(x); //qDebug()<<" tick @ x="<getCurrentPlotterStyle().debugRegionLineWidth/2.0); painter.setPen(p); painter.setBrush(QBrush(QColor(Qt::transparent))); painter.drawRect(rect); } } void JKQTPHorizontalAxisBase::drawAxisLabel2(JKQTPEnhancedPainter &painter, double left, double top, QSizeF labelMax, JKQTPCADrawMode drawMode) { const double labelOffset0=parent->pt2px(painter, axisStyle.labelDistance); double labelOffset=labelOffset0; if (drawMode.testFlag(JKQTPCADMTicks)) labelOffset+=parent->pt2px(painter, axisStyle.tickOutsideLength); if (drawMode.testFlag(JKQTPCADMTickLabels)) { labelOffset+=parent->pt2px(painter, axisStyle.tickLabelDistance); labelOffset+=labelMax.height();//+labelMax.height(); } getParentMathText()->setFontSize(axisStyle.labelFontSize*parent->getFontSizeMultiplier()); getParentMathText()->setFontSpecial(getParent()->getCurrentPlotterStyle().defaultFontName); getParentMathText()->setFontColor(axisStyle.labelColor); getParentMathText()->parse(axisLabel); const auto labSize=getParentMathText()->getSizeDetail(painter); QRectF rect(0,0, getParentPlotWidth(), labSize.overallHeight); QPointF pos0(left, top-labelOffset-rect.height()); Qt::Alignment align=Qt::AlignBottom|Qt::AlignHCenter; if (axisStyle.labelPosition==JKQTPLabelMaxBesides) { rect=QRectF(0,0, labSize.width, labSize.overallHeight); pos0=QPointF(left+getParentPlotWidth()+labelOffset0, top-labSize.baselineHeight); align=Qt::AlignBottom|Qt::AlignLeft; } else if (axisStyle.labelPosition==JKQTPLabelMinBesides) { rect=QRectF(0,0, labSize.width, labSize.overallHeight); pos0=QPointF(left-labelOffset0-labSize.width, top-labSize.baselineHeight); align=Qt::AlignBottom|Qt::AlignRight; } else if (axisStyle.labelPosition==JKQTPLabelMin) { align=Qt::AlignBottom|Qt::AlignLeft; } else if (axisStyle.labelPosition==JKQTPLabelMax) { align=Qt::AlignBottom|Qt::AlignRight; } else if (axisStyle.labelPosition==JKQTPLabelCenter) { align=Qt::AlignBottom|Qt::AlignHCenter; } painter.save(); auto __finalpaintinner=JKQTPFinally([&painter]() {painter.restore();}); painter.translate(pos0); getParentMathText()->draw(painter, align, rect, parent->getCurrentPlotterStyle().debugShowTextBoxes); if (getParent()->getCurrentPlotterStyle().debugShowRegionBoxes) { painter.save(); auto __finalpaintinnerif=JKQTPFinally([&painter]() {painter.restore();}); QPen p("magenta"); QColor col=p.color(); col.setAlphaF(0.8f); p.setColor(col); p.setWidthF(getParent()->getCurrentPlotterStyle().debugRegionLineWidth/2.0); painter.setPen(p); painter.setBrush(QBrush(QColor(Qt::transparent))); painter.drawRect(rect); } //painter.resetTransform(); } void JKQTPHorizontalAxisBase::drawAxes(JKQTPEnhancedPainter& painter, int move1, int move2) { #ifdef JKQTBP_AUTOTIMER JKQTPAutoOutputTimer jkaat(QString("JKQTPHorizontalAxis[%1]::drawAxes()").arg(objectName())); #endif const bool isSecondAxis=isSecondaryAxis(); // correct move1,move2 for the length of inside ticks for secondary axes double moveForTicks1=0, moveForTicks2=0; if (isSecondAxis && axisStyle.drawMode1.testFlag(JKQTPCADMTicks)) moveForTicks1=qMax(axisStyle.minorTickInsideLength,axisStyle.tickInsideLength); if (isSecondAxis && axisStyle.drawMode2.testFlag(JKQTPCADMTicks)) moveForTicks2=qMax(axisStyle.minorTickInsideLength,axisStyle.tickInsideLength); // make shure all parameters are calculated correctly calcPlotScaling(); // determine pixel coordinates of important positions double right=x2p(axismax); double left=x2p(axismin); double bottom=0; double top=0; if (inverted) { qSwap(left, right); } if (getParentOtheraxisInverted()) { top=getParentOtheraxisOffset()-getParentOtheraxisWidth();//; bottom=getParentOtheraxisOffset();//; } else { top=getParentOtheraxisOffset();//; bottom=getParentOtheraxisOffset()+getParentOtheraxisWidth();//; } // move axes outside plot rectangle, if required top-=parent->pt2px(painter, axisStyle.axisLineOffset)+move2+moveForTicks2; bottom+=parent->pt2px(painter, axisStyle.axisLineOffset)+move1+moveForTicks1; double ticklabelOffset1PT=axisStyle.tickLabelDistance; // offset of tick labels from axis 1 double minorticklabelOffset1PT=axisStyle.tickLabelDistance; // offset ofminor tick labels from axis 1 if (axisStyle.drawMode1.testFlag(JKQTPCADMTicks)) { ticklabelOffset1PT+=axisStyle.tickOutsideLength; minorticklabelOffset1PT+=axisStyle.minorTickOutsideLength; } double ticklabelOffset2PT=axisStyle.tickLabelDistance; // offset of tick labels from axis 2 double minorticklabelOffset2PT=axisStyle.tickLabelDistance; // offset ofminor tick labels from axis 2 if (axisStyle.drawMode2.testFlag(JKQTPCADMTicks)) { ticklabelOffset2PT+=axisStyle.tickOutsideLength; minorticklabelOffset2PT+=axisStyle.minorTickOutsideLength; } double ticklabelOffset0PT=axisStyle.tickLabelDistance; // offset of tick labels from axis 0 double minorticklabelOffset0PT=axisStyle.tickLabelDistance; // offset ofminor tick labels from axis 0 if (axisStyle.drawMode0.testFlag(JKQTPCADMTicks)) { ticklabelOffset0PT+=axisStyle.tickOutsideLength; minorticklabelOffset0PT+=axisStyle.minorTickOutsideLength; } //qDebug()<<" left="<setFontSize(this->axisStyle.tickLabelFontSize*parent->getFontSizeMultiplier()); getParentMathText()->setFontSpecial(getParent()->getCurrentPlotterStyle().defaultFontName); getParentMathText()->setFontColor(axisStyle.axisColor); // plot thick axis at y==0 if (axisStyle.showZeroAxis && (0>axismin) && (00) painter.drawLine(l); } painter.setPen(pmain); painter.setBrush(pmain.color()); // axis 0 properties bool drawZeroAxis=false; const double zeroaxispos=getZeroAxisPos(&drawZeroAxis); // draw thick axis lines, left and/or right if (axisStyle.drawMode1.testFlag(JKQTPCADMLine)) { const QLineF l(x2p(axismin), bottom, x2p(axismax), bottom); drawAxisLine(painter, l, axisStyle.drawMode1); } if (axisStyle.drawMode2.testFlag(JKQTPCADMLine)) { const QLineF l(x2p(axismin), top, x2p(axismax), top); drawAxisLine(painter, l, axisStyle.drawMode2); } if (axisStyle.drawMode0.testFlag(JKQTPCADMLine)) { const QLineF l(x2p(axismin), zeroaxispos, x2p(axismax), zeroaxispos); drawAxisLine(painter, l, axisStyle.drawMode0); } painter.setBrush(Qt::NoBrush); // plot minor and major ticks + tick labels double ascentMax, descentMax; QSizeF labelMax=getMaxTickLabelSize(painter, &ascentMax, &descentMax); double x=tickStart; QString label=""; bool first=true; // loop through all labels, as they are at the major ticks int cnt=0; QVector lines_ptick, lines_ptick2, lines_ptick0; QVector lines_pmtick, lines_pmtick2, lines_pmtick0; const double arrowFreeSpace=axisStyle.getArrowSize(painter, parent)*1.2; { #ifdef JKQTBP_AUTOTIMER JKQTPAutoOutputTimer jkaati(QString("JKQTPHorizontalAxis[%1]::drawAxes(): calcLabels").arg(objectName())); #endif while (getNextLabel(x, label, first) && cnt<200) { const double mtdist=getNextLabelDistance(x)/static_cast(axisStyle.minorTicks+1); const double xx=x2p(x); //qDebug()<<" tick @ x="<getCurrentPlotterStyle().debugShowRegionBoxes) { painter.save(); auto __finalpaintif=JKQTPFinally([&painter]() {painter.restore();}); QPen p("cyan"); if (isSecondAxis) p=QPen("darkcyan"); QColor col=p.color(); col.setAlphaF(0.6f); p.setColor(col); p.setWidthF(getParent()->getCurrentPlotterStyle().debugRegionLineWidth); painter.setPen(p); painter.setBrush(QBrush(QColor(Qt::transparent))); const QSizeF s1(getParentPlotWidth(), getSize1(painter).requiredSize); const QSizeF s2(getParentPlotWidth(), getSize2(painter).requiredSize); painter.drawRect(QRectF(QPointF(left, bottom-moveForTicks1), s1)); painter.drawRect(QRectF(QPointF(left, top+moveForTicks2-s2.height()), s2)); } } JKQTPHorizontalAxis::JKQTPHorizontalAxis(JKQTBasePlotter* parent, JKQTPCoordinateAxisRef otherAxisRef_): JKQTPHorizontalAxisBase(parent), otherAxisRef(otherAxisRef_) { //axisPrefix="xaxis_"; scaleSign=1; if (parent) { axisStyle=parent->getCurrentPlotterStyle().xAxisStyle; } else { axisStyle=JKQTPGetSystemDefaultBaseStyle().xAxisStyle; } } double JKQTPHorizontalAxis::getParentPlotWidth() const { return parent->getPlotWidth(); } double JKQTPHorizontalAxis::getParentPlotOffset() const { return parent->getInternalPlotBorderLeft(); } double JKQTPHorizontalAxis::getParentOtheraxisOffset() const { return getOtherAxis()->x2p(getOtherAxis()->getMax()); } double JKQTPHorizontalAxis::parentOtherAxisX2P(double x) const { return parent->y2p(x); } JKQTPCoordinateAxisRef JKQTPHorizontalAxis::getOtherAxisRef() const { return otherAxisRef; } const JKQTPCoordinateAxis *JKQTPHorizontalAxis::getOtherAxis() const { return parent->getYAxis(otherAxisRef); } double JKQTPHorizontalAxis::getParentOtheraxisWidth() const { return fabs(getOtherAxis()->x2p(getOtherAxis()->getMax())-getOtherAxis()->x2p(getOtherAxis()->getMin())); } bool JKQTPHorizontalAxis::getParentOtheraxisInverted() const { return getOtherAxis()->getInverted(); } JKQTPHorizontalIndependentAxis::JKQTPHorizontalIndependentAxis(double _axisOffset, double _axisWidth, double _otherAxisOffset, double _otherAxisWidth, JKQTBasePlotter* parent): JKQTPHorizontalAxis(parent), axisOffset(_axisOffset), axisWidth(_axisWidth), otherAxisWidth(_otherAxisOffset), otherAxisOffset(_otherAxisWidth), otherAxisInverted(false) { if (parent) { axisStyle=parent->getCurrentPlotterStyle().topColorbarAxisStyle; } else { axisStyle=JKQTPGetSystemDefaultBaseStyle().topColorbarAxisStyle; } } void JKQTPHorizontalIndependentAxis::setAxisOffset(double __value) { this->axisOffset = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPHorizontalIndependentAxis::setAxisWidth(double __value) { this->axisWidth = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPHorizontalIndependentAxis::setOtherAxisOffset(double __value) { this->otherAxisOffset = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPHorizontalIndependentAxis::setOtherAxisWidth(double __value) { this->otherAxisWidth = __value; this->paramsChanged=true; redrawPlot(); } void JKQTPHorizontalIndependentAxis::setOtherAxisInverted(bool __value) { this->otherAxisInverted = __value; this->paramsChanged=true; redrawPlot(); } double JKQTPHorizontalIndependentAxis::getParentPlotWidth() const { return axisWidth; } double JKQTPHorizontalIndependentAxis::getParentPlotOffset() const { return axisOffset; } double JKQTPHorizontalIndependentAxis::getParentOtheraxisWidth() const { return otherAxisWidth; } bool JKQTPHorizontalIndependentAxis::getParentOtheraxisInverted() const { return otherAxisInverted; } double JKQTPHorizontalIndependentAxis::getParentOtheraxisOffset() const { return otherAxisOffset; } double JKQTPHorizontalIndependentAxis::parentOtherAxisX2P(double /*x*/) const { return qQNaN(); }