Skip to content

Commit

Permalink
NEW add JKQTPParametrizedVectorFieldGraph, which draws color-coded ve…
Browse files Browse the repository at this point in the history
…ctor fields (color from length, angle, or user-supplied data column) + example
  • Loading branch information
jkriege2 committed Feb 9, 2024
1 parent 24526aa commit 25fcb2a
Show file tree
Hide file tree
Showing 24 changed files with 595 additions and 25 deletions.
2 changes: 2 additions & 0 deletions doc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ if(JKQtPlotter_BUILD_EXAMPLES)
#"multithreaded_complex[multithreaded]/multithreaded_complex/--mdfile=${CMAKE_CURRENT_LIST_DIR}/../examples/multithreaded/README.md --complexlabel"
graphlabels/graphlabels,graphlabels_hor
vectorfield
paramvectorfield
)


Expand Down Expand Up @@ -275,6 +276,7 @@ if(JKQtPlotter_BUILD_EXAMPLES)
second_axis/JKQTBasePlotter_addSecondaryYAxis,JKQTBasePlotter_addSecondaryXAxis
graphlabels/JKQTPGLabelAwayFromXAxis,JKQTPGLabelAwayFromYAxis,JKQTPGLabelTowardsXAxis,JKQTPGLabelTowardsYAxis,JKQTPGLabelAboveData,JKQTPGLabelRightHandSide,JKQTPGLabelBelowData,JKQTPGLabelLeftHandSide,JKQTPGLabelCenteredOnData,JKQTPGLabelCenteredOnDataVertical,JKQTPGLSimpleBox,JKQTPGLSimpleBoxVertical,JKQTPGLSimpleBoxAndLine,JKQTPGLSimpleBoxAndLineVertical,JKQTPGLSimpleBoxAndLineONLYLABELS,JKQTPGLSimpleBoxAndLineONLYLABELSVertical/--iteratefunctorsteps--smallscreenshotplot
vectorfield/JKQTPVectorFieldGraph,JKQTPVectorFieldGraphAnchorBottom,JKQTPVectorFieldGraphAnchorMid,JKQTPVectorFieldGraphAnchorTip,JKQTPVectorFieldGraphAutoscaleLength,JKQTPVectorFieldGraphLengthFromData,JKQTPVectorFieldGraphIgnoreLength,JKQTPVectorFieldGraphIgnoreLengthAutoscaleLineWidthFromLength,JKQTPVectorFieldGraphAutoscaleLengthAutoscaleLineWidthFromLength/--iteratefunctorsteps
paramvectorfield/JKQTPParametrizedVectorFieldGraph,JKQTPParametrizedVectorFieldGraphColorFromMagnitude,JKQTPParametrizedVectorFieldGraphColorFromAngle,JKQTPParametrizedVectorFieldGraphDefaultColor/--iteratefunctorsteps
)


Expand Down
3 changes: 3 additions & 0 deletions doc/dox/examples_and_tutorials.dox
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
<tr><td> \image html vectorfield_small.png
<td> \subpage JKQTPlotterVectorFieldExample
<td> `JKQTPVectorFieldGraph`
<tr><td> \image html paramvectorfield_small.png
<td> \subpage JKQTPParametrizedVectorFieldGraphExample
<td> `JKQTPParametrizedVectorFieldGraph`
</table>


