diff --git a/README.md b/README.md index 3102a9435b..8d77fb6f83 100644 --- a/README.md +++ b/README.md @@ -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 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 #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 +#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 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 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) diff --git a/doc/images/JKQTPbarHorizontalGraphStacked.png b/doc/images/JKQTPbarHorizontalGraphStacked.png new file mode 100644 index 0000000000..538fcfa247 Binary files /dev/null and b/doc/images/JKQTPbarHorizontalGraphStacked.png differ diff --git a/doc/images/JKQTPbarVerticalGraphStacked.png b/doc/images/JKQTPbarVerticalGraphStacked.png new file mode 100644 index 0000000000..b189f05e5e Binary files /dev/null and b/doc/images/JKQTPbarVerticalGraphStacked.png differ diff --git a/doc/images/plot_bargraphhorplot.png b/doc/images/plot_bargraphhorplot.png index 845294a691..e5a012312e 100644 Binary files a/doc/images/plot_bargraphhorplot.png and b/doc/images/plot_bargraphhorplot.png differ diff --git a/doc/images/plot_bargraphverplot.png b/doc/images/plot_bargraphverplot.png index e5a012312e..845294a691 100644 Binary files a/doc/images/plot_bargraphverplot.png and b/doc/images/plot_bargraphverplot.png differ diff --git a/jkqtmathtext.cpp b/jkqtmathtext.cpp index 5819ae2a9b..b954e50b6c 100644 --- a/jkqtmathtext.cpp +++ b/jkqtmathtext.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () @@ -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+""; @@ -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; jgetSize(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; jgetSize(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 (currentTokenIDaddNode(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+" "; 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*/) { diff --git a/jkqtmathtext.h b/jkqtmathtext.h index 1a2013dc45..f05c97a4cd 100644 --- a/jkqtmathtext.h +++ b/jkqtmathtext.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () @@ -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 > 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. */ diff --git a/jkqtp_imexport.h b/jkqtp_imexport.h index 4586f195f3..67d92a2243 100644 --- a/jkqtp_imexport.h +++ b/jkqtp_imexport.h @@ -3,7 +3,7 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () last modification: $LastChangedDate: 2015-04-02 13:55:22 +0200 (Do, 02 Apr 2015) $ (revision $Rev: 3902 $) diff --git a/jkqtpbarchartelements.cpp b/jkqtpbarchartelements.cpp new file mode 100644 index 0000000000..4a485c37e5 --- /dev/null +++ b/jkqtpbarchartelements.cpp @@ -0,0 +1,939 @@ +/* + Copyright (c) 2008-2018 Jan W. Krieger () + + + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + + + +#include "jkqtpbarchartelements.h" +#include "jkqtpbaseplotter.h" +#include +#include +#include +#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) || (xvsgzgetNextStyle(); + fillColor=parent->getPlotStyle(parentPlotStyle).color(); + } +} + + +JKQTPbarVerticalGraph::JKQTPbarVerticalGraph(JKQtPlotter* parent): + JKQTPxyGraph(parent) +{ + baseline=0.0; + color=QColor("black"); + fillColor=QColor("red"); + style=Qt::SolidLine; + lineWidth=1; + fillStyle=Qt::SolidPattern; + width=0.9; + shift=0; + + + if (parent) { // get style settings from parent object + parentPlotStyle=parent->getNextStyle(); + fillColor=parent->getPlotStyle(parentPlotStyle).color(); + } +} + +void JKQTPbarVerticalGraph::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) { + painter.save(); + QPen p=painter.pen(); + QPen np(Qt::NoPen); + p.setColor(color); + p.setStyle(style); + QBrush b=painter.brush(); + b.setColor(fillColor); + b.setStyle(fillStyle); + //int y=rect.top()+rect.height()/2.0; + painter.setPen(p); + painter.setBrush(b); + painter.drawRect(rect); + painter.restore(); +} + +QColor JKQTPbarVerticalGraph::getKeyLabelColor() { + return fillColor; +} + + +void JKQTPbarVerticalGraph::draw(JKQTPEnhancedPainter& painter) { +#ifdef JKQTBP_AUTOTIMER + JKQTPAutoOutputTimer jkaaot("JKQTPbarHorizontalGraph::draw"); +#endif + if (parent==nullptr) return; + JKQTPdatastore* datastore=parent->getDatastore(); + if (datastore==nullptr) return; + + drawErrorsBefore(painter); + + QPen p=painter.pen(); + p.setColor(color); + p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, lineWidth*parent->get_lineWidthMultiplier()))); + p.setStyle(style); + p.setJoinStyle(Qt::RoundJoin); + + QBrush b=painter.brush(); + b.setColor(fillColor); + b.setStyle(fillStyle); + + int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); + int imin=0; + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end+1, static_cast(imax)); + } + if (imaxx2p(0); +// if (parent->getXAxis()->isLogAxis()) x0=xAxis->x2p(parent->getXAxis()->getMin()); + double y0=yAxis->x2p(0); + if (parent->getYAxis()->isLogAxis()) y0=yAxis->x2p(parent->getYAxis()->getMin()); + double delta=1; + double deltap=0; + double deltam=0; + intSortData(); + const bool hasStackPar=hasStackParent(); + for (int iii=imin; iiiget(static_cast(xColumn),static_cast(i)); + 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(yColumn),static_cast(i)); + double yv0=y0; + if (!qFuzzyIsNull(baseline)) yv0=yAxis->x2p(baseline); + if (hasStackPar) { + double stackLastY=getParentStackedMax(i); + const double yvold=yv; + yv0=yAxis->x2p(stackLastY)-(get_lineWidth()); + yv=stackLastY+yvold; + } + if (sr<0 && lr<0) { // only one x-value + deltam=0.5; + deltap=0.5; + } else if (lr<0) { // the right-most x-value + deltap=deltam=fabs(xv-datastore->get(xColumn,sr))/2.0; + } else if (sr<0) { // the left-most x-value + deltam=deltap=fabs(datastore->get(xColumn,lr)-xv)/2.0; + } else { + deltam=fabs(xv-datastore->get(xColumn,sr))/2.0; + deltap=fabs(datastore->get(xColumn,lr)-xv)/2.0; + } + //std::cout<x2p(xv+shift*delta-width*deltam); + double y=yAxis->x2p(yv); + double xx=xAxis->x2p(xv+shift*delta+width*deltap); + double yy=yv0; + + //std::cout<<"delta="<getDatastore(); + if (datastore==nullptr) return; + + drawErrorsBefore(painter); + + QPen p=painter.pen(); + p.setColor(color); + p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, lineWidth*parent->get_lineWidthMultiplier()))); + p.setStyle(style); + p.setJoinStyle(Qt::RoundJoin); + + QBrush b=painter.brush(); + b.setColor(fillColor); + b.setStyle(fillStyle); + + int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); + int imin=0; + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end+1, static_cast(imax)); + } + if (imaxx2p(0); + if (parent->getXAxis()->isLogAxis()) x0=xAxis->x2p(parent->getXAxis()->getMin()); +// double y0=yAxis->x2p(0); +// if (parent->getYAxis()->isLogAxis()) y0=yAxis->x2p(parent->getYAxis()->getMin()); + double delta=1; + double deltap=0; + double deltam=0; + painter.save(); + intSortData(); + const bool hasStackPar=hasStackParent(); + for (int iii=imin; iiiget(static_cast(xColumn),static_cast(i)); + double yv=datastore->get(static_cast(yColumn),static_cast(i)); + 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="<0) { + smallestGreaterZero=baseline; + minx=baseline; + maxx=baseline; + } + + if (parent==nullptr) return false; + + JKQTPdatastore* datastore=parent->getDatastore(); + int imin=0; + int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(xColumn)).getRows()); + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end, static_cast(imax)); + } + if (imaxmaxx) maxx=xv; + if (xvget(static_cast(xColumn),static_cast(i)); + if (JKQTPIsOKFloat(xv)) { + if (xv>maxx) maxx=xv; + if (xvgetDatastore(); + int imin=0; + int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end, static_cast(imax)); + } + if (imaxget(static_cast(yColumn),static_cast(i)); + double delta, deltap, deltam; + 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.0pt2px(painter, parent->get_lineWidthMultiplier()*lineWidth))); + p.setStyle(style); + p.setJoinStyle(Qt::RoundJoin); + p.setCapStyle(Qt::RoundCap); + + return p; +} + +double JKQTPbarVerticalGraph::getParentStackedMax(int index) const +{ + return false; +} + +bool JKQTPbarVerticalGraph::hasStackParent() const +{ + return false; +} + +double JKQTPbarVerticalGraph::getStackedMax(int /*index*/) const +{ + return baseline; +} + + + +bool JKQTPbarVerticalGraph::isHorizontal() const +{ + return false; +} + +void JKQTPbarVerticalGraph::set_fillColor_and_darkenedColor(QColor fill, int colorDarker) +{ + set_fillColor(fill); + set_color(fill.darker(colorDarker)); +} + +JKQTPbarHorizontalErrorGraph::JKQTPbarHorizontalErrorGraph(JKQtBasePlotter *parent): + JKQTPbarHorizontalGraph(parent), JKQTPxGraphErrors() +{ + setErrorColorFromGraphColor(color); +} + +JKQTPbarHorizontalErrorGraph::JKQTPbarHorizontalErrorGraph(JKQtPlotter *parent): + JKQTPbarHorizontalGraph(parent), JKQTPxGraphErrors() +{ + setErrorColorFromGraphColor(color); +} + +bool JKQTPbarHorizontalErrorGraph::usesColumn(int c) +{ + return JKQTPbarHorizontalGraph::usesColumn(c)|| JKQTPxGraphErrors::errorUsesColumn(c); +} + +bool JKQTPbarHorizontalErrorGraph::getXMinMax(double &minx, double &maxx, double &smallestGreaterZero) +{ + if (xErrorColumn<0 || xErrorStyle==JKQTPnoError) { + return JKQTPbarHorizontalGraph::getXMinMax(minx, maxx, smallestGreaterZero); + } else { + bool start=false; + minx=0; + maxx=0; + smallestGreaterZero=0; + + if (parent==nullptr) return false; + + JKQTPdatastore* datastore=parent->getDatastore(); + int imin=0; + int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end, static_cast(imax)); + } + if (imaxget(static_cast(xColumn),static_cast(i))+getXErrorU(i, datastore); + double xvv=datastore->get(static_cast(xColumn),static_cast(i))-getXErrorL(i, datastore); + if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(xvv) ) { + if (start || xv>maxx) maxx=xv; + if (start || xvmaxx) maxx=xvv; + if (start || xvv0) { + smallestGreaterZero=baseline; + miny=baseline; + maxy=baseline; + } + + if (parent==nullptr) return false; + + JKQTPdatastore* datastore=parent->getDatastore(); + int imin=0; + int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end, static_cast(imax)); + } + if (imaxmaxy) maxy=yv; + if (yvget(static_cast(yColumn),static_cast(i)); + if (JKQTPIsOKFloat(yv)) { + if (yv>maxy) maxy=yv; + if (yv0) { + smallestGreaterZero=baseline; + miny=baseline; + maxy=baseline; + } + + if (parent==nullptr) return false; + + JKQTPdatastore* datastore=parent->getDatastore(); + int imin=0; + int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end, static_cast(imax)); + } + if (imaxget(static_cast(yColumn),static_cast(i))+getYErrorU(i, datastore); + double yvv=datastore->get(static_cast(yColumn),static_cast(i))-getYErrorL(i, datastore); + if (JKQTPIsOKFloat(yv) && JKQTPIsOKFloat(yvv) ) { + if (start || yv>maxy) maxy=yv; + if (start || yvmaxy) maxy=yvv; + if (start || yvvgetStackedMax(index); + } else { + return 0.0; + } +} + +bool JKQTPbarVerticalStackableGraph::hasStackParent() const +{ + return stackParent!=nullptr; +} + +const JKQTPbarVerticalStackableGraph *JKQTPbarVerticalStackableGraph::getStackParent() const +{ + return stackParent; +} + + + +double JKQTPbarVerticalStackableGraph::getStackedMax(int index) const +{ + double height=0; + if (parent!=nullptr) { + JKQTPdatastore* datastore=parent->getDatastore(); + height=datastore->get(static_cast(yColumn),static_cast(index)); + } + if (stackParent==nullptr) { + return height; + } else { + return stackParent->getStackedMax(index)+height; + } +} + +JKQTPbarHorizontalStackableGraph::JKQTPbarHorizontalStackableGraph(JKQtBasePlotter *parent): + JKQTPbarHorizontalGraph(parent), stackParent(nullptr) +{ + +} + +JKQTPbarHorizontalStackableGraph::JKQTPbarHorizontalStackableGraph(JKQtPlotter *parent): + JKQTPbarHorizontalGraph(parent), stackParent(nullptr) +{ + +} + +void JKQTPbarHorizontalStackableGraph::stackUpon(JKQTPbarHorizontalStackableGraph *parentGraph) +{ + stackParent=parentGraph; +} + +void JKQTPbarHorizontalStackableGraph::dontStackUpon() +{ + stackParent=nullptr; +} + +const JKQTPbarHorizontalStackableGraph *JKQTPbarHorizontalStackableGraph::getStackParent() const +{ + return stackParent; +} + + +double JKQTPbarHorizontalStackableGraph::getStackedMax(int index) const +{ + double height=0; + if (parent!=nullptr) { + JKQTPdatastore* datastore=parent->getDatastore(); + height=datastore->get(static_cast(xColumn),static_cast(index)); + } + if (stackParent==nullptr) { + return height; + } else { + return stackParent->getStackedMax(index)+height; + } +} + +double JKQTPbarHorizontalStackableGraph::getParentStackedMax(int index) const +{ + if (stackParent) { + return stackParent->getStackedMax(index); + } else { + return 0.0; + } +} + +bool JKQTPbarHorizontalStackableGraph::hasStackParent() const +{ + return stackParent!=nullptr; +} diff --git a/jkqtpbarchartelements.h b/jkqtpbarchartelements.h new file mode 100644 index 0000000000..f2c89f756c --- /dev/null +++ b/jkqtpbarchartelements.h @@ -0,0 +1,362 @@ +/* + Copyright (c) 2008-2018 Jan W. Krieger () + + + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + + + +/** + * \defgroup jkqtplotter_elements Plot Elements + * \ingroup jkqtplotter + * \defgroup jkqtplotter_plots Graphs + * \ingroup jkqtplotter_elements + */ + +/** \file jkqtpelements.h + * \ingroup jkqtplotter + */ + +#include +#include +#include +#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 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 diff --git a/jkqtpbaseelements.cpp b/jkqtpbaseelements.cpp index 02f517330f..bd0ded599c 100644 --- a/jkqtpbaseelements.cpp +++ b/jkqtpbaseelements.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () @@ -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 &x, const QStringList &label) { + for (int i=0; i &x, const QString *label) { + for (int i=0; itickSpacing = __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; } + diff --git a/jkqtpbaseelements.h b/jkqtpbaseelements.h index 62d935fd6a..f9b1a92747 100644 --- a/jkqtpbaseelements.h +++ b/jkqtpbaseelements.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () @@ -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& x, const QStringList& label) { - for (int i=0; i& 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& x, const QString* label) { - for (int i=0; i& 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\copybrief tickSpacing. * \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:
\copybrief axisMinWidth.
* \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:
\copybrief autoAxisSpacing.
* \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:
\copybrief minorTickLabelsEnabled.
* \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:
\copybrief logAxis.
@@ -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:
\copybrief logAxisBase.
* \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:
\copybrief userTickSpacing.
* \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:
\copybrief userLogTickSpacing.
* \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:
\copybrief labelType.
* \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:
\copybrief tickMode.
@@ -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:
\copybrief tickMode.
* \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:
\copybrief axisLabel.
* \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:
\copybrief labelPosition.
*/ - 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:
\copybrief labelFont.
*/ - 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:
\copybrief labelFontSize.
*/ - 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:
\copybrief tickLabelFont.
*/ - 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:
\copybrief tickTimeFormat.
*/ - 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:
\copybrief tickDateFormat.
*/ - 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:
\copybrief tickDateTimeFormat.
*/ - 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:
\copybrief tickLabelFontSize.
*/ - 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:
\copybrief minorTickLabelFontSize.
*/ - 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:
\copybrief minorTickLabelFullNumber.
*/ - 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:
\copybrief minTicks.
*/ - 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:
\copybrief minorTicks.
*/ - 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:
\copybrief minorTicks.
*/ - 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:
\copybrief tickOutsideLength.
*/ - 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:
\copybrief minorTickOutsideLength.
*/ - 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:
\copybrief tickInsideLength.
*/ - 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:
\copybrief minorTickInsideLength.
*/ - 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:
\copybrief axisColor.
*/ - 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:
\copybrief showZeroAxis.
*/ - 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:
\copybrief inverted.
*/ - 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:
\copybrief gridColor.
*/ - 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:
\copybrief minorGridColor.
*/ - 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:
\copybrief gridWidth.
*/ - 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:
\copybrief gridStyle.
*/ - 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:
\copybrief minorGridWidth.
*/ - 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:
\copybrief minorGridStyle.
*/ - 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:
\copybrief drawMode1.
*/ - 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:
\copybrief drawMode2.
*/ - 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:
\copybrief minorTickWidth.
*/ - 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:
\copybrief tickWidth.
*/ - 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:
\copybrief lineWidth.
*/ - 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:
\copybrief lineWidthZeroAxis.
*/ - 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:
\copybrief tickLabelDistance.
*/ - 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:
\copybrief labelDistance.
*/ - 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:
\copybrief labelDigits.
*/ - 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:
\copybrief drawGrid.
*/ - 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:
\copybrief drawMinorGrid.
*/ - 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:
\copybrief tickLabelAngle.
*/ - 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; diff --git a/jkqtpbasegraphs.cpp b/jkqtpbasegraphs.cpp new file mode 100644 index 0000000000..22853708e4 --- /dev/null +++ b/jkqtpbasegraphs.cpp @@ -0,0 +1,1104 @@ +/* + Copyright (c) 2008-2018 Jan W. Krieger () + + + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + + + +#include "jkqtpbasegraphs.h" +#include "jkqtpbaseplotter.h" +#include +#include +#include +#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) || (xvsgzget_plotter()) +{ + datarange_end=datarange_start=-1; + title=""; + visible=true; + setParent(parent->get_plotter()); +} + +JKQTPgraph::~JKQTPgraph() +{ + +} + +QImage JKQTPgraph::generateKeyMarker(QSize size) +{ + QImage img(size.width(),size.height(),QImage::Format_ARGB32); + if (parent) img.fill(parent->get_keyBackgroundColor()); + { + JKQTPEnhancedPainter painter(&img); + painter.setRenderHint(QPainter::Antialiasing, true); + painter.setRenderHint(QPainter::TextAntialiasing, true); + painter.setRenderHint(QPainter::SmoothPixmapTransform, true); + painter.setRenderHint(QPainter::HighQualityAntialiasing, true); + QRectF rect(0,0,size.width(),size.height()); + drawKeyMarker(painter, rect); + } + return img; +} + +QPointF JKQTPgraph::transform(const QPointF& x) { + if (xAxis&&yAxis) return QPointF(xAxis->x2p(x.x()), yAxis->x2p(x.y())); + return QPointF(); +} + +QPointF JKQTPgraph::backTransform(const QPointF& x) { + if (xAxis&&yAxis) return QPointF(xAxis->p2x(x.x()), yAxis->p2x(x.y())); + return QPointF(); +} + +void JKQTPgraph::setParent(JKQtBasePlotter* parent) { + this->parent=parent; + if (parent) { + this->xAxis=parent->getXAxis(); + this->yAxis=parent->getYAxis(); + } else { + xAxis=nullptr; + yAxis=nullptr; + } + QObject::setParent(parent); +} + +void JKQTPgraph::setParent(JKQtPlotter *parent) +{ + setParent(parent->get_plotter()); +} + +QVector JKQTPgraph::transform(const QVector& x) { + QVector res; + for (int i=0; i& x) { + QPainterPath res; + if (x.size()>0) { + res.moveTo(transform(x[0])); + for (int i=1; igetDatastore(); + int imin=0; + int imax=datastore->getColumn(column).getRows(); + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end, static_cast(imax)); + } + if (imaxget(column,i); + if (start || xv>maxx) maxx=xv; + if (start || xvgetDatastore(); + int imin=0; + int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end, static_cast(imax)); + } + if (imaxget(static_cast(xColumn),static_cast(i)); + if (JKQTPIsOKFloat(xv)) { + if (start || xv>maxx) maxx=xv; + if (start || xvgetDatastore(); + int imin=0; + int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end, static_cast(imax)); + } + if (imaxget(static_cast(yColumn),static_cast(i)); + if (JKQTPIsOKFloat(yv)) { + if (start || yv>maxy) maxy=yv; + if (start || yvgetNextStyle(); + //std::cout<<"got style settings from parent: "<getPlotStyle(parentPlotStyle).color(); + style=parent->getPlotStyle(parentPlotStyle).style(); + } + +} + +JKQTPsingleColumnGraph::JKQTPsingleColumnGraph(int dataColumn, JKQtBasePlotter *parent): + JKQTPgraph(parent) +{ + sortData=Unsorted; + this->dataColumn=dataColumn; + parentPlotStyle=-1; + color=QColor("red"); + style=Qt::SolidLine; + lineWidth=2; + parentPlotStyle=-1; + + if (parent) { // get style settings from parent object + parentPlotStyle=parent->getNextStyle(); + //std::cout<<"got style settings from parent: "<getPlotStyle(parentPlotStyle).color(); + style=parent->getPlotStyle(parentPlotStyle).style(); + } +} + +JKQTPsingleColumnGraph::JKQTPsingleColumnGraph(int dataColumn, QColor color, Qt::PenStyle style, double lineWidth, JKQtBasePlotter *parent): + JKQTPgraph(parent) +{ + sortData=Unsorted; + this->dataColumn=dataColumn; + this->color=color; + this->style=style; + this->lineWidth=lineWidth; + parentPlotStyle=-1; +} + + +JKQTPsingleColumnGraph::JKQTPsingleColumnGraph(JKQtPlotter *parent): + JKQTPgraph(parent) +{ + sortData=Unsorted; + dataColumn=-1; + color=QColor("red"); + style=Qt::SolidLine; + lineWidth=2; + parentPlotStyle=-1; + + if (parent) { // get style settings from parent object + parentPlotStyle=parent->getNextStyle(); + //std::cout<<"got style settings from parent: "<getPlotStyle(parentPlotStyle).color(); + style=parent->getPlotStyle(parentPlotStyle).style(); + } + +} + +JKQTPsingleColumnGraph::JKQTPsingleColumnGraph(int dataColumn, JKQtPlotter *parent): + JKQTPgraph(parent) +{ + sortData=Unsorted; + this->dataColumn=dataColumn; + parentPlotStyle=-1; + color=QColor("red"); + style=Qt::SolidLine; + lineWidth=2; + parentPlotStyle=-1; + + if (parent) { // get style settings from parent object + parentPlotStyle=parent->getNextStyle(); + //std::cout<<"got style settings from parent: "<getPlotStyle(parentPlotStyle).color(); + style=parent->getPlotStyle(parentPlotStyle).style(); + } +} + +JKQTPsingleColumnGraph::JKQTPsingleColumnGraph(int dataColumn, QColor color, Qt::PenStyle style, double lineWidth, JKQtPlotter *parent): + JKQTPgraph(parent) +{ + sortData=Unsorted; + this->dataColumn=dataColumn; + this->color=color; + this->style=style; + this->lineWidth=lineWidth; + parentPlotStyle=-1; +} + +JKQTPsingleColumnGraph::JKQTPsingleColumnGraph(int dataColumn, QColor color, Qt::PenStyle style, JKQtPlotter *parent): + JKQTPgraph(parent) +{ + sortData=Unsorted; + this->dataColumn=dataColumn; + this->color=color; + this->style=style; + this->lineWidth=2.0; + parentPlotStyle=-1; +} + +JKQTPsingleColumnGraph::JKQTPsingleColumnGraph(int dataColumn, QColor color, JKQtPlotter *parent): + JKQTPgraph(parent) +{ + sortData=Unsorted; + this->dataColumn=dataColumn; + this->color=color; + this->style=Qt::SolidLine; + this->lineWidth=2.0; + parentPlotStyle=-1; +} +QColor JKQTPsingleColumnGraph::getKeyLabelColor() +{ + return color; +} + +bool JKQTPsingleColumnGraph::usesColumn(int c) +{ + return c==dataColumn; +} + +QPen JKQTPsingleColumnGraph::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; +} + +void JKQTPsingleColumnGraph::intSortData() +{ + sortedIndices.clear(); + + + + if (parent==nullptr) return ; + + JKQTPdatastore* datastore=parent->getDatastore(); + int imin=0; + int imax=datastore->getColumn(dataColumn).getRows(); + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end, static_cast(imax)); + } + if (imax datas; + + if (sortData==JKQTPsingleColumnGraph::Sorted) { + + for (int i=0; iget(dataColumn,i); + sortedIndices<* dataorder) { + //std::cout<<"JKQTPgraphErrors::intPlotXYErrorIndicators(p, "<getDatastore(); + if (datastore==nullptr) return; + + if ((yErrorStyle==JKQTPnoError) && (xErrorStyle==JKQTPnoError)) return; + bool visX=(xErrorStyle!=JKQTPnoError)&&(xErrorColumn>=0||xErrorColumnLower>=0)&&(xColumn>=0)&&(yColumn>=0); + bool visY=(yErrorStyle!=JKQTPnoError)&&(yErrorColumn>=0||yErrorColumnLower>=0)&&(xColumn>=0)&&(yColumn>=0); + if (!visX&&!visY) return; + //std::cout<<" JKQTPgraphErrors::intPlotXYErrorIndicators(p, "<pt2px(painter, errorWidth*parent->get_lineWidthMultiplier()))); + p.setStyle(errorStyle); + p.setJoinStyle(Qt::RoundJoin); + p.setCapStyle(Qt::RoundCap); + painter.setPen(p); + + unsigned long long imaxx=0, imaxy=0; + if (xColumn>=0) imaxx=datastore->getColumn(static_cast(xColumn)).getRows(); + if (yColumn>=0) imaxy=datastore->getColumn(static_cast(yColumn)).getRows(); + int imax=qMin(imaxx, imaxy); + int imin=0; + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end, static_cast(imax)); + } + if (imaxpt2px(painter, errorbarSize); + QPolygonF polyX, polyY; + QList polyXTopPoints, polyXBottomPoints, polyYTopPoints, polyYBottomPoints; + QList errFC, errC; + bool defaultErrorColor=true; + + + /* + * double delta=1; + double deltap=0; + double deltam=0; + for (int i=imin; iget(static_cast(xColumn),static_cast(i)); + double yv=datastore->get(static_cast(yColumn),static_cast(i)); + if (imin==imax) { // only one x-value + deltam=0.5; + deltap=0.5; + } else if (i==imax-1) { // the right-most x-value + deltap=deltam=fabs(xv-datastore->get(xColumn,i-1))/2.0; + } else if (i==imin) { // the left-most x-value + deltam=deltap=fabs(datastore->get(xColumn,i+1)-xv)/2.0; + } else { + deltam=fabs(xv-datastore->get(xColumn,i-1))/2.0; + deltap=fabs(datastore->get(xColumn,i+1)-xv)/2.0; + } + delta=deltap+deltam; + **/ + + for (int iii=imin; iiivalue(iii, iii); + double xv=datastore->get(static_cast(xColumn),static_cast(i)); + double yv=datastore->get(static_cast(yColumn),static_cast(i)); + + double deltax=1; + double deltapx=0; + double deltamx=0; + if (imin==imax) { // only one x-value + deltamx=0.5; + deltapx=0.5; + } else if (i==imax-1&& i-1>=0) { // the right-most x-value + deltapx=deltamx=fabs(xv-datastore->get(xColumn,i-1))/2.0; + } else if (i==imin && i+1get(xColumn,i+1)-xv)/2.0; + } else { + if (i-1>=0) deltamx=fabs(xv-datastore->get(xColumn,i-1))/2.0; + if (i+1get(xColumn,i+1)-xv)/2.0; + } + deltax=deltapx+deltamx; + + double deltay=1; + double deltapy=0; + double deltamy=0; + if (imin==imax) { // only one y-value + deltamy=0.5; + deltapy=0.5; + } else if (i==imax-1&& i-1>=0) { // the right-most y-value + deltapy=deltamy=fabs(yv-datastore->get(yColumn,i-1))/2.0; + } else if (i==imin && i+1get(yColumn,i+1)-yv)/2.0; + } else { + if (i-1>=0) deltamy=fabs(yv-datastore->get(yColumn,i-1))/2.0; + if (i+1get(yColumn,i+1)-yv)/2.0; + } + deltay=deltapy+deltamy; + + bool plotlowerbarx=false; + bool plotupperbarx=false; + bool plotlowerbary=false; + bool plotupperbary=false; + + double xe=0; if (xErrorStyle!=JKQTPnoError && xErrorColumn>=0) { xe=datastore->get(xErrorColumn,i); plotupperbarx=true; } + double ye=0; if (yErrorStyle!=JKQTPnoError && yErrorColumn>=0) { ye=datastore->get(yErrorColumn,i); plotupperbary=true; } + double xl=0; if (xErrorSymmetric) { xl=xe; plotlowerbarx=plotupperbarx||(xl>0); } + else if (xErrorStyle!=JKQTPnoError && xErrorColumnLower>=0) { xl=datastore->get(xErrorColumnLower,i); plotlowerbarx=true; } + double yl=0; if (yErrorSymmetric) { yl=ye; plotlowerbary=plotupperbary||(yl>0); } + else if (yErrorStyle!=JKQTPnoError && yErrorColumnLower>=0) { yl=datastore->get(yErrorColumnLower,i); plotlowerbary=true; } + if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv) && JKQTPIsOKFloat(xe) && JKQTPIsOKFloat(ye) && JKQTPIsOKFloat(xl) && JKQTPIsOKFloat(yl)) { + double x=xAxis->x2p(xv+xrelshift*deltax); bool xok=JKQTPIsOKFloat(x); + double y=yAxis->x2p(yv+yrelshift*deltay); bool yok=JKQTPIsOKFloat(y); + QColor terrCol=errorColor; + QColor terrFillCol=errorFillColor; + defaultErrorColor = defaultErrorColor && !this->intPlotXYErrorIndicatorsGetColor(painter, parent, xAxis, yAxis, xColumn, yColumn, xErrorColumn, yErrorColumn, xErrorStyle, yErrorStyle, i, terrCol, terrFillCol); + + // x-errorpolygons + if (/*pastFirst &&*/ (xErrorStyle==JKQTPerrorPolygons || xErrorStyle==JKQTPerrorBarsPolygons || xErrorStyle==JKQTPerrorSimpleBarsPolygons)) { + //double xl1m=xmold; + //double xl1p=xpold; + //double yl1=yold; + double xl2m=xAxis->x2p(xv+xrelshift*deltax-xl); + double xl2p=xAxis->x2p(xv+xrelshift*deltax+xe); + double yl2=y; + /*painter.save(); + painter.setBrush(b); + painter.setPen(QPen(Qt::NoPen)); + QPolygonF poly; + poly << QPointF(xl1p, yl1) << QPointF(xl1m, yl1) << QPointF(xl2m, yl2) << QPointF(xl2p, yl2); + painter.drawConvexPolygon(poly); + painter.restore();*/ + polyXTopPoints<x2p(yv+yrelshift*deltay-yl); + double yl2p=yAxis->x2p(yv+yrelshift*deltay+ye); + double xl2=x; + /*painter.save(); + painter.setBrush(b); + painter.setPen(QPen(Qt::NoPen)); + QPolygonF poly; + poly << QPointF(xl1, yl1m) << QPointF(xl2, yl2m) << QPointF(xl2, yl2p) << QPointF(xl1, yl1p); + painter.drawConvexPolygon(poly); + painter.restore();*/ + polyYTopPoints<=xmin && xv<=xmax && yv>=ymin && yv<=ymax) { + //x-errorbars + if ((xErrorColumn>=0 || xErrorColumnLower>=0) && (xErrorStyle==JKQTPerrorBars || xErrorStyle==JKQTPerrorBarsLines|| xErrorStyle==JKQTPerrorBarsPolygons + || xErrorStyle==JKQTPerrorSimpleBars || xErrorStyle==JKQTPerrorSimpleBarsLines|| xErrorStyle==JKQTPerrorSimpleBarsPolygons)) { + double x0=xAxis->x2p(xv+xrelshift*deltax-xl); bool x0ok=JKQTPIsOKFloat(x0); + double x1=xAxis->x2p(xv+xrelshift*deltax+xe); bool x1ok=JKQTPIsOKFloat(x1); + painter.save(); + QPen pp=p; + pp.setColor(terrCol); + painter.setPen(pp); + if (x0ok&&x1ok&&xok&&yok) { + painter.drawLine(QLineF(x0, y, x1, y)); + if (xErrorStyle==JKQTPerrorBars || xErrorStyle==JKQTPerrorBarsLines|| xErrorStyle==JKQTPerrorBarsPolygons) { + if (plotlowerbarx) painter.drawLine(QLineF(x0,y-ebs_px/2.0,x0,y+ebs_px/2.0)); + if (plotupperbarx) painter.drawLine(QLineF(x1,y-ebs_px/2.0,x1,y+ebs_px/2.0)); + } + } else if (x0ok&&!x1ok&&xok&&yok) { + painter.drawLine(QLineF(x0, y, x, y)); + if (xErrorStyle==JKQTPerrorBars || xErrorStyle==JKQTPerrorBarsLines|| xErrorStyle==JKQTPerrorBarsPolygons) { + if (plotlowerbarx) painter.drawLine(QLineF(x0,y-ebs_px/2.0,x0,y+ebs_px/2.0)); + } + if (x0x2p(parent->getXMax()),y)); + else painter.drawLine(QLineF(x,y,xAxis->x2p(parent->getXMin()),y)); + } else if (!x0ok&&x1ok&&xok&&yok) { + painter.drawLine(QLineF(x1, y, x, y)); + if (xErrorStyle==JKQTPerrorBars || xErrorStyle==JKQTPerrorBarsLines|| xErrorStyle==JKQTPerrorBarsPolygons) { + if (plotupperbarx) painter.drawLine(QLineF(x1,y-ebs_px/2.0,x1,y+ebs_px/2.0)); + } + if (x1x2p(parent->getXMin()),y)); + else painter.drawLine(QLineF(x,y,xAxis->x2p(parent->getXMax()),y)); + } + painter.restore(); + } + // y-errorbars + if ((yErrorColumn>=0 || yErrorColumnLower>=0) && (yErrorStyle==JKQTPerrorBars || yErrorStyle==JKQTPerrorBarsLines || yErrorStyle==JKQTPerrorBarsPolygons + || yErrorStyle==JKQTPerrorSimpleBars || yErrorStyle==JKQTPerrorSimpleBarsLines || yErrorStyle==JKQTPerrorSimpleBarsPolygons)) { + double y0=yAxis->x2p(yv+yrelshift*deltay-yl); bool y0ok=JKQTPIsOKFloat(y0); + double y1=yAxis->x2p(yv+yrelshift*deltay+ye); bool y1ok=JKQTPIsOKFloat(y1); + painter.save(); + QPen pp=p; + pp.setColor(terrCol); + painter.setPen(pp); + if (y0ok&&y1ok&&xok&&yok) { + painter.drawLine(QLineF(x, y0, x, y1)); + if (yErrorStyle==JKQTPerrorBars || yErrorStyle==JKQTPerrorBarsLines || yErrorStyle==JKQTPerrorBarsPolygons) { + if (plotlowerbary) painter.drawLine(QLineF(x-ebs_px/2.0,y0,x+ebs_px/2.0,y0)); + if (plotupperbary) painter.drawLine(QLineF(x-ebs_px/2.0,y1,x+ebs_px/2.0,y1)); + } + } else if (y0ok&&!y1ok&&xok&&yok) { // upper errorbar OK, lower errorbar NAN + painter.drawLine(QLineF(x, y0, x, y)); + if (yErrorStyle==JKQTPerrorBars || yErrorStyle==JKQTPerrorBarsLines || yErrorStyle==JKQTPerrorBarsPolygons) { + if (plotlowerbary) painter.drawLine(QLineF(x-ebs_px/2.0,y0,x+ebs_px/2.0,y0)); + } + if (y0x2p(parent->getYMin()))); + else painter.drawLine(QLineF(x,y,x,yAxis->x2p(parent->getYMax()))); // inverted axis! + } else if (!y0ok&&y1ok&&xok&&yok) { + painter.drawLine(QLineF(x, y1, x, y)); + if (yErrorStyle==JKQTPerrorBars || yErrorStyle==JKQTPerrorBarsLines || yErrorStyle==JKQTPerrorBarsPolygons) { + if (plotupperbary) painter.drawLine(QLineF(x-ebs_px/2.0,y1,x+ebs_px/2.0,y1)); + } + if (y1x2p(parent->getYMax()))); + else painter.drawLine(QLineF(x,y,x,yAxis->x2p(parent->getYMin()))); + } + + painter.restore(); + } + + // error boxes + if (yErrorStyle==JKQTPerrorBoxes || xErrorStyle==JKQTPerrorBoxes || yErrorStyle==JKQTPerrorEllipses || xErrorStyle==JKQTPerrorEllipses ) { + double y0=yAxis->x2p(yv+yrelshift*deltay-yl); bool y0ok=JKQTPIsOKFloat(y0); + double y1=yAxis->x2p(yv+yrelshift*deltay+ye); bool y1ok=JKQTPIsOKFloat(y1); + double x0=xAxis->x2p(xv+xrelshift*deltax-xl); bool x0ok=JKQTPIsOKFloat(x0); + double x1=xAxis->x2p(xv+xrelshift*deltax+xe); bool x1ok=JKQTPIsOKFloat(x1); + painter.save(); + QPen pp=p; + pp.setColor(terrCol); + painter.setPen(pp); + QBrush bb=b; + bb.setColor(terrFillCol); + painter.setBrush(bb); + + QRectF errRect=QRectF(QPointF(x0,y0), QPointF(x1,y1)); + if ((y0ok&&y1ok)||(x0ok&&x1ok)) { + if (yErrorStyle==JKQTPerrorEllipses || xErrorStyle==JKQTPerrorEllipses) painter.drawEllipse(errRect); + else painter.drawRect(errRect); + } + + painter.restore(); + } //} + + // x-errorlines + if (pastFirst && (xErrorStyle==JKQTPerrorLines || xErrorStyle==JKQTPerrorBarsLines || xErrorStyle==JKQTPerrorSimpleBarsLines)) { + double xl1m=xmold; + double xl1p=xpold; + double yl1=yold; + double xl2m=xAxis->x2p(xv+xrelshift*deltax-xl); + double xl2p=xAxis->x2p(xv+xrelshift*deltax+xe); + double yl2=y; + painter.save(); + QPen pp=p; + pp.setColor(terrCol); + painter.setPen(pp); + if (JKQTPIsOKFloat(xl1m)&&JKQTPIsOKFloat(yl1)&&JKQTPIsOKFloat(xl2m)&&JKQTPIsOKFloat(yl2)) { + painter.drawLine(QLineF(xl1m, yl1, xl2m, yl2)); + } + if (JKQTPIsOKFloat(xl1p)&&JKQTPIsOKFloat(yl1)&&JKQTPIsOKFloat(xl2p)&&JKQTPIsOKFloat(yl2)) { + painter.drawLine(QLineF(xl1p, yl1, xl2p, yl2)); + } + painter.restore(); + } + + + // y-errorlines + if (pastFirst && (yErrorStyle==JKQTPerrorLines || yErrorStyle==JKQTPerrorBarsLines || yErrorStyle==JKQTPerrorSimpleBarsLines)) { + double yl1m=ymold; + double yl1p=ypold; + double xl1=xold; + double yl2m=yAxis->x2p(yv+yrelshift*deltay-yl); + double yl2p=yAxis->x2p(yv+yrelshift*deltay+ye); + double xl2=x; + painter.save(); + QPen pp=p; + pp.setColor(terrCol); + painter.setPen(pp); + if (JKQTPIsOKFloat(xl1)&&JKQTPIsOKFloat(yl1m)&&JKQTPIsOKFloat(xl2)&&JKQTPIsOKFloat(yl2m)) { + painter.drawLine(QLineF(xl1, yl1m, xl2, yl2m)); + } + if (JKQTPIsOKFloat(xl1)&&JKQTPIsOKFloat(yl1p)&&JKQTPIsOKFloat(xl2)&&JKQTPIsOKFloat(yl2p)) { + painter.drawLine(QLineF(xl1, yl1p, xl2, yl2p)); + } + painter.restore(); + } + + + + pastFirst=true; + xold=x; + xmold=xAxis->x2p(xv+xrelshift*deltax-xl); + xpold=xAxis->x2p(xv+xrelshift*deltax+xe); + yold=y; + ymold=yAxis->x2p(yv+yrelshift*deltay-yl); + ypold=yAxis->x2p(yv+yrelshift*deltay+ye); + } + } + // x-errorpolygons + if ((polyXTopPoints.size()>0 || polyXBottomPoints.size()>0) && (xErrorStyle==JKQTPerrorPolygons || xErrorStyle==JKQTPerrorBarsPolygons || xErrorStyle==JKQTPerrorSimpleBarsPolygons)) { + painter.save(); + painter.setBrush(b); + painter.setPen(QPen(Qt::NoPen)); + QPolygonF poly; + //poly << QPointF(xl1p, yl1) << QPointF(xl1m, yl1) << QPointF(xl2m, yl2) << QPointF(xl2p, yl2); + for (int i=0; i=0; i--) { + poly<0 || polyYBottomPoints.size()>0) && (yErrorStyle==JKQTPerrorPolygons || yErrorStyle==JKQTPerrorBarsPolygons || yErrorStyle==JKQTPerrorSimpleBarsPolygons)) { + painter.save(); + painter.setBrush(b); + painter.setPen(QPen(Qt::NoPen)); + QPolygonF poly; + //poly << QPointF(xl1p, yl1) << QPointF(xl1m, yl1) << QPointF(xl2m, yl2) << QPointF(xl2p, yl2); + for (int i=0; i=0; i--) { + poly<* dataorder) { + intPlotXYErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, xErrorColumn, -1, xErrorStyle, JKQTPnoError, datarange_start, datarange_end, xErrorColumnLower, -1, xErrorSymmetric, true, xrelshift, yrelshift, dataorder); +} + +double JKQTPxGraphErrors::getXErrorU(int i, JKQTPdatastore *ds) const +{ + if (ds && xErrorColumn>=0) { + return ds->get(xErrorColumn, i); + } + return 0.0; +} + +double JKQTPxGraphErrors::getXErrorL(int i, JKQTPdatastore *ds) const +{ + if (ds) { + if (xErrorSymmetric) { if (xErrorColumn>=0) return ds->get(xErrorColumn, i); } + else if (xErrorColumnLower>=0) return ds->get(xErrorColumnLower, i); + } + return 0.0; +} + + + + + + + +JKQTPyGraphErrors::JKQTPyGraphErrors(QColor graphColor): + JKQTPgraphErrors(graphColor) +{ + yErrorColumn=-1; + yErrorSymmetric=true; + yErrorStyle=JKQTPnoError; + yErrorColumnLower=-1; +} + +void JKQTPyGraphErrors::plotErrorIndicators(JKQTPEnhancedPainter& painter, JKQtBasePlotter* parent, JKQTPcoordinateAxis* xAxis, JKQTPcoordinateAxis* yAxis, int xColumn, int yColumn, long long datarange_start, long long datarange_end, double xrelshift, double yrelshift, const QVector* dataorder) { + intPlotXYErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, -1, yErrorColumn, JKQTPnoError, yErrorStyle, datarange_start, datarange_end, -1, yErrorColumnLower, true, yErrorSymmetric, xrelshift, yrelshift, dataorder); +} + +double JKQTPyGraphErrors::getYErrorU(int i, JKQTPdatastore *ds) const +{ + if (ds && yErrorColumn>=0) { + return ds->get(yErrorColumn, i); + } + return 0.0; +} + +double JKQTPyGraphErrors::getYErrorL(int i, JKQTPdatastore *ds) const +{ + if (ds) { + if (yErrorSymmetric) { if (yErrorColumn>=0) return ds->get(yErrorColumn, i); } + else if (yErrorColumnLower>=0) return ds->get(yErrorColumnLower, i); + } + return 0.0; +} + + + + + + + +JKQTPxyGraphErrors::JKQTPxyGraphErrors(QColor graphColor): + JKQTPgraphErrors(graphColor) +{ + xErrorSymmetric=true; + yErrorSymmetric=true; + yErrorColumn=-1; + yErrorStyle=JKQTPnoError; + xErrorColumn=-1; + xErrorStyle=JKQTPnoError; + xErrorColumnLower=-1; + yErrorColumnLower=-1; + +} + +void JKQTPxyGraphErrors::plotErrorIndicators(JKQTPEnhancedPainter& painter, JKQtBasePlotter* parent, JKQTPcoordinateAxis* xAxis, JKQTPcoordinateAxis* yAxis, int xColumn, int yColumn, long long datarange_start, long long datarange_end, double xrelshift, double yrelshift, const QVector* dataorder) { + this->intPlotXYErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, xErrorColumn, yErrorColumn, xErrorStyle, yErrorStyle, datarange_start, datarange_end, xErrorColumnLower, yErrorColumnLower, xErrorSymmetric, yErrorSymmetric, xrelshift, yrelshift, dataorder); +} + +double JKQTPxyGraphErrors::getXErrorU(int i, JKQTPdatastore *ds) const +{ + if (ds && xErrorColumn>=0) { + return ds->get(xErrorColumn, i); + } + return 0.0; +} + +double JKQTPxyGraphErrors::getXErrorL(int i, JKQTPdatastore *ds) const +{ + if (ds && xErrorColumn>=0) { + if (xErrorSymmetric) { if (xErrorColumn>=0) return ds->get(xErrorColumn, i); } + else if (xErrorColumnLower>=0) return ds->get(xErrorColumnLower, i); + } + return 0.0; +} + +double JKQTPxyGraphErrors::getYErrorU(int i, JKQTPdatastore *ds) const +{ + if (ds && yErrorColumn>=0) { + return ds->get(yErrorColumn, i); + } + return 0.0; +} + +double JKQTPxyGraphErrors::getYErrorL(int i, JKQTPdatastore *ds) const +{ + if (ds && yErrorColumn>=0) { + if (yErrorSymmetric) { if (yErrorColumn>=0) return ds->get(yErrorColumn, i); } + else if (yErrorColumnLower>=0) return ds->get(yErrorColumnLower, i); + } + return 0.0; +} + + + + + + + + + +void JKQTPxyGraph::intSortData() +{ + sortedIndices.clear(); + + + + if (parent==nullptr) return ; + + JKQTPdatastore* datastore=parent->getDatastore(); + int imin=0; + int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end, static_cast(imax)); + } + if (imax datas; + + if (sortData==JKQTPxyLineGraph::SortedX) { + + for (int i=0; iget(static_cast(xColumn),static_cast(i)); + sortedIndices<get(static_cast(yColumn),static_cast(i)); + sortedIndices<) + + + + 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 . +*/ + + + +/** + * \defgroup jkqtplotter_elements Plot Elements + * \ingroup jkqtplotter + * \defgroup jkqtplotter_plots Graphs + * \ingroup jkqtplotter_elements + */ + +/** \file jkqtpelements.h + * \ingroup jkqtplotter + */ + +#include +#include +#include +#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 according to the parent's transformation rules */ + QVector transform(const QVector& x); + + /** \brief tool routine that transforms a QVector according to the parent's transformation rules + * and returns a (non-closed) path consisting of lines */ + QPainterPath transformToLinePath(const QVector& x); + + /** \brief tool routine that transforms a QVector according to the parent's transformation rules + * and returns a polygon */ + inline QPolygonF transformToPolygon(const QVector& 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:
\copybrief sortData.
\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 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:
\copybrief sortData.
\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 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* 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 *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 *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 *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 *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 diff --git a/jkqtpbaseplotter.cpp b/jkqtpbaseplotter.cpp index a41dd4f00f..9030d77ee7 100644 --- a/jkqtpbaseplotter.cpp +++ b/jkqtpbaseplotter.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center + Copyright (c) 2008-2018 Jan W. Krieger (, ), 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 yCol double width=w/(double)yColumns.size(); double s=-1.0*w/2.0+width/2.0; for (int i=0; iset_title(titles[i]); g->set_xColumn(xColumn); g->set_yColumn(yColumns[i]); @@ -3324,7 +3326,7 @@ void JKQtBasePlotter::addVerticalBargraph(QVector xColumns, size_t yColu double width=w/(double)xColumns.size(); double s=-1.0*w/2.0+width/2.0; for (int i=0; iset_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 &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, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () @@ -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& gr); + template + 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. * diff --git a/jkqtpboxplotelements.cpp b/jkqtpboxplotelements.cpp new file mode 100644 index 0000000000..7e48d0d396 --- /dev/null +++ b/jkqtpboxplotelements.cpp @@ -0,0 +1,1226 @@ +/* + Copyright (c) 2008-2018 Jan W. Krieger () + + + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + + + +#include "jkqtpboxplotelements.h" +#include "jkqtpbaseplotter.h" +#include +#include +#include +#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) || (xvsgzgetNextStyle(); + //std::cout<<"got style settings from parent: "<getPlotStyle(parentPlotStyle).color(); + whiskerStyle=parent->getPlotStyle(parentPlotStyle).style(); + } + +} + + +JKQTPboxplotVerticalGraph::JKQTPboxplotVerticalGraph(JKQtPlotter* parent): + JKQTPgraph(parent) +{ + posColumn=-1; + medianColumn=-1; + meanColumn=-1; + minColumn=-1; + maxColumn=-1; + percentile25Column=-1; + percentile75Column=-1; + color=QColor("red"); + fillColor=QColor("white"); + fillStyle=Qt::SolidPattern; + whiskerStyle=Qt::SolidLine; + lineWidth=1; + boxWidth=0.4; + meanSymbol=JKQTPplus; + meanSymbolWidth=1; + meanSymbolSize=12; + sortData=Unsorted; + + if (parent) { // get style settings from parent object + parentPlotStyle=parent->getNextStyle(); + //std::cout<<"got style settings from parent: "<getPlotStyle(parentPlotStyle).color(); + whiskerStyle=parent->getPlotStyle(parentPlotStyle).style(); + } + +} + + +void JKQTPboxplotVerticalGraph::draw(JKQTPEnhancedPainter& painter) { +#ifdef JKQTBP_AUTOTIMER + JKQTPAutoOutputTimer jkaaot("JKQTPboxplotVerticalGraph::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.setJoinStyle(Qt::RoundJoin); + p.setJoinStyle(Qt::RoundJoin); + p.setCapStyle(Qt::RoundCap); + QPen pw=p; + pw.setStyle(whiskerStyle); + QPen np(Qt::NoPen); + + QBrush b=painter.brush(); + b.setColor(fillColor); + b.setStyle(fillStyle); + + int imax=datastore->getColumn(posColumn).getRows(); + int imin=0; + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end, static_cast(imax)); + } + if (imaxx2p(datastore->get(posColumn,i-1)); + double xv=xAxis->x2p(datastore->get(posColumn,i)); + if (posColumn>=0 && JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(xv0)) { + if (bwfirst) { + boxwidth_real=fabs(xv-xv0); + bwfirst=false; + } else { + if (fabs(xv-xv0)>0) boxwidth_real=qMin(fabs(xv-xv0), boxwidth_real); + } + } + } + // 2. plot: + painter.save(); + for (int i=imin; iget(posColumn,i); + double p25v=datastore->get(percentile25Column,i); + double p75v=datastore->get(percentile75Column,i); + double minv=datastore->get(minColumn,i); + double maxv=datastore->get(maxColumn,i); + double medianv=datastore->get(medianColumn,i); + double mean=yAxis->x2p(datastore->get(meanColumn,i)); + + QVector lines_p, lines_pw; + + //std::cout<<"(xv, yv) = ( "<=0 && JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(p25v) && + JKQTPIsOKFloat(p75v) && JKQTPIsOKFloat(minv) && + JKQTPIsOKFloat(maxv) && JKQTPIsOKFloat(medianv) ) { + + painter.save(); + painter.setPen(p); + painter.setBrush(b); + //std::cout<<"boxplot(med="<x2p(xv); + double p25=yAxis->x2p(p25v); + double p75=yAxis->x2p(p75v); + double min=yAxis->x2p(minv); + double max=yAxis->x2p(maxv); + double median=yAxis->x2p(medianv); + + double xn=x+1; + if (i+1x2p(datastore->get(posColumn,i+1)); + else if (i-1>=0) xn=xAxis->x2p(datastore->get(posColumn,i-1)); + else xn=x+1; + + + double w=((boxwidth_real>0)?boxwidth_real:(fabs(xn-x)))*boxWidth; + double minstop=p25; + double maxstop=p75; + if (percentile25Column<0 && medianColumn>=0) minstop=median; + else if (percentile25Column<0 && meanColumn>=0) minstop=mean; + else if (percentile25Column<0 && maxColumn>=0) minstop=max; + if (percentile75Column<0 && medianColumn>=0) maxstop=median; + else if (percentile75Column<0 && meanColumn>=0) maxstop=mean; + else if (percentile75Column<0 && minColumn>=0) maxstop=min; + double xma=x+w/2.0; + double xmi=x-w/2.0; + double xma4=x+w/4.0; + double xmi4=x-w/4.0; + + if (imax<=0) { + xma=xAxis->x2p(xv+boxWidth/2.0); + xmi=xAxis->x2p(xv-boxWidth/2.0); + xma4=xAxis->x2p(xv+boxWidth/4.0); + xmi4=xAxis->x2p(xv-boxWidth/4.0); + } + + if (minColumn>=0) { + lines_p.append(QLineF(xmi4, min, xma4, min)); + lines_pw.append(QLineF(x, min, x, minstop)); + } + if (maxColumn>=0) { + lines_p.append(QLineF(xmi4, max, xma4, max)); + lines_pw.append(QLineF(x, max, x, maxstop)); + } + + if (percentile25Column>=0 && percentile75Column>=0) painter.drawRect(QRectF(xmi, p75, fabs(xma-xmi), fabs(p75-p25))); + if (medianColumn>=0) lines_p.append(QLineF(xmi+p.widthF()/2.0, median, xma-p.widthF()/2.0, median)); + if (meanColumn>=0 && JKQTPIsOKFloat(mean)) { + plotSymbol(painter, x, mean, meanSymbol, parent->pt2px(painter, meanSymbolSize), parent->pt2px(painter, meanSymbolWidth*parent->get_lineWidthMultiplier()), color, fillColor); + } + + + painter.setPen(p); + if (lines_p.size()>0) painter.drawLines(lines_p); + painter.setPen(pw); + if (lines_pw.size()>0) painter.drawLines(lines_pw); + painter.restore(); + + //first=true; + } + } + painter.restore(); + + + drawErrorsAfter(painter); +} + + +bool JKQTPboxplotVerticalGraph::getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) { + bool start=true; + minx=0; + maxx=0; + smallestGreaterZero=0; + + if (posColumn<0) return false; + if (parent==nullptr) return false; + + JKQTPdatastore* datastore=parent->getDatastore(); + int imin=0; + int imax=datastore->getColumn(posColumn).getRows(); + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end, static_cast(imax)); + } + if (imaxget(posColumn,i); + if (JKQTPIsOKFloat(xv)) { + double xn=xv+1; + if (i+1get(posColumn,i+1); + else if (i-1>=0) xn=datastore->get(posColumn,i-1); + else xn=xv+1; + double delta=fabs(xn-xv); + double w=delta*boxWidth; + double xma=xv+w; + double xmi=xv-w; + if (start || xma>maxx) maxx=xma; + if (start || xmigetDatastore(); + int imin=0; + int imax=datastore->getColumn(medianColumn).getRows(); + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end, static_cast(imax)); + } + if (imaxget(percentile25Column,i); + double p75=datastore->get(percentile75Column,i); + double min=datastore->get(minColumn,i); + double max=datastore->get(maxColumn,i); + double median=datastore->get(medianColumn,i); + if (JKQTPIsOKFloat(median)) { + if (start || median>maxy) maxy=median; + if (start || medianmaxy) maxy=p25; + if (JKQTPIsOKFloat(p25) &&p25maxy) maxy=p75; + if (JKQTPIsOKFloat(p75) &&p75maxy) maxy=min; + if (JKQTPIsOKFloat(min) &&minmaxy) maxy=max; + if (JKQTPIsOKFloat(max) &&maxpt2px(painter, lineWidth*parent->get_lineWidthMultiplier()))); + p.setJoinStyle(Qt::RoundJoin); + QPen pw=p; + pw.setStyle(whiskerStyle); + QPen np(Qt::NoPen); + + QBrush b=painter.brush(); + b.setColor(fillColor); + b.setStyle(fillStyle); + + double x=rect.left()+rect.width()/2.0; + double xma=x+rect.width()/2.5; + double xmi=x-rect.width()/2.5; + double min=rect.bottom(); + double max=rect.top(); + double median=max+rect.height()/2.0; + double w=rect.width()/1.8; + double p25=max+0.75*rect.height(); + double p75=max+0.25*rect.height(); + + painter.setPen(p); + painter.save(); + painter.setBrush(b); + painter.drawRect(QRectF(xmi, p75, fabs(xma-xmi), fabs(p75-p25))); + painter.restore(); + painter.drawLine(QLineF(xmi, median, xma, median)); + painter.drawLine(QLineF(x-w/4.0, max, x+w/4.0, max)); + painter.drawLine(QLineF(x-w/4.0, min, x+w/4.0, min)); + painter.setPen(pw); + painter.drawLine(QLineF(x, max, x, p75)); + painter.drawLine(QLineF(x, min, x, p25)); + painter.restore(); +} + +QColor JKQTPboxplotVerticalGraph::getKeyLabelColor() { + return color; +} + + + + +void JKQTPboxplotHorizontalGraph::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) { + painter.save(); + QPen p=painter.pen(); + p.setColor(color); + p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, lineWidth*parent->get_lineWidthMultiplier()))); + p.setJoinStyle(Qt::RoundJoin); + p.setJoinStyle(Qt::RoundJoin); + p.setCapStyle(Qt::RoundCap); + QPen pw=p; + pw.setStyle(whiskerStyle); + QPen np(Qt::NoPen); + + QBrush b=painter.brush(); + b.setColor(fillColor); + b.setStyle(fillStyle); + + double y=rect.top()+rect.height()/2.0; + double yma=y+rect.height()/2.5; + double ymi=y-rect.height()/2.5; + double min=rect.left(); + double max=rect.right(); + double median=max-rect.width()/2.0; + double w=rect.height()/1.8; + double p25=min+0.75*rect.width(); + double p75=min+0.25*rect.width(); + + painter.setPen(p); + painter.save(); + painter.setBrush(b); + painter.drawRect(QRectF(p75, ymi, fabs(p75-p25), fabs(yma-ymi))); + painter.restore(); + painter.drawLine(QLineF(median, ymi, median, yma)); + painter.drawLine(QLineF(max, y-w/4.0, max, y+w/4.0)); + painter.drawLine(QLineF(min, y-w/4.0, min, y+w/4.0)); + painter.setPen(pw); + painter.drawLine(QLineF(max, y, p75, y)); + painter.drawLine(QLineF(min, y, p25, y)); + painter.restore(); +} + +bool JKQTPboxplotHorizontalGraph::getXMinMax(double& miny, double& maxy, double& smallestGreaterZero) { + bool start=true; + miny=0; + maxy=0; + smallestGreaterZero=0; + + if (percentile25Column<0 && percentile75Column<0 && medianColumn<0 && minColumn<0 && maxColumn<0) return false; + + if (parent==nullptr) return false; + + JKQTPdatastore* datastore=parent->getDatastore(); + int imin=0; + int imax=datastore->getColumn(medianColumn).getRows(); + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end, static_cast(imax)); + } + if (imaxget(percentile25Column,i); + double p75=datastore->get(percentile75Column,i); + double min=datastore->get(minColumn,i); + double max=datastore->get(maxColumn,i); + double median=datastore->get(medianColumn,i); + if (JKQTPIsOKFloat(median)) { + if (start || median>maxy) maxy=median; + if (start || medianmaxy) maxy=p25; + if (JKQTPIsOKFloat(p25)&&p25maxy) maxy=p75; + if (JKQTPIsOKFloat(p75)&&p75maxy) maxy=min; + if (JKQTPIsOKFloat(min)&&minmaxy) maxy=max; + if (JKQTPIsOKFloat(max)&&maxgetDatastore(); + int imin=0; + int imax=datastore->getColumn(posColumn).getRows(); + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end, static_cast(imax)); + } + if (imaxget(posColumn,i); + double xn=xv+1; + if (i+1get(posColumn,i+1); + else if (i-1>=0) xn=datastore->get(posColumn,i-1); + else xn=xv+1; + double delta=fabs(xn-xv); + double w=delta*boxWidth; + double xma=xv+w; + double xmi=xv-w; + if (JKQTPIsOKFloat(xma) && JKQTPIsOKFloat(xmi) ) { + if (start || xma>maxx) maxx=xma; + if (start || xmigetDatastore(); + 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.setJoinStyle(Qt::RoundJoin); + p.setJoinStyle(Qt::RoundJoin); + p.setCapStyle(Qt::RoundCap); + QPen pw=p; + pw.setStyle(whiskerStyle); + QPen np(Qt::NoPen); + + QBrush b=painter.brush(); + b.setColor(fillColor); + b.setStyle(fillStyle); + + int imax=datastore->getColumn(posColumn).getRows(); + int imin=0; + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end, static_cast(imax)); + } + if (imaxx2p(datastore->get(posColumn,i-1)); + double xv=yAxis->x2p(datastore->get(posColumn,i)); + if (posColumn>=0 && JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(xv0)) { + if (bwfirst) { + boxwidth_real=fabs(xv-xv0); + bwfirst=false; + } else { + if (fabs(xv-xv0)>0) boxwidth_real=qMin(fabs(xv-xv0), boxwidth_real); + } + } + } + // 2. plot: + painter.save(); + + //bool first=false; + for (int i=imin; iget(posColumn,i); + double p25v=datastore->get(percentile25Column,i); + double p75v=datastore->get(percentile75Column,i); + double minv=datastore->get(minColumn,i); + double maxv=datastore->get(maxColumn,i); + double medianv=datastore->get(medianColumn,i); + double mean=xAxis->x2p(datastore->get(meanColumn,i)); + + QVector lines_p, lines_pw; + //std::cout<<"(xv, yv) = ( "<=0 && JKQTPIsOKFloat(yv) && + JKQTPIsOKFloat(p25v) && + JKQTPIsOKFloat(p75v) && + JKQTPIsOKFloat(minv) && + JKQTPIsOKFloat(maxv) && + JKQTPIsOKFloat(medianv)) { + + painter.save(); + painter.setPen(p); + painter.setBrush(b); + + + double p25=xAxis->x2p(p25v); + double p75=xAxis->x2p(p75v); + double min=xAxis->x2p(minv); + double max=xAxis->x2p(maxv); + double median=xAxis->x2p(medianv); + + + //std::cout<<"boxplot(med="<x2p(yv); + double minstop=p25; + double maxstop=p75; + if (percentile25Column<0 && medianColumn>=0) minstop=median; + else if (percentile25Column<0 && maxColumn>=0) minstop=max; + else if (percentile25Column<0 && meanColumn>=0) minstop=mean; + if (percentile75Column<0 && medianColumn>=0) maxstop=median; + else if (percentile75Column<0 && minColumn>=0) maxstop=min; + else if (percentile75Column<0 && meanColumn>=0) maxstop=mean; + + double yn=y+1; + if (i+1x2p(datastore->get(posColumn,i+1)); + else if (i-1>=0) yn=yAxis->x2p(datastore->get(posColumn,i-1)); + else yn=y+1; + double delta=fabs(yn-y); + double w=((boxwidth_real>0)?boxwidth_real:(delta))*boxWidth; + double yma=y-w/2.0; + double ymi=y+w/2.0; + double yma4=y+w/4.0; + double ymi4=y-w/4.0; + + if (imax<=1) { + ymi=yAxis->x2p(yv+boxWidth/2.0); + yma=yAxis->x2p(yv-boxWidth/2.0); + yma4=yAxis->x2p(yv+boxWidth/4.0); + ymi4=yAxis->x2p(yv-boxWidth/4.0); + } + if (minColumn>=0) { + lines_p.append(QLineF(min, ymi4, min, yma4)); + lines_pw.append(QLineF(min, y, minstop, y)); + } + if (maxColumn>=0) { + lines_p.append(QLineF(max, ymi4, max, yma4)); + lines_pw.append(QLineF(max, y, maxstop, y)); + } + if (percentile25Column>=0 && percentile75Column>=0) painter.drawRect(QRectF(p25, qMin(yma,ymi), fabs(p75-p25), fabs(yma-ymi))); + if (medianColumn>=0) lines_p.append(QLineF(median, ymi-p.widthF()/2.0, median, yma+p.widthF()/2.0)); + + if (meanColumn>=0 && JKQTPIsOKFloat(mean)) { + plotSymbol(painter, mean, y, meanSymbol, parent->pt2px(painter, meanSymbolSize), parent->pt2px(painter, meanSymbolWidth*parent->get_lineWidthMultiplier()), color, fillColor); + } + + //first=true; + painter.setPen(p); + if (lines_p.size()>0) painter.drawLines(lines_p); + painter.setPen(pw); + if (lines_pw.size()>0) painter.drawLines(lines_pw); + painter.restore(); + } + + } + + painter.restore(); + + drawErrorsAfter(painter); +} + + + + + + + + + + + + + + + + + + + + + +JKQTPboxplotVerticalElement::JKQTPboxplotVerticalElement(JKQtBasePlotter* parent): + JKQTPgraph(parent) +{ + pos=0; + median=0; + mean=0; + min=-1; + max=1; + drawMean=true; + drawMinMax=true; + percentile25=-0.75; + percentile75=0.75; + color=QColor("red"); + fillColor=QColor("white"); + fillStyle=Qt::SolidPattern; + whiskerStyle=Qt::SolidLine; + lineWidth=1; + boxWidth=0.4; + meanSymbol=JKQTPplus; + meanSymbolWidth=1; + meanSymbolSize=12; + + if (parent) { // get style settings from parent object + parentPlotStyle=parent->getNextStyle(); + //std::cout<<"got style settings from parent: "<getPlotStyle(parentPlotStyle).color(); + whiskerStyle=parent->getPlotStyle(parentPlotStyle).style(); + } + +} + +JKQTPboxplotVerticalElement::JKQTPboxplotVerticalElement(JKQtPlotter* parent): + JKQTPgraph(parent) +{ + pos=0; + median=0; + mean=0; + min=-1; + max=1; + drawMean=true; + drawMinMax=true; + percentile25=-0.75; + percentile75=0.75; + color=QColor("red"); + fillColor=QColor("white"); + fillStyle=Qt::SolidPattern; + whiskerStyle=Qt::SolidLine; + lineWidth=1; + boxWidth=0.4; + meanSymbol=JKQTPplus; + meanSymbolWidth=1; + meanSymbolSize=12; + + if (parent) { // get style settings from parent object + parentPlotStyle=parent->getNextStyle(); + //std::cout<<"got style settings from parent: "<getPlotStyle(parentPlotStyle).color(); + whiskerStyle=parent->getPlotStyle(parentPlotStyle).style(); + } + +} +void JKQTPboxplotVerticalElement::draw(JKQTPEnhancedPainter& painter) { +#ifdef JKQTBP_AUTOTIMER + JKQTPAutoOutputTimer jkaaot("JKQTPboxplotVerticalElement::draw"); +#endif + if (parent==nullptr) return; + + 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.setJoinStyle(Qt::RoundJoin); + p.setJoinStyle(Qt::RoundJoin); + p.setCapStyle(Qt::RoundCap); + QPen pw=p; + pw.setStyle(whiskerStyle); + QPen np(Qt::NoPen); + + QBrush b=painter.brush(); + b.setColor(fillColor); + b.setStyle(fillStyle); + + + double xv=pos; + double p25v=percentile25; + double p75v=percentile75; + double minv=min; + double maxv=max; + double medianv=median; + + //std::cout<<"(xv, yv) = ( "<x2p(xv); + double p25=yAxis->x2p(p25v); + double p75=yAxis->x2p(p75v); + double min=yAxis->x2p(minv); + double max=yAxis->x2p(maxv); + double median=yAxis->x2p(medianv); + + double w=boxWidth; + double xma=x+w/2.0; + double xmi=x-w/2.0; + + painter.save(); + painter.setPen(p); + painter.save(); + painter.setBrush(b); + painter.drawRect(QRectF(xmi, p75, fabs(xma-xmi), fabs(p75-p25))); + painter.restore(); + if (drawMedian) { + painter.drawLine(QLineF(xmi, median, xma, median)); + } + if (drawMinMax) { + painter.drawLine(QLineF(x-w/4.0, max, x+w/4.0, max)); + painter.drawLine(QLineF(x-w/4.0, min, x+w/4.0, min)); + painter.setPen(pw); + painter.drawLine(QLineF(x, max, x, p75)); + painter.drawLine(QLineF(x, min, x, p25)); + } + painter.restore(); + + if (drawMean) { + double mean=yAxis->x2p(this->mean); + plotSymbol(painter, x, mean, meanSymbol, parent->pt2px(painter, meanSymbolSize), parent->pt2px(painter, meanSymbolWidth*parent->get_lineWidthMultiplier()), color, fillColor); + } + + + } + painter.restore(); + + drawErrorsAfter(painter); +} + + +bool JKQTPboxplotVerticalElement::getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) { + minx=0; + maxx=0; + smallestGreaterZero=0; + + if (parent==nullptr) return false; + + double xv=pos; + double w=boxWidth; + double xma=xv+w; + double xmi=xv-w; + maxx=xma; + minx=xmi; + double xvsgz; + xvsgz=xmi; SmallestGreaterZeroCompare_xvsgz(); + xvsgz=xma; SmallestGreaterZeroCompare_xvsgz(); + return true; +} + +bool JKQTPboxplotVerticalElement::getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) { + miny=0; + maxy=0; + smallestGreaterZero=0; + + if (parent==nullptr) return false ; + + + double p25=percentile25; + double p75=percentile75; + if (drawMedian) { + maxy=median; + miny=median; + } else { + maxy=p75; + miny=p25; + } + if (p25>maxy) maxy=p25; + if (p25maxy) maxy=p75; + if (p75maxy) maxy=min; + if (drawMinMax && (minmaxy)) maxy=max; + if (drawMinMax && (maxpt2px(painter, lineWidth*parent->get_lineWidthMultiplier()))); + p.setJoinStyle(Qt::RoundJoin); + p.setJoinStyle(Qt::RoundJoin); + p.setCapStyle(Qt::RoundCap); + QPen pw=p; + pw.setStyle(whiskerStyle); + QPen np(Qt::NoPen); + + QBrush b=painter.brush(); + b.setColor(fillColor); + b.setStyle(fillStyle); + + double x=rect.left()+rect.width()/2.0; + double xma=x+rect.width()/2.5; + double xmi=x-rect.width()/2.5; + double min=rect.bottom(); + double max=rect.top(); + double median=max+rect.height()/2.0; + double w=rect.width()/1.8; + double p25=max+0.75*rect.height(); + double p75=max+0.25*rect.height(); + + painter.setPen(p); + painter.save(); + painter.setBrush(b); + painter.drawRect(QRectF(xmi, p75, fabs(xma-xmi), fabs(p75-p25))); + painter.restore(); + painter.drawLine(QLineF(xmi, median, xma, median)); + painter.drawLine(QLineF(x-w/4.0, max, x+w/4.0, max)); + painter.drawLine(QLineF(x-w/4.0, min, x+w/4.0, min)); + painter.setPen(pw); + painter.drawLine(QLineF(x, max, x, p75)); + painter.drawLine(QLineF(x, min, x, p25)); + painter.restore(); +} + +QColor JKQTPboxplotVerticalElement::getKeyLabelColor() { + return color; +} + + + + +void JKQTPboxplotHorizontalElement::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) { + painter.save(); + QPen p=painter.pen(); + p.setColor(color); + p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, lineWidth*parent->get_lineWidthMultiplier()))); + p.setJoinStyle(Qt::RoundJoin); + p.setJoinStyle(Qt::RoundJoin); + p.setCapStyle(Qt::RoundCap); + + QPen pw=p; + pw.setStyle(whiskerStyle); + QPen np(Qt::NoPen); + + QBrush b=painter.brush(); + b.setColor(fillColor); + b.setStyle(fillStyle); + + double y=rect.top()+rect.height()/2.0; + double yma=y+rect.height()/2.5; + double ymi=y-rect.height()/2.5; + double min=rect.left(); + double max=rect.right(); + double median=max-rect.width()/2.0; + double w=rect.height()/1.8; + double p25=min+0.75*rect.width(); + double p75=min+0.25*rect.width(); + + painter.setPen(p); + painter.save(); + painter.setBrush(b); + painter.drawRect(QRectF(p75, ymi, fabs(p75-p25), fabs(yma-ymi))); + painter.restore(); + painter.drawLine(QLineF(median, ymi, median, yma)); + painter.drawLine(QLineF(max, y-w/4.0, max, y+w/4.0)); + painter.drawLine(QLineF(min, y-w/4.0, min, y+w/4.0)); + painter.setPen(pw); + painter.drawLine(QLineF(max, y, p75, y)); + painter.drawLine(QLineF(min, y, p25, y)); + painter.restore(); +} + +bool JKQTPboxplotHorizontalElement::getXMinMax(double& miny, double& maxy, double& smallestGreaterZero) { + miny=0; + maxy=0; + smallestGreaterZero=0; + + if (parent==nullptr) return false; + + + double p25=percentile25; + double p75=percentile75; + if (drawMedian) { + maxy=median; + miny=median; + } else { + maxy=p75; + miny=p25; + } + if (p25>maxy) maxy=p25; + if (p25maxy) maxy=p75; + if (p75maxy) maxy=min; + if (drawMinMax && (minmaxy)) maxy=max; + if (drawMinMax && (maxpt2px(painter, lineWidth*parent->get_lineWidthMultiplier()))); + p.setJoinStyle(Qt::RoundJoin); + p.setJoinStyle(Qt::RoundJoin); + p.setCapStyle(Qt::RoundCap); + QPen pw=p; + pw.setStyle(whiskerStyle); + QPen np(Qt::NoPen); + + QBrush b=painter.brush(); + b.setColor(fillColor); + b.setStyle(fillStyle); + double yv=pos; + double p25v=percentile25; + double p75v=percentile75; + double minv=min; + double maxv=max; + double medianv=median; + + //std::cout<<"(xv, yv) = ( "<x2p(yv); + double p25=xAxis->x2p(p25v); + double p75=xAxis->x2p(p75v); + double min=xAxis->x2p(minv); + double max=xAxis->x2p(maxv); + double median=xAxis->x2p(medianv); + + double w=boxWidth; + double yma=y+w/2.0; + double ymi=y-w/2.0; + + painter.save(); + painter.setPen(p); + painter.save(); + painter.setBrush(b); + painter.drawRect(QRectF(p25, ymi, fabs(p75-p25), fabs(yma-ymi))); + painter.restore(); + if (drawMedian) { + painter.drawLine(QLineF(median, ymi, median, yma)); + } + if (drawMinMax) { + painter.drawLine(QLineF(max, y-w/4.0, max, y+w/4.0)); + painter.drawLine(QLineF(min, y-w/4.0, min, y+w/4.0)); + painter.setPen(pw); + painter.drawLine(QLineF(max, y, p75, y)); + painter.drawLine(QLineF(min, y, p25, y)); + } + painter.restore(); + + if (drawMean) { + double mean=yAxis->x2p(this->mean); + plotSymbol(painter, mean, y, meanSymbol, parent->pt2px(painter, meanSymbolSize), parent->pt2px(painter, meanSymbolWidth*parent->get_lineWidthMultiplier()), color, fillColor); + } + + } + painter.restore(); + + drawErrorsAfter(painter); +} + + + + + + +QPen JKQTPboxplotVerticalGraph::getLinePen(JKQTPEnhancedPainter& painter) const { + QPen p; + p.setColor(color); + p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->get_lineWidthMultiplier()*lineWidth))); + p.setJoinStyle(Qt::RoundJoin); + p.setCapStyle(Qt::RoundCap); + + return p; +} + +void JKQTPboxplotVerticalGraph::intSortData() +{ + sortedIndices.clear(); + + + + if (parent==nullptr) return ; + + JKQTPdatastore* datastore=parent->getDatastore(); + int imin=0; + int imax=datastore->getColumn(posColumn).getRows(); + // interpret data ranges + if (datarange_start>-1) { + imin=qMin(datarange_start, static_cast(imax)); + } + if (datarange_end>-1) { + imax=qMin(datarange_end, static_cast(imax)); + } + if (imax datas; + + if (sortData==JKQTPboxplotVerticalGraph::Sorted) { + + for (int i=0; iget(posColumn,i); + sortedIndices<pt2px(painter, parent->get_lineWidthMultiplier()*lineWidth))); + p.setJoinStyle(Qt::RoundJoin); + p.setCapStyle(Qt::RoundCap); + + return p; +} + diff --git a/jkqtpboxplotelements.h b/jkqtpboxplotelements.h new file mode 100644 index 0000000000..aae7e12714 --- /dev/null +++ b/jkqtpboxplotelements.h @@ -0,0 +1,371 @@ +/* + Copyright (c) 2008-2018 Jan W. Krieger () + + + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + + + +/** + * \defgroup jkqtplotter_elements Plot Elements + * \ingroup jkqtplotter + * \defgroup jkqtplotter_plots Graphs + * \ingroup jkqtplotter_elements + */ + +/** \file jkqtpelements.h + * \ingroup jkqtplotter + */ + +#include +#include +#include +#include "jkqtptools.h" +#include "jkqtp_imexport.h" +#include "jkqtpimagetools.h" +#include "jkqtpbasegraphs.h" + +#ifndef JKQTPBOXPLOTELEMENTS_H +#define JKQTPBOXPLOTELEMENTS_H + + + + +/*! \brief This implements vertical boxplots + \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:
\copybrief sortData.
\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 sortedIndices; + virtual void intSortData(); + inline int getDataIndex(int i) { + if (sortData==Unsorted) return i; + return sortedIndices.value(i,i); + } + +}; + + +/*! \brief This implements horizontal boxplots + \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 boxplot 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 boxplot 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 diff --git a/jkqtpdatastorage.cpp b/jkqtpdatastorage.cpp index 860253c96e..c6e04e6420 100644 --- a/jkqtpdatastorage.cpp +++ b/jkqtpdatastorage.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () diff --git a/jkqtpdatastorage.h b/jkqtpdatastorage.h index 380b486407..c99db04565 100644 --- a/jkqtpdatastorage.h +++ b/jkqtpdatastorage.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () diff --git a/jkqtpelements.cpp b/jkqtpelements.cpp index 7b062428f0..08a99688b8 100644 --- a/jkqtpelements.cpp +++ b/jkqtpelements.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () @@ -30,453 +30,6 @@ #include "jkqtplotter.h" #define SmallestGreaterZeroCompare_xvsgz() if ((xvsgz>10.0*DBL_MIN)&&((smallestGreaterZero<10.0*DBL_MIN) || (xvsgzget_plotter()) -{ - datarange_end=datarange_start=-1; - title=""; - visible=true; - setParent(parent->get_plotter()); -} - -QImage JKQTPgraph::generateKeyMarker(QSize size) -{ - QImage img(size.width(),size.height(),QImage::Format_ARGB32); - if (parent) img.fill(parent->get_keyBackgroundColor()); - { - JKQTPEnhancedPainter painter(&img); - painter.setRenderHint(QPainter::Antialiasing, true); - painter.setRenderHint(QPainter::TextAntialiasing, true); - painter.setRenderHint(QPainter::SmoothPixmapTransform, true); - painter.setRenderHint(QPainter::HighQualityAntialiasing, true); - QRectF rect(0,0,size.width(),size.height()); - drawKeyMarker(painter, rect); - } - return img; -} - -QPointF JKQTPgraph::transform(const QPointF& x) { - if (xAxis&&yAxis) return QPointF(xAxis->x2p(x.x()), yAxis->x2p(x.y())); - return QPointF(); -} - -QPointF JKQTPgraph::backTransform(const QPointF& x) { - if (xAxis&&yAxis) return QPointF(xAxis->p2x(x.x()), yAxis->p2x(x.y())); - return QPointF(); -} - -void JKQTPgraph::setParent(JKQtBasePlotter* parent) { - this->parent=parent; - if (parent) { - this->xAxis=parent->getXAxis(); - this->yAxis=parent->getYAxis(); - } else { - xAxis=nullptr; - yAxis=nullptr; - } - QObject::setParent(parent); -} - -void JKQTPgraph::setParent(JKQtPlotter *parent) -{ - setParent(parent->get_plotter()); -} - -QVector JKQTPgraph::transform(const QVector& x) { - QVector res; - for (int i=0; i& x) { - QPainterPath res; - if (x.size()>0) { - res.moveTo(transform(x[0])); - for (int i=1; igetDatastore(); - int imin=0; - int imax=datastore->getColumn(column).getRows(); - // interpret data ranges - if (datarange_start>-1) { - imin=qMin(datarange_start, static_cast(imax)); - } - if (datarange_end>-1) { - imax=qMin(datarange_end, static_cast(imax)); - } - if (imaxget(column,i); - if (start || xv>maxx) maxx=xv; - if (start || xvgetDatastore(); - int imin=0; - int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); - // interpret data ranges - if (datarange_start>-1) { - imin=qMin(datarange_start, static_cast(imax)); - } - if (datarange_end>-1) { - imax=qMin(datarange_end, static_cast(imax)); - } - if (imaxget(static_cast(xColumn),static_cast(i)); - if (JKQTPIsOKFloat(xv)) { - if (start || xv>maxx) maxx=xv; - if (start || xvgetDatastore(); - int imin=0; - int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); - // interpret data ranges - if (datarange_start>-1) { - imin=qMin(datarange_start, static_cast(imax)); - } - if (datarange_end>-1) { - imax=qMin(datarange_end, static_cast(imax)); - } - if (imaxget(static_cast(yColumn),static_cast(i)); - if (JKQTPIsOKFloat(yv)) { - if (start || yv>maxy) maxy=yv; - if (start || yvgetNextStyle(); - //std::cout<<"got style settings from parent: "<getPlotStyle(parentPlotStyle).color(); - style=parent->getPlotStyle(parentPlotStyle).style(); - } - -} - -JKQTPsingleColumnGraph::JKQTPsingleColumnGraph(int dataColumn, JKQtBasePlotter *parent): - JKQTPgraph(parent) -{ - sortData=Unsorted; - this->dataColumn=dataColumn; - parentPlotStyle=-1; - color=QColor("red"); - style=Qt::SolidLine; - lineWidth=2; - parentPlotStyle=-1; - - if (parent) { // get style settings from parent object - parentPlotStyle=parent->getNextStyle(); - //std::cout<<"got style settings from parent: "<getPlotStyle(parentPlotStyle).color(); - style=parent->getPlotStyle(parentPlotStyle).style(); - } -} - -JKQTPsingleColumnGraph::JKQTPsingleColumnGraph(int dataColumn, QColor color, Qt::PenStyle style, double lineWidth, JKQtBasePlotter *parent): - JKQTPgraph(parent) -{ - sortData=Unsorted; - this->dataColumn=dataColumn; - this->color=color; - this->style=style; - this->lineWidth=lineWidth; - parentPlotStyle=-1; -} - - -JKQTPsingleColumnGraph::JKQTPsingleColumnGraph(JKQtPlotter *parent): - JKQTPgraph(parent) -{ - sortData=Unsorted; - dataColumn=-1; - color=QColor("red"); - style=Qt::SolidLine; - lineWidth=2; - parentPlotStyle=-1; - - if (parent) { // get style settings from parent object - parentPlotStyle=parent->getNextStyle(); - //std::cout<<"got style settings from parent: "<getPlotStyle(parentPlotStyle).color(); - style=parent->getPlotStyle(parentPlotStyle).style(); - } - -} - -JKQTPsingleColumnGraph::JKQTPsingleColumnGraph(int dataColumn, JKQtPlotter *parent): - JKQTPgraph(parent) -{ - sortData=Unsorted; - this->dataColumn=dataColumn; - parentPlotStyle=-1; - color=QColor("red"); - style=Qt::SolidLine; - lineWidth=2; - parentPlotStyle=-1; - - if (parent) { // get style settings from parent object - parentPlotStyle=parent->getNextStyle(); - //std::cout<<"got style settings from parent: "<getPlotStyle(parentPlotStyle).color(); - style=parent->getPlotStyle(parentPlotStyle).style(); - } -} - -JKQTPsingleColumnGraph::JKQTPsingleColumnGraph(int dataColumn, QColor color, Qt::PenStyle style, double lineWidth, JKQtPlotter *parent): - JKQTPgraph(parent) -{ - sortData=Unsorted; - this->dataColumn=dataColumn; - this->color=color; - this->style=style; - this->lineWidth=lineWidth; - parentPlotStyle=-1; -} - -JKQTPsingleColumnGraph::JKQTPsingleColumnGraph(int dataColumn, QColor color, Qt::PenStyle style, JKQtPlotter *parent): - JKQTPgraph(parent) -{ - sortData=Unsorted; - this->dataColumn=dataColumn; - this->color=color; - this->style=style; - this->lineWidth=2.0; - parentPlotStyle=-1; -} - -JKQTPsingleColumnGraph::JKQTPsingleColumnGraph(int dataColumn, QColor color, JKQtPlotter *parent): - JKQTPgraph(parent) -{ - sortData=Unsorted; - this->dataColumn=dataColumn; - this->color=color; - this->style=Qt::SolidLine; - this->lineWidth=2.0; - parentPlotStyle=-1; -} -QColor JKQTPsingleColumnGraph::getKeyLabelColor() -{ - return color; -} - -bool JKQTPsingleColumnGraph::usesColumn(int c) -{ - return c==dataColumn; -} - -QPen JKQTPsingleColumnGraph::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; -} - -void JKQTPsingleColumnGraph::intSortData() -{ - sortedIndices.clear(); - - - - if (parent==nullptr) return ; - - JKQTPdatastore* datastore=parent->getDatastore(); - int imin=0; - int imax=datastore->getColumn(dataColumn).getRows(); - // interpret data ranges - if (datarange_start>-1) { - imin=qMin(datarange_start, static_cast(imax)); - } - if (datarange_end>-1) { - imax=qMin(datarange_end, static_cast(imax)); - } - if (imax datas; - - if (sortData==JKQTPsingleColumnGraph::Sorted) { - - for (int i=0; iget(dataColumn,i); - sortedIndices<* dataorder) { - //std::cout<<"JKQTPgraphErrors::intPlotXYErrorIndicators(p, "<getDatastore(); - if (datastore==nullptr) return; - - if ((yErrorStyle==JKQTPnoError) && (xErrorStyle==JKQTPnoError)) return; - bool visX=(xErrorStyle!=JKQTPnoError)&&(xErrorColumn>=0||xErrorColumnLower>=0)&&(xColumn>=0)&&(yColumn>=0); - bool visY=(yErrorStyle!=JKQTPnoError)&&(yErrorColumn>=0||yErrorColumnLower>=0)&&(xColumn>=0)&&(yColumn>=0); - if (!visX&&!visY) return; - //std::cout<<" JKQTPgraphErrors::intPlotXYErrorIndicators(p, "<pt2px(painter, errorWidth*parent->get_lineWidthMultiplier()))); - p.setStyle(errorStyle); - p.setJoinStyle(Qt::RoundJoin); - p.setCapStyle(Qt::RoundCap); - painter.setPen(p); - - unsigned long long imaxx=0, imaxy=0; - if (xColumn>=0) imaxx=datastore->getColumn(static_cast(xColumn)).getRows(); - if (yColumn>=0) imaxy=datastore->getColumn(static_cast(yColumn)).getRows(); - int imax=qMin(imaxx, imaxy); - int imin=0; - // interpret data ranges - if (datarange_start>-1) { - imin=qMin(datarange_start, static_cast(imax)); - } - if (datarange_end>-1) { - imax=qMin(datarange_end, static_cast(imax)); - } - if (imaxpt2px(painter, errorbarSize); - QPolygonF polyX, polyY; - QList polyXTopPoints, polyXBottomPoints, polyYTopPoints, polyYBottomPoints; - QList errFC, errC; - bool defaultErrorColor=true; - - - /* - * double delta=1; - double deltap=0; - double deltam=0; - for (int i=imin; iget(static_cast(xColumn),static_cast(i)); - double yv=datastore->get(static_cast(yColumn),static_cast(i)); - if (imin==imax) { // only one x-value - deltam=0.5; - deltap=0.5; - } else if (i==imax-1) { // the right-most x-value - deltap=deltam=fabs(xv-datastore->get(xColumn,i-1))/2.0; - } else if (i==imin) { // the left-most x-value - deltam=deltap=fabs(datastore->get(xColumn,i+1)-xv)/2.0; - } else { - deltam=fabs(xv-datastore->get(xColumn,i-1))/2.0; - deltap=fabs(datastore->get(xColumn,i+1)-xv)/2.0; - } - delta=deltap+deltam; - **/ - - for (int iii=imin; iiivalue(iii, iii); - double xv=datastore->get(static_cast(xColumn),static_cast(i)); - double yv=datastore->get(static_cast(yColumn),static_cast(i)); - - double deltax=1; - double deltapx=0; - double deltamx=0; - if (imin==imax) { // only one x-value - deltamx=0.5; - deltapx=0.5; - } else if (i==imax-1&& i-1>=0) { // the right-most x-value - deltapx=deltamx=fabs(xv-datastore->get(xColumn,i-1))/2.0; - } else if (i==imin && i+1get(xColumn,i+1)-xv)/2.0; - } else { - if (i-1>=0) deltamx=fabs(xv-datastore->get(xColumn,i-1))/2.0; - if (i+1get(xColumn,i+1)-xv)/2.0; - } - deltax=deltapx+deltamx; - - double deltay=1; - double deltapy=0; - double deltamy=0; - if (imin==imax) { // only one y-value - deltamy=0.5; - deltapy=0.5; - } else if (i==imax-1&& i-1>=0) { // the right-most y-value - deltapy=deltamy=fabs(yv-datastore->get(yColumn,i-1))/2.0; - } else if (i==imin && i+1get(yColumn,i+1)-yv)/2.0; - } else { - if (i-1>=0) deltamy=fabs(yv-datastore->get(yColumn,i-1))/2.0; - if (i+1get(yColumn,i+1)-yv)/2.0; - } - deltay=deltapy+deltamy; - - bool plotlowerbarx=false; - bool plotupperbarx=false; - bool plotlowerbary=false; - bool plotupperbary=false; - - double xe=0; if (xErrorStyle!=JKQTPnoError && xErrorColumn>=0) { xe=datastore->get(xErrorColumn,i); plotupperbarx=true; } - double ye=0; if (yErrorStyle!=JKQTPnoError && yErrorColumn>=0) { ye=datastore->get(yErrorColumn,i); plotupperbary=true; } - double xl=0; if (xErrorSymmetric) { xl=xe; plotlowerbarx=plotupperbarx||(xl>0); } - else if (xErrorStyle!=JKQTPnoError && xErrorColumnLower>=0) { xl=datastore->get(xErrorColumnLower,i); plotlowerbarx=true; } - double yl=0; if (yErrorSymmetric) { yl=ye; plotlowerbary=plotupperbary||(yl>0); } - else if (yErrorStyle!=JKQTPnoError && yErrorColumnLower>=0) { yl=datastore->get(yErrorColumnLower,i); plotlowerbary=true; } - if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv) && JKQTPIsOKFloat(xe) && JKQTPIsOKFloat(ye) && JKQTPIsOKFloat(xl) && JKQTPIsOKFloat(yl)) { - double x=xAxis->x2p(xv+xrelshift*deltax); bool xok=JKQTPIsOKFloat(x); - double y=yAxis->x2p(yv+yrelshift*deltay); bool yok=JKQTPIsOKFloat(y); - QColor terrCol=errorColor; - QColor terrFillCol=errorFillColor; - defaultErrorColor = defaultErrorColor && !this->intPlotXYErrorIndicatorsGetColor(painter, parent, xAxis, yAxis, xColumn, yColumn, xErrorColumn, yErrorColumn, xErrorStyle, yErrorStyle, i, terrCol, terrFillCol); - - // x-errorpolygons - if (/*pastFirst &&*/ (xErrorStyle==JKQTPerrorPolygons || xErrorStyle==JKQTPerrorBarsPolygons || xErrorStyle==JKQTPerrorSimpleBarsPolygons)) { - //double xl1m=xmold; - //double xl1p=xpold; - //double yl1=yold; - double xl2m=xAxis->x2p(xv+xrelshift*deltax-xl); - double xl2p=xAxis->x2p(xv+xrelshift*deltax+xe); - double yl2=y; - /*painter.save(); - painter.setBrush(b); - painter.setPen(QPen(Qt::NoPen)); - QPolygonF poly; - poly << QPointF(xl1p, yl1) << QPointF(xl1m, yl1) << QPointF(xl2m, yl2) << QPointF(xl2p, yl2); - painter.drawConvexPolygon(poly); - painter.restore();*/ - polyXTopPoints<x2p(yv+yrelshift*deltay-yl); - double yl2p=yAxis->x2p(yv+yrelshift*deltay+ye); - double xl2=x; - /*painter.save(); - painter.setBrush(b); - painter.setPen(QPen(Qt::NoPen)); - QPolygonF poly; - poly << QPointF(xl1, yl1m) << QPointF(xl2, yl2m) << QPointF(xl2, yl2p) << QPointF(xl1, yl1p); - painter.drawConvexPolygon(poly); - painter.restore();*/ - polyYTopPoints<=xmin && xv<=xmax && yv>=ymin && yv<=ymax) { - //x-errorbars - if ((xErrorColumn>=0 || xErrorColumnLower>=0) && (xErrorStyle==JKQTPerrorBars || xErrorStyle==JKQTPerrorBarsLines|| xErrorStyle==JKQTPerrorBarsPolygons - || xErrorStyle==JKQTPerrorSimpleBars || xErrorStyle==JKQTPerrorSimpleBarsLines|| xErrorStyle==JKQTPerrorSimpleBarsPolygons)) { - double x0=xAxis->x2p(xv+xrelshift*deltax-xl); bool x0ok=JKQTPIsOKFloat(x0); - double x1=xAxis->x2p(xv+xrelshift*deltax+xe); bool x1ok=JKQTPIsOKFloat(x1); - painter.save(); - QPen pp=p; - pp.setColor(terrCol); - painter.setPen(pp); - if (x0ok&&x1ok&&xok&&yok) { - painter.drawLine(QLineF(x0, y, x1, y)); - if (xErrorStyle==JKQTPerrorBars || xErrorStyle==JKQTPerrorBarsLines|| xErrorStyle==JKQTPerrorBarsPolygons) { - if (plotlowerbarx) painter.drawLine(QLineF(x0,y-ebs_px/2.0,x0,y+ebs_px/2.0)); - if (plotupperbarx) painter.drawLine(QLineF(x1,y-ebs_px/2.0,x1,y+ebs_px/2.0)); - } - } else if (x0ok&&!x1ok&&xok&&yok) { - painter.drawLine(QLineF(x0, y, x, y)); - if (xErrorStyle==JKQTPerrorBars || xErrorStyle==JKQTPerrorBarsLines|| xErrorStyle==JKQTPerrorBarsPolygons) { - if (plotlowerbarx) painter.drawLine(QLineF(x0,y-ebs_px/2.0,x0,y+ebs_px/2.0)); - } - if (x0x2p(parent->getXMax()),y)); - else painter.drawLine(QLineF(x,y,xAxis->x2p(parent->getXMin()),y)); - } else if (!x0ok&&x1ok&&xok&&yok) { - painter.drawLine(QLineF(x1, y, x, y)); - if (xErrorStyle==JKQTPerrorBars || xErrorStyle==JKQTPerrorBarsLines|| xErrorStyle==JKQTPerrorBarsPolygons) { - if (plotupperbarx) painter.drawLine(QLineF(x1,y-ebs_px/2.0,x1,y+ebs_px/2.0)); - } - if (x1x2p(parent->getXMin()),y)); - else painter.drawLine(QLineF(x,y,xAxis->x2p(parent->getXMax()),y)); - } - painter.restore(); - } - // y-errorbars - if ((yErrorColumn>=0 || yErrorColumnLower>=0) && (yErrorStyle==JKQTPerrorBars || yErrorStyle==JKQTPerrorBarsLines || yErrorStyle==JKQTPerrorBarsPolygons - || yErrorStyle==JKQTPerrorSimpleBars || yErrorStyle==JKQTPerrorSimpleBarsLines || yErrorStyle==JKQTPerrorSimpleBarsPolygons)) { - double y0=yAxis->x2p(yv+yrelshift*deltay-yl); bool y0ok=JKQTPIsOKFloat(y0); - double y1=yAxis->x2p(yv+yrelshift*deltay+ye); bool y1ok=JKQTPIsOKFloat(y1); - painter.save(); - QPen pp=p; - pp.setColor(terrCol); - painter.setPen(pp); - if (y0ok&&y1ok&&xok&&yok) { - painter.drawLine(QLineF(x, y0, x, y1)); - if (yErrorStyle==JKQTPerrorBars || yErrorStyle==JKQTPerrorBarsLines || yErrorStyle==JKQTPerrorBarsPolygons) { - if (plotlowerbary) painter.drawLine(QLineF(x-ebs_px/2.0,y0,x+ebs_px/2.0,y0)); - if (plotupperbary) painter.drawLine(QLineF(x-ebs_px/2.0,y1,x+ebs_px/2.0,y1)); - } - } else if (y0ok&&!y1ok&&xok&&yok) { // upper errorbar OK, lower errorbar NAN - painter.drawLine(QLineF(x, y0, x, y)); - if (yErrorStyle==JKQTPerrorBars || yErrorStyle==JKQTPerrorBarsLines || yErrorStyle==JKQTPerrorBarsPolygons) { - if (plotlowerbary) painter.drawLine(QLineF(x-ebs_px/2.0,y0,x+ebs_px/2.0,y0)); - } - if (y0x2p(parent->getYMin()))); - else painter.drawLine(QLineF(x,y,x,yAxis->x2p(parent->getYMax()))); // inverted axis! - } else if (!y0ok&&y1ok&&xok&&yok) { - painter.drawLine(QLineF(x, y1, x, y)); - if (yErrorStyle==JKQTPerrorBars || yErrorStyle==JKQTPerrorBarsLines || yErrorStyle==JKQTPerrorBarsPolygons) { - if (plotupperbary) painter.drawLine(QLineF(x-ebs_px/2.0,y1,x+ebs_px/2.0,y1)); - } - if (y1x2p(parent->getYMax()))); - else painter.drawLine(QLineF(x,y,x,yAxis->x2p(parent->getYMin()))); - } - - painter.restore(); - } - - // error boxes - if (yErrorStyle==JKQTPerrorBoxes || xErrorStyle==JKQTPerrorBoxes || yErrorStyle==JKQTPerrorEllipses || xErrorStyle==JKQTPerrorEllipses ) { - double y0=yAxis->x2p(yv+yrelshift*deltay-yl); bool y0ok=JKQTPIsOKFloat(y0); - double y1=yAxis->x2p(yv+yrelshift*deltay+ye); bool y1ok=JKQTPIsOKFloat(y1); - double x0=xAxis->x2p(xv+xrelshift*deltax-xl); bool x0ok=JKQTPIsOKFloat(x0); - double x1=xAxis->x2p(xv+xrelshift*deltax+xe); bool x1ok=JKQTPIsOKFloat(x1); - painter.save(); - QPen pp=p; - pp.setColor(terrCol); - painter.setPen(pp); - QBrush bb=b; - bb.setColor(terrFillCol); - painter.setBrush(bb); - - QRectF errRect=QRectF(QPointF(x0,y0), QPointF(x1,y1)); - if ((y0ok&&y1ok)||(x0ok&&x1ok)) { - if (yErrorStyle==JKQTPerrorEllipses || xErrorStyle==JKQTPerrorEllipses) painter.drawEllipse(errRect); - else painter.drawRect(errRect); - } - - painter.restore(); - } //} - - // x-errorlines - if (pastFirst && (xErrorStyle==JKQTPerrorLines || xErrorStyle==JKQTPerrorBarsLines || xErrorStyle==JKQTPerrorSimpleBarsLines)) { - double xl1m=xmold; - double xl1p=xpold; - double yl1=yold; - double xl2m=xAxis->x2p(xv+xrelshift*deltax-xl); - double xl2p=xAxis->x2p(xv+xrelshift*deltax+xe); - double yl2=y; - painter.save(); - QPen pp=p; - pp.setColor(terrCol); - painter.setPen(pp); - if (JKQTPIsOKFloat(xl1m)&&JKQTPIsOKFloat(yl1)&&JKQTPIsOKFloat(xl2m)&&JKQTPIsOKFloat(yl2)) { - painter.drawLine(QLineF(xl1m, yl1, xl2m, yl2)); - } - if (JKQTPIsOKFloat(xl1p)&&JKQTPIsOKFloat(yl1)&&JKQTPIsOKFloat(xl2p)&&JKQTPIsOKFloat(yl2)) { - painter.drawLine(QLineF(xl1p, yl1, xl2p, yl2)); - } - painter.restore(); - } - - - // y-errorlines - if (pastFirst && (yErrorStyle==JKQTPerrorLines || yErrorStyle==JKQTPerrorBarsLines || yErrorStyle==JKQTPerrorSimpleBarsLines)) { - double yl1m=ymold; - double yl1p=ypold; - double xl1=xold; - double yl2m=yAxis->x2p(yv+yrelshift*deltay-yl); - double yl2p=yAxis->x2p(yv+yrelshift*deltay+ye); - double xl2=x; - painter.save(); - QPen pp=p; - pp.setColor(terrCol); - painter.setPen(pp); - if (JKQTPIsOKFloat(xl1)&&JKQTPIsOKFloat(yl1m)&&JKQTPIsOKFloat(xl2)&&JKQTPIsOKFloat(yl2m)) { - painter.drawLine(QLineF(xl1, yl1m, xl2, yl2m)); - } - if (JKQTPIsOKFloat(xl1)&&JKQTPIsOKFloat(yl1p)&&JKQTPIsOKFloat(xl2)&&JKQTPIsOKFloat(yl2p)) { - painter.drawLine(QLineF(xl1, yl1p, xl2, yl2p)); - } - painter.restore(); - } - - - - pastFirst=true; - xold=x; - xmold=xAxis->x2p(xv+xrelshift*deltax-xl); - xpold=xAxis->x2p(xv+xrelshift*deltax+xe); - yold=y; - ymold=yAxis->x2p(yv+yrelshift*deltay-yl); - ypold=yAxis->x2p(yv+yrelshift*deltay+ye); - } - } - // x-errorpolygons - if ((polyXTopPoints.size()>0 || polyXBottomPoints.size()>0) && (xErrorStyle==JKQTPerrorPolygons || xErrorStyle==JKQTPerrorBarsPolygons || xErrorStyle==JKQTPerrorSimpleBarsPolygons)) { - painter.save(); - painter.setBrush(b); - painter.setPen(QPen(Qt::NoPen)); - QPolygonF poly; - //poly << QPointF(xl1p, yl1) << QPointF(xl1m, yl1) << QPointF(xl2m, yl2) << QPointF(xl2p, yl2); - for (int i=0; i=0; i--) { - poly<0 || polyYBottomPoints.size()>0) && (yErrorStyle==JKQTPerrorPolygons || yErrorStyle==JKQTPerrorBarsPolygons || yErrorStyle==JKQTPerrorSimpleBarsPolygons)) { - painter.save(); - painter.setBrush(b); - painter.setPen(QPen(Qt::NoPen)); - QPolygonF poly; - //poly << QPointF(xl1p, yl1) << QPointF(xl1m, yl1) << QPointF(xl2m, yl2) << QPointF(xl2p, yl2); - for (int i=0; i=0; i--) { - poly<* dataorder) { - intPlotXYErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, xErrorColumn, -1, xErrorStyle, JKQTPnoError, datarange_start, datarange_end, xErrorColumnLower, -1, xErrorSymmetric, true, xrelshift, yrelshift, dataorder); -} - -double JKQTPxGraphErrors::getXErrorU(int i, JKQTPdatastore *ds) const -{ - if (ds && xErrorColumn>=0) { - return ds->get(xErrorColumn, i); - } - return 0.0; -} - -double JKQTPxGraphErrors::getXErrorL(int i, JKQTPdatastore *ds) const -{ - if (ds) { - if (xErrorSymmetric) { if (xErrorColumn>=0) return ds->get(xErrorColumn, i); } - else if (xErrorColumnLower>=0) return ds->get(xErrorColumnLower, i); - } - return 0.0; -} - - - - - - - -JKQTPyGraphErrors::JKQTPyGraphErrors(QColor graphColor): - JKQTPgraphErrors(graphColor) -{ - yErrorColumn=-1; - yErrorSymmetric=true; - yErrorStyle=JKQTPnoError; - yErrorColumnLower=-1; -} - -void JKQTPyGraphErrors::plotErrorIndicators(JKQTPEnhancedPainter& painter, JKQtBasePlotter* parent, JKQTPcoordinateAxis* xAxis, JKQTPcoordinateAxis* yAxis, int xColumn, int yColumn, long long datarange_start, long long datarange_end, double xrelshift, double yrelshift, const QVector* dataorder) { - intPlotXYErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, -1, yErrorColumn, JKQTPnoError, yErrorStyle, datarange_start, datarange_end, -1, yErrorColumnLower, true, yErrorSymmetric, xrelshift, yrelshift, dataorder); -} - -double JKQTPyGraphErrors::getYErrorU(int i, JKQTPdatastore *ds) const -{ - if (ds && yErrorColumn>=0) { - return ds->get(yErrorColumn, i); - } - return 0.0; -} - -double JKQTPyGraphErrors::getYErrorL(int i, JKQTPdatastore *ds) const -{ - if (ds) { - if (yErrorSymmetric) { if (yErrorColumn>=0) return ds->get(yErrorColumn, i); } - else if (yErrorColumnLower>=0) return ds->get(yErrorColumnLower, i); - } - return 0.0; -} - - - - - - - -JKQTPxyGraphErrors::JKQTPxyGraphErrors(QColor graphColor): - JKQTPgraphErrors(graphColor) -{ - xErrorSymmetric=true; - yErrorSymmetric=true; - yErrorColumn=-1; - yErrorStyle=JKQTPnoError; - xErrorColumn=-1; - xErrorStyle=JKQTPnoError; - xErrorColumnLower=-1; - yErrorColumnLower=-1; - -} - -void JKQTPxyGraphErrors::plotErrorIndicators(JKQTPEnhancedPainter& painter, JKQtBasePlotter* parent, JKQTPcoordinateAxis* xAxis, JKQTPcoordinateAxis* yAxis, int xColumn, int yColumn, long long datarange_start, long long datarange_end, double xrelshift, double yrelshift, const QVector* dataorder) { - this->intPlotXYErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, xErrorColumn, yErrorColumn, xErrorStyle, yErrorStyle, datarange_start, datarange_end, xErrorColumnLower, yErrorColumnLower, xErrorSymmetric, yErrorSymmetric, xrelshift, yrelshift, dataorder); -} - -double JKQTPxyGraphErrors::getXErrorU(int i, JKQTPdatastore *ds) const -{ - if (ds && xErrorColumn>=0) { - return ds->get(xErrorColumn, i); - } - return 0.0; -} - -double JKQTPxyGraphErrors::getXErrorL(int i, JKQTPdatastore *ds) const -{ - if (ds && xErrorColumn>=0) { - if (xErrorSymmetric) { if (xErrorColumn>=0) return ds->get(xErrorColumn, i); } - else if (xErrorColumnLower>=0) return ds->get(xErrorColumnLower, i); - } - return 0.0; -} - -double JKQTPxyGraphErrors::getYErrorU(int i, JKQTPdatastore *ds) const -{ - if (ds && yErrorColumn>=0) { - return ds->get(yErrorColumn, i); - } - return 0.0; -} - -double JKQTPxyGraphErrors::getYErrorL(int i, JKQTPdatastore *ds) const -{ - if (ds && yErrorColumn>=0) { - if (yErrorSymmetric) { if (yErrorColumn>=0) return ds->get(yErrorColumn, i); } - else if (yErrorColumnLower>=0) return ds->get(yErrorColumnLower, i); - } - return 0.0; -} - - - - - - - - - - - - JKQTPxyLineGraph::JKQTPxyLineGraph(JKQtPlotter* parent): JKQTPxyGraph(parent) { - sortData=JKQTPxyLineGraph::Unsorted; + sortData=JKQTPxyGraph::Unsorted; drawSelectionLine=false; selectionLineColor=Qt::transparent; color=QColor("red"); @@ -1234,7 +254,7 @@ JKQTPxyLineGraph::JKQTPxyLineGraph(JKQtPlotter* parent): JKQTPxyLineGraph::JKQTPxyLineGraph(JKQtBasePlotter* parent): JKQTPxyGraph(parent) { - sortData=JKQTPxyLineGraph::Unsorted; + sortData=JKQTPxyGraph::Unsorted; drawSelectionLine=false; selectionLineColor=Qt::transparent; color=QColor("red"); @@ -1489,6 +509,14 @@ bool JKQTPxyLineErrorGraph::usesColumn(int c) return JKQTPxyLineGraph::usesColumn(c)||JKQTPxyGraphErrors::errorUsesColumn(c); } +void JKQTPxyLineErrorGraph::drawErrorsBefore(JKQTPEnhancedPainter &painter) +{ + intSortData(); + if (sortData==JKQTPxyGraph::Unsorted) plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end); + else plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end, 0, 0, &sortedIndices); + +} + @@ -2090,1813 +1118,6 @@ void JKQTPfilledCurveYGraph::draw(JKQTPEnhancedPainter& painter) { -JKQTPboxplotVerticalGraph::JKQTPboxplotVerticalGraph(JKQtBasePlotter* parent): - JKQTPgraph(parent) -{ - posColumn=-1; - medianColumn=-1; - meanColumn=-1; - minColumn=-1; - maxColumn=-1; - percentile25Column=-1; - percentile75Column=-1; - color=QColor("red"); - fillColor=QColor("white"); - fillStyle=Qt::SolidPattern; - whiskerStyle=Qt::SolidLine; - lineWidth=1; - boxWidth=0.4; - meanSymbol=JKQTPplus; - meanSymbolWidth=1; - meanSymbolSize=12; - sortData=Unsorted; - - if (parent) { // get style settings from parent object - parentPlotStyle=parent->getNextStyle(); - //std::cout<<"got style settings from parent: "<getPlotStyle(parentPlotStyle).color(); - whiskerStyle=parent->getPlotStyle(parentPlotStyle).style(); - } - -} - - -JKQTPboxplotVerticalGraph::JKQTPboxplotVerticalGraph(JKQtPlotter* parent): - JKQTPgraph(parent) -{ - posColumn=-1; - medianColumn=-1; - meanColumn=-1; - minColumn=-1; - maxColumn=-1; - percentile25Column=-1; - percentile75Column=-1; - color=QColor("red"); - fillColor=QColor("white"); - fillStyle=Qt::SolidPattern; - whiskerStyle=Qt::SolidLine; - lineWidth=1; - boxWidth=0.4; - meanSymbol=JKQTPplus; - meanSymbolWidth=1; - meanSymbolSize=12; - sortData=Unsorted; - - if (parent) { // get style settings from parent object - parentPlotStyle=parent->getNextStyle(); - //std::cout<<"got style settings from parent: "<getPlotStyle(parentPlotStyle).color(); - whiskerStyle=parent->getPlotStyle(parentPlotStyle).style(); - } - -} - - -void JKQTPboxplotVerticalGraph::draw(JKQTPEnhancedPainter& painter) { -#ifdef JKQTBP_AUTOTIMER - JKQTPAutoOutputTimer jkaaot("JKQTPboxplotVerticalGraph::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.setJoinStyle(Qt::RoundJoin); - p.setJoinStyle(Qt::RoundJoin); - p.setCapStyle(Qt::RoundCap); - QPen pw=p; - pw.setStyle(whiskerStyle); - QPen np(Qt::NoPen); - - QBrush b=painter.brush(); - b.setColor(fillColor); - b.setStyle(fillStyle); - - int imax=datastore->getColumn(posColumn).getRows(); - int imin=0; - // interpret data ranges - if (datarange_start>-1) { - imin=qMin(datarange_start, static_cast(imax)); - } - if (datarange_end>-1) { - imax=qMin(datarange_end, static_cast(imax)); - } - if (imaxx2p(datastore->get(posColumn,i-1)); - double xv=xAxis->x2p(datastore->get(posColumn,i)); - if (posColumn>=0 && JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(xv0)) { - if (bwfirst) { - boxwidth_real=fabs(xv-xv0); - bwfirst=false; - } else { - if (fabs(xv-xv0)>0) boxwidth_real=qMin(fabs(xv-xv0), boxwidth_real); - } - } - } - // 2. plot: - painter.save(); - for (int i=imin; iget(posColumn,i); - double p25v=datastore->get(percentile25Column,i); - double p75v=datastore->get(percentile75Column,i); - double minv=datastore->get(minColumn,i); - double maxv=datastore->get(maxColumn,i); - double medianv=datastore->get(medianColumn,i); - double mean=yAxis->x2p(datastore->get(meanColumn,i)); - - QVector lines_p, lines_pw; - - //std::cout<<"(xv, yv) = ( "<=0 && JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(p25v) && - JKQTPIsOKFloat(p75v) && JKQTPIsOKFloat(minv) && - JKQTPIsOKFloat(maxv) && JKQTPIsOKFloat(medianv) ) { - - painter.save(); - painter.setPen(p); - painter.setBrush(b); - //std::cout<<"boxplot(med="<x2p(xv); - double p25=yAxis->x2p(p25v); - double p75=yAxis->x2p(p75v); - double min=yAxis->x2p(minv); - double max=yAxis->x2p(maxv); - double median=yAxis->x2p(medianv); - - double xn=x+1; - if (i+1x2p(datastore->get(posColumn,i+1)); - else if (i-1>=0) xn=xAxis->x2p(datastore->get(posColumn,i-1)); - else xn=x+1; - - - double w=((boxwidth_real>0)?boxwidth_real:(fabs(xn-x)))*boxWidth; - double minstop=p25; - double maxstop=p75; - if (percentile25Column<0 && medianColumn>=0) minstop=median; - else if (percentile25Column<0 && meanColumn>=0) minstop=mean; - else if (percentile25Column<0 && maxColumn>=0) minstop=max; - if (percentile75Column<0 && medianColumn>=0) maxstop=median; - else if (percentile75Column<0 && meanColumn>=0) maxstop=mean; - else if (percentile75Column<0 && minColumn>=0) maxstop=min; - double xma=x+w/2.0; - double xmi=x-w/2.0; - double xma4=x+w/4.0; - double xmi4=x-w/4.0; - - if (imax<=0) { - xma=xAxis->x2p(xv+boxWidth/2.0); - xmi=xAxis->x2p(xv-boxWidth/2.0); - xma4=xAxis->x2p(xv+boxWidth/4.0); - xmi4=xAxis->x2p(xv-boxWidth/4.0); - } - - if (minColumn>=0) { - lines_p.append(QLineF(xmi4, min, xma4, min)); - lines_pw.append(QLineF(x, min, x, minstop)); - } - if (maxColumn>=0) { - lines_p.append(QLineF(xmi4, max, xma4, max)); - lines_pw.append(QLineF(x, max, x, maxstop)); - } - - if (percentile25Column>=0 && percentile75Column>=0) painter.drawRect(QRectF(xmi, p75, fabs(xma-xmi), fabs(p75-p25))); - if (medianColumn>=0) lines_p.append(QLineF(xmi+p.widthF()/2.0, median, xma-p.widthF()/2.0, median)); - if (meanColumn>=0 && JKQTPIsOKFloat(mean)) { - plotSymbol(painter, x, mean, meanSymbol, parent->pt2px(painter, meanSymbolSize), parent->pt2px(painter, meanSymbolWidth*parent->get_lineWidthMultiplier()), color, fillColor); - } - - - painter.setPen(p); - if (lines_p.size()>0) painter.drawLines(lines_p); - painter.setPen(pw); - if (lines_pw.size()>0) painter.drawLines(lines_pw); - painter.restore(); - - //first=true; - } - } - painter.restore(); - - - drawErrorsAfter(painter); -} - - -bool JKQTPboxplotVerticalGraph::getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) { - bool start=true; - minx=0; - maxx=0; - smallestGreaterZero=0; - - if (posColumn<0) return false; - if (parent==nullptr) return false; - - JKQTPdatastore* datastore=parent->getDatastore(); - int imin=0; - int imax=datastore->getColumn(posColumn).getRows(); - // interpret data ranges - if (datarange_start>-1) { - imin=qMin(datarange_start, static_cast(imax)); - } - if (datarange_end>-1) { - imax=qMin(datarange_end, static_cast(imax)); - } - if (imaxget(posColumn,i); - if (JKQTPIsOKFloat(xv)) { - double xn=xv+1; - if (i+1get(posColumn,i+1); - else if (i-1>=0) xn=datastore->get(posColumn,i-1); - else xn=xv+1; - double delta=fabs(xn-xv); - double w=delta*boxWidth; - double xma=xv+w; - double xmi=xv-w; - if (start || xma>maxx) maxx=xma; - if (start || xmigetDatastore(); - int imin=0; - int imax=datastore->getColumn(medianColumn).getRows(); - // interpret data ranges - if (datarange_start>-1) { - imin=qMin(datarange_start, static_cast(imax)); - } - if (datarange_end>-1) { - imax=qMin(datarange_end, static_cast(imax)); - } - if (imaxget(percentile25Column,i); - double p75=datastore->get(percentile75Column,i); - double min=datastore->get(minColumn,i); - double max=datastore->get(maxColumn,i); - double median=datastore->get(medianColumn,i); - if (JKQTPIsOKFloat(median)) { - if (start || median>maxy) maxy=median; - if (start || medianmaxy) maxy=p25; - if (JKQTPIsOKFloat(p25) &&p25maxy) maxy=p75; - if (JKQTPIsOKFloat(p75) &&p75maxy) maxy=min; - if (JKQTPIsOKFloat(min) &&minmaxy) maxy=max; - if (JKQTPIsOKFloat(max) &&maxpt2px(painter, lineWidth*parent->get_lineWidthMultiplier()))); - p.setJoinStyle(Qt::RoundJoin); - QPen pw=p; - pw.setStyle(whiskerStyle); - QPen np(Qt::NoPen); - - QBrush b=painter.brush(); - b.setColor(fillColor); - b.setStyle(fillStyle); - - double x=rect.left()+rect.width()/2.0; - double xma=x+rect.width()/2.5; - double xmi=x-rect.width()/2.5; - double min=rect.bottom(); - double max=rect.top(); - double median=max+rect.height()/2.0; - double w=rect.width()/1.8; - double p25=max+0.75*rect.height(); - double p75=max+0.25*rect.height(); - - painter.setPen(p); - painter.save(); - painter.setBrush(b); - painter.drawRect(QRectF(xmi, p75, fabs(xma-xmi), fabs(p75-p25))); - painter.restore(); - painter.drawLine(QLineF(xmi, median, xma, median)); - painter.drawLine(QLineF(x-w/4.0, max, x+w/4.0, max)); - painter.drawLine(QLineF(x-w/4.0, min, x+w/4.0, min)); - painter.setPen(pw); - painter.drawLine(QLineF(x, max, x, p75)); - painter.drawLine(QLineF(x, min, x, p25)); - painter.restore(); -} - -QColor JKQTPboxplotVerticalGraph::getKeyLabelColor() { - return color; -} - - - - -void JKQTPboxplotHorizontalGraph::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) { - painter.save(); - QPen p=painter.pen(); - p.setColor(color); - p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, lineWidth*parent->get_lineWidthMultiplier()))); - p.setJoinStyle(Qt::RoundJoin); - p.setJoinStyle(Qt::RoundJoin); - p.setCapStyle(Qt::RoundCap); - QPen pw=p; - pw.setStyle(whiskerStyle); - QPen np(Qt::NoPen); - - QBrush b=painter.brush(); - b.setColor(fillColor); - b.setStyle(fillStyle); - - double y=rect.top()+rect.height()/2.0; - double yma=y+rect.height()/2.5; - double ymi=y-rect.height()/2.5; - double min=rect.left(); - double max=rect.right(); - double median=max-rect.width()/2.0; - double w=rect.height()/1.8; - double p25=min+0.75*rect.width(); - double p75=min+0.25*rect.width(); - - painter.setPen(p); - painter.save(); - painter.setBrush(b); - painter.drawRect(QRectF(p75, ymi, fabs(p75-p25), fabs(yma-ymi))); - painter.restore(); - painter.drawLine(QLineF(median, ymi, median, yma)); - painter.drawLine(QLineF(max, y-w/4.0, max, y+w/4.0)); - painter.drawLine(QLineF(min, y-w/4.0, min, y+w/4.0)); - painter.setPen(pw); - painter.drawLine(QLineF(max, y, p75, y)); - painter.drawLine(QLineF(min, y, p25, y)); - painter.restore(); -} - -bool JKQTPboxplotHorizontalGraph::getXMinMax(double& miny, double& maxy, double& smallestGreaterZero) { - bool start=true; - miny=0; - maxy=0; - smallestGreaterZero=0; - - if (percentile25Column<0 && percentile75Column<0 && medianColumn<0 && minColumn<0 && maxColumn<0) return false; - - if (parent==nullptr) return false; - - JKQTPdatastore* datastore=parent->getDatastore(); - int imin=0; - int imax=datastore->getColumn(medianColumn).getRows(); - // interpret data ranges - if (datarange_start>-1) { - imin=qMin(datarange_start, static_cast(imax)); - } - if (datarange_end>-1) { - imax=qMin(datarange_end, static_cast(imax)); - } - if (imaxget(percentile25Column,i); - double p75=datastore->get(percentile75Column,i); - double min=datastore->get(minColumn,i); - double max=datastore->get(maxColumn,i); - double median=datastore->get(medianColumn,i); - if (JKQTPIsOKFloat(median)) { - if (start || median>maxy) maxy=median; - if (start || medianmaxy) maxy=p25; - if (JKQTPIsOKFloat(p25)&&p25maxy) maxy=p75; - if (JKQTPIsOKFloat(p75)&&p75maxy) maxy=min; - if (JKQTPIsOKFloat(min)&&minmaxy) maxy=max; - if (JKQTPIsOKFloat(max)&&maxgetDatastore(); - int imin=0; - int imax=datastore->getColumn(posColumn).getRows(); - // interpret data ranges - if (datarange_start>-1) { - imin=qMin(datarange_start, static_cast(imax)); - } - if (datarange_end>-1) { - imax=qMin(datarange_end, static_cast(imax)); - } - if (imaxget(posColumn,i); - double xn=xv+1; - if (i+1get(posColumn,i+1); - else if (i-1>=0) xn=datastore->get(posColumn,i-1); - else xn=xv+1; - double delta=fabs(xn-xv); - double w=delta*boxWidth; - double xma=xv+w; - double xmi=xv-w; - if (JKQTPIsOKFloat(xma) && JKQTPIsOKFloat(xmi) ) { - if (start || xma>maxx) maxx=xma; - if (start || xmigetDatastore(); - 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.setJoinStyle(Qt::RoundJoin); - p.setJoinStyle(Qt::RoundJoin); - p.setCapStyle(Qt::RoundCap); - QPen pw=p; - pw.setStyle(whiskerStyle); - QPen np(Qt::NoPen); - - QBrush b=painter.brush(); - b.setColor(fillColor); - b.setStyle(fillStyle); - - int imax=datastore->getColumn(posColumn).getRows(); - int imin=0; - // interpret data ranges - if (datarange_start>-1) { - imin=qMin(datarange_start, static_cast(imax)); - } - if (datarange_end>-1) { - imax=qMin(datarange_end, static_cast(imax)); - } - if (imaxx2p(datastore->get(posColumn,i-1)); - double xv=yAxis->x2p(datastore->get(posColumn,i)); - if (posColumn>=0 && JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(xv0)) { - if (bwfirst) { - boxwidth_real=fabs(xv-xv0); - bwfirst=false; - } else { - if (fabs(xv-xv0)>0) boxwidth_real=qMin(fabs(xv-xv0), boxwidth_real); - } - } - } - // 2. plot: - painter.save(); - - //bool first=false; - for (int i=imin; iget(posColumn,i); - double p25v=datastore->get(percentile25Column,i); - double p75v=datastore->get(percentile75Column,i); - double minv=datastore->get(minColumn,i); - double maxv=datastore->get(maxColumn,i); - double medianv=datastore->get(medianColumn,i); - double mean=xAxis->x2p(datastore->get(meanColumn,i)); - - QVector lines_p, lines_pw; - //std::cout<<"(xv, yv) = ( "<=0 && JKQTPIsOKFloat(yv) && - JKQTPIsOKFloat(p25v) && - JKQTPIsOKFloat(p75v) && - JKQTPIsOKFloat(minv) && - JKQTPIsOKFloat(maxv) && - JKQTPIsOKFloat(medianv)) { - - painter.save(); - painter.setPen(p); - painter.setBrush(b); - - - double p25=xAxis->x2p(p25v); - double p75=xAxis->x2p(p75v); - double min=xAxis->x2p(minv); - double max=xAxis->x2p(maxv); - double median=xAxis->x2p(medianv); - - - //std::cout<<"boxplot(med="<x2p(yv); - double minstop=p25; - double maxstop=p75; - if (percentile25Column<0 && medianColumn>=0) minstop=median; - else if (percentile25Column<0 && maxColumn>=0) minstop=max; - else if (percentile25Column<0 && meanColumn>=0) minstop=mean; - if (percentile75Column<0 && medianColumn>=0) maxstop=median; - else if (percentile75Column<0 && minColumn>=0) maxstop=min; - else if (percentile75Column<0 && meanColumn>=0) maxstop=mean; - - double yn=y+1; - if (i+1x2p(datastore->get(posColumn,i+1)); - else if (i-1>=0) yn=yAxis->x2p(datastore->get(posColumn,i-1)); - else yn=y+1; - double delta=fabs(yn-y); - double w=((boxwidth_real>0)?boxwidth_real:(delta))*boxWidth; - double yma=y-w/2.0; - double ymi=y+w/2.0; - double yma4=y+w/4.0; - double ymi4=y-w/4.0; - - if (imax<=1) { - ymi=yAxis->x2p(yv+boxWidth/2.0); - yma=yAxis->x2p(yv-boxWidth/2.0); - yma4=yAxis->x2p(yv+boxWidth/4.0); - ymi4=yAxis->x2p(yv-boxWidth/4.0); - } - if (minColumn>=0) { - lines_p.append(QLineF(min, ymi4, min, yma4)); - lines_pw.append(QLineF(min, y, minstop, y)); - } - if (maxColumn>=0) { - lines_p.append(QLineF(max, ymi4, max, yma4)); - lines_pw.append(QLineF(max, y, maxstop, y)); - } - if (percentile25Column>=0 && percentile75Column>=0) painter.drawRect(QRectF(p25, qMin(yma,ymi), fabs(p75-p25), fabs(yma-ymi))); - if (medianColumn>=0) lines_p.append(QLineF(median, ymi-p.widthF()/2.0, median, yma+p.widthF()/2.0)); - - if (meanColumn>=0 && JKQTPIsOKFloat(mean)) { - plotSymbol(painter, mean, y, meanSymbol, parent->pt2px(painter, meanSymbolSize), parent->pt2px(painter, meanSymbolWidth*parent->get_lineWidthMultiplier()), color, fillColor); - } - - //first=true; - painter.setPen(p); - if (lines_p.size()>0) painter.drawLines(lines_p); - painter.setPen(pw); - if (lines_pw.size()>0) painter.drawLines(lines_pw); - painter.restore(); - } - - } - - painter.restore(); - - drawErrorsAfter(painter); -} - - - - - - - - - - - - - - - - - - - - - -JKQTPboxplotVerticalElement::JKQTPboxplotVerticalElement(JKQtBasePlotter* parent): - JKQTPgraph(parent) -{ - pos=0; - median=0; - mean=0; - min=-1; - max=1; - drawMean=true; - drawMinMax=true; - percentile25=-0.75; - percentile75=0.75; - color=QColor("red"); - fillColor=QColor("white"); - fillStyle=Qt::SolidPattern; - whiskerStyle=Qt::SolidLine; - lineWidth=1; - boxWidth=0.4; - meanSymbol=JKQTPplus; - meanSymbolWidth=1; - meanSymbolSize=12; - - if (parent) { // get style settings from parent object - parentPlotStyle=parent->getNextStyle(); - //std::cout<<"got style settings from parent: "<getPlotStyle(parentPlotStyle).color(); - whiskerStyle=parent->getPlotStyle(parentPlotStyle).style(); - } - -} - -JKQTPboxplotVerticalElement::JKQTPboxplotVerticalElement(JKQtPlotter* parent): - JKQTPgraph(parent) -{ - pos=0; - median=0; - mean=0; - min=-1; - max=1; - drawMean=true; - drawMinMax=true; - percentile25=-0.75; - percentile75=0.75; - color=QColor("red"); - fillColor=QColor("white"); - fillStyle=Qt::SolidPattern; - whiskerStyle=Qt::SolidLine; - lineWidth=1; - boxWidth=0.4; - meanSymbol=JKQTPplus; - meanSymbolWidth=1; - meanSymbolSize=12; - - if (parent) { // get style settings from parent object - parentPlotStyle=parent->getNextStyle(); - //std::cout<<"got style settings from parent: "<getPlotStyle(parentPlotStyle).color(); - whiskerStyle=parent->getPlotStyle(parentPlotStyle).style(); - } - -} -void JKQTPboxplotVerticalElement::draw(JKQTPEnhancedPainter& painter) { -#ifdef JKQTBP_AUTOTIMER - JKQTPAutoOutputTimer jkaaot("JKQTPboxplotVerticalElement::draw"); -#endif - if (parent==nullptr) return; - - 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.setJoinStyle(Qt::RoundJoin); - p.setJoinStyle(Qt::RoundJoin); - p.setCapStyle(Qt::RoundCap); - QPen pw=p; - pw.setStyle(whiskerStyle); - QPen np(Qt::NoPen); - - QBrush b=painter.brush(); - b.setColor(fillColor); - b.setStyle(fillStyle); - - - double xv=pos; - double p25v=percentile25; - double p75v=percentile75; - double minv=min; - double maxv=max; - double medianv=median; - - //std::cout<<"(xv, yv) = ( "<x2p(xv); - double p25=yAxis->x2p(p25v); - double p75=yAxis->x2p(p75v); - double min=yAxis->x2p(minv); - double max=yAxis->x2p(maxv); - double median=yAxis->x2p(medianv); - - double w=boxWidth; - double xma=x+w/2.0; - double xmi=x-w/2.0; - - painter.save(); - painter.setPen(p); - painter.save(); - painter.setBrush(b); - painter.drawRect(QRectF(xmi, p75, fabs(xma-xmi), fabs(p75-p25))); - painter.restore(); - if (drawMedian) { - painter.drawLine(QLineF(xmi, median, xma, median)); - } - if (drawMinMax) { - painter.drawLine(QLineF(x-w/4.0, max, x+w/4.0, max)); - painter.drawLine(QLineF(x-w/4.0, min, x+w/4.0, min)); - painter.setPen(pw); - painter.drawLine(QLineF(x, max, x, p75)); - painter.drawLine(QLineF(x, min, x, p25)); - } - painter.restore(); - - if (drawMean) { - double mean=yAxis->x2p(this->mean); - plotSymbol(painter, x, mean, meanSymbol, parent->pt2px(painter, meanSymbolSize), parent->pt2px(painter, meanSymbolWidth*parent->get_lineWidthMultiplier()), color, fillColor); - } - - - } - painter.restore(); - - drawErrorsAfter(painter); -} - - -bool JKQTPboxplotVerticalElement::getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) { - minx=0; - maxx=0; - smallestGreaterZero=0; - - if (parent==nullptr) return false; - - double xv=pos; - double w=boxWidth; - double xma=xv+w; - double xmi=xv-w; - maxx=xma; - minx=xmi; - double xvsgz; - xvsgz=xmi; SmallestGreaterZeroCompare_xvsgz(); - xvsgz=xma; SmallestGreaterZeroCompare_xvsgz(); - return true; -} - -bool JKQTPboxplotVerticalElement::getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) { - miny=0; - maxy=0; - smallestGreaterZero=0; - - if (parent==nullptr) return false ; - - - double p25=percentile25; - double p75=percentile75; - if (drawMedian) { - maxy=median; - miny=median; - } else { - maxy=p75; - miny=p25; - } - if (p25>maxy) maxy=p25; - if (p25maxy) maxy=p75; - if (p75maxy) maxy=min; - if (drawMinMax && (minmaxy)) maxy=max; - if (drawMinMax && (maxpt2px(painter, lineWidth*parent->get_lineWidthMultiplier()))); - p.setJoinStyle(Qt::RoundJoin); - p.setJoinStyle(Qt::RoundJoin); - p.setCapStyle(Qt::RoundCap); - QPen pw=p; - pw.setStyle(whiskerStyle); - QPen np(Qt::NoPen); - - QBrush b=painter.brush(); - b.setColor(fillColor); - b.setStyle(fillStyle); - - double x=rect.left()+rect.width()/2.0; - double xma=x+rect.width()/2.5; - double xmi=x-rect.width()/2.5; - double min=rect.bottom(); - double max=rect.top(); - double median=max+rect.height()/2.0; - double w=rect.width()/1.8; - double p25=max+0.75*rect.height(); - double p75=max+0.25*rect.height(); - - painter.setPen(p); - painter.save(); - painter.setBrush(b); - painter.drawRect(QRectF(xmi, p75, fabs(xma-xmi), fabs(p75-p25))); - painter.restore(); - painter.drawLine(QLineF(xmi, median, xma, median)); - painter.drawLine(QLineF(x-w/4.0, max, x+w/4.0, max)); - painter.drawLine(QLineF(x-w/4.0, min, x+w/4.0, min)); - painter.setPen(pw); - painter.drawLine(QLineF(x, max, x, p75)); - painter.drawLine(QLineF(x, min, x, p25)); - painter.restore(); -} - -QColor JKQTPboxplotVerticalElement::getKeyLabelColor() { - return color; -} - - - - -void JKQTPboxplotHorizontalElement::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) { - painter.save(); - QPen p=painter.pen(); - p.setColor(color); - p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, lineWidth*parent->get_lineWidthMultiplier()))); - p.setJoinStyle(Qt::RoundJoin); - p.setJoinStyle(Qt::RoundJoin); - p.setCapStyle(Qt::RoundCap); - - QPen pw=p; - pw.setStyle(whiskerStyle); - QPen np(Qt::NoPen); - - QBrush b=painter.brush(); - b.setColor(fillColor); - b.setStyle(fillStyle); - - double y=rect.top()+rect.height()/2.0; - double yma=y+rect.height()/2.5; - double ymi=y-rect.height()/2.5; - double min=rect.left(); - double max=rect.right(); - double median=max-rect.width()/2.0; - double w=rect.height()/1.8; - double p25=min+0.75*rect.width(); - double p75=min+0.25*rect.width(); - - painter.setPen(p); - painter.save(); - painter.setBrush(b); - painter.drawRect(QRectF(p75, ymi, fabs(p75-p25), fabs(yma-ymi))); - painter.restore(); - painter.drawLine(QLineF(median, ymi, median, yma)); - painter.drawLine(QLineF(max, y-w/4.0, max, y+w/4.0)); - painter.drawLine(QLineF(min, y-w/4.0, min, y+w/4.0)); - painter.setPen(pw); - painter.drawLine(QLineF(max, y, p75, y)); - painter.drawLine(QLineF(min, y, p25, y)); - painter.restore(); -} - -bool JKQTPboxplotHorizontalElement::getXMinMax(double& miny, double& maxy, double& smallestGreaterZero) { - miny=0; - maxy=0; - smallestGreaterZero=0; - - if (parent==nullptr) return false; - - - double p25=percentile25; - double p75=percentile75; - if (drawMedian) { - maxy=median; - miny=median; - } else { - maxy=p75; - miny=p25; - } - if (p25>maxy) maxy=p25; - if (p25maxy) maxy=p75; - if (p75maxy) maxy=min; - if (drawMinMax && (minmaxy)) maxy=max; - if (drawMinMax && (maxpt2px(painter, lineWidth*parent->get_lineWidthMultiplier()))); - p.setJoinStyle(Qt::RoundJoin); - p.setJoinStyle(Qt::RoundJoin); - p.setCapStyle(Qt::RoundCap); - QPen pw=p; - pw.setStyle(whiskerStyle); - QPen np(Qt::NoPen); - - QBrush b=painter.brush(); - b.setColor(fillColor); - b.setStyle(fillStyle); - double yv=pos; - double p25v=percentile25; - double p75v=percentile75; - double minv=min; - double maxv=max; - double medianv=median; - - //std::cout<<"(xv, yv) = ( "<x2p(yv); - double p25=xAxis->x2p(p25v); - double p75=xAxis->x2p(p75v); - double min=xAxis->x2p(minv); - double max=xAxis->x2p(maxv); - double median=xAxis->x2p(medianv); - - double w=boxWidth; - double yma=y+w/2.0; - double ymi=y-w/2.0; - - painter.save(); - painter.setPen(p); - painter.save(); - painter.setBrush(b); - painter.drawRect(QRectF(p25, ymi, fabs(p75-p25), fabs(yma-ymi))); - painter.restore(); - if (drawMedian) { - painter.drawLine(QLineF(median, ymi, median, yma)); - } - if (drawMinMax) { - painter.drawLine(QLineF(max, y-w/4.0, max, y+w/4.0)); - painter.drawLine(QLineF(min, y-w/4.0, min, y+w/4.0)); - painter.setPen(pw); - painter.drawLine(QLineF(max, y, p75, y)); - painter.drawLine(QLineF(min, y, p25, y)); - } - painter.restore(); - - if (drawMean) { - double mean=yAxis->x2p(this->mean); - plotSymbol(painter, mean, y, meanSymbol, parent->pt2px(painter, meanSymbolSize), parent->pt2px(painter, meanSymbolWidth*parent->get_lineWidthMultiplier()), color, fillColor); - } - - } - painter.restore(); - - drawErrorsAfter(painter); -} - - - - - - -double JKQTPxFunctionLineGraphPolynomial(double x, void* param) { - double res=0; - QVector* d=static_cast*>(param); - if (d && d->size()>0) { - res=d->value(0,0); - double xx=x; - for (int i=1; isize(); i++) { - res=res+d->value(i,0)*xx; - xx=xx*x; - } - } - - return res; -} - -double JKQTPxFunctionLineGraphExponential(double x, void* param) { - double res=0; - QVector* d=static_cast*>(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* d=static_cast*>(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: "<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: "<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; -} - -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; xnext = 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* dv=static_cast*>(params); - if (plotFunction==JKQTPxFunctionLineGraphPolynomial && dv && dv->size()<=2) { - // we only need the first and last datapoint - } else { - for (double x=pxmin+delta0; xnext = 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; iget(parameterColumn,i); - iparams<=0 && !JKQTPIsOKFloat(iparams[i])) { - iparams.remove(i,1); - i--; - } - - //qDebug()<<"iparams:"; - //for (i=0; i=0) { - ierrorparams.clear(); - JKQTPdatastore* datastore=parent->getDatastore(); - int imin=0; - int imax=datastore->getColumn(errorParameterColumn).getRows(); - - for (int i=imin; iget(errorParameterColumn,i); - ierrorparams<=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<x<<", "<f<<"], ["<x<<", "<f<<"] ): 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 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) = ( "<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<next) filledPolygon<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=0; i--) { - poly<x; - double yv=d->f; - //std::cout<<"(xv, yv) = ( "<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) = ( "<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 ("<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) = ( "<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; ynext = 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); - -} - - @@ -4100,6 +1321,17 @@ void JKQTPstepHorizontalGraph::draw(JKQTPEnhancedPainter& painter) { +JKQTPstepVerticalGraph::JKQTPstepVerticalGraph(JKQtBasePlotter *parent): + JKQTPstepHorizontalGraph(parent) +{ +} + +JKQTPstepVerticalGraph::JKQTPstepVerticalGraph(JKQtPlotter *parent): + JKQTPstepHorizontalGraph(parent) +{ + +} + void JKQTPstepVerticalGraph::draw(JKQTPEnhancedPainter& painter) { #ifdef JKQTBP_AUTOTIMER JKQTPAutoOutputTimer jkaaot("JKQTPstepVerticalGraph::draw"); @@ -4219,557 +1451,6 @@ void JKQTPstepVerticalGraph::draw(JKQTPEnhancedPainter& painter) { -JKQTPbarHorizontalGraph::JKQTPbarHorizontalGraph(JKQtBasePlotter* parent): - JKQTPxyGraph(parent), JKQTPxyGraphErrors() -{ - 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(); - } - setErrorColorFromGraphColor(color); -} - - -JKQTPbarHorizontalGraph::JKQTPbarHorizontalGraph(JKQtPlotter* parent): - JKQTPxyGraph(parent), JKQTPxyGraphErrors() -{ - 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(); - } - setErrorColorFromGraphColor(color); -} - -void JKQTPbarHorizontalGraph::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 JKQTPbarHorizontalGraph::getKeyLabelColor() { - return fillColor; -} - - -void JKQTPbarHorizontalGraph::draw(JKQTPEnhancedPainter& painter) { -#ifdef JKQTBP_AUTOTIMER - JKQTPAutoOutputTimer jkaaot("JKQTPbarHorizontalGraph::draw"); -#endif - if (parent==nullptr) return; - JKQTPdatastore* datastore=parent->getDatastore(); - if (datastore==nullptr) return; - - drawErrorsBefore(painter); - - QPen p=painter.pen(); - p.setColor(color); - p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, lineWidth*parent->get_lineWidthMultiplier()))); - p.setStyle(style); - p.setJoinStyle(Qt::RoundJoin); - - QBrush b=painter.brush(); - b.setColor(fillColor); - b.setStyle(fillStyle); - - int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); - int imin=0; - // interpret data ranges - if (datarange_start>-1) { - imin=qMin(datarange_start, static_cast(imax)); - } - if (datarange_end>-1) { - imax=qMin(datarange_end+1, static_cast(imax)); - } - if (imaxx2p(0); -// if (parent->getXAxis()->isLogAxis()) x0=xAxis->x2p(parent->getXAxis()->getMin()); - double y0=yAxis->x2p(0); - if (parent->getYAxis()->isLogAxis()) y0=yAxis->x2p(parent->getYAxis()->getMin()); - double delta=1; - double deltap=0; - double deltam=0; - intSortData(); - for (int iii=imin; iiiget(static_cast(xColumn),static_cast(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(yColumn),static_cast(i)); -// if (imin==imax) { // only one x-value -// deltam=0.5; -// deltap=0.5; -// } else if (i==imax-1) { // the right-most x-value -// deltap=deltam=fabs(xv-datastore->get(xColumn,i-1))/2.0; -// } else if (i==imin) { // the left-most x-value -// deltam=deltap=fabs(datastore->get(xColumn,i+1)-xv)/2.0; -// } else { -// deltam=fabs(xv-datastore->get(xColumn,i-1))/2.0; -// deltap=fabs(datastore->get(xColumn,i+1)-xv)/2.0; -// } - if (sr<0 && lr<0) { // only one x-value - deltam=0.5; - deltap=0.5; - } else if (lr<0) { // the right-most x-value - deltap=deltam=fabs(xv-datastore->get(xColumn,sr))/2.0; - } else if (sr<0) { // the left-most x-value - deltam=deltap=fabs(datastore->get(xColumn,lr)-xv)/2.0; - } else { - deltam=fabs(xv-datastore->get(xColumn,sr))/2.0; - deltap=fabs(datastore->get(xColumn,lr)-xv)/2.0; - } - //std::cout<x2p(xv+shift*delta-width*deltam); - double y=yAxis->x2p(yv); - double xx=xAxis->x2p(xv+shift*delta+width*deltap); - double yy=y0; - if (!qFuzzyIsNull(baseline)) yy=yAxis->x2p(baseline); - //std::cout<<"delta="<getDatastore(); - if (datastore==nullptr) return; - - drawErrorsBefore(painter); - - QPen p=painter.pen(); - p.setColor(color); - p.setWidthF(qMax(JKQTPLOTTER_ABS_MIN_LINEWIDTH, parent->pt2px(painter, lineWidth*parent->get_lineWidthMultiplier()))); - p.setStyle(style); - p.setJoinStyle(Qt::RoundJoin); - - QBrush b=painter.brush(); - b.setColor(fillColor); - b.setStyle(fillStyle); - - int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); - int imin=0; - // interpret data ranges - if (datarange_start>-1) { - imin=qMin(datarange_start, static_cast(imax)); - } - if (datarange_end>-1) { - imax=qMin(datarange_end+1, static_cast(imax)); - } - if (imaxx2p(0); - if (parent->getXAxis()->isLogAxis()) x0=xAxis->x2p(parent->getXAxis()->getMin()); -// double y0=yAxis->x2p(0); -// if (parent->getYAxis()->isLogAxis()) y0=yAxis->x2p(parent->getYAxis()->getMin()); - double delta=1; - double deltap=0; - double deltam=0; - painter.save(); - intSortData(); - for (int iii=imin; iiiget(static_cast(xColumn),static_cast(i)); - double yv=datastore->get(static_cast(yColumn),static_cast(i)); - long long sr=datastore->getNextLowerIndex(yColumn, i, datarange_start, datarange_end); - long long lr=datastore->getNextHigherIndex(yColumn, i, datarange_start, datarange_end); -// if (imin==imax) { // only one x-value -// deltam=0.5; -// deltap=0.5; -// } else if (i==imax-1) { // the right-most x-value -// deltap=deltam=fabs(yv-datastore->get(yColumn,i-1))/2.0; -// } else if (i==imin) { // the left-most x-value -// deltam=deltap=fabs(datastore->get(yColumn,i+1)-yv)/2.0; -// } else { -// deltam=fabs(yv-datastore->get(yColumn,i-1))/2.0; -// deltap=fabs(datastore->get(yColumn,i+1)-yv)/2.0; -// } - - 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=x0; - 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="<getDatastore(); - int imin=0; - int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); - // interpret data ranges - if (datarange_start>-1) { - imin=qMin(datarange_start, static_cast(imax)); - } - if (datarange_end>-1) { - imax=qMin(datarange_end, static_cast(imax)); - } - if (imaxget(static_cast(xColumn),static_cast(i))+getXErrorU(i, datastore); - double xvv=datastore->get(static_cast(xColumn),static_cast(i))-getXErrorL(i, datastore); - if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(xvv) ) { - if (start || xv>maxx) maxx=xv; - if (start || xvmaxx) maxx=xvv; - if (start || xvvgetDatastore(); - int imin=0; - int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); - // interpret data ranges - if (datarange_start>-1) { - imin=qMin(datarange_start, static_cast(imax)); - } - if (datarange_end>-1) { - imax=qMin(datarange_end, static_cast(imax)); - } - if (imaxget(static_cast(yColumn),static_cast(i)); - double delta, deltap, deltam; - long long sr=datastore->getNextLowerIndex(yColumn, i, datarange_start, datarange_end); - long long lr=datastore->getNextHigherIndex(yColumn, i, datarange_start, datarange_end); -// if (imin==imax) { // only one x-value -// deltam=0.5; -// deltap=0.5; -// } else if (i==imax-1) { // the right-most x-value -// deltap=deltam=fabs(yv-datastore->get(yColumn,i-1))/2.0; -// } else if (i==imin) { // the left-most x-value -// deltam=deltap=fabs(datastore->get(yColumn,i+1)-yv)/2.0; -// } else { -// deltam=fabs(yv-datastore->get(yColumn,i-1))/2.0; -// deltap=fabs(datastore->get(yColumn,i+1)-yv)/2.0; -// } - - 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.00) smallestGreaterZero=rangeMin; + return true; +} + +QColor JKQTPhorizontalRange::getKeyLabelColor() +{ + return color; +} + void JKQTPhorizontalRange::setDrawCenterLineOnly() { plotCenterLine=true; @@ -5061,6 +1762,21 @@ void JKQTPverticalRange::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& re painter.restore(); } +bool JKQTPverticalRange::getXMinMax(double &minx, double &maxx, double &smallestGreaterZero) +{ + minx=rangeMin; + maxx=rangeMax; + smallestGreaterZero=0; + if (rangeMin>0) smallestGreaterZero=rangeMin; + return true; +} + +bool JKQTPverticalRange::getYMinMax(double &miny, double &maxy, double &smallestGreaterZero) +{ + smallestGreaterZero=miny=maxy=0; + return false; +} + QPen JKQTPxyLineGraph::getLinePen(JKQTPEnhancedPainter& painter) const { QPen p; @@ -5088,56 +1804,6 @@ QBrush JKQTPxyLineGraph::getBrush(JKQTPEnhancedPainter& /*painter*/) const { return b; } -void JKQTPxyGraph::intSortData() -{ - sortedIndices.clear(); - - - - if (parent==nullptr) return ; - - JKQTPdatastore* datastore=parent->getDatastore(); - int imin=0; - int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()); - // interpret data ranges - if (datarange_start>-1) { - imin=qMin(datarange_start, static_cast(imax)); - } - if (datarange_end>-1) { - imax=qMin(datarange_end, static_cast(imax)); - } - if (imax datas; - - if (sortData==JKQTPxyLineGraph::SortedX) { - - for (int i=0; iget(static_cast(xColumn),static_cast(i)); - sortedIndices<get(static_cast(yColumn),static_cast(i)); - sortedIndices<pt2px(painter, parent->get_lineWidthMultiplier()*lineWidth))); - p.setJoinStyle(Qt::RoundJoin); - p.setCapStyle(Qt::RoundCap); - - return p; -} - -void JKQTPboxplotVerticalGraph::intSortData() -{ - sortedIndices.clear(); - - - - if (parent==nullptr) return ; - - JKQTPdatastore* datastore=parent->getDatastore(); - int imin=0; - int imax=datastore->getColumn(posColumn).getRows(); - // interpret data ranges - if (datarange_start>-1) { - imin=qMin(datarange_start, static_cast(imax)); - } - if (datarange_end>-1) { - imax=qMin(datarange_end, static_cast(imax)); - } - if (imax datas; - - if (sortData==JKQTPboxplotVerticalGraph::Sorted) { - - for (int i=0; iget(posColumn,i); - sortedIndices<pt2px(painter, parent->get_lineWidthMultiplier()*lineWidth))); - p.setJoinStyle(Qt::RoundJoin); - p.setCapStyle(Qt::RoundCap); - - return p; -} - - -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; -} QBrush JKQTPstepHorizontalGraph::getBrush(JKQTPEnhancedPainter& /*painter*/) const { QBrush b; @@ -5297,24 +1851,6 @@ QPen JKQTPstepHorizontalGraph::getLinePen(JKQTPEnhancedPainter& painter) const { return p; } -QBrush JKQTPbarHorizontalGraph::getBrush(JKQTPEnhancedPainter& /*painter*/) const { - QBrush b; - b.setColor(fillColor); - b.setStyle(fillStyle); - return b; -} - -QPen JKQTPbarHorizontalGraph::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 JKQTPhorizontalRange::getBrush(JKQTPEnhancedPainter& /*painter*/ ) const { QBrush b; b.setColor(fillColor); @@ -5332,92 +1868,89 @@ QPen JKQTPhorizontalRange::getLinePen(JKQTPEnhancedPainter& painter) const { return p; } -void JKQTPxFunctionLineGraph::set_params(const QVector ¶ms) -{ - iparams=params; - set_params(&iparams); -} - -void JKQTPxFunctionLineGraph::set_copiedParams(const double *params, int N) -{ - QVector v; - for (int i=0; i &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 JKQTPxFunctionLineGraph::get_internalParams() const { - return iparams; -} -QVector JKQTPxFunctionLineGraph::get_internalErrorParams() const { - return ierrorparams; -} - -bool JKQTPxGraphErrors::errorUsesColumn(int c) -{ - return c==(xErrorColumn) || (c==xErrorColumnLower); -} - -bool JKQTPgraphErrors::errorUsesColumn(int /*c*/) -{ - return false; -} - -void JKQTPgraphErrors::setErrorColorFromGraphColor(QColor graphColor) -{ - errorColor=graphColor.darker(); - errorFillColor=graphColor.lighter(); - //errorColor.setAlphaF(0.5); -} - -bool JKQTPyGraphErrors::errorUsesColumn(int c) -{ - return (c==yErrorColumn) || (c==yErrorColumnLower); -} - -bool JKQTPxyGraphErrors::errorUsesColumn(int c) -{ - return (c==xErrorColumn)||(c==yErrorColumn)||(c==xErrorColumnLower)||(c==yErrorColumnLower); -} - -bool JKQTPxFunctionLineGraph::usesColumn(int c) -{ - return (c==parameterColumn)||(c==errorParameterColumn); -} - bool JKQTPimpulsesHorizontalErrorGraph::usesColumn(int c) { return JKQTPimpulsesHorizontalGraph::usesColumn(c)|| JKQTPxGraphErrors::errorUsesColumn(c); } +void JKQTPimpulsesHorizontalErrorGraph::drawErrorsAfter(JKQTPEnhancedPainter &painter) +{ + if (sortData==JKQTPxyGraph::Unsorted) plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end); + else plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end, 0, 0, &sortedIndices); +} + +JKQTPimpulsesVerticalErrorGraph::JKQTPimpulsesVerticalErrorGraph(JKQtBasePlotter *parent): + JKQTPimpulsesVerticalGraph(parent), JKQTPyGraphErrors() +{ + setErrorColorFromGraphColor(color); +} + +JKQTPimpulsesVerticalErrorGraph::JKQTPimpulsesVerticalErrorGraph(JKQtPlotter *parent): + JKQTPimpulsesVerticalGraph(parent), JKQTPyGraphErrors() +{ + setErrorColorFromGraphColor(color); +} + bool JKQTPimpulsesVerticalErrorGraph::usesColumn(int c) { return JKQTPimpulsesVerticalGraph::usesColumn(c)|| JKQTPyGraphErrors::errorUsesColumn(c); } +void JKQTPimpulsesVerticalErrorGraph::drawErrorsAfter(JKQTPEnhancedPainter &painter) +{ + if (sortData==JKQTPxyGraph::Unsorted) plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end); + else plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end, 0, 0, &sortedIndices); + +} + +JKQTPfilledCurveXErrorGraph::JKQTPfilledCurveXErrorGraph(JKQtBasePlotter *parent): + JKQTPfilledCurveXGraph(parent), JKQTPyGraphErrors() +{ + setErrorColorFromGraphColor(color); +} + +JKQTPfilledCurveXErrorGraph::JKQTPfilledCurveXErrorGraph(JKQtPlotter *parent): + JKQTPfilledCurveXGraph(parent), JKQTPyGraphErrors() +{ + setErrorColorFromGraphColor(color); +} + bool JKQTPfilledCurveXErrorGraph::usesColumn(int c) { return JKQTPfilledCurveXGraph::usesColumn(c)|| JKQTPyGraphErrors::errorUsesColumn(c); } +void JKQTPfilledCurveXErrorGraph::drawErrorsAfter(JKQTPEnhancedPainter &painter) +{ + if (sortData==JKQTPxyGraph::Unsorted) plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end); + else plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end, 0, 0, &sortedIndices); + +} + +JKQTPfilledCurveYErrorGraph::JKQTPfilledCurveYErrorGraph(JKQtBasePlotter *parent): + JKQTPfilledCurveYGraph(parent), JKQTPxGraphErrors() +{ + setErrorColorFromGraphColor(color); +} + +JKQTPfilledCurveYErrorGraph::JKQTPfilledCurveYErrorGraph(JKQtPlotter *parent): + JKQTPfilledCurveYGraph(parent), JKQTPxGraphErrors() +{ + setErrorColorFromGraphColor(color); +} + bool JKQTPfilledCurveYErrorGraph::usesColumn(int c) { return JKQTPfilledCurveYGraph::usesColumn(c)|| JKQTPxGraphErrors::errorUsesColumn(c); } +void JKQTPfilledCurveYErrorGraph::drawErrorsAfter(JKQTPEnhancedPainter &painter) +{ + if (sortData==JKQTPxyGraph::Unsorted) plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end); + else plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end, 0, 0, &sortedIndices); + +} + JKQTPxyParametrizedScatterGraph::JKQTPxyParametrizedScatterGraph(JKQtBasePlotter *parent): JKQTPxyLineGraph(parent), @@ -5838,6 +2371,13 @@ bool JKQTPxyParametrizedErrorScatterGraph::usesColumn(int c) } +void JKQTPxyParametrizedErrorScatterGraph::drawErrorsBefore(JKQTPEnhancedPainter &painter) +{ + intSortData(); + if (sortData==JKQTPxyGraph::Unsorted) plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end); + else plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end, 0, 0, &sortedIndices); +} + bool JKQTPxyParametrizedErrorScatterGraph::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*/) { QColor c=getLocalColor(index); @@ -5848,7 +2388,3 @@ bool JKQTPxyParametrizedErrorScatterGraph::intPlotXYErrorIndicatorsGetColor(JKQT } -bool JKQTPbarHorizontalGraph::isHorizontal() const -{ - return true; -} diff --git a/jkqtpelements.h b/jkqtpelements.h index 47afe2aeaf..b568544ee2 100644 --- a/jkqtpelements.h +++ b/jkqtpelements.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () @@ -36,6 +36,7 @@ #include "jkqtptools.h" #include "jkqtp_imexport.h" #include "jkqtpimagetools.h" +#include "jkqtpbasegraphs.h" #ifndef JKQTPELEMENTS_H #define JKQTPELEMENTS_H @@ -47,285 +48,6 @@ 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 */ - inline 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. - */ - inline 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. - */ - inline 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 according to the parent's transformation rules */ - QVector transform(const QVector& x); - - /** \brief tool routine that transforms a QVector according to the parent's transformation rules - * and returns a (non-closed) path consisting of lines */ - QPainterPath transformToLinePath(const QVector& x); - - /** \brief tool routine that transforms a QVector according to the parent's transformation rules - * and returns a polygon */ - inline QPolygonF transformToPolygon(const QVector& 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) - JKQTPGET_SET_MACRO(int, yColumn) - JKQTPGET_SET_MACRO(DataSortOrder, sortData) - /** \brief sets the property sortData to the specified \a __value. \details Description of the parameter sortData is:
\copybrief sortData.
\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 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) - 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:
\copybrief sortData.
\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 sortedIndices; - virtual void intSortData(); - inline int getDataIndex(int i) { - if (sortData==Unsorted) return i; - return sortedIndices.value(i,i); - } - -}; - /*! \brief interprets data as a stream of x- or y-positions \f$ p_i \f$ (depending in \a yPeaks ) ans plots a line on the height \a baseline and upright lines from baseline to baseline+peakHeight at each position \f$ p_i \f$. This can be used to @@ -386,245 +108,6 @@ class LIB_EXPORT JKQTPPeakStreamGraph: public JKQTPsingleColumnGraph { -/*! \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* 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 *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 *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 *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 *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; -}; - - - - /*! \brief This implements xy line plots. This also alows to draw symbols at the data points. \ingroup jkqtplotter_plots @@ -720,8 +203,11 @@ class LIB_EXPORT JKQTPxyParametrizedScatterGraph: public JKQTPxyLineGraph, publi virtual QColor getKeyLabelColor(); JKQTPGET_SET_MACRO(int, sizeColumn) + JKQTPSET_CAST_MACRO(size_t, int, sizeColumn) JKQTPGET_SET_MACRO(int, colorColumn) + JKQTPSET_CAST_MACRO(size_t, int, colorColumn) JKQTPGET_SET_MACRO(int, symbolColumn) + JKQTPSET_CAST_MACRO(size_t, int, symbolColumn) JKQTPGET_SET_MACRO(bool, colorColumnContainsRGB) JKQTPGET_SET_MACRO(bool, gridModeForSymbolSize) JKQTPGET_SET_MACRO(double, gridDeltaX) @@ -823,11 +309,7 @@ class LIB_EXPORT JKQTPxyLineErrorGraph: public JKQTPxyLineGraph, public JKQTPxyG protected: /** \brief this function is used to plot error inidcators before plotting the graphs. */ - inline virtual void drawErrorsBefore(JKQTPEnhancedPainter& painter) { - intSortData(); - if (sortData==JKQTPxyLineGraph::Unsorted) plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end); - else plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end, 0, 0, &sortedIndices); - }; + virtual void drawErrorsBefore(JKQTPEnhancedPainter& painter) ; }; @@ -863,11 +345,7 @@ class LIB_EXPORT JKQTPxyParametrizedErrorScatterGraph: public JKQTPxyParametrize protected: /** \brief this function is used to plot error inidcators before plotting the graphs. */ - inline virtual void drawErrorsBefore(JKQTPEnhancedPainter& painter) { - intSortData(); - if (sortData==JKQTPxyLineGraph::Unsorted) plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end); - else plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end, 0, 0, &sortedIndices); - } + virtual void drawErrorsBefore(JKQTPEnhancedPainter& painter) ; /** \brief this function can be used to set the color of the error indicators automatically * @@ -942,12 +420,7 @@ class LIB_EXPORT JKQTPimpulsesHorizontalErrorGraph: public JKQTPimpulsesHorizont protected: /** \brief this function is used to plot error inidcators before plotting the graphs. */ - inline virtual void drawErrorsAfter(JKQTPEnhancedPainter& painter) { - if (sortData==JKQTPxyLineGraph::Unsorted) plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end); - else plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end, 0, 0, &sortedIndices); - - //plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end); - } + virtual void drawErrorsAfter(JKQTPEnhancedPainter& painter) ; }; @@ -982,28 +455,15 @@ class LIB_EXPORT JKQTPimpulsesVerticalErrorGraph: public JKQTPimpulsesVerticalGr Q_OBJECT public: /** \brief class constructor */ - inline JKQTPimpulsesVerticalErrorGraph(JKQtBasePlotter* parent=nullptr): - JKQTPimpulsesVerticalGraph(parent), JKQTPyGraphErrors() - { - setErrorColorFromGraphColor(color); - } + JKQTPimpulsesVerticalErrorGraph(JKQtBasePlotter* parent=nullptr); /** \brief class constructor */ - inline JKQTPimpulsesVerticalErrorGraph(JKQtPlotter* parent): - JKQTPimpulsesVerticalGraph(parent), JKQTPyGraphErrors() - { - setErrorColorFromGraphColor(color); - } + JKQTPimpulsesVerticalErrorGraph(JKQtPlotter* parent); /** \copydoc JKQTPgraph::usesColumn() */ virtual bool usesColumn(int c); protected: /** \brief this function is used to plot error inidcators before plotting the graphs. */ - inline virtual void drawErrorsAfter(JKQTPEnhancedPainter& painter) { - if (sortData==JKQTPxyLineGraph::Unsorted) plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end); - else plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end, 0, 0, &sortedIndices); - - //plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end); - } + virtual void drawErrorsAfter(JKQTPEnhancedPainter& painter) ; }; @@ -1084,28 +544,15 @@ class LIB_EXPORT JKQTPfilledCurveXErrorGraph: public JKQTPfilledCurveXGraph, pub Q_OBJECT public: /** \brief class constructor */ - inline JKQTPfilledCurveXErrorGraph(JKQtBasePlotter* parent=nullptr): - JKQTPfilledCurveXGraph(parent), JKQTPyGraphErrors() - { - setErrorColorFromGraphColor(color); - } + JKQTPfilledCurveXErrorGraph(JKQtBasePlotter* parent=nullptr); /** \brief class constructor */ - inline JKQTPfilledCurveXErrorGraph(JKQtPlotter* parent): - JKQTPfilledCurveXGraph(parent), JKQTPyGraphErrors() - { - setErrorColorFromGraphColor(color); - } + JKQTPfilledCurveXErrorGraph(JKQtPlotter* parent); /** \copydoc JKQTPgraph::usesColumn() */ virtual bool usesColumn(int c); protected: /** \brief this function is used to plot error inidcators before plotting the graphs. */ - virtual void drawErrorsAfter(JKQTPEnhancedPainter& painter) { - if (sortData==JKQTPxyLineGraph::Unsorted) plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end); - else plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end, 0, 0, &sortedIndices); - - //plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end); - }; + virtual void drawErrorsAfter(JKQTPEnhancedPainter& painter); }; @@ -1142,597 +589,20 @@ class LIB_EXPORT JKQTPfilledCurveYErrorGraph: public JKQTPfilledCurveYGraph, pub Q_OBJECT public: /** \brief class constructor */ - inline JKQTPfilledCurveYErrorGraph(JKQtBasePlotter* parent=nullptr): - JKQTPfilledCurveYGraph(parent), JKQTPxGraphErrors() - { - setErrorColorFromGraphColor(color); - } - inline JKQTPfilledCurveYErrorGraph(JKQtPlotter* parent): - JKQTPfilledCurveYGraph(parent), JKQTPxGraphErrors() - { - setErrorColorFromGraphColor(color); - } + JKQTPfilledCurveYErrorGraph(JKQtBasePlotter* parent=nullptr); + JKQTPfilledCurveYErrorGraph(JKQtPlotter* parent); /** \copydoc JKQTPgraph::usesColumn() */ virtual bool usesColumn(int c); protected: /** \brief this function is used to plot error inidcators before plotting the graphs. */ - inline virtual void drawErrorsAfter(JKQTPEnhancedPainter& painter) { - //plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end); - if (sortData==JKQTPxyLineGraph::Unsorted) plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end); - else plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end, 0, 0, &sortedIndices); - - } + virtual void drawErrorsAfter(JKQTPEnhancedPainter& painter); }; -/*! \brief This implements vertical boxplots - \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:
\copybrief sortData.
\see sortData for more information */ - inline void set_sortData(int __value) { - sortData=(DataSortOrder)__value; - if (__value>0) sortData=Sorted; - } - JKQTPGET_SET_MACRO(int, posColumn) - JKQTPGET_SET_MACRO(int, medianColumn) - JKQTPGET_SET_MACRO(int, meanColumn) - JKQTPGET_SET_MACRO(int, minColumn) - JKQTPGET_SET_MACRO(int, maxColumn) - JKQTPGET_SET_MACRO(int, percentile25Column) - JKQTPGET_SET_MACRO(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 sortedIndices; - virtual void intSortData(); - inline int getDataIndex(int i) { - if (sortData==Unsorted) return i; - return sortedIndices.value(i,i); - } - -}; - - -/*! \brief This implements horizontal boxplots - \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 boxplot 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 boxplot 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); -}; - - - - - - -/*! \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 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 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 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 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. - */ - inline virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero) { smallestGreaterZero=minx=maxx=0; return false; } - /** \brief get the maximum and minimum y-value of the graph - */ - inline virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) { smallestGreaterZero=miny=maxy=0; return false; } - - /** \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& 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 p; - p< p; - p< p; - p< p; - p< p; - p< get_internalParams() const; - QVector 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& errorParams); - - JKQTPGET_SET_MACRO(int, parameterColumn) - JKQTPGET_SET_MACRO(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 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); - -}; - - - - - /*! \brief This implements a step plot with values \f$ \left(x, f(x) \right) \f$ @@ -1827,9 +697,9 @@ class LIB_EXPORT JKQTPstepVerticalGraph: public JKQTPstepHorizontalGraph { Q_OBJECT public: /** \brief class constructor */ - inline JKQTPstepVerticalGraph(JKQtBasePlotter* parent=nullptr): JKQTPstepHorizontalGraph(parent) {} + JKQTPstepVerticalGraph(JKQtBasePlotter* parent=nullptr); /** \brief class constructor */ - inline JKQTPstepVerticalGraph(JKQtPlotter* parent): JKQTPstepHorizontalGraph(parent) {} + JKQTPstepVerticalGraph(JKQtPlotter* parent); /** \brief plots the graph to the plotter object specified as parent */ virtual void draw(JKQTPEnhancedPainter& painter); @@ -1843,176 +713,6 @@ class LIB_EXPORT JKQTPstepVerticalGraph: public JKQTPstepHorizontalGraph { -/*! \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_bargraphhorplot.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 to this function. - - */ -class LIB_EXPORT JKQTPbarHorizontalGraph: public JKQTPxyGraph, public JKQTPxyGraphErrors { - 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 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); - inline void autoscaleBarWidthAndShiftSeparatedGroups(double groupWidth=0.75) { - autoscaleBarWidthAndShift(groupWidth, 1); - } - - 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) - 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; - protected: - /** \brief this function is used to plot error inidcators before plotting the graphs. */ - inline virtual void drawErrorsAfter(JKQTPEnhancedPainter& painter) { - //plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end, shift, 0.0); - if (sortData==JKQTPxyLineGraph::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); - - } - - -}; - - - - - - -/*! \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_bargraphverplot.png - - */ -class LIB_EXPORT JKQTPbarVerticalGraph: public JKQTPbarHorizontalGraph { - Q_OBJECT - public: - /** \brief class constructor */ - inline JKQTPbarVerticalGraph(JKQtBasePlotter* parent=nullptr): JKQTPbarHorizontalGraph(parent) {} - /** \brief class constructor */ - inline JKQTPbarVerticalGraph(JKQtPlotter* parent): JKQTPbarHorizontalGraph(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; - - protected: - /** \brief this function is used to plot error inidcators before plotting the graphs. */ - virtual void drawErrorsAfter(JKQTPEnhancedPainter& painter) { - //plotErrorIndicators(painter, parent, xAxis, yAxis, xColumn, yColumn, datarange_start, datarange_end, 0.0, shift); - if (sortData==JKQTPxyLineGraph::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, shift, &sortedIndices); - - }; -}; - - - - - - - - - /*! \brief simply marks a range (and possibly a centerline) in a plot. This may be used to display e.g. mean +/- stddev or a range of interest, or the range of good values, ... \ingroup jkqtplotter_plots @@ -2035,20 +735,14 @@ class LIB_EXPORT JKQTPhorizontalRange: public JKQTPgraph { * * The result is given in the two parameters which are call-by-reference parameters! */ - inline virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero){ smallestGreaterZero=minx=maxx=0; return false; } + 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! */ - inline virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) { - miny=rangeMin; - maxy=rangeMax; - smallestGreaterZero=0; - if (rangeMin>0) smallestGreaterZero=rangeMin; - return true; - } + virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero); /** \brief returns the color to be used for the key label */ - inline virtual QColor getKeyLabelColor() { return color; } + virtual QColor getKeyLabelColor(); void setDrawCenterLineOnly(); @@ -2146,19 +840,12 @@ class LIB_EXPORT JKQTPverticalRange: public JKQTPhorizontalRange { * * The result is given in the two parameters which are call-by-reference parameters! */ - inline virtual bool getXMinMax(double& minx, double& maxx, double& smallestGreaterZero){ - minx=rangeMin; - maxx=rangeMax; - smallestGreaterZero=0; - if (rangeMin>0) smallestGreaterZero=rangeMin; - return true; - - } + 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! */ - inline virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero) { smallestGreaterZero=miny=maxy=0; return false; } + virtual bool getYMinMax(double& miny, double& maxy, double& smallestGreaterZero); }; #endif // JKQTPELEMENTS_H diff --git a/jkqtpevaluatedfunctionelements.cpp b/jkqtpevaluatedfunctionelements.cpp new file mode 100644 index 0000000000..efadb00d44 --- /dev/null +++ b/jkqtpevaluatedfunctionelements.cpp @@ -0,0 +1,817 @@ +/* + Copyright (c) 2008-2018 Jan W. Krieger () + + + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + + + +#include "jkqtpevaluatedfunctionelements.h" +#include "jkqtpbaseplotter.h" +#include +#include +#include +#include "jkqtptools.h" +#include "jkqtpimageelements.h" +#include "jkqtpbaseelements.h" +#include "jkqtplotter.h" + + + +double JKQTPxFunctionLineGraphPolynomial(double x, void* param) { + double res=0; + QVector* d=static_cast*>(param); + if (d && d->size()>0) { + res=d->value(0,0); + double xx=x; + for (int i=1; isize(); i++) { + res=res+d->value(i,0)*xx; + xx=xx*x; + } + } + + return res; +} + +double JKQTPxFunctionLineGraphExponential(double x, void* param) { + double res=0; + QVector* d=static_cast*>(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* d=static_cast*>(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: "<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: "<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; xnext = 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* dv=static_cast*>(params); + if (plotFunction==JKQTPxFunctionLineGraphPolynomial && dv && dv->size()<=2) { + // we only need the first and last datapoint + } else { + for (double x=pxmin+delta0; xnext = 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; iget(parameterColumn,i); + iparams<=0 && !JKQTPIsOKFloat(iparams[i])) { + iparams.remove(i,1); + i--; + } + + //qDebug()<<"iparams:"; + //for (i=0; i=0) { + ierrorparams.clear(); + JKQTPdatastore* datastore=parent->getDatastore(); + int imin=0; + int imax=datastore->getColumn(errorParameterColumn).getRows(); + + for (int i=imin; iget(errorParameterColumn,i); + ierrorparams<=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<x<<", "<f<<"], ["<x<<", "<f<<"] ): 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 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) = ( "<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<next) filledPolygon<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=0; i--) { + poly<x; + double yv=d->f; + //std::cout<<"(xv, yv) = ( "<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) = ( "<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 ("<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) = ( "<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; ynext = 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 ¶ms) +{ + iparams=params; + set_params(&iparams); +} + +void JKQTPxFunctionLineGraph::set_copiedParams(const double *params, int N) +{ + QVector v; + for (int i=0; i &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 JKQTPxFunctionLineGraph::get_internalParams() const { + return iparams; +} +QVector JKQTPxFunctionLineGraph::get_internalErrorParams() const { + return ierrorparams; +} + + +bool JKQTPxFunctionLineGraph::usesColumn(int c) +{ + return (c==parameterColumn)||(c==errorParameterColumn); +} + diff --git a/jkqtpevaluatedfunctionelements.h b/jkqtpevaluatedfunctionelements.h new file mode 100644 index 0000000000..dc3ad669fc --- /dev/null +++ b/jkqtpevaluatedfunctionelements.h @@ -0,0 +1,290 @@ +/* + Copyright (c) 2008-2018 Jan W. Krieger () + + + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + + + +/** + * \defgroup jkqtplotter_elements Plot Elements + * \ingroup jkqtplotter + * \defgroup jkqtplotter_plots Graphs + * \ingroup jkqtplotter_elements + */ + +/** \file jkqtpelements.h + * \ingroup jkqtplotter + */ + +#include +#include +#include +#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 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 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 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 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& 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 p; + p< p; + p< p; + p< p; + p< p; + p< get_internalParams() const; + QVector 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& 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 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 diff --git a/jkqtpgeoelements.cpp b/jkqtpgeoelements.cpp index 47b9c7024f..b45f82bbb6 100644 --- a/jkqtpgeoelements.cpp +++ b/jkqtpgeoelements.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () diff --git a/jkqtpgeoelements.h b/jkqtpgeoelements.h index 24b4f9590b..8ebac69234 100644 --- a/jkqtpgeoelements.h +++ b/jkqtpgeoelements.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () diff --git a/jkqtpimageelements.cpp b/jkqtpimageelements.cpp index f0546f9b90..bdbcf067de 100644 --- a/jkqtpimageelements.cpp +++ b/jkqtpimageelements.cpp @@ -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 diff --git a/jkqtpimageelements.h b/jkqtpimageelements.h index 2a0d458da4..3c3f7a89bd 100644 --- a/jkqtpimageelements.h +++ b/jkqtpimageelements.h @@ -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 diff --git a/jkqtpimagetools.cpp b/jkqtpimagetools.cpp index d6b9ce33e2..e4920574d6 100644 --- a/jkqtpimagetools.cpp +++ b/jkqtpimagetools.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () diff --git a/jkqtpimagetools.h b/jkqtpimagetools.h index ccd0f43651..fee9c113b0 100644 --- a/jkqtpimagetools.h +++ b/jkqtpimagetools.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () diff --git a/jkqtplotter.cpp b/jkqtplotter.cpp index 8cd3e7b5dd..6c8021a22a 100644 --- a/jkqtplotter.cpp +++ b/jkqtplotter.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () diff --git a/jkqtplotter.h b/jkqtplotter.h index 0099dc9066..a2199f4828 100644 --- a/jkqtplotter.h +++ b/jkqtplotter.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center + Copyright (c) 2008-2018 Jan W. Krieger (, ), 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& gr) { plotter->addGraphs(gr); } + /** \brief add a new graphs from a QVector, QList, std::vector ... or any standard-iterateable container with JKQTPgraph*-items */ + template + 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; diff --git a/jkqtplotter.pri b/jkqtplotter.pri index 6c88246283..7ebf8b86e7 100644 --- a/jkqtplotter.pri +++ b/jkqtplotter.pri @@ -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 \ diff --git a/jkqtpmathparser.cpp b/jkqtpmathparser.cpp index f540a0f02a..2ab9437f6c 100644 --- a/jkqtpmathparser.cpp +++ b/jkqtpmathparser.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center + Copyright (c) 2008-2018 Jan W. Krieger (, ), German Cancer Research Center diff --git a/jkqtpmathparser.h b/jkqtpmathparser.h index 448861d676..cad3de68cb 100644 --- a/jkqtpmathparser.h +++ b/jkqtpmathparser.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () diff --git a/jkqtpoverlayelements.cpp b/jkqtpoverlayelements.cpp index d4585faa1d..b1f6736946 100644 --- a/jkqtpoverlayelements.cpp +++ b/jkqtpoverlayelements.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () diff --git a/jkqtpoverlayelements.h b/jkqtpoverlayelements.h index b20c184f45..58e8282a0a 100644 --- a/jkqtpoverlayelements.h +++ b/jkqtpoverlayelements.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () diff --git a/jkqtpparsedfunctionelements.cpp b/jkqtpparsedfunctionelements.cpp index dfccca7f36..14939ce2dc 100644 --- a/jkqtpparsedfunctionelements.cpp +++ b/jkqtpparsedfunctionelements.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () diff --git a/jkqtpparsedfunctionelements.h b/jkqtpparsedfunctionelements.h index 05c69b9a3a..3fbcc52287 100644 --- a/jkqtpparsedfunctionelements.h +++ b/jkqtpparsedfunctionelements.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () @@ -27,7 +27,7 @@ #include "jkqtptools.h" #include "jkqtpmathparser.h" #include "jkqtp_imexport.h" -#include "jkqtpelements.h" +#include "jkqtpevaluatedfunctionelements.h" // forward declarations class JKQtBasePlotter; diff --git a/jkqtpplotsmodel.h b/jkqtpplotsmodel.h index 0f26bb94c2..1c6311e945 100644 --- a/jkqtpplotsmodel.h +++ b/jkqtpplotsmodel.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2018 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () diff --git a/jkqtptools.cpp b/jkqtptools.cpp index 1fce63fb35..837c7328d1 100644 --- a/jkqtptools.cpp +++ b/jkqtptools.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg +Copyright (c) 2008-2018 Jan W. Krieger () diff --git a/jkqtptools.h b/jkqtptools.h index 0eff3f4d21..cba401f4c5 100644 --- a/jkqtptools.h +++ b/jkqtptools.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center + Copyright (c) 2008-2018 Jan W. Krieger (, ), 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:
\copybrief varname.
\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:
\copybrief varname.
\see varname for more information */ \ + inline virtual void set_##varname (const typefunction & __value) \ + { \ + this->varname = static_cast(__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 diff --git a/jkqttools.cpp b/jkqttools.cpp index 94b79478a2..204fb07d0b 100644 --- a/jkqttools.cpp +++ b/jkqttools.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () last modification: $LastChangedDate$ (revision $Rev$) diff --git a/jkqttools.h b/jkqttools.h index 8921852dae..73985541cb 100644 --- a/jkqttools.h +++ b/jkqttools.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2008-2015 Jan W. Krieger (, ), German Cancer Research Center (DKFZ) & IWR, University of Heidelberg + Copyright (c) 2008-2018 Jan W. Krieger () last modification: $LastChangedDate$ (revision $Rev$) diff --git a/test/jkqtplot_test/TestWidgetBarcharts.cpp b/test/jkqtplot_test/TestWidgetBarcharts.cpp index 98980ff7b7..cb8ca3a491 100644 --- a/test/jkqtplot_test/TestWidgetBarcharts.cpp +++ b/test/jkqtplot_test/TestWidgetBarcharts.cpp @@ -3,7 +3,7 @@ #include #include #include - +#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(); diff --git a/test/jkqtplot_test/TestWidgetGraphs.cpp b/test/jkqtplot_test/TestWidgetGraphs.cpp index 53d5eb355e..9f1b46b041 100644 --- a/test/jkqtplot_test/TestWidgetGraphs.cpp +++ b/test/jkqtplot_test/TestWidgetGraphs.cpp @@ -3,7 +3,7 @@ #include #include #include - +#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(); diff --git a/test/jkqtplotter_simpletest_barchart/jkqtplotter_simpletest_barchart.cpp b/test/jkqtplotter_simpletest_barchart/jkqtplotter_simpletest_barchart.cpp index a85dd90fd0..d0250610b3 100644 --- a/test/jkqtplotter_simpletest_barchart/jkqtplotter_simpletest_barchart.cpp +++ b/test/jkqtplotter_simpletest_barchart/jkqtplotter_simpletest_barchart.cpp @@ -1,5 +1,6 @@ #include #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")); diff --git a/test/jkqtplotter_simpletest_stackedbars/jkqtplotter_simpletest_stackedbars.cpp b/test/jkqtplotter_simpletest_stackedbars/jkqtplotter_simpletest_stackedbars.cpp new file mode 100644 index 0000000000..b4c25d6638 --- /dev/null +++ b/test/jkqtplotter_simpletest_stackedbars/jkqtplotter_simpletest_stackedbars.cpp @@ -0,0 +1,112 @@ +#include +#include "jkqtplotter.h" +#include "jkqtpbarchartelements.h" + + +template +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 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 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(plotV, false); + plotV.setWindowTitle("JKQTPbarVerticalStackableGraph"); + + JKQtPlotter plotH; + addGraph(plotH, true); + plotH.setWindowTitle("JKQTPbarHorizontalStackableGraph"); + + plotV.move(100,100); + plotH.move(750,100); + + return app.exec(); +} diff --git a/test/jkqtplotter_simpletest_stackedbars/jkqtplotter_simpletest_stackedbars.pro b/test/jkqtplotter_simpletest_stackedbars/jkqtplotter_simpletest_stackedbars.pro new file mode 100644 index 0000000000..03e5cf2f53 --- /dev/null +++ b/test/jkqtplotter_simpletest_stackedbars/jkqtplotter_simpletest_stackedbars.pro @@ -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