/* Copyright (c) 2008-2024 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.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 . */ #include "jkqtplotter/graphs/jkqtpviolinplotstylingmixins.h" #include "jkqtplotter/jkqtpbaseplotter.h" #include #include #include #include "jkqtplotter/jkqtptools.h" #include "jkqtplotter/graphs/jkqtpimage.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtplotter.h" JKQTPGraphViolinplotStyleMixin::JKQTPGraphViolinplotStyleMixin() { m_whiskerLinePen=QPen(getLineColor(), getLineWidth()); whiskerLineWidth=getLineWidth(); m_whiskerCapLinePen=QPen(getLineColor(), getLineWidth()); whiskerCapLineWidth=getLineWidth(); m_medianLinePen=QPen(getLineColor(), getLineWidth()); medianLineWidth=getLineWidth(); m_meanSymbolLinePen=QPen(getLineColor(), getLineWidth()); m_meanSymbolLineWidth=1; m_meanSymbolType=JKQTPGraphSymbols::JKQTPDefaultSymbol; m_meanSymbolSize=12; m_meanSymbolFillColor=m_meanSymbolLinePen.color().lighter(); m_meanSymbolFontName=QGuiApplication::font().family(); violinWidthAbsolute=m_meanSymbolSize*6.0; relativeWhiskerWidth=0.5; m_violinStyle=ViolinStyle::SmoothViolin; m_violinPositionMode=ViolinPositionMode::ViolinBoth; } void JKQTPGraphViolinplotStyleMixin::initViolinplotStyle(JKQTBasePlotter *parent, int &parentPlotStyle) { setFillStyle(Qt::SolidPattern); setFillColor(parent->getCurrentPlotterStyle().plotBackgroundBrush.color()); initLineStyle(parent, parentPlotStyle, JKQTPPlotStyleType::Boxplot); if (parent) { // get style settings from parent object if (parentPlotStyle<0) parentPlotStyle=parent->getNextStyle(); const JKQTBasePlotter::JKQTPPen pen=parent->getPlotStyle(parentPlotStyle, JKQTPPlotStyleType::Boxplot); m_whiskerLinePen.setColor(pen.color()); m_whiskerLinePen.setStyle(pen.style()); whiskerLineWidth=pen.widthF(); m_whiskerCapLinePen.setColor(pen.color()); m_whiskerCapLinePen.setStyle(pen.style()); whiskerCapLineWidth=pen.widthF(); m_medianLinePen.setColor(pen.color()); m_medianLinePen.setStyle(pen.style()); medianLineWidth=pen.widthF(); m_meanSymbolLinePen=QPen(pen.color(), pen.style()); m_meanSymbolSize=pen.symbolSize(); m_meanSymbolLineWidth=pen.symbolLineWidthF(); m_meanSymbolType=pen.symbol(); m_meanSymbolFillColor=pen.symbolFillColor(); m_meanSymbolFontName=parent->getDefaultTextFontName(); } setWhiskerLineColor(getLineColor()); setWhiskerCapLineColor(getLineColor()); setMedianLineColor(getLineColor()); setMeanSymbolType(JKQTPPlus); if (m_meanSymbolSize>0) { violinWidthAbsolute=m_meanSymbolSize*6.0; } } void JKQTPGraphViolinplotStyleMixin::setViolinWidthAbsolute(double __value) { violinWidthAbsolute=__value; } double JKQTPGraphViolinplotStyleMixin::getViolinWidthAbsolute() const { return violinWidthAbsolute; } void JKQTPGraphViolinplotStyleMixin::setViolinplotColor(QColor c, JKQTBasePlotter *parent) { setLineColor(c); setFillColor(JKQTPGetDerivedColor(parent->getCurrentPlotterStyle().graphsStyle.filledStyle.fillColorDerivationMode, c)); setMeanColor(c); setMeanFillColor(JKQTPGetDerivedColor(parent->getCurrentPlotterStyle().graphsStyle.filledStyle.symbolFillColorDerivationMode, c)); setWhiskerLineColor(getLineColor()); setWhiskerCapLineColor(getLineColor()); setMedianLineColor(getLineColor()); c.setAlphaF(0.5); setHighlightingLineColor(c); } void JKQTPGraphViolinplotStyleMixin::setViolinplotColor(QColor c, QColor bc, JKQTBasePlotter *parent) { setViolinplotColor(c, parent); setFillColor(bc); setMeanFillColor(bc); } void JKQTPGraphViolinplotStyleMixin::setRelativeWhiskerWidth(double __value) { relativeWhiskerWidth=__value; } double JKQTPGraphViolinplotStyleMixin::getRelativeWhiskerWidth() const { return relativeWhiskerWidth; } void JKQTPGraphViolinplotStyleMixin::setMeanSymbolType(JKQTPGraphSymbols __value) { m_meanSymbolType=__value; } JKQTPGraphSymbols JKQTPGraphViolinplotStyleMixin::getMeanSymbolType() const { return m_meanSymbolType; } void JKQTPGraphViolinplotStyleMixin::setMeanSymbolFontName(const QString &__value) { m_meanSymbolFontName=__value; } QString JKQTPGraphViolinplotStyleMixin::getMeanSymbolFontName() const { return m_meanSymbolFontName; } void JKQTPGraphViolinplotStyleMixin::setMeanSize(double __value) { m_meanSymbolSize=__value; } double JKQTPGraphViolinplotStyleMixin::getMeanSize() const { return m_meanSymbolSize; } void JKQTPGraphViolinplotStyleMixin::setMeanColor(const QColor &__value) { m_meanSymbolLinePen.setColor(__value); } QColor JKQTPGraphViolinplotStyleMixin::getMeanColor() const { return m_meanSymbolLinePen.color(); } void JKQTPGraphViolinplotStyleMixin::setMeanFillColor(const QColor &__value) { m_meanSymbolFillColor=__value; } QColor JKQTPGraphViolinplotStyleMixin::getMeanFillColor() const { return m_meanSymbolFillColor; } void JKQTPGraphViolinplotStyleMixin::setMeanLineWidth(double __value) { m_meanSymbolLineWidth=__value; } double JKQTPGraphViolinplotStyleMixin::getMeanLineWidth() const { return m_meanSymbolLineWidth; } QFont JKQTPGraphViolinplotStyleMixin::getMeanSymbolFont() const { QFont f(m_meanSymbolFontName, m_meanSymbolSize); f.setStyleStrategy(QFont::PreferDefault); return f; } JKQTPGraphViolinplotStyleMixin::ViolinStyle JKQTPGraphViolinplotStyleMixin::getViolinStyle() const { return m_violinStyle; } void JKQTPGraphViolinplotStyleMixin::setViolinStyle(JKQTPGraphViolinplotStyleMixin::ViolinStyle style) { m_violinStyle=style; } JKQTPGraphViolinplotStyleMixin::ViolinPositionMode JKQTPGraphViolinplotStyleMixin::getViolinPositionMode() const { return m_violinPositionMode; } void JKQTPGraphViolinplotStyleMixin::setViolinPositionMode(JKQTPGraphViolinplotStyleMixin::ViolinPositionMode positionMode) { m_violinPositionMode=positionMode; } void JKQTPGraphViolinplotStyleMixin::setMeanLineStyle(Qt::PenStyle __value) { this->m_meanSymbolLinePen.setStyle(__value); } Qt::PenStyle JKQTPGraphViolinplotStyleMixin::getMeanLineStyle() const { return this->m_meanSymbolLinePen.style(); } void JKQTPGraphViolinplotStyleMixin::setMeanLineDashOffset(qreal offset) { m_meanSymbolLinePen.setDashOffset(offset); } qreal JKQTPGraphViolinplotStyleMixin::getMeanLineDashOffset() const { return m_meanSymbolLinePen.dashOffset(); } void JKQTPGraphViolinplotStyleMixin::setMeanLineDashPattern(const QVector &pattern) { m_meanSymbolLinePen.setDashPattern(pattern); m_meanSymbolLinePen.setStyle(Qt::CustomDashLine); } QVector JKQTPGraphViolinplotStyleMixin::getMeanLineDashPattern() const { return m_meanSymbolLinePen.dashPattern(); } void JKQTPGraphViolinplotStyleMixin::setMedianLineWidth(double __value) { medianLineWidth=__value; } double JKQTPGraphViolinplotStyleMixin::getMedianLineWidth() const { return medianLineWidth; } void JKQTPGraphViolinplotStyleMixin::setMedianLineColor(QColor __value) { m_medianLinePen.setColor(__value); } QColor JKQTPGraphViolinplotStyleMixin::getMedianLineColor() const { return m_medianLinePen.color(); } void JKQTPGraphViolinplotStyleMixin::setMedianLineStyle(Qt::PenStyle __value) { this->m_medianLinePen.setStyle(__value); } Qt::PenStyle JKQTPGraphViolinplotStyleMixin::getMedianLineStyle() const { return this->m_medianLinePen.style(); } void JKQTPGraphViolinplotStyleMixin::setMedianLineDashOffset(qreal offset) { m_medianLinePen.setDashOffset(offset); } qreal JKQTPGraphViolinplotStyleMixin::getMedianLineDashOffset() const { return m_medianLinePen.dashOffset(); } void JKQTPGraphViolinplotStyleMixin::setMedianLineDashPattern(const QVector &pattern) { m_medianLinePen.setDashPattern(pattern); m_medianLinePen.setStyle(Qt::CustomDashLine); } QVector JKQTPGraphViolinplotStyleMixin::getMedianLineDashPattern() const { return m_medianLinePen.dashPattern(); } void JKQTPGraphViolinplotStyleMixin::setMedianLineJoinStyle(Qt::PenJoinStyle style) { m_medianLinePen.setJoinStyle(style); } Qt::PenJoinStyle JKQTPGraphViolinplotStyleMixin::getMedianLineJoinStyle() const { return m_medianLinePen.joinStyle(); } void JKQTPGraphViolinplotStyleMixin::setMedianLineCapStyle(Qt::PenCapStyle style) { m_medianLinePen.setCapStyle(style); } Qt::PenCapStyle JKQTPGraphViolinplotStyleMixin::getMedianLineCapStyle() const { return m_medianLinePen.capStyle(); } void JKQTPGraphViolinplotStyleMixin::setMedianLineBrush(const QBrush &style) { m_medianLinePen.setBrush(style); } QBrush JKQTPGraphViolinplotStyleMixin::getMedianLineBrush() const { return m_medianLinePen.brush(); } void JKQTPGraphViolinplotStyleMixin::setWhiskerLineStyle(Qt::PenStyle __value) { this->m_whiskerLinePen.setStyle(__value); } Qt::PenStyle JKQTPGraphViolinplotStyleMixin::getWhiskerLineStyle() const { return this->m_whiskerLinePen.style(); } void JKQTPGraphViolinplotStyleMixin::setWhiskerLineWidth(double __value) { whiskerLineWidth=__value; } double JKQTPGraphViolinplotStyleMixin::getWhiskerLineWidth() const { return whiskerLineWidth; } void JKQTPGraphViolinplotStyleMixin::setWhiskerLineColor(QColor __value) { m_whiskerLinePen.setColor(__value); } QColor JKQTPGraphViolinplotStyleMixin::getWhiskerLineColor() const { return m_whiskerLinePen.color(); } void JKQTPGraphViolinplotStyleMixin::setWhiskerLineDashOffset(qreal offset) { m_whiskerLinePen.setDashOffset(offset); } qreal JKQTPGraphViolinplotStyleMixin::getWhiskerLineDashOffset() const { return m_whiskerLinePen.dashOffset(); } void JKQTPGraphViolinplotStyleMixin::setWhiskerLineDashPattern(const QVector &pattern) { m_whiskerLinePen.setDashPattern(pattern); m_whiskerLinePen.setStyle(Qt::CustomDashLine); } QVector JKQTPGraphViolinplotStyleMixin::getWhiskerLineDashPattern() const { return m_whiskerLinePen.dashPattern(); } void JKQTPGraphViolinplotStyleMixin::setWhiskerLineJoinStyle(Qt::PenJoinStyle style) { m_whiskerLinePen.setJoinStyle(style); } Qt::PenJoinStyle JKQTPGraphViolinplotStyleMixin::getWhiskerLineJoinStyle() const { return m_whiskerLinePen.joinStyle(); } void JKQTPGraphViolinplotStyleMixin::setWhiskerLineCapStyle(Qt::PenCapStyle style) { m_whiskerLinePen.setCapStyle(style); } Qt::PenCapStyle JKQTPGraphViolinplotStyleMixin::getWhiskerLineCapStyle() const { return m_whiskerLinePen.capStyle(); } void JKQTPGraphViolinplotStyleMixin::setWhiskerLineBrush(const QBrush &style) { m_whiskerLinePen.setBrush(style); } QBrush JKQTPGraphViolinplotStyleMixin::getWhiskerLineBrush() const { return m_whiskerLinePen.brush(); } QPen JKQTPGraphViolinplotStyleMixin::getWhiskerPen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const { QPen pw=m_whiskerLinePen; pw.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*whiskerLineWidth))); pw.setJoinStyle(Qt::MiterJoin); pw.setCapStyle(Qt::FlatCap); return pw; } void JKQTPGraphViolinplotStyleMixin::setWhiskerCapLineStyle(Qt::PenStyle __value) { this->m_whiskerCapLinePen.setStyle(__value); } Qt::PenStyle JKQTPGraphViolinplotStyleMixin::getWhiskerCapLineStyle() const { return this->m_whiskerCapLinePen.style(); } void JKQTPGraphViolinplotStyleMixin::setWhiskerCapLineWidth(double __value) { whiskerCapLineWidth=__value; } double JKQTPGraphViolinplotStyleMixin::getWhiskerCapLineWidth() const { return whiskerCapLineWidth; } void JKQTPGraphViolinplotStyleMixin::setWhiskerCapLineColor(QColor __value) { m_whiskerCapLinePen.setColor(__value); } QColor JKQTPGraphViolinplotStyleMixin::getWhiskerCapLineColor() const { return m_whiskerCapLinePen.color(); } void JKQTPGraphViolinplotStyleMixin::setWhiskerCapLineDashOffset(qreal offset) { m_whiskerCapLinePen.setDashOffset(offset); } qreal JKQTPGraphViolinplotStyleMixin::getWhiskerCapLineDashOffset() const { return m_whiskerCapLinePen.dashOffset(); } void JKQTPGraphViolinplotStyleMixin::setWhiskerCapLineDashPattern(const QVector &pattern) { m_whiskerCapLinePen.setDashPattern(pattern); m_whiskerCapLinePen.setStyle(Qt::CustomDashLine); } QVector JKQTPGraphViolinplotStyleMixin::getWhiskerCapLineDashPattern() const { return m_whiskerCapLinePen.dashPattern(); } void JKQTPGraphViolinplotStyleMixin::setWhiskerCapLineJoinStyle(Qt::PenJoinStyle style) { m_whiskerCapLinePen.setJoinStyle(style); } Qt::PenJoinStyle JKQTPGraphViolinplotStyleMixin::getWhiskerCapLineJoinStyle() const { return m_whiskerCapLinePen.joinStyle(); } void JKQTPGraphViolinplotStyleMixin::setWhiskerCapLineCapStyle(Qt::PenCapStyle style) { m_whiskerCapLinePen.setCapStyle(style); } Qt::PenCapStyle JKQTPGraphViolinplotStyleMixin::getWhiskerCapLineCapStyle() const { return m_whiskerCapLinePen.capStyle(); } void JKQTPGraphViolinplotStyleMixin::setWhiskerCapLineBrush(const QBrush &style) { m_whiskerCapLinePen.setBrush(style); } QBrush JKQTPGraphViolinplotStyleMixin::getWhiskerCapLineBrush() const { return m_whiskerCapLinePen.brush(); } QPen JKQTPGraphViolinplotStyleMixin::getWhiskerCapPen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const { QPen pw=m_whiskerCapLinePen; pw.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*whiskerCapLineWidth))); pw.setJoinStyle(Qt::MiterJoin); return pw; } QPen JKQTPGraphViolinplotStyleMixin::getMedianPen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const { QPen pw=m_medianLinePen; pw.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*medianLineWidth))); pw.setJoinStyle(Qt::MiterJoin); pw.setCapStyle(Qt::FlatCap); return pw; } QPen JKQTPGraphViolinplotStyleMixin::getMeanSymbolPen(JKQTPEnhancedPainter& painter, JKQTBasePlotter* parent) const { QPen p=m_meanSymbolLinePen; p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_meanSymbolLineWidth))); p.setStyle(Qt::SolidLine); p.setJoinStyle(Qt::RoundJoin); p.setCapStyle(Qt::RoundCap); return p; } QPen JKQTPGraphViolinplotStyleMixin::getMeanLinePen(JKQTPEnhancedPainter& painter, JKQTBasePlotter* parent) const { QPen p=m_meanSymbolLinePen; p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_meanSymbolLineWidth))); p.setJoinStyle(Qt::MiterJoin); p.setCapStyle(Qt::FlatCap); return p; } QBrush JKQTPGraphViolinplotStyleMixin::getMeanSymbolBrush(JKQTPEnhancedPainter& /*painter*/, JKQTBasePlotter* /*parent*/) const { QBrush b; b.setColor(m_meanSymbolFillColor); return b; } void JKQTPGraphViolinplotStyleMixin::plotStyledMeanSymbol(JKQTBasePlotter *parent, JKQTPEnhancedPainter &painter, double x, double y) const { JKQTPPlotSymbol(painter, x, y,m_meanSymbolType, parent->pt2px(painter, m_meanSymbolSize), parent->pt2px(painter, m_meanSymbolLineWidth*parent->getLineWidthMultiplier()), m_meanSymbolLinePen.color(), m_meanSymbolFillColor, getMeanSymbolFont()); } void JKQTPGraphViolinplotStyleMixin::plotVerticalViolinplot(JKQTBasePlotter *parent, JKQTPEnhancedPainter &painter, double xp, double xpleft, double xpright, const QVector &violin_cat, const QVector &violin_freq, double minp, double medianp, double maxp, double meanp) const { if (JKQTPIsOKFloat(xp) ) { painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); painter.setBrush(Qt::NoBrush); double minstop=medianp; double maxstop=medianp; if (!JKQTPIsOKFloat(minstop) && JKQTPIsOKFloat(meanp)) minstop=meanp; else if (!JKQTPIsOKFloat(minstop) && JKQTPIsOKFloat(maxp)) minstop=maxp; if (!JKQTPIsOKFloat(maxstop) && JKQTPIsOKFloat(meanp)) maxstop=meanp; else if (!JKQTPIsOKFloat(maxstop) && JKQTPIsOKFloat(minp)) maxstop=minp; const double wl=fabs(xpright-xp); const double wr=fabs(xpleft-xp); const double xprightWhisker=xp+wr*getRelativeWhiskerWidth(); const double xpleftWhisker=xp-wl*getRelativeWhiskerWidth(); // draw violin const int NViol=std::min(violin_cat.size(), violin_freq.size()); double medianMin=xpleft; double medianMax=xpright; if (NViol>0) { double fmin=violin_freq[0], fmax=violin_freq[0]; for (int i=1; i1) { painter.save(); auto __finalpaintboxvio=JKQTPFinally([&painter]() {painter.restore();}); painter.setPen(getLinePen(painter, parent)); painter.setBrush(getFillBrush(painter, parent)); for (int i=0; i0 && i1) { QPolygonF pleft, pright; pleft<1) { QPolygonF pleft, pright; for (int i=0; i0 && i0 && i &violin_cat, const QVector &violin_freq, double minp, double medianp, double maxp, double meanp) const { if (JKQTPIsOKFloat(yp) ) { painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); painter.setBrush(Qt::NoBrush); double minstop=medianp; double maxstop=medianp; if (!JKQTPIsOKFloat(minstop) && JKQTPIsOKFloat(meanp)) minstop=meanp; else if (!JKQTPIsOKFloat(minstop) && JKQTPIsOKFloat(maxp)) minstop=maxp; if (!JKQTPIsOKFloat(maxstop) && JKQTPIsOKFloat(meanp)) maxstop=meanp; else if (!JKQTPIsOKFloat(maxstop) && JKQTPIsOKFloat(minp)) maxstop=minp; const double wbot=fabs(ypbottom-yp); const double wtop=fabs(yptop-yp); const double xbottomWhisker=yp+wbot*getRelativeWhiskerWidth(); const double xptopWhisker=yp-wtop*getRelativeWhiskerWidth(); // draw violin const int NViol=std::min(violin_cat.size(), violin_freq.size()); double medianMin=ypbottom; double medianMax=yptop; if (NViol>0) { double fmin=violin_freq[0], fmax=violin_freq[0]; for (int i=1; i1) { painter.save(); auto __finalpaintboxvio=JKQTPFinally([&painter]() {painter.restore();}); painter.setPen(getLinePen(painter, parent)); painter.setBrush(getFillBrush(painter, parent)); for (int i=0; i0 && i1) { QPolygonF pleft, pright; pleft<1) { QPolygonF pleft, pright; for (int i=0; i0 && i0 && i