mirror of
https://github.com/jkriege2/JKQtPlotter.git
synced 2024-12-24 09:31:40 +08:00
implemented wiggle plots (feature request #68)
This commit is contained in:
parent
d45083ee9b
commit
ee2477a1f6
@ -35,9 +35,12 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
|
||||
<tr><td> \image html JKQTPBarHorizontalGraphStacked_small.png
|
||||
<td> \subpage JKQTPlotterStackedBarChart
|
||||
<td> `JKQTPBarVerticalStackableGraph`, `JKQTPBarHorizontalStackableGraph` <br> C++-style vectors of data
|
||||
<tr><td> \image html filledgraphs_small.png
|
||||
<td> \subpage JKQTPlotterFilledGraphs
|
||||
<td> `JKQTPBarVerticalGraph` <br> setting/altering data in `JKQTPDatstore` directly <br> transparent plots <br> calculating histograms
|
||||
<tr><td> \image html filledgraphs_small.png
|
||||
<td> \subpage JKQTPlotterFilledGraphs
|
||||
<td> `JKQTPFilledCurveXGraph`/`JKQTPFilledCurveYGraph` <br> setting/altering data in `JKQTPDatstore` directly <br> transparent plots <br> calculating histograms
|
||||
<tr><td> \image html wiggleplots_small.png
|
||||
<td> \subpage JKQTPlotterWigglePlots
|
||||
<td> `JKQTPFilledCurveXGraph`/`JKQTPFilledCurveYGraph` <br> setting/altering data in `JKQTPDatstore` directly <br> data-depentend coloring <br> random-walks <br> seismographic data
|
||||
<tr><td> \image html impulsesplot_small.png
|
||||
<td> \subpage JKQTPlotterImpulsePlots
|
||||
<td> `JKQTPImpulsesVerticalGraph` and `JKQTPImpulsesHorizontalGraph` <br> C++-style QVector as plot data
|
||||
|
@ -14,7 +14,7 @@ This page lists release notes for the diferent version of JKQTPlotter
|
||||
\subsection page_whatsnew_TRUNK_OVERVIEW trunk: Overview
|
||||
Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
|
||||
<ul>
|
||||
<li></li>
|
||||
<li>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>
|
||||
</ul>
|
||||
|
||||
\subsection page_whatsnew_TRUNK_DOWNLOAD trunk: Download
|
||||
|
@ -60,5 +60,5 @@ add_subdirectory(symbols_and_styles)
|
||||
add_subdirectory(ui)
|
||||
add_subdirectory(user_interaction)
|
||||
add_subdirectory(violinplot)
|
||||
|
||||
add_subdirectory(wiggleplots)
|
||||
|
||||
|
@ -15,7 +15,8 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
|
||||
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/errorbarstyles_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/errorbarstyles) | [Different Types of Error Indicators](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/errorbarstyles) | `JKQTPXYLineErrorGraph` <br> different styles of error indicators for x- and y-errors <br> C++-style QVector for data <br> styling error indicators <br> moving key and formatting plotter grid |
|
||||
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/barchart_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/barchart) | [Simple Bar Charts](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/barchart) | `JKQTPBarVerticalGraph` <br> C-style arrays of data |
|
||||
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/JKQTPbarHorizontalGraphStacked_small.png) <br> ![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/JKQTPbarVerticalGraphStacked_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/stackedbars) | [Stacked Bar Charts](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/stackedbars) | `JKQTPBarVerticalStackableGraph`, `JKQTPBarHorizontalStackableGraph` <br> C++-style vectors of data |
|
||||
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/filledgraphs_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/filledgraphs) | [Filled Curve Plots](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/filledgraphs) | `JKQTPBarVerticalGraph` <br> setting/altering data in `JKQTPDatstore` directly <br> transparent plots <br> calculating histograms |
|
||||
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/filledgraphs_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/filledgraphs) | [Filled Curve Plots](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/filledgraphs) | `JKQTPFilledCurveXGraph`/`JKQTPFilledCurveYGraph` <br> setting/altering data in `JKQTPDatstore` directly <br> transparent plots <br> calculating histograms |
|
||||
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/wiggleplots_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/wiggleplots) | [Wiggle Plots](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/wiggleplots) | `JKQTPFilledCurveXGraph`/`JKQTPFilledCurveYGraph` <br> setting/altering data in `JKQTPDatstore` directly <br> data-dependent coloring <br> random-walks <br> seismographic data |
|
||||
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/impulsesplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/impulsesplot) | [Impulse Plots](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/impulsesplot) | `JKQTPImpulsesVerticalGraph` and `JKQTPImpulsesHorizontalGraph` <br> C++-style QVector as plot data |
|
||||
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/paramscatterplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/paramscatterplot) | [Scatter Graph with Parametrized Symbols/Colors](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/paramscatterplot) | `JKQTPXYParametrizedScatterGraph` <br> C++-style QVector as plot data <br> modify scatter/points/line-graph properties by data |
|
||||
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/paramscatterplot_image_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/paramscatterplot_image) | [Draw an Artistic Image with a Parametrized Scatter Graph](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/paramscatterplot_image) | `JKQTPXYParametrizedScatterGraph` <br> C++-style QVector as plot data <br> rectangular arrangement of scatters <br> generative computer graphics |
|
||||
|
29
examples/wiggleplots/CMakeLists.txt
Normal file
29
examples/wiggleplots/CMakeLists.txt
Normal file
@ -0,0 +1,29 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
set(EXAMPLE_NAME wiggleplots)
|
||||
set(EXENAME jkqtptest_${EXAMPLE_NAME})
|
||||
|
||||
message( STATUS ".. Building Example ${EXAMPLE_NAME}" )
|
||||
|
||||
|
||||
# Set up source files
|
||||
set(SOURCES ${EXAMPLE_NAME}.cpp)
|
||||
set(HEADERS )
|
||||
set(RESOURCES )
|
||||
set(UIS )
|
||||
|
||||
add_executable(${EXENAME} WIN32 ${SOURCES} ${HEADERS} ${RESOURCES} ${UIS})
|
||||
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()
|
||||
|
||||
|
||||
|
||||
# Installation
|
||||
install(TARGETS ${EXENAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
||||
#Installation of Qt DLLs on Windows
|
||||
jkqtplotter_deployqt(${EXENAME})
|
149
examples/wiggleplots/README.md
Normal file
149
examples/wiggleplots/README.md
Normal file
@ -0,0 +1,149 @@
|
||||
# Example (JKQTPlotter): Wiggle Plots {#JKQTPlotterWigglePlots}
|
||||
|
||||
This project (see `./examples/wiggleplots/`) demonstrates how to draw "wiggle plots" with JKQtPlotter, using `JKQTPFilledCurveXGraph` or `JKQTPFilledCurveYGraph`. Wiggle plots are plots, where the fill color is different above and below the baseline of the plot. They are e.g. used in seismology.
|
||||
|
||||
The source code of the main application can be found in [`wiggleplots.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/wiggleplots/wiggleplots.cpp). If creates two different plots that demonstrate two styles of plots and also uses the horizontal and vertical variant of the graph class.
|
||||
|
||||
## Plot red/blue wiggle plot using `JKQTPFilledCurveXGraph`
|
||||
|
||||
For the first example we simulate a 1D random walk and plot the result as a filles wiggle plot:
|
||||
|
||||
In a first step, we obtain a pointer to the JKQTPDatastore and add two columns to it.
|
||||
```.cpp
|
||||
// 1. get a pointer to the internal datastore (for convenience)
|
||||
JKQTPDatastore* ds=plot.getDatastore();
|
||||
|
||||
// 2. now we create 2 datacolumns with length 1000 (NSteps) entries in the datastore
|
||||
// these will later hold the time-step and position of a random walker
|
||||
const size_t NSteps=400;
|
||||
const size_t columnT=ds->addLinearColumn(NSteps, 0, NSteps-1, "time");
|
||||
const size_t columnX=ds->addColumn(NSteps, "position");
|
||||
```
|
||||
|
||||
Now we fill the column with the random walk data:
|
||||
|
||||
```.cpp
|
||||
// 3. now we simulate a simple rendom walk and store the calculated positions
|
||||
// in columnX
|
||||
double pos=5;
|
||||
const double stepsize=1;
|
||||
std::random_device rd; // random number generators:
|
||||
std::mt19937 gen{rd()};
|
||||
std::uniform_int_distribution<int> dist(0,1);
|
||||
|
||||
for (size_t t=0; t<NSteps; t++) {
|
||||
ds->set(columnX, t, pos);
|
||||
pos=pos+stepsize*(static_cast<double>(dist(gen))*2.0-1.0);
|
||||
}
|
||||
```
|
||||
|
||||
Now we can generate the actual graph and set its basic properties and data columns:
|
||||
|
||||
```.cpp
|
||||
// 4. now we add three semi-transparent, filled curve plots, one for each histogram
|
||||
JKQTPFilledCurveXGraph* graph=new JKQTPFilledCurveXGraph(&plot);
|
||||
|
||||
// 5. set graph titles
|
||||
graph->setTitle("Random Walk");
|
||||
|
||||
// 6. set data
|
||||
graph->setXColumn(columnT); graph->setYColumn(columnX);
|
||||
```
|
||||
|
||||
Now we can acrivate the wiggle plot style filling mode and set the fill colors and line color and width.
|
||||
|
||||
```.cpp
|
||||
// 7.1 enable wiggle-plot filling
|
||||
graph->setFillMode(JKQTPFilledCurveXGraph::TwoColorFilling);
|
||||
// 7.2 draw the data also as a black, thin line
|
||||
graph->setLineColor(QColor("black"));
|
||||
graph->setLineWidth(1);
|
||||
// 7.3 fill areas below the baseline with red
|
||||
graph->setFillColor(QColor("red"));
|
||||
// 7.4 fill areas above the baseline with blue
|
||||
graph->fillStyleBelow().setFillColor(QColor("blue"));
|
||||
```
|
||||
|
||||
The baseline is set to the starting point (5) of the random walk. By default it would be at y=0.
|
||||
|
||||
```.cpp
|
||||
// 7.5 set the baseline to be at 5 (not the default 0
|
||||
graph->setBaseline(5);
|
||||
```
|
||||
|
||||
Now we only have to add the graph to the plotter and set some final properties for styling:
|
||||
|
||||
```.cpp
|
||||
// 8. add the graphs to the plot, so they are actually displayed
|
||||
plot.addGraph(graph);
|
||||
|
||||
// 9. set axis labels
|
||||
plot.getXAxis()->setAxisLabel("time $t$");
|
||||
plot.getYAxis()->setAxisLabel("walker position $x(t)$");
|
||||
|
||||
// 10. scale plot automatically
|
||||
plot.zoomToFit();
|
||||
|
||||
// 11. show plotter and make it a decent size
|
||||
plot.show();
|
||||
plot.resize(600,400);
|
||||
```
|
||||
|
||||
This is the resulting plot:
|
||||
|
||||
![wiggleplot of random walk](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/wiggleplot_x.png)
|
||||
|
||||
|
||||
## Plot black/transparent wiggle plot using `JKQTPFilledCurveYGraph` in a "seismographic style"
|
||||
|
||||
The second example follows mor or less the same steps as above, but here we add several graphs that each show a wavepacket that is shoft slightly:
|
||||
|
||||
```.cpp
|
||||
// 3. now we calculate several wavepackets and add a graph for each.
|
||||
const size_t NWavepackets=7;
|
||||
for (size_t nw=0; nw<NWavepackets; nw++) {
|
||||
const size_t columnPacket=ds->addColumn(NSteps, "wavepacket1");
|
||||
|
||||
const double packwidth=0.4/static_cast<double>(NWavepackets);
|
||||
const double pos=pow(static_cast<double>(nw), 0.6)*packwidth*3.5+5.0*packwidth;
|
||||
const double wavelength=packwidth/1.5;
|
||||
const double offset=(static_cast<double>(nw)*1.5+1.5);
|
||||
for (size_t ti=0; ti<NSteps; ti++) {
|
||||
const double t=ds->get(columnT, ti);
|
||||
ds->set(columnPacket, ti, offset+sin(2.0*M_PI*t/wavelength)*exp(-0.5*jkqtp_sqr(t-pos)/jkqtp_sqr(packwidth)));
|
||||
}
|
||||
|
||||
|
||||
// 4. now we add three semi-transparent, filled curve plots, one for each histogram
|
||||
JKQTPFilledCurveYGraph* graph=new JKQTPFilledCurveYGraph(&plot);
|
||||
|
||||
// set graph titles
|
||||
graph->setTitle("wave "+QString::number(nw+1));
|
||||
|
||||
// set data
|
||||
graph->setYColumn(columnT); graph->setXColumn(columnPacket);
|
||||
|
||||
// enable wiggle-plot filling
|
||||
graph->setFillMode(JKQTPFilledCurveXGraph::TwoColorFilling);
|
||||
// draw the data also as a black, thin line
|
||||
graph->setLineColor(QColor("black"));
|
||||
graph->setLineWidth(1);
|
||||
// fill areas below the baseline with red
|
||||
graph->setFillColor(Qt::transparent);
|
||||
// fill areas above the baseline with blue
|
||||
graph->fillStyleBelow().setFillColor(QColor("black"));
|
||||
// set the baseline to be at 5 (not the default 0
|
||||
graph->setBaseline(offset);
|
||||
|
||||
|
||||
// add the graphs to the plot, so they are actually displayed
|
||||
plot.addGraph(graph);
|
||||
}
|
||||
```
|
||||
|
||||
Also the colors are different: We use black below the baseline and transparent above. The line through the data points is black as well.
|
||||
|
||||
|
||||
This is the resulting plot:
|
||||
|
||||
![wiggleplot of random walk](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/wiggleplot_y.png)
|
155
examples/wiggleplots/wiggleplots.cpp
Normal file
155
examples/wiggleplots/wiggleplots.cpp
Normal file
@ -0,0 +1,155 @@
|
||||
/** \example wiggleplots.cpp
|
||||
* Shows how to use filled graphs with JKQTPlotter
|
||||
*
|
||||
* \ref JKQTPlotterwiggleplots
|
||||
*/
|
||||
|
||||
#include <QApplication>
|
||||
#include "jkqtplotter/jkqtplotter.h"
|
||||
#include "jkqtplotter/graphs/jkqtpfilledcurve.h"
|
||||
#include <random>
|
||||
|
||||
void drawRandomWalkX(JKQTPlotter& plot) {
|
||||
|
||||
// 1. get a pointer to the internal datastore (for convenience)
|
||||
JKQTPDatastore* ds=plot.getDatastore();
|
||||
|
||||
// 2. now we create 2 datacolumns with length 1000 (NSteps) entries in the datastore
|
||||
// these will later hold the time-step and position of a random walker
|
||||
const size_t NSteps=400;
|
||||
const size_t columnT=ds->addLinearColumn(NSteps, 0, NSteps-1, "time");
|
||||
const size_t columnX=ds->addColumn(NSteps, "position");
|
||||
|
||||
// 3. now we simulate a simple rendom walk and store the calculated positions
|
||||
// in columnX
|
||||
double pos=5;
|
||||
const double stepsize=1;
|
||||
std::random_device rd; // random number generators:
|
||||
std::mt19937 gen{rd()};
|
||||
std::uniform_int_distribution<int> dist(0,1);
|
||||
|
||||
for (size_t t=0; t<NSteps; t++) {
|
||||
ds->set(columnX, t, pos);
|
||||
pos=pos+stepsize*(static_cast<double>(dist(gen))*2.0-1.0);
|
||||
}
|
||||
|
||||
|
||||
// 4. now we add three semi-transparent, filled curve plots, one for each histogram
|
||||
JKQTPFilledCurveXGraph* graph=new JKQTPFilledCurveXGraph(&plot);
|
||||
|
||||
// 5. set graph titles
|
||||
graph->setTitle("Random Walk");
|
||||
|
||||
// 6. set data
|
||||
graph->setXColumn(columnT); graph->setYColumn(columnX);
|
||||
|
||||
// 7.1 enable wiggle-plot filling
|
||||
graph->setFillMode(JKQTPFilledCurveXGraph::TwoColorFilling);
|
||||
// 7.2 draw the data also as a black, thin line
|
||||
graph->setLineColor(QColor("black"));
|
||||
graph->setLineWidth(1);
|
||||
// 7.3 fill areas below the baseline with red
|
||||
graph->setFillColor(QColor("red"));
|
||||
// 7.4 fill areas above the baseline with blue
|
||||
graph->fillStyleBelow().setFillColor(QColor("blue"));
|
||||
// 7.5 set the baseline to be at 5 (not the default 0
|
||||
graph->setBaseline(5);
|
||||
|
||||
|
||||
// 8. add the graphs to the plot, so they are actually displayed
|
||||
plot.addGraph(graph);
|
||||
|
||||
// 9. set axis labels
|
||||
plot.getXAxis()->setAxisLabel("time $t$");
|
||||
plot.getYAxis()->setAxisLabel("walker position $x(t)$");
|
||||
|
||||
|
||||
// 10. scale plot automatically
|
||||
plot.zoomToFit();
|
||||
|
||||
// 11. show plotter and make it a decent size
|
||||
plot.show();
|
||||
plot.resize(600,400);
|
||||
}
|
||||
|
||||
void drawWavepacketsY(JKQTPlotter& plot) {
|
||||
|
||||
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
|
||||
JKQTPDatastore* ds=plot.getDatastore();
|
||||
|
||||
// 2. now we create a datacolumns with length 1200 (NSteps) entries in the datastore
|
||||
// these will later hold the time-value for each wavepacket
|
||||
const size_t NSteps=1200;
|
||||
const size_t columnT=ds->addLinearColumn(NSteps, 0, 1, "time");
|
||||
|
||||
|
||||
// 3. now we calculate several wavepackets and add a graph for each.
|
||||
const size_t NWavepackets=7;
|
||||
for (size_t nw=0; nw<NWavepackets; nw++) {
|
||||
const size_t columnPacket=ds->addColumn(NSteps, "wavepacket1");
|
||||
|
||||
const double packwidth=0.4/static_cast<double>(NWavepackets);
|
||||
const double pos=pow(static_cast<double>(nw), 0.6)*packwidth*3.5+5.0*packwidth;
|
||||
const double wavelength=packwidth/1.5;
|
||||
const double offset=(static_cast<double>(nw)*1.5+1.5);
|
||||
for (size_t ti=0; ti<NSteps; ti++) {
|
||||
const double t=ds->get(columnT, ti);
|
||||
ds->set(columnPacket, ti, offset+sin(2.0*M_PI*t/wavelength)*exp(-0.5*jkqtp_sqr(t-pos)/jkqtp_sqr(packwidth)));
|
||||
}
|
||||
|
||||
|
||||
// 4. now we add three semi-transparent, filled curve plots, one for each histogram
|
||||
JKQTPFilledCurveYGraph* graph=new JKQTPFilledCurveYGraph(&plot);
|
||||
|
||||
// set graph titles
|
||||
graph->setTitle("wave "+QString::number(nw+1));
|
||||
|
||||
// set data
|
||||
graph->setYColumn(columnT); graph->setXColumn(columnPacket);
|
||||
|
||||
// enable wiggle-plot filling
|
||||
graph->setFillMode(JKQTPFilledCurveXGraph::TwoColorFilling);
|
||||
// draw the data also as a black, thin line
|
||||
graph->setLineColor(QColor("black"));
|
||||
graph->setLineWidth(1);
|
||||
// fill areas below the baseline with red
|
||||
graph->setFillColor(Qt::transparent);
|
||||
// fill areas above the baseline with blue
|
||||
graph->fillStyleBelow().setFillColor(QColor("black"));
|
||||
// set the baseline to be at 5 (not the default 0
|
||||
graph->setBaseline(offset);
|
||||
|
||||
|
||||
// add the graphs to the plot, so they are actually displayed
|
||||
plot.addGraph(graph);
|
||||
}
|
||||
|
||||
// 5. set axis labels
|
||||
plot.getXAxis()->setAxisLabel("wavepacket amplitude $f(t)$");
|
||||
plot.getYAxis()->setAxisLabel("time $t$");
|
||||
|
||||
|
||||
// 4. scale plot automatically
|
||||
plot.zoomToFit();
|
||||
|
||||
// 5. show plotter and make it a decent size
|
||||
plot.show();
|
||||
plot.resize(600,600);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,6,0) && QT_VERSION < QT_VERSION_CHECK(6,0,0)
|
||||
|
||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // DPI support
|
||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); //HiDPI pixmaps
|
||||
#endif
|
||||
QApplication app(argc, argv);
|
||||
|
||||
JKQTPlotter plotWalk, plotWavepackets;
|
||||
drawRandomWalkX(plotWalk);
|
||||
drawWavepacketsY(plotWavepackets);
|
||||
|
||||
return app.exec();
|
||||
}
|
30
examples/wiggleplots/wiggleplots.pro
Normal file
30
examples/wiggleplots/wiggleplots.pro
Normal file
@ -0,0 +1,30 @@
|
||||
# source code for this simple demo
|
||||
SOURCES = wiggleplots.cpp
|
||||
|
||||
RESOURCES +=
|
||||
|
||||
# configure Qt
|
||||
CONFIG += link_prl qt
|
||||
QT += core gui xml svg
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
|
||||
|
||||
# output executable name
|
||||
TARGET = wiggleplots
|
||||
|
||||
|
||||
# include JKQTPlotter source code
|
||||
DEPENDPATH += ../../lib ../../qmake/staticlib/jkqtplotterlib
|
||||
INCLUDEPATH += ../../lib
|
||||
CONFIG (debug, debug|release) {
|
||||
LIBS += -L../../qmake/staticlib/jkqtplotterlib/debug -ljkqtplotterlib_debug
|
||||
} else {
|
||||
LIBS += -L../../qmake/staticlib/jkqtplotterlib/release -ljkqtplotterlib
|
||||
}
|
||||
message("LIBS = $$LIBS")
|
||||
|
||||
win32-msvc*: DEFINES += _USE_MATH_DEFINES
|
||||
win32-msvc*: DEFINES += NOMINMAX
|
||||
|
||||
|
||||
|
||||
|
8
examples/wiggleplots/wiggleplots_and_lib.pro
Normal file
8
examples/wiggleplots/wiggleplots_and_lib.pro
Normal file
@ -0,0 +1,8 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS += jkqtplotterlib wiggleplots
|
||||
|
||||
jkqtplotterlib.file = ../../qmake/staticlib/jkqtplotterlib/jkqtplotterlib.pro
|
||||
|
||||
wiggleplots.file=$$PWD/wiggleplots.pro
|
||||
wiggleplots.depends = jkqtplotterlib
|
@ -33,11 +33,12 @@
|
||||
|
||||
|
||||
JKQTPFilledCurveGraphBase::JKQTPFilledCurveGraphBase(JKQTBasePlotter *parent):
|
||||
JKQTPXYBaselineGraph(parent)
|
||||
JKQTPXYBaselineGraph(parent), m_fillMode(FillMode::SingleFilling)
|
||||
{
|
||||
parentPlotStyle=-1;
|
||||
initLineStyle(parent, parentPlotStyle, JKQTPPlotStyleType::Filled);
|
||||
initFillStyle(parent, parentPlotStyle, JKQTPPlotStyleType::Filled);
|
||||
m_fillStyleBelow.initFillStyleInvertedColor(this);
|
||||
setFillCurve(true);
|
||||
setDrawLine(true);
|
||||
}
|
||||
@ -57,16 +58,50 @@ void JKQTPFilledCurveGraphBase::drawKeyMarker(JKQTPEnhancedPainter &painter, QRe
|
||||
painter.setPen(np);
|
||||
if (getDrawLine()) painter.setPen(p);
|
||||
painter.setBrush(b);
|
||||
if (getFillCurve()) painter.drawRect(rect);
|
||||
if (getFillCurve()) {
|
||||
if (getFillMode()==FillMode::SingleFilling) {
|
||||
painter.drawRect(rect);
|
||||
} else {
|
||||
QBrush belowB=fillStyleBelow().getFillBrush(painter, parent);
|
||||
QPolygonF p,pb;
|
||||
p<<rect.topLeft()<<rect.topRight()<<rect.bottomRight();
|
||||
pb<<rect.topLeft()<<rect.bottomRight()<<rect.bottomLeft();
|
||||
painter.drawPolygon(p);
|
||||
painter.setBrush(belowB);
|
||||
painter.drawPolygon(pb);
|
||||
painter.setBrush(b);
|
||||
}
|
||||
}
|
||||
if (!getFillCurve() && getDrawLine()) painter.drawLine(QLineF(rect.left(), y, rect.right(), y));
|
||||
}
|
||||
|
||||
JKQTPGraphFillStyleMixin &JKQTPFilledCurveGraphBase::fillStyleBelow()
|
||||
{
|
||||
return m_fillStyleBelow;
|
||||
}
|
||||
|
||||
const JKQTPGraphFillStyleMixin &JKQTPFilledCurveGraphBase::fillStyleBelow() const
|
||||
{
|
||||
return m_fillStyleBelow;
|
||||
}
|
||||
|
||||
JKQTPFilledCurveGraphBase::FillMode JKQTPFilledCurveGraphBase::getFillMode() const
|
||||
{
|
||||
return m_fillMode;
|
||||
}
|
||||
|
||||
void JKQTPFilledCurveGraphBase::setColor(QColor c)
|
||||
{
|
||||
setLineColor(c);
|
||||
setFillColor(JKQTPGetDerivedColor(parent->getCurrentPlotterStyle().graphsStyle.filledStyle.fillColorDerivationMode, c));
|
||||
c.setAlphaF(0.5);
|
||||
setHighlightingLineColor(c);
|
||||
m_fillStyleBelow.initFillStyleInvertedColor(this);
|
||||
}
|
||||
|
||||
void JKQTPFilledCurveGraphBase::setFillMode(FillMode mode)
|
||||
{
|
||||
m_fillMode=mode;
|
||||
}
|
||||
|
||||
|
||||
@ -98,6 +133,7 @@ void JKQTPFilledCurveXGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
QPen ph=getHighlightingLinePen(painter, parent);
|
||||
QPen np(Qt::NoPen);
|
||||
QBrush b=getFillBrush(painter, parent);
|
||||
QBrush b_below=fillStyleBelow().getFillBrush(painter, parent);
|
||||
|
||||
int imax=0;
|
||||
int imin=0;
|
||||
@ -150,7 +186,22 @@ void JKQTPFilledCurveXGraph::draw(JKQTPEnhancedPainter& painter) {
|
||||
auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
|
||||
if (getFillCurve()) {
|
||||
painter.fillPath(pf, b);
|
||||
if (getFillMode()==FillMode::SingleFilling) {
|
||||
painter.fillPath(pf, b);
|
||||
} else if (getFillMode()==FillMode::TwoColorFilling) {
|
||||
QRectF rAbove=pf.boundingRect();
|
||||
rAbove.setBottom(y0);
|
||||
QPainterPath pAbove;
|
||||
pAbove.addRect(rAbove);
|
||||
QRectF rBelow=pf.boundingRect();
|
||||
rBelow.setTop(y0);
|
||||
QPainterPath pBelow;
|
||||
pBelow.addRect(rBelow);
|
||||
QPainterPath pfa=pf.intersected(pAbove);
|
||||
QPainterPath pfb=pf.intersected(pBelow);
|
||||
painter.fillPath(pfa, b);
|
||||
painter.fillPath(pfb, b_below);
|
||||
}
|
||||
}
|
||||
|
||||
if (isHighlighted()) {
|
||||
@ -196,6 +247,7 @@ void JKQTPFilledCurveYGraph::draw(JKQTPEnhancedPainter &painter)
|
||||
QPen ph=getHighlightingLinePen(painter, parent);
|
||||
QPen np(Qt::NoPen);
|
||||
QBrush b=getFillBrush(painter, parent);
|
||||
QBrush b_below=fillStyleBelow().getFillBrush(painter, parent);
|
||||
|
||||
int imax=0;
|
||||
int imin=0;
|
||||
@ -245,7 +297,22 @@ void JKQTPFilledCurveYGraph::draw(JKQTPEnhancedPainter &painter)
|
||||
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
|
||||
|
||||
if (getFillCurve()) {
|
||||
painter.fillPath(pf, b);
|
||||
if (getFillMode()==FillMode::SingleFilling) {
|
||||
painter.fillPath(pf, b);
|
||||
} else if (getFillMode()==FillMode::TwoColorFilling) {
|
||||
QRectF rAbove=pf.boundingRect();
|
||||
rAbove.setLeft(x0);
|
||||
QPainterPath pAbove;
|
||||
pAbove.addRect(rAbove);
|
||||
QRectF rBelow=pf.boundingRect();
|
||||
rBelow.setRight(x0);
|
||||
QPainterPath pBelow;
|
||||
pBelow.addRect(rBelow);
|
||||
QPainterPath pfa=pf.intersected(pAbove);
|
||||
QPainterPath pfb=pf.intersected(pBelow);
|
||||
painter.fillPath(pfa, b);
|
||||
painter.fillPath(pfb, b_below);
|
||||
}
|
||||
}
|
||||
|
||||
if (isHighlighted()) {
|
||||
|
@ -40,6 +40,16 @@
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPFilledCurveGraphBase: public JKQTPXYBaselineGraph, public JKQTPGraphLineAndFillStyleMixin {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/** \brief specifies how the area below the graph is filled
|
||||
*
|
||||
* \see setFillMode(), getFillMode(), fillStyleBelow(), \ref JKQTPlotterWigglePlots
|
||||
*/
|
||||
enum FillMode {
|
||||
SingleFilling=0, /*!< \brief the whole area is filled with the same color/pattern, generates "simple filled plots", such as \image html filledgraphs_small.png */
|
||||
TwoColorFilling=1 /*!< \brief the area above and below baseline with the two different colors/patterns, generates "wiggle plots", such as \image html wiggleplots_small.png */
|
||||
};
|
||||
Q_ENUM(FillMode)
|
||||
|
||||
/** \brief class constructor */
|
||||
explicit JKQTPFilledCurveGraphBase(JKQTBasePlotter* parent=nullptr);
|
||||
|
||||
@ -47,12 +57,23 @@ public:
|
||||
virtual QColor getKeyLabelColor() const override;
|
||||
/** \brief plots a key marker inside the specified rectangle \a rect */
|
||||
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) override;
|
||||
|
||||
/** \copydoc m_fillStyleBelow */
|
||||
JKQTPGraphFillStyleMixin& fillStyleBelow();
|
||||
/** \copydoc m_fillStyleBelow */
|
||||
const JKQTPGraphFillStyleMixin& fillStyleBelow() const;
|
||||
/** \copydoc m_fillMode */
|
||||
FillMode getFillMode() const;
|
||||
public slots:
|
||||
/** \brief set line-color, fill color and symbol color */
|
||||
void setColor(QColor c);
|
||||
/** \copydoc m_fillMode */
|
||||
void setFillMode(FillMode mode);
|
||||
protected:
|
||||
|
||||
/** \brief specifies how the area of the graph is filles */
|
||||
FillMode m_fillMode;
|
||||
/** \brief if m_fillMode \c ==FillAboveAndBelowDifferently then this fill style is used below the baseline and
|
||||
* the default fill style is used above */
|
||||
JKQTPGraphFillStyleMixin m_fillStyleBelow;
|
||||
};
|
||||
|
||||
|
||||
@ -63,6 +84,19 @@ protected:
|
||||
\image html filledgraphs.png
|
||||
|
||||
\see \ref JKQTPlotterFilledGraphs
|
||||
|
||||
This class also provides the possibility to file above and below the baseline with different style.
|
||||
Such plots are sometimes called "Wiggle Plots" and are often used (in their black/white-variety for seismographic
|
||||
data plotting.
|
||||
|
||||
\image html wiggleplot_x.png
|
||||
|
||||
To generate such a plot, used \c JKQTPFilledCurveXGraph::setFillMode(JKQTPFilledCurveXGraph::FillMode::TwoColorFilling)
|
||||
and then use \c JKQTPFilledCurveXGraph::fillStyleBelow() to access the fill style for the area below the baseline
|
||||
and the default fill style to define the fill style above the baseline.
|
||||
|
||||
\see \ref JKQTPlotterWigglePlots
|
||||
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPFilledCurveXGraph: public JKQTPFilledCurveGraphBase {
|
||||
Q_OBJECT
|
||||
@ -113,6 +147,18 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPFilledCurveXErrorGraph: public JKQTPFilledCurv
|
||||
|
||||
\see \ref JKQTPlotterFilledGraphs
|
||||
|
||||
This class also provides the possibility to file above and below the baseline with different style.
|
||||
Such plots are sometimes called "Wiggle Plots" and are often used (in their black/white-variety for seismographic
|
||||
data plotting.
|
||||
|
||||
\image html wiggleplot_x.png
|
||||
|
||||
To generate such a plot, used \c JKQTPFilledCurveXGraph::setFillMode(JKQTPFilledCurveXGraph::FillMode::TwoColorFilling)
|
||||
and then use \c JKQTPFilledCurveXGraph::fillStyleBelow() to access the fill style for the area below the baseline
|
||||
and the default fill style to define the fill style above the baseline.
|
||||
|
||||
\see \ref JKQTPlotterWigglePlots
|
||||
|
||||
*/
|
||||
class JKQTPLOTTER_LIB_EXPORT JKQTPFilledCurveYGraph: public JKQTPFilledCurveGraphBase {
|
||||
Q_OBJECT
|
||||
|
@ -288,6 +288,19 @@ JKQTPGraphFillStyleMixin::JKQTPGraphFillStyleMixin()
|
||||
}
|
||||
|
||||
|
||||
void JKQTPGraphFillStyleMixin::initFillStyleInvertedColor(JKQTPGraphFillStyleMixin *other)
|
||||
{
|
||||
if (other) { // get style settings from parent object
|
||||
m_fillColor=other->getFillColor();
|
||||
qreal h=0,s=0,v=0,a=0;
|
||||
m_fillColor.getHsvF(&h, &s, &v, &a);
|
||||
h=std::fmod(h+120.0/360.0, 1.0);
|
||||
m_fillColor.setHsvF(h,s,v,a);
|
||||
m_fillBrush.setColor(m_fillColor);
|
||||
m_fillBrush.setStyle(other->getFillStyle());
|
||||
}
|
||||
}
|
||||
|
||||
void JKQTPGraphFillStyleMixin::initFillStyle(JKQTBasePlotter *parent, int &parentPlotStyle, JKQTPPlotStyleType styletype)
|
||||
{
|
||||
if (parent) { // get style settings from parent object
|
||||
|
@ -400,6 +400,8 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPGraphFillStyleMixin {
|
||||
|
||||
/** \brief initiaize the fill style (from the parent plotter) */
|
||||
void initFillStyle(JKQTBasePlotter* parent, int &parentPlotStyle, JKQTPPlotStyleType styletype=JKQTPPlotStyleType::Default);
|
||||
/** \brief initiaize the fill style from another JKQTPGraphFillStyleMixin \a other by inverting its fill color */
|
||||
void initFillStyleInvertedColor(JKQTPGraphFillStyleMixin *other);
|
||||
|
||||
virtual ~JKQTPGraphFillStyleMixin();
|
||||
|
||||
@ -434,14 +436,15 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPGraphFillStyleMixin {
|
||||
|
||||
Q_PROPERTY(Qt::BrushStyle fillStyle MEMBER m_fillStyle READ getFillStyle WRITE setFillStyle)
|
||||
Q_PROPERTY(QColor fillColor MEMBER m_fillColor READ getFillColor WRITE setFillColor)
|
||||
|
||||
/** \brief constructs a QBrush from the graph fill styling properties */
|
||||
QBrush getFillBrush(JKQTPEnhancedPainter &painter, JKQTBasePlotter* parent) const;
|
||||
private:
|
||||
/** \brief fill style of the graph */
|
||||
QBrush m_fillBrush;
|
||||
/** \brief last fill color of the graph */
|
||||
QColor m_fillColor;
|
||||
protected:
|
||||
/** \brief constructs a QBrush from the graph fill styling properties */
|
||||
QBrush getFillBrush(JKQTPEnhancedPainter &painter, JKQTBasePlotter* parent) const;
|
||||
};
|
||||
|
||||
|
||||
|
BIN
screenshots/wiggleplot_x.png
Normal file
BIN
screenshots/wiggleplot_x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 90 KiB |
BIN
screenshots/wiggleplot_y.png
Normal file
BIN
screenshots/wiggleplot_y.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 111 KiB |
BIN
screenshots/wiggleplots_small.png
Normal file
BIN
screenshots/wiggleplots_small.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.1 KiB |
Loading…
Reference in New Issue
Block a user