/* 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 //#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() { //if (paramsChanged) { calcPlotScaling(); parent->redrawPlot(); //} } JKQTMathText* JKQTPCoordinateAxis::getParentMathText() { return parent->getMathText(); } const JKQTMathText* JKQTPCoordinateAxis::getParentMathText() const { 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) res=addTickUnit("("+res+QString("%1/%2").arg(num).arg(denom)+")"); } } } else { res=addTickUnit(res); } } //std::cout< "<(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(); } 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(); } std::pair JKQTPCoordinateAxis::getSize0(JKQTPEnhancedPainter &/*painter*/) { return std::pair(QSizeF(0,0),QSizeF(0,0)); } 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() = ["<getCurrentPlotterStyle().yAxisStyle; } else { axisStyle=JKQTPGetSystemDefaultBaseStyle().yAxisStyle; } } double JKQTPVerticalAxis::getParentPlotWidth() const { return parent->getPlotHeight(); } double JKQTPVerticalAxis::getParentPlotOffset() const { return parent->getInternalPlotBorderTop(); } std::pair JKQTPVerticalAxis::getSize0(JKQTPEnhancedPainter& painter) { if (axisStyle.drawMode0==JKQTPCADMnone) return std::pair(QSizeF(0,0),QSizeF(0,0)); 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; // find out the maximum width over all visible plot labels labwidth+=getMaxTickLabelSize(painter).width(); } if (axisStyle.drawMode0.testFlag(JKQTPCADMAxisLabel)) { ptwidth+=axisStyle.labelDistance; // find out size of axis label labwidth+=parent->getTextSizeSize(getParent()->getCurrentPlotterStyle().defaultFontName, axisStyle.labelFontSize*parent->getFontSizeMultiplier(), axisLabel, painter).height(); } 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); const QSizeF s1(qMax(0.0,qMax(parent->pt2px(painter, ptwidth)+labwidth, arrowSize)-bottom_offset), getParentPlotWidth()); const QSizeF s2(qMax(0.0,qMax(parent->pt2px(painter, ptwidth_r), arrowSize)-top_offset), getParentPlotWidth()); 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 JKQTPVerticalAxis::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 JKQTPVerticalAxis::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 JKQTPVerticalAxis::drawAxisLabel1(JKQTPEnhancedPainter &painter, double left, double bottom, QSizeF labelMax, JKQTPCADrawMode drawMode) { double labelOffset=parent->pt2px(painter, axisStyle.labelDistance); 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 JKQTMathTextNodeSize labelsize=getParentMathText()->getSizeDetail(painter); QRectF rect(0,0, getParentPlotWidth(), labelsize.overallHeight);//plotBorderLeft-30); painter.save(); auto __finalpaintiner=JKQTPFinally([&painter]() {painter.restore();}); painter.translate(QPointF(left-labelOffset-rect.height(), bottom)); painter.rotate(-90); //JKQTPEnhancedPainter::RenderHints h=painter.renderHints(); //painter.drawRect(rect); //painter.drawEllipse(-4, -4, 8, 8); switch(axisStyle.labelPosition) { case JKQTPLabelMax: getParentMathText()->draw(painter, Qt::AlignBottom|Qt::AlignRight, rect, parent->getCurrentPlotterStyle().debugShowTextBoxes); break; case JKQTPLabelMin: getParentMathText()->draw(painter, Qt::AlignBottom|Qt::AlignLeft, rect, parent->getCurrentPlotterStyle().debugShowTextBoxes); break; case JKQTPLabelCenter: getParentMathText()->draw(painter, Qt::AlignBottom|Qt::AlignHCenter, rect, parent->getCurrentPlotterStyle().debugShowTextBoxes); break; } 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 JKQTPVerticalAxis::drawAxisLabel2(JKQTPEnhancedPainter &painter, double right, double bottom, QSizeF labelMax, JKQTPCADrawMode drawMode) { double labelOffset=parent->pt2px(painter, axisStyle.labelDistance); 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 JKQTMathTextNodeSize labelsize=getParentMathText()->getSizeDetail(painter); QRectF rect(0,0, getParentPlotWidth(), labelsize.overallHeight);//plotBorderLeft-30); painter.save(); auto __finalpaintinner=JKQTPFinally([&painter]() {painter.restore();}); painter.translate(QPointF(right+labelOffset, bottom)); painter.rotate(-90); //JKQTPEnhancedPainter::RenderHints h=painter.renderHints(); //painter.drawRect(rect); //painter.drawEllipse(-4, -4, 8, 8); switch(axisStyle.labelPosition) { case JKQTPLabelMax: getParentMathText()->draw(painter, Qt::AlignBottom|Qt::AlignRight, rect, parent->getCurrentPlotterStyle().debugShowTextBoxes); break; case JKQTPLabelMin: getParentMathText()->draw(painter, Qt::AlignBottom|Qt::AlignLeft, rect, parent->getCurrentPlotterStyle().debugShowTextBoxes); break; case JKQTPLabelCenter: getParentMathText()->draw(painter, Qt::AlignBottom|Qt::AlignHCenter, rect, parent->getCurrentPlotterStyle().debugShowTextBoxes); break; } 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 JKQTPVerticalAxis::drawAxes(JKQTPEnhancedPainter& painter) { #ifdef JKQTBP_AUTOTIMER JKQTPAutoOutputTimer jkaat(QString("JKQTPEnhancedPainter[%1]::drawAxes()").arg(objectName())); #endif // 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); right+=parent->pt2px(painter, axisStyle.axisLineOffset); 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_pmtick.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_pmtick.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"); p.setWidthF(getParent()->getCurrentPlotterStyle().debugRegionLineWidth); QColor col=p.color(); col.setAlphaF(0.8f); p.setColor(col); painter.setPen(p); painter.setBrush(QBrush(QColor(Qt::transparent))); QSizeF s1, s2; s1=getSize1(painter); s2=getSize2(painter); painter.drawRect(QRectF(QPointF(left-s1.width(), top), s1)); painter.drawRect(QRectF(QPointF(right, top), s2)); } //qDebug()<<" end JKQTPVerticalAxis::drawAxes("; } JKQTPVerticalIndependentAxis::JKQTPVerticalIndependentAxis(double _axisOffset, double _axisWidth, double _otherAxisOffset, double _otherAxisWidth, JKQTBasePlotter* parent): JKQTPVerticalAxis(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(); } JKQTPHorizontalAxis::JKQTPHorizontalAxis(JKQTBasePlotter* parent): JKQTPCoordinateAxis(parent) { //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(); } std::pair JKQTPHorizontalAxis::getSize0(JKQTPEnhancedPainter& painter) { if (axisStyle.drawMode0==JKQTPCADMnone) return std::pair(QSizeF(0,0),QSizeF(0,0)); double ptheight=0; double ptheight_t=0; 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+=axisStyle.tickOutsideLength; ptheight_t+=axisStyle.tickOutsideLength; } if (axisStyle.drawMode1.testFlag(JKQTPCADMTickLabels)) { ptheight+=axisStyle.tickLabelDistance; // find out the maximum width over all visible plot labels labheight+=getMaxTickLabelSize(painter).height(); } if (axisStyle.drawMode1.testFlag(JKQTPCADMAxisLabel)) { ptheight+=axisStyle.labelDistance; // find out size of axis label labheight+=parent->getTextSizeSize(getParent()->getCurrentPlotterStyle().defaultFontName, axisStyle.labelFontSize*parent->getFontSizeMultiplier(), axisLabel, painter).height(); } 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; return std::pair( QSizeF(getParentPlotWidth(), qMax(0.0,qMax(arrowSize,parent->pt2px(painter, ptheight)+labheight)-left_offset)), QSizeF(getParentPlotWidth(), qMax(0.0,qMax(arrowSize,parent->pt2px(painter, ptheight_t))-right_offset)) ); } QSizeF JKQTPHorizontalAxis::getSize1(JKQTPEnhancedPainter& painter) { if (axisStyle.drawMode1==JKQTPCADMnone) return QSize(0,0); 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+=axisStyle.tickOutsideLength; if (axisStyle.drawMode1.testFlag(JKQTPCADMTickLabels)) { ptheight+=axisStyle.tickLabelDistance; // find out the maximum width over all visible plot labels labheight+=getMaxTickLabelSize(painter).height(); } if (axisStyle.drawMode1.testFlag(JKQTPCADMAxisLabel)) { ptheight+=axisStyle.labelDistance; // find out size of axis label labheight+=parent->getTextSizeSize(getParent()->getCurrentPlotterStyle().defaultFontName, axisStyle.labelFontSize*parent->getFontSizeMultiplier(), axisLabel, painter).height(); } return QSizeF(getParentPlotWidth(), qMax(arrowSize,parent->pt2px(painter, ptheight)+labheight)).expandedTo(getSize0(painter).first); } QSizeF JKQTPHorizontalAxis::getSize2(JKQTPEnhancedPainter& painter) { if (axisStyle.drawMode2==JKQTPCADMnone) return QSize(0,0); 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+=axisStyle.tickOutsideLength; if (axisStyle.drawMode2.testFlag(JKQTPCADMTickLabels)) { ptheight+=axisStyle.tickLabelDistance; // find out the maximum width over all visible plot labels labheight+=getMaxTickLabelSize(painter).height(); } if (axisStyle.drawMode2.testFlag(JKQTPCADMAxisLabel)) { ptheight+=axisStyle.labelDistance; // find out size of axis label labheight+=parent->getTextSizeSize(getParent()->getCurrentPlotterStyle().defaultFontName, axisStyle.labelFontSize*parent->getFontSizeMultiplier(), axisLabel, painter).height(); } return QSizeF(getParentPlotWidth(), qMax(arrowSize,parent->pt2px(painter, ptheight)+labheight)).expandedTo(getSize0(painter).second); } double JKQTPHorizontalAxis::getParentOtheraxisOffset() const { return parent->y2p(parent->getYMax()); } double JKQTPHorizontalAxis::parentOtherAxisX2P(double x) const { return parent->y2p(x); } double JKQTPHorizontalAxis::getParentOtheraxisWidth() const { return fabs(parent->y2p(parent->getYMax())-parent->y2p(parent->getYMin())); } bool JKQTPHorizontalAxis::getParentOtheraxisInverted() const { return parent->getYAxis()->getInverted(); } void JKQTPHorizontalAxis::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 JKQTPHorizontalAxis::drawAxisLabel2(JKQTPEnhancedPainter &painter, double left, double top, QSizeF labelMax, JKQTPCADrawMode drawMode) { double labelOffset=parent->pt2px(painter, axisStyle.labelDistance); 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); QRectF rect(0,0, getParentPlotWidth(), getParentMathText()->getSize(painter).height());//plotBorderLeft-30); painter.save(); auto __finalpaintinner=JKQTPFinally([&painter]() {painter.restore();}); painter.translate(QPointF(left, top-labelOffset-rect.height())); //JKQTPEnhancedPainter::RenderHints h=painter.renderHints(); //painter.drawRect(rect); //painter.drawEllipse(-4, -4, 8, 8); switch(axisStyle.labelPosition) { case JKQTPLabelMax: getParentMathText()->draw(painter, Qt::AlignBottom|Qt::AlignRight, rect, parent->getCurrentPlotterStyle().debugShowTextBoxes); break; case JKQTPLabelMin: getParentMathText()->draw(painter, Qt::AlignBottom|Qt::AlignLeft, rect, parent->getCurrentPlotterStyle().debugShowTextBoxes); break; case JKQTPLabelCenter: getParentMathText()->draw(painter, Qt::AlignBottom|Qt::AlignHCenter, rect, parent->getCurrentPlotterStyle().debugShowTextBoxes); break; } 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 JKQTPHorizontalAxis::drawAxes(JKQTPEnhancedPainter& painter) { #ifdef JKQTBP_AUTOTIMER JKQTPAutoOutputTimer jkaat(QString("JKQTPHorizontalAxis[%1]::drawAxes()").arg(objectName())); #endif // 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); bottom+=parent->pt2px(painter, axisStyle.axisLineOffset); 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"); QColor col=p.color(); col.setAlphaF(0.8f); p.setColor(col); p.setWidthF(getParent()->getCurrentPlotterStyle().debugRegionLineWidth); painter.setPen(p); painter.setBrush(QBrush(QColor(Qt::transparent))); QSizeF s1,s2; s1=getSize1(painter); s2=getSize2(painter); painter.drawRect(QRectF(QPointF(left, bottom), s1)); painter.drawRect(QRectF(QPointF(left, top-s2.height()), s2)); } } 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(); }