JKQTPlotter: REORGANIZED: separated line-graphs from jkqtpscatter.h/.cpp into jkqtplines.h/.cpp

This commit is contained in:
jkriege2 2022-08-25 22:41:41 +02:00
parent a90cbecd9d
commit fdb8ce2d75
7 changed files with 456 additions and 354 deletions

View File

@ -24,6 +24,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>FIXED issue <a href="https://github.com/jkriege2/JKQtPlotter/pull/70">#70: Typo in jkqtplotter/CMakeLists.txt</a>, thanks to <a href="https://github.com/tedlinlab">user:tedlinlab</a></li>
<li>FIXED issue <a href="https://github.com/jkriege2/JKQtPlotter/pull/80">#80: Bug with multiple inheritance with Q_GDAGET with CLANG</a>, thanks to <a href="https://github.com/igormironchik">user:igormironchik</a>, caused by <a href="https://bugreports.qt.io/browse/QTBUG-104874">QTBUG-104874</a></li>
<li>FIXED: styling was not properly applied to coordinate axes of colorbars outside the plot</li>
<li>REORGANIZED: separated line-graphs from jkqtpscatter.h/.cpp into jkqtplines.h/.cpp</li>
<li>IMPROVED: QT6-compatibility by removing deprecated warnings</li>
<li>NEW: JKQTPFilledCurveXGraph and JKQTPFilledCurveYGraph can now plot wiggle plots with different fill styles above and below the baseline (feature request <a href="https://github.com/jkriege2/JKQtPlotter/issues/68">#68 Wiggle Plots</a> from <a href="https://github.com/xichaoqiang">user:xichaoqiang</a> </li>
<li>NEW/BREAKING CHANGE: data tooltip can now also be shown when "just" moving the mouse (so far this was only possible when dragging the mouse with a button pressed). This also removes JKQtPlotter::getActMouseLeftAsToolTip() and adds JKQtPlotter::getActMouseMoveToolTip() instead! Also the default toolbars and context menus changed!</li>

View File

@ -55,6 +55,7 @@ isEmpty(JKQTP_PLOTTER_PRI_INCLUDED) {
$$PWD/jkqtplotter/graphs/jkqtpbarchartbase.h \
$$PWD/jkqtplotter/graphs/jkqtpbarchart.h \
$$PWD/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.h \
$$PWD/jkqtplotter/graphs/jkqtplines.h \
$$PWD/jkqtplotter/gui/jkqtpcomboboxes.h \
$$PWD/jkqtplotter/gui/jkqtpenhancedspinboxes.h \
$$PWD/jkqtplotter/gui/jkqtpenhancedtableview.h \
@ -107,6 +108,7 @@ isEmpty(JKQTP_PLOTTER_PRI_INCLUDED) {
$$PWD/jkqtplotter/graphs/jkqtpbarchartbase.cpp \
$$PWD/jkqtplotter/graphs/jkqtpbarchart.cpp \
$$PWD/jkqtplotter/graphs/jkqtpevaluatedparametriccurve.cpp \
$$PWD/jkqtplotter/graphs/jkqtplines.cpp \
$$PWD/jkqtplotter/gui/jkqtpcomboboxes.cpp \
$$PWD/jkqtplotter/gui/jkqtpenhancedspinboxes.cpp \
$$PWD/jkqtplotter/gui/jkqtpenhancedtableview.cpp \

View File

@ -66,6 +66,7 @@ set(SOURCES_GRAPHS
${CMAKE_CURRENT_LIST_DIR}/graphs/jkqtpviolinplotstylingmixins.cpp
${CMAKE_CURRENT_LIST_DIR}/graphs/jkqtpstatisticsadaptors.cpp
${CMAKE_CURRENT_LIST_DIR}/graphs/jkqtpevaluatedparametriccurve.cpp
${CMAKE_CURRENT_LIST_DIR}/graphs/jkqtplines.cpp
)
set(SOURCES_GUI
${CMAKE_CURRENT_LIST_DIR}/gui/jkqtpcomboboxes.cpp
@ -169,6 +170,8 @@ set(HEADERS_GRAPHS
$<INSTALL_INTERFACE:graphs/jkqtpbarchart.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/graphs/jkqtpevaluatedparametriccurve.h>
$<INSTALL_INTERFACE:graphs/jkqtpevaluatedparametriccurve.h>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/graphs/jkqtplines.h>
$<INSTALL_INTERFACE:graphs/jkqtplines.h>
)
set(HEADERS_GUI
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/gui/jkqtpcomboboxes.h>

View File

@ -0,0 +1,307 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "jkqtplotter/graphs/jkqtplines.h"
#include "jkqtplotter/jkqtpbaseplotter.h"
#include <stdlib.h>
#include <QDebug>
#include <QMarginsF>
#include <iostream>
#include "jkqtcommon/jkqtpdrawingtools.h"
#include "jkqtplotter/jkqtptools.h"
#include "jkqtplotter/jkqtpimagetools.h"
#include "jkqtplotter/graphs/jkqtpimage.h"
#include "jkqtplotter/jkqtpbaseelements.h"
#include "jkqtplotter/jkqtplotter.h"
#define SmallestGreaterZeroCompare_xvsgz() if ((xvsgz>10.0*DBL_MIN)&&((smallestGreaterZero<10.0*DBL_MIN) || (xvsgz<smallestGreaterZero))) smallestGreaterZero=xvsgz;
JKQTPXYLineGraph::JKQTPXYLineGraph(JKQTPlotter* parent):
JKQTPXYLineGraph(parent->getPlotter())
{
}
JKQTPXYLineGraph::JKQTPXYLineGraph(JKQTBasePlotter* parent):
JKQTPXYGraph(parent),
drawLine(true)
{
sortData=JKQTPXYGraph::Unsorted;
initLineStyle(parent, parentPlotStyle, JKQTPPlotStyleType::Default);
initSymbolStyle(parent, parentPlotStyle, JKQTPPlotStyleType::Default);
}
void JKQTPXYLineGraph::draw(JKQTPEnhancedPainter& painter) {
#ifdef JKQTBP_AUTOTIMER
JKQTPAutoOutputTimer jkaaot("JKQTPXYLineGraph::draw");
#endif
if (parent==nullptr) return;
const JKQTPDatastore* datastore=parent->getDatastore();
if (datastore==nullptr) return;
//qDebug()<<"JKQTPXYLineGraph::draw();";
drawErrorsBefore(painter);
{
//qDebug()<<"JKQTPXYLineGraph::draw(): "<<1;
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
//qDebug()<<"JKQTPXYLineGraph::draw(): "<<2;
const QPen p=getLinePen(painter, parent);
const QPen penSelection=getHighlightingLinePen(painter, parent);
const auto symType=getSymbolType();
const double xmin=transformX(parent->getXAxis()->getMin());
const double xmax=transformX(parent->getXAxis()->getMax());
const double ymin=transformY(parent->getYAxis()->getMin());
const double ymax=transformY(parent->getYAxis()->getMax());
const double symbolSize=parent->pt2px(painter, getSymbolSize());
const QMarginsF clipMargins=(symType==JKQTPNoSymbol)?QMarginsF(0,0,0,0):QMarginsF(symbolSize,symbolSize,symbolSize,symbolSize);
const QRectF cliprect=QRectF(qMin(xmin,xmax),qMin(ymin,ymax),fabs(xmax-xmin),fabs(ymax-ymin))+clipMargins;
int imax=0;
int imin=0;
if (getIndexRange(imin, imax)) {
QList<QPolygonF> vec_linesP;
vec_linesP.push_back(QPolygonF());
intSortData();
for (int iii=imin; iii<imax; iii++) {
const int i=qBound(imin, getDataIndex(iii), imax);
const double xv=datastore->get(static_cast<size_t>(xColumn),static_cast<size_t>(i));
const double yv=datastore->get(static_cast<size_t>(yColumn),static_cast<size_t>(i));
const double x=transformX(xv);
const double y=transformY(yv);
//qDebug()<<"JKQTPXYLineGraph::draw(): (xv, yv) = ( "<<xv<<", "<<yv<<" )";
if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv) && JKQTPIsOKFloat(x) && JKQTPIsOKFloat(y)) {
//if (isHighlighted() && getSymbolType()!=JKQTPNoSymbol) {
//JKQTPPlotSymbol(painter, x, y, JKQTPFilledCircle, parent->pt2px(painter, symbolSize*1.5), parent->pt2px(painter, symbolWidth*parent->getLineWidthMultiplier()), penSelection.color(), penSelection.color());
//}
if ((!parent->getXAxis()->isLogAxis() || xv>0.0) && (!parent->getYAxis()->isLogAxis() || yv>0.0) ) {
if (symType!=JKQTPNoSymbol && cliprect.contains(x,y)) plotStyledSymbol(parent, painter, x, y);
if (drawLine) {
vec_linesP.last() << QPointF(x,y);
}
} else {
if (drawLine) {
if (vec_linesP.size()==0 || vec_linesP.last().size()>0)
vec_linesP.push_back(QPolygonF());
}
}
}
}
//qDebug()<<"JKQTPXYLineGraph::draw(): "<<4<<" lines="<<lines.size();
//qDebug()<<"JKQTPXYLineGraph::draw(): "<<5<<" p="<<painter.pen();
if (drawLine) {
//qDebug()<<"JKQTPXYLineGraph::draw(): vec_linesP.size()=="<<vec_linesP.size();
QList<QPolygonF> linesToDraw;
if (getUseNonvisibleLineCompression()) linesToDraw=JKQTPClipPolyLines(JKQTPSimplifyPolyLines(vec_linesP, p.widthF()*getNonvisibleLineCompressionAgressiveness()), cliprect);
else linesToDraw=JKQTPClipPolyLines(vec_linesP, cliprect);
//qDebug()<<"JKQTPXYLineGraph::draw(): linesToDraw.size()=="<<linesToDraw.size()<<", clip: x="<<xmin<<".."<<xmax<<", y="<<ymin<<".."<<ymax;
for (const auto &linesP : linesToDraw) {
//qDebug()<<"JKQTPXYLineGraph::draw(): linesPFromV.size()=="<<linesPFromV.size()<<" useNonvisibleLineCompression="<<getUseNonvisibleLineCompression();
//qDebug()<<"JKQTPXYLineGraph::draw(): --> linesP.size()=="<<linesP.size();
if (linesP.size()>0) {
if (isHighlighted()) {
painter.setPen(penSelection);
painter.drawPolyline(linesP);
}
painter.setPen(p);
painter.drawPolyline(linesP);
}
}
}
//qDebug()<<"JKQTPXYLineGraph::draw(): "<<6;
}
}
//qDebug()<<"JKQTPXYLineGraph::draw(): "<<7;
drawErrorsAfter(painter);
//qDebug()<<"JKQTPXYLineGraph::draw() ... done";
}
void JKQTPXYLineGraph::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
const double minSize=qMin(rect.width(), rect.height());
const double maxSize=qMax(rect.width(), rect.height());
double symbolSize=parent->pt2px(painter, this->getSymbolSize());
if (symbolSize>minSize*0.9) symbolSize=minSize*0.9;
double symbolWidth=parent->pt2px(painter, this->getSymbolLineWidth()*parent->getLineWidthMultiplier());
if (symbolWidth>0.3*symbolSize) symbolWidth=0.3*symbolSize;
double lineWidth=parent->pt2px(painter, this->getLineWidth()*parent->getLineWidthMultiplier());
if (lineWidth>0.5*maxSize) lineWidth=0.5*maxSize;
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
QPen p=getLinePen(painter, parent);
p.setColor(getKeyLabelColor());
p.setStyle(getLineStyle());
p.setWidthF(lineWidth);
painter.setPen(p);
double y=rect.top()+rect.height()/2.0;
if (drawLine) painter.drawLine(QLineF(rect.left(), y, rect.right(), y));
JKQTPPlotSymbol(painter, rect.left()+rect.width()/2.0, rect.top()+rect.height()/2.0, getSymbolType(), symbolSize, symbolWidth, getKeyLabelColor(), getSymbolFillColor());
}
QColor JKQTPXYLineGraph::getKeyLabelColor() const {
return getSymbolColor();
}
void JKQTPXYLineGraph::setDrawLine(bool __value)
{
this->drawLine = __value;
}
bool JKQTPXYLineGraph::getDrawLine() const
{
return this->drawLine;
}
void JKQTPXYLineGraph::setColor(QColor c)
{
setLineColor(c);
setSymbolColor(c);
setSymbolFillColor(JKQTPGetDerivedColor(parent->getCurrentPlotterStyle().graphsStyle.defaultGraphStyle.fillColorDerivationMode, c));
c.setAlphaF(0.5);
setHighlightingLineColor(c);
}
JKQTPXYLineErrorGraph::JKQTPXYLineErrorGraph(JKQTBasePlotter *parent):
JKQTPXYLineGraph(parent)
{
setErrorColorFromGraphColor(getSymbolColor());
initErrorStyle(parent, parentPlotStyle);
}
JKQTPXYLineErrorGraph::JKQTPXYLineErrorGraph(JKQTPlotter *parent):
JKQTPXYLineErrorGraph(parent->getPlotter())
{
}
bool JKQTPXYLineErrorGraph::getXMinMax(double &minx, double &maxx, double &smallestGreaterZero) {
if (xErrorColumn<0 || xErrorStyle==JKQTPNoError) {
return JKQTPXYLineGraph::getXMinMax(minx, maxx, smallestGreaterZero);
} else {
bool start=true;
minx=0;
maxx=0;
smallestGreaterZero=0;
if (parent==nullptr) return false;
const JKQTPDatastore* datastore=parent->getDatastore();
int imax=0;
int imin=0;
if (getIndexRange(imin, imax)) {
for (int i=imin; i<imax; i++) {
double xv=datastore->get(static_cast<size_t>(xColumn),static_cast<size_t>(i))+getXErrorU(i, datastore);
if (JKQTPIsOKFloat(xv)) {
if (start || xv>maxx) maxx=xv;
if (start || xv<minx) minx=xv;
const double xvsgz=xv; SmallestGreaterZeroCompare_xvsgz();
start=false;
}
xv=datastore->get(static_cast<size_t>(xColumn),static_cast<size_t>(i))-getXErrorL(i, datastore);
if (JKQTPIsOKFloat(xv)) {
if (start || xv>maxx) maxx=xv;
if (start || xv<minx) minx=xv;
const double xvsgz=xv; SmallestGreaterZeroCompare_xvsgz();
start=false;
}
}
return !start;
}
}
return false;
}
bool JKQTPXYLineErrorGraph::getYMinMax(double &miny, double &maxy, double &smallestGreaterZero) {
if (yErrorColumn<0 || yErrorStyle==JKQTPNoError) {
return JKQTPXYLineGraph::getYMinMax(miny, maxy, smallestGreaterZero);
} else {
bool start=true;
miny=0;
maxy=0;
smallestGreaterZero=0;
if (parent==nullptr) return false;
const JKQTPDatastore* datastore=parent->getDatastore();
int imax=0;
int imin=0;
if (getIndexRange(imin, imax)) {
for (int i=imin; i<imax; i++) {
double yv=datastore->get(static_cast<size_t>(yColumn),static_cast<size_t>(i))+getYErrorU(i, datastore);
if (JKQTPIsOKFloat(yv)) {
if (start || yv>maxy) maxy=yv;
if (start || yv<miny) miny=yv;
const double xvsgz=yv; SmallestGreaterZeroCompare_xvsgz();
start=false;
}
yv=datastore->get(static_cast<size_t>(yColumn),static_cast<size_t>(i))-getYErrorL(i, datastore);
if (JKQTPIsOKFloat(yv)) {
if (start || yv>maxy) maxy=yv;
if (start || yv<miny) miny=yv;
const double xvsgz=yv; SmallestGreaterZeroCompare_xvsgz();
start=false;
}
}
return !start;
}
}
return false;
}
bool JKQTPXYLineErrorGraph::usesColumn(int c) const
{
return JKQTPXYLineGraph::usesColumn(c)||JKQTPXYGraphErrors::errorUsesColumn(c);
}
void JKQTPXYLineErrorGraph::drawErrorsBefore(JKQTPEnhancedPainter &painter)
{
intSortData();
if (sortData==JKQTPXYGraph::Unsorted) plotErrorIndicators(painter, parent, this, xColumn, yColumn);
else plotErrorIndicators(painter, parent, this, xColumn, yColumn, 0, 0, &sortedIndices);
}

View File

@ -0,0 +1,139 @@
/*
Copyright (c) 2008-2022 Jan W. Krieger (<jan@jkrieger.de>)
This software is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License (LGPL) as published by
the Free Software Foundation, either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License (LGPL) for more details.
You should have received a copy of the GNU Lesser General Public License (LGPL)
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef JKQTPLINES_H
#define JKQTPLINES_H
#include <QString>
#include <QPainter>
#include <QPair>
#include <functional>
#include "jkqtplotter/jkqtptools.h"
#include "jkqtplotter/jkqtplotter_imexport.h"
#include "jkqtcommon/jkqtpdrawingtools.h"
#include "jkqtplotter/jkqtpgraphsbase.h"
#include "jkqtcommon/jkqtpenhancedpainter.h"
#include "jkqtplotter/jkqtpgraphsbaseerrors.h"
#include "jkqtplotter/graphs/jkqtprange.h"
#include "jkqtplotter/jkqtpgraphsbasestylingmixins.h"
// forward declarations
class JKQTBasePlotter;
class JKQTPlotter;
class JKQTPCoordinateAxis;
class JKQTPDatastore;
//class JKQTPColorPaletteStyleAndToolsMixin;
/*! \brief This implements xy line plots. This also alows to draw symbols at the data points.
\ingroup jkqtplotter_linesymbolgraphs_simple
\image html plot_lineplots.png
\note This classes can (and does by default) apply a line-compression strategy that improves plotting speed
but reduces accuracy a bit. See JKQTPGraphLinesCompressionMixin for details.
\see \ref JKQTPlotterAdvancedLineAndFillStyling, \ref JKQTPlotterSimpleTest, \ref JKQTPlotterSymbolsAndStyles,
jkqtpstatAddVKDE1D(), jkqtpstatAddVKDE1DAutoranged(), jkqtpstatAddHKDE1D(), jkqtpstatAddHKDE1DAutoranged(),
JKQTPGraphLinesCompressionMixin
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPXYLineGraph: public JKQTPXYGraph, public JKQTPGraphLineStyleMixin, public JKQTPGraphSymbolStyleMixin, public JKQTPGraphLinesCompressionMixin {
Q_OBJECT
public:
/** \brief class constructor */
explicit JKQTPXYLineGraph(JKQTBasePlotter* parent=nullptr);
/** \brief class constructor */
JKQTPXYLineGraph(JKQTPlotter* parent);
/** \brief plots the graph to the plotter object specified as parent */
virtual void draw(JKQTPEnhancedPainter& painter) override;
/** \brief plots a key marker inside the specified rectangle \a rect */
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) override;
/** \brief returns the color to be used for the key label */
virtual QColor getKeyLabelColor() const override;
/** \copydoc drawLine */
void setDrawLine(bool __value);
/** \copydoc drawLine */
bool getDrawLine() const;
/** \brief set color of line and symbol */
void setColor(QColor c);
protected:
/** \brief indicates whether to draw a line or not */
bool drawLine;
};
/*! \brief This implements xy line plots with x and y error indicators.
\ingroup jkqtplotter_linesymbolgraphs_simple
\image html plot_errorbarlineplots.png
\image html plot_errorlinelineplots.png
\image html plot_errorpolygonlineplots.png
\see jkqtpstatAddXYErrorLineGraph(), jkqtpstatAddXErrorLineGraph(), jkqtpstatAddYErrorLineGraph(), \ref JKQTPlotterErrorBarStyles, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPXYLineErrorGraph: public JKQTPXYLineGraph, public JKQTPXYGraphErrors {
Q_OBJECT
public:
/** \brief class constructor */
JKQTPXYLineErrorGraph(JKQTBasePlotter* parent=nullptr);
/** \brief class constructor */
JKQTPXYLineErrorGraph(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) override;
/** \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) override;
/** \copydoc JKQTPGraph::usesColumn() */
virtual bool usesColumn(int c) const override;
protected:
/** \brief this function is used to plot error inidcators before plotting the graphs. */
virtual void drawErrorsBefore(JKQTPEnhancedPainter& painter) override;
};
#endif // JKQTPLINES_H

View File

@ -43,267 +43,6 @@
JKQTPXYLineGraph::JKQTPXYLineGraph(JKQTPlotter* parent):
JKQTPXYLineGraph(parent->getPlotter())
{
}
JKQTPXYLineGraph::JKQTPXYLineGraph(JKQTBasePlotter* parent):
JKQTPXYGraph(parent),
drawLine(true)
{
sortData=JKQTPXYGraph::Unsorted;
initLineStyle(parent, parentPlotStyle, JKQTPPlotStyleType::Default);
initSymbolStyle(parent, parentPlotStyle, JKQTPPlotStyleType::Default);
}
void JKQTPXYLineGraph::draw(JKQTPEnhancedPainter& painter) {
#ifdef JKQTBP_AUTOTIMER
JKQTPAutoOutputTimer jkaaot("JKQTPXYLineGraph::draw");
#endif
if (parent==nullptr) return;
const JKQTPDatastore* datastore=parent->getDatastore();
if (datastore==nullptr) return;
//qDebug()<<"JKQTPXYLineGraph::draw();";
drawErrorsBefore(painter);
{
//qDebug()<<"JKQTPXYLineGraph::draw(): "<<1;
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
//qDebug()<<"JKQTPXYLineGraph::draw(): "<<2;
const QPen p=getLinePen(painter, parent);
const QPen penSelection=getHighlightingLinePen(painter, parent);
const auto symType=getSymbolType();
const double xmin=transformX(parent->getXAxis()->getMin());
const double xmax=transformX(parent->getXAxis()->getMax());
const double ymin=transformY(parent->getYAxis()->getMin());
const double ymax=transformY(parent->getYAxis()->getMax());
const double symbolSize=parent->pt2px(painter, getSymbolSize());
const QMarginsF clipMargins=(symType==JKQTPNoSymbol)?QMarginsF(0,0,0,0):QMarginsF(symbolSize,symbolSize,symbolSize,symbolSize);
const QRectF cliprect=QRectF(qMin(xmin,xmax),qMin(ymin,ymax),fabs(xmax-xmin),fabs(ymax-ymin))+clipMargins;
int imax=0;
int imin=0;
if (getIndexRange(imin, imax)) {
QList<QPolygonF> vec_linesP;
vec_linesP.push_back(QPolygonF());
intSortData();
for (int iii=imin; iii<imax; iii++) {
const int i=qBound(imin, getDataIndex(iii), imax);
const double xv=datastore->get(static_cast<size_t>(xColumn),static_cast<size_t>(i));
const double yv=datastore->get(static_cast<size_t>(yColumn),static_cast<size_t>(i));
const double x=transformX(xv);
const double y=transformY(yv);
//qDebug()<<"JKQTPXYLineGraph::draw(): (xv, yv) = ( "<<xv<<", "<<yv<<" )";
if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv) && JKQTPIsOKFloat(x) && JKQTPIsOKFloat(y)) {
//if (isHighlighted() && getSymbolType()!=JKQTPNoSymbol) {
//JKQTPPlotSymbol(painter, x, y, JKQTPFilledCircle, parent->pt2px(painter, symbolSize*1.5), parent->pt2px(painter, symbolWidth*parent->getLineWidthMultiplier()), penSelection.color(), penSelection.color());
//}
if ((!parent->getXAxis()->isLogAxis() || xv>0.0) && (!parent->getYAxis()->isLogAxis() || yv>0.0) ) {
if (symType!=JKQTPNoSymbol && cliprect.contains(x,y)) plotStyledSymbol(parent, painter, x, y);
if (drawLine) {
vec_linesP.last() << QPointF(x,y);
}
} else {
if (drawLine) {
if (vec_linesP.size()==0 || vec_linesP.last().size()>0)
vec_linesP.push_back(QPolygonF());
}
}
}
}
//qDebug()<<"JKQTPXYLineGraph::draw(): "<<4<<" lines="<<lines.size();
//qDebug()<<"JKQTPXYLineGraph::draw(): "<<5<<" p="<<painter.pen();
if (drawLine) {
//qDebug()<<"JKQTPXYLineGraph::draw(): vec_linesP.size()=="<<vec_linesP.size();
QList<QPolygonF> linesToDraw;
if (getUseNonvisibleLineCompression()) linesToDraw=JKQTPClipPolyLines(JKQTPSimplifyPolyLines(vec_linesP, p.widthF()*getNonvisibleLineCompressionAgressiveness()), cliprect);
else linesToDraw=JKQTPClipPolyLines(vec_linesP, cliprect);
//qDebug()<<"JKQTPXYLineGraph::draw(): linesToDraw.size()=="<<linesToDraw.size()<<", clip: x="<<xmin<<".."<<xmax<<", y="<<ymin<<".."<<ymax;
for (const auto &linesP : linesToDraw) {
//qDebug()<<"JKQTPXYLineGraph::draw(): linesPFromV.size()=="<<linesPFromV.size()<<" useNonvisibleLineCompression="<<getUseNonvisibleLineCompression();
//qDebug()<<"JKQTPXYLineGraph::draw(): --> linesP.size()=="<<linesP.size();
if (linesP.size()>0) {
if (isHighlighted()) {
painter.setPen(penSelection);
painter.drawPolyline(linesP);
}
painter.setPen(p);
painter.drawPolyline(linesP);
}
}
}
//qDebug()<<"JKQTPXYLineGraph::draw(): "<<6;
}
}
//qDebug()<<"JKQTPXYLineGraph::draw(): "<<7;
drawErrorsAfter(painter);
//qDebug()<<"JKQTPXYLineGraph::draw() ... done";
}
void JKQTPXYLineGraph::drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) {
const double minSize=qMin(rect.width(), rect.height());
const double maxSize=qMax(rect.width(), rect.height());
double symbolSize=parent->pt2px(painter, this->getSymbolSize());
if (symbolSize>minSize*0.9) symbolSize=minSize*0.9;
double symbolWidth=parent->pt2px(painter, this->getSymbolLineWidth()*parent->getLineWidthMultiplier());
if (symbolWidth>0.3*symbolSize) symbolWidth=0.3*symbolSize;
double lineWidth=parent->pt2px(painter, this->getLineWidth()*parent->getLineWidthMultiplier());
if (lineWidth>0.5*maxSize) lineWidth=0.5*maxSize;
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
QPen p=getLinePen(painter, parent);
p.setColor(getKeyLabelColor());
p.setStyle(getLineStyle());
p.setWidthF(lineWidth);
painter.setPen(p);
double y=rect.top()+rect.height()/2.0;
if (drawLine) painter.drawLine(QLineF(rect.left(), y, rect.right(), y));
JKQTPPlotSymbol(painter, rect.left()+rect.width()/2.0, rect.top()+rect.height()/2.0, getSymbolType(), symbolSize, symbolWidth, getKeyLabelColor(), getSymbolFillColor());
}
QColor JKQTPXYLineGraph::getKeyLabelColor() const {
return getSymbolColor();
}
void JKQTPXYLineGraph::setDrawLine(bool __value)
{
this->drawLine = __value;
}
bool JKQTPXYLineGraph::getDrawLine() const
{
return this->drawLine;
}
void JKQTPXYLineGraph::setColor(QColor c)
{
setLineColor(c);
setSymbolColor(c);
setSymbolFillColor(JKQTPGetDerivedColor(parent->getCurrentPlotterStyle().graphsStyle.defaultGraphStyle.fillColorDerivationMode, c));
c.setAlphaF(0.5);
setHighlightingLineColor(c);
}
JKQTPXYLineErrorGraph::JKQTPXYLineErrorGraph(JKQTBasePlotter *parent):
JKQTPXYLineGraph(parent)
{
setErrorColorFromGraphColor(getSymbolColor());
initErrorStyle(parent, parentPlotStyle);
}
JKQTPXYLineErrorGraph::JKQTPXYLineErrorGraph(JKQTPlotter *parent):
JKQTPXYLineErrorGraph(parent->getPlotter())
{
}
bool JKQTPXYLineErrorGraph::getXMinMax(double &minx, double &maxx, double &smallestGreaterZero) {
if (xErrorColumn<0 || xErrorStyle==JKQTPNoError) {
return JKQTPXYLineGraph::getXMinMax(minx, maxx, smallestGreaterZero);
} else {
bool start=true;
minx=0;
maxx=0;
smallestGreaterZero=0;
if (parent==nullptr) return false;
const JKQTPDatastore* datastore=parent->getDatastore();
int imax=0;
int imin=0;
if (getIndexRange(imin, imax)) {
for (int i=imin; i<imax; i++) {
double xv=datastore->get(static_cast<size_t>(xColumn),static_cast<size_t>(i))+getXErrorU(i, datastore);
if (JKQTPIsOKFloat(xv)) {
if (start || xv>maxx) maxx=xv;
if (start || xv<minx) minx=xv;
const double xvsgz=xv; SmallestGreaterZeroCompare_xvsgz();
start=false;
}
xv=datastore->get(static_cast<size_t>(xColumn),static_cast<size_t>(i))-getXErrorL(i, datastore);
if (JKQTPIsOKFloat(xv)) {
if (start || xv>maxx) maxx=xv;
if (start || xv<minx) minx=xv;
const double xvsgz=xv; SmallestGreaterZeroCompare_xvsgz();
start=false;
}
}
return !start;
}
}
return false;
}
bool JKQTPXYLineErrorGraph::getYMinMax(double &miny, double &maxy, double &smallestGreaterZero) {
if (yErrorColumn<0 || yErrorStyle==JKQTPNoError) {
return JKQTPXYLineGraph::getYMinMax(miny, maxy, smallestGreaterZero);
} else {
bool start=true;
miny=0;
maxy=0;
smallestGreaterZero=0;
if (parent==nullptr) return false;
const JKQTPDatastore* datastore=parent->getDatastore();
int imax=0;
int imin=0;
if (getIndexRange(imin, imax)) {
for (int i=imin; i<imax; i++) {
double yv=datastore->get(static_cast<size_t>(yColumn),static_cast<size_t>(i))+getYErrorU(i, datastore);
if (JKQTPIsOKFloat(yv)) {
if (start || yv>maxy) maxy=yv;
if (start || yv<miny) miny=yv;
const double xvsgz=yv; SmallestGreaterZeroCompare_xvsgz();
start=false;
}
yv=datastore->get(static_cast<size_t>(yColumn),static_cast<size_t>(i))-getYErrorL(i, datastore);
if (JKQTPIsOKFloat(yv)) {
if (start || yv>maxy) maxy=yv;
if (start || yv<miny) miny=yv;
const double xvsgz=yv; SmallestGreaterZeroCompare_xvsgz();
start=false;
}
}
return !start;
}
}
return false;
}
bool JKQTPXYLineErrorGraph::usesColumn(int c) const
{
return JKQTPXYLineGraph::usesColumn(c)||JKQTPXYGraphErrors::errorUsesColumn(c);
}
void JKQTPXYLineErrorGraph::drawErrorsBefore(JKQTPEnhancedPainter &painter)
{
intSortData();
if (sortData==JKQTPXYGraph::Unsorted) plotErrorIndicators(painter, parent, this, xColumn, yColumn);
else plotErrorIndicators(painter, parent, this, xColumn, yColumn, 0, 0, &sortedIndices);
}

View File

@ -17,8 +17,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef jkqtpgraphs_H
#define jkqtpgraphs_H
#ifndef jkqtpscatter_H
#define jkqtpscatter_H
#include <QString>
@ -32,6 +32,7 @@
#include "jkqtcommon/jkqtpenhancedpainter.h"
#include "jkqtplotter/jkqtpgraphsbaseerrors.h"
#include "jkqtplotter/graphs/jkqtprange.h"
#include "jkqtplotter/graphs/jkqtplines.h"
#include "jkqtplotter/jkqtpgraphsbasestylingmixins.h"
// forward declarations
@ -46,59 +47,6 @@ class JKQTPDatastore;
/*! \brief This implements xy line plots. This also alows to draw symbols at the data points.
\ingroup jkqtplotter_linesymbolgraphs_simple
\image html plot_lineplots.png
\note This classes can (and does by default) apply a line-compression strategy that improves plotting speed
but reduces accuracy a bit. See JKQTPGraphLinesCompressionMixin for details.
\see \ref JKQTPlotterAdvancedLineAndFillStyling, \ref JKQTPlotterSimpleTest, \ref JKQTPlotterSymbolsAndStyles,
jkqtpstatAddVKDE1D(), jkqtpstatAddVKDE1DAutoranged(), jkqtpstatAddHKDE1D(), jkqtpstatAddHKDE1DAutoranged(),
JKQTPGraphLinesCompressionMixin
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPXYLineGraph: public JKQTPXYGraph, public JKQTPGraphLineStyleMixin, public JKQTPGraphSymbolStyleMixin, public JKQTPGraphLinesCompressionMixin {
Q_OBJECT
public:
/** \brief class constructor */
explicit JKQTPXYLineGraph(JKQTBasePlotter* parent=nullptr);
/** \brief class constructor */
JKQTPXYLineGraph(JKQTPlotter* parent);
/** \brief plots the graph to the plotter object specified as parent */
virtual void draw(JKQTPEnhancedPainter& painter) override;
/** \brief plots a key marker inside the specified rectangle \a rect */
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) override;
/** \brief returns the color to be used for the key label */
virtual QColor getKeyLabelColor() const override;
/** \copydoc drawLine */
void setDrawLine(bool __value);
/** \copydoc drawLine */
bool getDrawLine() const;
/** \brief set color of line and symbol */
void setColor(QColor c);
protected:
/** \brief indicates whether to draw a line or not */
bool drawLine;
};
/*! \brief This implements xy scatter plots (like JKQTPXYLineGraph), but the color and size of the symbols may be taken from a column.
\ingroup jkqtplotter_linesymbolgraphs_param
@ -383,43 +331,6 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPXYParametrizedScatterGraph: public JKQTPXYGrap
/*! \brief This implements xy line plots with x and y error indicators.
\ingroup jkqtplotter_linesymbolgraphs_simple
\image html plot_errorbarlineplots.png
\image html plot_errorlinelineplots.png
\image html plot_errorpolygonlineplots.png
\see jkqtpstatAddXYErrorLineGraph(), jkqtpstatAddXErrorLineGraph(), jkqtpstatAddYErrorLineGraph(), \ref JKQTPlotterErrorBarStyles, \ref JKQTPlotterBasicJKQTPDatastoreStatisticsGroupedStat
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPXYLineErrorGraph: public JKQTPXYLineGraph, public JKQTPXYGraphErrors {
Q_OBJECT
public:
/** \brief class constructor */
JKQTPXYLineErrorGraph(JKQTBasePlotter* parent=nullptr);
/** \brief class constructor */
JKQTPXYLineErrorGraph(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) override;
/** \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) override;
/** \copydoc JKQTPGraph::usesColumn() */
virtual bool usesColumn(int c) const override;
protected:
/** \brief this function is used to plot error inidcators before plotting the graphs. */
virtual void drawErrorsBefore(JKQTPEnhancedPainter& painter) override;
};
/*! \brief This implements xy scatter plots (like JKQTPXYLineGraph), but the color and size of the symbols may be taken from a column. with errorbars
\ingroup jkqtplotter_linesymbolgraphs_param
@ -464,4 +375,4 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPXYParametrizedErrorScatterGraph: public JKQTPX
#endif // jkqtpgraphs_H
#endif // jkqtpscatter_H