JKQTPlotter: NEW: added new error indicator styles JKQTPErrorHalfBarsOutwards, JKQTPErrorHalfBarsInwards, JKQTPErrorHalfBarsAbove, JKQTPErrorHalfBarsBelow which are especially useful for barcharts

JKQTPlotter: added example for barcharts with errorbars
This commit is contained in:
jkriege2 2022-09-10 22:35:30 +02:00
parent 40748de442
commit 6cc08c2041
21 changed files with 418 additions and 64 deletions

View File

@ -40,9 +40,12 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
<tr><td> \image html barchart_small.png
<td> \subpage JKQTPlotterBarcharts
<td> `JKQTPBarVerticalGraph` <br> C-style arrays of data
<tr><td> \image html barchart_errorbars_small.png
<td> \subpage JKQTPlotterBarchartsErrorBars
<td> `JKQTPBarVerticalErrorGraph` <br> JKQTPDatastore::addColumnCalculatedFromColumn()
<tr><td> \image html barchart_twocolor_small.png
<td> \subpage JKQTPlotterBarchartsTwoColorFilling
<td> `JKQTPBarVerticalGraph` <br>
<td> `JKQTPBarVerticalGraph` <br> JKQTPDatastore::addColumnCalculatedFromColumn()
<tr><td> \image html stackedbars_small.png
<td> \subpage JKQTPlotterStackedBarChart
<td> `JKQTPBarVerticalStackableGraph`, `JKQTPBarHorizontalStackableGraph` <br> C++-style vectors of data
@ -52,6 +55,9 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
<tr><td> \image html wiggleplots_small.png
<td> \subpage JKQTPlotterWigglePlots
<td> `JKQTPFilledCurveXGraph`/`JKQTPFilledCurveYGraph` <br> setting/altering data in `JKQTPDatstore` directly <br> data-depentend coloring <br> random-walks <br> seismographic data
<tr><td> \image html filledgraphs_errors_small.png
<td> \subpage JKQTPlotterFilledGraphsErrorBars
<td> `JKQTPFilledCurveXErrorGraph`/`JKQTPFilledCurveYErrorGraph`
<tr><td> \image html impulsesplot_small.png
<td> \subpage JKQTPlotterImpulsePlots
<td> `JKQTPImpulsesVerticalGraph` and `JKQTPImpulsesHorizontalGraph` <br> C++-style QVector as plot data

View File

@ -48,6 +48,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>NEW: added property drawLineInForeground to JKQTPXYLineGraph and JKQTPXYParametrizedScatterGraph</li>
<li>NEW: added JKQTPXYGraph::setKeyColumn()/JKQTPXYGraph::getKeyColumn() and JKQTPXYGraph::setValueColumn()/JKQTPXYGraph::getValueColumn() and corresponding functions in other classes. In most graph classes they point to xColumn for key and yColumn for values. These functions are virtual and overwritten in derived classes with horizontally oriented graphs, where they point to yColumn for key and yColumn for value. This way you can write generic code with classes for both orientations.</li>
<li>NEW: barcharts (derived from JKQTPBarGraphBase) can be configured to use different fill styles above and below the baseline, see JKQTPBarGraphBase::FillMode </li>
<li>NEW: added new error indicator styles JKQTPErrorHalfBarsOutwards, JKQTPErrorHalfBarsInwards, JKQTPErrorHalfBarsAbove, JKQTPErrorHalfBarsBelow which are especially useful for barcharts</li>
</ul></li>
<li>JKQTMathText:<ul>

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

View File

@ -48,6 +48,7 @@ add_subdirectory(jkqtplot_test)
add_subdirectory(advplotstyling)
add_subdirectory(barchart)
add_subdirectory(boxplot)
add_subdirectory(barchart_errorbars)
add_subdirectory(barchart_twocolor)
add_subdirectory(contourplot)
add_subdirectory(datastore)
@ -61,6 +62,7 @@ add_subdirectory(distributionplot)
add_subdirectory(errorbarstyles)
add_subdirectory(evalcurve)
add_subdirectory(filledgraphs)
add_subdirectory(filledgraphs_errors)
add_subdirectory(functionplot)
add_subdirectory(geo_arrows)
add_subdirectory(geo_simple)

View File

