added possibility to register custom symbols for JKQTPPlotSymbol()

This commit is contained in:
jkriege2 2022-09-06 12:39:23 +02:00
parent f6def4b9d1
commit bf1416d5a6
5 changed files with 141 additions and 37 deletions

View File

@ -44,6 +44,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>NEW: made it's delay a global static variable that can be set and red with JKQTPlotter::setGlobalResizeDelay() and JKQTPlotter::getGlobalResizeDelay()</li>
<li>NEW: Using JKQTMathText::useGuiFonts() for FONT rendering by default</li>
<li>NEW: added the option to draw a character from a font as symbol (<code>JKQTPCharacterSymbol+QChar('C').unicode()</code> and <code>JKQTPFilledCharacterSymbol+QChar('C').unicode()</code>)</li>
<li>NEW: added the option to register a custom symbol using JKQTPRegisterCustomGraphSymbol() </li>
</ul></li>
<li>JKQTMathText:<ul>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -93,6 +93,7 @@ QString JKQTPGraphSymbols2String(JKQTPGraphSymbols pos) {
case JKQTPSymbolCount: JKQTPGraphSymbols2String(JKQTPMaxSymbolID);
case JKQTPCharacterSymbol:
case JKQTPFilledCharacterSymbol:
case JKQTPFirstCustomSymbol:
break;
}
if (pos>=JKQTPCharacterSymbol && pos<=JKQTPCharacterSymbol+0xFFFF) {
@ -105,6 +106,10 @@ QString JKQTPGraphSymbols2String(JKQTPGraphSymbols pos) {
while (s.size()<4) s="0"+s;
return "symbol_filled_char"+s;
}
if (pos>=JKQTPFirstCustomSymbol) {
QString s=QString::number(pos-JKQTPFirstCustomSymbol);
return "symbol_custom"+s;
}
return "";
}
@ -177,6 +182,7 @@ QString JKQTPGraphSymbols2NameString(JKQTPGraphSymbols pos) {
case JKQTPSymbolCount: JKQTPGraphSymbols2NameString(JKQTPMaxSymbolID);
case JKQTPCharacterSymbol:
case JKQTPFilledCharacterSymbol:
case JKQTPFirstCustomSymbol:
break;
}
if (pos>=JKQTPCharacterSymbol && pos<=JKQTPCharacterSymbol+0xFFFF) {
@ -185,6 +191,9 @@ QString JKQTPGraphSymbols2NameString(JKQTPGraphSymbols pos) {
if (pos>=JKQTPFilledCharacterSymbol && pos<=JKQTPFilledCharacterSymbol+0xFFFF) {
return QObject::tr("filled character")+" '"+QChar(static_cast<uint16_t>(pos-JKQTPFilledCharacterSymbol))+"'";
}
if (pos>=JKQTPFirstCustomSymbol) {
return QObject::tr("custom symbol %1").arg(static_cast<uint64_t>(pos-JKQTPFirstCustomSymbol));
}
return "";
}
JKQTPGraphSymbols String2JKQTPGraphSymbols(const QString& pos) {
@ -279,6 +288,9 @@ JKQTPGraphSymbols String2JKQTPGraphSymbols(const QString& pos) {
if (posT.startsWith("symbol_filled_char")) {
return JKQTPFilledCharacterSymbol+posT.mid(18).toUInt(nullptr,16);
}
if (posT.startsWith("symbol_custom")) {
return JKQTPFirstCustomSymbol+posT.mid(13).toUInt();
}
return JKQTPNoSymbol;
}
@ -538,3 +550,18 @@ QList<QPolygonF> JKQTPSimplifyPolyLines(const QList<QPolygonF> &lines_in, double
}
return l;
}
QVector<JKQTPCustomGraphSymbolFunctor> JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore=QVector<JKQTPCustomGraphSymbolFunctor>();
JKQTPGraphSymbols JKQTPRegisterCustomGraphSymbol(JKQTPCustomGraphSymbolFunctor&& f)
{
JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore.emplace_back(std::move(f));
return JKQTPFirstCustomSymbol+(JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore.size()-1);
}
JKQTPGraphSymbols JKQTPRegisterCustomGraphSymbol(const JKQTPCustomGraphSymbolFunctor& f)
{
JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore.emplace_back(f);
return JKQTPFirstCustomSymbol+(JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore.size()-1);
}

View File

@ -38,6 +38,7 @@
#include <cmath>
#include <utility>
#include <QDebug>
#include <QVector>
#include <QGuiApplication>
#include "jkqtcommon/jkqtpmathtools.h"
#include "jkqtcommon/jkqtpcodestructuring.h"
@ -46,6 +47,31 @@ class JKQTPEnhancedPainter; // forward
/** \brief functor used to draw a custom JKQTPGraphSymbols
* \ingroup jkqtptools_drawing
*
* Draw the symbol with these properties:
* - center at (0,0)
* - width 1, i.e. x=-0.5...0.5
* - height 1, i.e. y=-0.5...0.5
* - you can assume that a proper pen and brush is set with the correct properties
* - scaling to the final size is donw by JKQTPPlotSymbol()
* - drawing is protected by surronding \c p.save(); and \c p.restore(); in JKQTPPlotSymbol()
* .
*
* As an example, the following code-snippet:
* \code
* [](QPainter& p) {
* p.drawEllipse(QPointF(-0.2, -0.2), 0.3, 0.3);
* p.setBrush(Qt::NoBrush);
* p.drawEllipse(QPointF(0.2, -0.2), 0.3, 0.3);
* p.drawEllipse(QPointF(0, 0.2), 0.3, 0.3);
* };
* \endcode
* generates this symbol: \image html symbols/symbol_custom.png
*/
typedef std::function<void(QPainter& p)> JKQTPCustomGraphSymbolFunctor;
/*! \brief tool class with static values used by JKQTPlotter/JKQTBasePlotter
\ingroup jkqtptools_drawing
*/
@ -53,6 +79,11 @@ struct JKQTPlotterDrawingTools {
/** \brief smallest linewidth any line in JKQTPlotter/JKQTBasePlotter may have
*/
static JKQTCOMMON_LIB_EXPORT const double ABS_MIN_LINEWIDTH;
/** \brief stores all custom JKQTPGraphSymbols registered using JKQTPRegisterCustomGraphSymbol
* \ingroup jkqtptools_drawing
* \internal
*/
static JKQTCOMMON_LIB_EXPORT QVector<JKQTPCustomGraphSymbolFunctor> JKQTPCustomGraphSymbolStore;
};
@ -145,6 +176,8 @@ enum JKQTPGraphSymbols: uint64_t {
\image html symbols/symbol_filled_char_at.png "generated by JKQTPFilledCharacterSymbol+QChar('@').unicode()"
\image html symbols/symbol_filled_char_club.png "generated by JKQTPFilledCharacterSymbol+QChar(0x2663).unicode()"
*/
JKQTPFirstCustomSymbol=JKQTPFilledCharacterSymbol+0xFFFF+0xF, /*!< \brief draw a completely custom symbol, defined by supplying a functor to JKQTPRegisterCustomGraphSymbol()
\image html symbols/symbol_custom.png "generated by <code>[](QPainter& p) { p.drawEllipse(QPointF(-0.2, -0.2), 0.3, 0.3); p.setBrush(Qt::NoBrush); p.drawEllipse(QPointF(0.2, -0.2), 0.3, 0.3); p.drawEllipse(QPointF(0, 0.2), 0.3, 0.3); };</code>" */
};
inline JKQTPGraphSymbols operator+(JKQTPGraphSymbols a, uint8_t b) {
@ -179,6 +212,25 @@ inline JKQTPGraphSymbols operator+(JKQTPGraphSymbols a, int64_t b) {
return static_cast<JKQTPGraphSymbols>(static_cast<uint64_t>(a)+b);
}
/** \brief register a JKQTPCustomGraphSymbolFunctor that draws a custom symbol.Returns an ID that allows to access the symbol!
* \ingroup jkqtptools_drawing
*
* The functor is stored in the global/static store JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore, i.e. these are available throughout the runtime of the program
*
* \see JKQTPCustomGraphSymbolFunctor for an example
*/
JKQTCOMMON_LIB_EXPORT JKQTPGraphSymbols JKQTPRegisterCustomGraphSymbol(JKQTPCustomGraphSymbolFunctor&&);
/** \brief register a JKQTPCustomGraphSymbolFunctor that draws a custom symbol.Returns an ID that allows to access the symbol!
* \ingroup jkqtptools_drawing
*
* The functor is stored in the global/static store JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore, i.e. these are available throughout the runtime of the program
*
* \see JKQTPCustomGraphSymbolFunctor for an example
*/
JKQTCOMMON_LIB_EXPORT JKQTPGraphSymbols JKQTPRegisterCustomGraphSymbol(const JKQTPCustomGraphSymbolFunctor&);
/** \brief converts a JKQTPGraphSymbols variable into a identifier string
* \ingroup jkqtptools_drawing
*/
@ -193,6 +245,40 @@ JKQTCOMMON_LIB_EXPORT QString JKQTPGraphSymbols2NameString(JKQTPGraphSymbols pos
*/
JKQTCOMMON_LIB_EXPORT JKQTPGraphSymbols String2JKQTPGraphSymbols(const QString& pos);
/*! \brief plot the specified symbol at pixel position x,y
\ingroup jkqtptools_drawing
\tparam TPainter Type of \a painter: A class like JKQTPEnhancedPainter or <a href="http://doc.qt.io/qt-5/qpainter.html">QPainter</a>
\param painter the <a href="http://doc.qt.io/qt-5/qpainter.html">QPainter</a> to draw to
\param x x-coordinate of the symbol center
\param y y-coordinate of the symbol center
\param symbol type of the symbol to plot, see JKQTPGraphSymbols
\param size size (width/height) of the symbol around (\a x , \a y)
\param symbolLineWidth width of the lines used to draw the symbol
\param color color of the symbol lines
\param fillColor color of the symbol filling
\param symbolFont font used to draw symbols like \c JKQTPCharacterSymbol+QChar('@').unicode()
*/
template <class TPainter>
inline void JKQTPPlotSymbol(TPainter& painter, double x, double y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor, QFont symbolFont);
/*! \brief plot the specified symbol at pixel position x,y
\ingroup jkqtptools_drawing
\param paintDevice the paint device to draw on
\param x x-coordinate of the symbol center
\param y y-coordinate of the symbol center
\param symbol type of the symbol to plot, see JKQTPGraphSymbols
\param size size (width/height) of the symbol around (\a x , \a y)
\param symbolLineWidth width of the lines used to draw the symbol
\param color color of the symbol lines
\param fillColor color of the symbol filling
\param symbolFont font used to draw symbols like \c JKQTPCharacterSymbol+QChar('@').unicode()
*/
JKQTCOMMON_LIB_EXPORT void JKQTPPlotSymbol(QPaintDevice& paintDevice, double x, double y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor, const QFont &symbolFont);
@ -286,40 +372,6 @@ inline void JKQTPPlotDecoratedLine(TPainter& painter, const QLineF& l, JKQTPLine
/** \brief calculates the tail decorator size from the line width \a line_width, using decoratorSizeFactor and a non-linear scaling function that levels off towards small \a line_width and increases sub-linearly for large ones, so the arrow heads to not grow too much */
JKQTCOMMON_LIB_EXPORT double JKQTPLineDecoratorStyleCalcDecoratorSize(double line_width, double decoratorSizeFactor);
/*! \brief plot the specified symbol at pixel position x,y
\ingroup jkqtptools_drawing
\tparam TPainter Type of \a painter: A class like JKQTPEnhancedPainter or <a href="http://doc.qt.io/qt-5/qpainter.html">QPainter</a>
\param painter the <a href="http://doc.qt.io/qt-5/qpainter.html">QPainter</a> to draw to
\param x x-coordinate of the symbol center
\param y y-coordinate of the symbol center
\param symbol type of the symbol to plot, see JKQTPGraphSymbols
\param size size (width/height) of the symbol around (\a x , \a y)
\param symbolLineWidth width of the lines used to draw the symbol
\param color color of the symbol lines
\param fillColor color of the symbol filling
\param symbolFont font used to draw symbols like \c JKQTPCharacterSymbol+QChar('@').unicode()
*/
template <class TPainter>
inline void JKQTPPlotSymbol(TPainter& painter, double x, double y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor, QFont symbolFont);
/*! \brief plot the specified symbol at pixel position x,y
\ingroup jkqtptools_drawing
\param paintDevice the paint device to draw on
\param x x-coordinate of the symbol center
\param y y-coordinate of the symbol center
\param symbol type of the symbol to plot, see JKQTPGraphSymbols
\param size size (width/height) of the symbol around (\a x , \a y)
\param symbolLineWidth width of the lines used to draw the symbol
\param color color of the symbol lines
\param fillColor color of the symbol filling
\param symbolFont font used to draw symbols like \c JKQTPCharacterSymbol+QChar('@').unicode()
*/
JKQTCOMMON_LIB_EXPORT void JKQTPPlotSymbol(QPaintDevice& paintDevice, double x, double y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor, const QFont &symbolFont);
@ -873,6 +925,7 @@ inline void JKQTPPlotSymbol(TPainter& painter, double x, double y, JKQTPGraphSym
case JKQTPSymbolCount:
case JKQTPCharacterSymbol:
case JKQTPFilledCharacterSymbol:
case JKQTPFirstCustomSymbol:
break;
}
if (symbol>=JKQTPCharacterSymbol && symbol<=JKQTPCharacterSymbol+0xFFFF) {
@ -913,6 +966,17 @@ inline void JKQTPPlotSymbol(TPainter& painter, double x, double y, JKQTPGraphSym
path.addText(0,0,symbolFont, ch),
painter.drawPath(path);
}
if (symbol>=JKQTPFirstCustomSymbol) {
const int idx(static_cast<int>(symbol-JKQTPFirstCustomSymbol));
if (idx>=0 && idx<JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore.size()) {
painter.setPen(p);
painter.translate(QPointF(x,y));
painter.scale(symbolSize,symbolSize);
painter.setBrush(b);
painter.setPen(pDescaled);
JKQTPlotterDrawingTools::JKQTPCustomGraphSymbolStore[idx].operator()(painter);
}
}
}
template <class TPainter>

View File

@ -105,6 +105,18 @@ int main(int argc, char* argv[])
p.setPen(QPen(QColor("green"),0.5));
//p.drawRect(2,2,iconsize-4,iconsize-4);
stopPaintingAndSave(img, p, outputDir.absoluteFilePath("symbol_filled_char_club.png"));
JKQTPCustomGraphSymbolFunctor f=[](QPainter& p) {
p.drawEllipse(QPointF(-0.2, -0.2), 0.3, 0.3);
p.setBrush(Qt::NoBrush);
p.drawEllipse(QPointF(0.2, -0.2), 0.3, 0.3);
p.drawEllipse(QPointF(0, 0.2), 0.3, 0.3);
};
JKQTPGraphSymbols customs=JKQTPRegisterCustomGraphSymbol(f);
startPainting(img, p, iconsize, backgroundColor);
JKQTPPlotSymbol(p, iconsize/2,iconsize/2,customs,iconsize-4,2,QColor("blue"), QColor("salmon").lighter(120),QGuiApplication::font().family());
p.setPen(QPen(QColor("green"),0.5));
stopPaintingAndSave(img, p, outputDir.absoluteFilePath("symbol_custom.png"));
}
if (listlinedecorators) {