Expand Down
3 changes: 3 additions & 0 deletions doc/dox/jkqtplotter_plotelements_classdoc.dox
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,9 @@ This group assembles graphs that represent vector fields (i.e. sets of quadruple
<tr>
<td>\image html vectorfield_small.png
<td> JKQTPVectorFieldGraph
<tr>
<td>\image html paramvectorfield_small.png
<td> JKQTPParametrizedVectorFieldGraph
</table>


Expand Down
4 changes: 3 additions & 1 deletion doc/dox/whatsnew.dox
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,9 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>NEW: allow linear-gradient(), currentcolor, ... in brush definitions of style.ini-file ... and using it is cyberpunk and dark styles</li>
<li>NEW: style simple_noaxes.ini</li>
<li>NEW: JKQTPXYGraphLabels which can draw a label next to each datapoint in the given x/y-dataset. The labels can be x-/y- or x&y-coordinates or custom, then defined by a user-supplied functor (+example \ref JKQTPlotterGraphLabelsExample)</li>
<li>NEW: Base class JKQTPXYAndVectorGraph for graphs like vector fields, e.g. (x,y,dx,dy) or (x,y,angle,length) and an actual implementation JKQTPVectorFieldGraph (+example \ref JKQTPlotterVectorFieldExample)</li>
<li>NEW: Base class JKQTPXYAndVectorGraph for graphs like vector fields, e.g. (x,y,dx,dy) or (x,y,angle,length) </li>
<li>NEW: JKQTPVectorFieldGraph for drawing "simple" vector fields/quiver plots (+example \ref JKQTPlotterVectorFieldExample)</li>
<li>NEW: JKQTPParametrizedVectorFieldGraph for drawing color-coded vector fields/quiver plots (+example \ref JKQTPParametrizedVectorFieldGraphExample)</li>
</ul></li>

<li>JKQTMathText:<ul>
Expand Down
Binary file added doc/images/JKQTPParametrizedVectorFieldGraph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified doc/images/JKQTPVectorFieldGraphIgnoreLength.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ if (JKQtPlotter_BUILD_LIB_JKQTPLOTTER)
add_subdirectory(paramscatterplot_image)
add_subdirectory(paramscatterplot_customsymbol)
add_subdirectory(parsedfunctionplot)
add_subdirectory(paramvectorfield)
add_subdirectory(rgbimageplot)
add_subdirectory(rgbimageplot_cimg)
add_subdirectory(rgbimageplot_opencv)
Expand Down
25 changes: 25 additions & 0 deletions examples/paramvectorfield/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
cmake_minimum_required(VERSION 3.23)

set(EXAMPLE_NAME paramvectorfield)
set(EXENAME jkqtptest_${EXAMPLE_NAME})

message( STATUS ".. Building Example ${EXAMPLE_NAME}" )



add_executable(${EXENAME} WIN32 ${EXAMPLE_NAME}.cpp)
target_link_libraries(${EXENAME} JKQTPExampleToolsLib)
target_include_directories(${EXENAME} PRIVATE ../../lib)
target_link_libraries(${EXENAME} ${jkqtplotter_namespace}JKQTPlotter${jkqtplotter_LIBNAME_VERSION_PART})

# precomiled headers to speed up compilation
if (JKQtPlotter_BUILD_WITH_PRECOMPILED_HEADERS)
target_precompile_headers(${EXENAME} REUSE_FROM jkqtptest_simpletest)
endif (JKQtPlotter_BUILD_WITH_PRECOMPILED_HEADERS)


# Installation
install(TARGETS ${EXENAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

#Installation of Qt DLLs on Windows
jkqtplotter_deployqt(${EXENAME})
63 changes: 63 additions & 0 deletions examples/paramvectorfield/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Example (JKQTPlotter): Vector Field Plot Example {#JKQTPParametrizedVectorFieldGraphExample}
This project (see [`paramvectorfield`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/paramvectorfield) demonstrates the use of JKQTPParametrizedVectorFieldGraph to visualize a vector field with additional information encoded in the color of the vectors.

The source code of the main application is (see [`paramvectorfield.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/paramvectorfield/paramvectorfield.cpp).

Here is a short summary of the important parts of the code:

```.cpp
// 1. setup a plotter window and get a pointer to the internal datastore (for convenience)
JKQTPlotter plot;
JKQTPDatastore* ds=plot.getDatastore();


// 2. make up some arbitrary data to be used for plotting
// this generates a 2D grid of x/y-coordinates and then calculates dx=cos(y)*sqrt(x/3.0) and dy=sin(x)*sqrt(x/3.0)
const auto columnXY=ds->addLinearGridColumns(NX, 0, 6, NY, -3, 3,"x","y");
const auto columnDX=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return sin(y)*sqrt(x/3.0); });
const auto columnDY=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return cos(x)*sqrt(x/3.0); });
// now we also calulate a column that encodes some other information that can be color-coded
const auto columnC=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return sqrt(fabs(y)); });


// 3. create JKQTPVectorFieldGraph to display the data:
JKQTPParametrizedVectorFieldGraph* graph1=new JKQTPParametrizedVectorFieldGraph(&plot);
graph1->setXYColumns(columnXY);
graph1->setDxColumn(columnDX);
graph1->setDyColumn(columnDY);
graph1->setColorColumn(columnC);
graph1->setTitle(QObject::tr("$\\vec{f}(x,y)=\\bigl[\\sin(y)\\cdot\\sqrt{x/3}, \\cos(x)\\cdot\\sqrt{x/3}\\bigr]^\\mathrm{T}$"));

// 4. add the graphs to the plot, so it is actually displayed
plot.addGraph(graph1);

```
The result looks like this:
![paramvectorfield](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/paramvectorfield.png)
By default, the color of the drawn vector is determined from the color column provided to the graph object.
But you can also choose to not provide a color column and instead set
```.cpp
graph1->setVectorColorMode(JKQTPParametrizedVectorFieldGraph::ColorFromMagnitude);
```

Now the color encodes the actual length (or magnitude) of the vectors:

![paramvectorfield](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/doc/images/JKQTPParametrizedVectorFieldGraphColorFromMagnitude.png)


Alternatively

```.cpp
graph1->setVectorColorMode(JKQTPParametrizedVectorFieldGraph::ColorFromAngle);
```
will color-encode the rotation angle (in radians, 3 o'clock is 0rad) of the vectors:
![paramvectorfield](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/doc/images/JKQTPParametrizedVectorFieldGraphColorFromAngle.png)
86 changes: 86 additions & 0 deletions examples/paramvectorfield/paramvectorfield.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/** \example vectorfield.cpp
* Display a vector field
*
* \ref JKQTPlotterVectorFieldExample
*/

#include "jkqtpexampleapplication.h"
#include <QApplication>
#include "jkqtplotter/jkqtplotter.h"
#include "jkqtplotter/graphs/jkqtpvectorfield.h"
#include "jkqtplotter/graphs/jkqtpscatter.h"
#include "jkqtpexampleapplication.h"


#define NX 9
#define NY 9

int main(int argc, char* argv[])
{

JKQTPAppSettingController highDPIController(argc,argv);
JKQTPExampleApplication app(argc, argv);


// 1. setup a plotter window and get a pointer to the internal datastore (for convenience)
JKQTPlotter plot;
plot.getPlotter()->setUseAntiAliasingForGraphs(true); // nicer (but slower) plotting
plot.getPlotter()->setUseAntiAliasingForSystem(true); // nicer (but slower) plotting
plot.getPlotter()->setUseAntiAliasingForText(true); // nicer (but slower) text rendering
JKQTPDatastore* ds=plot.getDatastore();



// 2. make up some arbitrary data to be used for plotting
// this generates a 2D grid of x/y-coordinates and then calculates dx=cos(y)*sqrt(x/3.0) and dy=sin(x)*sqrt(x/3.0)
const auto columnXY=ds->addLinearGridColumns(NX, 0, 6, NY, -3, 3,"x","y");
const auto columnDX=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return sin(y)*sqrt(x/3.0); });
const auto columnDY=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return cos(x)*sqrt(x/3.0); });
// now we also calulate a column that encodes some other information that can be color-coded
const auto columnC=ds->addCalculatedColumnFromColumn(columnXY.first, columnXY.second, [](double x,double y) { return sqrt(fabs(y)); });


// 3. create JKQTPVectorFieldGraph to display the data:
JKQTPParametrizedVectorFieldGraph* graph1=new JKQTPParametrizedVectorFieldGraph(&plot);
graph1->setXYColumns(columnXY);
graph1->setDxColumn(columnDX);
graph1->setDyColumn(columnDY);
graph1->setColorColumn(columnC);
graph1->setTitle(QObject::tr("$\\vec{f}(x,y)=\\bigl[\\sin(y)\\cdot\\sqrt{x/3}, \\cos(x)\\cdot\\sqrt{x/3}\\bigr]^\\mathrm{T}$"));

// 4. add the graphs to the plot, so it is actually displayed
plot.addGraph(graph1);

// 5. scale the plot so the graph is contained
plot.getPlotter()->setAxisAspectRatio(1);
plot.getPlotter()->setAspectRatio(1);
plot.getPlotter()->setMaintainAxisAspectRatio(true);
plot.getPlotter()->setMaintainAspectRatio(true);
plot.zoomToFit();


// show plotter and make it a decent size
plot.setWindowTitle("JKQTPVectorFieldGraph example");
plot.show();
plot.resize(400/plot.devicePixelRatioF(),430/plot.devicePixelRatioF());



app.addExportStepFunctor([&](){
graph1->setVectorColorMode(JKQTPParametrizedVectorFieldGraph::ColorFromMagnitude);
plot.redrawPlot();
});

app.addExportStepFunctor([&](){
graph1->setVectorColorMode(JKQTPParametrizedVectorFieldGraph::ColorFromAngle);
plot.redrawPlot();
});

app.addExportStepFunctor([&](){
graph1->setVectorColorMode(JKQTPParametrizedVectorFieldGraph::DefaultColor);
plot.redrawPlot();
});


return app.exec();
}
2 changes: 1 addition & 1 deletion examples/vectorfield/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Example (JKQTPlotter): Vector Field Plot Example {#JKQTPlotterVectorFieldExample}
This project (see [`vectorfield`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/vectorfield) demonstrates the use of JKQTPXYvectorfield to add labels to the datapoints of a graph.
This project (see [`vectorfield`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/vectorfield) demonstrates the use of JKQTPVectorFieldGraph to visualize a vector field.

The source code of the main application is (see [`vectorfield.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/vectorfield/vectorfield.cpp).

Expand Down
2 changes: 1 addition & 1 deletion examples/vectorfield/vectorfield.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ int main(int argc, char* argv[])
});
app.addExportStepFunctor([&](){
graph1->setAnchorPoint(JKQTPVectorFieldGraph::AnchorMid);
plot.redrawPlot();
plot.redrawPlot();
});

app.addExportStepFunctor([&](){
Expand Down
4 changes: 2 additions & 2 deletions lib/jkqtplotter/graphs/jkqtpbarchartbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,9 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBarGraphBase: public JKQTPXYBaselineGraph, pub
/** \brief class constructor */
JKQTPBarGraphBase(JKQTPlotter* parent);

/** \brief plots a key marker inside the specified rectangle \a rect */
/** \copydoc JKQTPXYBaselineGraph::drawKeyMarker() */
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, const QRectF& rect) override;
/** \brief returns the color to be used for the key label */
/** \copydoc JKQTPXYBaselineGraph::getKeyLabelColor() */
virtual QColor getKeyLabelColor() const override;


Expand Down
2 changes: 1 addition & 1 deletion lib/jkqtplotter/graphs/jkqtpboxplot.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPBoxplotVerticalGraph: public JKQTPBoxplotGraph

/** \brief plots the graph to the plotter object specified as parent */
virtual void draw(JKQTPEnhancedPainter& painter) override;
/** \brief plots a key marker inside the specified rectangle \a rect */
/** \copydoc JKQTPBoxplotGraphBase::drawKeyMarker() */
virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, const QRectF& rect) override;

/** \copydoc JKQTPPlotElement::getXMinMax() */
Expand Down
1 change: 1 addition & 0 deletions lib/jkqtplotter/graphs/jkqtpscatter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ JKQTPXYParametrizedScatterGraph::JKQTPXYParametrizedScatterGraph(JKQTBasePlotter
symbolFillDerivationMode=JKQTPColorDerivationMode::JKQTPFFCMLighterColor;
if (parent) {
symbolFillDerivationMode=parent->getCurrentPlotterStyle().graphsStyle.defaultGraphStyle.fillColorDerivationMode;
palette=parent->getCurrentPlotterStyle().graphsStyle.defaultPalette;
}

clearSizeColumnFunctor();
Expand Down
Loading

0 comments on commit 25fcb2a

Please sign in to comment.