@ -0,0 +1,34 @@
cmake_minimum_required(VERSION 3.16)
set(EXAMPLE_NAME barchart_errorbars)
set(EXENAME jkqtptest_${EXAMPLE_NAME})
message( STATUS ".. Building Example ${EXAMPLE_NAME}" )
# Set up source files
set(SOURCES barchart_errorbars.cpp )
set(HEADERS )
set(RESOURCES )
set(UIS )
add_executable(${EXENAME} WIN32 ${SOURCES} ${HEADERS} ${RESOURCES} ${UIS})
target_link_libraries(${EXENAME} JKQTPExampleToolsLib)
target_include_directories(${EXENAME} PRIVATE ../../lib)
if(JKQtPlotter_BUILD_STATIC_LIBS)
target_link_libraries(${EXENAME} JKQTPlotterLib)
elseif(JKQtPlotter_BUILD_SHARED_LIBS)
target_link_libraries(${EXENAME} JKQTPlotterSharedLib)
endif()
# precomiled headers to speed up compilation
if (JKQtPlotter_BUILD_WITH_PRECOMPILED_HEADERS)
target_precompile_headers(${EXENAME} REUSE_FROM jkqtptest_simpletest)
endif (JKQtPlotter_BUILD_WITH_PRECOMPILED_HEADERS)
# Installation
install(TARGETS ${EXENAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
#Installation of Qt DLLs on Windows
jkqtplotter_deployqt(${EXENAME})

View File

@ -0,0 +1,62 @@
# Example (JKQTPlotter): Barchart With Error Bars {#JKQTPlotterBarchartsErrorBars}
This project (see [`barchart_errorbars`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/barchart_errorbars) shows how to draw barcharts with different styles of error indicators.
The source code of the main application is (see [`barchart_errorbars.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/barchart_errorbars/barchart_errorbars.cpp):
```.cpp
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
JKQTPDatastore* ds=plot.getDatastore();
// 2. now we create three columns for key and value
size_t columnK=ds->addLinearColumn(6, 0.4*JKQTPSTATISTICS_PI, 2.2*JKQTPSTATISTICS_PI,"k");
size_t columnV=ds->addColumnCalculatedFromColumn(columnK, &cos, "v");
size_t columnE=ds->addColumnCalculatedFromColumn(columnK, [](double x) { return 0.05+0.06*(1.0+sin(x)); }, "error");
// 3. create a graph in the plot, which plots the dataset with symmetric:
JKQTPBarVerticalErrorGraph* graph1=new JKQTPBarVerticalErrorGraph(&plot);
graph1->setKeyColumn(columnK);
graph1->setValueColumn(columnV);
graph1->setBarErrorColumn(columnE);
// set error indicator style
graph1->setBarErrorStyle(JKQTPErrorBars);
graph1->setTitle(QObject::tr("JKQTPErrorBars"));
plot.addGraph(graph1);
// 4. create a second graph in the plot, which plots the second dataset with outer error bars only:
JKQTPBarVerticalErrorGraph* graph2=new JKQTPBarVerticalErrorGraph(&plot);
graph2->setKeyColumn(columnK);
graph2->setValueColumn(columnV);
graph2->setBarErrorColumn(columnE);
// set error indicator style
graph2->setBarErrorStyle(JKQTPErrorHalfBarsOutwards);
graph2->setTitle(QObject::tr("JKQTPErrorHalfBarsOutwards"));
plot.addGraph(graph2);
// 5. now we set the graphs, so they are plotted side-by-side
// This function searches all JKQTPBarHorizontalGraph in the current
// plot and sets their shift/scale so they form a nice plot with
// side-by-side groups
graph1->autoscaleBarWidthAndShift(0.9, 0.9);
// 6 autoscale the plot so the graph is contained
plot.zoomToFit();
// 7. show plotter and make it a decent size
plot.getPlotter()->setKeyPosition(JKQTPKeyInsideTopLeft);
plot.setWindowTitle(title);
plot.show();
plot.resize(400,400);
```
The result looks like this:
![barchart_errorbars](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/barchart_errorbars.png)
In order to draw horizontal error bars, you have to use `JKQTPBarHorizontalErrorGraph` instead of `JKQTPBarVerticalErrorGraph`:
![barchart_errorbars_hor](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/barchart_errorbars_hor.png)

View File

@ -0,0 +1,77 @@
/** \example barchart_errorbars.cpp
* Shows how to draw Barcharts with errorbars in a JKQTPlotter
*
* \ref JKQTPlotterBarchartsErrorBars
*/
#include "jkqtpexampleapplication.h"
#include <QApplication>
#include "jkqtplotter/jkqtplotter.h"
#include "jkqtplotter/graphs/jkqtpscatter.h"
#include "jkqtplotter/graphs/jkqtpbarchart.h"
#include "jkqtpexampleapplication.h"
#include "jkqtcommon/jkqtpmathtools.h"
template <class TCHART>
void doExample(JKQTPlotter& plot, const QString& title)
{
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
JKQTPDatastore* ds=plot.getDatastore();
// 2. now we create three columns for key and value
size_t columnK=ds->addLinearColumn(6, 0.4*JKQTPSTATISTICS_PI, 2.2*JKQTPSTATISTICS_PI,"k");
size_t columnV=ds->addColumnCalculatedFromColumn(columnK, &cos, "v");
size_t columnE=ds->addColumnCalculatedFromColumn(columnK, [](double x) { return 0.05+0.06*(1.0+sin(x)); }, "error");
// 3. create a graph in the plot, which plots the dataset with symmetric:
TCHART* graph1=new TCHART(&plot);
graph1->setKeyColumn(columnK);
graph1->setValueColumn(columnV);
graph1->setBarErrorColumn(columnE);
// set error indicator style
graph1->setBarErrorStyle(JKQTPErrorBars);
graph1->setTitle(QObject::tr("JKQTPErrorBars"));
plot.addGraph(graph1);
// 4. create a second graph in the plot, which plots the second dataset with outer error bars only:
TCHART* graph2=new TCHART(&plot);
graph2->setKeyColumn(columnK);
graph2->setValueColumn(columnV);
graph2->setBarErrorColumn(columnE);
// set error indicator style
graph2->setBarErrorStyle(JKQTPErrorHalfBarsOutwards);
graph2->setTitle(QObject::tr("JKQTPErrorHalfBarsOutwards"));
plot.addGraph(graph2);
// 5. now we set the graphs, so they are plotted side-by-side
// This function searches all JKQTPBarHorizontalGraph in the current
// plot and sets their shift/scale so they form a nice plot with
// side-by-side groups
graph1->autoscaleBarWidthAndShift(0.9, 0.9);
// 6 autoscale the plot so the graph is contained
plot.zoomToFit();
// 7. show plotter and make it a decent size
plot.getPlotter()->setKeyPosition(JKQTPKeyInsideTopLeft);
plot.setWindowTitle(title);
plot.show();
plot.resize(400,400);
}
int main(int argc, char* argv[])
{
JKQTPAppSettingController highDPIController(argc,argv);
JKQTPExampleApplication app(argc, argv);
JKQTPlotter plotV, plotH;
doExample<JKQTPBarVerticalErrorGraph>(plotV, "1: JKQTPBarVerticalErrorGraph");
doExample<JKQTPBarHorizontalErrorGraph>(plotH, "2: JKQTPBarHorizontalErrorGraph");
return app.exec();
}

View File

@ -363,12 +363,51 @@ bool JKQTPBarHorizontalErrorGraph::usesColumn(int c) const
bool JKQTPBarHorizontalErrorGraph::getXMinMax(double &minx, double &maxx, double &smallestGreaterZero)
{
if (xErrorColumn<0 || xErrorStyle==JKQTPNoError) {
return JKQTPBarHorizontalGraph::getXMinMax(minx, maxx, smallestGreaterZero);
} else {
bool start=false;
minx=0;
maxx=0;
smallestGreaterZero=0;
if (getBaseline()>0) {
smallestGreaterZero=getBaseline();
minx=getBaseline();
maxx=getBaseline();
}
if (parent==nullptr) return false;
JKQTPDatastore* datastore=parent->getDatastore();
int imax=0;
int imin=0;
if (getIndexRange(imin, imax)) {
for (int i=imin; i<imax; i++) {
double yv=getBaseline();
if (JKQTPIsOKFloat(yv)) {
if (yv>maxx) maxx=yv;
if (yv<minx) minx=yv;
double xvsgz;
xvsgz=yv; SmallestGreaterZeroCompare_xvsgz();
}
yv=datastore->get(static_cast<size_t>(xColumn),static_cast<size_t>(i));
if (JKQTPIsOKFloat(yv)) {
if (yv>maxx) maxx=yv;
if (yv<minx) minx=yv;
double xvsgz;
xvsgz=yv; SmallestGreaterZeroCompare_xvsgz();
}
}
return true;
}
} else {
bool start=false;
minx=getBaseline();
maxx=getBaseline();
smallestGreaterZero=0;
if (getBaseline()>0) {
smallestGreaterZero=getBaseline();
minx=getBaseline();
maxx=getBaseline();
}
if (parent==nullptr) return false;
@ -377,25 +416,25 @@ bool JKQTPBarHorizontalErrorGraph::getXMinMax(double &minx, double &maxx, double
int imin=0;
if (getIndexRange(imin, imax)) {
for (int i=imin; i<imax; i++) {
double xvsgz;
const double xv=datastore->get(static_cast<size_t>(xColumn),static_cast<size_t>(i))+getXErrorU(i, datastore);
const 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 (xvv>maxx) maxx=xvv;
if (xvv<minx) minx=xvv;
xvsgz=xvv; SmallestGreaterZeroCompare_xvsgz();
const double yv=datastore->get(static_cast<size_t>(xColumn),static_cast<size_t>(i))+getXErrorU(i, datastore);
const double yvv=datastore->get(static_cast<size_t>(xColumn),static_cast<size_t>(i))-getXErrorL(i, datastore);
if (JKQTPIsOKFloat(yv) && JKQTPIsOKFloat(yvv) ) {
if (start || yv>maxx) maxx=yv;
if (start || yv<minx) minx=yv;
double xvsgz;
xvsgz=yv; SmallestGreaterZeroCompare_xvsgz();
if (start || yvv>maxx) maxx=yvv;
if (start || yvv<minx) minx=yvv;
xvsgz=yvv; SmallestGreaterZeroCompare_xvsgz();
start=false;
}
}
return !start;
}
return false;
}
return false;
}
void JKQTPBarHorizontalErrorGraph::drawErrorsAfter(JKQTPEnhancedPainter &painter)
@ -416,6 +455,26 @@ int JKQTPBarHorizontalErrorGraph::getBarLowerErrorColumn() const
return getXErrorColumnLower();
}
JKQTPErrorPlotstyle JKQTPBarHorizontalErrorGraph::getBarErrorStyle() const
{
return getXErrorStyle();
}
bool JKQTPBarHorizontalErrorGraph::getBarErrorSymmetric() const
{
return getXErrorSymmetric();
}
void JKQTPBarHorizontalErrorGraph::setBarErrorSymmetric(bool __value)
{
setXErrorSymmetric(__value);
}
void JKQTPBarHorizontalErrorGraph::setBarErrorStyle(JKQTPErrorPlotstyle __value)
{
setXErrorStyle(__value);
}
void JKQTPBarHorizontalErrorGraph::setBarErrorColumn(int column)
{
setXErrorColumn(column);
@ -542,6 +601,26 @@ int JKQTPBarVerticalErrorGraph::getBarLowerErrorColumn() const
return getYErrorColumnLower();
}
JKQTPErrorPlotstyle JKQTPBarVerticalErrorGraph::getBarErrorStyle() const
{
return getYErrorStyle();
}
bool JKQTPBarVerticalErrorGraph::getBarErrorSymmetric() const
{
return getYErrorSymmetric();
}
void JKQTPBarVerticalErrorGraph::setBarErrorSymmetric(bool __value)
{
setYErrorSymmetric(__value);
}
void JKQTPBarVerticalErrorGraph::setBarErrorStyle(JKQTPErrorPlotstyle __value)
{
setYErrorStyle(__value);
}
void JKQTPBarVerticalErrorGraph::setBarErrorColumn(int column)
{
setYErrorColumn(column);

View File

@ -117,7 +117,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBarVerticalGraph: public JKQTPBarGraphBase {
* \ingroup jkqtplotter_barssticks
*
* This works much the same as JKQTPBarHorizontalGraph. Here is an example output:
* \image html plot_bargraphverploterr.png
* \image html JKQTPBarVerticalErrorGraph.png
*
* \see jkqtpstatAddYErrorBarGraph(), JKQTPBarVerticalGraph, \ref JKQTPlotterBarcharts
*/
@ -141,7 +141,16 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBarVerticalErrorGraph: public JKQTPBarVertical
int getBarErrorColumn() const;
/** \brief returns the column that contains the lower bar height errors */
int getBarLowerErrorColumn() const;
/** \brief returns the error style of the bar */
JKQTPErrorPlotstyle getBarErrorStyle() const;
/** \brief returns whether the errors of the bars are symmetric */
bool getBarErrorSymmetric() const;
public slots:
/** \brief sets whether the errors of the bars are symmetric */
void setBarErrorSymmetric(bool __value);
/** \brief sets the error style of the bar */
void setBarErrorStyle(JKQTPErrorPlotstyle __value);
/** \brief sets the column that contains the bar height errors */
void setBarErrorColumn(int column) ;
@ -238,7 +247,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBarHorizontalGraph: public JKQTPBarGraphBase {
* \ingroup jkqtplotter_barssticks
*
* This works much the same as JKQTPBarHorizontalGraph. Here is an example output:
* \image html plot_bargraphhorploterr.png
* \image html JKQTPBarHorizontalErrorGraph.png
*
* \see jkqtpstatAddXErrorBarGraph(), JKQTPBarHorizontalGraph, \ref JKQTPlotterBarcharts
*
@ -264,7 +273,16 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBarHorizontalErrorGraph: public JKQTPBarHorizo
int getBarErrorColumn() const;
/** \brief returns the column that contains the lower bar height errors */
int getBarLowerErrorColumn() const;
/** \brief returns the error style of the bar */
JKQTPErrorPlotstyle getBarErrorStyle() const;
/** \brief returns whether the errors of the bars are symmetric */
bool getBarErrorSymmetric() const;
public slots:
/** \brief sets whether the errors of the bars are symmetric */
void setBarErrorSymmetric(bool __value);
/** \brief sets the error style of the bar */
void setBarErrorStyle(JKQTPErrorPlotstyle __value);
/** \brief sets the column that contains the bar height errors */
void setBarErrorColumn(int column) ;

View File

@ -393,8 +393,10 @@ void JKQTPGraphErrorStyleMixin::intPlotXYErrorIndicators(JKQTPEnhancedPainter& p
//x-errorbars
if ((xErrorColumn>=0 || xErrorColumnLower>=0) && (xErrorStyle==JKQTPErrorBars || xErrorStyle==JKQTPErrorBarsLines|| xErrorStyle==JKQTPErrorBarsPolygons
|| xErrorStyle==JKQTPErrorSimpleBars || xErrorStyle==JKQTPErrorSimpleBarsLines|| xErrorStyle==JKQTPErrorSimpleBarsPolygons)) {
if ((xErrorColumn>=0 || xErrorColumnLower>=0)
&& (xErrorStyle==JKQTPErrorBars || xErrorStyle==JKQTPErrorBarsLines|| xErrorStyle==JKQTPErrorBarsPolygons
|| xErrorStyle==JKQTPErrorSimpleBars || xErrorStyle==JKQTPErrorSimpleBarsLines|| xErrorStyle==JKQTPErrorSimpleBarsPolygons))
{
double x0=parentGraph->transformX(xv+xrelshift*deltax-xl); bool x0ok=JKQTPIsOKFloat(x0);
double x1=parentGraph->transformX(xv+xrelshift*deltax+xe); bool x1ok=JKQTPIsOKFloat(x1);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
@ -427,10 +429,79 @@ void JKQTPGraphErrorStyleMixin::intPlotXYErrorIndicators(JKQTPEnhancedPainter& p
l=JKQTPClipLine(l, cliprect);
if (l.length()>0) painter.drawLine(l);
}
}
// y-errorbars
if ((yErrorColumn>=0 || yErrorColumnLower>=0)
&& (yErrorStyle==JKQTPErrorBars || yErrorStyle==JKQTPErrorBarsLines || yErrorStyle==JKQTPErrorBarsPolygons
|| yErrorStyle==JKQTPErrorSimpleBars || yErrorStyle==JKQTPErrorSimpleBarsLines || yErrorStyle==JKQTPErrorSimpleBarsPolygons))
{
double y0=parentGraph->transformY(yv+yrelshift*deltay-yl); bool y0ok=JKQTPIsOKFloat(y0);
double y1=parentGraph->transformY(yv+yrelshift*deltay+ye); bool y1ok=JKQTPIsOKFloat(y1);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
QPen pp=p;
if (!defaultErrorColor) pp.setColor(terrCol);
painter.setPen(pp);
QList<QLineF> elines;
if (y0ok&&y1ok&&xok&&yok) {
elines<<QLineF(x, y0, x, y1);
if (yErrorStyle==JKQTPErrorBars || yErrorStyle==JKQTPErrorBarsLines || yErrorStyle==JKQTPErrorBarsPolygons) {
if (plotlowerbary) elines<<QLineF(x-ebs_px/2.0,y0,x+ebs_px/2.0,y0);
if (plotupperbary) elines<<QLineF(x-ebs_px/2.0,y1,x+ebs_px/2.0,y1);
}
} else if (y0ok&&!y1ok&&xok&&yok) { // upper errorbar OK, lower errorbar NAN
elines<<QLineF(x, y0, x, y);
if (yErrorStyle==JKQTPErrorBars || yErrorStyle==JKQTPErrorBarsLines || yErrorStyle==JKQTPErrorBarsPolygons) {
if (plotlowerbary) elines<<QLineF(x-ebs_px/2.0,y0,x+ebs_px/2.0,y0);
}
if (y0<y) elines<<QLineF(x,y,x,parentGraph->transformY(parent->getYMin()));
else elines<<QLineF(x,y,x,parentGraph->transformY(parent->getYMax())); // inverted axis!
} else if (!y0ok&&y1ok&&xok&&yok) {
elines<<QLineF(x, y1, x, y);
if (yErrorStyle==JKQTPErrorBars || yErrorStyle==JKQTPErrorBarsLines || yErrorStyle==JKQTPErrorBarsPolygons) {
if (plotupperbary) elines<<QLineF(x-ebs_px/2.0,y1,x+ebs_px/2.0,y1);
}
if (y1<y) elines<<QLineF(x,y,x,parentGraph->transformY(parent->getYMax()));
else elines<<QLineF(x,y,x,parentGraph->transformY(parent->getYMin()));
}
// y-errorbars
if ((yErrorColumn>=0 || yErrorColumnLower>=0) && (yErrorStyle==JKQTPErrorBars || yErrorStyle==JKQTPErrorBarsLines || yErrorStyle==JKQTPErrorBarsPolygons
|| yErrorStyle==JKQTPErrorSimpleBars || yErrorStyle==JKQTPErrorSimpleBarsLines || yErrorStyle==JKQTPErrorSimpleBarsPolygons)) {
for (QLineF& l: elines) {
l=JKQTPClipLine(l, cliprect);
if (l.length()>0) painter.drawLine(l);
}
}
// half errorbars
if ((xErrorColumn>=0) && (xErrorStyle==JKQTPErrorHalfBarsAbove|| xErrorStyle==JKQTPErrorHalfBarsInwards|| xErrorStyle==JKQTPErrorHalfBarsBelow|| xErrorStyle==JKQTPErrorHalfBarsOutwards))
{
double x0=parentGraph->transformX(xv+xrelshift*deltax-xl); bool x0ok=JKQTPIsOKFloat(x0);
double x1=parentGraph->transformX(xv+xrelshift*deltax+xe); bool x1ok=JKQTPIsOKFloat(x1);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
QPen pp=p;
if (!defaultErrorColor) pp.setColor(terrCol);
painter.setPen(pp);
QList<QLineF> elines;
if ( (xErrorStyle==JKQTPErrorHalfBarsAbove
|| (xErrorStyle==JKQTPErrorHalfBarsOutwards && xv>0.0)
|| (xErrorStyle==JKQTPErrorHalfBarsInwards && xv<0.0))
&&x1ok&&xok&&yok) {
elines<<QLineF(x, y, x1, y);
elines<<QLineF(x1,y-ebs_px/2.0,x1,y+ebs_px/2.0);
} else if ((xErrorStyle==JKQTPErrorHalfBarsBelow
|| (xErrorStyle==JKQTPErrorHalfBarsOutwards && xv<=0.0)
|| (xErrorStyle==JKQTPErrorHalfBarsInwards && xv>=0.0))
&&x0ok&&xok&&yok) {
elines<<QLineF(x0, y, x, y);
elines<<QLineF(x0,y-ebs_px/2.0,x0,y+ebs_px/2.0);
}
for (QLineF& l: elines) {
l=JKQTPClipLine(l, cliprect);
if (l.length()>0) painter.drawLine(l);
}
}
// half errorbars
if ((yErrorColumn>=0) && (yErrorStyle==JKQTPErrorHalfBarsAbove|| yErrorStyle==JKQTPErrorHalfBarsInwards|| yErrorStyle==JKQTPErrorHalfBarsBelow|| yErrorStyle==JKQTPErrorHalfBarsOutwards))
{
double y0=parentGraph->transformY(yv+yrelshift*deltay-yl); bool y0ok=JKQTPIsOKFloat(y0);
double y1=parentGraph->transformY(yv+yrelshift*deltay+ye); bool y1ok=JKQTPIsOKFloat(y1);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
@ -438,56 +509,48 @@ void JKQTPGraphErrorStyleMixin::intPlotXYErrorIndicators(JKQTPEnhancedPainter& p
if (!defaultErrorColor) pp.setColor(terrCol);
painter.setPen(pp);
QList<QLineF> elines;
if (y0ok&&y1ok&&xok&&yok) {
elines<<QLineF(x, y0, x, y1);
if (yErrorStyle==JKQTPErrorBars || yErrorStyle==JKQTPErrorBarsLines || yErrorStyle==JKQTPErrorBarsPolygons) {
if (plotlowerbary) elines<<QLineF(x-ebs_px/2.0,y0,x+ebs_px/2.0,y0);
if (plotupperbary) elines<<QLineF(x-ebs_px/2.0,y1,x+ebs_px/2.0,y1);
}
} else if (y0ok&&!y1ok&&xok&&yok) { // upper errorbar OK, lower errorbar NAN
if ( (yErrorStyle==JKQTPErrorHalfBarsAbove
|| (yErrorStyle==JKQTPErrorHalfBarsOutwards && yv>0.0)
|| (yErrorStyle==JKQTPErrorHalfBarsInwards && yv<0.0))
&&yok&&y1ok&&xok) {
elines<<QLineF(x, y, x, y1);
elines<<QLineF(x-ebs_px/2.0,y1,x+ebs_px/2.0,y1);
} else if ((yErrorStyle==JKQTPErrorHalfBarsBelow
|| (yErrorStyle==JKQTPErrorHalfBarsOutwards && yv<=0.0)
|| (yErrorStyle==JKQTPErrorHalfBarsInwards && yv>=0.0))
&&y0ok&&yok&&xok) {
elines<<QLineF(x, y0, x, y);
if (yErrorStyle==JKQTPErrorBars || yErrorStyle==JKQTPErrorBarsLines || yErrorStyle==JKQTPErrorBarsPolygons) {
if (plotlowerbary) elines<<QLineF(x-ebs_px/2.0,y0,x+ebs_px/2.0,y0);
}
if (y0<y) elines<<QLineF(x,y,x,parentGraph->transformY(parent->getYMin()));
else elines<<QLineF(x,y,x,parentGraph->transformY(parent->getYMax())); // inverted axis!
} else if (!y0ok&&y1ok&&xok&&yok) {
elines<<QLineF(x, y1, x, y);
if (yErrorStyle==JKQTPErrorBars || yErrorStyle==JKQTPErrorBarsLines || yErrorStyle==JKQTPErrorBarsPolygons) {
if (plotupperbary) elines<<QLineF(x-ebs_px/2.0,y1,x+ebs_px/2.0,y1);
}
if (y1<y) elines<<QLineF(x,y,x,parentGraph->transformY(parent->getYMax()));
else elines<<QLineF(x,y,x,parentGraph->transformY(parent->getYMin()));
elines<<QLineF(x-ebs_px/2.0,y0,x+ebs_px/2.0,y0);
}
for (QLineF& l: elines) {
l=JKQTPClipLine(l, cliprect);
if (l.length()>0) painter.drawLine(l);
}
}
// error boxes
if (yErrorStyle==JKQTPErrorBoxes || xErrorStyle==JKQTPErrorBoxes || yErrorStyle==JKQTPErrorEllipses || xErrorStyle==JKQTPErrorEllipses ) {
double y0=parentGraph->transformY(yv+yrelshift*deltay-yl); bool y0ok=JKQTPIsOKFloat(y0);
double y1=parentGraph->transformY(yv+yrelshift*deltay+ye); bool y1ok=JKQTPIsOKFloat(y1);
double x0=parentGraph->transformX(xv+xrelshift*deltax-xl); bool x0ok=JKQTPIsOKFloat(x0);
double x1=parentGraph->transformX(xv+xrelshift*deltax+xe); bool x1ok=JKQTPIsOKFloat(x1);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
QPen pp=p;
if (!defaultErrorColor) pp.setColor(terrCol);
painter.setPen(pp);
QBrush bb=b;
if (!defaultErrorColor) bb.setColor(terrFillCol);
painter.setBrush(bb);
const QRectF errRect=QRectF(QPointF(x0,y0), QPointF(x1,y1));
if (((y0ok&&y1ok)||(x0ok&&x1ok))&&cliprect.intersects(errRect)) {
if (yErrorStyle==JKQTPErrorEllipses || xErrorStyle==JKQTPErrorEllipses) painter.drawEllipse(errRect);
else painter.drawRect(errRect);
}
// error boxes
if (yErrorStyle==JKQTPErrorBoxes || xErrorStyle==JKQTPErrorBoxes || yErrorStyle==JKQTPErrorEllipses || xErrorStyle==JKQTPErrorEllipses ) {
double y0=parentGraph->transformY(yv+yrelshift*deltay-yl); bool y0ok=JKQTPIsOKFloat(y0);
double y1=parentGraph->transformY(yv+yrelshift*deltay+ye); bool y1ok=JKQTPIsOKFloat(y1);
double x0=parentGraph->transformX(xv+xrelshift*deltax-xl); bool x0ok=JKQTPIsOKFloat(x0);
double x1=parentGraph->transformX(xv+xrelshift*deltax+xe); bool x1ok=JKQTPIsOKFloat(x1);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
QPen pp=p;
if (!defaultErrorColor) pp.setColor(terrCol);
painter.setPen(pp);
QBrush bb=b;
if (!defaultErrorColor) bb.setColor(terrFillCol);
painter.setBrush(bb);
const QRectF errRect=QRectF(QPointF(x0,y0), QPointF(x1,y1));
if (((y0ok&&y1ok)||(x0ok&&x1ok))&&cliprect.intersects(errRect)) {
if (yErrorStyle==JKQTPErrorEllipses || xErrorStyle==JKQTPErrorEllipses) painter.drawEllipse(errRect);
else painter.drawRect(errRect);
}
} //}
}
// x-errorlines
if (pastFirst && (xErrorStyle==JKQTPErrorLines || xErrorStyle==JKQTPErrorBarsLines || xErrorStyle==JKQTPErrorSimpleBarsLines)) {
double xl1m=xmold;

View File

@ -197,6 +197,10 @@ QString JKQTPErrorPlotstyle2String(JKQTPErrorPlotstyle pos) {
case JKQTPErrorEllipses: return "error_ell";
case JKQTPErrorLines: return "error_lines";
case JKQTPErrorBars: return "error_bars";
case JKQTPErrorHalfBarsAbove: return "error_bars_half_above";
case JKQTPErrorHalfBarsBelow: return "error_bars_half_below";
case JKQTPErrorHalfBarsInwards: return "error_bars_half_inwards";
case JKQTPErrorHalfBarsOutwards: return "error_bars_half_outwards";
case JKQTPErrorSimpleBars: return "error_simplebars";
case JKQTPErrorPolygons: return "error_polygons";
case JKQTPErrorBarsLines: return "error_bars_lines";
@ -220,6 +224,10 @@ JKQTPErrorPlotstyle String2JKQTPErrorPlotstyle(const QString& pos) {
if (s=="error_bars_polygons") return JKQTPErrorBarsPolygons;
if (s=="error_simplebars_lines") return JKQTPErrorSimpleBarsLines;
if (s=="error_simplebars_polygons") return JKQTPErrorSimpleBarsPolygons;
if (s=="error_bars_half_above") return JKQTPErrorHalfBarsAbove;
if (s=="error_bars_half_below") return JKQTPErrorHalfBarsBelow;
if (s=="error_bars_half_inwards") return JKQTPErrorHalfBarsInwards;
if (s=="error_bars_half_outwards") return JKQTPErrorHalfBarsOutwards;
return JKQTPNoError;
}

View File

@ -582,6 +582,10 @@ enum JKQTPErrorPlotstyle {
JKQTPErrorSimpleBars=6, /*!< \brief simplified error bars for each data point \image html JKQTPErrorSimpleBars.png */
JKQTPErrorLines=5, /*!< \brief a second and third graph line above and below the actual data which indicates the error value \image html JKQTPErrorLines.png */
JKQTPErrorBars=4, /*!< \brief error bars for each data point \image html JKQTPErrorBars.png */
JKQTPErrorHalfBarsOutwards=11, /*!< \brief half error bars for each data point, pointing outwards \image html JKQTPErrorHalfBarsOutwards.png */
JKQTPErrorHalfBarsInwards=12, /*!< \brief half error bars for each data point, pointing inwards \image html JKQTPErrorHalfBarsInwards.png */
JKQTPErrorHalfBarsAbove=13, /*!< \brief half error bars for each data point, pointing up \image html JKQTPErrorHalfBarsAbove.png */
JKQTPErrorHalfBarsBelow=14, /*!< \brief half error bars for each data point, pointing down \image html JKQTPErrorHalfBarsBelow.png */
JKQTPErrorPolygons=3, /*!< \brief line error lines, but with filled range in between \image html JKQTPErrorPolygons.png */
JKQTPErrorBarsLines=2, /*!< \brief error bars and lines for each data point \image html JKQTPErrorBarsLines.png */
JKQTPErrorBarsPolygons=1, /*!< \brief error bars and polygons for each data point \image html JKQTPErrorBarsPolygons.png */

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB