mirror of
https://github.com/jkriege2/JKQtPlotter.git
synced 2024-12-24 09:31:40 +08:00
reworked class hierarchy of bar charts
This commit is contained in:
parent
4c98310147
commit
9dbfd6e173
@ -25,7 +25,8 @@ Changes, compared to \ref page_whatsnew_V2019_11 "v2019.11" include:
|
||||
<li>removed/breaking change: removed the overlay elements (derived from JKQTPOverlayElement), which were not very well set up and are more confusing than useful.</li>
|
||||
<li>improved/breaking change: geometric objects now use an adaptive drawing algorithm to represent curves (before e.g. ellipses were always separated into a fixed number of line-segments)</li>
|
||||
<li>improved: constructors and access functions for several geometric objects (e.g. more constructors, additional functions to retrieve parameters in diferent forms, iterators for polygons, ...)</li>
|
||||
<li>improved/breaking change: reworked class hirarchy of parsed function plots and declared several setters as slots.</li>
|
||||
<li>improved/breaking change: reworked class hierarchy of parsed function plots and declared several setters as slots.</li>
|
||||
<li>improved/breaking change: reworked class hierarchy of bar charts.</li>
|
||||
<li>bugfixed/improved: aspect ratio handling in JKQTPlotter.</li>
|
||||
<li>new: added geometric plot objects JKQTPGeoArrow to draw arrows (aka lines with added line-end decorators, also extended JKQTPGeoLine, JKQTPGeoInfiniteLine, JKQTPGeoPolyLines to draw line-end decorator (aka arrows)</li>
|
||||
<li>new: all geometric objects can either be drawn as graphic element (i.e. lines are straight line, even on non-linear axes), or as mathematical curve (i.e. on non-linear axes, lines become the appropriate curve representing the linear function, connecting the given start/end-points). The only exceptions are ellipses (and the derived arcs,pies,chords), which are always drawn as mathematical curves</li>
|
||||
|
@ -89,8 +89,17 @@ int main(int argc, char* argv[])
|
||||
return app.exec();
|
||||
}
|
||||
```
|
||||
|
||||
Note: Here we use the functions `JKQTPBarVerticalGraph::setXColumn()` and `JKQTPBarVerticalGraph::setYColumn()` to set the columns to use for the stack positions (X) and heights (Y). Instead you can also use the semantic version `JKQTPBarGraphBase::setBarPositionColumn()` and `JKQTPBarGraphBase::setBarHeightColumn()`.
|
||||
|
||||
The result looks like this:
|
||||
|
||||
![barchart](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/barchart.png)
|
||||
|
||||
|
||||
|
||||
In order to draw horizontal error bars, you have to use `JKQTPBarHorizontalGraph` instead of `JKQTPBarVerticalGraph`:
|
||||
|
||||
![barchart](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/barchart_hor.png)
|
||||
|
||||
|
||||
|
@ -10,16 +10,17 @@
|
||||
#include "jkqtplotter/graphs/jkqtpbarchart.h"
|
||||
|
||||
#define Ndata 5
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
|
||||
|
||||
template <class TCHART>
|
||||
void doExample()
|
||||
{
|
||||
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
|
||||
JKQTPlotter plot;
|
||||
plot.getPlotter()->setUseAntiAliasingForGraphs(true); // nicer (but slower) plotting
|
||||
plot.getPlotter()->setUseAntiAliasingForSystem(true); // nicer (but slower) plotting
|
||||
plot.getPlotter()->setUseAntiAliasingForText(true); // nicer (but slower) text rendering
|
||||
JKQTPDatastore* ds=plot.getDatastore();
|
||||
JKQTPlotter* plot=new JKQTPlotter();
|
||||
plot->getPlotter()->setUseAntiAliasingForGraphs(true); // nicer (but slower) plotting
|
||||
plot->getPlotter()->setUseAntiAliasingForSystem(true); // nicer (but slower) plotting
|
||||
plot->getPlotter()->setUseAntiAliasingForText(true); // nicer (but slower) text rendering
|
||||
JKQTPDatastore* ds=plot->getDatastore();
|
||||
|
||||
// 2. now we create data for three simple barchart
|
||||
QString L[Ndata]={ "cat. A", "cat. C", "cat. B", "cat. D", "other"}; // unsorted category axis
|
||||
@ -41,24 +42,24 @@ int main(int argc, char* argv[])
|
||||
size_t columnY3=ds->addCopiedColumn(Y3, Ndata, "y3");
|
||||
|
||||
// 4. create graphs in the plot, which plots the dataset X/Y1, X/Y2 and X/Y3:
|
||||
JKQTPBarVerticalGraph* graph1=new JKQTPBarVerticalGraph(&plot);
|
||||
graph1->setXColumn(columnX);
|
||||
graph1->setYColumn(columnY1);
|
||||
TCHART* graph1=new TCHART(plot);
|
||||
graph1->setBarPositionColumn(columnX);
|
||||
graph1->setBarHeightColumn(columnY1);
|
||||
graph1->setTitle(QObject::tr("dataset 1"));
|
||||
JKQTPBarVerticalGraph* graph2=new JKQTPBarVerticalGraph(&plot);
|
||||
graph2->setXColumn(columnX);
|
||||
graph2->setYColumn(columnY2);
|
||||
TCHART* graph2=new TCHART(plot);
|
||||
graph2->setBarPositionColumn(columnX);
|
||||
graph2->setBarHeightColumn(columnY2);
|
||||
graph2->setTitle(QObject::tr("dataset 2"));
|
||||
JKQTPBarVerticalGraph* graph3=new JKQTPBarVerticalGraph(&plot);
|
||||
graph3->setXColumn(columnX);
|
||||
graph3->setYColumn(columnY3);
|
||||
TCHART* graph3=new TCHART(plot);
|
||||
graph3->setBarPositionColumn(columnX);
|
||||
graph3->setBarHeightColumn(columnY3);
|
||||
graph3->setTitle(QObject::tr("dataset 3"));
|
||||
|
||||
|
||||
// 5. add the graphs to the plot, so it is actually displayed
|
||||
plot.addGraph(graph1);
|
||||
plot.addGraph(graph2);
|
||||
plot.addGraph(graph3);
|
||||
plot->addGraph(graph1);
|
||||
plot->addGraph(graph2);
|
||||
plot->addGraph(graph3);
|
||||
|
||||
// 6. now we set the graphs, so they are plotted side-by-side
|
||||
// This function searches all JKQTPBarHorizontalGraph in the current
|
||||
@ -66,29 +67,45 @@ int main(int argc, char* argv[])
|
||||
// side-by-side groups
|
||||
graph1->autoscaleBarWidthAndShift(0.75, 1);
|
||||
|
||||
// 7. data is grouped into 5 numbere groups (1..5), but we also have string
|
||||
// labels for these groups (stored in L). In order to display these labels,
|
||||
// we have to tell the x-Axis to use these special labels:
|
||||
plot.getXAxis()->addAxisTickLabels(X, L, Ndata);
|
||||
// also we can rotate the labels a bit (by 45 degree), so they fit better
|
||||
plot.getXAxis()->setTickLabelAngle(45);
|
||||
plot.getXAxis()->setTickLabelFontSize(12);
|
||||
if (dynamic_cast<JKQTPBarVerticalGraph*>(graph1)!=nullptr) {
|
||||
// 7. data is grouped into 5 numbere groups (1..5), but we also have string
|
||||
// labels for these groups (stored in L). In order to display these labels,
|
||||
// we have to tell the x-Axis to use these special labels:
|
||||
plot->getXAxis()->addAxisTickLabels(X, L, Ndata);
|
||||
// also we can rotate the labels a bit (by 45 degree), so they fit better
|
||||
plot->getXAxis()->setTickLabelAngle(45);
|
||||
plot->getXAxis()->setTickLabelFontSize(12);
|
||||
} else {
|
||||
// 7. data is grouped into 5 numbere groups (1..5), but we also have string
|
||||
// labels for these groups (stored in L). In order to display these labels,
|
||||
// we have to tell the x-Axis to use these special labels:
|
||||
plot->getYAxis()->addAxisTickLabels(X, L, Ndata);
|
||||
plot->getYAxis()->setTickLabelFontSize(12);
|
||||
}
|
||||
|
||||
// 8. finally we move the plot key/legend to the outside, top-right
|
||||
// and lay it out as a single row
|
||||
// NOTE: plot is a descendent of QWidget, which uses an internal object of
|
||||
// type JKQTBasePlotter, which does the actual plotting.
|
||||
// So many properties of the plot are only available in this internal
|
||||
// object, which you can access by plot.getPlotter().
|
||||
plot.getPlotter()->setKeyPosition(JKQTPKeyOutsideTopRight);
|
||||
plot.getPlotter()->setKeyLayout(JKQTPKeyLayoutOneRow);
|
||||
// object, which you can access by plot->getPlotter().
|
||||
plot->getPlotter()->setKeyPosition(JKQTPKeyOutsideTopRight);
|
||||
plot->getPlotter()->setKeyLayout(JKQTPKeyLayoutOneRow);
|
||||
|
||||
// 9 autoscale the plot so the graph is contained
|
||||
plot.zoomToFit();
|
||||
plot->zoomToFit();
|
||||
|
||||
// show plotter and make it a decent size
|
||||
plot.show();
|
||||
plot.resize(600,400);
|
||||
plot->show();
|
||||
plot->resize(600,400);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
|
||||
doExample<JKQTPBarVerticalGraph>();
|
||||
doExample<JKQTPBarHorizontalGraph>();
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ isEmpty(JKQTP_PLOTTER_PRI_INCLUDED) {
|
||||
$$PWD/jkqtplotter/graphs/jkqtpscatter.h \
|
||||
$$PWD/jkqtplotter/graphs/jkqtprange.h \
|
||||
$$PWD/jkqtplotter/graphs/jkqtpspecialline.h \
|
||||
$$PWD/jkqtplotter/graphs/jkqtpbarchartbase.h \
|
||||
$$PWD/jkqtplotter/graphs/jkqtpbarchart.h \
|
||||
$$PWD/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.h \
|
||||
$$PWD/jkqtplotter/gui/jkqtpcomboboxes.h \
|
||||
@ -97,6 +98,7 @@ isEmpty(JKQTP_PLOTTER_PRI_INCLUDED) {
|
||||
$$PWD/jkqtplotter/graphs/jkqtpscatter.cpp \
|
||||
$$PWD/jkqtplotter/graphs/jkqtprange.cpp \
|
||||
$$PWD/jkqtplotter/graphs/jkqtpspecialline.cpp \
|
||||
$$PWD/jkqtplotter/graphs/jkqtpbarchartbase.cpp \
|
||||
$$PWD/jkqtplotter/graphs/jkqtpbarchart.cpp \
|
||||
$$PWD/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.cpp \
|
||||
$$PWD/jkqtplotter/gui/jkqtpcomboboxes.cpp \
|
||||
|
@ -40,6 +40,7 @@ set(SOURCES_GRAPHS
|
||||
graphs/jkqtpscatter.cpp
|
||||
graphs/jkqtprange.cpp
|
||||
graphs/jkqtpspecialline.cpp
|
||||
graphs/jkqtpbarchartbase.cpp
|
||||
graphs/jkqtpbarchart.cpp
|
||||
graphs/jkqtpboxplot.cpp
|
||||
graphs/jkqtpboxplotstylingmixins.cpp
|
||||
@ -115,6 +116,7 @@ set(HEADERS_GRAPHS
|
||||
graphs/jkqtpscatter.h
|
||||
graphs/jkqtprange.h
|
||||
graphs/jkqtpspecialline.h
|
||||
graphs/jkqtpbarchartbase.h
|
||||
graphs/jkqtpbarchart.h
|
||||
graphs/jkqtpevaluatedparametriccurve.h
|
||||
)
|
||||
|
@ -37,14 +37,9 @@
|
||||
|
||||
|
||||
JKQTPBarVerticalGraph::JKQTPBarVerticalGraph(JKQTBasePlotter* parent):
|
||||
JKQTPXYGraph(parent)
|
||||
JKQTPBarGraphBase(parent)
|
||||
{
|
||||
baseline=0.0;
|
||||
width=0.9;
|
||||
shift=0;
|
||||
|
||||
initFillStyle(parent, parentPlotStyle);
|
||||
initLineStyle(parent, parentPlotStyle);
|
||||
}
|
||||
|
||||
|
||||
@ -53,23 +48,6 @@ JKQTPBarVerticalGraph::JKQTPBarVerticalGraph(JKQTPlotter* parent):
|
||||
{
|
||||
}
|
||||
|
||||
void JKQTPBarVerticalGraph::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
QPen p=getLinePenForRects(painter, parent);
|
||||
QPen np(Qt::NoPen);
|
||||
QBrush b=getFillBrush(painter, parent);
|
||||
//int y=rect.top()+rect.height()/2.0;
|
||||
painter.setPen(p);
|
||||
painter.setBrush(b);
|
||||
painter.drawRect(rect);
|
||||
|
||||
}
|
||||
|
||||
QColor JKQTPBarVerticalGraph::getKeyLabelColor() const {
|
||||
return getFillColor();
|
||||
}
|
||||
|
||||
|
||||
void JKQTPBarVerticalGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaaot("JKQTPBarHorizontalGraph::draw");
|
||||
@ -158,139 +136,46 @@ void JKQTPBarVerticalGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
}
|
||||
|
||||
bool JKQTPBarVerticalGraph::getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) {
|
||||
bool start=true;
|
||||
minx=0;
|
||||
maxx=0;
|
||||
smallestGreaterZero=0;
|
||||
|
||||
if (parent==nullptr) return false;
|
||||
|
||||
JKQTPDatastore* datastore=parent->getDatastore();
|
||||
int imin=0;
|
||||
int imax=static_cast<int>(qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn))));
|
||||
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));
|
||||
int sr=datastore->getNextLowerIndex(xColumn, i);
|
||||
int lr=datastore->getNextHigherIndex(xColumn, i);
|
||||
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;
|
||||
return getPositionsMinMax(minx, maxx, smallestGreaterZero);
|
||||
}
|
||||
|
||||
bool JKQTPBarVerticalGraph::getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) {
|
||||
miny=0;
|
||||
maxy=0;
|
||||
smallestGreaterZero=0;
|
||||
if (baseline>0) {
|
||||
smallestGreaterZero=baseline;
|
||||
miny=baseline;
|
||||
maxy=baseline;
|
||||
}
|
||||
|
||||
if (parent==nullptr) return false;
|
||||
|
||||
JKQTPDatastore* datastore=parent->getDatastore();
|
||||
int imin=0;
|
||||
int imax=static_cast<int>(qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn))));
|
||||
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;
|
||||
return getValuesMinMax(miny, maxy, smallestGreaterZero);
|
||||
}
|
||||
|
||||
void JKQTPBarVerticalGraph::autoscaleBarWidthAndShift(double maxWidth, double shrinkFactor)
|
||||
int JKQTPBarVerticalGraph::getBarPositionColumn() const
|
||||
{
|
||||
if (parent) {
|
||||
double cntH=0;
|
||||
for (size_t i=0; i<parent->getGraphCount(); i++) {
|
||||
JKQTPPlotElement* g=parent->getGraph(i);
|
||||
JKQTPBarVerticalGraph* gb=qobject_cast<JKQTPBarVerticalGraph*>(g);
|
||||
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++) {
|
||||
JKQTPPlotElement* g=parent->getGraph(i);
|
||||
JKQTPBarVerticalGraph* gb=qobject_cast<JKQTPBarVerticalGraph*>(g);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return xColumn;
|
||||
}
|
||||
|
||||
void JKQTPBarVerticalGraph::autoscaleBarWidthAndShiftSeparatedGroups(double groupWidth) {
|
||||
autoscaleBarWidthAndShift(groupWidth, 1);
|
||||
int JKQTPBarVerticalGraph::getBarHeightColumn() const
|
||||
{
|
||||
return yColumn;
|
||||
}
|
||||
|
||||
void JKQTPBarVerticalGraph::setBarPositionColumn(int column)
|
||||
{
|
||||
xColumn=column;
|
||||
}
|
||||
|
||||
void JKQTPBarVerticalGraph::setBarPositionColumn(size_t column)
|
||||
{
|
||||
xColumn=column;
|
||||
}
|
||||
|
||||
void JKQTPBarVerticalGraph::setBarHeightColumn(int column)
|
||||
{
|
||||
yColumn=column;
|
||||
}
|
||||
|
||||
void JKQTPBarVerticalGraph::setBarHeightColumn(size_t column)
|
||||
{
|
||||
yColumn=column;
|
||||
}
|
||||
|
||||
bool JKQTPBarVerticalGraph::considerForAutoscaling(JKQTPBarGraphBase *other) const
|
||||
{
|
||||
return (dynamic_cast<JKQTPBarVerticalGraph*>(other)!=nullptr);
|
||||
}
|
||||
|
||||
|
||||
@ -303,7 +188,7 @@ void JKQTPBarVerticalGraph::autoscaleBarWidthAndShiftSeparatedGroups(double grou
|
||||
|
||||
|
||||
JKQTPBarHorizontalGraph::JKQTPBarHorizontalGraph(JKQTBasePlotter *parent):
|
||||
JKQTPBarVerticalGraph(parent)
|
||||
JKQTPBarGraphBase(parent)
|
||||
{
|
||||
|
||||
}
|
||||
@ -314,6 +199,41 @@ JKQTPBarHorizontalGraph::JKQTPBarHorizontalGraph(JKQTPlotter *parent):
|
||||
|
||||
}
|
||||
|
||||
int JKQTPBarHorizontalGraph::getBarPositionColumn() const
|
||||
{
|
||||
return yColumn;
|
||||
}
|
||||
|
||||
int JKQTPBarHorizontalGraph::getBarHeightColumn() const
|
||||
{
|
||||
return xColumn;
|
||||
}
|
||||
|
||||
void JKQTPBarHorizontalGraph::setBarPositionColumn(int column)
|
||||
{
|
||||
yColumn=column;
|
||||
}
|
||||
|
||||
void JKQTPBarHorizontalGraph::setBarPositionColumn(size_t column)
|
||||
{
|
||||
yColumn=column;
|
||||
}
|
||||
|
||||
void JKQTPBarHorizontalGraph::setBarHeightColumn(int column)
|
||||
{
|
||||
xColumn=column;
|
||||
}
|
||||
|
||||
void JKQTPBarHorizontalGraph::setBarHeightColumn(size_t column)
|
||||
{
|
||||
xColumn=column;
|
||||
}
|
||||
|
||||
bool JKQTPBarHorizontalGraph::considerForAutoscaling(JKQTPBarGraphBase *other) const
|
||||
{
|
||||
return (dynamic_cast<JKQTPBarHorizontalGraph*>(other)!=nullptr);
|
||||
}
|
||||
|
||||
void JKQTPBarHorizontalGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
#ifdef JKQTBP_AUTOTIMER
|
||||
JKQTPAutoOutputTimer jkaaot("JKQTPBarVerticalGraph::draw");
|
||||
@ -401,180 +321,18 @@ void JKQTPBarHorizontalGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
}
|
||||
|
||||
bool JKQTPBarHorizontalGraph::getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) {
|
||||
minx=0;
|
||||
maxx=0;
|
||||
smallestGreaterZero=0;
|
||||
if (baseline>0) {
|
||||
smallestGreaterZero=baseline;
|
||||
minx=baseline;
|
||||
maxx=baseline;
|
||||
}
|
||||
|
||||
if (parent==nullptr) return false;
|
||||
|
||||
JKQTPDatastore* datastore=parent->getDatastore();
|
||||
int imin=0;
|
||||
int imax=static_cast<int>(qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn))));
|
||||
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;
|
||||
return getValuesMinMax(minx, maxx, smallestGreaterZero);
|
||||
}
|
||||
|
||||
bool JKQTPBarHorizontalGraph::getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) {
|
||||
bool start=true;
|
||||
miny=0;
|
||||
maxy=0;
|
||||
smallestGreaterZero=0;
|
||||
return getPositionsMinMax(miny, maxy, smallestGreaterZero);
|
||||
|
||||
if (parent==nullptr) return false;
|
||||
|
||||
JKQTPDatastore* datastore=parent->getDatastore();
|
||||
int imin=0;
|
||||
int imax=static_cast<int>(qMin(datastore->getRows(static_cast<size_t>(xColumn)), datastore->getRows(static_cast<size_t>(yColumn))));
|
||||
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;
|
||||
int sr=datastore->getNextLowerIndex(yColumn, i);
|
||||
int lr=datastore->getNextHigherIndex(yColumn, i);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
bool JKQTPBarHorizontalGraph::isHorizontal() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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::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;
|
||||
}
|
||||
|
||||
void JKQTPBarVerticalGraph::setFillColor_and_darkenedColor(QColor fill, int colorDarker)
|
||||
{
|
||||
setFillColor(fill);
|
||||
setLineColor(fill.darker(colorDarker));
|
||||
}
|
||||
|
||||
JKQTPBarHorizontalErrorGraph::JKQTPBarHorizontalErrorGraph(JKQTBasePlotter *parent):
|
||||
JKQTPBarHorizontalGraph(parent)
|
||||
{
|
||||
@ -641,6 +399,38 @@ void JKQTPBarHorizontalErrorGraph::drawErrorsAfter(JKQTPEnhancedPainter &painter
|
||||
else plotErrorIndicators(painter, parent, this, xColumn, yColumn, 0.0, shift, &sortedIndices);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int JKQTPBarHorizontalErrorGraph::getBarErrorColumn() const
|
||||
{
|
||||
return getXErrorColumn();
|
||||
}
|
||||
|
||||
int JKQTPBarHorizontalErrorGraph::getBarLowerErrorColumn() const
|
||||
{
|
||||
return getXErrorColumnLower();
|
||||
}
|
||||
|
||||
void JKQTPBarHorizontalErrorGraph::setBarErrorColumn(int column)
|
||||
{
|
||||
setXErrorColumn(column);
|
||||
}
|
||||
|
||||
void JKQTPBarHorizontalErrorGraph::setBarErrorColumn(size_t column)
|
||||
{
|
||||
setXErrorColumn(column);
|
||||
}
|
||||
|
||||
void JKQTPBarHorizontalErrorGraph::setBarLowerErrorColumn(int column)
|
||||
{
|
||||
setXErrorColumnLower(column);
|
||||
}
|
||||
|
||||
void JKQTPBarHorizontalErrorGraph::setBarLowerErrorColumn(size_t column)
|
||||
{
|
||||
setXErrorColumnLower(column);
|
||||
}
|
||||
|
||||
JKQTPBarVerticalErrorGraph::JKQTPBarVerticalErrorGraph(JKQTBasePlotter *parent):
|
||||
JKQTPBarVerticalGraph(parent)
|
||||
{
|
||||
@ -745,6 +535,36 @@ bool JKQTPBarVerticalErrorGraph::getYMinMax(double &miny, double &maxy, double &
|
||||
}
|
||||
}
|
||||
|
||||
int JKQTPBarVerticalErrorGraph::getBarErrorColumn() const
|
||||
{
|
||||
return getYErrorColumn();
|
||||
}
|
||||
|
||||
int JKQTPBarVerticalErrorGraph::getBarLowerErrorColumn() const
|
||||
{
|
||||
return getYErrorColumnLower();
|
||||
}
|
||||
|
||||
void JKQTPBarVerticalErrorGraph::setBarErrorColumn(int column)
|
||||
{
|
||||
setYErrorColumn(column);
|
||||
}
|
||||
|
||||
void JKQTPBarVerticalErrorGraph::setBarErrorColumn(size_t column)
|
||||
{
|
||||
setYErrorColumn(column);
|
||||
}
|
||||
|
||||
void JKQTPBarVerticalErrorGraph::setBarLowerErrorColumn(int column)
|
||||
{
|
||||
setYErrorColumnLower(column);
|
||||
}
|
||||
|
||||
void JKQTPBarVerticalErrorGraph::setBarLowerErrorColumn(size_t column)
|
||||
{
|
||||
setYErrorColumnLower(column);
|
||||
}
|
||||
|
||||
void JKQTPBarVerticalErrorGraph::drawErrorsAfter(JKQTPEnhancedPainter &painter)
|
||||
{
|
||||
//plotErrorIndicators(painter, parent, this, xColumn, yColumn, shift, 0.0);
|
||||
@ -752,6 +572,17 @@ void JKQTPBarVerticalErrorGraph::drawErrorsAfter(JKQTPEnhancedPainter &painter)
|
||||
else plotErrorIndicators(painter, parent, this, xColumn, yColumn, shift, 0, &sortedIndices);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
JKQTPBarVerticalStackableGraph::JKQTPBarVerticalStackableGraph(JKQTBasePlotter *parent):
|
||||
JKQTPBarVerticalGraph(parent), stackParent(nullptr)
|
||||
{
|
||||
@ -779,7 +610,7 @@ double JKQTPBarVerticalStackableGraph::getParentStackedMax(int index) const
|
||||
if (stackParent) {
|
||||
return stackParent->getStackedMax(index);
|
||||
} else {
|
||||
return 0.0;
|
||||
return baseline;
|
||||
}
|
||||
}
|
||||
|
||||
@ -793,7 +624,10 @@ const JKQTPBarVerticalStackableGraph *JKQTPBarVerticalStackableGraph::getStackPa
|
||||
return stackParent;
|
||||
}
|
||||
|
||||
|
||||
JKQTPBarVerticalStackableGraph *JKQTPBarVerticalStackableGraph::getStackParent()
|
||||
{
|
||||
return stackParent;
|
||||
}
|
||||
|
||||
double JKQTPBarVerticalStackableGraph::getStackedMax(int index) const
|
||||
{
|
||||
@ -836,6 +670,11 @@ const JKQTPBarHorizontalStackableGraph *JKQTPBarHorizontalStackableGraph::getSta
|
||||
return stackParent;
|
||||
}
|
||||
|
||||
JKQTPBarHorizontalStackableGraph *JKQTPBarHorizontalStackableGraph::getStackParent()
|
||||
{
|
||||
return stackParent;
|
||||
}
|
||||
|
||||
|
||||
double JKQTPBarHorizontalStackableGraph::getStackedMax(int index) const
|
||||
{
|
||||
@ -856,7 +695,7 @@ double JKQTPBarHorizontalStackableGraph::getParentStackedMax(int index) const
|
||||
if (stackParent) {
|
||||
return stackParent->getStackedMax(index);
|
||||
} else {
|
||||
return 0.0;
|
||||
return baseline;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,12 +26,13 @@
|
||||
#include "jkqtplotter/jkqtpgraphsbase.h"
|
||||
#include "jkqtplotter/jkqtpgraphsbaseerrors.h"
|
||||
#include "jkqtplotter/jkqtpgraphsbasestylingmixins.h"
|
||||
#include "jkqtplotter/graphs/jkqtpbarchartbase.h"
|
||||
#ifndef jkqtpgraphsbarchart_H
|
||||
#define jkqtpgraphsbarchart_H
|
||||
|
||||
|
||||
|
||||
/*! \brief This implements a bar graph with bars starting at \f$ y=0 \f$ to \f$ y=f(x) \f$
|
||||
/*! \brief This implements a bar graph with bars starting at \f$ yoverride \f$ to \f$ y=f(x) \f$
|
||||
\ingroup jkqtplotter_barssticks
|
||||
|
||||
This class plots a bargraph. This image explains the parameters:
|
||||
@ -43,7 +44,7 @@
|
||||
to plot multiple bars for every x-value, by having on JKQTPSpecialLineHorizontalGraph object per
|
||||
set of bars that belong together. For example for three bars per x-value one would set:
|
||||
\verbatim
|
||||
width=0.3
|
||||
widthoverride.3
|
||||
shift=-0.3 / 0 / +0.3
|
||||
\endverbatim
|
||||
This results in a bargraph, as shown here:
|
||||
@ -56,7 +57,7 @@
|
||||
|
||||
\see JKQTPBarHorizontalGraph, \ref JKQTPlotterBarcharts, jkqtpstatAddHHistogram1D(), jkqtpstatAddHHistogram1DAutoranged()
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPBarVerticalGraph: public JKQTPXYGraph, public JKQTPGraphLineStyleMixin, public JKQTPGraphFillStyleMixin {
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPBarVerticalGraph: public JKQTPBarGraphBase {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/** \brief class constructor */
|
||||
@ -66,10 +67,6 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBarVerticalGraph: public JKQTPXYGraph, public
|
||||
|
||||
/** \brief plots the graph to the plotter object specified as parent */
|
||||
virtual void draw(JKQTPEnhancedPainter& painter) override;
|
||||
/** \brief plots a key marker inside the specified rectangle \a rect */
|
||||
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) override;
|
||||
/** \brief returns the color to be used for the key label */
|
||||
virtual QColor getKeyLabelColor() const override;
|
||||
|
||||
/** \brief get the maximum and minimum x-value of the graph
|
||||
*
|
||||
@ -81,132 +78,35 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBarVerticalGraph: public JKQTPXYGraph, public
|
||||
* The result is given in the two parameters which are call-by-reference parameters!
|
||||
*/
|
||||
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) override;
|
||||
|
||||
/** \brief returns xColumn or yColumn, whichever is used for the position of the bars (depending on whether the barchart is vertical or horizontal \see getBarHeightColumn(), xColumn, yColumn */
|
||||
virtual int getBarPositionColumn() const override;
|
||||
|
||||
/** \brief returns xColumn or yColumn, whichever is used for the height of the bars (depending on whether the barchart is vertical or horizontal \see getBarPositionColumn(), xColumn, yColumn */
|
||||
virtual int getBarHeightColumn() const override;
|
||||
|
||||
/** \brief finds all bar charts of the same orientation and determines width and shift, so they stand side by side
|
||||
*
|
||||
* \param maxWidth the maximum (relative) width, that all bars will span of the (doubled) inter-bar distance
|
||||
* \param shrinkFactor factor, by which the bar are shrinked compared to the available space
|
||||
*
|
||||
* \note This function will scale ALL graphs of the parent plot, which were derived from JKQTPBarHorizontalGraph, that match in orientation (as returned by isHorizontal() ).
|
||||
*/
|
||||
virtual void autoscaleBarWidthAndShift(double maxWidth=0.9, double shrinkFactor=0.8);
|
||||
public slots:
|
||||
/** \brief returns xColumn or yColumn, whichever is used for the position of the bars (depending on whether the barchart is vertical or horizontal \see getBarHeightColumn(), xColumn, yColumn */
|
||||
virtual void setBarPositionColumn(int column) override;
|
||||
|
||||
/** \brief returns xColumn or yColumn, whichever is used for the position of the bars (depending on whether the barchart is vertical or horizontal \see getBarHeightColumn(), xColumn, yColumn */
|
||||
virtual void setBarPositionColumn(size_t column) override;
|
||||
|
||||
/** \brief returns xColumn or yColumn, whichever is used for the height of the bars (depending on whether the barchart is vertical or horizontal \see getBarPositionColumn(), xColumn, yColumn */
|
||||
virtual void setBarHeightColumn(int column) override;
|
||||
|
||||
/** \brief returns xColumn or yColumn, whichever is used for the height of the bars (depending on whether the barchart is vertical or horizontal \see getBarPositionColumn(), xColumn, yColumn */
|
||||
virtual void setBarHeightColumn(size_t column) override;
|
||||
|
||||
/** \brief equivalent to \c autoscaleBarWidthAndShift(groupWidth,1);
|
||||
*/
|
||||
void autoscaleBarWidthAndShiftSeparatedGroups(double groupWidth=0.75);
|
||||
|
||||
/** \brief retruns \c true, if the bars are horizontal (JKQTPBarHorizontalGraph) and \c false if they are vertical (JKQTPBarVerticalGraph) */
|
||||
virtual bool isHorizontal() const;
|
||||
|
||||
/** \brief set outline and fill color at the same time
|
||||
* \see setFillColor_and_darkenedColor()
|
||||
*/
|
||||
virtual void setColor(QColor c);
|
||||
|
||||
/*! \copydoc shift */
|
||||
void setShift(double __value);
|
||||
/*! \copydoc shift */
|
||||
double getShift() const;
|
||||
/*! \copydoc width */
|
||||
void setWidth(double __value);
|
||||
/*! \copydoc width */
|
||||
double getWidth() const;
|
||||
/*! \copydoc baseline */
|
||||
void setBaseline(double __value);
|
||||
/*! \copydoc baseline */
|
||||
double getBaseline() const;
|
||||
/** \brief sets the fill color and the color together, where fillColor is set to \a fill and the line-color is set to \c fill.darker(colorDarker)
|
||||
* \see setColor()
|
||||
*/
|
||||
void setFillColor_and_darkenedColor(QColor fill, int colorDarker=200);
|
||||
protected:
|
||||
/** \brief the width of the bargraphs, relative to the distance between the current and the next x-value
|
||||
*
|
||||
* See the following graphic to understand this concept:
|
||||
* \image html bargraph_basics.png
|
||||
*/
|
||||
double width;
|
||||
/** \brief the shift of the bargraphs, relative to the distance between the current and the next x-value
|
||||
*
|
||||
* See the following graphic to understand this concept:
|
||||
* \image html bargraph_basics.png
|
||||
*/
|
||||
double shift;
|
||||
|
||||
/** \brief baseline of the plot (NOTE: 0 is interpreted as until plot border in log-mode!!!)
|
||||
*/
|
||||
double baseline;
|
||||
|
||||
|
||||
/** \brief used to generate stacked plots: returns the upper boundary of this plot in a stack, for the index-th datapoint
|
||||
*
|
||||
* \note This function returns \a baseline in this implementation. It is implemented in the derived classes JKQTPBarVerticalStackableGraph
|
||||
* and JKQTPBarHorizontalStackableGraph. The function is placed here, so the plotting does not have to be reimplemented in the
|
||||
* derived classes that allow for stacking, but can be implemented once centrally.
|
||||
*/
|
||||
virtual double getStackedMax(int index) const;
|
||||
|
||||
/** \brief calls getStackedMax() on the stack parent (if available)
|
||||
*
|
||||
* \note This function returns \c 0.0 in this implementation. It is implemented in the derived classes JKQTPBarVerticalStackableGraph
|
||||
* and JKQTPBarHorizontalStackableGraph. The function is placed here, so the plotting does not have to be reimplemented in the
|
||||
* derived classes that allow for stacking, but can be implemented once centrally.
|
||||
*/
|
||||
virtual double getParentStackedMax(int index) const;
|
||||
|
||||
/** \brief returns \c true, if a stack parent is set (if available)
|
||||
*
|
||||
* \note This function returns \c false in this implementation. It is implemented in the derived classes JKQTPBarVerticalStackableGraph
|
||||
* and JKQTPBarHorizontalStackableGraph. The function is placed here, so the plotting does not have to be reimplemented in the
|
||||
* derived classes that allow for stacking, but can be implemented once centrally.
|
||||
*/
|
||||
virtual bool hasStackParent() const;
|
||||
|
||||
/** \brief this function is used by autoscaleBarWidthAndShift() to determine whether a given graph shall be taken into account when autoscaling.
|
||||
* Typically this returns \c true for all JKQTPBarGraphBase-derved objects with the same orientation (horizontal or vertical) */
|
||||
virtual bool considerForAutoscaling( JKQTPBarGraphBase* other) const override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*! \brief This implements a bar graph with bars starting at \f$ y=0 \f$ to \f$ y=f(x) \f$
|
||||
* Optionally several graphs of this type may be stacked on top of each other
|
||||
* \ingroup jkqtplotter_barssticks
|
||||
*
|
||||
* Draw stacked barcharts by connecting several plots by calling \c setStackedParent(belowPlot) for each plot
|
||||
* \image html JKQTPBarVerticalGraphStacked.png
|
||||
*
|
||||
* \see JKQTPBarVerticalGraph, \ref JKQTPlotterStackedBarChart
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPBarVerticalStackableGraph: public JKQTPBarVerticalGraph {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/** \brief class constructor */
|
||||
JKQTPBarVerticalStackableGraph(JKQTBasePlotter* parent=nullptr);
|
||||
/** \brief class constructor */
|
||||
JKQTPBarVerticalStackableGraph(JKQTPlotter* parent);
|
||||
/** \brief stacks this barchart upon the given \a parentGraph */
|
||||
void stackUpon(JKQTPBarVerticalStackableGraph* parentGraph);
|
||||
/** \brief unstacks this graph (i.e. deletes the parent graph in the stack) */
|
||||
void dontStackUpon();
|
||||
/** \brief returns the stack parent graph, or \c nullptr */
|
||||
const JKQTPBarVerticalStackableGraph* getStackParent() const;
|
||||
|
||||
protected:
|
||||
|
||||
/** \brief if set (!=nullptr), the current plot is drawn stacked onto this plot
|
||||
*
|
||||
* draw stacked barcharts by connecting several plots by calling \c setStackedParent(belowPlot) for each plot
|
||||
*/
|
||||
JKQTPBarVerticalStackableGraph* stackParent;
|
||||
|
||||
/** \brief used to generate stacked plots: returns the upper boundary of this plot in a stack, for the index-th datapoint */
|
||||
virtual double getStackedMax(int index) const override;
|
||||
/** \brief calls getStackedMax() on the stack parent (if available), or \c 0.0 */
|
||||
virtual double getParentStackedMax(int index) const override;
|
||||
|
||||
/** \brief returns \c true, if a stack parent is set (if available) */
|
||||
virtual bool hasStackParent() const override;
|
||||
};
|
||||
|
||||
/*! \brief This implements a bar graph with bars starting at \f$ y=0 \f$ to \f$ y=f(x) \f$
|
||||
/*! \brief This implements a bar graph with bars starting at \f$ yoverride \f$ to \f$ y=f(x) \f$
|
||||
* and error indicator
|
||||
* \ingroup jkqtplotter_barssticks
|
||||
*
|
||||
@ -231,6 +131,22 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBarVerticalErrorGraph: public JKQTPBarVertical
|
||||
*/
|
||||
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) override;
|
||||
|
||||
/** \brief returns the column that contains the bar height errors */
|
||||
int getBarErrorColumn() const;
|
||||
/** \brief returns the column that contains the lower bar height errors */
|
||||
int getBarLowerErrorColumn() const;
|
||||
public slots:
|
||||
/** \brief sets the column that contains the bar height errors */
|
||||
void setBarErrorColumn(int column) ;
|
||||
|
||||
/** \brief sets the column that contains the bar height errors */
|
||||
void setBarErrorColumn(size_t column) ;
|
||||
/** \brief sets the column that contains the bar height errors */
|
||||
void setBarLowerErrorColumn(int column) ;
|
||||
|
||||
/** \brief sets the column that contains the bar height errors */
|
||||
void setBarLowerErrorColumn(size_t column) ;
|
||||
|
||||
protected:
|
||||
/** \brief this function is used to plot error inidcators before plotting the graphs. */
|
||||
virtual void drawErrorsAfter(JKQTPEnhancedPainter& painter) override;
|
||||
@ -239,7 +155,8 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBarVerticalErrorGraph: public JKQTPBarVertical
|
||||
|
||||
|
||||
|
||||
/*! \brief This implements a bar graph with bars starting at \f$ x=0 \f$ to \f$ x=f(y) \f$
|
||||
|
||||
/*! \brief This implements a bar graph with bars starting at \f$ xoverride \f$ to \f$ x=f(y) \f$
|
||||
\ingroup jkqtplotter_barssticks
|
||||
|
||||
This works much the same as JKQTPBarHorizontalGraph. Here is an example output:
|
||||
@ -249,7 +166,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBarVerticalErrorGraph: public JKQTPBarVertical
|
||||
|
||||
\see \ref JKQTPlotterBarcharts, jkqtpstatAddVHistogram1D(), jkqtpstatAddVHistogram1DAutoranged()
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPBarHorizontalGraph: public JKQTPBarVerticalGraph {
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPBarHorizontalGraph: public JKQTPBarGraphBase {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/** \brief class constructor */
|
||||
@ -271,54 +188,34 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBarHorizontalGraph: public JKQTPBarVerticalGra
|
||||
*/
|
||||
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) override;
|
||||
|
||||
virtual bool isHorizontal() const override;
|
||||
/** \brief returns xColumn or yColumn, whichever is used for the position of the bars (depending on whether the barchart is vertical or horizontal \see getBarHeightColumn(), xColumn, yColumn */
|
||||
virtual int getBarPositionColumn() const override;
|
||||
|
||||
/** \brief returns xColumn or yColumn, whichever is used for the height of the bars (depending on whether the barchart is vertical or horizontal \see getBarPositionColumn(), xColumn, yColumn */
|
||||
virtual int getBarHeightColumn() const override;
|
||||
public slots:
|
||||
|
||||
/** \brief sets xColumn or yColumn, whichever is used for the position of the bars (depending on whether the barchart is vertical or horizontal \see getBarHeightColumn(), xColumn, yColumn */
|
||||
virtual void setBarPositionColumn(int column) override;
|
||||
|
||||
/** \brief sets xColumn or yColumn, whichever is used for the position of the bars (depending on whether the barchart is vertical or horizontal \see getBarHeightColumn(), xColumn, yColumn */
|
||||
virtual void setBarPositionColumn(size_t column) override;
|
||||
|
||||
/** \brief sets xColumn or yColumn, whichever is used for the height of the bars (depending on whether the barchart is vertical or horizontal \see getBarPositionColumn(), xColumn, yColumn */
|
||||
virtual void setBarHeightColumn(int column) override;
|
||||
|
||||
/** \brief sets xColumn or yColumn, whichever is used for the height of the bars (depending on whether the barchart is vertical or horizontal \see getBarPositionColumn(), xColumn, yColumn */
|
||||
virtual void setBarHeightColumn(size_t column) override;
|
||||
protected:
|
||||
|
||||
/** \brief this function is used by autoscaleBarWidthAndShift() to determine whether a given graph shall be taken into account when autoscaling.
|
||||
* Typically this returns \c true for all JKQTPBarGraphBase-derved objects with the same orientation (horizontal or vertical) */
|
||||
virtual bool considerForAutoscaling( JKQTPBarGraphBase* other) const override;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*! \brief This implements a bar graph with bars starting at \f$ y=0 \f$ to \f$ y=f(x) \f$
|
||||
* Optionally several graphs of this type may be stacked on top of each other
|
||||
* \ingroup jkqtplotter_barssticks
|
||||
*
|
||||
* Draw stacked barcharts by connecting several plots by calling \c setStackedParent(belowPlot) for each plot
|
||||
* \image html JKQTPBarHorizontalGraphStacked.png
|
||||
*
|
||||
*
|
||||
* \see JKQTPBarHorizontalGraph, \ref JKQTPlotterStackedBarChart
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPBarHorizontalStackableGraph: public JKQTPBarHorizontalGraph {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/** \brief class constructor */
|
||||
JKQTPBarHorizontalStackableGraph(JKQTBasePlotter* parent=nullptr);
|
||||
/** \brief class constructor */
|
||||
JKQTPBarHorizontalStackableGraph(JKQTPlotter* parent);
|
||||
/** \brief stacks this barchart upon the given \a parentGraph */
|
||||
void stackUpon(JKQTPBarHorizontalStackableGraph* parentGraph);
|
||||
/** \brief unstacks this graph (i.e. deletes the parent graph in the stack) */
|
||||
void dontStackUpon();
|
||||
/** \brief returns the stack parent graph, or \c nullptr */
|
||||
const JKQTPBarHorizontalStackableGraph* getStackParent() const;
|
||||
|
||||
protected:
|
||||
|
||||
/** \brief if set (!=nullptr), the current plot is drawn stacked onto this plot
|
||||
*
|
||||
* draw stacked barcharts by connecting several plots by calling \c setStackedParent(belowPlot) for each plot
|
||||
*/
|
||||
JKQTPBarHorizontalStackableGraph* stackParent;
|
||||
|
||||
/** \brief used to generate stacked plots: returns the upper boundary of this plot in a stack, for the index-th datapoint */
|
||||
virtual double getStackedMax(int index) const override;
|
||||
/** \brief calls getStackedMax() on the stack parent (if available), or \c 0.0 */
|
||||
virtual double getParentStackedMax(int index) const override;
|
||||
|
||||
/** \brief returns \c true, if a stack parent is set (if available) */
|
||||
virtual bool hasStackParent() const override;
|
||||
};
|
||||
|
||||
/*! \brief This implements a bar graph with bars starting at \f$ x=0 \f$ to \f$ x=f(y) \f$
|
||||
/*! \brief This implements a bar graph with bars starting at \f$ xoverride \f$ to \f$ x=f(y) \f$
|
||||
* and error indicator
|
||||
* \ingroup jkqtplotter_barssticks
|
||||
*
|
||||
@ -344,6 +241,22 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBarHorizontalErrorGraph: public JKQTPBarHorizo
|
||||
*/
|
||||
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) override;
|
||||
|
||||
|
||||
/** \brief returns the column that contains the bar height errors */
|
||||
int getBarErrorColumn() const;
|
||||
/** \brief returns the column that contains the lower bar height errors */
|
||||
int getBarLowerErrorColumn() const;
|
||||
public slots:
|
||||
/** \brief sets the column that contains the bar height errors */
|
||||
void setBarErrorColumn(int column) ;
|
||||
|
||||
/** \brief sets the column that contains the bar height errors */
|
||||
void setBarErrorColumn(size_t column) ;
|
||||
/** \brief sets the column that contains the bar height errors */
|
||||
void setBarLowerErrorColumn(int column) ;
|
||||
|
||||
/** \brief sets the column that contains the bar height errors */
|
||||
void setBarLowerErrorColumn(size_t column) ;
|
||||
protected:
|
||||
/** \brief this function is used to plot error inidcators before plotting the graphs. */
|
||||
virtual void drawErrorsAfter(JKQTPEnhancedPainter& painter) override;
|
||||
@ -355,4 +268,109 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBarHorizontalErrorGraph: public JKQTPBarHorizo
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*! \brief This implements a bar graph with bars starting at \f$ yoverride \f$ to \f$ y=f(x) \f$
|
||||
* Optionally several graphs of this type may be stacked on top of each other
|
||||
* \ingroup jkqtplotter_barssticks
|
||||
*
|
||||
* Draw stacked barcharts by connecting several plots by calling \c setStackedParent(belowPlot) for each plot
|
||||
* \image html JKQTPBarVerticalGraphStacked.png
|
||||
*
|
||||
* \see JKQTPBarVerticalGraph, \ref JKQTPlotterStackedBarChart
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPBarVerticalStackableGraph: public JKQTPBarVerticalGraph {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/** \brief class constructor */
|
||||
JKQTPBarVerticalStackableGraph(JKQTBasePlotter* parent=nullptr);
|
||||
/** \brief class constructor */
|
||||
JKQTPBarVerticalStackableGraph(JKQTPlotter* parent);
|
||||
/** \brief stacks this barchart upon the given \a parentGraph */
|
||||
void stackUpon(JKQTPBarVerticalStackableGraph* parentGraph);
|
||||
/** \brief unstacks this graph (i.e. deletes the parent graph in the stack) */
|
||||
void dontStackUpon();
|
||||
/** \brief returns the stack parent graph, or \c nullptr */
|
||||
const JKQTPBarVerticalStackableGraph* getStackParent() const;
|
||||
/** \brief returns the stack parent graph, or \c nullptr */
|
||||
JKQTPBarVerticalStackableGraph* getStackParent();
|
||||
|
||||
protected:
|
||||
|
||||
/** \brief if set (!=nullptr), the current plot is drawn stacked onto this plot
|
||||
*
|
||||
* draw stacked barcharts by connecting several plots by calling \c setStackedParent(belowPlot) for each plot
|
||||
*/
|
||||
JKQTPBarVerticalStackableGraph* stackParent;
|
||||
|
||||
/** \brief used to generate stacked plots: returns the upper boundary of the parent plot in a stack, for the index-th datapoint */
|
||||
double getParentStackedMax(int index) const ;
|
||||
|
||||
|
||||
/** \brief returns \c true, if a stack parent is set (if available) */
|
||||
bool hasStackParent() const ;
|
||||
/** \brief used to generate stacked plots: returns the upper boundary of this plot in a stack, for the index-th datapoint */
|
||||
double getStackedMax(int index) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*! \brief This implements a bar graph with bars starting at \f$ yoverride \f$ to \f$ y=f(x) \f$
|
||||
* Optionally several graphs of this type may be stacked on top of each other
|
||||
* \ingroup jkqtplotter_barssticks
|
||||
*
|
||||
* Draw stacked barcharts by connecting several plots by calling \c setStackedParent(belowPlot) for each plot
|
||||
* \image html JKQTPBarHorizontalGraphStacked.png
|
||||
*
|
||||
*
|
||||
* \see JKQTPBarHorizontalGraph, \ref JKQTPlotterStackedBarChart
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPBarHorizontalStackableGraph: public JKQTPBarHorizontalGraph {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/** \brief class constructor */
|
||||
JKQTPBarHorizontalStackableGraph(JKQTBasePlotter* parent=nullptr);
|
||||
/** \brief class constructor */
|
||||
JKQTPBarHorizontalStackableGraph(JKQTPlotter* parent);
|
||||
/** \brief stacks this barchart upon the given \a parentGraph */
|
||||
void stackUpon(JKQTPBarHorizontalStackableGraph* parentGraph);
|
||||
/** \brief unstacks this graph (i.e. deletes the parent graph in the stack) */
|
||||
void dontStackUpon();
|
||||
/** \brief returns the stack parent graph, or \c nullptr */
|
||||
const JKQTPBarHorizontalStackableGraph* getStackParent() const;
|
||||
/** \brief returns the stack parent graph, or \c nullptr */
|
||||
JKQTPBarHorizontalStackableGraph* getStackParent() ;
|
||||
|
||||
protected:
|
||||
|
||||
/** \brief if set (!=nullptr), the current plot is drawn stacked onto this plot
|
||||
*
|
||||
* draw stacked barcharts by connecting several plots by calling \c setStackedParent(belowPlot) for each plot
|
||||
*/
|
||||
JKQTPBarHorizontalStackableGraph* stackParent;
|
||||
|
||||
/** \brief used to generate stacked plots: returns the upper boundary of the parent plot in a stack, for the index-th datapoint */
|
||||
virtual double getParentStackedMax(int index) const override;
|
||||
|
||||
/** \brief returns \c true, if a stack parent is set (if available) */
|
||||
virtual bool hasStackParent() const override;
|
||||
/** \brief used to generate stacked plots: returns the upper boundary of this plot in a stack, for the index-th datapoint */
|
||||
double getStackedMax(int index) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // jkqtpgraphsbarchart_H
|
||||
|
273
lib/jkqtplotter/graphs/jkqtpbarchartbase.cpp
Normal file
273
lib/jkqtplotter/graphs/jkqtpbarchartbase.cpp
Normal file
@ -0,0 +1,273 @@
|
||||
/*
|
||||
Copyright (c) 2008-2020 Jan W. Krieger (<jan@jkrieger.de>)
|
||||
|
||||
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "jkqtplotter/graphs/jkqtpbarchartbase.h"
|
||||
#include "jkqtplotter/jkqtpbaseplotter.h"
|
||||
#include <stdlib.h>
|
||||
#include <QDebug>
|
||||
#include <iostream>
|
||||
#include "jkqtplotter/jkqtptools.h"
|
||||
#include "jkqtplotter/graphs/jkqtpimage.h"
|
||||
#include "jkqtplotter/jkqtpbaseelements.h"
|
||||
#include "jkqtplotter/jkqtplotter.h"
|
||||
|
||||
#define SmallestGreaterZeroCompare_xvsgz() if ((xvsgz>10.0*DBL_MIN)&&((smallestGreaterZero<10.0*DBL_MIN) || (xvsgz<smallestGreaterZero))) smallestGreaterZero=xvsgz;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
JKQTPBarGraphBase::JKQTPBarGraphBase(JKQTBasePlotter* parent):
|
||||
JKQTPXYGraph(parent), width(0.9), shift(0), baseline(0.0)
|
||||
{
|
||||
initFillStyle(parent, parentPlotStyle);
|
||||
initLineStyle(parent, parentPlotStyle);
|
||||
}
|
||||
|
||||
|
||||
JKQTPBarGraphBase::JKQTPBarGraphBase(JKQTPlotter* parent):
|
||||
JKQTPBarGraphBase(parent->getPlotter())
|
||||
{
|
||||
}
|
||||
|
||||
void JKQTPBarGraphBase::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
QPen p=getLinePenForRects(painter, parent);
|
||||
QPen np(Qt::NoPen);
|
||||
QBrush b=getFillBrush(painter, parent);
|
||||
//int y=rect.top()+rect.height()/2.0;
|
||||
painter.setPen(p);
|
||||
painter.setBrush(b);
|
||||
painter.drawRect(rect);
|
||||
|
||||
}
|
||||
|
||||
QColor JKQTPBarGraphBase::getKeyLabelColor() const {
|
||||
return getFillColor();
|
||||
}
|
||||
|
||||
|
||||
void JKQTPBarGraphBase::autoscaleBarWidthAndShift(double maxWidth, double shrinkFactor)
|
||||
{
|
||||
if (parent) {
|
||||
double cntH=0;
|
||||
for (size_t i=0; i<parent->getGraphCount(); i++) {
|
||||
JKQTPPlotElement* g=parent->getGraph(i);
|
||||
JKQTPBarGraphBase* gb=qobject_cast<JKQTPBarGraphBase*>(g);
|
||||
if (gb && considerForAutoscaling(gb)) {
|
||||
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++) {
|
||||
JKQTPPlotElement* g=parent->getGraph(i);
|
||||
JKQTPBarGraphBase* gb=qobject_cast<JKQTPBarGraphBase*>(g);
|
||||
if (gb && considerForAutoscaling(gb)) {
|
||||
if (cntH>1) {
|
||||
gb->width=widthH;
|
||||
gb->shift=h-0.5;
|
||||
h=h+dH;
|
||||
} else {
|
||||
gb->width=maxWidth;
|
||||
gb->shift=0.0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void JKQTPBarGraphBase::autoscaleBarWidthAndShiftSeparatedGroups(double groupWidth) {
|
||||
autoscaleBarWidthAndShift(groupWidth, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void JKQTPBarGraphBase::setColor(QColor c)
|
||||
{
|
||||
setLineColor(c);
|
||||
setFillColor(JKQTPGetDerivedColor(parent->getCurrentPlotterStyle().graphFillColorDerivationMode, c));
|
||||
c.setAlphaF(0.5);
|
||||
setHighlightingLineColor(c);
|
||||
}
|
||||
|
||||
void JKQTPBarGraphBase::setShift(double __value)
|
||||
{
|
||||
this->shift = __value;
|
||||
}
|
||||
|
||||
double JKQTPBarGraphBase::getShift() const
|
||||
{
|
||||
return this->shift;
|
||||
}
|
||||
|
||||
void JKQTPBarGraphBase::setWidth(double __value)
|
||||
{
|
||||
this->width = __value;
|
||||
}
|
||||
|
||||
double JKQTPBarGraphBase::getWidth() const
|
||||
{
|
||||
return this->width;
|
||||
}
|
||||
|
||||
void JKQTPBarGraphBase::setBaseline(double __value)
|
||||
{
|
||||
this->baseline = __value;
|
||||
}
|
||||
|
||||
double JKQTPBarGraphBase::getBaseline() const
|
||||
{
|
||||
return this->baseline;
|
||||
}
|
||||
|
||||
void JKQTPBarGraphBase::setFillColor_and_darkenedColor(QColor fill, int colorDarker)
|
||||
{
|
||||
setFillColor(fill);
|
||||
setLineColor(fill.darker(colorDarker));
|
||||
}
|
||||
|
||||
double JKQTPBarGraphBase::getParentStackedMax(int /*index*/) const
|
||||
{
|
||||
return baseline;
|
||||
}
|
||||
|
||||
bool JKQTPBarGraphBase::hasStackParent() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool JKQTPBarGraphBase::getValuesMinMax(double &mmin, double &mmax, double &smallestGreaterZero)
|
||||
{
|
||||
mmin=0;
|
||||
mmax=0;
|
||||
smallestGreaterZero=0;
|
||||
if (baseline>0) {
|
||||
smallestGreaterZero=baseline;
|
||||
mmin=baseline;
|
||||
mmax=baseline;
|
||||
}
|
||||
|
||||
if (getBarPositionColumn()<0 || getBarHeightColumn()<0) return false;
|
||||
|
||||
const size_t poscol=static_cast<size_t>(getBarPositionColumn());
|
||||
const size_t datacol=static_cast<size_t>(getBarHeightColumn());
|
||||
|
||||
if (parent==nullptr) return false;
|
||||
|
||||
JKQTPDatastore* datastore=parent->getDatastore();
|
||||
int imin=0;
|
||||
int imax=static_cast<int>(qMin(datastore->getRows(poscol), datastore->getRows(datacol)));
|
||||
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;
|
||||
const double boxstart=getParentStackedMax(i);
|
||||
if (hasStackParent()) {
|
||||
stack=boxstart;
|
||||
yv=stack;
|
||||
}
|
||||
if (JKQTPIsOKFloat(yv)) {
|
||||
if (yv>mmax) mmax=yv;
|
||||
if (yv<mmin) mmin=yv;
|
||||
double xvsgz;
|
||||
xvsgz=yv; SmallestGreaterZeroCompare_xvsgz();
|
||||
}
|
||||
yv=stack+datastore->get(datacol,static_cast<size_t>(i));
|
||||
if (JKQTPIsOKFloat(yv)) {
|
||||
if (yv>mmax) mmax=yv;
|
||||
if (yv<mmin) mmin=yv;
|
||||
double xvsgz;
|
||||
xvsgz=yv; SmallestGreaterZeroCompare_xvsgz();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JKQTPBarGraphBase::getPositionsMinMax(double &mmin, double &mmax, double &smallestGreaterZero)
|
||||
{
|
||||
bool start=true;
|
||||
mmin=0;
|
||||
mmax=0;
|
||||
smallestGreaterZero=0;
|
||||
|
||||
if (getBarPositionColumn()<0 || getBarHeightColumn()<0) return false;
|
||||
|
||||
const size_t poscol=static_cast<size_t>(getBarPositionColumn());
|
||||
const size_t datacol=static_cast<size_t>(getBarHeightColumn());
|
||||
|
||||
if (parent==nullptr) return false;
|
||||
|
||||
JKQTPDatastore* datastore=parent->getDatastore();
|
||||
int imin=0;
|
||||
int imax=static_cast<int>(qMin(datastore->getRows(poscol), datastore->getRows(datacol)));
|
||||
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(poscol,static_cast<size_t>(i));
|
||||
int sr=datastore->getNextLowerIndex(poscol, i);
|
||||
int lr=datastore->getNextHigherIndex(poscol, i);
|
||||
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(poscol,sr))/2.0;
|
||||
} else if (sr<0) { // the left-most x-value
|
||||
deltam=deltap=fabs(datastore->get(poscol,lr)-xv)/2.0;
|
||||
} else {
|
||||
deltam=fabs(xv-datastore->get(poscol,sr))/2.0;
|
||||
deltap=fabs(datastore->get(poscol,lr)-xv)/2.0;
|
||||
}
|
||||
delta=deltap+deltam;
|
||||
|
||||
if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(delta) ) {
|
||||
|
||||
if (start || xv+shift*delta+width*delta/2.0>mmax) mmax=xv+shift*delta+width*delta/2.0;
|
||||
if (start || xv+shift*delta-width*delta/2.0<mmin) mmin=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;
|
||||
}
|
||||
|
172
lib/jkqtplotter/graphs/jkqtpbarchartbase.h
Normal file
172
lib/jkqtplotter/graphs/jkqtpbarchartbase.h
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
Copyright (c) 2008-2020 Jan W. Krieger (<jan@jkrieger.de>)
|
||||
|
||||
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QString>
|
||||
#include <QPainter>
|
||||
#include <QPair>
|
||||
#include "jkqtplotter/jkqtptools.h"
|
||||
#include "jkqtplotter/jkqtplotter_imexport.h"
|
||||
#include "jkqtplotter/jkqtpimagetools.h"
|
||||
#include "jkqtplotter/jkqtpgraphsbase.h"
|
||||
#include "jkqtplotter/jkqtpgraphsbaseerrors.h"
|
||||
#include "jkqtplotter/jkqtpgraphsbasestylingmixins.h"
|
||||
#ifndef jkqtpgraphsbarchartbase_H
|
||||
#define jkqtpgraphsbarchartbase_H
|
||||
|
||||
|
||||
|
||||
/** \brief This is a base-class for all bar graphs with vertical or horizontal orientation (the orientation is implemented in dervied classes!)
|
||||
* \ingroup jkqtplotter_barssticks
|
||||
*
|
||||
* This class plots a bargraph. This image explains the parameters:
|
||||
*
|
||||
* \image html bargraph_basics.png
|
||||
*
|
||||
* By default the sift parameter is, so the bar is centered at the x-value. The width is 0.9,
|
||||
* so adjacent bars are plotted with a small distance between them. It is possible to use these two parameters
|
||||
* to plot multiple bars for every x-value, by having on JKQTPSpecialLineHorizontalGraph object per
|
||||
* set of bars that belong together. For example for three bars per x-value one would set:
|
||||
* \verbatim
|
||||
* width=0.3
|
||||
* shift=-0.3 / 0 / +0.3
|
||||
* \endverbatim
|
||||
* This results in a bargraph, as shown here:
|
||||
*
|
||||
* \image html plot_bargraphverplot.png
|
||||
*
|
||||
*
|
||||
*
|
||||
* \see JKQTPBarHorizontalGraph, JKQTPBarVerticalGraph
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPBarGraphBase: public JKQTPXYGraph, public JKQTPGraphLineStyleMixin, public JKQTPGraphFillStyleMixin {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/** \brief class constructor */
|
||||
JKQTPBarGraphBase(JKQTBasePlotter* parent=nullptr);
|
||||
/** \brief class constructor */
|
||||
JKQTPBarGraphBase(JKQTPlotter* parent);
|
||||
|
||||
/** \brief plots a key marker inside the specified rectangle \a rect */
|
||||
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) override;
|
||||
/** \brief returns the color to be used for the key label */
|
||||
virtual QColor getKeyLabelColor() const override;
|
||||
|
||||
|
||||
|
||||
/*! \copydoc shift */
|
||||
double getShift() const;
|
||||
/*! \copydoc width */
|
||||
double getWidth() const;
|
||||
/*! \copydoc baseline */
|
||||
double getBaseline() const;
|
||||
/** \brief sets the fill color and the color together, where fillColor is set to \a fill and the line-color is set to \c fill.darker(colorDarker)
|
||||
* \see setColor()
|
||||
*/
|
||||
void setFillColor_and_darkenedColor(QColor fill, int colorDarker=200);
|
||||
|
||||
/** \brief returns xColumn or yColumn, whichever is used for the position of the bars (depending on whether the barchart is vertical or horizontal \see getBarHeightColumn(), xColumn, yColumn */
|
||||
virtual int getBarPositionColumn() const =0;
|
||||
|
||||
/** \brief returns xColumn or yColumn, whichever is used for the height of the bars (depending on whether the barchart is vertical or horizontal \see getBarPositionColumn(), xColumn, yColumn */
|
||||
virtual int getBarHeightColumn() const =0;
|
||||
public slots:
|
||||
|
||||
/** \brief finds all bar charts of the same orientation and determines width and shift, so they stand side by side
|
||||
*
|
||||
* \param maxWidth the maximum (relative) width, that all bars will span of the (doubled) inter-bar distance
|
||||
* \param shrinkFactor factor, by which the bar are shrinked compared to the available space
|
||||
*
|
||||
* \note This function will scale ALL graphs of the parent plot, which were derived from JKQTPBarHorizontalGraph, that match in orientation (as returned by isHorizontal() ).
|
||||
*/
|
||||
virtual void autoscaleBarWidthAndShift(double maxWidth=0.9, double shrinkFactor=0.8);
|
||||
|
||||
/** \brief equivalent to \c autoscaleBarWidthAndShift(groupWidth,1);
|
||||
*/
|
||||
void autoscaleBarWidthAndShiftSeparatedGroups(double groupWidth=0.75);
|
||||
/*! \copydoc shift */
|
||||
void setShift(double __value);
|
||||
/*! \copydoc width */
|
||||
void setWidth(double __value);
|
||||
/*! \copydoc baseline */
|
||||
void setBaseline(double __value);
|
||||
|
||||
/** \brief set outline and fill color at the same time
|
||||
* \see setFillColor_and_darkenedColor()
|
||||
*/
|
||||
virtual void setColor(QColor c);
|
||||
|
||||
|
||||
/** \brief returns xColumn or yColumn, whichever is used for the position of the bars (depending on whether the barchart is vertical or horizontal \see getBarHeightColumn(), xColumn, yColumn */
|
||||
virtual void setBarPositionColumn(int column) =0;
|
||||
|
||||
/** \brief returns xColumn or yColumn, whichever is used for the position of the bars (depending on whether the barchart is vertical or horizontal \see getBarHeightColumn(), xColumn, yColumn */
|
||||
virtual void setBarPositionColumn(size_t column) =0;
|
||||
|
||||
/** \brief returns xColumn or yColumn, whichever is used for the height of the bars (depending on whether the barchart is vertical or horizontal \see getBarPositionColumn(), xColumn, yColumn */
|
||||
virtual void setBarHeightColumn(int column) =0;
|
||||
|
||||
/** \brief returns xColumn or yColumn, whichever is used for the height of the bars (depending on whether the barchart is vertical or horizontal \see getBarPositionColumn(), xColumn, yColumn */
|
||||
virtual void setBarHeightColumn(size_t column) =0;
|
||||
protected:
|
||||
/** \brief the width of the bargraphs, relative to the distance between the current and the next x-value
|
||||
*
|
||||
* See the following graphic to understand this concept:
|
||||
* \image html bargraph_basics.png
|
||||
*/
|
||||
double width;
|
||||
/** \brief the shift of the bargraphs, relative to the distance between the current and the next x-value
|
||||
*
|
||||
* See the following graphic to understand this concept:
|
||||
* \image html bargraph_basics.png
|
||||
*/
|
||||
double shift;
|
||||
|
||||
/** \brief baseline of the plot (NOTE: 0 is interpreted as until plot border in log-mode!!!)
|
||||
*/
|
||||
double baseline;
|
||||
|
||||
/** \brief this function is used by autoscaleBarWidthAndShift() to determine whether a given graph shall be taken into account when autoscaling.
|
||||
* Typically this returns \c true for all JKQTPBarGraphBase-derved objects with the same orientation (horizontal or vertical) */
|
||||
virtual bool considerForAutoscaling( JKQTPBarGraphBase* other) const=0;
|
||||
|
||||
/** \brief used to generate stacked plots: returns the upper boundary of the parent plot in a stack, for the index-th datapoint */
|
||||
virtual double getParentStackedMax(int index) const ;
|
||||
|
||||
/** \brief returns \c true, if a stack parent is set (if available) */
|
||||
virtual bool hasStackParent() const ;
|
||||
|
||||
/** \brief get the maximum and minimum value in the box-elongation (i.e. value) direction of the graph
|
||||
*
|
||||
* The result is given in the two parameters which are call-by-reference parameters!
|
||||
*/
|
||||
bool getValuesMinMax(double& mmin, double& mmax, double& smallestGreaterZero) ;
|
||||
/** \brief get the maximum and minimum value of the box positions of the graph
|
||||
*
|
||||
* The result is given in the two parameters which are call-by-reference parameters!
|
||||
*/
|
||||
bool getPositionsMinMax(double& mmin, double& mmax, double& smallestGreaterZero) ;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // jkqtpgraphsbarchartbase_H
|
BIN
screenshots/barchart_hor.png
Normal file
BIN
screenshots/barchart_hor.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
Loading…
Reference in New Issue
Block a user