JKQtPlotter/examples/vectorfield
2024-02-10 00:26:45 +01:00
..
CMakeLists.txt NEW: Base class JKQTPXYAndVectorGraph for graphs like vector fields, e.g. (x,y,dx,dy) or (x,y,angle,length) 2024-02-08 21:52:30 +01:00
README.md NEW add JKQTPParametrizedVectorFieldGraph, which draws color-coded vector fields (color from length, angle, or user-supplied data column) + example 2024-02-10 00:26:45 +01:00
vectorfield.cpp NEW add JKQTPParametrizedVectorFieldGraph, which draws color-coded vector fields (color from length, angle, or user-supplied data column) + example 2024-02-10 00:26:45 +01:00

Example (JKQTPlotter): Vector Field Plot Example

This project (see vectorfield demonstrates the use of JKQTPVectorFieldGraph to visualize a vector field.

The source code of the main application is (see vectorfield.cpp.

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

    // 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); });

    // 3. create JKQTPVectorFieldGraph to display the data:
    JKQTPVectorFieldGraph* graph1=new JKQTPVectorFieldGraph(&plot);
    graph1->setXYColumns(columnXY);
    graph1->setDxColumn(columnDX);
    graph1->setDyColumn(columnDY);
        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:

vectorfield

By default, the length of the drawn vector is determined from the actual length in the data via an autoscaling algorithm that is supposed to prevent the vectors from overlapping. But you can modify this behaviour by adding a line

        graph1->setVectorLengthMode(JKQTPVectorFieldGraph::LengthFromData);

which will use the given lengths directly (only scaled by an optional factor defined by JKQTPVectorFieldGraph::setLengthScaleFactor() ). The result then looks like this:

vectorfield

Alternatively you can also set

        graph1->setVectorLengthMode(JKQTPVectorFieldGraph::IgnoreLength);

which will draw all vectors with the same length. You can scale this length by setting JKQTPVectorFieldGraph::setAutoscaleLengthFactor() ). The result then looks like this:

vectorfield

Finally it is also possibly to scale the vector's line width with its length:

        graph1->setVectorLengthMode(JKQTPVectorFieldGraph::AutoscaleLength);
        graph1->setVectorLineWidthMode(JKQTPVectorFieldGraph::AutoscaleLineWidthFromLength);

This will result in a plot like this:

vectorfield