/* Copyright (c) 2008-2018 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 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/jkqtpbarchartelements.h" #include "jkqtplotter/jkqtpbaseplotter.h" #include #include #include #include "jkqtplottertools/jkqtptools.h" #include "jkqtplotter/jkqtpimageelements.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtplotter.h" #define SmallestGreaterZeroCompare_xvsgz() if ((xvsgz>10.0*DBL_MIN)&&((smallestGreaterZero<10.0*DBL_MIN) || (xvsgzgetNextStyle(); fillColor=parent->getPlotStyle(parentPlotStyle).color(); } } JKQTPbarVerticalGraph::JKQTPbarVerticalGraph(JKQtPlotter* parent): JKQTPxyGraph(parent) { baseline=0.0; color=QColor("black"); fillColor=QColor("red"); style=Qt::SolidLine; lineWidth=1; fillStyle=Qt::SolidPattern; width=0.9; shift=0; if (parent) { // get style settings from parent object parentPlotStyle=parent->getNextStyle(); fillColor=parent->getPlotStyle(parentPlotStyle).color(); } } void JKQTPbarVerticalGraph::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) { painter.save(); QPen p=painter.pen(); QPen np(Qt::NoPen); p.setColor(color); p.setStyle(style); QBrush b=painter.brush(); b.setColor(fillColor); b.setStyle(fillStyle); //int y=rect.top()+rect.height()/2.0; painter.setPen(p); painter.setBrush(b); painter.drawRect(rect); painter.restore(); } QColor JKQTPbarVerticalGraph::getKeyLabelColor() { return fillColor; } void JKQTPbarVerticalGraph::draw(JKQTPEnhancedPainter& painter) { #ifdef JKQTBP_AUTOTIMER JKQTPAutoOutputTimer jkaaot("JKQTPbarHorizontalGraph::draw"); #endif if (parent==nullptr) return; JKQTPdatastore* datastore=parent->getDatastore(); if (datastore==nullptr) return; drawErrorsBefore(painter); QPen p=painter.pen(); p.setColor(color); p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, lineWidth*parent->get_lineWidthMultiplier()))); p.setStyle(style); p.setJoinStyle(Qt::RoundJoin); QBrush b=painter.brush(); b.setColor(fillColor); b.setStyle(fillStyle); int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); int imin=0; // interpret data ranges if (datarange_start>-1) { imin=qMin(datarange_start, static_cast(imax)); } if (datarange_end>-1) { imax=qMin(datarange_end+1, static_cast(imax)); } if (imaxx2p(0); // if (parent->getXAxis()->isLogAxis()) x0=xAxis->x2p(parent->getXAxis()->getMin()); double y0=yAxis->x2p(0); if (parent->getYAxis()->isLogAxis()) y0=yAxis->x2p(parent->getYAxis()->getMin()); double delta=1; double deltap=0; double deltam=0; intSortData(); const bool hasStackPar=hasStackParent(); for (int iii=imin; iiiget(static_cast(xColumn),static_cast(i)); int sr=datastore->getNextLowerIndex(xColumn, i, datarange_start, datarange_end); int lr=datastore->getNextHigherIndex(xColumn, i, datarange_start, datarange_end); double yv=datastore->get(static_cast(yColumn),static_cast(i)); double yv0=y0; if (!qFuzzyIsNull(baseline)) yv0=yAxis->x2p(baseline); if (hasStackPar) { double stackLastY=getParentStackedMax(i); const double yvold=yv; yv0=yAxis->x2p(stackLastY)-(get_lineWidth()); yv=stackLastY+yvold; } if (sr<0 && lr<0) { // only one x-value deltam=0.5; deltap=0.5; } else if (lr<0) { // the right-most x-value deltap=deltam=fabs(xv-datastore->get(xColumn,sr))/2.0; } else if (sr<0) { // the left-most x-value deltam=deltap=fabs(datastore->get(xColumn,lr)-xv)/2.0; } else { deltam=fabs(xv-datastore->get(xColumn,sr))/2.0; deltap=fabs(datastore->get(xColumn,lr)-xv)/2.0; } //std::cout<x2p(xv+shift*delta-width*deltam); double y=yAxis->x2p(yv); double xx=xAxis->x2p(xv+shift*delta+width*deltap); double yy=yv0; //std::cout<<"delta="<getDatastore(); if (datastore==nullptr) return; drawErrorsBefore(painter); QPen p=painter.pen(); p.setColor(color); p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, lineWidth*parent->get_lineWidthMultiplier()))); p.setStyle(style); p.setJoinStyle(Qt::RoundJoin); QBrush b=painter.brush(); b.setColor(fillColor); b.setStyle(fillStyle); int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); int imin=0; // interpret data ranges if (datarange_start>-1) { imin=qMin(datarange_start, static_cast(imax)); } if (datarange_end>-1) { imax=qMin(datarange_end+1, static_cast(imax)); } if (imaxx2p(0); if (parent->getXAxis()->isLogAxis()) x0=xAxis->x2p(parent->getXAxis()->getMin()); // double y0=yAxis->x2p(0); // if (parent->getYAxis()->isLogAxis()) y0=yAxis->x2p(parent->getYAxis()->getMin()); double delta=1; double deltap=0; double deltam=0; painter.save(); intSortData(); const bool hasStackPar=hasStackParent(); for (int iii=imin; iiiget(static_cast(xColumn),static_cast(i)); double yv=datastore->get(static_cast(yColumn),static_cast(i)); int sr=datastore->getNextLowerIndex(yColumn, i, datarange_start, datarange_end); int lr=datastore->getNextHigherIndex(yColumn, i, datarange_start, datarange_end); double xv0=x0; if (!qFuzzyIsNull(baseline)) xv0=xAxis->x2p(baseline); if (hasStackPar) { double stackLastX=getParentStackedMax(i); const double xvold=xv; xv0=xAxis->x2p(stackLastX)+(get_lineWidth()); xv=stackLastX+xvold; } if (sr<0 && lr<0) { // only one y-value deltam=0.5; deltap=0.5; } else if (lr<0) { // the right-most y-value deltap=deltam=fabs(yv-datastore->get(yColumn,sr))/2.0; } else if (sr<0) { // the left-most y-value deltam=deltap=fabs(datastore->get(yColumn,lr)-yv)/2.0; } else { deltam=fabs(yv-datastore->get(yColumn,sr))/2.0; deltap=fabs(datastore->get(yColumn,lr)-yv)/2.0; } delta=deltap+deltam; if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv)) { double x=xv0; if (!qFuzzyIsNull(baseline)) x=xAxis->x2p(baseline); double y=yAxis->x2p(yv+shift*delta+width*deltap); double xx=xAxis->x2p(xv); double yy=yAxis->x2p(yv+shift*delta-width*deltam); if (x>xx) { qSwap(x,xx); } //qDebug()<<"delta="<0) { smallestGreaterZero=baseline; minx=baseline; maxx=baseline; } if (parent==nullptr) return false; JKQTPdatastore* datastore=parent->getDatastore(); int imin=0; int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(xColumn)).getRows()); // interpret data ranges if (datarange_start>-1) { imin=qMin(datarange_start, static_cast(imax)); } if (datarange_end>-1) { imax=qMin(datarange_end, static_cast(imax)); } if (imaxmaxx) maxx=xv; if (xvget(static_cast(xColumn),static_cast(i)); if (JKQTPIsOKFloat(xv)) { if (xv>maxx) maxx=xv; if (xvgetDatastore(); int imin=0; int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); // interpret data ranges if (datarange_start>-1) { imin=qMin(datarange_start, static_cast(imax)); } if (datarange_end>-1) { imax=qMin(datarange_end, static_cast(imax)); } if (imaxget(static_cast(yColumn),static_cast(i)); double delta, deltap, deltam; int sr=datastore->getNextLowerIndex(yColumn, i, datarange_start, datarange_end); int lr=datastore->getNextHigherIndex(yColumn, i, datarange_start, datarange_end); if (sr<0 && lr<0) { // only one y-value deltam=0.5; deltap=0.5; } else if (lr<0) { // the right-most y-value deltap=deltam=fabs(yv-datastore->get(yColumn,sr))/2.0; } else if (sr<0) { // the left-most y-value deltam=deltap=fabs(datastore->get(yColumn,lr)-yv)/2.0; } else { deltam=fabs(yv-datastore->get(yColumn,sr))/2.0; deltap=fabs(datastore->get(yColumn,lr)-yv)/2.0; } delta=deltap+deltam; if (JKQTPIsOKFloat(yv) && JKQTPIsOKFloat(delta) ) { if (start || yv+shift*delta+width*delta/2.0>maxy) maxy=yv+shift*delta+width*delta/2.0; if (start || yv+shift*delta-width*delta/2.0pt2px(painter, parent->get_lineWidthMultiplier()*lineWidth))); p.setStyle(style); p.setJoinStyle(Qt::RoundJoin); p.setCapStyle(Qt::RoundCap); return p; } double JKQTPbarVerticalGraph::getParentStackedMax(int /*index*/) const { return false; } bool JKQTPbarVerticalGraph::hasStackParent() const { return false; } double JKQTPbarVerticalGraph::getStackedMax(int /*index*/) const { return baseline; } bool JKQTPbarVerticalGraph::isHorizontal() const { return false; } void JKQTPbarVerticalGraph::set_fillColor_and_darkenedColor(QColor fill, int colorDarker) { set_fillColor(fill); set_color(fill.darker(colorDarker)); } JKQTPbarHorizontalErrorGraph::JKQTPbarHorizontalErrorGraph(JKQtBasePlotter *parent): JKQTPbarHorizontalGraph(parent), JKQTPxGraphErrors() { setErrorColorFromGraphColor(color); } JKQTPbarHorizontalErrorGraph::JKQTPbarHorizontalErrorGraph(JKQtPlotter *parent): JKQTPbarHorizontalGraph(parent), JKQTPxGraphErrors() { setErrorColorFromGraphColor(color); } bool JKQTPbarHorizontalErrorGraph::usesColumn(int c) { return JKQTPbarHorizontalGraph::usesColumn(c)|| JKQTPxGraphErrors::errorUsesColumn(c); } bool JKQTPbarHorizontalErrorGraph::getXMinMax(double &minx, double &maxx, double &smallestGreaterZero) { if (xErrorColumn<0 || xErrorStyle==JKQTPnoError) { return JKQTPbarHorizontalGraph::getXMinMax(minx, maxx, smallestGreaterZero); } else { bool start=false; minx=0; maxx=0; smallestGreaterZero=0; if (parent==nullptr) return false; JKQTPdatastore* datastore=parent->getDatastore(); int imin=0; int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); // interpret data ranges if (datarange_start>-1) { imin=qMin(datarange_start, static_cast(imax)); } if (datarange_end>-1) { imax=qMin(datarange_end, static_cast(imax)); } if (imaxget(static_cast(xColumn),static_cast(i))+getXErrorU(i, datastore); double xvv=datastore->get(static_cast(xColumn),static_cast(i))-getXErrorL(i, datastore); if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(xvv) ) { if (start || xv>maxx) maxx=xv; if (start || xvmaxx) maxx=xvv; if (start || xvv0) { smallestGreaterZero=baseline; miny=baseline; maxy=baseline; } if (parent==nullptr) return false; JKQTPdatastore* datastore=parent->getDatastore(); int imin=0; int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); // interpret data ranges if (datarange_start>-1) { imin=qMin(datarange_start, static_cast(imax)); } if (datarange_end>-1) { imax=qMin(datarange_end, static_cast(imax)); } if (imaxmaxy) maxy=yv; if (yvget(static_cast(yColumn),static_cast(i)); if (JKQTPIsOKFloat(yv)) { if (yv>maxy) maxy=yv; if (yv0) { smallestGreaterZero=baseline; miny=baseline; maxy=baseline; } if (parent==nullptr) return false; JKQTPdatastore* datastore=parent->getDatastore(); int imin=0; int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); // interpret data ranges if (datarange_start>-1) { imin=qMin(datarange_start, static_cast(imax)); } if (datarange_end>-1) { imax=qMin(datarange_end, static_cast(imax)); } if (imaxget(static_cast(yColumn),static_cast(i))+getYErrorU(i, datastore); double yvv=datastore->get(static_cast(yColumn),static_cast(i))-getYErrorL(i, datastore); if (JKQTPIsOKFloat(yv) && JKQTPIsOKFloat(yvv) ) { if (start || yv>maxy) maxy=yv; if (start || yvmaxy) maxy=yvv; if (start || yvvgetStackedMax(index); } else { return 0.0; } } bool JKQTPbarVerticalStackableGraph::hasStackParent() const { return stackParent!=nullptr; } const JKQTPbarVerticalStackableGraph *JKQTPbarVerticalStackableGraph::getStackParent() const { return stackParent; } double JKQTPbarVerticalStackableGraph::getStackedMax(int index) const { double height=0; if (parent!=nullptr) { JKQTPdatastore* datastore=parent->getDatastore(); height=datastore->get(static_cast(yColumn),static_cast(index)); } if (stackParent==nullptr) { return height; } else { return stackParent->getStackedMax(index)+height; } } JKQTPbarHorizontalStackableGraph::JKQTPbarHorizontalStackableGraph(JKQtBasePlotter *parent): JKQTPbarHorizontalGraph(parent), stackParent(nullptr) { } JKQTPbarHorizontalStackableGraph::JKQTPbarHorizontalStackableGraph(JKQtPlotter *parent): JKQTPbarHorizontalGraph(parent), stackParent(nullptr) { } void JKQTPbarHorizontalStackableGraph::stackUpon(JKQTPbarHorizontalStackableGraph *parentGraph) { stackParent=parentGraph; } void JKQTPbarHorizontalStackableGraph::dontStackUpon() { stackParent=nullptr; } const JKQTPbarHorizontalStackableGraph *JKQTPbarHorizontalStackableGraph::getStackParent() const { return stackParent; } double JKQTPbarHorizontalStackableGraph::getStackedMax(int index) const { double height=0; if (parent!=nullptr) { JKQTPdatastore* datastore=parent->getDatastore(); height=datastore->get(static_cast(xColumn),static_cast(index)); } if (stackParent==nullptr) { return height; } else { return stackParent->getStackedMax(index)+height; } } double JKQTPbarHorizontalStackableGraph::getParentStackedMax(int index) const { if (stackParent) { return stackParent->getStackedMax(index); } else { return 0.0; } } bool JKQTPbarHorizontalStackableGraph::hasStackParent() const { return stackParent!=nullptr; }