- added stackable barcharts, incl. simple test program

- organized barcharts into hor/ver that can in addition EITHER be stackable, or with error indicators
- reorganized  graphs (split jkqtpelements.h/.cpp into several files)
This commit is contained in:
jkriege2 2018-11-25 14:53:26 +01:00
parent b10406a134
commit d1fdd1f56e
49 changed files with 6852 additions and 5457 deletions

120
README.md
View File

@ -157,12 +157,13 @@ The result looks like this:
![jkqtplotter_simpletest_symbols_and_errors](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_symbols_and_errors.png)
###Simple barchart
This project (see `./test/jkqtplotter_simpletest_barchart/`) simply creates a JKQtPlotter widget (as a new window) and adds a single line-graph (a sine-wave) that has y-errorbars. In addition, this example shows how to change some of the axis properties and how to use LaTeX markup to format axis labels (can actually be used for all labels in JKQtPlotter). Also, in comparison to the last example, here we initialize the data from C-type arrays (double*), instead of QVector<double> objects.
This project (see `./test/jkqtplotter_simpletest_barchart/`) simply creates a JKQtPlotter widget (as a new window) and adds several barcharts. They are ordered in groups.
The soruce code of the main application is (see `./test/jkqtplotter_simpletest_barchart/jkqtplotter_simpletest_barchart.cpp`):
```c++
#include <QApplication>
#include "jkqtplotter.h"
#include "jkqtpbarchartelements.h"
#define Ndata 5
int main(int argc, char* argv[])
@ -194,15 +195,15 @@ 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:
JKQTPbarHorizontalGraph* graph1=new JKQTPbarHorizontalGraph(&plot);
JKQTPbarVerticalGraph* graph1=new JKQTPbarVerticalGraph(&plot);
graph1->set_xColumn(columnX);
graph1->set_yColumn(columnY1);
graph1->set_title(QObject::tr("dataset 1"));
JKQTPbarHorizontalGraph* graph2=new JKQTPbarHorizontalGraph(&plot);
JKQTPbarVerticalGraph* graph2=new JKQTPbarVerticalGraph(&plot);
graph2->set_xColumn(columnX);
graph2->set_yColumn(columnY2);
graph2->set_title(QObject::tr("dataset 2"));
JKQTPbarHorizontalGraph* graph3=new JKQTPbarHorizontalGraph(&plot);
JKQTPbarVerticalGraph* graph3=new JKQTPbarVerticalGraph(&plot);
graph3->set_xColumn(columnX);
graph3->set_yColumn(columnY3);
graph3->set_title(QObject::tr("dataset 3"));
@ -214,7 +215,7 @@ int main(int argc, char* argv[])
plot.addGraph(graph3);
// 6. now we set the graphs, so they are plotted side-by-side
// This function searches all JKQTPbarHorizontalGraph in the current
// This function searches all JKQTPbarVerticalGraph in the current
// plot and sets their shift/scale so they form a nice plot with
// side-by-side groups
graph1->autoscaleBarWidthAndShift(0.75, 1);
@ -250,6 +251,115 @@ The result looks like this:
![jkqtplotter_simpletest_barchart](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_barchart.png)
###Simple stacked barchart
This project (see `./test/jkqtplotter_simpletest_stackedbars/`) simply creates a JKQtPlotter widget (as a new window) and adds several stacked barcharts.
The soruce code of the main application is (see `./test/jkqtplotter_simpletest_stackedbars/jkqtplotter_simpletest_stackedbars.cpp`):
```c++
#include <QApplication>
#include "jkqtplotter.h"
#include "jkqtpbarchartelements.h"
#define Ndata 5
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
JKQtPlotter plot;
plot.get_plotter()->set_useAntiAliasingForGraphs(true); // nicer (but slower) plotting
plot.get_plotter()->set_useAntiAliasingForSystem(true); // nicer (but slower) plotting
plot.get_plotter()->set_useAntiAliasingForText(true); // nicer (but slower) text rendering
JKQTPdatastore* ds=plot.getDatastore();
// 2. now we create data for the charts (taken from https://commons.wikimedia.org/wiki/File:Energiemix_Deutschland.svg)
QVector<double> year, percentage_other, percentage_coaloil, percentage_gas, percentage_nuclear, percentage_green;
year << 1990 << 1995 << 2000 << 2005 << 2010 << 2015;
percentage_other << 3.5 << 3.5 << 4.4 << 4.4 << 5 << 5 ;
percentage_coaloil << 58.7 << 55.7 << 51.5 << 48.2 << 42.9 << 43.1;
percentage_gas << 6.5 << 7.7 << 8.5 << 11.7 << 14.1 << 9.6 ;
percentage_nuclear << 27.7 << 28.7 << 29.4 << 26.2 << 22.2 << 14.2;
percentage_green << 3.6 << 4.4 << 6.2 << 9.5 << 15.8 << 28.1;
// 3. make data available to JKQtPlotter by adding it to the internal datastore.
// Note: In this step the data is copied (of not specified otherwise)
// the variables cYear, cOther ... will contain the internal column ID of the
// newly created columns with names "year" and "other" ... and the (copied) data
size_t cYear=ds->addCopiedColumn(year, "year");
size_t cOther=ds->addCopiedColumn(percentage_other, "other");
size_t cCoalOil=ds->addCopiedColumn(percentage_coaloil, "coal & oil");
size_t cGas=ds->addCopiedColumn(percentage_gas, "natural gas");
size_t cNuclear=ds->addCopiedColumn(percentage_nuclear, "nuclear energy");
size_t cGreen=ds->addCopiedColumn(percentage_green, "green energy");
// 4. create graphs in the plot, which plots the dataset year/other, year/coal, ...
// The color of the graphs is set by calling set_fillColor_and_darkenedColor(), which sets the
// fillColor to the given color and makes the outline of the bars (i.e. their "color") a darker
// shade of the given color.
QVector<JKQTPbarVerticalStackableGraph*> graphs;
graphs.push_back(new JKQTPbarVerticalStackableGraph(&plot));
graphs.back()->set_xColumn(cYear);
graphs.back()->set_yColumn(cOther);
graphs.back()->set_title(QObject::tr("other sources"));
graphs.back()->set_fillColor_and_darkenedColor(QColor("red"));
graphs.push_back(new JKQTPbarVerticalStackableGraph(&plot));
graphs.back()->set_xColumn(cYear);
graphs.back()->set_yColumn(cCoalOil);
graphs.back()->set_title(QObject::tr("coal & oil"));
graphs.back()->set_fillColor_and_darkenedColor(QColor("darkgrey"));
graphs.back()->stackUpon(graphs[graphs.size()-2]);
graphs.push_back(new JKQTPbarVerticalStackableGraph(&plot));
graphs.back()->set_xColumn(cYear);
graphs.back()->set_yColumn(cGas);
graphs.back()->set_title(QObject::tr("natural gas"));
graphs.back()->set_fillColor_and_darkenedColor(QColor("blue"));
graphs.back()->stackUpon(graphs[graphs.size()-2]);
graphs.push_back(new JKQTPbarVerticalStackableGraph(&plot));
graphs.back()->set_xColumn(cYear);
graphs.back()->set_yColumn(cNuclear);
graphs.back()->set_title(QObject::tr("nuclear energy"));
graphs.back()->set_fillColor_and_darkenedColor(QColor("gold"));
graphs.back()->stackUpon(graphs[graphs.size()-2]);
graphs.push_back(new JKQTPbarVerticalStackableGraph(&plot));
graphs.back()->set_xColumn(cYear);
graphs.back()->set_yColumn(cGreen);
graphs.back()->set_title(QObject::tr("green energy"));
graphs.back()->set_fillColor_and_darkenedColor(QColor("darkgreen"));
graphs.back()->stackUpon(graphs[graphs.size()-2]);
// 5. add the graphs to the plot, so it is actually displayed
plot.addGraphs(graphs);
// 6. set axis labels
plot.get_xAxis()->set_axisLabel("year");
plot.get_yAxis()->set_axisLabel("fraction of energy production in Germany [%]");
// 7. 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.get_plotter().
plot.get_plotter()->set_keyPosition(JKQTPkeyOutsideTopRight);
plot.get_plotter()->set_keyLayout(JKQTPkeyLayoutOneRow);
// 8 autoscale the plot so the graph is contained
plot.zoomToFit();
// show plotter and make it a decent size
plot.show();
plot.resize(600,400);
return app.exec();
}
```
The result looks like this:
![JKQTPbarVerticalGraphStacked](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/doc/images/JKQTPbarVerticalGraphStacked.png)
![JKQTPbarHorizontalGraphStacked](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/doc/images/JKQTPbarHorizontalGraphStacked.png)
##Screenshots
###Scatter Plots and Boxplots
![Scatterplots](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/screen_scatter.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)
@ -356,6 +356,11 @@ bool JKQTmathText::MTtextNode::toHtml(QString &html, JKQTmathText::MTenvironment
return true;
}
QString JKQTmathText::MTtextNode::getTypeName() const
{
return QLatin1String("MTtextNode(")+text+")";
}
QString JKQTmathText::MTtextNode::textTransform(const QString &text, JKQTmathText::MTenvironment currentEv, bool /*forSize*/)
{
QString txt=text;
@ -446,6 +451,11 @@ JKQTmathText::MTinstruction1Node::~MTinstruction1Node() {
if (child!=nullptr) delete child;
}
QString JKQTmathText::MTinstruction1Node::getTypeName() const
{
return QLatin1String("MTinstruction1Node(")+name+")";
}
void JKQTmathText::MTinstruction1Node::getSizeInternal(QPainter& painter, JKQTmathText::MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos) {
JKQTmathText::MTenvironment ev=currentEv;
if (name=="bf" || name=="textbf" || name=="mathbf") ev.bold=true;
@ -602,6 +612,16 @@ double JKQTmathText::MTsubscriptNode::draw(QPainter& painter, double x, double y
return child->draw(painter, xx, y+shift, ev);//+0.5*fm.boundingRect("A").width();
}
bool JKQTmathText::MTsubscriptNode::isSubOrSuper()
{
return true;
}
QString JKQTmathText::MTsubscriptNode::getTypeName() const
{
return "MTsubscriptNode";
}
bool JKQTmathText::MTsubscriptNode::toHtml(QString &html, JKQTmathText::MTenvironment currentEv, JKQTmathText::MTenvironment defaultEv) {
html=html+"<sub>";
@ -697,6 +717,11 @@ void JKQTmathText::MTsqrtNode::set_drawBoxes(bool draw)
}
QString JKQTmathText::MTsqrtNode::getTypeName() const
{
return "MTsqrtNode";
}
@ -715,6 +740,11 @@ JKQTmathText::MTfracNode::~MTfracNode() {
if (child2!=nullptr) delete child2;
}
QString JKQTmathText::MTfracNode::getTypeName() const
{
return "MTfracNode";
}
void JKQTmathText::MTfracNode::getSizeInternal(QPainter& painter, JKQTmathText::MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos) {
QFontMetricsF fm(currentEv.getFont(parent), painter.device());
JKQTmathText::MTenvironment ev1=currentEv;
@ -920,6 +950,11 @@ JKQTmathText::MTmatrixNode::~MTmatrixNode() {
children.clear();
}
QString JKQTmathText::MTmatrixNode::getTypeName() const
{
return "MTmatrixNode";
}
void JKQTmathText::MTmatrixNode::getSizeInternal(QPainter& painter, JKQTmathText::MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos) {
QFontMetricsF fm(currentEv.getFont(parent), painter.device());
JKQTmathText::MTenvironment ev1=currentEv;
@ -944,7 +979,7 @@ void JKQTmathText::MTmatrixNode::getSizeInternal(QPainter& painter, JKQTmathText
//widths[i].resize(columns);
//baselines[i]=heights[i]=widths[i];
for (int j=0; j<children[i].size(); j++) {
children[i].at(j)->getSize(painter, ev1, width1, baselineHeight1, overallHeight1, strikeoutPos1);;
children[i].at(j)->getSize(painter, ev1, width1, baselineHeight1, overallHeight1, strikeoutPos1);
/*widths[i].operator[](j)=width1;
baselines[i].operator[](j)=baselineHeight;
heights[i].operator[](j)=overallHeight1;*/
@ -990,7 +1025,7 @@ double JKQTmathText::MTmatrixNode::draw(QPainter& painter, double x, double y, J
//widths[i].resize(columns);
//baselines[i]=heights[i]=widths[i];
for (int j=0; j<children[i].size(); j++) {
if (children[i].at(j)!=nullptr) children[i].at(j)->getSize(painter, ev1, width1, baselineHeight1, overallHeight1, strikeoutPos);;
if (children[i].at(j)!=nullptr) children[i].at(j)->getSize(painter, ev1, width1, baselineHeight1, overallHeight1, strikeoutPos);
/*widths[i].operator[](j)=width1;
baselines[i].operator[](j)=baselineHeight;
heights[i].operator[](j)=overallHeight1;*/
@ -1197,6 +1232,11 @@ void JKQTmathText::MTdecoratedNode::set_drawBoxes(bool draw)
}
QString JKQTmathText::MTdecoratedNode::getTypeName() const
{
return "MTdecoratedNode";
}
@ -1241,6 +1281,16 @@ double JKQTmathText::MTsuperscriptNode::draw(QPainter& painter, double x, double
return child->draw(painter, xx, y-shift, ev);//+0.5*fm.boundingRect("A").width();
}
bool JKQTmathText::MTsuperscriptNode::isSubOrSuper()
{
return true;
}
QString JKQTmathText::MTsuperscriptNode::getTypeName() const
{
return "MTsuperscriptNode";
}
bool JKQTmathText::MTsuperscriptNode::toHtml(QString &html, JKQTmathText::MTenvironment currentEv, JKQTmathText::MTenvironment defaultEv)
{
@ -1492,6 +1542,11 @@ void JKQTmathText::MTbraceNode::set_drawBoxes(bool draw)
}
QString JKQTmathText::MTbraceNode::getTypeName() const
{
return QLatin1String("MTbraceNode(")+openbrace+" "+closebrace+")";
}
void JKQTmathText::MTbraceNode::getBraceWidth(QPainter &/*painter*/, JKQTmathText::MTenvironment ev, double /*baselineHeight*/, double overallHeight, double &bracewidth, double &braceheight)
{
/*QFont evf=ev.getFont(parent);
@ -1539,6 +1594,11 @@ JKQTmathText::MTlistNode::~MTlistNode() {
nodes.clear();
}
QString JKQTmathText::MTlistNode::getTypeName() const
{
return "MTlistNode";
}
void JKQTmathText::MTlistNode::getSizeInternal(QPainter& painter, JKQTmathText::MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos) {
width=0;
overallHeight=0;
@ -2281,11 +2341,11 @@ JKQTmathText::MTsymbolNode::MTsymbolNode(JKQTmathText* parent, QString name, boo
else if (n=="notni") symbol=QChar(0x220C);
else if (n=="circ") symbol=QChar(0x2218);
else if (n=="tilde") symbol=QChar(0x223C);
else if (n=="iint") { symbol=QChar(0x222C); fontFactor=mathFontFactor; /*yfactor=+0.1;;*/ heightIsAscent=true; exactAscent=true; }
else if (n=="iiint") { symbol=QChar(0x222D); fontFactor=mathFontFactor; /*yfactor=+0.1;;*/ heightIsAscent=true; exactAscent=true; }
else if (n=="oint") { symbol=QChar(0x222E); fontFactor=mathFontFactor; /*yfactor=+0.1;;*/ heightIsAscent=true; exactAscent=true; }
else if (n=="oiint") { symbol=QChar(0x222F); fontFactor=mathFontFactor; /*yfactor=+0.1;;*/ heightIsAscent=true; exactAscent=true; }
else if (n=="oiiint") { symbol=QChar(0x2230); fontFactor=mathFontFactor; /*yfactor=+0.1;;*/ heightIsAscent=true; exactAscent=true; }
else if (n=="iint") { symbol=QChar(0x222C); fontFactor=mathFontFactor; /*yfactor=+0.1;*/ heightIsAscent=true; exactAscent=true; }
else if (n=="iiint") { symbol=QChar(0x222D); fontFactor=mathFontFactor; /*yfactor=+0.1;*/ heightIsAscent=true; exactAscent=true; }
else if (n=="oint") { symbol=QChar(0x222E); fontFactor=mathFontFactor; /*yfactor=+0.1;*/ heightIsAscent=true; exactAscent=true; }
else if (n=="oiint") { symbol=QChar(0x222F); fontFactor=mathFontFactor; /*yfactor=+0.1;*/ heightIsAscent=true; exactAscent=true; }
else if (n=="oiiint") { symbol=QChar(0x2230); fontFactor=mathFontFactor; /*yfactor=+0.1;*/ heightIsAscent=true; exactAscent=true; }
else if (n=="emptyset") symbol=QChar(0x2300);
else if (n=="varnothing") symbol=QChar(0x2300);
else if (n=="odot") symbol=QChar(0x2299);
@ -2326,10 +2386,10 @@ JKQTmathText::MTsymbolNode::MTsymbolNode(JKQTmathText* parent, QString name, boo
else if (n=="multimap") { symbol=QChar(0x22B8); }
else if (n=="maporiginal") { symbol=QChar(0x22B6); }
else if (n=="mapimage") { symbol=QChar(0x22B7); }
else if (n=="bigcap") { symbol=QChar(0x22C2); heightIsAscent=true; exactAscent=true;; heightIsAscent=true; exactAscent=true; }
else if (n=="bigcup") { symbol=QChar(0x22C3); heightIsAscent=true; exactAscent=true;; heightIsAscent=true; exactAscent=true; }
else if (n=="bigvee") { symbol=QChar(0x22C1); heightIsAscent=true; exactAscent=true;; heightIsAscent=true; exactAscent=true; }
else if (n=="bighat") { symbol=QChar(0x22C0); heightIsAscent=true; exactAscent=true;; heightIsAscent=true; exactAscent=true; }
else if (n=="bigcap") { symbol=QChar(0x22C2); heightIsAscent=true; exactAscent=true; heightIsAscent=true; exactAscent=true; }
else if (n=="bigcup") { symbol=QChar(0x22C3); heightIsAscent=true; exactAscent=true; heightIsAscent=true; exactAscent=true; }
else if (n=="bigvee") { symbol=QChar(0x22C1); heightIsAscent=true; exactAscent=true; heightIsAscent=true; exactAscent=true; }
else if (n=="bighat") { symbol=QChar(0x22C0); heightIsAscent=true; exactAscent=true; heightIsAscent=true; exactAscent=true; }
else if (n=="benzene") symbol=QChar(0x232C);
else if (n=="times") symbol=QChar(0x2A2F);
@ -2366,7 +2426,7 @@ JKQTmathText::MTsymbolNode::MTsymbolNode(JKQTmathText* parent, QString name, boo
else if (n=="diamond") symbol=QChar(0xE0);
else if (n=="langle") symbol=QChar(0x2329);
else if (n=="rangle") symbol=QChar(0x232A);
else if (n=="int") { symbol=QChar(0x222B); fontFactor=mathFontFactor; /*yfactor=+0.1;;*/ heightIsAscent=true; exactAscent=true; }
else if (n=="int") { symbol=QChar(0x222B); fontFactor=mathFontFactor; /*yfactor=+0.1;*/ heightIsAscent=true; exactAscent=true; }
else if (n=="infty") { symbol=QChar(0x221E); }
else if (n=="forall") { symbol=QChar(0x2200); }
else if (n=="exists") { symbol=QChar(0x2203); }
@ -2614,6 +2674,11 @@ JKQTmathText::MTsymbolNode::MTsymbolNode(JKQTmathText* parent, QString name, boo
JKQTmathText::MTsymbolNode::~MTsymbolNode() {
}
QString JKQTmathText::MTsymbolNode::getTypeName() const
{
return QLatin1String("MTsymbolNode(")+symbolName+QLatin1String(")");
}
QFont JKQTmathText::MTsymbolNode::getFontName(symbolFont f, QFont& fi) {
QFont fr=fi;
switch(f) {
@ -3472,7 +3537,7 @@ JKQTmathText::MTnode* JKQTmathText::parseLatexString(bool get, QString quitOnClo
currentTokenID++;
if (currentTokenID<parseString.size()) c=parseString[currentTokenID];
}
if (c!='}') error_list.append(tr("error @ ch. %1: \verb{...} not closed by '}'").arg(currentTokenID).arg(name));;
if (c!='}') error_list.append(tr("error @ ch. %1: \verb{...} not closed by '}'").arg(currentTokenID).arg(name));
nl->addNode(new MTtextNode(this, text, false));
}
} else if (name=="frac") {
@ -3966,6 +4031,22 @@ void JKQTmathText::draw(QPainter& painter, int flags, QRectF rect, bool drawBoxe
}
}
JKQTmathText::MTwhitespaceNode::MTwhitespaceNode(JKQTmathText *parent):
MTtextNode(parent, " ", false, false)
{
}
JKQTmathText::MTwhitespaceNode::~MTwhitespaceNode()
{
}
QString JKQTmathText::MTwhitespaceNode::getTypeName() const
{
return QLatin1String("MTwhitespaceNode(")+text+")";
}
bool JKQTmathText::MTwhitespaceNode::toHtml(QString &html, JKQTmathText::MTenvironment /*currentEv*/, JKQTmathText::MTenvironment /*defaultEv*/) {
html=html+"&nbsp;";
return true;
@ -3976,6 +4057,11 @@ void JKQTmathText::MTnode::set_drawBoxes(bool draw)
this->drawBoxes=draw;
}
QString JKQTmathText::MTnode::getTypeName() const
{
return "MTnode";
}
QString JKQTmathText::fracModeToString(JKQTmathText::MTfracMode mode)
{
switch(mode) {
@ -4174,6 +4260,11 @@ JKQTmathText::MTplainTextNode::MTplainTextNode(JKQTmathText *parent, QString tex
}
QString JKQTmathText::MTplainTextNode::getTypeName() const
{return QLatin1String("MTplainTextNode(")+text+")";
}
QString JKQTmathText::MTplainTextNode::textTransform(const QString &text, JKQTmathText::MTenvironment /*currentEv*/, bool /*forSize*/)
{

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)
@ -276,7 +276,7 @@ class LIB_EXPORT JKQTmathText : public QObject {
JKQTPGET_MACRO(bool, drawBoxes)
virtual void set_drawBoxes(bool draw);
inline virtual QString getTypeName() const { return "MTnode"; }
virtual QString getTypeName() const;
protected:
JKQTmathText* parent;
bool drawBoxes;
@ -292,7 +292,7 @@ class LIB_EXPORT JKQTmathText : public QObject {
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv);
virtual bool toHtml(QString& html, JKQTmathText::MTenvironment currentEv, JKQTmathText::MTenvironment defaultEv);
JKQTPGET_MACRO(QString, text)
inline virtual QString getTypeName() const { return QLatin1String("MTtextNode(")+text+")"; }
virtual QString getTypeName() const ;
protected:
QString text;
virtual QString textTransform(const QString& text, JKQTmathText::MTenvironment currentEv, bool forSize=false);
@ -302,16 +302,16 @@ class LIB_EXPORT JKQTmathText : public QObject {
class MTplainTextNode: public MTtextNode {
public:
MTplainTextNode(JKQTmathText* parent, QString text, bool addWhitespace, bool stripInnerWhitepace=false);
inline virtual QString getTypeName() const { return QLatin1String("MTplainTextNode(")+text+")"; }
virtual QString getTypeName() const;
protected:
virtual QString textTransform(const QString& text, JKQTmathText::MTenvironment currentEv, bool forSize=false);
};
/** \brief subclass representing one whitepsace node in the syntax tree */
class MTwhitespaceNode: public MTtextNode {
public:
MTwhitespaceNode(JKQTmathText* parent): MTtextNode(parent, " ", false, false) {};
virtual ~MTwhitespaceNode(){};
inline virtual QString getTypeName() const { return QLatin1String("MTwhitespaceNode(")+text+")"; }
MTwhitespaceNode(JKQTmathText* parent);
virtual ~MTwhitespaceNode();
virtual QString getTypeName() const;
/** \brief convert node to HTML and returns \c true on success */
virtual bool toHtml(QString& html, JKQTmathText::MTenvironment currentEv, JKQTmathText::MTenvironment defaultEv);
};
@ -321,7 +321,7 @@ class LIB_EXPORT JKQTmathText : public QObject {
public:
MTsymbolNode(JKQTmathText* parent, QString name, bool addWhitespace);
virtual ~MTsymbolNode();
inline virtual QString getTypeName() const { return QLatin1String("MTsymbolNode(")+symbolName+QLatin1String(")"); }
virtual QString getTypeName() const;
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos);
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv);
virtual bool toHtml(QString& html, JKQTmathText::MTenvironment currentEv, JKQTmathText::MTenvironment defaultEv);
@ -357,7 +357,7 @@ class LIB_EXPORT JKQTmathText : public QObject {
public:
MTlistNode(JKQTmathText* parent);
virtual ~MTlistNode();
inline virtual QString getTypeName() const { return "MTlistNode"; }
virtual QString getTypeName() const;
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos);
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv);
void addNode(MTnode* n) { nodes.append(n); }
@ -374,7 +374,7 @@ class LIB_EXPORT JKQTmathText : public QObject {
public:
MTinstruction1Node(JKQTmathText* parent, QString name, MTnode* child, const QStringList& parameters=QStringList());
virtual ~MTinstruction1Node();
inline virtual QString getTypeName() const { return QLatin1String("MTinstruction1Node(")+name+")"; }
virtual QString getTypeName() const;
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos);
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv);
/** \brief convert node to HTML and returns \c true on success */
@ -399,8 +399,8 @@ class LIB_EXPORT JKQTmathText : public QObject {
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos);
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv);
/** \brief returns true if node is subscript or superscript node */
virtual bool isSubOrSuper() { return true; }
inline virtual QString getTypeName() const { return "MTsubscriptNode"; }
virtual bool isSubOrSuper() ;
virtual QString getTypeName() const;
JKQTPGET_MACRO(MTnode*, child)
virtual bool toHtml(QString& html, JKQTmathText::MTenvironment currentEv, JKQTmathText::MTenvironment defaultEv);
virtual void set_drawBoxes(bool draw);
@ -416,9 +416,9 @@ class LIB_EXPORT JKQTmathText : public QObject {
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos);
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv);
/** \brief returns true if node is subscript or superscript node */
virtual bool isSubOrSuper() { return true; }
virtual bool isSubOrSuper();
JKQTPGET_MACRO(MTnode*, child)
inline virtual QString getTypeName() const { return "MTsuperscriptNode"; }
virtual QString getTypeName() const;
virtual bool toHtml(QString& html, JKQTmathText::MTenvironment currentEv, JKQTmathText::MTenvironment defaultEv);
virtual void set_drawBoxes(bool draw);
protected:
@ -434,7 +434,7 @@ class LIB_EXPORT JKQTmathText : public QObject {
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv);
virtual bool toHtml(QString& html, JKQTmathText::MTenvironment currentEv, JKQTmathText::MTenvironment defaultEv);
virtual void set_drawBoxes(bool draw);
inline virtual QString getTypeName() const { return QLatin1String("MTbraceNode(")+openbrace+" "+closebrace+")"; }
virtual QString getTypeName() const;
JKQTPGET_MACRO(MTnode*, child)
JKQTPGET_MACRO(QString, openbrace)
JKQTPGET_MACRO(QString, closebrace)
@ -458,7 +458,7 @@ class LIB_EXPORT JKQTmathText : public QObject {
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv);
virtual bool toHtml(QString& html, JKQTmathText::MTenvironment currentEv, JKQTmathText::MTenvironment defaultEv);
virtual void set_drawBoxes(bool draw);
inline virtual QString getTypeName() const { return "MTsqrtNode"; }
virtual QString getTypeName() const ;
JKQTPGET_MACRO(MTnode*, child)
JKQTPGET_MACRO(int, degree)
protected:
@ -484,7 +484,7 @@ class LIB_EXPORT JKQTmathText : public QObject {
public:
MTfracNode(JKQTmathText* parent, MTnode* child_top, MTnode* child_bottom, MTfracMode mode);
virtual ~MTfracNode();
inline virtual QString getTypeName() const { return "MTfracNode"; }
virtual QString getTypeName() const ;
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos);
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv);
virtual bool toHtml(QString& html, JKQTmathText::MTenvironment currentEv, JKQTmathText::MTenvironment defaultEv);
@ -503,7 +503,7 @@ class LIB_EXPORT JKQTmathText : public QObject {
public:
MTmatrixNode(JKQTmathText* parent, QVector<QVector<MTnode*> > children);
virtual ~MTmatrixNode();
inline virtual QString getTypeName() const { return "MTmatrixNode"; }
virtual QString getTypeName() const;
virtual void getSizeInternal(QPainter& painter, MTenvironment currentEv, double& width, double& baselineHeight, double& overallHeight, double& strikeoutPos);
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv);
virtual bool toHtml(QString& html, JKQTmathText::MTenvironment currentEv, JKQTmathText::MTenvironment defaultEv);
@ -542,7 +542,7 @@ class LIB_EXPORT JKQTmathText : public QObject {
virtual double draw(QPainter& painter, double x, double y, MTenvironment currentEv);
virtual bool toHtml(QString& html, JKQTmathText::MTenvironment currentEv, JKQTmathText::MTenvironment defaultEv);
virtual void set_drawBoxes(bool draw);
inline virtual QString getTypeName() const { return "MTdecoratedNode"; }
virtual QString getTypeName() const ;
JKQTPGET_MACRO(MTnode*, child)
JKQTPGET_MACRO(MTdecoration, decoration)
protected:
@ -554,77 +554,77 @@ class LIB_EXPORT JKQTmathText : public QObject {
/** \brief font color */
JKQTMTPROPERTY(QColor, fontColor);
JKQTMTPROPERTY(QColor, fontColor)
/** \brief base font size in points */
JKQTMTPROPERTY(double, fontSize);
JKQTMTPROPERTY(double, fontSize)
/** \brief roman font */
JKQTMTPROPERTY(QString, fontRoman);
JKQTMTPROPERTY(QString, fontRoman)
/** \brief sans-serif font */
JKQTMTPROPERTY(QString, fontSans);
JKQTMTPROPERTY(QString, fontSans)
/** \brief typewriter font */
JKQTMTPROPERTY(QString, fontTypewriter);
JKQTMTPROPERTY(QString, fontTypewriter)
/** \brief script font */
JKQTMTPROPERTY(QString, fontScript);
JKQTMTPROPERTY(QString, fontScript)
/** \brief greek font */
JKQTMTPROPERTY(QString, fontGreek);
JKQTMTPROPERTY(QString, fontGreek)
/** \brief symbol font, used for math symbols. */
JKQTMTPROPERTY(QString, fontSymbol);
JKQTMTPROPERTY(QString, fontSymbol)
/** \brief symbol font, used for braces in math mode. */
JKQTMTPROPERTY(QString, fontBraces);
JKQTMTPROPERTY(QString, fontBraces)
/** \brief symbol font, used for integrals in math mode. */
JKQTMTPROPERTY(QString, fontIntegrals);
JKQTMTPROPERTY(QString, fontIntegrals)
/** \brief font used for caligraphic symbols (escepcially in math environments) */
JKQTMTPROPERTY(QString, fontCaligraphic);
JKQTMTPROPERTY(QString, fontCaligraphic)
/** \brief font used for blackboard (double-stroke) symbols (escepcially in math environments) */
JKQTMTPROPERTY(QString, fontBlackboard);
JKQTMTPROPERTY(QString, fontBlackboard)
/** \brief roman font for math environment */
JKQTMTPROPERTY(QString, fontMathRoman);
JKQTMTPROPERTY(QString, fontMathRoman)
/** \brief sans font for math environment */
JKQTMTPROPERTY(QString, fontMathSans);
JKQTMTPROPERTY(QString, fontMathSans)
/** \brief prefix for LaTeX fonts */
JKQTMTPROPERTY(QString, fontLatexPrefix);
JKQTMTPROPERTY(QString, fontLatexPrefix)
/** \brief postfix for LaTeX fonts */
JKQTMTPROPERTY(QString, fontLatexPostfix);
JKQTMTPROPERTY(QString, fontLatexPostfix)
/** \brief specifies the encoding of special character fonts (default is \c MTFEwinSymbol ) */
JKQTMTPROPERTY(MTfontEncoding, fontEncoding);
JKQTMTPROPERTY(MTfontEncoding, fontEncoding)
/** \brief resizing factor for braces in math mode */
JKQTMTPROPERTY(double, brace_factor);
JKQTMTPROPERTY(double, brace_factor)
/** \brief shrinking the width of braces in math mode 0: reduce to 0 pixel width, 1: leave unchanged*/
JKQTMTPROPERTY(double, brace_shrink_factor);
JKQTMTPROPERTY(double, brace_shrink_factor)
/** \brief resizing factor for font size in sub-/superscript */
JKQTMTPROPERTY(double, subsuper_size_factor);
JKQTMTPROPERTY(double, subsuper_size_factor)
/** \brief fraction of a whitespace by which to shift a sub-/superscript left/right when the previous text is italic */
JKQTMTPROPERTY(double, italic_correction_factor);
JKQTMTPROPERTY(double, italic_correction_factor)
/** \brief like subsuper_size_factor, but for operators (\\sum, \\int) where the text is placed above/below the symbol */
JKQTMTPROPERTY(double, operatorsubsuper_size_factor);
JKQTMTPROPERTY(double, operatorsubsuper_size_factor)
/** \brief factor, used to extend the size of an operator in math mode */
JKQTMTPROPERTY(double, mathoperator_width_factor);
JKQTMTPROPERTY(double, mathoperator_width_factor)
/** \brief relative shift of text in superscript to normal text:
* 0= baseline kept, 1: baseline shifted to top of normal text */
JKQTMTPROPERTY(double, super_shift_factor);
JKQTMTPROPERTY(double, super_shift_factor)
/** \brief relative shift of text in subscript to normal text:
* 0= baseline kept, 1: baseline shifted to bottom of normal text */
JKQTMTPROPERTY(double, sub_shift_factor);
JKQTMTPROPERTY(double, sub_shift_factor)
/** \brief indicates whether to use STIX fonts or not */
JKQTMTPROPERTY(bool, useSTIXfonts);
JKQTMTPROPERTY(bool, useSTIXfonts)
/** \brief indicates whether to use XITS fonts or not */
JKQTMTPROPERTY(bool, useXITSfonts);
JKQTMTPROPERTY(bool, useXITSfonts)
/** \brief indicates whether to use XITS fonts or not */
JKQTMTPROPERTY(bool, useASANAfonts);
JKQTMTPROPERTY(bool, useASANAfonts)
/** \brief scaling factor for font of nominator and denominator of a fraction */
JKQTMTPROPERTY(double, frac_factor);
JKQTMTPROPERTY(double, frac_factor)
/** \brief shift of denominator/nummerator away from central line of a frac */
JKQTMTPROPERTY(double, frac_shift_factor);
JKQTMTPROPERTY(double, frac_shift_factor)
/** \brief scaling factor for font of underbrace/overbrace text */
JKQTMTPROPERTY(double, underbrace_factor);
JKQTMTPROPERTY(double, underbrace_factor)
/** \brief scaling factor for font of underset/overset text */
JKQTMTPROPERTY(double, underset_factor);
JKQTMTPROPERTY(double, underset_factor)
/** \brief fraction of the brace ascent that the brace is shifted downwards, when scaled */
JKQTMTPROPERTY(double, brace_y_shift_factor);
JKQTMTPROPERTY(double, brace_y_shift_factor)
/** \brief size of the decorations (dot, tilde, ...), as fractio of the baselineheight */
JKQTMTPROPERTY(double, decoration_height_factor);
JKQTMTPROPERTY(double, decoration_height_factor)
/** \brief switches on some options that will grant better rendering at the expense of higher time consumption */
JKQTMTPROPERTY(bool, expensiveRendering);
JKQTMTPROPERTY(bool, expensiveRendering)
/** \brief a list that will be filled with error messages while parsing, if any error occur */
QStringList error_list;
/** \brief used by the parser. This is used to implement brace pairs with \\right. */

View File

@ -3,7 +3,7 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)
last modification: $LastChangedDate: 2015-04-02 13:55:22 +0200 (Do, 02 Apr 2015) $ (revision $Rev: 3902 $)

939
jkqtpbarchartelements.cpp Normal file
View File

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

362
jkqtpbarchartelements.h Normal file
View File

@ -0,0 +1,362 @@
/*
Copyright (c) 2008-2018 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 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/>.
*/
/**
* \defgroup jkqtplotter_elements Plot Elements
* \ingroup jkqtplotter
* \defgroup jkqtplotter_plots Graphs
* \ingroup jkqtplotter_elements
*/
/** \file jkqtpelements.h
* \ingroup jkqtplotter
*/
#include <QString>
#include <QPainter>
#include <QPair>
#include "jkqtptools.h"
#include "jkqtp_imexport.h"
#include "jkqtpimagetools.h"
#include "jkqtpbasegraphs.h"
#ifndef JKQTPBARCHARTELEMENTS_H
#define JKQTPBARCHARTELEMENTS_H
/*! \brief This implements a bar graph with bars starting at \f$ y=0 \f$ to \f$ y=f(x) \f$
\ingroup jkqtplotter_plots
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 JKQTPstepHorizontalGraph 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
You can use JKQTPlotter::addHorizontalBargraph() to add a series of bargraphs, where the width and shift are determined
automatically. The y-columns are given as a QVector<int> to this function.
*/
class LIB_EXPORT JKQTPbarVerticalGraph: public JKQTPxyGraph {
Q_OBJECT
public:
/** \brief class constructor */
JKQTPbarVerticalGraph(JKQtBasePlotter* parent=nullptr);
/** \brief class constructor */
JKQTPbarVerticalGraph(JKQtPlotter* parent);
/** \brief plots the graph to the plotter object specified as parent */
virtual void draw(JKQTPEnhancedPainter& painter);
/** \brief plots a key marker inside the specified rectangle \a rect */
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect);
/** \brief returns the color to be used for the key label */
virtual QColor getKeyLabelColor();
/** \brief get the maximum and minimum x-value of the graph
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero);
/** \brief get the maximum and minimum y-value of the graph
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero);
/** \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);
void autoscaleBarWidthAndShiftSeparatedGroups(double groupWidth=0.75);
virtual bool isHorizontal() const;
JKQTPGET_SET_MACRO(QColor, color)
JKQTPGET_SET_MACRO(QColor, fillColor)
JKQTPGET_SET_MACRO(Qt::BrushStyle, fillStyle)
JKQTPGET_SET_MACRO(Qt::PenStyle, style)
JKQTPGET_SET_MACRO(double, lineWidth)
JKQTPGET_SET_MACRO(double, shift)
JKQTPGET_SET_MACRO(double, width)
JKQTPGET_SET_MACRO(double, baseline)
/** \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) */
void set_fillColor_and_darkenedColor(QColor fill, int colorDarker=200);
protected:
/** \brief color of the graph */
QColor color;
/** \brief color of the graph fill */
QColor fillColor;
/** \brief linestyle of the graph lines */
Qt::PenStyle style;
/** \brief width (pixels) of the graph */
double lineWidth;
/** \brief fill style, if the curve should be filled */
Qt::BrushStyle fillStyle;
/** \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 which plot style to use from the parent plotter (via JKQtPlotterBase::getPlotStyle() and JKQtPlotterBase::getNextStyle() ) */
int parentPlotStyle;
QBrush getBrush(JKQTPEnhancedPainter& painter) const;
QPen getLinePen(JKQTPEnhancedPainter &painter) const;
/** \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 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_plots
*
* Draw stacked barcharts by connecting several plots by calling \c set_stackedParent(belowPlot) for each plot
* \image html JKQTPbarVerticalGraphStacked.png
*
*/
class 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 set_stackedParent(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;
/** \brief calls getStackedMax() on the stack parent (if available), or \c 0.0 */
virtual double getParentStackedMax(int index) const;
/** \brief returns \c true, if a stack parent is set (if available) */
virtual bool hasStackParent() const;
};
/*! \brief This implements a bar graph with bars starting at \f$ y=0 \f$ to \f$ y=f(x) \f$
* and error indicator
* \ingroup jkqtplotter_plots
*
* This works much the same as JKQTPbarHorizontalGraph. Here is an example output:
* \image html plot_bargraphverploterr.png
*
*/
class LIB_EXPORT JKQTPbarVerticalErrorGraph: public JKQTPbarVerticalGraph, public JKQTPyGraphErrors {
Q_OBJECT
public:
/** \brief class constructor */
JKQTPbarVerticalErrorGraph(JKQtBasePlotter* parent=nullptr);
/** \brief class constructor */
JKQTPbarVerticalErrorGraph(JKQtPlotter* parent);
/** \copydoc JKQTPgraph::usesColumn() */
virtual bool usesColumn(int c);
/** \brief get the maximum and minimum y-value of the graph
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero);
protected:
/** \brief this function is used to plot error inidcators before plotting the graphs. */
virtual void drawErrorsAfter(JKQTPEnhancedPainter& painter) ;
};
/*! \brief This implements a bar graph with bars starting at \f$ x=0 \f$ to \f$ x=f(y) \f$
\ingroup jkqtplotter_plots
This works much the same as JKQTPbarHorizontalGraph. Here is an example output:
\image html plot_bargraphhorplot.png
*/
class LIB_EXPORT JKQTPbarHorizontalGraph: public JKQTPbarVerticalGraph {
Q_OBJECT
public:
/** \brief class constructor */
JKQTPbarHorizontalGraph(JKQtBasePlotter* parent=nullptr);
/** \brief class constructor */
JKQTPbarHorizontalGraph(JKQtPlotter* parent);
/** \brief plots the graph to the plotter object specified as parent */
virtual void draw(JKQTPEnhancedPainter& painter);
/** \brief get the maximum and minimum x-value of the graph
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero);
/** \brief get the maximum and minimum y-value of the graph
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero);
virtual bool isHorizontal() const;
};
/*! \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_plots
*
* Draw stacked barcharts by connecting several plots by calling \c set_stackedParent(belowPlot) for each plot
* \image html JKQTPbarHorizontalGraphStacked.png
*
*/
class 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 set_stackedParent(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;
/** \brief calls getStackedMax() on the stack parent (if available), or \c 0.0 */
virtual double getParentStackedMax(int index) const;
/** \brief returns \c true, if a stack parent is set (if available) */
virtual bool hasStackParent() const;
};
/*! \brief This implements a bar graph with bars starting at \f$ x=0 \f$ to \f$ x=f(y) \f$
* and error indicator
* \ingroup jkqtplotter_plots
*
* This works much the same as JKQTPbarHorizontalGraph. Here is an example output:
* \image html plot_bargraphhorploterr.png
*
*/
class LIB_EXPORT JKQTPbarHorizontalErrorGraph: public JKQTPbarHorizontalGraph, public JKQTPxGraphErrors {
Q_OBJECT
public:
/** \brief class constructor */
JKQTPbarHorizontalErrorGraph(JKQtBasePlotter* parent=nullptr);
/** \brief class constructor */
JKQTPbarHorizontalErrorGraph(JKQtPlotter* parent);
/** \copydoc JKQTPgraph::usesColumn() */
virtual bool usesColumn(int c);
/** \brief get the maximum and minimum x-value of the graph
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero);
protected:
/** \brief this function is used to plot error inidcators before plotting the graphs. */
virtual void drawErrorsAfter(JKQTPEnhancedPainter& painter) ;
};
#endif // JKQTPBARCHARTELEMENTS_H

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)
@ -194,6 +194,44 @@ void JKQTPcoordinateAxis::loadSettings(JKQTPcoordinateAxis* settings) {
calcPlotScaling();
}
void JKQTPcoordinateAxis::clearAxisTickLabels() {
tickLabels.clear();
update_plot();
}
void JKQTPcoordinateAxis::addAxisTickLabel(double x, QString label) {
tickLabels.append(qMakePair(x, label));
update_plot();
}
void JKQTPcoordinateAxis::addAxisTickLabels(const QVector<double> &x, const QStringList &label) {
for (int i=0; i<qMin(x.size(), label.size()); i++) {
tickLabels.append(qMakePair(x[i], label[i]));
}
update_plot();
}
void JKQTPcoordinateAxis::addAxisTickLabels(const double *x, const QStringList &label) {
for (int i=0; i<label.size(); i++) {
tickLabels.append(qMakePair(x[i], label[i]));
}
update_plot();
}
void JKQTPcoordinateAxis::addAxisTickLabels(const QVector<double> &x, const QString *label) {
for (int i=0; i<x.size(); i++) {
tickLabels.append(qMakePair(x[i], label[i]));
}
update_plot();
}
void JKQTPcoordinateAxis::addAxisTickLabels(const double *x, const QString *label, int items) {
for (int i=0; i<items; i++) {
tickLabels.append(qMakePair(x[i], label[i]));
}
update_plot();
}
void JKQTPcoordinateAxis::loadSettings(QSettings& settings, QString group) {
JKQTPPROPERTYload(settings, group+axisPrefix, showZeroAxis, "show_zero_line", toBool());
JKQTPPROPERTYload(settings, group+axisPrefix, autoAxisSpacing, "auto_spacing", toBool());
@ -725,6 +763,10 @@ void JKQTPcoordinateAxis::calcPlotScaling(bool force) {
}
bool JKQTPcoordinateAxis::isLogAxis() const {
return logAxis || (tickMode==JKQTPLTMPower);
}
void JKQTPcoordinateAxis::setRange(double aamin, double aamax) {
double oldamin=axismin;
double oldamax=axismax;
@ -772,6 +814,30 @@ void JKQTPcoordinateAxis::setNoAbsoluteRange() {
setRange(axismin, axismax);
}
void JKQTPcoordinateAxis::set_tickSpacing(double __value) {
this->tickSpacing = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_axisMinWidth(double __value) {
this->axisMinWidth = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_autoAxisSpacing(bool __value) {
this->autoAxisSpacing = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_minorTickLabelsEnabled(bool __value) {
this->minorTickLabelsEnabled = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_logAxis(bool __value)
{
this->logAxis = __value;
@ -786,6 +852,30 @@ void JKQTPcoordinateAxis::set_logAxis(bool __value)
update_plot();
}
void JKQTPcoordinateAxis::set_logAxisBase(double __value) {
this->logAxisBase = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_userTickSpacing(double __value) {
this->userTickSpacing = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_userLogTickSpacing(double __value) {
this->userLogTickSpacing = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_labelType(JKQTPCAlabelType __value) {
this->labelType = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_tickMode(JKQTPLabelTickMode __value)
{
this->tickMode = __value;
@ -793,6 +883,245 @@ void JKQTPcoordinateAxis::set_tickMode(JKQTPLabelTickMode __value)
set_logAxis(this->logAxis);
}
void JKQTPcoordinateAxis::set_tickMode(int __value) {
set_tickMode(JKQTPLabelTickMode(__value));
}
void JKQTPcoordinateAxis::set_axisLabel(QString __value) {
this->axisLabel = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_labelPosition(JKQTPlabelPosition __value) {
this->labelPosition = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_labelFont(QString __value) {
this->labelFont = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_labelFontSize(double __value) {
this->labelFontSize = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_tickLabelFont(QString __value) {
this->tickLabelFont = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_tickTimeFormat(QString __value) {
this->tickTimeFormat = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_tickDateFormat(QString __value) {
this->tickDateFormat = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_tickDateTimeFormat(QString __value) {
this->tickDateTimeFormat = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_tickLabelFontSize(double __value) {
this->tickLabelFontSize = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_minorTickLabelFontSize(double __value) {
this->minorTickLabelFontSize = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_minorTickLabelFullNumber(bool __value) {
this->minorTickLabelFullNumber = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_minTicks(unsigned int __value) {
this->minTicks = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_minorTicks(unsigned int __value) {
this->minorTicks = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_minorTicks(int __value) {
this->minorTicks = qMax(int(0), __value);
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_tickOutsideLength(double __value) {
this->tickOutsideLength = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_minorTickOutsideLength(double __value) {
this->minorTickOutsideLength = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_tickInsideLength(double __value) {
this->tickInsideLength = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_minorTickInsideLength(double __value) {
this->minorTickInsideLength = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_axisColor(QColor __value) {
this->axisColor = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_showZeroAxis(bool __value) {
this->showZeroAxis = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_inverted(bool __value) {
this->inverted = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_gridColor(QColor __value) {
this->gridColor = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_minorGridColor(QColor __value) {
this->minorGridColor = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_gridWidth(double __value) {
this->gridWidth = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_gridStyle(Qt::PenStyle __value) {
this->gridStyle = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_minorGridWidth(double __value) {
this->minorGridWidth = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_minorGridStyle(Qt::PenStyle __value) {
this->minorGridStyle = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_drawMode1(JKQTPCAdrawMode __value) {
this->drawMode1 = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_drawMode2(JKQTPCAdrawMode __value) {
this->drawMode2 = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_minorTickWidth(double __value) {
this->minorTickWidth = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_tickWidth(double __value) {
this->tickWidth = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_lineWidth(double __value) {
this->lineWidth = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_lineWidthZeroAxis(double __value) {
this->lineWidthZeroAxis = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_tickLabelDistance(double __value) {
this->tickLabelDistance = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_labelDistance(double __value) {
this->labelDistance = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_labelDigits(int __value) {
this->labelDigits = __value;
this->paramsChanged=true;
this->autoLabelDigits=false;
update_plot();
}
void JKQTPcoordinateAxis::set_drawGrid(bool __value) {
this->drawGrid = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_drawMinorGrid(bool __value) {
this->drawMinorGrid = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::set_tickLabelAngle(double __value) {
this->tickLabelAngle = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPcoordinateAxis::setAbsoluteRange(double amin, double amax) {
axisabsoultemin=amin;
@ -1416,6 +1745,36 @@ JKQTPverticalIndependentAxis::JKQTPverticalIndependentAxis(double axisOffset, do
this->otherAxisInverted=false;
}
void JKQTPverticalIndependentAxis::set_axisOffset(double __value) {
this->axisOffset = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPverticalIndependentAxis::set_axisWidth(double __value) {
this->axisWidth = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPverticalIndependentAxis::set_otherAxisOffset(double __value) {
this->otherAxisOffset = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPverticalIndependentAxis::set_otherAxisWidth(double __value) {
this->otherAxisWidth = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPverticalIndependentAxis::set_otherAxisInverted(bool __value) {
this->otherAxisInverted = __value;
this->paramsChanged=true;
update_plot();
}
@ -1958,4 +2317,44 @@ JKQTPhorizontalIndependentAxis::JKQTPhorizontalIndependentAxis(double axisOffset
this->otherAxisInverted=false;
}
void JKQTPhorizontalIndependentAxis::set_axisOffset(double __value) {
this->axisOffset = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPhorizontalIndependentAxis::set_axisWidth(double __value) {
this->axisWidth = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPhorizontalIndependentAxis::set_otherAxisOffset(double __value) {
this->otherAxisOffset = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPhorizontalIndependentAxis::set_otherAxisWidth(double __value) {
this->otherAxisWidth = __value;
this->paramsChanged=true;
update_plot();
}
void JKQTPhorizontalIndependentAxis::set_otherAxisInverted(bool __value) {
this->otherAxisInverted = __value;
this->paramsChanged=true;
update_plot();
}
double JKQTPhorizontalIndependentAxis::get_parent_plotwidth() const { return axisWidth; }
double JKQTPhorizontalIndependentAxis::get_parent_plotoffset() const { return axisOffset; }
double JKQTPhorizontalIndependentAxis::get_parent_otheraxis_width() const { return otherAxisWidth; }
bool JKQTPhorizontalIndependentAxis::get_parent_otheraxis_inverted() const { return otherAxisInverted; }
double JKQTPhorizontalIndependentAxis::get_parent_otheraxis_offset() const { return otherAxisOffset; }

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)
@ -181,7 +181,7 @@ class LIB_EXPORT JKQTPcoordinateAxis: public QObject {
} else {
return r;
}
};
}
/** \brief return time coordinate coordinate from x-pixel */
inline double p2x(long x) const {
@ -199,46 +199,20 @@ class LIB_EXPORT JKQTPcoordinateAxis: public QObject {
/** \brief clear axis tick labels. This switches back to automatic labels mode for the axis. */
inline void clearAxisTickLabels() {
tickLabels.clear();
update_plot();
}
void clearAxisTickLabels();
/** \brief add a new tick label to the axis */
inline void addAxisTickLabel(double x, QString label) {
tickLabels.append(qMakePair(x, label));
update_plot();
}
void addAxisTickLabel(double x, QString label);
/** \brief add a new tick label to the axis */
inline void addAxisTickLabels(const QVector<double>& x, const QStringList& label) {
for (int i=0; i<qMin(x.size(), label.size()); i++) {
tickLabels.append(qMakePair(x[i], label[i]));
}
update_plot();
}
void addAxisTickLabels(const QVector<double>& x, const QStringList& label);
/** \brief add a new tick label to the axis */
inline void addAxisTickLabels(const double* x, const QStringList& label) {
for (int i=0; i<label.size(); i++) {
tickLabels.append(qMakePair(x[i], label[i]));
}
update_plot();
}
void addAxisTickLabels(const double* x, const QStringList& label);
/** \brief add a new tick label to the axis */
inline void addAxisTickLabels(const QVector<double>& x, const QString* label) {
for (int i=0; i<x.size(); i++) {
tickLabels.append(qMakePair(x[i], label[i]));
}
update_plot();
}
void addAxisTickLabels(const QVector<double>& x, const QString* label);
/** \brief add a new tick label to the axis */
inline void addAxisTickLabels(const double* x, const QString* label, int items) {
for (int i=0; i<items; i++) {
tickLabels.append(qMakePair(x[i], label[i]));
}
update_plot();
}
void addAxisTickLabels(const double* x, const QString* label, int items);
/** \brief returns the size of the left/bottom axis in pixels */
virtual QSize getSize1(JKQTPEnhancedPainter& painter)=0;
@ -305,17 +279,16 @@ class LIB_EXPORT JKQTPcoordinateAxis: public QObject {
/** \brief returns the current min */
inline double getMin() const {return axismin; };
inline double getMin() const {return axismin; }
/** \brief returns the current max */
inline double getMax() const {return axismax; };
inline double getMax() const {return axismax; }
/** \brief returns the current absolute min */
inline double getAbsoluteMin() const {return axisabsoultemin; };
inline double getAbsoluteMin() const {return axisabsoultemin; }
/** \brief returns the current absolute max */
inline double getAbsoluteMax() const {return axisabsoultemax; };
inline double getAbsoluteMax() const {return axisabsoultemax; }
/** \brief calculate the scaling and offset values from axis min/max values
*
* This is only executed when \c paramChanged==true, as otherwise the data has to be still
@ -324,9 +297,7 @@ class LIB_EXPORT JKQTPcoordinateAxis: public QObject {
void calcPlotScaling(bool force=false);
inline bool isLogAxis() const {
return logAxis || (tickMode==JKQTPLTMPower);
}
bool isLogAxis() const;
public slots:
/** \brief set range of plot axis */
@ -339,38 +310,22 @@ class LIB_EXPORT JKQTPcoordinateAxis: public QObject {
/** \brief sets the property tickSpacing to the specified \a __value.
* \details Description of the parameter tickSpacing is: <CENTER>\copybrief tickSpacing.</CENTER>
* \see tickSpacing for more information */
inline virtual void set_tickSpacing(double __value) {
this->tickSpacing = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_tickSpacing(double __value);
/** \brief sets the property axisMinWidth to the specified \a __value.
* \details Description of the parameter tickSpacing is: <CENTER>\copybrief axisMinWidth.</CENTER>
* \see axisMinWidth for more information */
inline virtual void set_axisMinWidth(double __value) {
this->axisMinWidth = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_axisMinWidth(double __value);
/** \brief sets the property autoAxisSpacing to the specified \a __value.
* \details Description of the parameter autoAxisSpacing is: <CENTER>\copybrief autoAxisSpacing.</CENTER>
* \see autoAxisSpacing for more information */
inline virtual void set_autoAxisSpacing(bool __value) {
this->autoAxisSpacing = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_autoAxisSpacing(bool __value);
/** \brief sets the property minorTickLabelsEnabled to the specified \a __value.
* \details Description of the parameter minorTickLabelsEnabled is: <CENTER>\copybrief minorTickLabelsEnabled.</CENTER>
* \see autoAxisSpacing for more information */
inline virtual void set_minorTickLabelsEnabled(bool __value) {
this->minorTickLabelsEnabled = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_minorTickLabelsEnabled(bool __value);
/** \brief sets the property logAxis to the specified \a __value.
* \details Description of the parameter logAxis is: <CENTER>\copybrief logAxis.</CENTER>
@ -380,38 +335,22 @@ class LIB_EXPORT JKQTPcoordinateAxis: public QObject {
/** \brief sets the property logAxisBase to the specified \a __value.
* \details Description of the parameter logAxisBase is: <CENTER>\copybrief logAxisBase.</CENTER>
* \see logAxisBase for more information */
inline virtual void set_logAxisBase (double __value) {
this->logAxisBase = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_logAxisBase (double __value);
/** \brief sets the property userTickSpacing to the specified \a __value.
* \details Description of the parameter userTickSpacing is: <CENTER>\copybrief userTickSpacing.</CENTER>
* \see userTickSpacing for more information */
inline virtual void set_userTickSpacing (double __value) {
this->userTickSpacing = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_userTickSpacing (double __value);
/** \brief sets the property userLogTickSpacing to the specified \a __value.
* \details Description of the parameter userLogTickSpacing is: <CENTER>\copybrief userLogTickSpacing.</CENTER>
* \see userLogTickSpacing for more information */
inline virtual void set_userLogTickSpacing (double __value) {
this->userLogTickSpacing = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_userLogTickSpacing (double __value);
/** \brief sets the property labelType to the specified \a __value.
* \details Description of the parameter labelType is: <CENTER>\copybrief labelType.</CENTER>
* \see labelType for more information */
inline virtual void set_labelType (JKQTPCAlabelType __value) {
this->labelType = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_labelType (JKQTPCAlabelType __value);
/** \brief sets the property tickMode to the specified \a __value.
* \details Description of the parameter tickMode is: <CENTER>\copybrief tickMode.</CENTER>
@ -420,333 +359,169 @@ class LIB_EXPORT JKQTPcoordinateAxis: public QObject {
/** \brief sets the property tickMode to the specified \a __value.
* \details Description of the parameter tickMode is: <CENTER>\copybrief tickMode.</CENTER>
* \see tickMode for more information */
inline virtual void set_tickMode (int __value) {
set_tickMode(JKQTPLabelTickMode(__value));
};
virtual void set_tickMode (int __value);
/** \brief sets the property axisLabel to the specified \a __value.
* \details Description of the parameter axisLabel is: <CENTER>\copybrief axisLabel.</CENTER>
* \see axisLabel for more information */
inline virtual void set_axisLabel (QString __value) {
this->axisLabel = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_axisLabel (QString __value);
/** \brief sets the property labelPosition to the specified \a __value.
* \details Description of the parameter labelPosition is: <CENTER>\copybrief labelPosition.</CENTER> */
inline virtual void set_labelPosition (JKQTPlabelPosition __value) {
this->labelPosition = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_labelPosition (JKQTPlabelPosition __value);
/** \brief sets the property labelFont to the specified \a __value.
* \details Description of the parameter labelFont is: <CENTER>\copybrief labelFont.</CENTER> */
inline virtual void set_labelFont (QString __value) {
this->labelFont = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_labelFont (QString __value);
/** \brief sets the property labelFontSize to the specified \a __value.
* \details Description of the parameter labelFontSize is: <CENTER>\copybrief labelFontSize.</CENTER> */
inline virtual void set_labelFontSize (double __value) {
this->labelFontSize = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_labelFontSize (double __value);
/** \brief sets the property tickLabelFont to the specified \a __value.
* \details Description of the parameter tickLabelFont is: <CENTER>\copybrief tickLabelFont.</CENTER> */
inline virtual void set_tickLabelFont (QString __value) {
this->tickLabelFont = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_tickLabelFont (QString __value);
/** \brief sets the property tickTimeFormat to the specified \a __value.
* \details Description of the parameter tickTimeFormat is: <CENTER>\copybrief tickTimeFormat.</CENTER> */
inline virtual void set_tickTimeFormat (QString __value) {
this->tickTimeFormat = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_tickTimeFormat (QString __value);
/** \brief sets the property tickDateFormat to the specified \a __value.
* \details Description of the parameter tickDateFormat is: <CENTER>\copybrief tickDateFormat.</CENTER> */
inline virtual void set_tickDateFormat (QString __value) {
this->tickDateFormat = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_tickDateFormat (QString __value);
/** \brief sets the property tickDateTimeFormat to the specified \a __value.
* \details Description of the parameter tickDateTimeFormat is: <CENTER>\copybrief tickDateTimeFormat.</CENTER> */
inline virtual void set_tickDateTimeFormat (QString __value) {
this->tickDateTimeFormat = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_tickDateTimeFormat (QString __value);
/** \brief sets the property tickLabelFontSize to the specified \a __value.
* \details Description of the parameter tickLabelFontSize is: <CENTER>\copybrief tickLabelFontSize.</CENTER> */
inline virtual void set_tickLabelFontSize (double __value) {
this->tickLabelFontSize = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_tickLabelFontSize (double __value);
/** \brief sets the property minorTickLabelFontSize to the specified \a __value.
* \details Description of the parameter minorTickLabelFontSize is: <CENTER>\copybrief minorTickLabelFontSize.</CENTER> */
inline virtual void set_minorTickLabelFontSize (double __value) {
this->minorTickLabelFontSize = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_minorTickLabelFontSize (double __value);
/** \brief sets the property minorTickLabelFullNumber to the specified \a __value.
* \details Description of the parameter minorTickLabelFullNumber is: <CENTER>\copybrief minorTickLabelFullNumber.</CENTER> */
inline virtual void set_minorTickLabelFullNumber (bool __value) {
this->minorTickLabelFullNumber = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_minorTickLabelFullNumber (bool __value);
/** \brief sets the property minTicks to the specified \a __value.
* \details Description of the parameter minTicks is: <CENTER>\copybrief minTicks.</CENTER> */
inline virtual void set_minTicks(unsigned int __value) {
this->minTicks = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_minTicks(unsigned int __value);
/** \brief sets the property minorTicks to the specified \a __value.
* \details Description of the parameter minorTicks is: <CENTER>\copybrief minorTicks.</CENTER> */
inline virtual void set_minorTicks (unsigned int __value) {
this->minorTicks = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_minorTicks (unsigned int __value);
/** \brief sets the property minorTicks to the specified \a __value.
* \details Description of the parameter minorTicks is: <CENTER>\copybrief minorTicks.</CENTER> */
inline virtual void set_minorTicks (int __value) {
this->minorTicks = qMax(int(0), __value);
this->paramsChanged=true;
update_plot();
};
virtual void set_minorTicks (int __value);
/** \brief sets the property tickOutsideLength to the specified \a __value.
* \details Description of the parameter tickOutsideLength is: <CENTER>\copybrief tickOutsideLength.</CENTER> */
inline virtual void set_tickOutsideLength(double __value) {
this->tickOutsideLength = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_tickOutsideLength(double __value);
/** \brief sets the property minorTickOutsideLength to the specified \a __value.
* \details Description of the parameter minorTickOutsideLength is: <CENTER>\copybrief minorTickOutsideLength.</CENTER> */
inline virtual void set_minorTickOutsideLength (double __value) {
this->minorTickOutsideLength = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_minorTickOutsideLength (double __value);
/** \brief sets the property tickInsideLength to the specified \a __value.
* \details Description of the parameter tickInsideLength is: <CENTER>\copybrief tickInsideLength.</CENTER> */
inline virtual void set_tickInsideLength(double __value) {
this->tickInsideLength = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_tickInsideLength(double __value);
/** \brief sets the property minorTickInsideLength to the specified \a __value.
* \details Description of the parameter minorTickInsideLength is: <CENTER>\copybrief minorTickInsideLength.</CENTER> */
inline virtual void set_minorTickInsideLength (double __value) {
this->minorTickInsideLength = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_minorTickInsideLength (double __value);
/** \brief sets the property axisColor to the specified \a __value.
* \details Description of the parameter axisColor is: <CENTER>\copybrief axisColor.</CENTER> */
inline virtual void set_axisColor (QColor __value) {
this->axisColor = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_axisColor (QColor __value);
/** \brief sets the property showZeroAxis to the specified \a __value.
* \details Description of the parameter showZeroAxis is: <CENTER>\copybrief showZeroAxis.</CENTER> */
inline virtual void set_showZeroAxis(bool __value) {
this->showZeroAxis = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_showZeroAxis(bool __value);
/** \brief sets the property inverted to the specified \a __value.
* \details Description of the parameter inverted is: <CENTER>\copybrief inverted.</CENTER> */
inline virtual void set_inverted(bool __value) {
this->inverted = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_inverted(bool __value);
/** \brief sets the property gridColor to the specified \a __value.
* \details Description of the parameter gridColor is: <CENTER>\copybrief gridColor.</CENTER> */
inline virtual void set_gridColor(QColor __value) {
this->gridColor = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_gridColor(QColor __value);
/** \brief sets the property minorGridColor to the specified \a __value.
* \details Description of the parameter minorGridColor is: <CENTER>\copybrief minorGridColor.</CENTER> */
inline virtual void set_minorGridColor(QColor __value) {
this->minorGridColor = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_minorGridColor(QColor __value);
/** \brief sets the property gridWidth to the specified \a __value.
* \details Description of the parameter gridWidth is: <CENTER>\copybrief gridWidth.</CENTER> */
inline virtual void set_gridWidth (double __value) {
this->gridWidth = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_gridWidth (double __value);
/** \brief sets the property gridStyle to the specified \a __value.
* \details Description of the parameter gridStyle is: <CENTER>\copybrief gridStyle.</CENTER> */
inline virtual void set_gridStyle(Qt::PenStyle __value) {
this->gridStyle = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_gridStyle(Qt::PenStyle __value);
/** \brief sets the property minorGridWidth to the specified \a __value.
* \details Description of the parameter minorGridWidth is: <CENTER>\copybrief minorGridWidth.</CENTER> */
inline virtual void set_minorGridWidth(double __value) {
this->minorGridWidth = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_minorGridWidth(double __value);
/** \brief sets the property minorGridStyle to the specified \a __value.
* \details Description of the parameter minorGridStyle is: <CENTER>\copybrief minorGridStyle.</CENTER> */
inline virtual void set_minorGridStyle (Qt::PenStyle __value) {
this->minorGridStyle = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_minorGridStyle (Qt::PenStyle __value);
/** \brief sets the property drawMode1 to the specified \a __value.
* \details Description of the parameter drawMode1 is: <CENTER>\copybrief drawMode1.</CENTER> */
inline virtual void set_drawMode1 (JKQTPCAdrawMode __value) {
this->drawMode1 = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_drawMode1 (JKQTPCAdrawMode __value);
/** \brief sets the property drawMode2 to the specified \a __value.
* \details Description of the parameter drawMode2 is: <CENTER>\copybrief drawMode2.</CENTER> */
inline virtual void set_drawMode2(JKQTPCAdrawMode __value) {
this->drawMode2 = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_drawMode2(JKQTPCAdrawMode __value);
/** \brief sets the property minorTickWidth to the specified \a __value.
* \details Description of the parameter minorTickWidth is: <CENTER>\copybrief minorTickWidth.</CENTER> */
inline virtual void set_minorTickWidth(double __value) {
this->minorTickWidth = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_minorTickWidth(double __value);
/** \brief sets the property tickWidth to the specified \a __value.
* \details Description of the parameter tickWidth is: <CENTER>\copybrief tickWidth.</CENTER> */
inline virtual void set_tickWidth (double __value) {
this->tickWidth = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_tickWidth (double __value);
/** \brief sets the property lineWidth to the specified \a __value.
* \details Description of the parameter lineWidth is: <CENTER>\copybrief lineWidth.</CENTER> */
inline virtual void set_lineWidth (double __value) {
this->lineWidth = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_lineWidth (double __value);
/** \brief sets the property lineWidthZeroAxis to the specified \a __value.
* \details Description of the parameter lineWidthZeroAxis is: <CENTER>\copybrief lineWidthZeroAxis.</CENTER> */
inline virtual void set_lineWidthZeroAxis (double __value) {
this->lineWidthZeroAxis = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_lineWidthZeroAxis (double __value);
/** \brief sets the property tickLabelDistance to the specified \a __value.
* \details Description of the parameter tickLabelDistance is: <CENTER>\copybrief tickLabelDistance.</CENTER> */
inline virtual void set_tickLabelDistance(double __value) {
this->tickLabelDistance = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_tickLabelDistance(double __value);
/** \brief sets the property labelDistance to the specified \a __value.
* \details Description of the parameter labelDistance is: <CENTER>\copybrief labelDistance.</CENTER> */
inline virtual void set_labelDistance(double __value) {
this->labelDistance = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_labelDistance(double __value);
/** \brief sets the property labelDigits to the specified \a __value.
* \details Description of the parameter labelDistance is: <CENTER>\copybrief labelDigits.</CENTER> */
inline virtual void set_labelDigits(int __value) {
this->labelDigits = __value;
this->paramsChanged=true;
this->autoLabelDigits=false;
update_plot();
};
virtual void set_labelDigits(int __value);
/** \brief sets the property drawGrid to the specified \a __value.
* \details Description of the parameter drawGrid is: <CENTER>\copybrief drawGrid.</CENTER> */
inline virtual void set_drawGrid(bool __value) {
this->drawGrid = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_drawGrid(bool __value);
/** \brief sets the property drawMinorGrid to the specified \a __value.
* \details Description of the parameter drawMinorGrid is: <CENTER>\copybrief drawMinorGrid.</CENTER> */
inline virtual void set_drawMinorGrid(bool __value) {
this->drawMinorGrid = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_drawMinorGrid(bool __value);
/** \brief sets the property tickLabelAngle to the specified \a __value.
* \details Description of the parameter tickLabelAngle is: <CENTER>\copybrief tickLabelAngle.</CENTER> */
inline virtual void set_tickLabelAngle(double __value) {
this->tickLabelAngle = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_tickLabelAngle(double __value);
protected:
/** \brief indicates whether one of the parameters has changed sinse the last recalculation of tickspacing ... */
@ -818,69 +593,69 @@ class LIB_EXPORT JKQTPcoordinateAxis: public QObject {
/** \brief when \c true, the digits of the labels are calculated automatically */
bool autoLabelDigits;
/** \brief indicates whether the object should use automatic tick spacing for the x axis (calculated by calcPlotScaling() ) */
JKQTPPROPERTY(bool, autoAxisSpacing);
JKQTPPROPERTY(bool, autoAxisSpacing)
/** \brief if \c true, the plotter displays minor axis labels as number between 1 and 10 in some cases */
JKQTPPROPERTY(bool, minorTickLabelsEnabled);
JKQTPPROPERTY(bool, minorTickLabelsEnabled)
/** \brief indicates whether the y axis has a logarithmic scale */
JKQTPPROPERTY(bool, logAxis);
JKQTPPROPERTY(bool, logAxis)
/** \brief the base for a logarithmic x axis */
JKQTPPROPERTY(double, logAxisBase);
JKQTPPROPERTY(double, logAxisBase)
/** \brief if autoXAxisSpacing is \c false then this value is used for xTickSpacing. So this is the property which
* is editable by use of public access methods.
*/
JKQTPPROPERTY(double, userTickSpacing);
JKQTPPROPERTY(double, userTickSpacing)
/** \brief if autoXAxisSpacing is \c false then this value is used for xTickSpacing. So this is the property which
* is editable by use of public access methods.
*/
JKQTPPROPERTY(double, userLogTickSpacing);
JKQTPPROPERTY(double, userLogTickSpacing)
/** \brief indicates how to draw the labels */
JKQTPPROPERTY(JKQTPCAlabelType, labelType);
JKQTPPROPERTY(JKQTPCAlabelType, labelType)
/** \brief mode of the major ticks */
JKQTPPROPERTY(JKQTPLabelTickMode, tickMode);
JKQTPPROPERTY(JKQTPLabelTickMode, tickMode)
/** \brief axis label of the axis */
QString axisLabel;
/** \brief position of the axis label */
JKQTPPROPERTY(JKQTPlabelPosition, labelPosition);
JKQTPPROPERTY(JKQTPlabelPosition, labelPosition)
/** \brief font of the axis labels */
JKQTPPROPERTY(QString, labelFont);
JKQTPPROPERTY(QString, labelFont)
/** \brief fontsize of the axis labels */
JKQTPPROPERTY(double, labelFontSize);
JKQTPPROPERTY(double, labelFontSize)
/** \brief font of the axis tick labels */
JKQTPPROPERTY(QString, tickLabelFont);
JKQTPPROPERTY(QString, tickLabelFont)
/** \brief fontsize of the axis tick labels */
JKQTPPROPERTY(double, tickLabelFontSize);
JKQTPPROPERTY(double, tickLabelFontSize)
/** \brief fontsize of the minor axis tick labels */
JKQTPPROPERTY(double, minorTickLabelFontSize);
JKQTPPROPERTY(double, minorTickLabelFontSize)
/** \brief indicates whether to draw a thick axis line at x=0 (zero axis) */
JKQTPPROPERTY(bool, showZeroAxis);
JKQTPPROPERTY(bool, showZeroAxis)
/** \brief indicates whether the minor tick labels should be full numbers, or just a number between 0..10 */
JKQTPPROPERTY(bool, minorTickLabelFullNumber);
JKQTPPROPERTY(bool, minorTickLabelFullNumber)
/** \brief draw mode of the main (left/bottom) axis */
JKQTPPROPERTY(JKQTPCAdrawMode, drawMode1);
JKQTPPROPERTY(JKQTPCAdrawMode, drawMode1)
/** \brief draw mode of the secondary (right/top) axis */
JKQTPPROPERTY(JKQTPCAdrawMode, drawMode2);
JKQTPPROPERTY(JKQTPCAdrawMode, drawMode2)
/** \brief line width of minor ticks in pixels */
JKQTPPROPERTY(double, minorTickWidth);
JKQTPPROPERTY(double, minorTickWidth)
/** \brief line width of ticks in pixels */
JKQTPPROPERTY(double, tickWidth);
JKQTPPROPERTY(double, tickWidth)
/** \brief line width of axis in pixels */
JKQTPPROPERTY(double, lineWidth);
JKQTPPROPERTY(double, lineWidth)
/** \brief line width of 0-line in pixels */
JKQTPPROPERTY(double, lineWidthZeroAxis);
JKQTPPROPERTY(double, lineWidthZeroAxis)
/** \brief format string for time tick labels */
JKQTPPROPERTY(QString, tickTimeFormat);
JKQTPPROPERTY(QString, tickTimeFormat)
/** \brief format string for date tick labels */
JKQTPPROPERTY(QString, tickDateFormat);
JKQTPPROPERTY(QString, tickDateFormat)
/** \brief format string for datetime tick labels */
JKQTPPROPERTY(QString, tickDateTimeFormat);
JKQTPPROPERTY(QString, tickDateTimeFormat)
/** \brief calculates the tick spacing for a linear axis that spans \a awidth and that should
* show at least \a minTicks ticks.
@ -916,42 +691,42 @@ class LIB_EXPORT JKQTPcoordinateAxis: public QObject {
int calcLinearUnitDigits();
/** \brief minimum number of axis ticks */
JKQTPPROPERTY(unsigned int, minTicks);
JKQTPPROPERTY(unsigned int, minTicks)
/** \brief number of minor grid lines per axis tick interval */
JKQTPPROPERTY(unsigned int, minorTicks);
JKQTPPROPERTY(unsigned int, minorTicks)
/** \brief length of an axis tick outside the plot border in pt */
JKQTPPROPERTY(double, tickOutsideLength);
JKQTPPROPERTY(double, tickOutsideLength)
/** \brief length of a minor axis tick outside the plot border in pt */
JKQTPPROPERTY(double, minorTickOutsideLength);
JKQTPPROPERTY(double, minorTickOutsideLength)
/** \brief length of an axis tick inside the plot border in pt */
JKQTPPROPERTY(double, tickInsideLength);
JKQTPPROPERTY(double, tickInsideLength)
/** \brief length of a minor axis tick inside the plot border in pt */
JKQTPPROPERTY(double, minorTickInsideLength);
JKQTPPROPERTY(double, minorTickInsideLength)
/** \brief color of the axis (labels, ticks, axis itself ...) */
JKQTPPROPERTY(QColor, axisColor);
JKQTPPROPERTY(QColor, axisColor)
/** \brief distance between tick end and label start in pt */
JKQTPPROPERTY(double, tickLabelDistance);
JKQTPPROPERTY(double, tickLabelDistance)
/** \brief distance between tick label and axis label in pt */
JKQTPPROPERTY(double, labelDistance);
JKQTPPROPERTY(double, labelDistance)
/** \brief rotation angle of tick labels [-180..180], i.e. given in degrees, default is 0 (horizontal) */
JKQTPPROPERTY(double, tickLabelAngle);
JKQTPPROPERTY(double, tickLabelAngle)
/** \brief indicates whether to draw the major grid lines */
JKQTPPROPERTY(bool, drawGrid);
JKQTPPROPERTY(bool, drawGrid)
/** \brief indicates whether to draw the minor grid lines */
JKQTPPROPERTY(bool, drawMinorGrid);
JKQTPPROPERTY(bool, drawMinorGrid)
/** \brief color of the grid*/
JKQTPPROPERTY(QColor, gridColor);
JKQTPPROPERTY(QColor, gridColor)
/** \brief color of the minor grid lines */
JKQTPPROPERTY(QColor, minorGridColor);
JKQTPPROPERTY(QColor, minorGridColor)
/** \brief width of the grid lines (in pixel) */
JKQTPPROPERTY(double, gridWidth);
JKQTPPROPERTY(double, gridWidth)
/** \brief line stye of the grid lines */
JKQTPPROPERTY(Qt::PenStyle, gridStyle);
JKQTPPROPERTY(Qt::PenStyle, gridStyle)
/** \brief width of the minor grid lines (in pixel) */
JKQTPPROPERTY(double, minorGridWidth);
JKQTPPROPERTY(double, minorGridWidth)
/** \brief line stye of the minor grid lines */
JKQTPPROPERTY(Qt::PenStyle, minorGridStyle);
JKQTPPROPERTY(Qt::PenStyle, minorGridStyle)
/** \brief axis prefix for storage of parameters */
QString axisPrefix;
@ -1032,35 +807,15 @@ class LIB_EXPORT JKQTPverticalIndependentAxis: public JKQTPverticalAxis {
/** \brief class constructor */
JKQTPverticalIndependentAxis(double axisOffset, double axisWidth, double otherAxisOffset, double otherAxisWidth, JKQtBasePlotter* parent);
/** \brief set the axis offset */
inline virtual void set_axisOffset(double __value) {
this->axisOffset = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_axisOffset(double __value);
/** \brief set the axis width */
inline virtual void set_axisWidth(double __value) {
this->axisWidth = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_axisWidth(double __value);
/** \brief set the other axis offset */
inline virtual void set_otherAxisOffset(double __value) {
this->otherAxisOffset = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_otherAxisOffset(double __value);
/** \brief set the other axis width */
inline virtual void set_otherAxisWidth(double __value) {
this->otherAxisWidth = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_otherAxisWidth(double __value);
/** \brief set the other axis width */
inline virtual void set_otherAxisInverted(bool __value) {
this->otherAxisInverted = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_otherAxisInverted(bool __value);
protected:
/** \brief width of the plot in the direction of the axis */
virtual double get_parent_plotwidth() const { return axisWidth; }
@ -1134,44 +889,24 @@ class LIB_EXPORT JKQTPhorizontalIndependentAxis: public JKQTPhorizontalAxis {
/** \brief class constructor */
JKQTPhorizontalIndependentAxis(double axisOffset, double axisWidth, double otherAxisOffset, double otherAxisWidth, JKQtBasePlotter* parent);
/** \brief se the axis offset */
inline virtual void set_axisOffset(double __value) {
this->axisOffset = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_axisOffset(double __value);
/** \brief se the axis width */
inline virtual void set_axisWidth(double __value) {
this->axisWidth = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_axisWidth(double __value);
/** \brief set the other axis offset */
inline virtual void set_otherAxisOffset(double __value) {
this->otherAxisOffset = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_otherAxisOffset(double __value);
/** \brief set the other axis width */
inline virtual void set_otherAxisWidth(double __value) {
this->otherAxisWidth = __value;
this->paramsChanged=true;
update_plot();
};
inline virtual void set_otherAxisInverted(bool __value) {
this->otherAxisInverted = __value;
this->paramsChanged=true;
update_plot();
};
virtual void set_otherAxisWidth(double __value);
virtual void set_otherAxisInverted(bool __value);
protected:
/** \brief width of the plot in the direction of the axis */
virtual double get_parent_plotwidth() const { return axisWidth; }
virtual double get_parent_plotwidth() const;
/** \brief offset of the plot in the direction of the axis */
virtual double get_parent_plotoffset() const { return axisOffset; }
virtual double get_parent_plotoffset() const;
/** \brief pixel of other (perpendicular) axis (needed for grids) */
virtual double get_parent_otheraxis_width() const { return otherAxisWidth; }
virtual bool get_parent_otheraxis_inverted() const { return otherAxisInverted; }
virtual double get_parent_otheraxis_width() const;
virtual bool get_parent_otheraxis_inverted() const;
/** \brief pixel offset of (perpendicular) other axis (needed for grids) */
virtual double get_parent_otheraxis_offset() const { return otherAxisOffset; }
virtual double get_parent_otheraxis_offset() const;
double axisOffset;
double axisWidth;

1104
jkqtpbasegraphs.cpp Normal file

File diff suppressed because it is too large Load Diff

576
jkqtpbasegraphs.h Normal file
View File

@ -0,0 +1,576 @@
/*
Copyright (c) 2008-2018 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 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/>.
*/
/**
* \defgroup jkqtplotter_elements Plot Elements
* \ingroup jkqtplotter
* \defgroup jkqtplotter_plots Graphs
* \ingroup jkqtplotter_elements
*/
/** \file jkqtpelements.h
* \ingroup jkqtplotter
*/
#include <QString>
#include <QPainter>
#include <QPair>
#include "jkqtptools.h"
#include "jkqtp_imexport.h"
#include "jkqtpimagetools.h"
#ifndef JKQTPBASEGRAPHS_H
#define JKQTPBASEGRAPHS_H
// forward declarations
class JKQtBasePlotter;
class JKQtPlotter;
class JKQTPcoordinateAxis;
class JKQTPdatastore;
//class JKQTPColorPaletteTools;
/** \brief this virtual base class describes one of the graphs, which are part of a JKQtPlotter object
* \ingroup jkqtplotter_plots
*
* Each possible graph is represented by a subgraph of this. So additional plots may be created by
* deriving new JKQTPgraph classes. To do so implement/overwrite these functions:
* - void draw(JKQTPEnhancedPainter& painter);
* - void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect);
* - bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero);
* - void getGraphsYMinMax(double& miny, double& maxy);
* - QColor getKeyLabelColor()=0;
* .
*
* There are two properties datarange_start and datarange_end. By default they are -1 and therefore ignored.
* if they are != -1 the plotter only displays the datapoints with the indexes [datarange_start .. datarange_end]
* although there might be more data points available (range [0 .. maxDataPoints]). The datarange is cut at the
* full range, i.e. if datarange_end>maxDataPoints the plotter displays [datarange_start .. maxDataPoints].
*/
class LIB_EXPORT JKQTPgraph: public QObject {
Q_OBJECT
public:
/** \brief class constructor */
explicit JKQTPgraph(JKQtBasePlotter* parent=nullptr);
/** \brief class constructor */
explicit JKQTPgraph(JKQtPlotter* parent);
/** \brief default wirtual destructor */
virtual ~JKQTPgraph() ;
/** \brief plots the graph to the plotter object specified as parent */
virtual void draw(JKQTPEnhancedPainter& painter)=0;
/** \brief plots a key marker inside the specified rectangle \a rect */
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect)=0;
/** \brief returns an image with a key marker inside */
QImage generateKeyMarker(QSize size=QSize(16,16));
/** \brief get the maximum and minimum x-value of the graph
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero)=0;
/** \brief get the maximum and minimum y-value of the graph
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero)=0;
/** \brief returns the color to be used for the key label */
virtual QColor getKeyLabelColor()=0;
JKQTPGET_SET_VMACRO(QString, title)
JKQTPGET_SET_MACRO(long long, datarange_start)
JKQTPGET_SET_MACRO(long long, datarange_end)
JKQTPGET_SET_MACRO(bool, visible)
/** \brief returns the parent painter class */
inline JKQtBasePlotter* getParent() { return parent; }
/** \brief sets the parent painter class */
virtual void setParent(JKQtBasePlotter* parent);
/** \brief sets the parent painter class */
virtual void setParent(JKQtPlotter* parent);
/*! \brief if the graph plots outside the actual plot field of view (e.g. color bars, scale bars, ...)
\note If you want to draw outside, then you'll also have to implement drawOutside()
*/
virtual void getOutsideSize(JKQTPEnhancedPainter& painter, int& leftSpace, int& rightSpace, int& topSpace, int& bottomSpace);
/*! \brief plots outside the actual plot field of view (e.g. color bars, scale bars, ...)
\note If you want to draw outside, then you'll also have to implement getOutsideSize(), so enough space is reserved
The four value supplied tell the method where to draw (inside one of the rectangles).
*/
virtual void drawOutside(JKQTPEnhancedPainter& painter, QRect leftSpace, QRect rightSpace, QRect topSpace, QRect bottomSpace);
/** \brief returns \c true if the given column is used by the graph */
virtual bool usesColumn(int column);
protected:
/** \brief the plotter object this object belongs to */
JKQtBasePlotter* parent;
/** \brief this function is used to plot error inidcators before plotting the graphs.
*
* By default this function does nothing. But children of this class may overwrite it to implement
* drawing error indicators.
*/
virtual void drawErrorsBefore(JKQTPEnhancedPainter& /*painter*/);
/** \brief this function is used to plot error inidcators after plotting the graphs.
*
* By default this function does nothing. But children of this class may overwrite it to implement
* drawing error indicators.
*/
virtual void drawErrorsAfter(JKQTPEnhancedPainter& /*painter*/);
/** \brief tool routine that transforms a QPointF according to the parent's transformation rules */
QPointF transform(const QPointF& x);
/** \brief tool routine that back-transforms a QPointF according to the parent's transformation rules */
QPointF backTransform(const QPointF& x);
/** \brief tool routine that transforms a QPointF according to the parent's transformation rules */
inline QPointF transform(double x, double y) {
return transform(QPointF(x,y));
}
/** \brief tool routine that back-transforms a QPointF according to the parent's transformation rules */
inline QPointF backTransform(double x, double y) {
return backTransform(QPointF(x,y));
}
/** \brief tool routine that transforms a QVector<QPointF> according to the parent's transformation rules */
QVector<QPointF> transform(const QVector<QPointF>& x);
/** \brief tool routine that transforms a QVector<QPointF> according to the parent's transformation rules
* and returns a (non-closed) path consisting of lines */
QPainterPath transformToLinePath(const QVector<QPointF>& x);
/** \brief tool routine that transforms a QVector<QPointF> according to the parent's transformation rules
* and returns a polygon */
inline QPolygonF transformToPolygon(const QVector<QPointF>& x) {
return QPolygonF(transform(x));
}
/** \brief title of the plot (for display in key!). If no title is supplied, no key entry is drawn. */
QString title;
/** \brief start of the range of plot data. -1 switches the lower data range border off. */
long long datarange_start;
/** \brief end of the range of plot data. -1 switches the upper data range border off. */
long long datarange_end;
/** \brief indicates whether the graph is visible in the plot */
bool visible;
/** \brief get the maximum and minimum value of the given column
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
bool getDataMinMax(int column, double& minx, double& maxx, double& smallestGreaterZero);
JKQTPcoordinateAxis* xAxis;
JKQTPcoordinateAxis* yAxis;
};
/*! \brief This virtual JKQTPgraph descendent may be used as base for all graphs that use at least two columns
that specify x and y coordinates for the single plot points.
\ingroup jkqtplotter_plots
This class implements basic management facilities for the data columns and implements the function
- bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero);
- bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero);
.
*/
class LIB_EXPORT JKQTPxyGraph: public JKQTPgraph {
Q_OBJECT
public:
enum DataSortOrder {
Unsorted=0,
SortedX=1,
SortedY=2
};
/** \brief class constructor */
JKQTPxyGraph(JKQtBasePlotter* parent=nullptr);
/** \brief class constructor */
JKQTPxyGraph(JKQtPlotter* parent);
/** \brief get the maximum and minimum x-value of the graph
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero);
/** \brief get the maximum and minimum y-value of the graph
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero);
/** \copydoc JKQTPgraph::usesColumn() */
virtual bool usesColumn(int column);
JKQTPGET_SET_MACRO(int, xColumn)
JKQTPSET_CAST_MACRO(size_t, int, xColumn)
JKQTPGET_SET_MACRO(int, yColumn)
JKQTPSET_CAST_MACRO(size_t, int, yColumn)
JKQTPGET_SET_MACRO(DataSortOrder, sortData)
/** \brief sets the property sortData to the specified \a __value. \details Description of the parameter sortData is: <CENTER>\copybrief sortData.</CENTER> \see sortData for more information */
inline void set_sortData(int __value) {
sortData=(DataSortOrder)__value;
}
protected:
/** \brief the column that contains the x-component of the datapoints */
int xColumn;
/** \brief the column that contains the y-component of the datapoints */
int yColumn;
/** \brief if \c !=Unsorted, the data is sorted before plotting */
DataSortOrder sortData;
/** \brief this array contains the order of indices, in which to access the data in the data columns */
QVector<int> sortedIndices;
virtual void intSortData();
inline int getDataIndex(int i) {
if (sortData==Unsorted) return i;
return sortedIndices.value(i,i);
}
};
/*! \brief This virtual JKQTPgraph descendent may be used as base for all graphs that use at least one column
of data
\ingroup jkqtplotter_plots
*/
class LIB_EXPORT JKQTPsingleColumnGraph: public JKQTPgraph {
Q_OBJECT
public:
enum DataSortOrder {
Unsorted=0,
Sorted=1
};
/** \brief class constructor */
JKQTPsingleColumnGraph(JKQtBasePlotter* parent=nullptr);
JKQTPsingleColumnGraph(int dataColumn, JKQtBasePlotter* parent=nullptr);
JKQTPsingleColumnGraph(int dataColumn, QColor color, Qt::PenStyle style=Qt::SolidLine, double lineWidth=2.0, JKQtBasePlotter* parent=nullptr);
JKQTPsingleColumnGraph(JKQtPlotter* parent);
JKQTPsingleColumnGraph(int dataColumn, JKQtPlotter* parent);
JKQTPsingleColumnGraph(int dataColumn, QColor color, Qt::PenStyle style, double lineWidth, JKQtPlotter* parent);
JKQTPsingleColumnGraph(int dataColumn, QColor color, Qt::PenStyle style, JKQtPlotter* parent);
JKQTPsingleColumnGraph(int dataColumn, QColor color, JKQtPlotter* parent);
/** \brief returns the color to be used for the key label */
virtual QColor getKeyLabelColor();
JKQTPGET_SET_MACRO(int, dataColumn)
JKQTPSET_CAST_MACRO(size_t, int, dataColumn)
JKQTPGET_SET_MACRO(QColor, color)
JKQTPGET_SET_MACRO(Qt::PenStyle, style)
JKQTPGET_SET_MACRO(double, lineWidth)
JKQTPGET_SET_MACRO(DataSortOrder, sortData)
/** \brief sets the property sortData to the specified \a __value. \details Description of the parameter sortData is: <CENTER>\copybrief sortData.</CENTER> \see sortData for more information */
inline void set_sortData(int __value) {
sortData=(DataSortOrder)__value;
if (__value>0) sortData=Sorted;
}
/** \copydoc JKQTPgraph::usesColumn() */
virtual bool usesColumn(int c);
protected:
/** \brief the column that contains the datapoints */
int dataColumn;
/** \brief which plot style to use from the parent plotter (via JKQtPlotterBase::getPlotStyle() and JKQtPlotterBase::getNextStyle() ) */
int parentPlotStyle;
/** \brief color of the graph */
QColor color;
/** \brief linestyle of the graph lines */
Qt::PenStyle style;
/** \brief width (pixels) of the graph */
double lineWidth;
QPen getLinePen(JKQTPEnhancedPainter &painter) const;
/** \brief if \c !=Unsorted, the data is sorted before plotting */
DataSortOrder sortData;
/** \brief this array contains the order of indices, in which to access the data in the data columns */
QVector<int> sortedIndices;
virtual void intSortData();
inline int getDataIndex(int i) {
if (sortData==Unsorted) return i;
return sortedIndices.value(i,i);
}
};
/*! \brief Descendents of this class add data fields for error indicators and methods to plot them to a class.
\ingroup jkqtplotter_plots
This class is meant to be used with multiple inheritance. I.e. if you implemented some kind of plot
you may derive an error plot class in which you will have to overwrite the JKQTPgraph::drawErrorsBefor()
or drawErrorsAfter() so it calls the plotErrorIndicators() method from this class. In addition this class
will add some public datamemebers and methods to your class that allow to specify the properties of the
error indicators (plot properties: color, width, ... and columns for the data).
*/
class LIB_EXPORT JKQTPgraphErrors {
public:
/** \brief class contructor */
JKQTPgraphErrors(QColor graphColor=QColor("black"));
JKQTPGET_SET_MACRO(QColor, errorColor)
JKQTPGET_SET_MACRO(Qt::PenStyle, errorStyle)
JKQTPGET_SET_MACRO(double, errorWidth)
JKQTPGET_SET_MACRO(QColor, errorFillColor)
JKQTPGET_SET_MACRO(Qt::BrushStyle, errorFillStyle)
JKQTPGET_SET_MACRO(double, errorbarSize)
/** \brief returns true, if the error plots use the given column */
virtual bool errorUsesColumn(int c);
void setErrorColorFromGraphColor(QColor graphColor);
protected:
/** \brief color of the error lines/bars */
QColor errorColor;
/** \brief linestyle of the error lines/bars */
Qt::PenStyle errorStyle;
/** \brief width (pixels) of the error lines/bars */
double errorWidth;
/** \brief fill color for error polygons */
QColor errorFillColor;
/** \brief fill style for error polygons */
Qt::BrushStyle errorFillStyle;
/** \brief size of the error bar end markers [pixels] */
double errorbarSize;
/** \brief draw error indicators with the parameters defined in this class. The position of the datapoints is
* given by the \a xColumn and \a yColumn. It is also possible to specify a datarange. This method is called by
* the JKQTPgraph descendents */
virtual void plotErrorIndicators(JKQTPEnhancedPainter& painter, JKQtBasePlotter* parent, JKQTPcoordinateAxis* xAxis, JKQTPcoordinateAxis* yAxis, int xColumn, int yColumn, long long datarange_start=-1, long long datarange_end=-1, double xrelshift=0, double yrelshift=0.0, const QVector<int>* dataorder=nullptr)=0;
/** \brief draw error indicators with the parameters defined in this class. The position of the datapoints is
* given by the \a xColumn and \a yColumn. It is also possible to specify a datarange. */
void intPlotXYErrorIndicators(JKQTPEnhancedPainter& painter, JKQtBasePlotter* parent, JKQTPcoordinateAxis* xAxis, JKQTPcoordinateAxis* yAxis, int xColumn, int yColumn, int xErrorColumn, int yErrorColumn, JKQTPerrorPlotstyle xErrorStyle, JKQTPerrorPlotstyle yErrorStyle, long long datarange_start=-1, long long datarange_end=-1, int xErrorColumnLower=-1, int yErrorColumnLower=-1, bool xErrorSymmetric=true, bool yErrorSymmetric=true, double xrelshift=0, double yrelshift=0.0, const QVector<int> *dataorder=nullptr);
/** \brief this function can be used to set the color of the error indicators automatically
*
* return \c true and the colors to use, if applicable, the default implementation returns false */
virtual bool intPlotXYErrorIndicatorsGetColor(JKQTPEnhancedPainter& painter, JKQtBasePlotter* parent, JKQTPcoordinateAxis* xAxis, JKQTPcoordinateAxis* yAxis, int xColumn, int yColumn, int xErrorColumn, int yErrorColumn, JKQTPerrorPlotstyle xErrorStyle, JKQTPerrorPlotstyle yErrorStyle, long long index, QColor& errorColor, QColor& errorFillColor);
virtual double getXErrorU(int i, JKQTPdatastore* ds) const;
virtual double getXErrorL(int i, JKQTPdatastore* ds) const;
virtual double getYErrorU(int i, JKQTPdatastore* ds) const;
virtual double getYErrorL(int i, JKQTPdatastore* ds) const;
//** \brief plot a single error indicator */
//void intPlotXYErrorIndicator(JKQTPEnhancedPainter& painter, double x, double xperror, double xmerror, double y, double yperror, double ymerror, JKQTPerrorPlotstyle xErrorStyle=JKQTPnoError, JKQTPerrorPlotstyle yErrorStyle=JKQTPnoError, double lastx=0, double lastxperror=0, double lastxmerror=0, double lasty=0, double lastyperror=0, double lastymerror=0);
};
/*! \brief This class adds data fields for error indicators in x direction to a JKQTPgraph descendent.
\ingroup jkqtplotter_plots
\see JKQTPgraphErrors
*/
class LIB_EXPORT JKQTPxGraphErrors: public JKQTPgraphErrors {
public:
/** \brief class contructor */
JKQTPxGraphErrors(QColor graphColor=QColor("black"));
JKQTPGET_SET_MACRO(bool, xErrorSymmetric)
JKQTPGET_MACRO(int, xErrorColumnLower)
JKQTPGET_MACRO(int, xErrorColumn)
JKQTPGET_SET_MACRO(JKQTPerrorPlotstyle, xErrorStyle)
inline void set_xErrorColumn(int __value) {
if (this->xErrorColumn != __value) { \
this->xErrorColumn = __value; \
if (xErrorColumn>=0 && xErrorStyle==JKQTPnoError) xErrorStyle=JKQTPerrorBars; \
} \
}
inline void set_xErrorColumnLower(int __value) {
if (this->xErrorColumnLower != __value) { \
this->xErrorColumnLower = __value; \
if (xErrorColumnLower>=0 && xErrorStyle==JKQTPnoError) xErrorStyle=JKQTPerrorBars; \
} \
}
/** \brief returns true, if the error plots use the given column */
virtual bool errorUsesColumn(int c);
protected:
/** \brief the column that contains the error of the x-component of the datapoints */
int xErrorColumn;
/** \brief the column that contains the error of the x-component of the datapoints. This is used as the lower error length, if xErrorSymmetric \c ==false. */
int xErrorColumnLower;
/** \brief indicates whether the x-errors are symmetric (from one column only) */
bool xErrorSymmetric;
/** \brief how to draw the errors (if available) of the x-value */
JKQTPerrorPlotstyle xErrorStyle;
/** \brief draw error indicators with the parameters defined in this class. The position of the datapoints is
* given by the \a xColumn and \a yColumn. It is also possible to specify a datarange. */
virtual void plotErrorIndicators(JKQTPEnhancedPainter& painter, JKQtBasePlotter* parent, JKQTPcoordinateAxis* xAxis, JKQTPcoordinateAxis* yAxis, int xColumn, int yColumn, long long datarange_start=-1, long long datarange_end=-1, double xrelshift=0, double yrelshift=0.0, const QVector<int> *dataorder=nullptr);
virtual double getXErrorU(int i, JKQTPdatastore* ds) const;
virtual double getXErrorL(int i, JKQTPdatastore* ds) const;
};
/*! \brief This class adds data fields for error indicators in y direction to a class.
\ingroup jkqtplotter_plots
\see JKQTPgraphErrors
*/
class LIB_EXPORT JKQTPyGraphErrors: public JKQTPgraphErrors {
public:
/** \brief class contructor */
JKQTPyGraphErrors(QColor graphColor=QColor("black"));
JKQTPGET_SET_MACRO(bool, yErrorSymmetric)
JKQTPGET_MACRO(int, yErrorColumnLower)
JKQTPGET_MACRO(int, yErrorColumn)
JKQTPGET_SET_MACRO(JKQTPerrorPlotstyle, yErrorStyle)
/** \copydoc JKQTPgraphErrors::errorUsesColumn() */
virtual bool errorUsesColumn(int c);
inline void set_yErrorColumn(int __value) {
if (this->yErrorColumn != __value) { \
this->yErrorColumn = __value; \
if (yErrorColumn>=0 && yErrorStyle==JKQTPnoError) yErrorStyle=JKQTPerrorBars; \
} \
}
inline void set_yErrorColumnLower(int __value) {
if (this->yErrorColumnLower != __value) { \
this->yErrorColumnLower = __value; \
if (yErrorColumnLower>=0 && yErrorStyle==JKQTPnoError) yErrorStyle=JKQTPerrorBars; \
} \
}
protected:
/** \brief the column that contains the error of the x-component of the datapoints */
int yErrorColumn;
/** \brief how to draw the errors (if available) of the x-value */
JKQTPerrorPlotstyle yErrorStyle;
/** \brief indicates whether the y-errors are symmetric (from one column only) */
bool yErrorSymmetric;
/** \brief the column that contains the error of the y-component of the datapoints. This is used as the lower error length, if yErrorSymmetric \c ==false. */
int yErrorColumnLower;
/** \brief draw error indicators with the parameters defined in this class. The position of the datapoints is
* given by the \a xColumn and \a yColumn. It is also possible to specify a datarange. */
virtual void plotErrorIndicators(JKQTPEnhancedPainter& painter, JKQtBasePlotter* parent, JKQTPcoordinateAxis* xAxis, JKQTPcoordinateAxis* yAxis, int xColumn, int yColumn, long long datarange_start=-1, long long datarange_end=-1, double xrelshift=0, double yrelshift=0.0, const QVector<int> *dataorder=nullptr);
virtual double getYErrorU(int i, JKQTPdatastore* ds) const;
virtual double getYErrorL(int i, JKQTPdatastore* ds) const;
};
/*! \brief This class adds data fields for error indicators in x and y direction to a class.
\ingroup jkqtplotter_plots
\see JKQTPgraphErrors
*/
class LIB_EXPORT JKQTPxyGraphErrors: public JKQTPgraphErrors {
public:
/** \brief class contructor */
JKQTPxyGraphErrors(QColor graphColor=QColor("black"));
JKQTPGET_SET_MACRO(bool, xErrorSymmetric)
JKQTPGET_SET_MACRO(bool, yErrorSymmetric)
JKQTPGET_MACRO(int, xErrorColumnLower)
JKQTPGET_MACRO(int, xErrorColumn)
JKQTPGET_MACRO(int, yErrorColumnLower)
JKQTPGET_MACRO(int, yErrorColumn)
JKQTPGET_SET_MACRO(JKQTPerrorPlotstyle, yErrorStyle)
JKQTPGET_SET_MACRO(JKQTPerrorPlotstyle, xErrorStyle)
/** \copydoc JKQTPgraphErrors::errorUsesColumn() */
virtual bool errorUsesColumn(int c);
inline void set_xErrorColumn(int __value) {
if (this->xErrorColumn != __value) { \
this->xErrorColumn = __value; \
if (xErrorColumn>=0 && xErrorStyle==JKQTPnoError) xErrorStyle=JKQTPerrorBars; \
} \
}
inline void set_xErrorColumnLower(int __value) {
if (this->xErrorColumnLower != __value) { \
this->xErrorColumnLower = __value; \
if (xErrorColumnLower>=0 && xErrorStyle==JKQTPnoError) xErrorStyle=JKQTPerrorBars; \
} \
}
inline void set_yErrorColumn(int __value) {
if (this->yErrorColumn != __value) { \
this->yErrorColumn = __value; \
if (yErrorColumn>=0 && yErrorStyle==JKQTPnoError) yErrorStyle=JKQTPerrorBars; \
} \
}
inline void set_yErrorColumnLower(int __value) {
if (this->yErrorColumnLower != __value) { \
this->yErrorColumnLower = __value; \
if (yErrorColumnLower>=0 && yErrorStyle==JKQTPnoError) yErrorStyle=JKQTPerrorBars; \
} \
}
protected:
/** \brief the column that contains the error of the x-component of the datapoints */
int yErrorColumn;
/** \brief how to draw the errors (if available) of the x-value */
JKQTPerrorPlotstyle yErrorStyle;
/** \brief the column that contains the error of the x-component of the datapoints */
int xErrorColumn;
/** \brief how to draw the errors (if available) of the x-value */
JKQTPerrorPlotstyle xErrorStyle;
/** \brief indicates whether the x-errors are symmetric (from one column only) */
bool xErrorSymmetric;
/** \brief indicates whether the y-errors are symmetric (from one column only) */
bool yErrorSymmetric;
/** \brief the column that contains the error of the x-component of the datapoints. This is used as the lower error length, if xErrorSymmetric \c ==false. */
int xErrorColumnLower;
/** \brief the column that contains the error of the y-component of the datapoints. This is used as the lower error length, if yErrorSymmetric \c ==false. */
int yErrorColumnLower;
/** \brief draw error indicators with the parameters defined in this class. The position of the datapoints is
* given by the \a xColumn and \a yColumn. It is also possible to specify a datarange. */
virtual void plotErrorIndicators(JKQTPEnhancedPainter& painter, JKQtBasePlotter* parent, JKQTPcoordinateAxis* xAxis, JKQTPcoordinateAxis* yAxis, int xColumn, int yColumn, long long datarange_start=-1, long long datarange_end=-1, double xrelshift=0, double yrelshift=0.0, const QVector<int> *dataorder=nullptr);
virtual double getXErrorU(int i, JKQTPdatastore* ds) const;
virtual double getXErrorL(int i, JKQTPdatastore* ds) const;
virtual double getYErrorU(int i, JKQTPdatastore* ds) const;
virtual double getYErrorL(int i, JKQTPdatastore* ds) const;
};
#endif // JKQTPBASEGRAPHS_H

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center
@ -49,6 +49,8 @@
#ifdef QFWIDLIB_LIBRARY
# include "qftools.h"
#endif
#include "jkqtpboxplotelements.h"
#include "jkqtpbarchartelements.h"
static QString globalUserSettigsFilename="";
static QString globalUserSettigsPrefix="";
@ -639,8 +641,8 @@ void JKQtBasePlotter::loadSettings(QSettings& settings, QString group){
keyFont=settings.value(g+"key_fontname", keyFont).toString();
keyFontSize=settings.value(g+"key_fontsize", keyFontSize).toInt();
key_item_width=settings.value(g+"key_item_width", key_item_width).toInt();
key_item_height=settings.value(g+"key_item_height", key_item_height).toInt();;
key_line_length=settings.value(g+"key_line_width", key_line_length).toInt();;
key_item_height=settings.value(g+"key_item_height", key_item_height).toInt();
key_line_length=settings.value(g+"key_line_width", key_line_length).toInt();
keyAutosize=settings.value(g+"key_autosize", keyAutosize).toBool();
plotLabelFontname=settings.value(g+"plotLabelFontname", plotLabelFontname).toString();
@ -3307,7 +3309,7 @@ void JKQtBasePlotter::addHorizontalBargraph(size_t xColumn, QVector<size_t> yCol
double width=w/(double)yColumns.size();
double s=-1.0*w/2.0+width/2.0;
for (int i=0; i<yColumns.size(); i++) {
JKQTPbarHorizontalGraph* g=new JKQTPbarHorizontalGraph(this);
JKQTPbarVerticalGraph* g=new JKQTPbarVerticalGraph(this);
g->set_title(titles[i]);
g->set_xColumn(xColumn);
g->set_yColumn(yColumns[i]);
@ -3324,7 +3326,7 @@ void JKQtBasePlotter::addVerticalBargraph(QVector<size_t> xColumns, size_t yColu
double width=w/(double)xColumns.size();
double s=-1.0*w/2.0+width/2.0;
for (int i=0; i<xColumns.size(); i++) {
JKQTPbarVerticalGraph* g=new JKQTPbarVerticalGraph(this);
JKQTPbarHorizontalGraph* g=new JKQTPbarHorizontalGraph(this);
g->set_title(titles[i]);
g->set_xColumn(xColumns[i]);
g->set_yColumn(yColumn);
@ -4176,11 +4178,6 @@ bool JKQtBasePlotter::containsGraph(JKQTPgraph* gr) const {
return false;
};
void JKQtBasePlotter::addGraphs(const QList<JKQTPgraph *> &gr) {
for (int i=0; i< gr.size(); i++) {
addGraph(gr[i]);
}
};
void JKQtBasePlotter::setGraphsDataRange(long long datarange_start, long long datarange_end) {
for (int i=0; i<graphs.size(); i++) {

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)
@ -1141,7 +1141,12 @@ class LIB_EXPORT JKQtBasePlotter: public QObject {
size_t moveGraphBottom(JKQTPgraph* gr);
/** \brief add a new graphs from a QVector */
void addGraphs(const QList<JKQTPgraph*>& gr);
template <class TJKQTPgraphContainer>
inline void addGraphs(const TJKQTPgraphContainer& gr) {
for (auto it=gr.begin(); it!=gr.end(); ++it) {
addGraph(*it);
}
}
/** \brief add a new graph, returns it's position in the graphs list.
*

1226
jkqtpboxplotelements.cpp Normal file

File diff suppressed because it is too large Load Diff

371
jkqtpboxplotelements.h Normal file
View File

@ -0,0 +1,371 @@
/*
Copyright (c) 2008-2018 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 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/>.
*/
/**
* \defgroup jkqtplotter_elements Plot Elements
* \ingroup jkqtplotter
* \defgroup jkqtplotter_plots Graphs
* \ingroup jkqtplotter_elements
*/
/** \file jkqtpelements.h
* \ingroup jkqtplotter
*/
#include <QString>
#include <QPainter>
#include <QPair>
#include "jkqtptools.h"
#include "jkqtp_imexport.h"
#include "jkqtpimagetools.h"
#include "jkqtpbasegraphs.h"
#ifndef JKQTPBOXPLOTELEMENTS_H
#define JKQTPBOXPLOTELEMENTS_H
/*! \brief This implements vertical <a href="http://en.wikipedia.org/wiki/Box_plot">boxplots</a>
\ingroup jkqtplotter_plots
the x position is given in posColumn. All other data are given in the medianColumn, minColumn, maxColumn,
percentile25Column and percentile75Column.
\image html plot_boxplotvertical.png
*/
class LIB_EXPORT JKQTPboxplotVerticalGraph: public JKQTPgraph {
Q_OBJECT
public:
enum DataSortOrder {
Unsorted=0,
Sorted=1
};
/** \brief class constructor */
JKQTPboxplotVerticalGraph(JKQtBasePlotter* parent=nullptr);
/** \brief class constructor */
JKQTPboxplotVerticalGraph(JKQtPlotter* parent);
/** \brief plots the graph to the plotter object specified as parent */
virtual void draw(JKQTPEnhancedPainter& painter);
/** \brief plots a key marker inside the specified rectangle \a rect */
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect);
/** \brief returns the color to be used for the key label */
virtual QColor getKeyLabelColor();
/** \brief get the maximum and minimum x-value of the graph
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero);
/** \brief get the maximum and minimum y-value of the graph
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero);
/** \copydoc JKQTPgraph::usesColumn() */
virtual bool usesColumn(int c);
JKQTPGET_SET_MACRO(DataSortOrder, sortData)
/** \brief sets the property sortData to the specified \a __value. \details Description of the parameter sortData is: <CENTER>\copybrief sortData.</CENTER> \see sortData for more information */
inline void set_sortData(int __value) {
sortData=(DataSortOrder)__value;
if (__value>0) sortData=Sorted;
}
JKQTPGET_SET_MACRO(int, posColumn)
JKQTPSET_CAST_MACRO(size_t, int, posColumn)
JKQTPGET_SET_MACRO(int, medianColumn)
JKQTPSET_CAST_MACRO(size_t, int, medianColumn)
JKQTPGET_SET_MACRO(int, meanColumn)
JKQTPSET_CAST_MACRO(size_t, int, meanColumn)
JKQTPGET_SET_MACRO(int, minColumn)
JKQTPSET_CAST_MACRO(size_t, int, minColumn)
JKQTPGET_SET_MACRO(int, maxColumn)
JKQTPSET_CAST_MACRO(size_t, int, maxColumn)
JKQTPGET_SET_MACRO(int, percentile25Column)
JKQTPSET_CAST_MACRO(size_t, int, percentile25Column)
JKQTPGET_SET_MACRO(int, percentile75Column)
JKQTPSET_CAST_MACRO(size_t, int, percentile75Column)
JKQTPGET_SET_MACRO(QColor, color)
JKQTPGET_SET_MACRO(QColor, fillColor)
JKQTPGET_SET_MACRO(Qt::PenStyle, whiskerStyle)
JKQTPGET_SET_MACRO(Qt::BrushStyle, fillStyle)
JKQTPGET_SET_MACRO(double, lineWidth)
JKQTPGET_SET_MACRO(double, boxWidth)
JKQTPGET_SET_MACRO(JKQTPgraphSymbols, meanSymbol)
JKQTPGET_SET_MACRO(double, meanSymbolWidth)
JKQTPGET_SET_MACRO(double, meanSymbolSize)
protected:
/** \brief which plot style to use from the parent plotter (via JKQtPlotterBase::getPlotStyle() and JKQtPlotterBase::getNextStyle() ) */
int parentPlotStyle;
/** \brief the column that contains the x-component of the datapoints */
int posColumn;
/** \brief the column that contains the median-component of the datapoints */
int medianColumn;
/** \brief the column that contains the median-component of the datapoints. \note This column is strictly optional. */
int meanColumn;
/** \brief the column that contains the minimum-component of the datapoints */
int minColumn;
/** \brief the column that contains the maximum-component of the datapoints */
int maxColumn;
/** \brief the column that contains the 25% percentile-component of the datapoints */
int percentile25Column;
/** \brief the column that contains the 75% percentile-component of the datapoints */
int percentile75Column;
/** \brief color of the lines */
QColor color;
/** \brief color of the box fill */
QColor fillColor;
/** \brief fill style for the box */
Qt::BrushStyle fillStyle;
/** \brief linestyle of the whisker lines */
Qt::PenStyle whiskerStyle;
/** \brief width (pixels) of the graph */
double lineWidth;
/** \brief width of box in percent of distance between the current two posColumn values
* if we only plot one box&whiskers then this is the width in plot coordinates */
double boxWidth;
/** \brief which symbol to use for the mean */
JKQTPgraphSymbols meanSymbol;
/** \brief size (diameter in pixels) of the symbol for the mean */
double meanSymbolSize;
/** \brief width (in pixels) of the lines used to plot the symbol for the mean */
double meanSymbolWidth;
QBrush getBrush(JKQTPEnhancedPainter& painter) const;
QPen getLinePen(JKQTPEnhancedPainter &painter) const;
/** \brief if \c !=Unsorted, the data is sorted before plotting */
DataSortOrder sortData;
/** \brief this array contains the order of indices, in which to access the data in the data columns */
QVector<int> sortedIndices;
virtual void intSortData();
inline int getDataIndex(int i) {
if (sortData==Unsorted) return i;
return sortedIndices.value(i,i);
}
};
/*! \brief This implements horizontal <a href="http://en.wikipedia.org/wiki/Box_plot">boxplots</a>
\ingroup jkqtplotter_plots
the x position is given in posColumn. All other data are given in the medianColumn, minColumn, maxColumn,
percentile25Column and percentile75Column.
\image html plot_boxplothorizontal.png
*/
class LIB_EXPORT JKQTPboxplotHorizontalGraph: public JKQTPboxplotVerticalGraph {
Q_OBJECT
public:
/** \brief class constructor */
inline JKQTPboxplotHorizontalGraph(JKQtBasePlotter* parent=nullptr):
JKQTPboxplotVerticalGraph(parent)
{
}
inline JKQTPboxplotHorizontalGraph(JKQtPlotter* parent):
JKQTPboxplotVerticalGraph(parent)
{
}
/** \brief plots the graph to the plotter object specified as parent */
virtual void draw(JKQTPEnhancedPainter& painter);
/** \brief plots a key marker inside the specified rectangle \a rect */
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect);
/** \brief get the maximum and minimum x-value of the graph
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero);
/** \brief get the maximum and minimum y-value of the graph
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero);
};
/*! \brief This implements a vertical <a href="http://en.wikipedia.org/wiki/Box_plot">boxplot</a> where the data is directly given to the
object and not stored in a column, as in JKQTPboxplotVerticalGraph
\ingroup jkqtplotter_plots
the x position is given in posColumn. All other data are given in the median, min, max,
percentile25 and percentile75.
\image html plot_boxplotvertical.png
*/
class LIB_EXPORT JKQTPboxplotVerticalElement: public JKQTPgraph {
Q_OBJECT
public:
/** \brief class constructor */
JKQTPboxplotVerticalElement(JKQtBasePlotter* parent=nullptr);
/** \brief class constructor */
JKQTPboxplotVerticalElement(JKQtPlotter* parent);
/** \brief plots the graph to the plotter object specified as parent */
virtual void draw(JKQTPEnhancedPainter& painter);
/** \brief plots a key marker inside the specified rectangle \a rect */
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect);
/** \brief returns the color to be used for the key label */
virtual QColor getKeyLabelColor();
/** \brief get the maximum and minimum x-value of the graph
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero);
/** \brief get the maximum and minimum y-value of the graph
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero);
JKQTPGET_SET_MACRO(double, pos)
JKQTPGET_SET_MACRO_I(double, median, drawMedian=true)
JKQTPGET_SET_MACRO_I(double, mean, drawMean=true)
JKQTPGET_SET_MACRO_I(double, min, drawMinMax=true)
JKQTPGET_SET_MACRO_I(double, max, drawMinMax=true)
JKQTPGET_SET_MACRO(double, percentile25)
JKQTPGET_SET_MACRO(double, percentile75)
JKQTPGET_SET_MACRO(QColor, color)
JKQTPGET_SET_MACRO(QColor, fillColor)
JKQTPGET_SET_MACRO(Qt::PenStyle, whiskerStyle)
JKQTPGET_SET_MACRO(double, lineWidth)
JKQTPGET_SET_MACRO(double, boxWidth)
JKQTPGET_SET_MACRO(JKQTPgraphSymbols, meanSymbol)
JKQTPGET_SET_MACRO(double, meanSymbolWidth)
JKQTPGET_SET_MACRO(double, meanSymbolSize)
JKQTPGET_SET_MACRO(bool, drawMean)
JKQTPGET_SET_MACRO(bool, drawMedian)
JKQTPGET_SET_MACRO(bool, drawMinMax)
protected:
/** \brief which plot style to use from the parent plotter (via JKQtPlotterBase::getPlotStyle() and JKQtPlotterBase::getNextStyle() ) */
int parentPlotStyle;
/** \brief the column that contains the x-component of the datapoints */
double pos;
/** \brief the column that contains the median-component of the datapoints */
double median;
/** \brief the column that contains the median-component of the datapoints. \note This column is strictly optional. */
double mean;
/** \brief indicates whether to draw the mean */
bool drawMean;
/** \brief indicates whether to draw the median */
bool drawMedian;
/** \brief indicates whether to draw the percentiles */
bool drawMinMax;
/** \brief the column that contains the minimum-component of the datapoints */
double min;
/** \brief the column that contains the maximum-component of the datapoints */
double max;
/** \brief the column that contains the 25% percentile-component of the datapoints */
double percentile25;
/** \brief the column that contains the 75% percentile-component of the datapoints */
double percentile75;
/** \brief color of the lines */
QColor color;
/** \brief color of the box fill */
QColor fillColor;
/** \brief fill style for the box */
Qt::BrushStyle fillStyle;
/** \brief linestyle of the whisker lines */
Qt::PenStyle whiskerStyle;
/** \brief width (pixels) of the graph */
double lineWidth;
/** \brief width of box in plot coordinates */
double boxWidth;
/** \brief which symbol to use for the mean */
JKQTPgraphSymbols meanSymbol;
/** \brief size (diameter in pixels) of the symbol for the mean */
double meanSymbolSize;
/** \brief width (in pixels) of the lines used to plot the symbol for the mean */
double meanSymbolWidth;
QBrush getBrush(JKQTPEnhancedPainter& painter) const;
QPen getLinePen(JKQTPEnhancedPainter& painter) const;
};
/*! \brief This implements a horizontal <a href="http://en.wikipedia.org/wiki/Box_plot">boxplot</a> where the data is directly given to the
object and not stored in a column, as in JKQTPboxplotVerticalGraph
\ingroup jkqtplotter_plots
the x position is given in pos. All other data are given in the median, min, max,
percentile25 and percentile75.
\image html plot_boxplothorizontal.png
*/
class LIB_EXPORT JKQTPboxplotHorizontalElement: public JKQTPboxplotVerticalElement {
Q_OBJECT
public:
/** \brief class constructor */
inline JKQTPboxplotHorizontalElement(JKQtBasePlotter* parent=nullptr):
JKQTPboxplotVerticalElement(parent)
{
}
/** \brief class constructor */
inline JKQTPboxplotHorizontalElement(JKQtPlotter* parent):
JKQTPboxplotVerticalElement(parent)
{
}
/** \brief plots the graph to the plotter object specified as parent */
virtual void draw(JKQTPEnhancedPainter& painter);
/** \brief plots a key marker inside the specified rectangle \a rect */
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect);
/** \brief get the maximum and minimum x-value of the graph
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero);
/** \brief get the maximum and minimum y-value of the graph
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero);
};
#endif // JKQTPBOXPLOTELEMENTS_H

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,817 @@
/*
Copyright (c) 2008-2018 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 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 "jkqtpevaluatedfunctionelements.h"
#include "jkqtpbaseplotter.h"
#include <stdlib.h>
#include <QDebug>
#include <iostream>
#include "jkqtptools.h"
#include "jkqtpimageelements.h"
#include "jkqtpbaseelements.h"
#include "jkqtplotter.h"
double JKQTPxFunctionLineGraphPolynomial(double x, void* param) {
double res=0;
QVector<double>* d=static_cast<QVector<double>*>(param);
if (d && d->size()>0) {
res=d->value(0,0);
double xx=x;
for (int i=1; i<d->size(); i++) {
res=res+d->value(i,0)*xx;
xx=xx*x;
}
}
return res;
}
double JKQTPxFunctionLineGraphExponential(double x, void* param) {
double res=0;
QVector<double>* d=static_cast<QVector<double>*>(param);
if (d) {
if (d->size()>=3) {
res=d->value(0,0)+d->value(1,0)*exp(x/d->value(2,0));
} else if (d->size()>=2) {
res=d->value(0,0)*exp(x/d->value(1,0));
}
}
return res;
}
double JKQTPxFunctionLineGraphPowerLaw(double x, void* param) {
double res=0;
QVector<double>* d=static_cast<QVector<double>*>(param);
if (d) {
if (d->size()>=3) {
res=d->value(0,0)+d->value(1,0)*pow(x, d->value(2,1));
} else if (d->size()>=2) {
res=d->value(0,0)*pow(x, d->value(1,1));
} else if (d->size()>=1) {
res=pow(x, d->value(0,1));
}
}
return res;
}
JKQTPxFunctionLineGraph::JKQTPxFunctionLineGraph(JKQtBasePlotter* parent):
JKQTPgraph(parent)
{
color=QColor("red");
fillColor=color.lighter();
style=Qt::SolidLine;
lineWidth=2;
fillStyle=Qt::SolidPattern;
drawLine=true;
fillCurve=false;
plotFunction=nullptr;
params=nullptr;
minSamples=10;
maxRefinementDegree=7;
slopeTolerance=0.005;
minPixelPerSample=32;
plotRefinement=true;
displaySamplePoints=false;
data=nullptr;
drawErrorPolygons=false;
drawErrorLines=false;
errorPlotFunction=nullptr;
errorParams=nullptr;
errorColor=color.lighter();
errorFillColor=color.lighter();
errorStyle=Qt::SolidLine;
errorLineWidth=1;
errorFillStyle=Qt::SolidPattern;
parameterColumn=-1;
errorParameterColumn=-1;
if (parent) { // get style settings from parent object
parentPlotStyle=parent->getNextStyle();
//std::cout<<"got style settings from parent: "<<parentPlotStyle<<std::endl;
color=parent->getPlotStyle(parentPlotStyle).color();
fillColor=color.lighter();
style=parent->getPlotStyle(parentPlotStyle).style();
errorColor=color.lighter();
errorFillColor=color.lighter();
errorStyle=style;
}
fillColor.setAlphaF(0.5);
errorFillColor.setAlphaF(0.5);
}
JKQTPxFunctionLineGraph::JKQTPxFunctionLineGraph(JKQtPlotter* parent):
JKQTPgraph(parent)
{
color=QColor("red");
fillColor=color.lighter();
style=Qt::SolidLine;
lineWidth=2;
fillStyle=Qt::SolidPattern;
drawLine=true;
fillCurve=false;
plotFunction=nullptr;
params=nullptr;
minSamples=10;
maxRefinementDegree=7;
slopeTolerance=0.005;
minPixelPerSample=32;
plotRefinement=true;
displaySamplePoints=false;
data=nullptr;
drawErrorPolygons=false;
drawErrorLines=false;
errorPlotFunction=nullptr;
errorParams=nullptr;
errorColor=color.lighter();
errorFillColor=color.lighter();
errorStyle=Qt::SolidLine;
errorLineWidth=1;
errorFillStyle=Qt::SolidPattern;
parameterColumn=-1;
errorParameterColumn=-1;
if (parent) { // get style settings from parent object
parentPlotStyle=parent->getNextStyle();
//std::cout<<"got style settings from parent: "<<parentPlotStyle<<std::endl;
color=parent->getPlotStyle(parentPlotStyle).color();
fillColor=color.lighter();
style=parent->getPlotStyle(parentPlotStyle).style();
errorColor=color.lighter();
errorFillColor=color.lighter();
errorStyle=style;
}
fillColor.setAlphaF(0.5);
errorFillColor.setAlphaF(0.5);
}
JKQTPxFunctionLineGraph::~JKQTPxFunctionLineGraph() {
clearData();
}
void JKQTPxFunctionLineGraph::clearData() {
while (data!=nullptr) {
doublePair* d=data;
data=data->next;
delete d;
}
data=nullptr;
}
void JKQTPxFunctionLineGraph::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
painter.save();
QPen p=painter.pen();
p.setJoinStyle(Qt::RoundJoin);
p.setCapStyle(Qt::RoundCap);
QPen np(Qt::NoPen);
p.setColor(color);
p.setStyle(style);
QBrush b=painter.brush();
b.setColor(fillColor);
b.setStyle(fillStyle);
int y=rect.top()+rect.height()/2.0;
painter.setPen(np);
if (drawLine) painter.setPen(p);
painter.setBrush(b);
if (fillCurve) painter.drawRect(rect);
if (!fillCurve & drawLine) painter.drawLine(QLineF(rect.left(), y, rect.right(), y));
painter.restore();
}
QColor JKQTPxFunctionLineGraph::getKeyLabelColor() {
return color;
}
bool JKQTPxFunctionLineGraph::getXMinMax(double &minx, double &maxx, double &smallestGreaterZero)
{
smallestGreaterZero=minx=maxx=0; return false;
}
bool JKQTPxFunctionLineGraph::getYMinMax(double &miny, double &maxy, double &smallestGreaterZero)
{
smallestGreaterZero=miny=maxy=0; return false;
}
void JKQTPxFunctionLineGraph::createPlotData(bool collectParams) {
#ifdef JKQTBP_AUTOTIMER
JKQTPAutoOutputTimer jkaat(QString("JKQTPxFunctionLineGraph[%1]::createPlotData()").arg(title));
#endif
clearData();
if (collectParams) collectParameters();
if (parent==nullptr) return;
if (plotFunction==nullptr) return;
double xmin=parent->getXMin();
double xmax=parent->getXMax();
double pxmin=xAxis->x2p(xmin);
double pxmax=xAxis->x2p(xmax);
double delta0=(pxmax-pxmin)/(double)minSamples;
//double logdelta0=(log(xmax)-log(xmin))/(double)minSamples;
// initially sample function
doublePair* d=new doublePair;
d->x=xmin;
d->f=plotFunction(xmin, params);
d->next=nullptr;
data=d;
/*if (parent && parent->getXAxis()->isLogAxis()) {
for (double x=log(xmin)+logdelta0; x<log(xmax); x=x+logdelta0) {
d->next = new doublePair;
d->next->x=exp(x+((double)rand()/(double)RAND_MAX-0.5)*delta0/2.0);
d->next->f=plotFunction(d->next->x, params);
d->next->next=nullptr;
doublePair* dd=d;
d=d->next;
refine(dd, d);
}
} else {*/
QVector<double>* dv=static_cast<QVector<double>*>(params);
if (plotFunction==JKQTPxFunctionLineGraphPolynomial && dv && dv->size()<=2) {
// we only need the first and last datapoint
} else {
for (double x=pxmin+delta0; x<pxmax; x=x+delta0) {
d->next = new doublePair;
d->next->x=parent->p2x(x+((double)rand()/(double)RAND_MAX-0.5)*delta0/2.0);
d->next->f=plotFunction(d->next->x, params);
d->next->next=nullptr;
doublePair* dd=d;
d=d->next;
refine(dd, d);
}
}
//}
d->next = new doublePair;
d->next->x=xmax;
d->next->f=plotFunction(xmax, params);
d->next->next=nullptr;
refine(d, d->next);
}
void JKQTPxFunctionLineGraph::collectParameters()
{
if (parent && parameterColumn>=0) {
iparams.clear();
JKQTPdatastore* datastore=parent->getDatastore();
int imin=0;
int imax=datastore->getColumn(parameterColumn).getRows();
for (int i=imin; i<imax; i++) {
double xv=datastore->get(parameterColumn,i);
iparams<<xv;
}
//qDebug()<<"iparams_beforeclean:";
//for (int i=0; i<iparams.size(); i++) qDebug()<<iparams[i];
int i=iparams.size()-1;
while (i>=0 && !JKQTPIsOKFloat(iparams[i])) {
iparams.remove(i,1);
i--;
}
//qDebug()<<"iparams:";
//for (i=0; i<iparams.size(); i++) qDebug()<<iparams[i];
params=&iparams;
}
if (parent && errorParameterColumn>=0) {
ierrorparams.clear();
JKQTPdatastore* datastore=parent->getDatastore();
int imin=0;
int imax=datastore->getColumn(errorParameterColumn).getRows();
for (int i=imin; i<imax; i++) {
double xv=datastore->get(errorParameterColumn,i);
ierrorparams<<xv;
}
int i=ierrorparams.size()-1;
while (i>=0 && !JKQTPIsOKFloat(ierrorparams[i])) {
ierrorparams.remove(i,1);
i--;
}
errorParams=&ierrorparams;
}
}
void JKQTPxFunctionLineGraph::refine(doublePair* a, doublePair* b, unsigned int degree) {
if (degree>=maxRefinementDegree) return;
double ax=xAxis->x2p(a->x);
double af=xAxis->x2p(a->f);
double bx=xAxis->x2p(b->x);
double bf=xAxis->x2p(b->f);
double delta=bx - ax;
//double logdelta=log(bx) - log(ax);
double xmid=ax+(delta)/2.0;
/*if (parent && parent->getXAxis()->isLogAxis()) {
xmid=log(a->x)+(logdelta)/2.0;
xmid=xmid+((double)rand()/(double)RAND_MAX-0.5)*delta/5.0;
xmid=exp(xmid);
} else {*/
xmid=xmid+((double)rand()/(double)RAND_MAX-0.5)*delta/5.0; // shake by 10%
//}
double realxmid=parent->p2x(xmid);
double realfmid=plotFunction(realxmid, params);
double fmid=yAxis->x2p(realfmid);
double a1=(fmid - af)/(xmid - ax);
double a2=(bf - fmid)/(bx - xmid);
//std::cout<<std::string(degree*2, ' ')<<"refine( ["<<a->x<<", "<<a->f<<"], ["<<xmid<<", "<<fmid<<"], ["<<b->x<<", "<<b->f<<"] ): a1="<<a1<<", a2="<<a2<<" acrit="<<abs(a2/a1)-1.0<<"\n";
//std::cout<<std::string(degree*2, ' ')<<"refine(): a1="<<a1<<", a2="<<a2<<" acrit="<<fabs(a2-a1)<<"\n";
if (fabs(a2-a1)>slopeTolerance || delta>minPixelPerSample) {
doublePair* dmid = new doublePair;
dmid->x=realxmid;
dmid->f=realfmid;
a->next=dmid;
dmid->next=b;
refine(a, dmid, degree+1);
refine(dmid, b, degree+1);
}
}
void JKQTPxFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
#ifdef JKQTBP_AUTOTIMER
JKQTPAutoOutputTimer jkaaot("JKQTPxFunctionLineGraph::draw");
#endif
if (parent==nullptr) return;
JKQTPdatastore* datastore=parent->getDatastore();
if (datastore==nullptr) return;
//qDebug()<<"start plot\n";
createPlotData();
//qDebug()<<"plot data created\n";
drawErrorsBefore(painter);
painter.save();
QPen p=painter.pen();
p.setColor(color);
p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, lineWidth*parent->get_lineWidthMultiplier())));
p.setStyle(style);
p.setJoinStyle(Qt::RoundJoin);
p.setJoinStyle(Qt::RoundJoin);
p.setCapStyle(Qt::RoundCap);
QPen np(Qt::NoPen);
QPen ep=painter.pen();
ep.setColor(errorColor);
ep.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, errorLineWidth*parent->get_lineWidthMultiplier())));
ep.setStyle(errorStyle);
ep.setJoinStyle(Qt::RoundJoin);
QBrush b=painter.brush();
b.setColor(fillColor);
b.setStyle(fillStyle);
QBrush eb=painter.brush();
eb.setColor(errorFillColor);
eb.setStyle(errorFillStyle);
// double xold=-1;
// double yold=-1;
// double ypeold=-1;
// double ymeold=-1;
// double x0=xAxis->x2p(0);
// if (parent->getXAxis()->isLogAxis()) x0=xAxis->x2p(parent->getXAxis()->getMin());
double y0=yAxis->x2p(0);
if (parent->getYAxis()->isLogAxis()) y0=yAxis->x2p(parent->getYAxis()->getMin());
bool first=false;
doublePair* d=data;
//QPainterPath pa, pfill;
//QPainterPath pel, pef;
QPolygonF filledPolygon, linePolygon, errorLineTop, errorLineBottom;
QList<QPointF> epTop, epBottom;
double yami=qMin(yAxis->x2p(parent->getYAxis()->getMin()),yAxis->x2p(parent->getYAxis()->getMax()));
double yama=qMax(yAxis->x2p(parent->getYAxis()->getMin()),yAxis->x2p(parent->getYAxis()->getMax()));
double dypix=fabs(yama-yami);
yami=yami-2*dypix;
yama=yama+2*dypix;
while (d!=nullptr) {
double xv=d->x;
double yv=d->f;
//std::cout<<"(xv, yv) = ( "<<xv<<", "<<yv<<" )\n";
if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv)) {
double x=xAxis->x2p(xv);
double y=yAxis->x2p(yv);
double ype=0, yme=0;
if ((drawErrorLines || drawErrorPolygons) && (errorPlotFunction!=nullptr)) {
double e=errorPlotFunction(xv, errorParams);
ype=yAxis->x2p(yv+e);
yme=yAxis->x2p(yv-e);
ype=qBound(yami, ype, yama);
yme=qBound(yami, yme, yama);
}
y=qBound(yami, y, yama);
if (fillCurve) {
if (!first) filledPolygon<<QPointF(x, y0);
filledPolygon<<QPointF(x, y);
if (!d->next) filledPolygon<<QPointF(x, y0);
}
if (drawErrorPolygons && (errorPlotFunction!=nullptr)) {
epTop<<QPointF(x, ype);
epBottom<<QPointF(x, yme);
}
if (drawLine) {
linePolygon<<QPointF(x, y);
}
if (drawErrorLines && (errorPlotFunction!=nullptr)) {
errorLineTop<<QPointF(x, ype);
errorLineBottom<<QPointF(x, yme);
}
// xold=x;
// yold=y;
// ypeold=ype;
// ymeold=yme;
first=true;
}
d=d->next;
}
if (drawErrorPolygons) {
painter.save();
painter.setBrush(eb);
painter.setPen(np);
QPolygonF poly;
//poly << QPointF(xold, ypeold) << QPointF(x, ype)<< QPointF(x, yme) << QPointF(xold, ymeold) ;
for (int i=0; i<epTop.size(); i++) {
poly<<epTop[i];
}
for (int i=epBottom.size()-1; i>=0; i--) {
poly<<epBottom[i];
}
painter.drawPolygon(poly, Qt::OddEvenFill);
painter.restore();
}
if (fillCurve) {
painter.save();
painter.setBrush(b);
painter.setPen(np);
painter.drawPolygon(filledPolygon, Qt::OddEvenFill);
painter.restore();
}
if (drawLine) {
painter.save();
painter.setPen(p);
painter.drawPolyline(linePolygon);
painter.restore();
}
if (drawErrorLines && (errorPlotFunction!=nullptr)) {
painter.save();
painter.setPen(ep);
painter.drawPolyline(errorLineTop);
painter.drawPolyline(errorLineBottom);
painter.restore();
}
QColor c=color;
c.setHsv(fmod(color.hue()+90, 360), color.saturation(), color.value());
d=data;
if (displaySamplePoints) {
painter.save();
while (d!=nullptr) {
double xv=d->x;
double yv=d->f;
//std::cout<<"(xv, yv) = ( "<<xv<<", "<<yv<<" )\n";
if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv)) {
double x=xAxis->x2p(xv);
double y=yAxis->x2p(yv);
plotSymbol(painter, x, y, JKQTPcross, 6,1*parent->get_lineWidthMultiplier(), c, QColor(Qt::transparent));
}
d=d->next;
}
painter.restore();
}
painter.restore();
drawErrorsAfter(painter);
//std::cout<<"plot done\n";
}
void JKQTPyFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
#ifdef JKQTBP_AUTOTIMER
JKQTPAutoOutputTimer jkaaot("JKQTPyFunctionLineGraph::draw");
#endif
if (parent==nullptr) return;
JKQTPdatastore* datastore=parent->getDatastore();
if (datastore==nullptr) return;
//std::cout<<"start plot\n";
createPlotData();
//std::cout<<"plot data created\n";
drawErrorsBefore(painter);
painter.save();
QPen p=painter.pen();
p.setColor(color);
p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, lineWidth*parent->get_lineWidthMultiplier())));
p.setStyle(style);
p.setJoinStyle(Qt::RoundJoin);
p.setJoinStyle(Qt::RoundJoin);
p.setCapStyle(Qt::RoundCap);
QPen np(Qt::NoPen);
QPen ep=painter.pen();
ep.setColor(errorColor);
ep.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, errorLineWidth*parent->get_lineWidthMultiplier())));
ep.setStyle(errorStyle);
ep.setJoinStyle(Qt::RoundJoin);
QBrush b=painter.brush();
b.setColor(fillColor);
b.setStyle(fillStyle);
QBrush eb=painter.brush();
eb.setColor(errorFillColor);
eb.setStyle(errorFillStyle);
double xold=-1;
double yold=-1;
double xpeold=-1;
double xmeold=-1;
double x0=xAxis->x2p(0);
if (parent->getXAxis()->isLogAxis()) x0=xAxis->x2p(parent->getXAxis()->getMin());
// double y0=yAxis->x2p(0);
// if (parent->getYAxis()->isLogAxis()) y0=yAxis->x2p(parent->getYAxis()->getMin());
bool first=false;
doublePair* d=data;
while (d!=nullptr) {
double yv=d->x;
double xv=d->f;
//std::cout<<"(xv, yv) = ( "<<xv<<", "<<yv<<" )\n";
if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv)) {
double x=xAxis->x2p(xv);
double y=yAxis->x2p(yv);
double xpe=0, xme=0;
if ((drawErrorLines || drawErrorPolygons) && (errorPlotFunction!=nullptr)) {
double e=errorPlotFunction(xv, errorParams);
xpe=xAxis->x2p(xv+e);
xme=xAxis->x2p(xv-e);
}
if (first) {
double xl1=xold;
double yl1=yold;
double xl2=x;
double yl2=y;
if (fillCurve) {
painter.save();
painter.setBrush(b);
painter.setPen(np);
QPolygonF poly;
poly << QPointF(xl1, yl1) << QPointF(xl2, yl2) << QPointF(x0, yl2) << QPointF(x0, yl1);
painter.drawConvexPolygon(poly);
painter.restore();
/*pfill.lineTo(x, y);
if (d->next==nullptr) { // last datapoint
pfill.lineTo(x, y0);
}*/
}
if (drawErrorPolygons && (errorPlotFunction!=nullptr)) {
painter.save();
painter.setBrush(eb);
painter.setPen(np);
QPolygonF poly;
poly << QPointF(xpeold, yold) << QPointF(xpe, y)<< QPointF(xme, y) << QPointF(xmeold, yold) ;
painter.drawConvexPolygon(poly);
painter.restore();
}
if (drawLine) {
painter.setPen(p);
//pa.lineTo(x, y);
painter.drawLine(QLineF(xl1, yl1, xl2, yl2));
}
if (drawErrorLines && (errorPlotFunction!=nullptr)) {
painter.setPen(ep);
painter.drawLine(QLineF(xpeold, yold, xpe, y));
painter.drawLine(QLineF(xmeold, yold, xme, y));
}
//std::cout<<"line ("<<xl1<<", "<<yl1<<") -- ("<<xl2<<", "<<yl2<<")"<<std::endl;
} /*else {
if (drawLine) {
pa.moveTo(x, y);
}
if (fillCurve) {
pfill.moveTo(x, y0);
pfill.lineTo(x, y);
}
}*/
xold=x;
yold=y;
xpeold=xpe;
xmeold=xme;
first=true;
}
d=d->next;
}
/*if (fillCurve) {
pfill.closeSubpath();
painter.save();
painter.setBrush(b);
painter.setPen(np);
painter.drawPath(pfill);
painter.restore();
}
if (drawLine) {
painter.setPen(p);
painter.drawPath(pa);
painter.restore();
}*/
QColor c=color;
c.setHsv(fmod(color.hue()+90, 360), color.saturation(), color.value());
d=data;
if (displaySamplePoints) while (d!=nullptr) {
double yv=d->x;
double xv=d->f;
//std::cout<<"(xv, yv) = ( "<<xv<<", "<<yv<<" )\n";
if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv)) {
double x=xAxis->x2p(xv);
double y=yAxis->x2p(yv);
plotSymbol(painter, x, y, JKQTPcross, 6, 1*parent->get_lineWidthMultiplier(), c, QColor(Qt::transparent));
}
d=d->next;
}
painter.restore();
drawErrorsAfter(painter);
//std::cout<<"plot done\n";
}
void JKQTPyFunctionLineGraph::createPlotData(bool /*collectParams*/) {
clearData();
if (parent==nullptr) return;
if (plotFunction==nullptr) return;
double ymin=parent->getYMin();
double ymax=parent->getYMax();
double delta0=(ymax-ymin)/(double)minSamples;
// initially sample function
doublePair* d=new doublePair;
d->x=ymin;
d->f=plotFunction(ymin, params);
d->next=nullptr;
data=d;
for (double y=ymin+delta0; y<ymax; y=y+delta0) {
d->next = new doublePair;
d->next->x=y+((double)rand()/(double)RAND_MAX-0.5)*delta0/2.0;
d->next->f=plotFunction(d->next->x, params);
d->next->next=nullptr;
doublePair* dd=d;
d=d->next;
refine(dd, d);
}
d->next = new doublePair;
d->next->x=ymax;
d->next->f=plotFunction(ymax, params);
d->next->next=nullptr;
refine(d, d->next);
}
QBrush JKQTPxFunctionLineGraph::getBrush(JKQTPEnhancedPainter& /*painter*/) const {
QBrush b;
b.setColor(fillColor);
b.setStyle(fillStyle);
return b;
}
QPen JKQTPxFunctionLineGraph::getLinePen(JKQTPEnhancedPainter &painter) const {
QPen p;
p.setColor(color);
p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->get_lineWidthMultiplier()*lineWidth)));
p.setStyle(style);
p.setJoinStyle(Qt::RoundJoin);
p.setCapStyle(Qt::RoundCap);
return p;
}
QBrush JKQTPxFunctionLineGraph::getErrorBrush(JKQTPEnhancedPainter& /*painter*/) const {
QBrush b;
b.setColor(errorFillColor);
b.setStyle(errorFillStyle);
return b;
}
QPen JKQTPxFunctionLineGraph::getErrorLinePen(JKQTPEnhancedPainter& painter) const {
QPen p;
p.setColor(errorColor);
p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->get_lineWidthMultiplier()*errorLineWidth)));
p.setStyle(errorStyle);
p.setJoinStyle(Qt::RoundJoin);
p.setCapStyle(Qt::RoundCap);
return p;
}
void JKQTPxFunctionLineGraph::set_params(const QVector<double> &params)
{
iparams=params;
set_params(&iparams);
}
void JKQTPxFunctionLineGraph::set_copiedParams(const double *params, int N)
{
QVector<double> v;
for (int i=0; i<N; i++) { v<<params[i]; }
set_params(v);
}
void JKQTPxFunctionLineGraph::set_errorParams(const QVector<double> &errorParams)
{
ierrorparams=errorParams;
set_errorParams(&ierrorparams);
}
void JKQTPxFunctionLineGraph::setSpecialFunction(JKQTPxFunctionLineGraph::SpecialFunction function)
{
if (function==JKQTPxFunctionLineGraph::Polynomial) set_plotFunction(JKQTPxFunctionLineGraphPolynomial);
else if (function==JKQTPxFunctionLineGraph::Exponential) set_plotFunction(JKQTPxFunctionLineGraphExponential);
else if (function==JKQTPxFunctionLineGraph::PowerLaw) set_plotFunction(JKQTPxFunctionLineGraphPowerLaw);
}
QVector<double> JKQTPxFunctionLineGraph::get_internalParams() const {
return iparams;
}
QVector<double> JKQTPxFunctionLineGraph::get_internalErrorParams() const {
return ierrorparams;
}
bool JKQTPxFunctionLineGraph::usesColumn(int c)
{
return (c==parameterColumn)||(c==errorParameterColumn);
}

View File

@ -0,0 +1,290 @@
/*
Copyright (c) 2008-2018 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 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/>.
*/
/**
* \defgroup jkqtplotter_elements Plot Elements
* \ingroup jkqtplotter
* \defgroup jkqtplotter_plots Graphs
* \ingroup jkqtplotter_elements
*/
/** \file jkqtpelements.h
* \ingroup jkqtplotter
*/
#include <QString>
#include <QPainter>
#include <QPair>
#include "jkqtpelements.h"
#include "jkqtp_imexport.h"
#ifndef JKQTPEVALUATEDFUNCTIONELEMENTS_H
#define JKQTPEVALUATEDFUNCTIONELEMENTS_H
/*! \brief type of functions that may be plottet
\ingroup jkqtplotter_plots
This is the type of functions \f$ y=f(x, \vec{p}) \f$ that may be plottet by JKQTPxFunctionLineGraph
and JKQTPyFunctionLineGraph. It is possible to supply parameters \f$ \vec{p} \f$ to the function that
influence its result. Parameters are given as a pointer to some memory location. The function has to
know on its own how to interpret these.
*/
typedef double(*jkqtpPlotFunctionType)(double, void*);
/*! \brief This implements line plots where the data is taken from a user supplied function \f$ y=f(x) \f$
\ingroup jkqtplotter_plots
This class implements an intelligent plotting algorithm for functions. It starts by sampling
the function at minSamples positions. Then each function interval is bisected recursively if
necessary. To do so the function is evaluated at the mid point and the slopes \f$ \alpha_{\mbox{left}} \f$
and \f$ \alpha_{\mbox{right}} \f$ of the two linear segments are compared. the midpoint is added
to the graph if \f[ \left|\alpha_{\mbox{right}}-\alpha_{\mbox{left}}\right|>\mbox{slopeTolerance} \f]
In addition all sampling points except minimum and maximum are beeing shifted by a random fraction their
distance to the other points. This helps to prevent beats when sampling periodic functions.
the following image
\image html plot_functionplots.png
*/
class LIB_EXPORT JKQTPxFunctionLineGraph: public JKQTPgraph {
Q_OBJECT
public:
enum SpecialFunction {
Polynomial, /*!< \brief a polynomial \f$ f(x)=p_0+p_1x+p_2x^2+p_3x^3+... \f$ The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */
Line=Polynomial, /*!< \brief a polynomial \f$ f(x)=p_0+p_1x \f$ The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */
Exponential, /*!< \brief an exponential function \f$ f(x)=p_0+p_1\cdot\exp(x/p_2) \f$ or \f$ f(x)=p_0\cdot\exp(x/p_1) \f$ (depending on the number of parameters). The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */
PowerLaw /*!< \brief an exponential function \f$ f(x)=p_0+p_1\cdot x^{p_3} \f$ or \f$ f(x)=p_0\cdot x^{p_1} \f$ or \f$ f(x)= x^{p_0} \f$ (depending on the number of parameters) The parameters \a params have to be point to a QVector<double> and contain the parameters \f$ p_0, p_1, ... \f$ */
};
/** \brief class constructor */
JKQTPxFunctionLineGraph(JKQtBasePlotter* parent=nullptr);
/** \brief class constructor */
JKQTPxFunctionLineGraph(JKQtPlotter* parent);
/** \brief class destructor */
virtual ~JKQTPxFunctionLineGraph();
/** \brief plots the graph to the plotter object specified as parent */
virtual void draw(JKQTPEnhancedPainter& painter);
/** \brief plots a key marker inside the specified rectangle \a rect */
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect);
/** \brief returns the color to be used for the key label */
virtual QColor getKeyLabelColor();
/** \brief get the maximum and minimum x-value of the graph
*
* This functions returns 0 for both parameters, so that the plotter uses the predefined
* min and max values.
*/
virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero);
/** \brief get the maximum and minimum y-value of the graph
*/
virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero);
/** \brief clear the data sampled from the function. */
void clearData();
JKQTPGET_SET_MACRO(QColor, color)
JKQTPGET_SET_MACRO(QColor, fillColor)
JKQTPGET_SET_MACRO(Qt::BrushStyle, fillStyle)
JKQTPGET_SET_MACRO(Qt::PenStyle, style)
JKQTPGET_SET_MACRO(double, lineWidth)
JKQTPGET_SET_MACRO(bool, drawLine)
JKQTPGET_SET_MACRO_I(jkqtpPlotFunctionType, plotFunction, clearData())
JKQTPGET_SET_MACRO_I(void*, params, clearData())
/** \brief sets the params as a pointer to an internal COPY of the given vector (not the data of the vector, as then the size would be unknown!!!) */
void set_params(const QVector<double>& params);
/** \brief sets the params from a copy of the given array of length \a N */
void set_copiedParams(const double* params, int N);
inline void set_paramsV(double p1) {
QVector<double> p;
p<<p1;
set_params(p);
}
inline void set_paramsV(double p1, double p2) {
QVector<double> p;
p<<p1<<p2;
set_params(p);
}
inline void set_paramsV(double p1, double p2, double p3) {
QVector<double> p;
p<<p1<<p2<<p3;
set_params(p);
}
inline void set_paramsV(double p1, double p2, double p3, double p4) {
QVector<double> p;
p<<p1<<p2<<p3<<p4;
set_params(p);
}
inline void set_paramsV(double p1, double p2, double p3, double p4, double p5) {
QVector<double> p;
p<<p1<<p2<<p3<<p4<<p5;
set_params(p);
}
QVector<double> get_internalParams() const;
QVector<double> get_internalErrorParams() const;
JKQTPGET_SET_MACRO(unsigned int, minSamples)
JKQTPGET_SET_MACRO(unsigned int, maxRefinementDegree)
JKQTPGET_SET_MACRO(double, slopeTolerance)
JKQTPGET_SET_MACRO(double, minPixelPerSample)
JKQTPGET_SET_MACRO(bool, plotRefinement)
JKQTPGET_SET_MACRO(bool, displaySamplePoints)
JKQTPGET_SET_MACRO(bool, drawErrorPolygons)
JKQTPGET_SET_MACRO(bool, drawErrorLines)
JKQTPGET_SET_MACRO(jkqtpPlotFunctionType, errorPlotFunction)
JKQTPGET_SET_MACRO(void*, errorParams)
/** \brief sets the error params as a pointer to an internal COPY of the given vector (not the data of the vector, as then the size would be unknown!!!) */
void set_errorParams(const QVector<double>& errorParams);
JKQTPGET_SET_MACRO(int, parameterColumn)
JKQTPSET_CAST_MACRO(size_t, int, parameterColumn)
JKQTPGET_SET_MACRO(int, errorParameterColumn)
JKQTPSET_CAST_MACRO(size_t, int, errorParameterColumn)
JKQTPGET_SET_MACRO(QColor, errorColor)
JKQTPGET_SET_MACRO(QColor, errorFillColor)
JKQTPGET_SET_MACRO(Qt::BrushStyle, errorFillStyle)
JKQTPGET_SET_MACRO(Qt::PenStyle, errorStyle)
JKQTPGET_SET_MACRO(double, errorLineWidth)
/** \copydoc JKQTPgraph::usesColumn() */
virtual bool usesColumn(int c);
/** \brief sets function to the given special function */
void setSpecialFunction(SpecialFunction function);
protected:
/** \brief which plot style to use from the parent plotter (via JKQtPlotterBase::getPlotStyle() and JKQtPlotterBase::getNextStyle() ) */
int parentPlotStyle;
struct doublePair {
double x;
double f;
doublePair* next;
};
/** \brief a linked list holding the datapoints \f$ \left(x, y=f(x, \vec{p})\right) \f$ to be plotted */
doublePair* data;
/** \brief fill the data array with data from the function plotFunction */
virtual void createPlotData( bool collectParams=true);
virtual void collectParameters();
void refine(doublePair* a, doublePair* b, unsigned int degree=0);
int parameterColumn;
int errorParameterColumn;
/** \brief color of the graph */
QColor color;
/** \brief color of the graph fill */
QColor fillColor;
/** \brief linestyle of the graph lines */
Qt::PenStyle style;
/** \brief width (pixels) of the graph */
double lineWidth;
/** \brief fill style, if the curve should be filled */
Qt::BrushStyle fillStyle;
/** \brief indicates whether to draw a line or not */
bool drawLine;
/** \brief indicates whether to fill the space between the curve and the x-axis */
bool fillCurve;
/** \brief the function to be plotted */
jkqtpPlotFunctionType plotFunction;
/** \brief pointer to the parameters supplied to the plotting funtion */
void* params;
/** \brief the minimum number of points to evaluate the function at */
unsigned int minSamples;
/** \brief the maximum number of recursive refinement steps
*
* each step bisects the interval \f$ [a, b] \f$ into two halfes. So the maximum number
* of points plotted at all are thus:
* \f[ \mbox{minSamples} \cdot 2^{\mbox{maxRefinementDegree}} \f]
*/
unsigned int maxRefinementDegree;
/** \brief the tolerance for the difference of two subsequent slopes */
double slopeTolerance;
/** \brief create one sample at least every \a minPixelPerSample pixels */
double minPixelPerSample;
/** \brief switch on or off [default: on] the plot refinement algorithm */
bool plotRefinement;
/** \brief if true [default: off] display the points where the function has been sampled */
bool displaySamplePoints;
/** \brief indicates whether an error polygon should be drawn */
bool drawErrorPolygons;
/** \brief indicates whether error lines should be drawn */
bool drawErrorLines;
/** \brief this function calculates the error at a given position */
jkqtpPlotFunctionType errorPlotFunction;
/** \brief parameters for errorFunction */
void* errorParams;
/** \brief color of the error graph */
QColor errorColor;
/** \brief color of the error graph fill */
QColor errorFillColor;
/** \brief linestyle of the error graph lines */
Qt::PenStyle errorStyle;
/** \brief width (pixels) of the error graph */
double errorLineWidth;
/** \brief fill style, if the error curve should be filled */
Qt::BrushStyle errorFillStyle;
QBrush getBrush(JKQTPEnhancedPainter& painter) const;
QPen getLinePen(JKQTPEnhancedPainter& painter) const;
QBrush getErrorBrush(JKQTPEnhancedPainter& painter) const;
QPen getErrorLinePen(JKQTPEnhancedPainter &painter) const;
QVector<double> iparams, ierrorparams;
};
/*! \brief This implements line plots where the data is taken from a user supplied function \f$ x=f(y) \f$
\ingroup jkqtplotter_plots
*/
class LIB_EXPORT JKQTPyFunctionLineGraph: public JKQTPxFunctionLineGraph {
Q_OBJECT
public:
/** \brief class constructor */
inline JKQTPyFunctionLineGraph(JKQtBasePlotter* parent=nullptr):JKQTPxFunctionLineGraph(parent) {}
/** \brief class constructor */
inline JKQTPyFunctionLineGraph(JKQtPlotter* parent):JKQTPxFunctionLineGraph(parent) {}
/** \brief plots the graph to the plotter object specified as parent */
virtual void draw(JKQTPEnhancedPainter& painter);
protected:
/** \brief fill the data array with data from the function plotFunction */
virtual void createPlotData( bool collectParams=true);
};
#endif // JKQTPEVALUATEDFUNCTIONELEMENTS_H

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger & Sebastian Isbaner (contour plot), German Cancer Research Center
Copyright (c) 2008-2018 Jan W. Krieger & Sebastian Isbaner (contour plot), German Cancer Research Center

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger & Sebastian Isbaner (contour plot), German Cancer Research Center
Copyright (c) 2008-2018 Jan W. Krieger & Sebastian Isbaner (contour plot), German Cancer Research Center

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center
@ -253,8 +253,9 @@ class LIB_EXPORT JKQtPlotter: public QWidget {
/** \brief move the given graph to the top, or add it, if it is not yet contained */
inline size_t moveGraphBottom(JKQTPgraph* gr) { return plotter->moveGraphBottom(gr); }
/** \brief add a new graphs from a QVector */
inline void addGraphs(const QList<JKQTPgraph*>& gr) { plotter->addGraphs(gr); }
/** \brief add a new graphs from a QVector<JKQTPgraph*>, QList<JKQTPgraph*>, std::vector<JKQTPgraph*> ... or any standard-iterateable container with JKQTPgraph*-items */
template <class TJKQTPgraphContainer>
inline void addGraphs(const TJKQTPgraphContainer& gr) { plotter->addGraphs(gr); }
/** \brief sets minimum and maximum x-value to plot */
inline void setX(double xminn, double xmaxx) { plotter->setX(xminn, xmaxx); }
@ -470,13 +471,13 @@ class LIB_EXPORT JKQtPlotter: public QWidget {
/** \brief fill color of the zoom rectangle */
JKQTPPROPERTY(QColor, userActionColor);
JKQTPPROPERTY(QColor, userActionColor)
/** \brief fill color of the zoom rectangle */
JKQTPPROPERTY(QPainter::CompositionMode, userActionCompositionMode);
JKQTPPROPERTY(QPainter::CompositionMode, userActionCompositionMode)
/** \brief width/height of the icons in the plotter toolbar in pixels */
JKQTPPROPERTY(int, toolbarIconSize);
JKQTPPROPERTY(int, toolbarIconSize)
/** \brief this is set \c true if we are drawing a zoom rectangle */
bool mouseDragingRectangle;
@ -597,7 +598,7 @@ class LIB_EXPORT JKQtPlotter: public QWidget {
top border, so the position fits in. The default widget font is used for the output. */
bool displayMousePosition;
/** \brief this string is used to generate the position output above the graph */
JKQTPPROPERTY(QString, mousePositionTemplate);
JKQTPPROPERTY(QString, mousePositionTemplate)
/** \brief if set \c true and displayMousePosition is \c true, the mouse position is not automaticallz determined, but the text given to setMousePositionLabel() is used */
bool displayCustomMousePosition;
QString customMousePositiontext;

View File

@ -4,6 +4,7 @@ QMAKE_CXXFLAGS += -fexceptions
HEADERS += $$PWD/jkqtpbaseplotter.h \
$$PWD/jkqtpdatastorage.h \
$$PWD/jkqtpbasegraphs.h \
$$PWD/jkqtpelements.h \
$$PWD/jkqtmathtext.h \
$$PWD/jkqtpbaseelements.h \
@ -12,6 +13,9 @@ HEADERS += $$PWD/jkqtpbaseplotter.h \
$$PWD/jkqttools.h \
$$PWD/jkqtpimageelements.h \
$$PWD/jkqtpimagetools.h \
$$PWD/jkqtpbarchartelements.h \
$$PWD/jkqtpboxplotelements.h \
$$PWD/jkqtpevaluatedfunctionelements.h \
$$PWD/jkqtpparsedfunctionelements.h \
$$PWD/jkqtpoverlayelements.h \
$$PWD/jkqtpgeoelements.h \
@ -22,6 +26,7 @@ HEADERS += $$PWD/jkqtpbaseplotter.h \
SOURCES += $$PWD/jkqtpbaseplotter.cpp \
$$PWD/jkqtpdatastorage.cpp \
$$PWD/jkqtpbasegraphs.cpp \
$$PWD/jkqtpelements.cpp \
$$PWD/jkqtmathtext.cpp \
$$PWD/jkqtpbaseelements.cpp \
@ -30,6 +35,9 @@ SOURCES += $$PWD/jkqtpbaseplotter.cpp \
$$PWD/jkqttools.cpp \
$$PWD/jkqtpimageelements.cpp \
$$PWD/jkqtpimagetools.cpp \
$$PWD/jkqtpbarchartelements.cpp \
$$PWD/jkqtpboxplotelements.cpp \
$$PWD/jkqtpevaluatedfunctionelements.cpp \
$$PWD/jkqtpparsedfunctionelements.cpp \
$$PWD/jkqtpoverlayelements.cpp \
$$PWD/jkqtpgeoelements.cpp \

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)
@ -27,7 +27,7 @@
#include "jkqtptools.h"
#include "jkqtpmathparser.h"
#include "jkqtp_imexport.h"
#include "jkqtpelements.h"
#include "jkqtpevaluatedfunctionelements.h"
// forward declarations
class JKQtBasePlotter;

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center
@ -335,14 +335,26 @@
* methodes
*/
#define JKQTPSET_MACRO(type,varname) \
typedef type typedef_set_##varname ;\
/** \brief sets the property varname to the specified \a __value. \details Description of the parameter varname is: <CENTER>\copybrief varname.</CENTER> \see varname for more information */ \
inline virtual void set_##varname (const typedef_set_##varname & __value) \
inline virtual void set_##varname (const type & __value) \
{ \
this->varname = __value; \
}
#define JKQTPSetMacro(type,varname) JKQTPSET_MACRO(type,varname)
/**
* \brief create set_varname(type __value) methods/functions
* inside a class, where \c type is the type of \c varname and \c varname is a
* previously declared private variable that should be accessed by these
* methodes
*/
#define JKQTPSET_CAST_MACRO(typefunction,typeinternal,varname) \
/** \brief sets the property varname to the specified \a __value, where __value is static_cast'ed from typefunction to typeinternal. \details Description of the parameter varname is: <CENTER>\copybrief varname.</CENTER> \see varname for more information */ \
inline virtual void set_##varname (const typefunction & __value) \
{ \
this->varname = static_cast<typeinternal>(__value); \
}
/**
* \brief create set_varname(type __value) methods/functions
* inside a class, where \c type is the type of \c varname and \c varname is a

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)
last modification: $LastChangedDate$ (revision $Rev$)

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2008-2015 Jan W. Krieger (<jan@jkrieger.de>, <j.krieger@dkfz.de>), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg
Copyright (c) 2008-2018 Jan W. Krieger (<jan@jkrieger.de>)
last modification: $LastChangedDate$ (revision $Rev$)

View File

@ -3,7 +3,7 @@
#include <QDate>
#include <QDateTime>
#include <QApplication>
#include "jkqtpbarchartelements.h"
@ -47,7 +47,7 @@ TestWidgetBarcharts::TestWidgetBarcharts(QWidget *parent) :
size_t bcpy2=plotBarchart->getDatastore()->addCopiedColumn(dataBCY2, "y2");
size_t bcpye2=plotBarchart->getDatastore()->addCopiedColumn(dataBCYE2, "ye2");
JKQTPbarHorizontalGraph* plteBar1=new JKQTPbarHorizontalGraph(plotBarchart->get_plotter());
JKQTPbarVerticalErrorGraph* plteBar1=new JKQTPbarVerticalErrorGraph(plotBarchart->get_plotter());
plteBar1->set_title(tr("bars 1"));
plteBar1->set_xColumn(bcpxd);
plteBar1->set_yColumn(bcpy1);
@ -56,7 +56,7 @@ TestWidgetBarcharts::TestWidgetBarcharts(QWidget *parent) :
plteBar1->set_shift(-0.25);
plotBarchart->get_plotter()->addGraph(plteBar1);
JKQTPbarHorizontalGraph* plteBar2=new JKQTPbarHorizontalGraph(plotBarchart->get_plotter());
JKQTPbarVerticalErrorGraph* plteBar2=new JKQTPbarVerticalErrorGraph(plotBarchart->get_plotter());
plteBar2->set_xColumn(bcpxd);
plteBar2->set_yColumn(bcpy2);
plteBar2->set_yErrorColumn(bcpye2);
@ -64,7 +64,7 @@ TestWidgetBarcharts::TestWidgetBarcharts(QWidget *parent) :
plteBar2->set_width(0.45);
plteBar2->set_shift(0.25);
plteBar2->set_baseline(0.5);
plteBar2->set_xErrorSymmetric(false);
plteBar2->set_yErrorSymmetric(false);
plotBarchart->get_plotter()->addGraph(plteBar2);
plteBar2->autoscaleBarWidthAndShift();
@ -82,26 +82,26 @@ TestWidgetBarcharts::TestWidgetBarcharts(QWidget *parent) :
barchartLayout->addWidget(plotBarchart2);
plteBar1=new JKQTPbarVerticalGraph(plotBarchart2->get_plotter());
plteBar1->set_title(tr("bars 1"));
plteBar1->set_yColumn(bcpx);
plteBar1->set_xColumn(bcpy1);
plteBar1->set_xErrorColumn(bcpye1);
plteBar1->set_width(0.45);
plteBar1->set_shift(-0.25);
plotBarchart2->get_plotter()->addGraph(plteBar1);
JKQTPbarHorizontalErrorGraph* plteBar3=new JKQTPbarHorizontalErrorGraph(plotBarchart2->get_plotter());
plteBar3->set_title(tr("bars 1"));
plteBar3->set_yColumn(bcpx);
plteBar3->set_xColumn(bcpy1);
plteBar3->set_xErrorColumn(bcpye1);
plteBar3->set_width(0.45);
plteBar3->set_shift(-0.25);
plotBarchart2->get_plotter()->addGraph(plteBar3);
plteBar2=new JKQTPbarVerticalGraph(plotBarchart2->get_plotter());
plteBar2->set_yColumn(bcpx);
plteBar2->set_xColumn(bcpy2);
plteBar2->set_xErrorColumn(bcpye2);
plteBar2->set_title(tr("bars 2"));
plteBar2->set_width(0.45);
plteBar2->set_shift(0.25);
plteBar2->set_xErrorSymmetric(false);
plotBarchart2->get_plotter()->addGraph(plteBar2);
JKQTPbarHorizontalErrorGraph* plteBar4=new JKQTPbarHorizontalErrorGraph(plotBarchart2->get_plotter());
plteBar4->set_yColumn(bcpx);
plteBar4->set_xColumn(bcpy2);
plteBar4->set_xErrorColumn(bcpye2);
plteBar4->set_title(tr("bars 2"));
plteBar4->set_width(0.45);
plteBar4->set_shift(0.25);
plteBar4->set_xErrorSymmetric(false);
plotBarchart2->get_plotter()->addGraph(plteBar4);
plteBar2->autoscaleBarWidthAndShift(0.9, 1);
plteBar4->autoscaleBarWidthAndShift(0.9, 1);
plotBarchart2->set_doDrawing(true);
plotBarchart2->zoomToFit();

View File

@ -3,7 +3,7 @@
#include <QDate>
#include <QDateTime>
#include <QApplication>
#include "jkqtpboxplotelements.h"
@ -330,7 +330,7 @@ void TestWidgetGraphs::setESSymbol(int index)
void TestWidgetGraphs::setSortOrder2(int index)
{
if (index==0) pltePlot2->set_sortData(JKQTPxyLineGraph::Unsorted);
if (index==0) pltePlot2->set_sortData(JKQTPxyGraph::Unsorted);
if (index==1) pltePlot2->set_sortData(JKQTPxyLineGraph::SortedX);
if (index==2) pltePlot2->set_sortData(JKQTPxyLineGraph::SortedY);
plotBot->update_plot();

View File

@ -1,5 +1,6 @@
#include <QApplication>
#include "jkqtplotter.h"
#include "jkqtpbarchartelements.h"
#define Ndata 5
int main(int argc, char* argv[])
@ -14,7 +15,7 @@ int main(int argc, char* argv[])
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"};
QString L[Ndata]={ "cat. A", "cat. C", "cat. B", "cat. D", "other"}; // unsorted category axis
double X[Ndata]={ 1, 3, 2, 4, 5};
//QString L[Ndata]={ "cat. A", "cat. B", "cat. C", "cat. D", "other"}; // correctly sorted data!
//double X[Ndata]={ 1, 2, 3, 4, 5};
@ -33,15 +34,15 @@ 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:
JKQTPbarHorizontalGraph* graph1=new JKQTPbarHorizontalGraph(&plot);
JKQTPbarVerticalGraph* graph1=new JKQTPbarVerticalGraph(&plot);
graph1->set_xColumn(columnX);
graph1->set_yColumn(columnY1);
graph1->set_title(QObject::tr("dataset 1"));
JKQTPbarHorizontalGraph* graph2=new JKQTPbarHorizontalGraph(&plot);
JKQTPbarVerticalGraph* graph2=new JKQTPbarVerticalGraph(&plot);
graph2->set_xColumn(columnX);
graph2->set_yColumn(columnY2);
graph2->set_title(QObject::tr("dataset 2"));
JKQTPbarHorizontalGraph* graph3=new JKQTPbarHorizontalGraph(&plot);
JKQTPbarVerticalGraph* graph3=new JKQTPbarVerticalGraph(&plot);
graph3->set_xColumn(columnX);
graph3->set_yColumn(columnY3);
graph3->set_title(QObject::tr("dataset 3"));

View File

@ -0,0 +1,112 @@
#include <QApplication>
#include "jkqtplotter.h"
#include "jkqtpbarchartelements.h"
template<class TGRAPH>
void addGraph(JKQtPlotter& plot, bool swapXY) {
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
plot.get_plotter()->set_useAntiAliasingForGraphs(true); // nicer (but slower) plotting
plot.get_plotter()->set_useAntiAliasingForSystem(true); // nicer (but slower) plotting
plot.get_plotter()->set_useAntiAliasingForText(true); // nicer (but slower) text rendering
JKQTPdatastore* ds=plot.getDatastore();
// 2. now we create data for the charts (taken from https://commons.wikimedia.org/wiki/File:Energiemix_Deutschland.svg)
QVector<double> year, percentage_other, percentage_coaloil, percentage_gas, percentage_nuclear, percentage_green;
year << 1990 << 1995 << 2000 << 2005 << 2010 << 2015;
percentage_other << 3.5 << 3.5 << 4.4 << 4.4 << 5 << 5 ;
percentage_coaloil << 58.7 << 55.7 << 51.5 << 48.2 << 42.9 << 43.1;
percentage_gas << 6.5 << 7.7 << 8.5 << 11.7 << 14.1 << 9.6 ;
percentage_nuclear << 27.7 << 28.7 << 29.4 << 26.2 << 22.2 << 14.2;
percentage_green << 3.6 << 4.4 << 6.2 << 9.5 << 15.8 << 28.1;
// 3. make data available to JKQtPlotter by adding it to the internal datastore.
// Note: In this step the data is copied (of not specified otherwise)
// the variables cYear, cOther ... will contain the internal column ID of the
// newly created columns with names "year" and "other" ... and the (copied) data
size_t cYear=ds->addCopiedColumn(year, "year");
size_t cOther=ds->addCopiedColumn(percentage_other, "other");
size_t cCoalOil=ds->addCopiedColumn(percentage_coaloil, "coal & oil");
size_t cGas=ds->addCopiedColumn(percentage_gas, "natural gas");
size_t cNuclear=ds->addCopiedColumn(percentage_nuclear, "nuclear energy");
size_t cGreen=ds->addCopiedColumn(percentage_green, "green energy");
// 4. create graphs in the plot, which plots the dataset year/other, year/coal, ...
// The color of the graphs is set by calling set_fillColor_and_darkenedColor(), which sets the
// fillColor to the given color and makes the outline of the bars (i.e. their "color") a darker
// shade of the given color.
QVector<TGRAPH*> graphs;
graphs.push_back(new TGRAPH(&plot));
graphs.back()->set_xColumn((!swapXY)?cYear:cOther);
graphs.back()->set_yColumn((!swapXY)?cOther:cYear);
graphs.back()->set_title(QObject::tr("other sources"));
graphs.back()->set_fillColor_and_darkenedColor(QColor("red"));
graphs.push_back(new TGRAPH(&plot));
graphs.back()->set_xColumn((!swapXY)?cYear:cCoalOil);
graphs.back()->set_yColumn((!swapXY)?cCoalOil:cYear);
graphs.back()->set_title(QObject::tr("coal & oil"));
graphs.back()->set_fillColor_and_darkenedColor(QColor("darkgrey"));
graphs.back()->stackUpon(graphs[graphs.size()-2]);
graphs.push_back(new TGRAPH(&plot));
graphs.back()->set_xColumn((!swapXY)?cYear:cGas);
graphs.back()->set_yColumn((!swapXY)?cGas:cYear);
graphs.back()->set_title(QObject::tr("natural gas"));
graphs.back()->set_fillColor_and_darkenedColor(QColor("blue"));
graphs.back()->stackUpon(graphs[graphs.size()-2]);
graphs.push_back(new TGRAPH(&plot));
graphs.back()->set_xColumn((!swapXY)?cYear:cNuclear);
graphs.back()->set_yColumn((!swapXY)?cNuclear:cYear);
graphs.back()->set_title(QObject::tr("nuclear energy"));
graphs.back()->set_fillColor_and_darkenedColor(QColor("gold"));
graphs.back()->stackUpon(graphs[graphs.size()-2]);
graphs.push_back(new TGRAPH(&plot));
graphs.back()->set_xColumn((!swapXY)?cYear:cGreen);
graphs.back()->set_yColumn((!swapXY)?cGreen:cYear);
graphs.back()->set_title(QObject::tr("green energy"));
graphs.back()->set_fillColor_and_darkenedColor(QColor("darkgreen"));
graphs.back()->stackUpon(graphs[graphs.size()-2]);
// 5. add the graphs to the plot, so it is actually displayed
plot.addGraphs(graphs);
// 6. set axis labels
plot.get_xAxis()->set_axisLabel("year");
plot.get_yAxis()->set_axisLabel("fraction of energy production in Germany [%]");
// 7. 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.get_plotter().
plot.get_plotter()->set_keyPosition(JKQTPkeyOutsideTopRight);
plot.get_plotter()->set_keyLayout(JKQTPkeyLayoutOneRow);
// 8 autoscale the plot so the graph is contained
plot.zoomToFit();
// show plotter and make it a decent size
plot.show();
plot.resize(600,400);
}
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
JKQtPlotter plotV;
addGraph<JKQTPbarVerticalStackableGraph>(plotV, false);
plotV.setWindowTitle("JKQTPbarVerticalStackableGraph");
JKQtPlotter plotH;
addGraph<JKQTPbarHorizontalStackableGraph>(plotH, true);
plotH.setWindowTitle("JKQTPbarHorizontalStackableGraph");
plotV.move(100,100);
plotH.move(750,100);
return app.exec();
}

View File

@ -0,0 +1,16 @@
# source code for this simple demo
SOURCES = jkqtplotter_simpletest_stackedbars.cpp
# configure Qt
CONFIG += qt
QT += core gui svg
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
# output executable name
TARGET = jkqtplotter_simpletest_stackedbars
# include JKQtPlotter source code
include(../../jkqtplotter.pri)
# here you can activate some debug options
#DEFINES += SHOW_JKQTPLOTTER_DEBUG
#DEFINES += JKQTBP_AUTOTIMER