2018-11-25 21:53:26 +08:00
|
|
|
/*
|
2019-01-20 23:15:10 +08:00
|
|
|
Copyright (c) 2008-2019 Jan W. Krieger (<jan@jkrieger.de>)
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
2019-02-08 00:24:46 +08:00
|
|
|
the Free Software Foundation, either version 2.1 of the License, or
|
2018-11-25 21:53:26 +08:00
|
|
|
(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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-12-19 00:13:18 +08:00
|
|
|
#include "jkqtplotter/jkqtpgraphsbarchart.h"
|
2018-11-26 03:25:44 +08:00
|
|
|
#include "jkqtplotter/jkqtpbaseplotter.h"
|
2018-11-25 21:53:26 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <QDebug>
|
|
|
|
#include <iostream>
|
2018-11-26 03:25:44 +08:00
|
|
|
#include "jkqtplottertools/jkqtptools.h"
|
2018-12-19 00:13:18 +08:00
|
|
|
#include "jkqtplotter/jkqtpgraphsimage.h"
|
2018-11-26 03:25:44 +08:00
|
|
|
#include "jkqtplotter/jkqtpbaseelements.h"
|
|
|
|
#include "jkqtplotter/jkqtplotter.h"
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
#define SmallestGreaterZeroCompare_xvsgz() if ((xvsgz>10.0*DBL_MIN)&&((smallestGreaterZero<10.0*DBL_MIN) || (xvsgz<smallestGreaterZero))) smallestGreaterZero=xvsgz;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPBarVerticalGraph::JKQTPBarVerticalGraph(JKQTBasePlotter* parent):
|
|
|
|
JKQTPXYGraph(parent)
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
baseline=0.0;
|
|
|
|
width=0.9;
|
|
|
|
shift=0;
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
initFillStyle(parent, parentPlotStyle);
|
|
|
|
initLineStyle(parent, parentPlotStyle);
|
2018-11-25 21:53:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-20 23:15:10 +08:00
|
|
|
JKQTPBarVerticalGraph::JKQTPBarVerticalGraph(JKQTPlotter* parent):
|
2019-02-08 00:24:46 +08:00
|
|
|
JKQTPBarVerticalGraph(parent->getPlotter())
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
void JKQTPBarVerticalGraph::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
|
2019-02-08 00:24:46 +08:00
|
|
|
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
2019-04-22 19:27:50 +08:00
|
|
|
QPen p=getLinePenForRects(painter, parent);
|
2018-11-25 21:53:26 +08:00
|
|
|
QPen np(Qt::NoPen);
|
2019-04-22 19:27:50 +08:00
|
|
|
QBrush b=getFillBrush(painter, parent);
|
2018-11-25 21:53:26 +08:00
|
|
|
//int y=rect.top()+rect.height()/2.0;
|
|
|
|
painter.setPen(p);
|
|
|
|
painter.setBrush(b);
|
|
|
|
painter.drawRect(rect);
|
2019-02-08 00:24:46 +08:00
|
|
|
|
2018-11-25 21:53:26 +08:00
|
|
|
}
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
QColor JKQTPBarVerticalGraph::getKeyLabelColor() const {
|
|
|
|
return getFillColor();
|
2018-11-25 21:53:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
void JKQTPBarVerticalGraph::draw(JKQTPEnhancedPainter& painter) {
|
2018-11-25 21:53:26 +08:00
|
|
|
#ifdef JKQTBP_AUTOTIMER
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPAutoOutputTimer jkaaot("JKQTPBarHorizontalGraph::draw");
|
2018-11-25 21:53:26 +08:00
|
|
|
#endif
|
|
|
|
if (parent==nullptr) return;
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPDatastore* datastore=parent->getDatastore();
|
2018-11-25 21:53:26 +08:00
|
|
|
if (datastore==nullptr) return;
|
|
|
|
|
|
|
|
drawErrorsBefore(painter);
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
QPen p=getLinePenForRects(painter, parent);
|
2018-11-25 21:53:26 +08:00
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
QBrush b=getFillBrush(painter, parent);
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows());
|
|
|
|
int imin=0;
|
2019-02-03 21:04:48 +08:00
|
|
|
|
2018-11-25 21:53:26 +08:00
|
|
|
if (imax<imin) {
|
|
|
|
int h=imin;
|
|
|
|
imin=imax;
|
|
|
|
imax=h;
|
|
|
|
}
|
|
|
|
if (imin<0) imin=0;
|
|
|
|
if (imax<0) imax=0;
|
|
|
|
|
2019-02-08 00:24:46 +08:00
|
|
|
{
|
|
|
|
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
|
|
|
|
|
|
|
// double x0=transformX(0);
|
|
|
|
// if (parent->getXAxis()->isLogAxis()) x0=transformX(parent->getXAxis()->getMin());
|
|
|
|
double y0=transformY(0);
|
|
|
|
if (parent->getYAxis()->isLogAxis()) y0=transformY(parent->getYAxis()->getMin());
|
|
|
|
double delta=1;
|
|
|
|
double deltap=0;
|
|
|
|
double deltam=0;
|
|
|
|
intSortData();
|
|
|
|
const bool hasStackPar=hasStackParent();
|
|
|
|
for (int iii=imin; iii<imax; iii++) {
|
|
|
|
int i=qBound(imin, getDataIndex(iii), imax);
|
|
|
|
double xv=datastore->get(static_cast<size_t>(xColumn),static_cast<size_t>(i));
|
|
|
|
int sr=datastore->getNextLowerIndex(xColumn, i);
|
|
|
|
int lr=datastore->getNextHigherIndex(xColumn, i);
|
|
|
|
double yv=datastore->get(static_cast<size_t>(yColumn),static_cast<size_t>(i));
|
|
|
|
double yv0=y0;
|
|
|
|
if (!qFuzzyIsNull(baseline)) yv0=transformY(baseline);
|
|
|
|
if (hasStackPar) {
|
|
|
|
double stackLastY=getParentStackedMax(i);
|
|
|
|
const double yvold=yv;
|
|
|
|
yv0=transformY(stackLastY)-(getLineWidth());
|
|
|
|
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<<iii<<", \t"<<i<<", \t"<<sr<<", \t"<<lr<<", \t"<<deltam<<", \t"<<deltap<<"\n\n";
|
|
|
|
delta=deltap+deltam;
|
|
|
|
|
|
|
|
if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv)) {
|
|
|
|
double x=transformX(xv+shift*delta-width*deltam);
|
|
|
|
double y=transformY(yv);
|
|
|
|
double xx=transformX(xv+shift*delta+width*deltap);
|
|
|
|
double yy=yv0;
|
|
|
|
|
|
|
|
//std::cout<<"delta="<<delta<<" x="<<x<<" y="<<y<<" xx="<<xx<<" yy="<<yy<<std::endl;
|
|
|
|
if (yy<y) { qSwap(y,yy); }
|
|
|
|
if (JKQTPIsOKFloat(x) && JKQTPIsOKFloat(xx) && JKQTPIsOKFloat(y) && JKQTPIsOKFloat(yy)) {
|
|
|
|
painter.setBrush(b);
|
|
|
|
painter.setPen(p);
|
|
|
|
QRectF r(QPointF(x, y), QPointF(xx, yy));
|
|
|
|
painter.drawRect(r);
|
2018-11-25 21:53:26 +08:00
|
|
|
|
2019-02-08 00:24:46 +08:00
|
|
|
}
|
2018-11-25 21:53:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-08 00:24:46 +08:00
|
|
|
}
|
2018-11-25 21:53:26 +08:00
|
|
|
drawErrorsAfter(painter);
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
bool JKQTPBarVerticalGraph::getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) {
|
2018-11-25 21:53:26 +08:00
|
|
|
bool start=true;
|
|
|
|
minx=0;
|
|
|
|
maxx=0;
|
|
|
|
smallestGreaterZero=0;
|
|
|
|
|
|
|
|
if (parent==nullptr) return false;
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPDatastore* datastore=parent->getDatastore();
|
2018-11-25 21:53:26 +08:00
|
|
|
int imin=0;
|
|
|
|
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows());
|
|
|
|
if (imax<imin) {
|
|
|
|
int h=imin;
|
|
|
|
imin=imax;
|
|
|
|
imax=h;
|
|
|
|
}
|
|
|
|
if (imin<0) imin=0;
|
|
|
|
if (imax<0) imax=0;
|
|
|
|
|
|
|
|
for (int i=imin; i<imax; i++) {
|
|
|
|
double xv=datastore->get(static_cast<size_t>(xColumn),static_cast<size_t>(i));
|
2019-02-03 21:04:48 +08:00
|
|
|
int sr=datastore->getNextLowerIndex(xColumn, i);
|
|
|
|
int lr=datastore->getNextHigherIndex(xColumn, i);
|
2018-11-25 21:53:26 +08:00
|
|
|
double delta, deltap, deltam;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
delta=deltap+deltam;
|
|
|
|
|
|
|
|
if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(delta) ) {
|
|
|
|
|
|
|
|
if (start || xv+shift*delta+width*delta/2.0>maxx) maxx=xv+shift*delta+width*delta/2.0;
|
|
|
|
if (start || xv+shift*delta-width*delta/2.0<minx) minx=xv+shift*delta-width*delta/2.0;
|
|
|
|
double xvsgz;
|
|
|
|
xvsgz=xv+shift*delta+width*delta/2.0; SmallestGreaterZeroCompare_xvsgz();
|
|
|
|
xvsgz=xv+shift*delta-width*delta/2.0; SmallestGreaterZeroCompare_xvsgz();
|
|
|
|
start=false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return !start;
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
bool JKQTPBarVerticalGraph::getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) {
|
2018-11-25 21:53:26 +08:00
|
|
|
miny=0;
|
|
|
|
maxy=0;
|
|
|
|
smallestGreaterZero=0;
|
|
|
|
if (baseline>0) {
|
|
|
|
smallestGreaterZero=baseline;
|
|
|
|
miny=baseline;
|
|
|
|
maxy=baseline;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parent==nullptr) return false;
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPDatastore* datastore=parent->getDatastore();
|
2018-11-25 21:53:26 +08:00
|
|
|
int imin=0;
|
|
|
|
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows());
|
|
|
|
if (imax<imin) {
|
|
|
|
int h=imin;
|
|
|
|
imin=imax;
|
|
|
|
imax=h;
|
|
|
|
}
|
|
|
|
if (imin<0) imin=0;
|
|
|
|
if (imax<0) imax=0;
|
|
|
|
|
|
|
|
for (int i=imin; i<imax; i++) {
|
|
|
|
double stack=0;
|
|
|
|
double yv=baseline;
|
|
|
|
if (!isHorizontal()) {
|
|
|
|
stack=getParentStackedMax(i);
|
|
|
|
yv=stack;
|
|
|
|
}
|
|
|
|
if (JKQTPIsOKFloat(yv)) {
|
|
|
|
if (yv>maxy) maxy=yv;
|
|
|
|
if (yv<miny) miny=yv;
|
|
|
|
double xvsgz;
|
|
|
|
xvsgz=yv; SmallestGreaterZeroCompare_xvsgz();
|
|
|
|
}
|
|
|
|
yv=stack+datastore->get(static_cast<size_t>(yColumn),static_cast<size_t>(i));
|
|
|
|
if (JKQTPIsOKFloat(yv)) {
|
|
|
|
if (yv>maxy) maxy=yv;
|
|
|
|
if (yv<miny) miny=yv;
|
|
|
|
double xvsgz;
|
|
|
|
xvsgz=yv; SmallestGreaterZeroCompare_xvsgz();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
void JKQTPBarVerticalGraph::autoscaleBarWidthAndShift(double maxWidth, double shrinkFactor)
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
if (parent) {
|
|
|
|
double cntH=0;
|
|
|
|
for (size_t i=0; i<parent->getGraphCount(); i++) {
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPPlotElement* g=parent->getGraph(i);
|
|
|
|
JKQTPBarVerticalGraph* gb=qobject_cast<JKQTPBarVerticalGraph*>(g);
|
2018-11-25 21:53:26 +08:00
|
|
|
if (gb && gb->isHorizontal()==isHorizontal()) {
|
|
|
|
cntH++;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
double widthH=1.0/cntH*maxWidth*shrinkFactor;
|
|
|
|
double dH=maxWidth/(cntH);
|
|
|
|
double h=0.1+dH/2.0;
|
|
|
|
for (size_t i=0; i<parent->getGraphCount(); i++) {
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPPlotElement* g=parent->getGraph(i);
|
|
|
|
JKQTPBarVerticalGraph* gb=qobject_cast<JKQTPBarVerticalGraph*>(g);
|
2018-11-25 21:53:26 +08:00
|
|
|
if (gb && gb->isHorizontal()==isHorizontal()) {
|
|
|
|
if (cntH>1) {
|
|
|
|
gb->width=widthH;
|
|
|
|
gb->shift=h-0.5;
|
|
|
|
h=h+dH;
|
|
|
|
} else {
|
|
|
|
gb->width=maxWidth;
|
|
|
|
gb->shift=0.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
void JKQTPBarVerticalGraph::autoscaleBarWidthAndShiftSeparatedGroups(double groupWidth) {
|
2018-11-25 21:53:26 +08:00
|
|
|
autoscaleBarWidthAndShift(groupWidth, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPBarHorizontalGraph::JKQTPBarHorizontalGraph(JKQTBasePlotter *parent):
|
|
|
|
JKQTPBarVerticalGraph(parent)
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-01-20 23:15:10 +08:00
|
|
|
JKQTPBarHorizontalGraph::JKQTPBarHorizontalGraph(JKQTPlotter *parent):
|
2019-02-08 00:24:46 +08:00
|
|
|
JKQTPBarHorizontalGraph(parent->getPlotter())
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
void JKQTPBarHorizontalGraph::draw(JKQTPEnhancedPainter& painter) {
|
2018-11-25 21:53:26 +08:00
|
|
|
#ifdef JKQTBP_AUTOTIMER
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPAutoOutputTimer jkaaot("JKQTPBarVerticalGraph::draw");
|
2018-11-25 21:53:26 +08:00
|
|
|
#endif
|
|
|
|
if (parent==nullptr) return;
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPDatastore* datastore=parent->getDatastore();
|
2018-11-25 21:53:26 +08:00
|
|
|
if (datastore==nullptr) return;
|
|
|
|
|
|
|
|
drawErrorsBefore(painter);
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
QPen p=getLinePenForRects(painter, parent);
|
2018-11-25 21:53:26 +08:00
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
QBrush b=getFillBrush(painter, parent);
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows());
|
|
|
|
int imin=0;
|
|
|
|
if (imax<imin) {
|
|
|
|
int h=imin;
|
|
|
|
imin=imax;
|
|
|
|
imax=h;
|
|
|
|
}
|
|
|
|
if (imin<0) imin=0;
|
|
|
|
if (imax<0) imax=0;
|
|
|
|
|
2018-12-28 05:52:00 +08:00
|
|
|
double x0=transformX(0);
|
2019-01-26 03:16:04 +08:00
|
|
|
if (parent->getXAxis()->isLogAxis()) x0=transformX(parent->getXAxis()->getMin());
|
2018-12-28 05:52:00 +08:00
|
|
|
// double y0=transformY(0);
|
2019-01-26 03:16:04 +08:00
|
|
|
// if (parent->getYAxis()->isLogAxis()) y0=transformY(parent->getYAxis()->getMin());
|
2018-11-25 21:53:26 +08:00
|
|
|
double delta=1;
|
|
|
|
double deltap=0;
|
|
|
|
double deltam=0;
|
2019-02-08 00:24:46 +08:00
|
|
|
{
|
|
|
|
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
|
|
|
intSortData();
|
|
|
|
const bool hasStackPar=hasStackParent();
|
|
|
|
for (int iii=imin; iii<imax; iii++) {
|
|
|
|
int i=qBound(imin, getDataIndex(iii), imax);
|
|
|
|
double xv=datastore->get(static_cast<size_t>(xColumn),static_cast<size_t>(i));
|
|
|
|
double yv=datastore->get(static_cast<size_t>(yColumn),static_cast<size_t>(i));
|
|
|
|
int sr=datastore->getNextLowerIndex(yColumn, i);
|
|
|
|
int lr=datastore->getNextHigherIndex(yColumn, i);
|
|
|
|
double xv0=x0;
|
|
|
|
if (!qFuzzyIsNull(baseline)) xv0=transformX(baseline);
|
|
|
|
if (hasStackPar) {
|
|
|
|
double stackLastX=getParentStackedMax(i);
|
|
|
|
const double xvold=xv;
|
|
|
|
xv0=transformX(stackLastX)+(getLineWidth());
|
|
|
|
xv=stackLastX+xvold;
|
|
|
|
}
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
|
2019-02-08 00:24:46 +08:00
|
|
|
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=transformX(baseline);
|
|
|
|
double y=transformY(yv+shift*delta+width*deltap);
|
|
|
|
double xx=transformX(xv);
|
|
|
|
double yy=transformY(yv+shift*delta-width*deltam);
|
|
|
|
if (x>xx) { qSwap(x,xx); }
|
|
|
|
//qDebug()<<"delta="<<delta<<" x="<<x<<" y="<<y<<" xx="<<xx<<" yy="<<yy;
|
|
|
|
//qDebug()<<"xv="<<xv<<" x0="<<x0<<" x="<<x<<"..."<<xx;
|
|
|
|
if (JKQTPIsOKFloat(x) && JKQTPIsOKFloat(xx) && JKQTPIsOKFloat(y) && JKQTPIsOKFloat(yy)) {
|
|
|
|
painter.setBrush(b);
|
|
|
|
painter.setPen(p);
|
|
|
|
QRectF r(QPointF(x, y), QPointF(xx, yy));
|
|
|
|
painter.drawRect(r);
|
|
|
|
}
|
2018-11-25 21:53:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-08 00:24:46 +08:00
|
|
|
}
|
2018-11-25 21:53:26 +08:00
|
|
|
drawErrorsAfter(painter);
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
bool JKQTPBarHorizontalGraph::getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) {
|
2018-11-25 21:53:26 +08:00
|
|
|
minx=0;
|
|
|
|
maxx=0;
|
|
|
|
smallestGreaterZero=0;
|
|
|
|
if (baseline>0) {
|
|
|
|
smallestGreaterZero=baseline;
|
|
|
|
minx=baseline;
|
|
|
|
maxx=baseline;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parent==nullptr) return false;
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPDatastore* datastore=parent->getDatastore();
|
2018-11-25 21:53:26 +08:00
|
|
|
int imin=0;
|
|
|
|
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(xColumn)).getRows());
|
|
|
|
if (imax<imin) {
|
|
|
|
int h=imin;
|
|
|
|
imin=imax;
|
|
|
|
imax=h;
|
|
|
|
}
|
|
|
|
if (imin<0) imin=0;
|
|
|
|
if (imax<0) imax=0;
|
|
|
|
|
|
|
|
for (int i=imin; i<imax; i++) {
|
|
|
|
double stack=0;
|
|
|
|
double xv=baseline;
|
|
|
|
if (isHorizontal()) {
|
|
|
|
stack=getParentStackedMax(i);
|
|
|
|
xv=stack;
|
|
|
|
}
|
|
|
|
if (JKQTPIsOKFloat(xv)) {
|
|
|
|
if (xv>maxx) maxx=xv;
|
|
|
|
if (xv<minx) minx=xv;
|
|
|
|
double xvsgz;
|
|
|
|
xvsgz=xv; SmallestGreaterZeroCompare_xvsgz();
|
|
|
|
}
|
|
|
|
xv=stack+datastore->get(static_cast<size_t>(xColumn),static_cast<size_t>(i));
|
|
|
|
if (JKQTPIsOKFloat(xv)) {
|
|
|
|
if (xv>maxx) maxx=xv;
|
|
|
|
if (xv<minx) minx=xv;
|
|
|
|
double xvsgz;
|
|
|
|
xvsgz=xv; SmallestGreaterZeroCompare_xvsgz();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
bool JKQTPBarHorizontalGraph::getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) {
|
2018-11-25 21:53:26 +08:00
|
|
|
bool start=true;
|
|
|
|
miny=0;
|
|
|
|
maxy=0;
|
|
|
|
smallestGreaterZero=0;
|
|
|
|
|
|
|
|
if (parent==nullptr) return false;
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPDatastore* datastore=parent->getDatastore();
|
2018-11-25 21:53:26 +08:00
|
|
|
int imin=0;
|
|
|
|
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows());
|
|
|
|
if (imax<imin) {
|
|
|
|
int h=imin;
|
|
|
|
imin=imax;
|
|
|
|
imax=h;
|
|
|
|
}
|
|
|
|
if (imin<0) imin=0;
|
|
|
|
if (imax<0) imax=0;
|
|
|
|
|
|
|
|
for (int i=imin; i<imax; i++) {
|
|
|
|
double yv=datastore->get(static_cast<size_t>(yColumn),static_cast<size_t>(i));
|
|
|
|
double delta, deltap, deltam;
|
2019-02-03 21:04:48 +08:00
|
|
|
int sr=datastore->getNextLowerIndex(yColumn, i);
|
|
|
|
int lr=datastore->getNextHigherIndex(yColumn, i);
|
2018-11-25 21:53:26 +08:00
|
|
|
|
|
|
|
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.0<miny) miny=yv+shift*delta-width*delta/2.0;
|
|
|
|
double xvsgz;
|
|
|
|
xvsgz=yv+shift*delta+width*delta/2.0; SmallestGreaterZeroCompare_xvsgz();
|
|
|
|
xvsgz=yv+shift*delta-width*delta/2.0; SmallestGreaterZeroCompare_xvsgz();
|
|
|
|
start=false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return !start;
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
bool JKQTPBarHorizontalGraph::isHorizontal() const
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
double JKQTPBarVerticalGraph::getParentStackedMax(int /*index*/) const
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
bool JKQTPBarVerticalGraph::hasStackParent() const
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
double JKQTPBarVerticalGraph::getStackedMax(int /*index*/) const
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
return baseline;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
bool JKQTPBarVerticalGraph::isHorizontal() const
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-04-22 19:27:50 +08:00
|
|
|
void JKQTPBarVerticalGraph::setColor(QColor c)
|
|
|
|
{
|
|
|
|
setLineColor(c);
|
|
|
|
setFillColor(JKQTPGetDerivedColor(parent->getCurrentPlotterStyle().graphFillColorDerivationMode, c));
|
|
|
|
c.setAlphaF(0.5);
|
|
|
|
setHighlightingLineColor(c);
|
|
|
|
}
|
|
|
|
|
|
|
|
void JKQTPBarVerticalGraph::setShift(double __value)
|
|
|
|
{
|
|
|
|
this->shift = __value;
|
|
|
|
}
|
|
|
|
|
|
|
|
double JKQTPBarVerticalGraph::getShift() const
|
|
|
|
{
|
|
|
|
return this->shift;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JKQTPBarVerticalGraph::setWidth(double __value)
|
|
|
|
{
|
|
|
|
this->width = __value;
|
|
|
|
}
|
|
|
|
|
|
|
|
double JKQTPBarVerticalGraph::getWidth() const
|
|
|
|
{
|
|
|
|
return this->width;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JKQTPBarVerticalGraph::setBaseline(double __value)
|
|
|
|
{
|
|
|
|
this->baseline = __value;
|
|
|
|
}
|
|
|
|
|
|
|
|
double JKQTPBarVerticalGraph::getBaseline() const
|
|
|
|
{
|
|
|
|
return this->baseline;
|
|
|
|
}
|
|
|
|
|
2019-01-26 20:00:40 +08:00
|
|
|
void JKQTPBarVerticalGraph::setFillColor_and_darkenedColor(QColor fill, int colorDarker)
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
2019-01-26 20:00:40 +08:00
|
|
|
setFillColor(fill);
|
2019-04-22 19:27:50 +08:00
|
|
|
setLineColor(fill.darker(colorDarker));
|
2018-11-25 21:53:26 +08:00
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPBarHorizontalErrorGraph::JKQTPBarHorizontalErrorGraph(JKQTBasePlotter *parent):
|
2019-04-22 19:27:50 +08:00
|
|
|
JKQTPBarHorizontalGraph(parent), JKQTPXGraphErrors(getKeyLabelColor(), parent)
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
2019-04-22 19:27:50 +08:00
|
|
|
setErrorColorFromGraphColor(getKeyLabelColor());
|
2019-02-08 00:24:46 +08:00
|
|
|
if (parentPlotStyle>=0) setErrorStyleFromPen(parent->getPlotStyle(parentPlotStyle));
|
2018-11-25 21:53:26 +08:00
|
|
|
}
|
|
|
|
|
2019-01-20 23:15:10 +08:00
|
|
|
JKQTPBarHorizontalErrorGraph::JKQTPBarHorizontalErrorGraph(JKQTPlotter *parent):
|
2019-02-08 00:24:46 +08:00
|
|
|
JKQTPBarHorizontalErrorGraph(parent->getPlotter())
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
2019-02-08 00:24:46 +08:00
|
|
|
|
2018-11-25 21:53:26 +08:00
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
bool JKQTPBarHorizontalErrorGraph::usesColumn(int c) const
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
2019-01-20 17:49:29 +08:00
|
|
|
return JKQTPBarHorizontalGraph::usesColumn(c)|| JKQTPXGraphErrors::errorUsesColumn(c);
|
2018-11-25 21:53:26 +08:00
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
bool JKQTPBarHorizontalErrorGraph::getXMinMax(double &minx, double &maxx, double &smallestGreaterZero)
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
2019-01-20 17:49:29 +08:00
|
|
|
if (xErrorColumn<0 || xErrorStyle==JKQTPNoError) {
|
|
|
|
return JKQTPBarHorizontalGraph::getXMinMax(minx, maxx, smallestGreaterZero);
|
2018-11-25 21:53:26 +08:00
|
|
|
} else {
|
|
|
|
bool start=false;
|
|
|
|
minx=0;
|
|
|
|
maxx=0;
|
|
|
|
smallestGreaterZero=0;
|
|
|
|
|
|
|
|
if (parent==nullptr) return false;
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPDatastore* datastore=parent->getDatastore();
|
2018-11-25 21:53:26 +08:00
|
|
|
int imin=0;
|
|
|
|
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows());
|
|
|
|
if (imax<imin) {
|
|
|
|
int h=imin;
|
|
|
|
imin=imax;
|
|
|
|
imax=h;
|
|
|
|
}
|
|
|
|
if (imin<0) imin=0;
|
|
|
|
if (imax<0) imax=0;
|
|
|
|
|
|
|
|
for (int i=imin; i<imax; i++) {
|
|
|
|
double xvsgz;
|
|
|
|
double xv=datastore->get(static_cast<size_t>(xColumn),static_cast<size_t>(i))+getXErrorU(i, datastore);
|
|
|
|
double xvv=datastore->get(static_cast<size_t>(xColumn),static_cast<size_t>(i))-getXErrorL(i, datastore);
|
|
|
|
if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(xvv) ) {
|
|
|
|
if (start || xv>maxx) maxx=xv;
|
|
|
|
if (start || xv<minx) minx=xv;
|
|
|
|
xvsgz=xv; SmallestGreaterZeroCompare_xvsgz();
|
|
|
|
start=false;
|
|
|
|
if (start || xvv>maxx) maxx=xvv;
|
|
|
|
if (start || xvv<minx) minx=xvv;
|
|
|
|
xvsgz=xvv; SmallestGreaterZeroCompare_xvsgz();
|
|
|
|
start=false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return !start;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
void JKQTPBarHorizontalErrorGraph::drawErrorsAfter(JKQTPEnhancedPainter &painter)
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
2019-02-03 21:04:48 +08:00
|
|
|
if (sortData==JKQTPXYGraph::Unsorted) plotErrorIndicators(painter, parent, this, xColumn, yColumn, 0.0, shift);
|
|
|
|
else plotErrorIndicators(painter, parent, this, xColumn, yColumn, 0.0, shift, &sortedIndices);
|
2018-11-25 21:53:26 +08:00
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPBarVerticalErrorGraph::JKQTPBarVerticalErrorGraph(JKQTBasePlotter *parent):
|
2019-04-22 19:27:50 +08:00
|
|
|
JKQTPBarVerticalGraph(parent), JKQTPYGraphErrors(getKeyLabelColor(), parent)
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
2019-04-22 19:27:50 +08:00
|
|
|
setErrorColorFromGraphColor(getKeyLabelColor());
|
2019-02-08 00:24:46 +08:00
|
|
|
if (parentPlotStyle>=0) setErrorStyleFromPen(parent->getPlotStyle(parentPlotStyle));
|
|
|
|
|
2018-11-25 21:53:26 +08:00
|
|
|
}
|
|
|
|
|
2019-01-20 23:15:10 +08:00
|
|
|
JKQTPBarVerticalErrorGraph::JKQTPBarVerticalErrorGraph(JKQTPlotter *parent):
|
2019-02-08 00:24:46 +08:00
|
|
|
JKQTPBarVerticalErrorGraph(parent->getPlotter())
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
2019-02-08 00:24:46 +08:00
|
|
|
|
2018-11-25 21:53:26 +08:00
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
bool JKQTPBarVerticalErrorGraph::usesColumn(int c) const
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
2019-01-20 17:49:29 +08:00
|
|
|
return JKQTPBarVerticalGraph::usesColumn(c)|| JKQTPYGraphErrors::errorUsesColumn(c);
|
2018-11-25 21:53:26 +08:00
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
bool JKQTPBarVerticalErrorGraph::getYMinMax(double &miny, double &maxy, double &smallestGreaterZero)
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
2019-01-20 17:49:29 +08:00
|
|
|
if (yErrorColumn<0 || yErrorStyle==JKQTPNoError) {
|
2018-11-25 21:53:26 +08:00
|
|
|
miny=0;
|
|
|
|
maxy=0;
|
|
|
|
smallestGreaterZero=0;
|
|
|
|
if (baseline>0) {
|
|
|
|
smallestGreaterZero=baseline;
|
|
|
|
miny=baseline;
|
|
|
|
maxy=baseline;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parent==nullptr) return false;
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPDatastore* datastore=parent->getDatastore();
|
2018-11-25 21:53:26 +08:00
|
|
|
int imin=0;
|
|
|
|
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows());
|
|
|
|
if (imax<imin) {
|
|
|
|
int h=imin;
|
|
|
|
imin=imax;
|
|
|
|
imax=h;
|
|
|
|
}
|
|
|
|
if (imin<0) imin=0;
|
|
|
|
if (imax<0) imax=0;
|
|
|
|
|
|
|
|
for (int i=imin; i<imax; i++) {
|
|
|
|
double yv=baseline;
|
|
|
|
if (JKQTPIsOKFloat(yv)) {
|
|
|
|
if (yv>maxy) maxy=yv;
|
|
|
|
if (yv<miny) miny=yv;
|
|
|
|
double xvsgz;
|
|
|
|
xvsgz=yv; SmallestGreaterZeroCompare_xvsgz();
|
|
|
|
}
|
|
|
|
yv=datastore->get(static_cast<size_t>(yColumn),static_cast<size_t>(i));
|
|
|
|
if (JKQTPIsOKFloat(yv)) {
|
|
|
|
if (yv>maxy) maxy=yv;
|
|
|
|
if (yv<miny) miny=yv;
|
|
|
|
double xvsgz;
|
|
|
|
xvsgz=yv; SmallestGreaterZeroCompare_xvsgz();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
bool start=false;
|
|
|
|
miny=baseline;
|
|
|
|
maxy=baseline;
|
|
|
|
smallestGreaterZero=0;
|
|
|
|
if (baseline>0) {
|
|
|
|
smallestGreaterZero=baseline;
|
|
|
|
miny=baseline;
|
|
|
|
maxy=baseline;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parent==nullptr) return false;
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPDatastore* datastore=parent->getDatastore();
|
2018-11-25 21:53:26 +08:00
|
|
|
int imin=0;
|
|
|
|
int imax=qMin(datastore->getColumn(static_cast<size_t>(xColumn)).getRows(), datastore->getColumn(static_cast<size_t>(yColumn)).getRows());
|
|
|
|
if (imax<imin) {
|
|
|
|
int h=imin;
|
|
|
|
imin=imax;
|
|
|
|
imax=h;
|
|
|
|
}
|
|
|
|
if (imin<0) imin=0;
|
|
|
|
if (imax<0) imax=0;
|
|
|
|
|
|
|
|
|
|
|
|
for (int i=imin; i<imax; i++) {
|
|
|
|
double yv=datastore->get(static_cast<size_t>(yColumn),static_cast<size_t>(i))+getYErrorU(i, datastore);
|
|
|
|
double yvv=datastore->get(static_cast<size_t>(yColumn),static_cast<size_t>(i))-getYErrorL(i, datastore);
|
|
|
|
if (JKQTPIsOKFloat(yv) && JKQTPIsOKFloat(yvv) ) {
|
|
|
|
if (start || yv>maxy) maxy=yv;
|
|
|
|
if (start || yv<miny) miny=yv;
|
|
|
|
double xvsgz;
|
|
|
|
xvsgz=yv; SmallestGreaterZeroCompare_xvsgz();
|
|
|
|
if (start || yvv>maxy) maxy=yvv;
|
|
|
|
if (start || yvv<miny) miny=yvv;
|
|
|
|
xvsgz=yvv; SmallestGreaterZeroCompare_xvsgz();
|
|
|
|
start=false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return !start;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
void JKQTPBarVerticalErrorGraph::drawErrorsAfter(JKQTPEnhancedPainter &painter)
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
2019-02-03 21:04:48 +08:00
|
|
|
//plotErrorIndicators(painter, parent, this, xColumn, yColumn, shift, 0.0);
|
|
|
|
if (sortData==JKQTPXYGraph::Unsorted) plotErrorIndicators(painter, parent, this, xColumn, yColumn, shift, 0.0);
|
|
|
|
else plotErrorIndicators(painter, parent, this, xColumn, yColumn, shift, 0, &sortedIndices);
|
2018-11-25 21:53:26 +08:00
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPBarVerticalStackableGraph::JKQTPBarVerticalStackableGraph(JKQTBasePlotter *parent):
|
|
|
|
JKQTPBarVerticalGraph(parent), stackParent(nullptr)
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-01-20 23:15:10 +08:00
|
|
|
JKQTPBarVerticalStackableGraph::JKQTPBarVerticalStackableGraph(JKQTPlotter *parent):
|
2019-02-08 00:24:46 +08:00
|
|
|
JKQTPBarVerticalStackableGraph(parent->getPlotter())
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
void JKQTPBarVerticalStackableGraph::stackUpon(JKQTPBarVerticalStackableGraph *parentGraph)
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
stackParent=parentGraph;
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
void JKQTPBarVerticalStackableGraph::dontStackUpon()
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
stackParent=nullptr;
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
double JKQTPBarVerticalStackableGraph::getParentStackedMax(int index) const
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
if (stackParent) {
|
|
|
|
return stackParent->getStackedMax(index);
|
|
|
|
} else {
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
bool JKQTPBarVerticalStackableGraph::hasStackParent() const
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
return stackParent!=nullptr;
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
const JKQTPBarVerticalStackableGraph *JKQTPBarVerticalStackableGraph::getStackParent() const
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
return stackParent;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
double JKQTPBarVerticalStackableGraph::getStackedMax(int index) const
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
double height=0;
|
|
|
|
if (parent!=nullptr) {
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPDatastore* datastore=parent->getDatastore();
|
2018-11-25 21:53:26 +08:00
|
|
|
height=datastore->get(static_cast<size_t>(yColumn),static_cast<size_t>(index));
|
|
|
|
}
|
|
|
|
if (stackParent==nullptr) {
|
|
|
|
return height;
|
|
|
|
} else {
|
|
|
|
return stackParent->getStackedMax(index)+height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPBarHorizontalStackableGraph::JKQTPBarHorizontalStackableGraph(JKQTBasePlotter *parent):
|
|
|
|
JKQTPBarHorizontalGraph(parent), stackParent(nullptr)
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-01-20 23:15:10 +08:00
|
|
|
JKQTPBarHorizontalStackableGraph::JKQTPBarHorizontalStackableGraph(JKQTPlotter *parent):
|
2019-02-08 00:24:46 +08:00
|
|
|
JKQTPBarHorizontalStackableGraph(parent->getPlotter())
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
void JKQTPBarHorizontalStackableGraph::stackUpon(JKQTPBarHorizontalStackableGraph *parentGraph)
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
stackParent=parentGraph;
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
void JKQTPBarHorizontalStackableGraph::dontStackUpon()
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
stackParent=nullptr;
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
const JKQTPBarHorizontalStackableGraph *JKQTPBarHorizontalStackableGraph::getStackParent() const
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
return stackParent;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
double JKQTPBarHorizontalStackableGraph::getStackedMax(int index) const
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
double height=0;
|
|
|
|
if (parent!=nullptr) {
|
2019-01-20 17:49:29 +08:00
|
|
|
JKQTPDatastore* datastore=parent->getDatastore();
|
2018-11-25 21:53:26 +08:00
|
|
|
height=datastore->get(static_cast<size_t>(xColumn),static_cast<size_t>(index));
|
|
|
|
}
|
|
|
|
if (stackParent==nullptr) {
|
|
|
|
return height;
|
|
|
|
} else {
|
|
|
|
return stackParent->getStackedMax(index)+height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
double JKQTPBarHorizontalStackableGraph::getParentStackedMax(int index) const
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
if (stackParent) {
|
|
|
|
return stackParent->getStackedMax(index);
|
|
|
|
} else {
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-20 17:49:29 +08:00
|
|
|
bool JKQTPBarHorizontalStackableGraph::hasStackParent() const
|
2018-11-25 21:53:26 +08:00
|
|
|
{
|
|
|
|
return stackParent!=nullptr;
|
|
|
|
}
|