diff --git a/doc/images/JKQTPSingleColumnSymbolsGraph_RugPlot.png b/doc/images/JKQTPSingleColumnSymbolsGraph_RugPlot.png new file mode 100644 index 0000000000..3434c6f588 Binary files /dev/null and b/doc/images/JKQTPSingleColumnSymbolsGraph_RugPlot.png differ diff --git a/lib/jkqtplotter/jkqtpgraphssinglecolumnsymbols.cpp b/lib/jkqtplotter/jkqtpgraphssinglecolumnsymbols.cpp index 93ae9adee9..0981214fb2 100644 --- a/lib/jkqtplotter/jkqtpgraphssinglecolumnsymbols.cpp +++ b/lib/jkqtplotter/jkqtpgraphssinglecolumnsymbols.cpp @@ -119,6 +119,11 @@ void JKQTPSingleColumnSymbolsGraph::draw(JKQTPEnhancedPainter &painter) std::uniform_real_distribution<> dRandomScatter{position-width/2.0, position+width/2.0}; const double symSize=parent->pt2px(painter, getSymbolSize()); + QPen p=painter.pen(); + p.setColor(getSymbolColor()); + p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, getSymbolLineWidth()))); + p.setStyle(Qt::SolidLine); + p.setCapStyle(Qt::FlatCap); QVector plotSymbols; // collects symbol locations e.g. for BeeSwarmScatter-plots @@ -154,7 +159,13 @@ void JKQTPSingleColumnSymbolsGraph::draw(JKQTPEnhancedPainter &painter) } plotSymbols.append(QPointF(x,y)); if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv)) { - plotStyledSymbol(parent, painter, x, y); + if (positionScatterStyle!=RugPlot) { + plotStyledSymbol(parent, painter, x, y); + } else { + painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); + painter.setPen(p); + painter.drawLine(QLineF(x, y-symSize,x,y+symSize)); + } addHitTestData(xv, yv,iii, datastore); } } @@ -180,8 +191,13 @@ void JKQTPSingleColumnSymbolsGraph::draw(JKQTPEnhancedPainter &painter) } plotSymbols.append(QPointF(x,y)); if (JKQTPIsOKFloat(xv) && JKQTPIsOKFloat(yv)) { - plotSymbols.append(QPointF(x,y)); - plotStyledSymbol(parent, painter, x, y); + if (positionScatterStyle!=RugPlot) { + plotStyledSymbol(parent, painter, x, y); + } else { + painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); + painter.setPen(p); + painter.drawLine(QLineF(x-symSize, y,x+symSize,y)); + } addHitTestData(xv, yv,iii, datastore); } } @@ -206,7 +222,21 @@ void JKQTPSingleColumnSymbolsGraph::drawKeyMarker(JKQTPEnhancedPainter &painter, painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); QPen p=getSymbolPen(painter, parent); painter.setPen(p); - JKQTPPlotSymbol(painter, rect.left()+rect.width()/2.0, rect.top()+rect.height()/2.0, getSymbolType(), symbolSize, symbolWidth, getKeyLabelColor(), getSymbolFillColor()); + if (positionScatterStyle!=RugPlot) { + JKQTPPlotSymbol(painter, rect.left()+rect.width()/2.0, rect.top()+rect.height()/2.0, getSymbolType(), symbolSize, symbolWidth, getKeyLabelColor(), getSymbolFillColor()); + } else { + painter.translate(rect.center()); + if (dataDirection==DataDirection::X) { + painter.rotate(90); + } + painter.drawLine(QLineF(-rect.width()/4.0, rect.height()*(-0.4), rect.width()/4.0, rect.height()*(-0.4))); + painter.drawLine(QLineF(-rect.width()/4.0, rect.height()*(-0.2), rect.width()/4.0, rect.height()*(-0.2))); + painter.drawLine(QLineF(-rect.width()/4.0, rect.height()*0.0, rect.width()/4.0, rect.height()*0.0)); + painter.drawLine(QLineF(-rect.width()/4.0, rect.height()*0.05, rect.width()/4.0, rect.height()*0.05)); + painter.drawLine(QLineF(-rect.width()/4.0, rect.height()*0.15, rect.width()/4.0, rect.height()*0.15)); + painter.drawLine(QLineF(-rect.width()/4.0, rect.height()*0.3, rect.width()/4.0, rect.height()*0.3)); + painter.drawLine(QLineF(-rect.width()/4.0, rect.height()*0.45, rect.width()/4.0, rect.height()*0.45)); + } } diff --git a/lib/jkqtplotter/jkqtpgraphssinglecolumnsymbols.h b/lib/jkqtplotter/jkqtpgraphssinglecolumnsymbols.h index 389b78a751..11855908e7 100644 --- a/lib/jkqtplotter/jkqtpgraphssinglecolumnsymbols.h +++ b/lib/jkqtplotter/jkqtpgraphssinglecolumnsymbols.h @@ -57,6 +57,7 @@ class JKQTP_LIB_EXPORT JKQTPSingleColumnSymbolsGraph: public JKQTPSingleColumnGr NoScatter, /*!< \brief missing coordinate is exactly position for every datapoint in dataColumn \image html JKQTPSingleColumnSymbolsGraph_NoScatter.png */ RandomScatter, /*!< \brief missing coordinate scatters around position (with distribution-width width ) \image html JKQTPSingleColumnSymbolsGraph_RandomScatter.png */ BeeSwarmScatter, /*!< \brief missing coordinate scatters around position and the algorithm tries to prevent overlay of two symbols ("bee swarm plot", see e.g. https://www.r-statistics.com/2011/03/beeswarm-boxplot-and-plotting-it-with-r/). Note that this algorithm can be rather slow!!! \image html JKQTPSingleColumnSymbolsGraph_BeeSwarmScatter.png */ + RugPlot, /*!< \brief like NoScatter but draws each data-point as a horzintal/vertical line, centered around position, not as a symbol ("rug plot", see e.g. https://en.wikipedia.org/wiki/Rug_plot). \image html JKQTPSingleColumnSymbolsGraph_RugPlot.png */ }; /** \brief class constructor */