JKQTPlotter: added examples for custom symbols
@ -122,6 +122,7 @@ if(JKQtPlotter_BUILD_EXAMPLES)
|
||||
# the basenames are applied to the windows in the order of their windowTitle()s!
|
||||
set(JKQTPlotter_GenerateDocScreenshots_From
|
||||
scatter/scatter,scatter_error
|
||||
scatter_customsymbol
|
||||
simpletest
|
||||
barchart/barchart,barchart_hor
|
||||
wiggleplots/wiggleplot_x,wiggleplot_y
|
||||
@ -151,6 +152,7 @@ if(JKQtPlotter_BUILD_EXAMPLES)
|
||||
impulsesplot
|
||||
parametriccurve/parametriccurve1,parametriccurve2
|
||||
paramscatterplot
|
||||
paramscatterplot_customsymbol
|
||||
#paramscatterplot_image
|
||||
parsedfunctionplot
|
||||
rgbimageplot
|
||||
|
@ -19,6 +19,9 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
|
||||
<tr><td> \image html scatter_small.png
|
||||
<td> \subpage JKQTPlotterscatter
|
||||
<td> `JKQTPXYScatterGraph` <br> Iterator-Interface for JKQTDatastore
|
||||
<tr><td> \image html scatter_customsymbol_small.png
|
||||
<td> \subpage JKQTPlotterscatterCustomSymbol
|
||||
<td> `JKQTPXYScatterGraph` <br>custom symbols JKQTPCharacterSymbol, JKQTPFilledCharacterSymbol, JKQTPRegisterCustomGraphSymbol()<br> Iterator-Interface for JKQTDatastore
|
||||
<tr><td> \image html speed_small.png
|
||||
<td> \subpage JKQTPlotterSpeedTest
|
||||
<td> `JKQTPXYLineGraph` <br> external `std::array<double,N>` data, not owned by datastore <br> live-data, measure plotting speed <br> tipps to increas plotting speed
|
||||
@ -49,9 +52,12 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
|
||||
<tr><td> \image html impulsesplot_small.png
|
||||
<td> \subpage JKQTPlotterImpulsePlots
|
||||
<td> `JKQTPImpulsesVerticalGraph` and `JKQTPImpulsesHorizontalGraph` <br> C++-style QVector as plot data
|
||||
<tr><td> \image html paramscatterplot_small.png
|
||||
<td> \subpage JKQTPlotterParamScatter
|
||||
<tr><td> \image html paramscatterplot_small.png
|
||||
<td> \subpage JKQTPlotterParamScatter
|
||||
<td> `JKQTPXYParametrizedScatterGraph` <br> C++-style QVector as plot data <br> modify scatter/points/line-graph properties by data
|
||||
<tr><td> \image html paramscatterplot_customsymbol_small.png
|
||||
<td> \subpage JKQTPlotterparamscatterCustomSymbol
|
||||
<td> `JKQTPXYParametrizedScatterGraph` <br>custom and varying symbols using JKQTPRegisterCustomGraphSymbol()<br>iterator interface to `JKQTPDatastore`
|
||||
<tr><td> \image html paramscatterplot_image_small.png
|
||||
<td> \subpage JKQTPlotterParamScatterImage
|
||||
<td> `JKQTPXYParametrizedScatterGraph` <br> C++-style QVector as plot data <br> rectangular arrangement of scatters <br> generative computer graphics
|
||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.8 KiB |
@ -77,12 +77,14 @@ add_subdirectory(multiplot)
|
||||
add_subdirectory(parametriccurve)
|
||||
add_subdirectory(paramscatterplot)
|
||||
add_subdirectory(paramscatterplot_image)
|
||||
add_subdirectory(paramscatterplot_customsymbol)
|
||||
add_subdirectory(parsedfunctionplot)
|
||||
add_subdirectory(rgbimageplot)
|
||||
add_subdirectory(rgbimageplot_cimg)
|
||||
add_subdirectory(rgbimageplot_opencv)
|
||||
add_subdirectory(rgbimageplot_qt)
|
||||
add_subdirectory(scatter)
|
||||
add_subdirectory(scatter_customsymbol)
|
||||
add_subdirectory(speed)
|
||||
add_subdirectory(stackedbars)
|
||||
add_subdirectory(stepplots)
|
||||
|
33
examples/paramscatterplot_customsymbol/CMakeLists.txt
Normal file
@ -0,0 +1,33 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
set(EXAMPLE_NAME paramscatterplot_customsymbol)
|
||||
set(EXENAME jkqtptest_${EXAMPLE_NAME})
|
||||
|
||||
message( STATUS ".. Building Example ${EXAMPLE_NAME}" )
|
||||
|
||||
|
||||
# Set up source files
|
||||
set(SOURCES paramscatterplot_customsymbol.cpp )
|
||||
set(HEADERS )
|
||||
set(RESOURCES )
|
||||
set(UIS )
|
||||
|
||||
add_executable(${EXENAME} WIN32 ${SOURCES} ${HEADERS} ${RESOURCES} ${UIS})
|
||||
target_link_libraries(${EXENAME} JKQTPExampleToolsLib)
|
||||
target_include_directories(${EXENAME} PRIVATE ../../lib)
|
||||
if(JKQtPlotter_BUILD_STATIC_LIBS)
|
||||
target_link_libraries(${EXENAME} JKQTPlotterLib)
|
||||
|
||||
elseif(JKQtPlotter_BUILD_SHARED_LIBS)
|
||||
target_link_libraries(${EXENAME} JKQTPlotterSharedLib)
|
||||
endif()
|
||||
|
||||
# precomiled headers to speed up compilation
|
||||
target_precompile_headers(${EXENAME} PRIVATE ../../lib/jkqtplotter/private/jkqtplotter_precomp.h)
|
||||
|
||||
|
||||
# Installation
|
||||
install(TARGETS ${EXENAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
||||
#Installation of Qt DLLs on Windows
|
||||
jkqtplotter_deployqt(${EXENAME})
|
69
examples/paramscatterplot_customsymbol/README.md
Normal file
@ -0,0 +1,69 @@
|
||||
# Example (JKQTPlotter): Parametrized Scatter-graph with custom symbols {#JKQTPlotterparamscatterCustomSymbol}
|
||||
|
||||
This project (see `./examples/paramscatterplot_customsymbol/`) demonstrates using JKQTPlotter to draw a parametrized scatter graph (JKQTPXYParametrizedScatterGraph) with custom symbols. To demonstrate this, we create a plot with several symbols, connected by a line, where each symbol shows a pie-chart with varying fractions.
|
||||
|
||||
The source code of the example can be found in [`paramscatterplot_customsymbol.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/paramscatterplot_customsymbol/paramscatterplot_customsymbol.cpp).
|
||||
|
||||
First we create a plotter window and get a pointer to the internal datastore (for convenience). Then we add three new datacolumns and obtain back inserters.
|
||||
```.cpp
|
||||
JKQTPlotter plot;
|
||||
JKQTPDatastore* ds=plot.getDatastore();
|
||||
|
||||
size_t columnX=ds->addColumn("x");
|
||||
auto colXInserter=ds->backInserter(columnX);
|
||||
size_t columnY=ds->addColumn("y");
|
||||
auto colYInserter=ds->backInserter(columnY);
|
||||
size_t columnS=ds->addColumn("sym");
|
||||
auto colSInserter=ds->backInserter(columnS);
|
||||
```
|
||||
Now we define a functor that draws a pie chart with three segments with fractions `f1` (blue), `f2` (green) and `1.0-f1-f2` (yellow):
|
||||
```.cpp
|
||||
auto pieFunc=[](QPainter& p, double f1, double f2) {
|
||||
double f3=1.0-f1-f2;
|
||||
QRectF rec(-0.5,-0.5,1,1);
|
||||
p.setPen(QPen(QColor("black"), p.pen().width(), Qt::SolidLine));
|
||||
p.setBrush(QBrush(QColor("blue")));
|
||||
p.drawPie(rec, 90, -f1*360*16);
|
||||
p.setBrush(QBrush(QColor("green")));
|
||||
p.drawPie(rec, 90-f1*360*16, -f2*360*16);
|
||||
p.setBrush(QBrush(QColor("yellow")));
|
||||
p.drawPie(rec, 90-(f1+f2)*360*16, -f3*360*16);
|
||||
};
|
||||
```
|
||||
Now we create data for the plot, x and y follow a simple function and the symbols are encoded in a separated column, where for each datapoint, we register a new symbol using JKQTPRegisterCustomGraphSymbol(), which is drawn by a differently parametrized (f1,f2) functor pieFunc.
|
||||
```.cpp
|
||||
const int Ndata=5;
|
||||
for (int i=0; i<Ndata; i++) {
|
||||
// put data
|
||||
const double x=double(i)/double(Ndata-1);
|
||||
*(colXInserter++)=x;
|
||||
*(colYInserter++)=pow(x*1.3, 2.0);
|
||||
*(colSInserter++)=JKQTPRegisterCustomGraphSymbol(std::bind(pieFunc, std::placeholders::_1, x*0.4, 0.5-x*0.2));
|
||||
}
|
||||
```
|
||||
Finally we create a graph in the plot, which displays our datasets:
|
||||
```.cpp
|
||||
JKQTPXYParametrizedScatterGraph* graph1=new JKQTPXYParametrizedScatterGraph(&plot);
|
||||
graph1->setXColumn(columnX);
|
||||
graph1->setYColumn(columnY);
|
||||
graph1->setSymbolSize(25);
|
||||
graph1->setDrawLine(true);
|
||||
graph1->setLineWidth(4);
|
||||
graph1->setDrawLineInForeground(false);
|
||||
graph1->setColor(QColor("black"));
|
||||
graph1->setTitle(QObject::tr("pie scatter"));
|
||||
```
|
||||
The symbol type is stored in columnS, note however how we have to give a custom JKQTPXYParametrizedScatterGraph::symbolColumnFunctor, because the default one maps the values in the column to the range `[0...JKQTPMaxSymbolID]` in a cycling fashion (using a mod operation), but here we want to use the `stored ID directly.
|
||||
```.cpp
|
||||
graph1->setSymbolColumn(columnS);
|
||||
graph1->setSymbolColumnFunctor(std::bind([](double /*x*/, double /*y*/, double symbolcolumn)->JKQTPGraphSymbols {
|
||||
return static_cast<JKQTPGraphSymbols>(floor(symbolcolumn));
|
||||
}, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
plot.addGraph(graph1);
|
||||
```
|
||||
The result looks like this:
|
||||
|
||||
![paramscatterplot_customsymbol](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/paramscatterplot_customsymbol.png)
|
||||
|
||||
|
||||
|
@ -0,0 +1,96 @@
|
||||
/** \example scatter_customsymbol.cpp
|
||||
* Usage of JKQTPScatterGraph with custom symbols
|
||||
*
|
||||
* \ref JKQTPlotterscatterCustomSymbol
|
||||
*/
|
||||
|
||||
#include "jkqtpexampleapplication.h"
|
||||
#include <QApplication>
|
||||
#include "jkqtplotter/jkqtplotter.h"
|
||||
#include "jkqtplotter/graphs/jkqtpscatter.h"
|
||||
#include "jkqtpexampleapplication.h"
|
||||
#include <random>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
JKQTPAppSettingController highDPIController(argc,argv);
|
||||
JKQTPExampleApplication app(argc, argv);
|
||||
|
||||
|
||||
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
|
||||
JKQTPlotter plot;
|
||||
JKQTPDatastore* ds=plot.getDatastore();
|
||||
|
||||
// 2. add three columns to the JKQTPDatastore and obtain back-inserter iterators for these
|
||||
size_t columnX=ds->addColumn("x");
|
||||
auto colXInserter=ds->backInserter(columnX);
|
||||
size_t columnY=ds->addColumn("y");
|
||||
auto colYInserter=ds->backInserter(columnY);
|
||||
size_t columnS=ds->addColumn("sym");
|
||||
auto colSInserter=ds->backInserter(columnS);
|
||||
|
||||
// 3. now we define a functor that draws a pie chart with three segments with fractions
|
||||
// f1 (blue), f2 (green) and 1-f1-f2 (yellow)
|
||||
auto pieFunc=[](QPainter& p, double f1, double f2) {
|
||||
double f3=1.0-f1-f2;
|
||||
QRectF rec(-0.5,-0.5,1,1);
|
||||
p.setPen(QPen(QColor("black"), p.pen().width(), Qt::SolidLine));
|
||||
p.setBrush(QBrush(QColor("blue")));
|
||||
p.drawPie(rec, 90, -f1*360*16);
|
||||
p.setBrush(QBrush(QColor("green")));
|
||||
p.drawPie(rec, 90-f1*360*16, -f2*360*16);
|
||||
p.setBrush(QBrush(QColor("yellow")));
|
||||
p.drawPie(rec, 90-(f1+f2)*360*16, -f3*360*16);
|
||||
};
|
||||
// 4. now we create data for the plot, x and y follow a simple function
|
||||
// and the symbols are encoded in a separated column, where for each datapoint, we
|
||||
// register a new symbol using JKQTPRegisterCustomGraphSymbol(), which is drawn by
|
||||
// a differently parametrized (f1,f2) functor pieFunc.
|
||||
const int Ndata=5;
|
||||
for (int i=0; i<Ndata; i++) {
|
||||
// put data
|
||||
const double x=double(i)/double(Ndata-1);
|
||||
*(colXInserter++)=x;
|
||||
*(colYInserter++)=pow(x*1.3, 2.0);
|
||||
*(colSInserter++)=JKQTPRegisterCustomGraphSymbol(std::bind(pieFunc, std::placeholders::_1, x*0.4, 0.5-x*0.2));
|
||||
}
|
||||
|
||||
|
||||
// 5. Finally we create a graph in the plot, which displays our datasets:
|
||||
JKQTPXYParametrizedScatterGraph* graph1=new JKQTPXYParametrizedScatterGraph(&plot);
|
||||
graph1->setXColumn(columnX);
|
||||
graph1->setYColumn(columnY);
|
||||
graph1->setSymbolSize(25);
|
||||
graph1->setDrawLine(true);
|
||||
graph1->setLineWidth(4);
|
||||
graph1->setDrawLineInForeground(false);
|
||||
graph1->setColor(QColor("black"));
|
||||
graph1->setTitle(QObject::tr("pie scatter"));
|
||||
// the symbol type is stored in columnS, note however how we have to give a
|
||||
// custom JKQTPXYParametrizedScatterGraph::symbolColumnFunctor, because the
|
||||
// default one maps the values in the column to the range [0...JKQTPMaxSymbolID]
|
||||
// in a cycling fashion (using a mod operation), but here we want to use the
|
||||
// stored ID directly.
|
||||
graph1->setSymbolColumn(columnS);
|
||||
graph1->setSymbolColumnFunctor(std::bind([](double /*x*/, double /*y*/, double symbolcolumn)->JKQTPGraphSymbols {
|
||||
return static_cast<JKQTPGraphSymbols>(floor(symbolcolumn));
|
||||
}, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||
plot.addGraph(graph1);
|
||||
|
||||
|
||||
// 6. autoscale the plot so the graph is contained
|
||||
plot.setXY(-0.2,1.2,-0.4,2.2);
|
||||
|
||||
// show plotter and make it a decent size
|
||||
plot.getXAxis()->setShowZeroAxis(false);
|
||||
plot.getYAxis()->setShowZeroAxis(false);
|
||||
plot.setGrid(false);
|
||||
plot.getPlotter()->setKeyPosition(JKQTPKeyInsideTopLeft);
|
||||
plot.getPlotter()->setPlotLabel(QObject::tr("Custom Parametrized Scatter Symbols Example"));
|
||||
plot.show();
|
||||
plot.resize(500/plot.devicePixelRatioF(),400/plot.devicePixelRatioF());
|
||||
|
||||
|
||||
return app.exec();
|
||||
}
|
33
examples/scatter_customsymbol/CMakeLists.txt
Normal file
@ -0,0 +1,33 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
set(EXAMPLE_NAME scatter_customsymbol)
|
||||
set(EXENAME jkqtptest_${EXAMPLE_NAME})
|
||||
|
||||
message( STATUS ".. Building Example ${EXAMPLE_NAME}" )
|
||||
|
||||
|
||||
# Set up source files
|
||||
set(SOURCES scatter_customsymbol.cpp )
|
||||
set(HEADERS )
|
||||
set(RESOURCES )
|
||||
set(UIS )
|
||||
|
||||
add_executable(${EXENAME} WIN32 ${SOURCES} ${HEADERS} ${RESOURCES} ${UIS})
|
||||
target_link_libraries(${EXENAME} JKQTPExampleToolsLib)
|
||||
target_include_directories(${EXENAME} PRIVATE ../../lib)
|
||||
if(JKQtPlotter_BUILD_STATIC_LIBS)
|
||||
target_link_libraries(${EXENAME} JKQTPlotterLib)
|
||||
|
||||
elseif(JKQtPlotter_BUILD_SHARED_LIBS)
|
||||
target_link_libraries(${EXENAME} JKQTPlotterSharedLib)
|
||||
endif()
|
||||
|
||||
# precomiled headers to speed up compilation
|
||||
target_precompile_headers(${EXENAME} PRIVATE ../../lib/jkqtplotter/private/jkqtplotter_precomp.h)
|
||||
|
||||
|
||||
# Installation
|
||||
install(TARGETS ${EXENAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
||||
#Installation of Qt DLLs on Windows
|
||||
jkqtplotter_deployqt(${EXENAME})
|
113
examples/scatter_customsymbol/README.md
Normal file
@ -0,0 +1,113 @@
|
||||
# Example (JKQTPlotter): Scatter-graph with custom symbols {#JKQTPlotterscatterCustomSymbol}
|
||||
|
||||
This project (see `./examples/scatter_customsymbol/`) demonstrates using JKQTPlotter to draw a scatter graph (JKQTPXYScatterGraph) with custom symbols.
|
||||
|
||||
The source code of the example can be found in [`jkqtplotter_scatter.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/scatter_customsymbol/scatter_customsymbol.cpp).
|
||||
|
||||
First we create a plotter window and get a pointer to the internal datastore (for convenience):
|
||||
```.cpp
|
||||
JKQTPlotter plot;
|
||||
JKQTPDatastore* ds=plot.getDatastore();
|
||||
```
|
||||
Now we add several columns to the JKQTPDatastore and obtain back-inserter iterators for these:
|
||||
```.cpp
|
||||
size_t columnX=ds->addColumn("x");
|
||||
auto colXInserter=ds->backInserter(columnX);
|
||||
size_t columnY1=ds->addColumn("y1");
|
||||
auto colY1Inserter=ds->backInserter(columnY1);
|
||||
size_t columnY2=ds->addColumn("y2");
|
||||
auto colY2Inserter=ds->backInserter(columnY2);
|
||||
size_t columnY3=ds->addColumn("y3");
|
||||
auto colY3Inserter=ds->backInserter(columnY3);
|
||||
size_t columnY4=ds->addColumn("y4");
|
||||
auto colY4Inserter=ds->backInserter(columnY4);
|
||||
```
|
||||
... and fill the columns with data
|
||||
```.cpp
|
||||
const int Ndata=5;
|
||||
for (int i=0; i<Ndata; i++) {
|
||||
// put data
|
||||
const double x=double(i)/double(Ndata-1);
|
||||
*(colXInserter++)=x;
|
||||
*(colY1Inserter++)=3.0+pow(x*1.3, 2.0)*1.3;
|
||||
*(colY2Inserter++)=2.0+pow(x*1.3, 2.0)*1.2;
|
||||
*(colY3Inserter++)=1.0+pow(x*1.3, 2.0)*1.1;
|
||||
*(colY4Inserter++)=pow(x*1.3, 2.0);
|
||||
}
|
||||
```
|
||||
Now we create several graph objects of type JKQTPXYScatterGraph. Each one uses a different custom symbol style:
|
||||
|
||||
Graphs `graph3` and `graph4` use `JKQTPCharacterSymbol` and `JKQTPFilledCharacterSymbol` respectively to draw spades and hearts from the unicode characters `U+2660` and `U+2665` respectively. The two graphs differ in the coloring of the symbols. The `JKQTPCharacterSymbol` variant would use the color default (cycling) graph color, but here we overwrite this with `darkblue`. The `JKQTPFilledCharacterSymbol` variant uses red filled hearts with a thin black border.
|
||||
```.cpp
|
||||
JKQTPXYScatterGraph* graph3=new JKQTPXYScatterGraph(&plot);
|
||||
graph3->setXColumn(columnX);
|
||||
graph3->setYColumn(columnY3);
|
||||
graph3->setSymbolType(JKQTPCharacterSymbol+QChar(0x2660).unicode());
|
||||
graph3->setSymbolColor(QColor("darkblue"));
|
||||
graph3->setSymbolSize(15);
|
||||
graph3->setTitle(QObject::tr("spades"));
|
||||
plot.addGraph(graph3);
|
||||
|
||||
JKQTPXYScatterGraph* graph4=new JKQTPXYScatterGraph(&plot);
|
||||
graph4->setXColumn(columnX);
|
||||
graph4->setYColumn(columnY4);
|
||||
graph4->setSymbolType(JKQTPFilledCharacterSymbol+QChar(0x2665).unicode());
|
||||
graph4->setSymbolSize(20);
|
||||
graph4->setSymbolColor(QColor("black"));
|
||||
graph4->setSymbolFillColor(QColor("red"));
|
||||
graph4->setSymbolLineWidth(0.5);
|
||||
graph4->setTitle(QObject::tr("hearts"));
|
||||
plot.addGraph(graph4);
|
||||
```
|
||||
|
||||
The more advanced graphs `graph1` and `graph2` use `JKQTPRegisterCustomGraphSymbol()` to register functors that draw user-specific symbols:
|
||||
```.cpp
|
||||
JKQTPCustomGraphSymbolFunctor f=[](QPainter& p) {
|
||||
p.setBrush(Qt::NoBrush); // ensure that circles are not drawn filled
|
||||
p.drawEllipse(QPointF(-0.33, -0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
p.drawEllipse(QPointF(0, -0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
p.drawEllipse(QPointF(0.33, -0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
p.drawEllipse(QPointF(-0.33/2.0, 0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
p.drawEllipse(QPointF(0.33/2.0, 0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
};
|
||||
JKQTPGraphSymbols customsymbol_olympicrings=JKQTPRegisterCustomGraphSymbol(f);
|
||||
JKQTPXYScatterGraph* graph1=new JKQTPXYScatterGraph(&plot);
|
||||
graph1->setXColumn(columnX);
|
||||
graph1->setYColumn(columnY1);
|
||||
graph1->setSymbolType(customsymbol_olympicrings);
|
||||
graph1->setSymbolSize(30);
|
||||
graph1->setTitle(QObject::tr("olympics"));
|
||||
plot.addGraph(graph1);
|
||||
|
||||
|
||||
JKQTPGraphSymbols customsymbol_coloredolympicrings=JKQTPRegisterCustomGraphSymbol(
|
||||
[](QPainter& p) {
|
||||
p.setBrush(Qt::NoBrush); // ensure that circles are not drawn filled
|
||||
const double w=p.pen().widthF();
|
||||
p.setPen(QPen(QColor("red"), w));
|
||||
p.drawEllipse(QPointF(-0.33, -0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
p.setPen(QPen(QColor("black"), w));
|
||||
p.drawEllipse(QPointF(0, -0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
p.setPen(QPen(QColor("gold"), w));
|
||||
p.drawEllipse(QPointF(0.33, -0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
p.setPen(QPen(QColor("darkgreen"), w));
|
||||
p.drawEllipse(QPointF(-0.33/2.0, 0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
p.setPen(QPen(QColor("darkblue"), w));
|
||||
p.drawEllipse(QPointF(0.33/2.0, 0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
});
|
||||
JKQTPXYScatterGraph* graph2=new JKQTPXYScatterGraph(&plot);
|
||||
graph2->setXColumn(columnX);
|
||||
graph2->setYColumn(columnY2);
|
||||
graph2->setSymbolType(customsymbol_coloredolympicrings);
|
||||
graph2->setSymbolSize(30);
|
||||
graph2->setTitle(QObject::tr("colored olympics"));
|
||||
plot.addGraph(graph2);
|
||||
```
|
||||
Bothe variant show the olympic rings. `graph1` uses the (cycling) default graph color and `graph2` draws with user-defined colors.
|
||||
|
||||
The result looks like this:
|
||||
|
||||
![scatter_customsymbol](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/scatter_customsymbol.png)
|
||||
|
||||
|
||||
|
127
examples/scatter_customsymbol/scatter_customsymbol.cpp
Normal file
@ -0,0 +1,127 @@
|
||||
/** \example scatter_customsymbol.cpp
|
||||
* Usage of JKQTPScatterGraph with custom symbols
|
||||
*
|
||||
* \ref JKQTPlotterscatterCustomSymbol
|
||||
*/
|
||||
|
||||
#include "jkqtpexampleapplication.h"
|
||||
#include <QApplication>
|
||||
#include "jkqtplotter/jkqtplotter.h"
|
||||
#include "jkqtplotter/graphs/jkqtpscatter.h"
|
||||
#include "jkqtpexampleapplication.h"
|
||||
#include <random>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
JKQTPAppSettingController highDPIController(argc,argv);
|
||||
JKQTPExampleApplication app(argc, argv);
|
||||
|
||||
|
||||
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
|
||||
JKQTPlotter plot;
|
||||
JKQTPDatastore* ds=plot.getDatastore();
|
||||
|
||||
// 2. add two columns to the JKQTPDatastore and obtain back-inserter iterators for these
|
||||
size_t columnX=ds->addColumn("x");
|
||||
auto colXInserter=ds->backInserter(columnX);
|
||||
size_t columnY1=ds->addColumn("y1");
|
||||
auto colY1Inserter=ds->backInserter(columnY1);
|
||||
size_t columnY2=ds->addColumn("y2");
|
||||
auto colY2Inserter=ds->backInserter(columnY2);
|
||||
size_t columnY3=ds->addColumn("y3");
|
||||
auto colY3Inserter=ds->backInserter(columnY3);
|
||||
size_t columnY4=ds->addColumn("y4");
|
||||
auto colY4Inserter=ds->backInserter(columnY4);
|
||||
|
||||
|
||||
// 3. now we create data for a simple plot (a sine curve with random noise)
|
||||
const int Ndata=5;
|
||||
for (int i=0; i<Ndata; i++) {
|
||||
// put data
|
||||
const double x=double(i)/double(Ndata-1);
|
||||
*(colXInserter++)=x;
|
||||
*(colY1Inserter++)=3.0+pow(x*1.3, 2.0)*1.3;
|
||||
*(colY2Inserter++)=2.0+pow(x*1.3, 2.0)*1.2;
|
||||
*(colY3Inserter++)=1.0+pow(x*1.3, 2.0)*1.1;
|
||||
*(colY4Inserter++)=pow(x*1.3, 2.0);
|
||||
}
|
||||
|
||||
// 4. define custom symbol
|
||||
JKQTPCustomGraphSymbolFunctor f=[](QPainter& p) {
|
||||
p.setBrush(Qt::NoBrush); // ensure that circles are not drawn filled
|
||||
p.drawEllipse(QPointF(-0.33, -0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
p.drawEllipse(QPointF(0, -0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
p.drawEllipse(QPointF(0.33, -0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
p.drawEllipse(QPointF(-0.33/2.0, 0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
p.drawEllipse(QPointF(0.33/2.0, 0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
};
|
||||
JKQTPGraphSymbols customsymbol_olympicrings=JKQTPRegisterCustomGraphSymbol(f);
|
||||
|
||||
JKQTPGraphSymbols customsymbol_coloredolympicrings=JKQTPRegisterCustomGraphSymbol(
|
||||
[](QPainter& p) {
|
||||
p.setBrush(Qt::NoBrush); // ensure that circles are not drawn filled
|
||||
const double w=p.pen().widthF();
|
||||
p.setPen(QPen(QColor("red"), w));
|
||||
p.drawEllipse(QPointF(-0.33, -0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
p.setPen(QPen(QColor("black"), w));
|
||||
p.drawEllipse(QPointF(0, -0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
p.setPen(QPen(QColor("gold"), w));
|
||||
p.drawEllipse(QPointF(0.33, -0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
p.setPen(QPen(QColor("darkgreen"), w));
|
||||
p.drawEllipse(QPointF(-0.33/2.0, 0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
p.setPen(QPen(QColor("darkblue"), w));
|
||||
p.drawEllipse(QPointF(0.33/2.0, 0.33/4.0), 0.33/2.0, 0.33/2.0);
|
||||
});
|
||||
|
||||
// 4. create graphs in the plot, which plots the datasets:
|
||||
JKQTPXYScatterGraph* graph1=new JKQTPXYScatterGraph(&plot);
|
||||
graph1->setXColumn(columnX);
|
||||
graph1->setYColumn(columnY1);
|
||||
graph1->setSymbolType(customsymbol_olympicrings);
|
||||
graph1->setSymbolSize(30);
|
||||
graph1->setTitle(QObject::tr("olympics"));
|
||||
plot.addGraph(graph1);
|
||||
|
||||
JKQTPXYScatterGraph* graph2=new JKQTPXYScatterGraph(&plot);
|
||||
graph2->setXColumn(columnX);
|
||||
graph2->setYColumn(columnY2);
|
||||
graph2->setSymbolType(customsymbol_coloredolympicrings);
|
||||
graph2->setSymbolSize(30);
|
||||
graph2->setTitle(QObject::tr("colored olympics"));
|
||||
plot.addGraph(graph2);
|
||||
|
||||
JKQTPXYScatterGraph* graph3=new JKQTPXYScatterGraph(&plot);
|
||||
graph3->setXColumn(columnX);
|
||||
graph3->setYColumn(columnY3);
|
||||
graph3->setSymbolType(JKQTPCharacterSymbol+QChar(0x2660).unicode());
|
||||
graph3->setSymbolColor(QColor("darkblue"));
|
||||
graph3->setSymbolSize(15);
|
||||
graph3->setTitle(QObject::tr("spades"));
|
||||
plot.addGraph(graph3);
|
||||
|
||||
JKQTPXYScatterGraph* graph4=new JKQTPXYScatterGraph(&plot);
|
||||
graph4->setXColumn(columnX);
|
||||
graph4->setYColumn(columnY4);
|
||||
graph4->setSymbolType(JKQTPFilledCharacterSymbol+QChar(0x2665).unicode());
|
||||
graph4->setSymbolSize(20);
|
||||
graph4->setSymbolColor(QColor("black"));
|
||||
graph4->setSymbolFillColor(QColor("red"));
|
||||
graph4->setSymbolLineWidth(0.5);
|
||||
graph4->setTitle(QObject::tr("hearts"));
|
||||
plot.addGraph(graph4);
|
||||
|
||||
// 6. autoscale the plot so the graph is contained
|
||||
plot.setXY(-0.1,1.1,-1, 6);
|
||||
|
||||
// show plotter and make it a decent size
|
||||
plot.getXAxis()->setShowZeroAxis(false);
|
||||
plot.getYAxis()->setShowZeroAxis(false);
|
||||
plot.setGrid(false);
|
||||
plot.getPlotter()->setKeyPosition(JKQTPKeyInsideTopLeft);
|
||||
plot.getPlotter()->setPlotLabel(QObject::tr("Custom Scatter Symbols Example"));
|
||||
plot.show();
|
||||
plot.resize(500/plot.devicePixelRatioF(),500/plot.devicePixelRatioF());
|
||||
|
||||
return app.exec();
|
||||
}
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 144 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 176 KiB After Width: | Height: | Size: 176 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.6 KiB |
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
BIN
screenshots/paramscatterplot_customsymbol.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
screenshots/paramscatterplot_customsymbol_small.png
Normal file
After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
BIN
screenshots/scatter_customsymbol.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
screenshots/scatter_customsymbol_small.png
Normal file
After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |