diff --git a/JKQtPlotterBuildAllExamples.pro b/JKQtPlotterBuildAllExamples.pro
index 904166e366..0cf25f8440 100644
--- a/JKQtPlotterBuildAllExamples.pro
+++ b/JKQtPlotterBuildAllExamples.pro
@@ -77,6 +77,7 @@ addSimpleTest(ui)
addSimpleTest(boxplot)
addSimpleTest(advancedlineandfillstyling)
addSimpleTest(imageplot_nodatastore)
+addSimpleTest(datastore)
#addSimpleTest(rgbimageplot_opencv)
#addSimpleTest(imageplot_opencv)
diff --git a/doc/dox/examples_and_tutorials.dox b/doc/dox/examples_and_tutorials.dox
index 914e18011f..b1b081064a 100644
--- a/doc/dox/examples_and_tutorials.dox
+++ b/doc/dox/examples_and_tutorials.dox
@@ -143,6 +143,16 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
+\subsection jkqtp_extut_datamanagement Data Management
+
+
+ Screenshot | Description | Notes
+ |
---|
\image html simpletest_datastore_small.png
+ | \subpage JKQTPlotterAdvancedJKQTPDatastore
+ | Advanced Data Management with JKQTPDatastore
+ |
+
+
\subsection jkqtp_extut_complexexamples More Complex Examples
diff --git a/doc/dox/jkqtplotter.dox b/doc/dox/jkqtplotter.dox
index 2208b73bdf..1e2b81fb62 100644
--- a/doc/dox/jkqtplotter.dox
+++ b/doc/dox/jkqtplotter.dox
@@ -44,6 +44,8 @@ data sources (internal or external memory arrays. Later on it is simply possible
using the column number and the not a link to the actual data array, as the link is stored in these
classes.
+\see \ref JKQTPlotterAdvancedJKQTPDatastore for a detailed description of how to use this class for data management!
+
\defgroup jkqtpopencvinterface OpenCV Interfaceing Tools
\ingroup jkqtpdatastorage
diff --git a/examples/README.md b/examples/README.md
index 4b06f5f6e6..e9b8419253 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -59,12 +59,21 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
-## Plot Layout & Styling
+## Data Management
+
+| Screenshot | Description | Notes |
+|:-------------:| ------------- | ------------- |
+| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore) | [Advanced Usage of JKQTPDatastore](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore) | Advanced Data Management with JKQTPDatastore |
+
+
+
+
+## More Complex Examples
| Screenshot | Description | Notes |
|:-------------:| ------------- | ------------- |
| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/test_multiplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/test_multiplot) | [Layouting Several Plots](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/test_multiplot) | Combining plots in Qt Layouts
linking plot axes
copy data from a `std::map` int the datastore
print plots/print preview |
-| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/test_styling_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/test_styling) | [Styling of JKQTPlotter](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/test_styling) | Modifying different Aspects of the Styling of JKQTPlotter |
+| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/test_distributionplot_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/test_distributionplot) | [Plotting a Statistical Distribution of Data](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/test_distributionplot) | Combines several different graphs to draw random values, their distribution and some statistical properties |
diff --git a/examples/simpletest_datastore/README.md b/examples/simpletest_datastore/README.md
new file mode 100644
index 0000000000..c9eacc0a92
--- /dev/null
+++ b/examples/simpletest_datastore/README.md
@@ -0,0 +1,282 @@
+# Example (JKQTPlotter): Advanced Usage of JKQTPDatastore {#JKQTPlotterAdvancedJKQTPDatastore}
+This project (see `./examples/simpletest_datastore/`) explains several advanced options of JKQTPDatastore, which is the class used to centrally store the data for (most) graphs on a JKQTPlotter widget.
+
+
+The source code of the main application can be found in [`jkqtplotter_simpletest_datastore.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore/jkqtplotter_simpletest_datastore.cpp).
+This tutorial cites parts of this code to demonstrate different ways of working with data for the graphs.
+
+In every code-segment below, we will use these two declarations from the code to access the internal datastore of the JKQTPlotter instance:
+```.cpp
+ // 1. create a plotter window and get a pointer to the internal datastore (for convenience)
+ JKQTPlotter plot;
+ JKQTPDatastore* datastore=plot.getDatastore();
+```
+
+## Copy Data from different data structures into JKQTPDatastore
+
+### Copy Data from a Vector into a column of the JKQTPDatastore
+First we fill data into a QVector for a simple plot (a sine curve) and add a plot using this data:
+```.cpp
+ QVector X, Y;
+ const int Ndata=100;
+ for (int i=0; isetXColumn(ds->addCopiedColumn(X, "x"));
+ linegraph->setYColumn(ds->addCopiedColumn(Y, "y"));
+ linegraph->setTitle(QObject::tr("sine graph"));
+```
+Note that you could also use a `std::vector` instead, as `JKQTPDatastore::addCopiedColumn()` is a template function that only requires the container to support C++ standard iterations (with `begin()` and `end()`), as well as the function `size()` to determine the number of items in the container. Also other datatypes than `double` are possible, as long as they can be converted to `double` (the function `jkqtp_todouble()` is used to perform the conversion, notably all integer and floating-point types, as well as `bool` are supported out of the box).
+
+The plot from the code above looks like this:
+
+![simpletest_datastore_sine](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_sine.png)
+
+
+### Copy Data from a C-array into a column of the JKQTPDatastore
+Of course if you have your data in a C-array, you can use the same syntax:
+```.cpp
+ #define NDATA 5
+ double X[NDATA]= { 1, 2, 3, 4, 5 };
+ double Y[NDATA]= { 1, 0, 1, 0, 1 };
+ linegraph->setXColumn(datastore->addCopiedColumn(X, NDATA, "x"));
+ linegraph->setYColumn(datastore->addCopiedColumn(Y, NDATA, "Y"));
+```
+
+
+The plot from the code above looks like this:
+
+![simpletest_datastore_linkedcarray](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_linkedcarray.png)
+
+
+### Copy Data from a Map into a JKQTPDatastore
+Since graphs often display (x,y)-pairs, it may make sense to store them in a map (e.g. for histograms). There there are also functions that copy the contents of a map into a JKQTPDatastore, resulting in two columns beeing added:
+```.cpp
+ std::map datamap;
+ datamap[1]=1.1;
+ datamap[2]=1.4;
+ datamap[4]=1.2;
+ datamap[5]=1.8;
+ datamap[7]=0.9;
+ plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
+ linegraph->setXYColumns(datastore->addCopiedMap(datamap, "map_x", "map_y"));
+ linegraph->setTitle(QObject::tr("copied map"));
+```
+This code results in a graph like this:
+
+![simpletest_datastore_map](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_map.png)
+
+
+## Reference External Data in a column of the JKQTPDatastore
+
+### Referencing without transfer of ownership
+As an alternative to the method of copying data (see above), you could also just link the data. For this to work, the data has to reside in a C-array of type `double`, as this is the internal datatype of the `JKQTPDatastore`. You can simply replace the two lines with `JKQTPDatastore::addCopiedColumn()` in the example above by (we exploit the fact that `QVector::data()` returns a pointer to the internal C-array of the vector):
+```.cpp
+ linegraph->setXColumn(datastore->addColumn(X.data(), X.size(), "x"));
+ linegraph->setYColumn(datastore->addColumn(Y.data(), Y.size(), "Y"));
+```
+Of course if you have your data in a C-array, you can use the same syntax:
+```.cpp
+ #define NDATA 5
+ double XCA[NDATA]= { 1, 2, 3, 4, 5 };
+ double YCA[NDATA]= { 1, 0, 1, 0, 1 };
+ linegraph->setXColumn(datastore->addColumn(XCA, NDATA, "x"));
+ linegraph->setYColumn(datastore->addColumn(YCA, NDATA, "Y"));
+```
+This method is especially useful, when you have large datasets (e.g. images) that you don't want to copy around.
+
+Note however that the ownership of the data is not transfered to the JKQTPDatastore, i.e. you have to ensure that the data behind the pointer exists, as long as the column references the array and you have to ensure that the data is freed, when you don't need it any more.
+
+The plot from the code above looks like this:
+
+![simpletest_datastore_linkedcarray](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_linkedcarray.png)
+
+### Referencing with transfer of ownership
+In addition to the variants of `JKQTPDatastore::addColumn()`, that do not transfer ownership of the data to the `JKQTPDatastore`, you can also use `JKQTPDatastore::addInternalColumn()`, which tells the `JKQTPDatastore` to use the external data array and also take over its owner-ship. This implies that the array is freed when the `JKQTPDatastore` is destroyed, by calling `free()` in the array. Therefor data for this method needs to be allocated by using `malloc()` or `calloc()`:
+```.cpp
+ #define NDATA 5
+ double* XCA=(double*)malloc(NDATA, sizeof(double));
+ ...
+ linegraph->setXColumn(datastore->addInternalColumn(XCA, NDATA, "x"));
+```
+
+
+## JKQTPDatastore-internal Data Management
+It is also possible to leave the data mangement completely to the JKQTPDatastore and just edit the data with access functions from JKQTPDatastore.
+
+### Generating Columns Non-Initialized Columns and Filling Them
+The most basic way to generate data for a plot is to generate two non-initialized columns for the x- and y-coordinates of the graph points
+```.cpp
+ const int Ndata=100;
+ size_t colX=datastore->addColumn(Ndata, "x");
+ size_t colY=datastore->addColumn(Ndata, "y");
+```
+These calls to JKQTPDatastore::addColumn() will generate a column each with with `ndata` uninitialized entries.
+Then use JKQTPDatastore::set() to fill them with data:
+```.cpp
+ for (int i=0; iset(colX, i, x);
+ datastore->set(colY, i, sin(x));
+ }
+```
+
+Plotting these two columns versus each other results in a simple sine graph:
+
+![simpletest_datastore_sine](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_sine.png)
+
+
+
+### Generating Columns Preinitialized Columns
+For your convenience there are also function that simply create such a linear vector with one call:
+```.cpp
+ size_t colLinX=datastore->addLinearColumn(count, 0, 20, "x_lin");
+```
+This call is equivalent to
+```.cpp
+ for (size_t i=0; iset(colLinX, i, 0.0+static_cast(i)/static_cast(count-1)*20.0);
+ }
+```
+
+In both cases the column `colLinX` will contain these numbers afterwards:
+```
+ 0, 0.512821, 1.02564, 1.53846, 2.05128, 2.5641, 3.07692, ..., 18.9744, 19.4872, 20
+```
+
+Comparable functions exist for logarithmically spaced columns (`JKQTPDatastore::addLogColumn()` and `JKQTPDatastore::addDecadeLogColumn()` which only differ in the way the start and end values are specified):
+```.cpp
+ size_t colLogX=datastore->addLogColumn(30, 1, 1000, "x_log");
+```
+This call results in a column with these 30 values spanning the range between 1 and 1000:
+```
+ 1, 1.26896, 1.61026, 2.04336, ..., 8.53168, 10.8264, 13.7382, ..., 72.7895, 92.3671, ..., 788.046, 1000
+```
+
+### Using Data from one Column to Calculate Another
+
+After generating columns, as shown above, you can also use the data in these columns to calculate a second column based on the values in the first. You can do this explicitly:
+```.cpp
+ size_t colLinX=datastore->addLinearColumn(40, 0, 20, "x_lin");
+ size_t colFunc1=datastore->addColumn(datastore->getRows(colLinX), "cos(x_lin)*x_lin/20.0");
+ for (size_t i=0; igetRows(colLinX); i++) {
+ double x=datastore->get(colLinX, i);
+ datastore->set(colFunc1, i, cos(x)*x/20.0);
+ }
+```
+In this example the function JKQTPDatastore::get() is used to retrieve a value from a column and then JKQTPDatastore::set() is used to store a new value calculated from the read values into another column.
+
+Or use a special function that gets a column with values and a functor f: double->double as parameters:
+```.cpp
+ size_t colLinX=datastore->addLinearColumn(40, 0, 20, "x_lin");
+ size_t colFunc1=datastore->addColumnCalculatedFromColumn(colLinX, [](double x)->double { return cos(x)*x/20.0; }, "cos(x_lin)*x_lin/20.0");
+```
+
+Plotting these two columns versus each other
+```.cpp
+ plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
+ linegraph->setXColumn(colLinX);
+ linegraph->setYColumn(colFunc1);
+ linegraph->setTitle(QObject::tr("calculated column(s)"));
+```
+
+results in:
+
+![simpletest_datastore_calccolumns](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_calccolumns.png)
+
+
+### 2D-Datasets and Images
+There is also a function `JKQTPDatastore::addLinearGridColumns(size_t width, double startX, double endX, size_t height, double startY, double endY, const QString &nameX, const QString &nameY)` that generate two columns simultaneously that conatin the x- and y-coordinates of the points on a rectangular grid, in a column-major order:
+```.cpp
+ std::pair colLinXY=datastore->addLinearGridColumns(10, 10, 20, 10, 1.5, 3);
+```
+This call will generate these columns with x-values scaling between 10 and 20 (in 10 steps) and y-values between 1.5 and 3 (also in 10 steps):
+```
+ x y
+ ----------------------
+ 10, 1.5
+ 11.1111, 1.5
+ 12.2222, 1.5
+ 13.3333, 1.5
+ 14.4444, 1.5
+ 15.5556, 1.5
+ 16.6667, 1.5
+ 17.7778, 1.5
+ 18.8889, 1.5
+ 20, 1.5
+ 10, 1.66667
+ 11.1111, 1.66667
+ 12.2222, 1.66667
+ 13.3333, 1.66667
+ 14.4444, 1.66667
+ 15.5556, 1.66667
+ 16.6667, 1.66667
+ 17.7778, 1.66667
+ 18.8889, 1.66667
+ 20, 1.66667
+ 10, 1.83333
+ 11.1111, 1.83333
+ ... ...
+ ... ...
+ 18.8889, 3
+ 20, 3
+```
+Such x-y-coordinate columns are especially usefull when calculating data for an image (plotted by `JKQTPColumnMathImage`), or for a parametrized scatter plot (plotted by `JKQTPXYParametrizedScatterGraph`). To demonstrate this, we can can add another column with 10*10=100 entries and fill it with some values calculated from the the x and y-values in colLinXY:
+```.cpp
+ size_t imgColumn=datastore->addImageColumn(10, 10, "image values");
+ for (size_t i=0; igetRows(imgColumn); i++) {
+ double x=datastore->get(colLinXY.first, i);
+ double y=datastore->get(colLinXY.second, i);
+ datastore->set(imgColumn, i, cos((x-15.0))/(x-15.0)*cos((y-2.0))/(x-2.0));
+ }
+```
+Note that we used `JKQTPDatastore::addImageColumn(width,height,name)` here, which generates a column with `width*height` entries that are meant to be interpreted as a 2D image with width columns and height rows. This function therefore also save this image size in the column metadata and graphs can later extract this dimension and use it to set them up internally (e.g. JKQTPColumnMathImage::setImageColumn() does just that).
+In the example above we used the simple JKQTPDatastore::set() store values into our image column. This function treats the column as linearized in row-major order. Alternatively you can also use code like this to access the imageColumn as a real image or matrix:
+```.cpp
+ for (int iy=0; iy<10; iy++) {
+ for (int ix=0; ix<10; ix++) {
+ datastore->setPixel(imgColumn, ix, iy, sin(ix*iy));
+ }
+ }
+```
+Drawing this column as an image (using JKQTPColumnMathImage) will look like this:
+
+![simpletest_datastore_sineimg](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_sineimg.png)
+
+In these examples, the iteration and calculation is written out with an explicit for-loop. JKQTPDatastore also offers a shortcut function for this that accepts a functor with the calculation only:
+```.cpp
+ imgColumn=datastore->addColumnCalculatedFromColumn(colLinXY.first, colLinXY.second,
+ [](double x, double y)->double {
+ return cos((x-15.0))/(x-15.0)*cos((y-2.0))/(x-2.0);
+ },
+ "image value");
+```
+
+Then you can plot these as a parametrized scatter graph (`JKQTPXYParametrizedScatterGraph`) using:
+```.cpp
+ plot.addGraph(paramscattergraph=new JKQTPXYParametrizedScatterGraph(&plot));
+ paramscattergraph->setXYColumns(colLinXY);
+ paramscattergraph->setColorColumn(imgColumn);
+ paramscattergraph->setTitle(QObject::tr("parametrized scatter"));
+```
+... or alternatively you can only use the column imgColumn in a `JKQTPColumnMathImage`
+```.cpp
+ plot.addGraph(imggraph=new JKQTPColumnMathImage(&plot));
+ imggraph->setImageColumn(imgColumn);
+ imggraph->setX(21);
+ imggraph->setY(1.5);
+ imggraph->setWidth(10);
+ imggraph->setHeight(1.5);
+ imggraph->setTitle(QObject::tr("imgColumn"));
+```
+The result will look like this:
+
+![simpletest_datastore_image](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_image.png)
+
+
diff --git a/examples/simpletest_datastore/jkqtplotter_simpletest_datastore.cpp b/examples/simpletest_datastore/jkqtplotter_simpletest_datastore.cpp
new file mode 100644
index 0000000000..9853b49475
--- /dev/null
+++ b/examples/simpletest_datastore/jkqtplotter_simpletest_datastore.cpp
@@ -0,0 +1,140 @@
+/** \example jkqtplotter_simpletest_datastore.cpp
+ * A very basic example for the usage of JKQTPlotter
+ *
+ * \ref JKQTPlottersimpletest_datastore
+ */
+
+#include
+#include "jkqtplotter/jkqtplotter.h"
+#include "jkqtplotter/jkqtpgraphsscatter.h"
+#include "jkqtplotter/jkqtpgraphsimage.h"
+
+
+int main(int argc, char* argv[])
+{
+ QApplication app(argc, argv);
+
+ // 1. create a plotter window and get a pointer to the internal datastore (for convenience)
+ JKQTPlotter plot;
+ JKQTPDatastore* datastore=plot.getDatastore();
+
+ JKQTPXYLineGraph* linegraph;
+ JKQTPColumnMathImage* imggraph;
+ JKQTPXYParametrizedScatterGraph* paramscattergraph;
+
+ // 2. first we create data inside a QVector for a simple plot (a sine curve) ... and add the plot
+ // note that you could use a std::vector equally well
+ QVector X, Y;
+ const int Ndata=100;
+ for (int i=0; isetXColumn(datastore->addCopiedColumn(X, "x"));
+ linegraph->setYColumn(datastore->addCopiedColumn(Y, "y"));
+ // alternatively you can also tell JKQTPDatastore to just reference an external array:
+ //linegraph->setXColumn(datastore->addColumn(X.data(), X.size(), "x"));
+ //linegraph->setYColumn(datastore->addColumn(Y.data(), Y.size(), "Y"));
+ linegraph->setTitle(QObject::tr("sine graph"));
+
+
+
+ // 3. Now we generate a plot from data in a C-array, just reference in the JKQTPDatastore
+ #define NDATA 5
+ double XCA[NDATA]= { 1, 2, 3, 4, 5 };
+ double YCA[NDATA]= { 1, 0, 1, 0, 1 };
+ plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
+ linegraph->setXColumn(datastore->addColumn(XCA, NDATA, "xca (C-array)"));
+ linegraph->setYColumn(datastore->addColumn(YCA, NDATA, "yca (C-array)"));
+ // of course you could also simply copy the data with a comparable syntax:
+ //linegraph->setXColumn(datastore->addCopiedColumn(XCA, NDATA, "xca (C-array)"));
+ //linegraph->setYColumn(datastore->addCopiedColumn(YCA, NDATA, "yca (C-array)"));
+ linegraph->setTitle(QObject::tr("linked C-array data"));
+
+
+ // 4. Since graphs often display (x,y)-pairs, it may make sense to store them in a map (e.g. for histograms)
+ // There there are also functions that copy the contents of a map into a JKQTPDatastore, resulting in
+ // two columns beeing added:
+ std::map datamap;
+ datamap[1]=1.1;
+ datamap[2]=1.4;
+ datamap[4]=1.2;
+ datamap[5]=1.8;
+ datamap[7]=0.9;
+ plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
+ linegraph->setXYColumns(datastore->addCopiedMap(datamap, "map_x", "map_y"));
+ linegraph->setTitle(QObject::tr("copied map"));
+
+
+
+ // 5. It is also possible to leave the data mangement completely to the JKQTPDatastore
+ // and just edit the data with access functions from JKQTPDatastore:
+ plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
+ // 5.1 this adds a column with 40 values, linearly spaced between 0 and 20 (inclusive).
+ size_t colLinX=datastore->addLinearColumn(40, 0, 20, "x_lin");
+ // 5.2 this adds a column with one entry for every entry x in the column colLinX, where
+ // the entry is calculated by applying a function cos(x)*x/20.0
+ size_t colFunc1=datastore->addColumnCalculatedFromColumn(colLinX, [](double x)->double { return cos(x)*x/20.0; }, "cos(x_lin)*x_lin/20.0");
+ // the same can be done by this code explicitly:
+ // 5.2.1 add a column with as many rows as column colLinX
+ //size_t colFunc1=datastore->addColumn(datastore->getRows(colLinX), "cos(x_lin)*x_lin/20.0");
+ // 5.2.2 iterate over the data in column colLinX and set a newly calculated value into a row of column colFunc1
+ //for (size_t i=0; igetRows(colLinX); i++) {
+ // double x=datastore->get(colLinX, i);
+ // datastore->set(colFunc1, i, cos(x)*x/20.0);
+ //}
+ linegraph->setXColumn(colLinX);
+ linegraph->setYColumn(colFunc1);
+ linegraph->setTitle(QObject::tr("calculated column(s)"));
+
+
+ // 6. The function addLinearGridColumns() generates a rectangular 2D grid of coordinates
+ // in row-major order. Here we generate a 10x10 grid with x-coordinates between 10 and 20 (inclusive)
+ // and y-coordinates between 1.5 and 3:
+ std::pair colLinXY=datastore->addLinearGridColumns(10, 10, 20, 10, 1.5, 3);
+ // now we can add another column with 10*10=100 entries and fill it with some values
+ // calculated from the the x and y-values in colLinXY:
+ size_t imgColumn=datastore->addImageColumn(10, 10, "image values");
+ for (size_t i=0; igetRows(imgColumn); i++) {
+ double x=datastore->get(colLinXY.first, i);
+ double y=datastore->get(colLinXY.second, i);
+ datastore->set(imgColumn, i, cos((x-15.0))/(x-15.0)*cos((y-2.0))/(x-2.0));
+ }
+ // alternatively you can access image pixels with setPixel():
+ //for (int iy=0; iy<10; iy++) {
+ // for (int ix=0; ix<10; ix++) {
+ // datastore->setPixel(imgColumn, ix, iy, sin(ix*iy/30.0));
+ // }
+ //}
+ // the loop above can be written more compact using addColumnCalculatedFromColumn():
+ //imgColumn=datastore->addColumnCalculatedFromColumn(colLinXY.first, colLinXY.second, [](double x, double y)->double { return cos((x-15.0))/(x-15.0)*cos((y-2.0))/(x-2.0); }, "image value");
+ // finally we can use a JKQTPXYParametrizedScatterGraph to display the data from our three columns
+ // by using colLinXY->first and colLinXY->second as positions for symbols that are colored, based
+ // on the respective value in imgColumn:
+ plot.addGraph(paramscattergraph=new JKQTPXYParametrizedScatterGraph(&plot));
+ paramscattergraph->setXYColumns(colLinXY);
+ paramscattergraph->setColorColumn(imgColumn);
+ paramscattergraph->setTitle(QObject::tr("parametrized scatter"));
+ // alternatively you can only use the column imgColumn in a JKQTPColumnMathImage
+ plot.addGraph(imggraph=new JKQTPColumnMathImage(&plot));
+ imggraph->setImageColumn(imgColumn);
+ imggraph->setX(21);
+ imggraph->setY(1.5);
+ imggraph->setWidth(10);
+ imggraph->setHeight(1.5);
+ imggraph->setTitle(QObject::tr("imgColumn"));
+
+
+
+ // 6. autoscale the plot so the graph is contained
+ plot.zoomToFit();
+
+ // show plotter and make it a decent size
+ plot.show();
+ plot.resize(600,400);
+
+ return app.exec();
+}
diff --git a/examples/simpletest_datastore/jkqtplotter_simpletest_datastore.pro b/examples/simpletest_datastore/jkqtplotter_simpletest_datastore.pro
new file mode 100644
index 0000000000..4e7258517e
--- /dev/null
+++ b/examples/simpletest_datastore/jkqtplotter_simpletest_datastore.pro
@@ -0,0 +1,26 @@
+# source code for this simple demo
+SOURCES = jkqtplotter_simpletest_datastore.cpp
+
+# configure Qt
+CONFIG += link_prl qt
+QT += core gui xml svg
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport
+
+# output executable name
+TARGET = jkqtplotter_simpletest_datastore
+
+# include JKQTPlotter source headers and link against library
+DEPENDPATH += ../../lib ../../staticlib/jkqtplotterlib
+INCLUDEPATH += ../../lib
+CONFIG (debug, debug|release) {
+ LIBS += -L../../staticlib/jkqtplotterlib/debug -ljkqtplotterlib_debug
+} else {
+ LIBS += -L../../staticlib/jkqtplotterlib/release -ljkqtplotterlib
+}
+message("LIBS = $$LIBS")
+
+win32-msvc*: DEFINES += _USE_MATH_DEFINES
+
+
+
+
diff --git a/examples/simpletest_datastore/jkqtplotter_simpletest_datastore_and_lib.pro b/examples/simpletest_datastore/jkqtplotter_simpletest_datastore_and_lib.pro
new file mode 100644
index 0000000000..01630b7267
--- /dev/null
+++ b/examples/simpletest_datastore/jkqtplotter_simpletest_datastore_and_lib.pro
@@ -0,0 +1,8 @@
+TEMPLATE = subdirs
+
+SUBDIRS += jkqtplotterlib jkqtplotter_simpletest_datastore
+
+jkqtplotterlib.file = ../../staticlib/jkqtplotterlib/jkqtplotterlib.pro
+
+jkqtplotter_simpletest_datastore.file=$$PWD/jkqtplotter_simpletest_datastore.pro
+jkqtplotter_simpletest_datastore.depends = jkqtplotterlib
diff --git a/examples/simpletest_filledgraphs/README.md b/examples/simpletest_filledgraphs/README.md
index 338a7a6190..6a23262d2c 100644
--- a/examples/simpletest_filledgraphs/README.md
+++ b/examples/simpletest_filledgraphs/README.md
@@ -15,20 +15,12 @@ And three columns with 256 entries each, which will be filled with the R-, G- an
size_t columnB=ds->addColumn(256, "historam_B");
```
-In this example we will access the data in the internal datastore directly. This access is possible through objects of type JKQTPColumn, which is a proxy to the data in one of the columns in a `JKQTdatastore`:
-
-```.cpp
- JKQTPColumn cG=ds->getColumn(columnG);
- JKQTPColumn cR=ds->getColumn(columnR);
- JKQTPColumn cB=ds->getColumn(columnB);
-```
-
In order to calculate the histograms, first all enries in the columns are set to 0:
```.cpp
- cR.setAll(0);
- cG.setAll(0);
- cB.setAll(0);
+ ds->setAll(columnG, 0);
+ ds->setAll(columnR, 0);
+ ds->setAll(columnB, 0);
```
Finally the histogram is calculated:
@@ -38,14 +30,14 @@ Finally the histogram is calculated:
for (int y=0; yinc(columnR, qRed(pix), 1);
+ ds->inc(columnG, qGreen(pix), 1);
+ ds->inc(columnB, qBlue(pix), 1);
}
}
- cR.scale(100.0/static_cast(image.width()*image.height()));
- cG.scale(100.0/static_cast(image.width()*image.height()));
- cB.scale(100.0/static_cast(image.width()*image.height()));
+ ds->scaleColumnValues(columnR, 100.0/static_cast(image.width()*image.height()));
+ ds->scaleColumnValues(columnG, 100.0/static_cast(image.width()*image.height()));
+ ds->scaleColumnValues(columnB, 100.0/static_cast(image.width()*image.height()));
```
Finally three `JKQTPFilledCurveXGraph` objects are generated and added to the plot (here we show the code for the R-channel only):
diff --git a/examples/simpletest_filledgraphs/jkqtplotter_simpletest_filledgraphs.cpp b/examples/simpletest_filledgraphs/jkqtplotter_simpletest_filledgraphs.cpp
index ccf5e005e1..6b8c0d2cf3 100644
--- a/examples/simpletest_filledgraphs/jkqtplotter_simpletest_filledgraphs.cpp
+++ b/examples/simpletest_filledgraphs/jkqtplotter_simpletest_filledgraphs.cpp
@@ -25,15 +25,10 @@ int main(int argc, char* argv[])
size_t columnR=ds->addColumn(256, "historam_R");
size_t columnG=ds->addColumn(256, "historam_G");
size_t columnB=ds->addColumn(256, "historam_B");
- // - in addition JKQTPColumn objects are generated, which can be used to access
- // the data in the columns
- JKQTPColumn cG=ds->getColumn(columnG);
- JKQTPColumn cR=ds->getColumn(columnR);
- JKQTPColumn cB=ds->getColumn(columnB);
// - now all columns for RGB are initialized to 0
- cR.setAll(0);
- cG.setAll(0);
- cB.setAll(0);
+ ds->setAll(columnG, 0);
+ ds->setAll(columnR, 0);
+ ds->setAll(columnB, 0);
// 3. now we open a BMP-file and load it into a QImage
QImage image(":/example.bmp");
@@ -41,15 +36,15 @@ int main(int argc, char* argv[])
for (int y=0; yinc(columnR, qRed(pix), 1);
+ ds->inc(columnG, qGreen(pix), 1);
+ ds->inc(columnB, qBlue(pix), 1);
}
}
// ... and normalize histograms
- cR.scale(100.0/static_cast(image.width()*image.height()));
- cG.scale(100.0/static_cast(image.width()*image.height()));
- cB.scale(100.0/static_cast(image.width()*image.height()));
+ ds->scaleColumnValues(columnR, 100.0/static_cast(image.width()*image.height()));
+ ds->scaleColumnValues(columnG, 100.0/static_cast(image.width()*image.height()));
+ ds->scaleColumnValues(columnB, 100.0/static_cast(image.width()*image.height()));
// 4. now we add three semi-transparent, filled curve plots, one for each histogram
diff --git a/lib/jkqtplotter/jkqtpbaseplotter.cpp b/lib/jkqtplotter/jkqtpbaseplotter.cpp
index 0cb1136132..adccb96f51 100644
--- a/lib/jkqtplotter/jkqtpbaseplotter.cpp
+++ b/lib/jkqtplotter/jkqtpbaseplotter.cpp
@@ -957,11 +957,11 @@ JKQTBasePlotter::JKQTPPen JKQTBasePlotter::getPlotStyle(int i) const{
p.setFillColor(JKQTPGetDerivedColor(plotterStyle.graphFillColorDerivationMode, p.color()));
p.setErrorLineColor(JKQTPGetDerivedColor(plotterStyle.graphErrorColorDerivationMode, p.color()));
p.setErrorFillColor(JKQTPGetDerivedColor(plotterStyle.graphErrorFillColorDerivationMode, p.errorColor()));
- p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, plotterStyle.defaultGraphWidth));
- p.setErrorLineWidth(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, plotterStyle.defaultGraphWidth));
- p.setSymbolSize(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, plotterStyle.defaultGraphSymbolSize));
+ p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, plotterStyle.defaultGraphWidth));
+ p.setErrorLineWidth(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, plotterStyle.defaultGraphWidth));
+ p.setSymbolSize(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, plotterStyle.defaultGraphSymbolSize));
p.setSymbolFillColor(JKQTPGetDerivedColor(plotterStyle.graphFillColorDerivationMode, p.color()));
- p.setSymbolLineWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, plotterStyle.defaultGraphSymbolLineWidth));
+ p.setSymbolLineWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, plotterStyle.defaultGraphSymbolLineWidth));
p.setStyle(plotterStyle.defaultGraphPenStyles[styleI]);
p.setSymbolType(plotterStyle.defaultGraphSymbols[symbolI]);
p.setFillStyle(plotterStyle.defaultGraphFillStyles[brushI]);
@@ -1088,7 +1088,7 @@ void JKQTBasePlotter::drawKey(JKQTPEnhancedPainter& painter) {
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
QPen pf=painter.pen();
pf.setColor(plotterStyle.keyStyle.frameColor);
- pf.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, pt2px(painter, plotterStyle.keyStyle.frameWidth*lineWidthMultiplier)));
+ pf.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, pt2px(painter, plotterStyle.keyStyle.frameWidth*lineWidthMultiplier)));
pf.setStyle(Qt::SolidLine);
painter.setBrush(plotterStyle.keyStyle.backgroundBrush);
@@ -1162,7 +1162,7 @@ void JKQTBasePlotter::drawPlot(JKQTPEnhancedPainter& painter, bool showOverlays)
if (plotterStyle.plotFrameVisible) {
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
QPen p(plotterStyle.plotFrameColor);
- p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, pt2px(painter, plotterStyle.plotFrameWidth*lineWidthMultiplier)));
+ p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, pt2px(painter, plotterStyle.plotFrameWidth*lineWidthMultiplier)));
painter.setPen(p);
painter.setBrush(plotterStyle.plotBackgroundBrush);
if (plotterStyle.plotFrameRounding<=0) {
diff --git a/lib/jkqtplotter/jkqtpcoordinateaxes.cpp b/lib/jkqtplotter/jkqtpcoordinateaxes.cpp
index 86ca151623..3bf7e70deb 100644
--- a/lib/jkqtplotter/jkqtpcoordinateaxes.cpp
+++ b/lib/jkqtplotter/jkqtpcoordinateaxes.cpp
@@ -1148,11 +1148,11 @@ void JKQTPVerticalAxis::drawGrids(JKQTPEnhancedPainter& painter) {
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
QPen pg=painter.pen();
pg.setColor(axisStyle.gridColor);
- pg.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.gridWidth*parent->getLineWidthMultiplier())));
+ pg.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.gridWidth*parent->getLineWidthMultiplier())));
pg.setStyle(axisStyle.gridStyle);
QPen pmg=painter.pen();
pmg.setColor(axisStyle.minorGridColor);
- pmg.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, axisStyle.minorGridWidth*parent->getLineWidthMultiplier())));
+ pmg.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, axisStyle.minorGridWidth*parent->getLineWidthMultiplier())));
pmg.setStyle(axisStyle.minorGridStyle);
//double top=x2p(axismax);
//double bottom=x2p(axismin);
@@ -1343,14 +1343,14 @@ void JKQTPVerticalAxis::drawAxes(JKQTPEnhancedPainter& painter) {
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
QPen pmain=painter.pen();
pmain.setColor(axisStyle.axisColor);
- pmain.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.lineWidth*parent->getLineWidthMultiplier())));
+ pmain.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.lineWidth*parent->getLineWidthMultiplier())));
pmain.setStyle(Qt::SolidLine);
QPen ptick=pmain;
- ptick.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.tickWidth*parent->getLineWidthMultiplier())));
+ ptick.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.tickWidth*parent->getLineWidthMultiplier())));
QPen pmtick=ptick;
- pmtick.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.minorTickWidth*parent->getLineWidthMultiplier())));
+ pmtick.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.minorTickWidth*parent->getLineWidthMultiplier())));
getParentMathText()->setFontSize(this->axisStyle.tickLabelFontSize*parent->getFontSizeMultiplier());
getParentMathText()->setFontRomanOrSpecial(getParent()->getCurrentPlotterStyle().defaultFontName);
@@ -1364,7 +1364,7 @@ void JKQTPVerticalAxis::drawAxes(JKQTPEnhancedPainter& painter) {
JKQTPAutoOutputTimer jkaat(QString("JKQTPEnhancedPainter[%1]::drawAxes(): 0Axis").arg(objectName()));
#endif
QPen pmain1=pmain;
- pmain1.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.lineWidthZeroAxis*parent->getLineWidthMultiplier())));
+ pmain1.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.lineWidthZeroAxis*parent->getLineWidthMultiplier())));
pmain1.setColor(axisStyle.colorZeroAxis);
pmain1.setStyle(axisStyle.styleZeroAxis);
painter.setPen(pmain1);
@@ -1771,11 +1771,11 @@ void JKQTPHorizontalAxis::drawGrids(JKQTPEnhancedPainter& painter) {
}
QPen pg=painter.pen();
pg.setColor(axisStyle.gridColor);
- pg.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.gridWidth*parent->getFontSizeMultiplier())));
+ pg.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.gridWidth*parent->getFontSizeMultiplier())));
pg.setStyle(axisStyle.gridStyle);
QPen pmg=painter.pen();
pmg.setColor(axisStyle.minorGridColor);
- pmg.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.minorGridWidth*parent->getLineWidthMultiplier())));
+ pmg.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.minorGridWidth*parent->getLineWidthMultiplier())));
pmg.setStyle(axisStyle.minorGridStyle);
double x=tickStart;
@@ -1926,14 +1926,14 @@ void JKQTPHorizontalAxis::drawAxes(JKQTPEnhancedPainter& painter) {
QPen pmain=painter.pen();
pmain.setColor(axisStyle.axisColor);
- pmain.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.lineWidth*parent->getLineWidthMultiplier())));
+ pmain.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.lineWidth*parent->getLineWidthMultiplier())));
pmain.setStyle(Qt::SolidLine);
QPen ptick=pmain;
- ptick.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.tickWidth*parent->getLineWidthMultiplier())));
+ ptick.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.tickWidth*parent->getLineWidthMultiplier())));
QPen pmtick=ptick;
- pmtick.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.minorTickWidth*parent->getLineWidthMultiplier())));
+ pmtick.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.minorTickWidth*parent->getLineWidthMultiplier())));
getParentMathText()->setFontSize(this->axisStyle.tickLabelFontSize*parent->getFontSizeMultiplier());
getParentMathText()->setFontRomanOrSpecial(getParent()->getCurrentPlotterStyle().defaultFontName);
@@ -1947,7 +1947,7 @@ void JKQTPHorizontalAxis::drawAxes(JKQTPEnhancedPainter& painter) {
JKQTPAutoOutputTimer jkaat(QString("JKQTPHorizontalAxis[%1]::drawAxes(): 0Axis").arg(objectName()));
#endif
QPen pmain1=pmain;
- pmain1.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.lineWidthZeroAxis*parent->getLineWidthMultiplier())));
+ pmain1.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, axisStyle.lineWidthZeroAxis*parent->getLineWidthMultiplier())));
pmain1.setColor(axisStyle.colorZeroAxis);
pmain1.setStyle(axisStyle.styleZeroAxis);
painter.setPen(pmain1);
diff --git a/lib/jkqtplotter/jkqtpdatastorage.cpp b/lib/jkqtplotter/jkqtpdatastorage.cpp
index 6dfcdc3f74..d6e1486fd7 100644
--- a/lib/jkqtplotter/jkqtpdatastorage.cpp
+++ b/lib/jkqtplotter/jkqtpdatastorage.cpp
@@ -22,7 +22,7 @@
#include "jkqtplotter/jkqtpdatastorage.h"
#include
#include
-
+#include
/**************************************************************************************************************************
* JKQTPColumn
@@ -34,23 +34,39 @@ JKQTPColumn::JKQTPColumn()
name="";
datastoreItem=0;
datastoreOffset=0;
+ imageColumns=1;
valid=false;
}
////////////////////////////////////////////////////////////////////////////////////////////////
-JKQTPColumn::JKQTPColumn(JKQTPDatastore *datastore, const QString &name, size_t datastoreItem, size_t datastoreOffset)
+JKQTPColumn::JKQTPColumn(JKQTPDatastore *datastore, const QString &name, size_t datastoreItem, size_t datastoreOffset, size_t imageColumns)
{
this->datastore=datastore;
this->datastoreItem=datastoreItem;
this->datastoreOffset=datastoreOffset;
+ this->imageColumns=imageColumns;
this->name=name;
valid=true;
}
////////////////////////////////////////////////////////////////////////////////////////////////
-JKQTPColumn::~JKQTPColumn()
-= default;
+void JKQTPColumn::setName(const QString &__value)
+{
+ this->name = __value;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+QString JKQTPColumn::getName() const
+{
+ return this->name;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+void JKQTPColumn::setImageColumns(size_t __value)
+{
+ imageColumns=__value;
+}
////////////////////////////////////////////////////////////////////////////////////////////////
size_t JKQTPColumn::getRows() const {
@@ -261,6 +277,11 @@ JKQTPDatastore::JKQTPDatastore()
clear();
}
+////////////////////////////////////////////////////////////////////////////////////////////////
+JKQTPDatastore::~JKQTPDatastore() {
+ clear();
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////
void JKQTPDatastore::clear(){
maxItemID=0;
@@ -310,6 +331,7 @@ void JKQTPDatastore::deleteAllPrefixedColumns(QString prefix, bool removeItems)
}
+
////////////////////////////////////////////////////////////////////////////////////////////////
void JKQTPDatastore::deleteColumn(size_t column, bool removeItems) {
if (removeItems) {
@@ -475,7 +497,31 @@ size_t JKQTPDatastore::addInternalColumn(double* data, size_t rows, const QStrin
//std::cout<<"adding column\n";
size_t it=addItem(new JKQTPDatastoreItem(JKQTPSingleColumn, data, 1, rows,true));
return addColumnForItem(it, 0, name);
-};
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+size_t JKQTPDatastore::addImageColumn(size_t width, size_t height, const QString &name)
+{
+ size_t col= addColumn(width*height, name);
+ columns[col].setImageColumns(width);
+ return col;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+size_t JKQTPDatastore::addImageColumn(double *data, size_t width, size_t height, const QString &name)
+{
+ size_t col= addColumn(data, width*height, name);
+ columns[col].setImageColumns(width);
+ return col;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+size_t JKQTPDatastore::addInternalImageColumn(double *data, size_t width, size_t height, const QString &name)
+{
+ size_t col= addInternalColumn(data, width*height, name);
+ columns[col].setImageColumns(width);
+ return col;
+}
@@ -524,6 +570,102 @@ size_t JKQTPDatastore::addLinearColumn(size_t rows, double start, double end, co
return addColumnForItem(itemid, 0, name);
}
+////////////////////////////////////////////////////////////////////////////////////////////////
+size_t JKQTPDatastore::addLogColumn(size_t rows, double start, double end, const QString &name)
+{
+ JKQTPDatastoreItem* it=new JKQTPDatastoreItem(1, rows);
+ const double x0=log(start)/log(10.0);
+ const double x1=log(end)/log(10.0);
+ for (size_t i=0; iset(0, i, pow(10.0, x0+static_cast(i)/static_cast(rows-1)*(x1-x0)));
+ }
+ size_t itemid= addItem(it);
+ return addColumnForItem(itemid, 0, name);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+size_t JKQTPDatastore::addDecadeLogColumn(size_t rows, double startDecade, double endDecade, const QString &name)
+{
+ JKQTPDatastoreItem* it=new JKQTPDatastoreItem(1, rows);
+ const double x0=startDecade;
+ const double x1=endDecade;
+ for (size_t i=0; iset(0, i, pow(10.0, x0+static_cast(i)/static_cast(rows-1)*(x1-x0)));
+ }
+ size_t itemid= addItem(it);
+ return addColumnForItem(itemid, 0, name);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+std::pair JKQTPDatastore::addLinearGridColumns(size_t width, double startX, double endX, size_t height, double startY, double endY, const QString &nameX, const QString &nameY)
+{
+ const double decX=(endX-startX)/static_cast(width-1);
+ const double decY=(endY-startY)/static_cast(height-1);
+ double y=startY;
+ size_t cx=addColumn(width*height, nameX);
+ size_t cy=addColumn(width*height, nameY);
+ size_t i=0;
+ for (size_t iy=0; iy &f, const QString &name)
+{
+ JKQTPDatastoreItem* it=new JKQTPDatastoreItem(1, rows);
+ for (size_t i=0; iset(0, i, f(i, this));
+ }
+ size_t itemid= addItem(it);
+ return addColumnForItem(itemid, 0, name);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+size_t JKQTPDatastore::addCalculatedColumn(size_t rows, const std::function &f, const QString &name)
+{
+ JKQTPDatastoreItem* it=new JKQTPDatastoreItem(1, rows);
+ for (size_t i=0; iset(0, i, f(i));
+ }
+ size_t itemid= addItem(it);
+ return addColumnForItem(itemid, 0, name);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+size_t JKQTPDatastore::addColumnCalculatedFromColumn(size_t otherColumn, const std::function &f, const QString &name)
+{
+ const JKQTPColumn& oc=columns.value(otherColumn);
+ JKQTPDatastoreItem* it=new JKQTPDatastoreItem(1, oc.getRows());
+ for (size_t i=0; iset(0, i, f(oc.getValue(i)));
+ }
+ size_t itemid= addItem(it);
+ return addColumnForItem(itemid, 0, name);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+size_t JKQTPDatastore::addColumnCalculatedFromColumn(size_t otherColumnX, size_t otherColumnY, const std::function &f, const QString &name)
+{
+ const JKQTPColumn& ocx=columns.value(otherColumnX);
+ const JKQTPColumn& ocy=columns.value(otherColumnY);
+ const size_t N= qMin(ocx.getRows(), ocy.getRows());
+ JKQTPDatastoreItem* it=new JKQTPDatastoreItem(1, N);
+ for (size_t i=0; iset(0, i, f(ocx.getValue(i), ocy.getValue(i)));
+ }
+ size_t itemid= addItem(it);
+ return addColumnForItem(itemid, 0, name);
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////
int JKQTPDatastore::getNextLowerIndex(size_t column, size_t row, int start, int end) const
@@ -938,7 +1080,7 @@ QVariant JKQTPDatastoreModel::data(const QModelIndex &index, int role) const {
if (datastore) {
if (role==Qt::DisplayRole || role==Qt::EditRole) {
int col=static_cast(datastore->getColumnIDs().value(column, -1));
- if (col>-1 && row>=0 && row(datastore->getColumn(col).getRows())) {
+ if (col>-1 && row>=0 && row(datastore->getRows(col))) {
return datastore->get(col, static_cast(row));
}
}
diff --git a/lib/jkqtplotter/jkqtpdatastorage.h b/lib/jkqtplotter/jkqtpdatastorage.h
index 0257344c15..6689ee00ce 100644
--- a/lib/jkqtplotter/jkqtpdatastorage.h
+++ b/lib/jkqtplotter/jkqtpdatastorage.h
@@ -82,6 +82,8 @@ enum JKQTPDatastoreItemFormat {
/** \brief This class manages chunks of memory that are used for column data in JKQTBasePlotter descendents
* \ingroup jkqtpdatastorage
*
+ * \see \ref JKQTPlotterAdvancedJKQTPDatastore for a detailed description of how to use this class for data management!
+ *
* This class manages a list if JKQTPDatastoreItem onjects that may each contain a chunk of memory, containig
* one or more columns of data. Each item can be accessed with get() by a specific ID which is returned by add().
* JKQTPColumn. You may only clear all chunks of memory/items. If you no longer need some of the data, but still want
@@ -135,17 +137,37 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
/** \brief add a new column to the datastore and return its ID */
size_t addColumn(JKQTPColumn col);
+ /** \brief add a new item to the datastore and return its ID
+ * This function retuns an item ID (which can be used with getItem() ), not a column ID! */
+ size_t addItem(JKQTPDatastoreItem* item);
- public:
- /** \brief class constructor, generates an empty datastore */
- JKQTPDatastore();
- /** \brief class destructor, destroys all subordered JKQTPDatastoreItem objects */
- ~JKQTPDatastore() {
- clear();
- }
- /** \brief deletes all items from the datastore and possibly frees the memory they manage */
- void clear();
+ /** \brief add a new columns/item with \a rows rows to the datastore and return its ID. The item uses internal memory management.
+ * This function retuns an item ID (which can be used with getItem() ), not a column ID! */
+ size_t addItem(size_t rows);
+
+ /** \brief add a new item with \a rows rows and \a columns columns to the datastore and return its ID. The item uses internal memory management.
+ * This function retuns an item ID (which can be used with getItem() ), not a column ID! */
+ size_t addItem(size_t columns, size_t rows);
+
+ /** \brief add one external column to the datastore. It contains \a rows rows.
+ * This function retuns an item ID (which can be used with getItem() ), not a column ID! */
+ size_t addItem(double* data, size_t rows);
+ /** \brief add one internal column to the datastore. It contains \a rows rows.
+ * This function retuns an item ID (which can be used with getItem() ), not a column ID! */
+ size_t addInternalItem(double* data, size_t rows);
+
+ /** \brief add one external column to the datastore. It contains \a rows rows. The data is copied and the copy managed internally
+ * This function retuns an item ID (which can be used with getItem() ), not a column ID! */
+ size_t addCopiedItem(const double *data, size_t rows);
+
+ /** \brief add an external memory block to the datastore. It contains \a rows rows and \a columns columns. \a dataformat determined the memory layout.
+ * This function retuns an item ID (which can be used with getItem() ), not a column ID! */
+ size_t addItem(JKQTPDatastoreItemFormat dataformat, double* data, size_t columns, size_t rows);
+
+ /** \brief add one external data block to the datastore. It contains \a rows rows and \a columns columns. The data is copied and the copy managed internally
+ * This function retuns an item ID (which can be used with getItem() ), not a column ID! */
+ size_t addCopiedItem(JKQTPDatastoreItemFormat dataformat, double* data, size_t columns, size_t rows);
/** \brief returns the JKQTPDatastoreItem object for the \a i -th item in the store */
inline JKQTPDatastoreItem* getItem(size_t i) {
@@ -157,12 +179,38 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
return items.value(i, nullptr);
}
- /** \brief add a new item to the datastore and return its ID */
- size_t addItem(JKQTPDatastoreItem* item);
+ /** \brief add a new columns which references a specified item and a specified column therein.
+ * \see \ref JKQTPlotterAdvancedJKQTPDatastore
+ */
+ size_t addColumnForItem(size_t itemID, size_t columnInItem, const QString& name=QString(""));
+
+ /** \brief returns the JKQTPColumn object for the \a i -th column in the store
+ *
+ * \warning This function copies the pointers/references to the internal data into a new object.
+ * Therefore you should delete it as soon as possible and not store the return value over long durations,
+ * as the data may get moved in the meantime and then the object gets invalid, but is not informed of this fact!
+ */
+ JKQTPColumn getColumn(size_t i) const;
- /** \brief add a new columns/item with \a rows rows to the datastore and return its ID. The item uses internal memory management. */
- size_t addItem(size_t rows);
+ /** \brief returns the JKQTPColumn object for the \a i -th column in the store
+ *
+ * \warning This function copies the pointers/references to the internal data into a new object.
+ * Therefore you should delete it as soon as possible and not store the return value over long durations,
+ * as the data may get moved in the meantime and then the object gets invalid, but is not informed of this fact!
+ */
+ JKQTPColumn getColumn(int i) const;
+ public:
+ /** \brief class constructor, generates an empty datastore */
+ JKQTPDatastore();
+ /** \brief class destructor, destroys all subordered JKQTPDatastoreItem objects */
+ ~JKQTPDatastore();
+
+
+
+ /** \brief deletes all items from the datastore and possibly frees the memory they manage */
+ void clear();
+
/** \brief delete the given column, if no other columns points to the datastore item of the column and \a removeItems is \c true, the item will be removed */
void deleteColumn(size_t column, bool removeItems=true);
@@ -173,24 +221,24 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
/** \brief delete all columns where the name starts with a given prefix, if no other columns points to the datastore item of the column and \a removeItems is \c true, the item will be removed */
void deleteAllPrefixedColumns(QString prefix, bool removeItems=true);
- /** \brief add a new item with \a rows rows and \a columns columns to the datastore and return its ID. The item uses internal memory management. */
- size_t addItem(size_t columns, size_t rows);
-
- /** \brief add one external column to the datastore. It contains \a rows rows.*/
- size_t addItem(double* data, size_t rows);
- /** \brief add one internal column to the datastore. It contains \a rows rows.*/
- size_t addInternalItem(double* data, size_t rows);
-
- /** \brief add an external memory block to the datastore. It contains \a rows rows and \a columns columns. \a dataformat determined the memory layout*/
- size_t addItem(JKQTPDatastoreItemFormat dataformat, double* data, size_t columns, size_t rows);
-
- /** \brief add one external column to the datastore. It contains \a rows rows. The data is copied and the copy managed internally */
- size_t addCopiedItem(const double *data, size_t rows);
-
- /** \brief add one external data block to the datastore. It contains \a rows rows and \a columns columns. The data is copied and the copy managed internally */
- size_t addCopiedItem(JKQTPDatastoreItemFormat dataformat, double* data, size_t columns, size_t rows);
-
+ /** \brief returns the number of rows in the column \a column */
+ inline size_t getRows(size_t column) const;
+ /** \brief returns a pointer to the data in column \a column, starting ar row \a row */
+ inline const double* getColumnPointer(size_t column, size_t row=0) const;
+ /** \brief returns a pointer to the data in column \a column, starting ar row \a row */
+ inline double* getColumnPointer(size_t column, size_t row=0);
+ /** \brief returns the number of rows in the column \a column */
+ inline size_t getRows(int column) const;
+ /** \brief returns a pointer to the data in column \a column, starting ar row \a row */
+ inline const double* getColumnPointer(int column, size_t row=0) const;
+ /** \brief returns a pointer to the data in column \a column, starting ar row \a row */
+ inline double* getColumnPointer(int column, size_t row=0);
+ /** \brief returns the width of the image, represented by \a column (in row-major ordering).
+ * Internally this returns the imageColumns or image width, if set in the column */
+ inline size_t getColumnImageWidth(int column);
+ /** \brief returns the height of the image, represented by \a column (in row-major ordering) */
+ inline size_t getColumnImageHeight(int column);
/** \brief returns the value at position (\c column, \c row). \c column is the logical column and will be mapped to the according memory block internally!) */
inline double get(size_t column, size_t row) const ;
@@ -201,7 +249,7 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
inline double get(int column, int row) const ;
/** \brief returns the value at position (\c column, \c row). \c column is the logical column and will be mapped to the according memory block internally!) */
inline double get(size_t column, int row) const ;
- /** \brief gets the index of the datapoint with the nearest, but lower value in the column (in a given inclusive row range [start ... end] values of -1 for the ranges are "wildcards", i.e. start/end of column)*/
+ /** \brief gets the index of the datapoint with the nearest, but lower value in the column (in a given inclusive row range [start ... end] values of -1 for the ranges are "wildcards", i.e. start/end of column)*/
int getNextLowerIndex(size_t column, size_t row, int start, int end) const;
/** \brief gets the index of the datapoint with the nearest, but lower value in the column */
int getNextLowerIndex(size_t column, size_t row) const;
@@ -209,11 +257,6 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
int getNextHigherIndex(size_t column, size_t row, int start, int end) const;
/** \brief gets the index of the datapoint with the nearest, but higher value in the column */
int getNextHigherIndex(size_t column, size_t row) const;
-
- /** \brief sets the value at position (\c column, \c row). \c column is the logical column and will be mapped to the according memory block internally!) */
- inline void set(size_t column, size_t row, double value);
- /** \brief sets the value at position (\c column, \c row). \c column is the logical column and will be mapped to the according memory block internally!) */
- inline void set(int column, size_t row, double value);
/** \brief gets the index of the datapoint with the nearest, but lower value in the column (in a given inclusive row range [start ... end] values of -1 for the ranges are "wildcards", i.e. start/end of column)*/
int getNextLowerIndex(int column, size_t row, int start, int end) const;
/** \brief gets the index of the datapoint with the nearest, but lower value in the column */
@@ -223,24 +266,153 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
/** \brief gets the index of the datapoint with the nearest, but higher value in the column */
int getNextHigherIndex(int column, size_t row) const;
+ /** \brief sets the value at position (\c column, \c row). \c column is the logical column and will be mapped to the according memory block internally!) */
+ inline void set(size_t column, size_t row, double value);
+ /** \brief sets the value at position (\c column, \c row). \c column is the logical column and will be mapped to the according memory block internally!) */
+ inline void set(int column, size_t row, double value);
+ /** \brief returns the value at position (\c x, \c y) in the \a column-th column, which is interpreted with the imageWidth stored in that column */
+ inline double getPixel(size_t column, size_t x, size_t y) const ;
+ /** \brief returns the value at position (\c x, \c y) in the \a column-th column, which is interpreted with the imageWidth stored in that column */
+ inline void setPixel(size_t column, size_t x, size_t y, double value) ;
+ /** \brief sets all entries in column \a column to \a value
+ *
+ * \see \ref JKQTPlotterFilledGraphs
+ */
+ inline void setAll(size_t column, double value);
+ /** \brief scales (multiplies) all entries in column \a column by \a factor
+ *
+ * \see \ref JKQTPlotterFilledGraphs
+ */
+ inline void scaleColumnValues(size_t column, double factor);
+ /** \brief increases entry in row \a row of column \a column by \a increment
+ *
+ * \see \ref JKQTPlotterFilledGraphs
+ */
+ inline void inc(size_t column, size_t row, double increment=1);
+ /** \brief decrements entry in row \a row of column \a column by \a decrement
+ *
+ * \see \ref JKQTPlotterFilledGraphs
+ */
+ inline void dec(size_t column, size_t row, double decrement=1);
- /** \brief add a new columns which references a specified item and a specified column therein. */
- size_t addColumnForItem(size_t itemID, size_t columnInItem, const QString& name=QString(""));
- /** \brief add a new columns with \a rows rows to the datastore and return its column ID. The new item uses internal memory management. */
+ /** \brief add a new columns with \a rows rows to the datastore and return its column ID. The new item uses internal memory management.
+ * \param rows number of rows in the data array
+ * \param name name for the column
+ * \return the ID of the newly created column
+ * \see \ref JKQTPlotterAdvancedJKQTPDatastore
+ */
size_t addColumn(size_t rows, const QString& name=QString(""));
- /** \brief add one external column to the datastore. It contains \a rows rows. This returns its logical column ID.*/
+ /** \brief add one external column to the datastore. It contains \a rows rows. This returns its logical column ID.
+ * Data is not owned by the JKQTPDatastore!
+ *
+ * \param data data array to be copied
+ * \param rows number of rows in the data array
+ * \param name name for the column
+ * \return the ID of the newly created column
+ *
+ * \code
+ * #define NDATA 5
+ * double XCA[NDATA]= { 1, 2, 3, 4, 5 };
+ * double YCA[NDATA]= { 1, 0, 1, 0, 1 };
+ * plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
+ * linegraph->setXColumn(datastore->addColumn(XCA, NDATA, "xca (C-array)"));
+ * linegraph->setYColumn(datastore->addColumn(YCA, NDATA, "yca (C-array)"));
+ * \endcode
+ * \see \ref JKQTPlotterAdvancedJKQTPDatastore
+ */
size_t addColumn(double* data, size_t rows, const QString& name=QString(""));
+ /** \brief add a column with \a rows entries from the array \a data,
+ * ownership of the memory behind \a data is transfered to the datastore
+ *
+ * \param data data array to be copied
+ * \param rows number of rows in the data array
+ * \param name name for the column
+ * \return the ID of the newly created column
+ *
+ * \code
+ * #define NDATA 5
+ * double* XCA=(double*)malloc(NDATA, sizeof(double));
+ * double* YCA=(double*)malloc(NDATA, sizeof(double));
+ * ...
+ * plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
+ * linegraph->setXColumn(datastore->addInternalColumn(XCA, NDATA, "x"));
+ * linegraph->setXColumn(datastore->addInternalColumn(YCA, NDATA, "y"));
+ * \endcode
+ * \see \ref JKQTPlotterAdvancedJKQTPDatastore
+ */
+ size_t addInternalColumn(double *data, size_t rows, const QString& name);
+
+
+ /** \brief add a new columns with \a width * \a height rows to the datastore and return its column ID. The new item uses internal memory management.
+ * The column is meant to represent an image in row-major order with x-dimention \a width and y-dimension \a height .
+ *
+ * \param width width of the image represented by the data array
+ * \param height height of the image represented by the data array
+ * \param name name for the column
+ * \return the ID of the newly created column
+ * \see addImageColumn(), addInternalImageColumn(), \ref JKQTPlotterAdvancedJKQTPDatastore
+ */
+ size_t addImageColumn(size_t width, size_t height, const QString& name=QString(""));
+
+ /** \brief add one external column to the datastore. It contains \a width * \a height rows. This returns its logical column ID.
+ * Data is not owned by the JKQTPDatastore!
+ * The column is meant to represent an image in row-major order with x-dimention \a width and y-dimension \a height .
+ *
+ *
+ * \param data data array to be copied
+ * \param width width of the image represented by the data array
+ * \param height height of the image represented by the data array
+ * \param name name for the column
+ * \return the ID of the newly created column
+ *
+ * \see addColumn(), addImageColumn(), addInternalImageColumn(), \ref JKQTPlotterAdvancedJKQTPDatastore
+ */
+ size_t addImageColumn(double* data, size_t width, size_t height, const QString& name=QString(""));
+ /** \brief add a column with \a width * \a height entries from the array \a data,
+ * ownership of the memory behind \a data is transfered to the datastore
+ * The column is meant to represent an image in row-major order with x-dimention \a width and y-dimension \a height .
+ *
+ *
+ * \param data data array to be copied
+ * \param width width of the image represented by the data array
+ * \param height height of the image represented by the data array
+ * \param name name for the column
+ * \return the ID of the newly created column
+ *
+ * \see addInternalColumn(), addImageColumn(), addInternalImageColumn(), \ref JKQTPlotterAdvancedJKQTPDatastore
+ */
+ size_t addInternalImageColumn(double *data, size_t width, size_t height, const QString& name);
-
-
- /** \brief copies the given \a old_column into a new one, reading the data with the given start column and stride */
+ /** \brief copies the given \a old_column into a new one, reading the data with the given start column and stride
+ *
+ * \param old_column the column to be duplicated
+ * \param start for row in column \a old_column to copy
+ * \param stride stride for iterating through \a old_column when copying
+ * \param name name for the new column
+ * \return ID of the newly created column
+ *
+ * Pseuo-Code:
+ * \code
+ * newColumn=addColumn(rowcount(old_column), name)
+ * forall ( r: rows(old_column)) {
+ * set(newColumn, r, get(old_column, r))
+ * }
+ * return newColumn;
+ * \endcode
+ */
size_t copyColumn(size_t old_column, size_t start, size_t stride, const QString& name=QString(""));
- /** \brief copies the given \a old_column into a new one */
+ /** \brief copies the given \a old_column into a new one
+ *
+ * \param old_column the column to be duplicated
+ * \param name name for the new column
+ * \return ID of the newly created column
+ * \see \ref JKQTPlotterAdvancedJKQTPDatastore
+ */
size_t copyColumn(size_t old_column, const QString& name=QString(""));
@@ -250,6 +422,22 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
* \param data data vector to be copied
* \param name name for the column
* \return the ID of the newly created column
+ *
+ * \code
+ * QVector X, Y;
+ * const int Ndata=100;
+ * for (int i=0; isetXColumn(datastore->addCopiedColumn(X, "x"));
+ * linegraph->setYColumn(datastore->addCopiedColumn(Y, "y"));
+ * \endcode
+ *
+ * \see \ref JKQTPlotterAdvancedJKQTPDatastore
*/
template
size_t addCopiedColumn(const TContainer& data, const QString& name=QString("")) {
@@ -270,11 +458,24 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
/** \brief add one external column to the datastore. It will be filled with the contents of vector \a data.
*
* \tparam TContainer datatype of the container, which need to support standard C++ iterators and the function \c size(). The contents needs to be convertible to double.
+ * The iterator of TContainer needs to support \c ++ and \c +=
* \param data data vector to be copied
* \param name name for the column
* \param stride strides through the container \a data with the given stride
* \param start starts copying from \a data with the element \a start
* \return the ID of the newly created column
+ *
+ * Pseudocode:
+ * \code
+ * it=data.begin();
+ * it += start; // shift by start items
+ * while (it!=data.end()) {
+ * newColumn.push_back(jkqtp_todouble(*it));
+ * it += stride;
+ * }
+ * \endcode
+ *
+ * \see \ref JKQTPlotterAdvancedJKQTPDatastore
*/
template
size_t addCopiedColumn(const TContainer& data, const QString& name, size_t stride, size_t start=0) {
@@ -304,6 +505,7 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
* \return the ID of the newly created column
*
* \note This function converts the input array \a data into an array of double!
+ * \see \ref JKQTPlotterAdvancedJKQTPDatastore
*/
template
size_t addCopiedColumn(const T* data, size_t rows, const QString& name=QString("")){
@@ -328,7 +530,15 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
* \param name name for the column
* \return the ID of the newly created column
*
+ * Pseudocode:
+ * \code
+ * for (i=start; i
size_t addCopiedColumn(const T* data, size_t rows, size_t stride, int start, const QString& name) {
@@ -351,7 +561,16 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
* \param stride when copying, this function steps throught the data with the given stride, so only eleemnts [0, stride, 2*stride, ... (rows-1)*stride]
are copied!
* \return the ID of the newly created column
*
+ *
+ * Pseudocode:
+ * \code
+ * for (i=0; i
size_t addCopiedColumn(const T* data, size_t rows, size_t stride, const QString& name) {
@@ -362,49 +581,60 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
/** \brief add one external column to the datastore. It contains \a width * \a height rows. The external data is assumed to be organized as a row-major image and is copied as such. The external data is copied to an internal array, so
* afterwards you can delete the external arrayThis returns its logical column ID.*/
template
- inline size_t addCopiedImageAsColumn(const T* data, size_t width, size_t height, const QString& name=QString(""), size_t stride=1, size_t start=0){
- return addCopiedColumn(data, width*height, stride, start, name);
- }
+ inline size_t addCopiedImageAsColumn(const T* data, size_t width, size_t height, const QString& name=QString(""), size_t stride=1, size_t start=0);
/** \brief add one external column to the datastore. It contains \a width * \a height rows. The external data is assumed to be organized as a row-major image and is copied as such. The external data is copied to an internal array, so
- * afterwards you can delete the external arrayThis returns its logical column ID.*/
+ * afterwards you can delete the external arrayThis returns its logical column ID.
+ *
+ * \tparam TContainer datatype of the container, which need to support standard C++ iterators and the function \c size(). The contents needs to be convertible to double.
+ * \param data data vector to be copied
+ * \param width width of the image, stored in \a data
+ * \param name name for the column
+ * \return the ID of the newly created column
+ */
template
- inline size_t addCopiedImageAsColumn(const TContainer& data, const QString& name=QString("")){
- return addCopiedColumn(data, name);
- }
+ inline size_t addCopiedImageAsColumn(const TContainer& data, size_t width, const QString& name=QString(""));
- /** \brief add one external column to the datastore. It contains \a width * \a height rows. The external data is assumed to be organized as a column-major image and is copied as row-major (i.e. is transposed). The external data is copied to an internal array, so
- * afterwards you can delete the external arrayThis returns its logical column ID.*/
+ /** \brief add a new column to the datastore, which is filled from the transposed column-major array \a data with
+ * the given \a width and \a height.
+ *
+ * The external data is assumed to be organized as a column-major image and is copied as row-major (i.e. is transposed).
+ * The external data is copied to an internal array, so afterwards you can delete the external arrayThis returns its logical column ID.
+ *
+ * \tparam T data type of the array \a data, needs to be convertible to \c double by jkqtp_todouble()
+ * \param data a column major image
+ * \param width width of \a data
+ * \param height height of \a data
+ * \param name name of the new column
+ * \param stride stride to use, when reading \a data. Use this to e.g. read one channel from a packed RGB-image (\c stride=3, \c start=0/1/2 )
+ * \param start first entry from \a data top copy \a data. Use this to e.g. read one channel from a packed RGB-image (\c stride=3, \c start=0/1/2 )
+ * \return ID of the newly added column
+ */
template
- size_t addCopiedImageAsColumnTranspose(const T* data, size_t width, size_t height, const QString& name=QString(""), size_t stride=1, size_t start=0){
- double* temp=static_cast(malloc(width*height*sizeof(T)));
-
- for (size_t x=0; x
- inline size_t addCopiedImageAsColumnTranspose(const QVector& data, size_t width, const QString& name=QString("")){
- return addCopiedImageAsColumnTranspose(data.data(), width, static_cast(data.size())/width, name);
- }
-
+ inline size_t addCopiedImageAsColumnTranspose(const QVector& data, size_t width, const QString& name=QString(""));
/** \brief add one external column to the datastore. It contains \a rows rows. The external data is copied to an internal array, so
* afterwards you can delete the external arrayThis returns its logical column ID.
*
* \note This function converts the input array \a data into an array of double!
+ * \see \ref JKQTPlotterAdvancedJKQTPDatastore
*/
template
size_t addCopiedColumnMasked(const T* data, const bool* mask, size_t rows, const QString& name=QString(""), bool useIfMaskEquals=false) {
@@ -420,19 +650,31 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
}
- size_t col= addCopiedColumn(d, rrs, name);
- free(d);
+ size_t col= addInternalColumn(d, rrs, name);
return col;
}
/** \brief add one external column to the datastore. It will be filled with the contents of vector \a data.
*
- * \tparam TContainer datatype of the container, which need to support standard C++ iterators and the function \c size(). The contents needs to be convertible to double.
+ * \tparam TContainer datatype of the container \a data, which need to support standard C++ iterators and the function \c size(). The contents needs to be convertible to double.
+ * \tparam TContainerMask datatype of the container \a mask, which need to support standard C++ iterators and the function \c size(). The contents needs to be convertible to bool.
* \param data data vector to be copied
+ * \param mask data vector to be copied
* \param name name for the column
* \param stride strides through the container \a data with the given stride
* \param start starts copying from \a data with the element \a start
* \return the ID of the newly created column
+ * \see \ref JKQTPlotterAdvancedJKQTPDatastore
+ *
+ * Pseudocode:
+ * \code
+ * for (i=0; i(mask[i])==useIfMaskEquals) {
+ * newColumn.push_back(jkqtp_todouble(data[i]));
+ * }
+ * }
+ * return newColumn;
+ * \endcode
*/
template
size_t addCopiedColumnMasked(const TContainer& data, const TContainerMask& mask, const QString& name=QString(""), bool useIfMaskEquals=false) {
@@ -443,7 +685,7 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
auto itmask=mask.begin();
auto itdata=data.begin();
for (size_t r=0; r(*itmask)==useIfMaskEquals) {
d[rrs]=jkqtp_todouble(*itdata);
rrs++;
}
@@ -451,42 +693,149 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
++itdata;
}
}
-
-
- size_t col= addCopiedColumn(d, rrs, name);
- free(d);
+ size_t col= addInternalColumn(d, rrs, name);
return col;
}
/** \brief copies the contents of the map-like container \a c into two columns of the datastore,
- * returns the two IDs of the items as a std::pair */
+ * returns the two IDs of the items as a std::pair
+ * \see \ref JKQTPlotterAdvancedJKQTPDatastore, jkqtp_todouble()
+ *
+ * \tparam TContainer datatype of the map-typed container (e.g. \c std::map or \c QMap ) The requiremen to this container is
+ * that it supports standard iterators with \c begin() and \c end() .
+ * \param c the map to copy to the datastore
+ * \param nameKey name for the column with the map keys
+ * \param nameValue name for the column with the map values
+ * \return a pair of IDs to the newly created columns (IDkeyColumn, IDvalueColumn)
+ * Example of usage:
+ * \code
+ * std::map datamap;
+ * datamap[1]=1.1;
+ * datamap[2]=1.4;
+ * datamap[4]=1.2;
+ * datamap[5]=1.8;
+ * datamap[7]=0.9;
+ * plot.addGraph(linegraph=new JKQTPXYLineGraph(&plot));
+ * linegraph->setXYColumns(datastore->addCopiedMap(datamap, "map_x", "map_y"));
+ * linegraph->setTitle(QObject::tr("copied map"));
+ * \endcode
+ */
template
std::pair addCopiedMap(const TContainer& c, const QString& nameKey=QString("map_key"), const QString& nameValue=QString("map_value")) {
- std::vector xvals;
- std::vector yvals;
+ const size_t N=std::distance(c.begin(), c.end());
+ double* xvals=static_cast(malloc(N*sizeof(double)));
+ double* yvals=static_cast(malloc(N*sizeof(double)));
+ size_t i=0;
for (auto it=c.begin(); it!=c.end(); ++it) {
- xvals.push_back(jkqtp_todouble(it->first));
- yvals.push_back(jkqtp_todouble(it->second));
+ xvals[i]=(jkqtp_todouble(it->first));
+ yvals[i]=(jkqtp_todouble(it->second));
+ i++;
}
- return std::make_pair(
- addCopiedColumn(xvals, nameKey),
- addCopiedColumn(yvals, nameValue)
- );
+ const size_t cx=addInternalColumn(xvals, N, nameKey);
+ const size_t cy=addInternalColumn(yvals, N, nameValue);
+ return std::pair(cx,cy);
}
- /** \brief add a column to the datastore that contains \a rows rows with increasing value starting at \a start and ending at \a end.
- * the values are equidistant between \a start end \a end */
+ /** \brief add a column to the datastore that contains \a rows rows with monotonely increasing value starting at \a start and ending at \a end.
+ * the values are equidistant between \a start end \a end
+ * \see addLogColumn(), addDecadeLogColumn(), \ref JKQTPlotterAdvancedJKQTPDatastore
+ */
size_t addLinearColumn(size_t rows, double start, double end, const QString& name=QString(""));
+ /** \brief add a column to the datastore that contains \a rows rows with monotonely increasing value starting at \a start and ending at \a end.
+ * the values are logarithmically spaced between \a start end \a end
+ * \see addLinearColumn(), addDecadeLogColumn(), \ref JKQTPlotterAdvancedJKQTPDatastore
+ */
+ size_t addLogColumn(size_t rows, double start, double end, const QString& name=QString(""));
+ /** \brief add a column to the datastore that contains \a rows rows with monotonely increasing value starting at 10^start and ending at 10^end.
+ * the values are logarithmically spaced between 10^start end 10^end
+ * \see addLinearColumn(), addLogColumn(), \ref JKQTPlotterAdvancedJKQTPDatastore
+ */
+ size_t addDecadeLogColumn(size_t rows, double startDecade, double endDecade, const QString& name=QString(""));
+
+
+ /** \brief add two columns to the datastore that contains the x- and y- coordinates of a rectangular grid with \a width points in x- and \a height
+ * points in y-direction.
+ *
+ * \param width number of columns in the mesh grid
+ * \param startX x-coordinate of the first column of the mesh grid
+ * \param endX x-coordinate of the last column of the mesh grid
+ * \param height number of rows in the mesh grid
+ * \param startY y-coordinate of the first row of the mesh grid
+ * \param endY y-coordinate of the last row of the mesh grid
+ * \param nameX name for the x-coordinate column
+ * \param nameY name for the y-coordinate column
+ * \return IDs of two column that contain the x- and y- coordinates od the mesh points (in row-major order), where the
+ * x-coordinates are linearly distributed between \a startX and \a endX and the x-coordinates are linearly
+ * distributed between \a startY and \a endY .
+ *
+ * \see addLogGridColumns(), addDecadeLogGridColumns(), addColumnCalculatedFromColumn(), JKQTPXYParametrizedScatterGraph, \ref JKQTPlotterAdvancedJKQTPDatastore
+ */
+ std::pair addLinearGridColumns(size_t width, double startX, double endX, size_t height, double startY, double endY, const QString& nameX=QString(""), const QString& nameY=QString(""));
+
+
+ /** \brief add a column with \a rows entries, that is calculated by calling \a f for each entry
+ *
+ * Pseudocode:
+ * \code
+ * for (i=0; i& f, const QString& name=QString(""));
+ /** \brief add a column with \a rows entries, that is calculated by calling \a f for each entry
+ *
+ * Pseudocode:
+ * \code
+ * for (i=0; i& f, const QString& name=QString(""));
+ /** \brief add a column with the same number of entries, as in the other column \a otherColumn , that are calculated by calling \a f for each entry in \a otherColumn
+ *
+ * Pseudocode:
+ * \code
+ * for (i=0; i& f, const QString& name=QString(""));
+ /** \brief add a column with the same number of entries, as in the other column \a otherColumn , that are calculated by calling \a f for each pair of entries in \a otherColumnX and \a otherColumnY
+ *
+ * Pseudocode:
+ * \code
+ * for (i=0; i& f, const QString& name=QString(""));
/** \brief returns the number of (logical) columns currently managed by the datastore */
inline size_t getColumnCount() { return static_cast(columns.size()); }
+ /** \brief returns a list with all available column IDs */
inline QList getColumnIDs() { return columns.keys(); }
/** \brief return the num of the first column with the given name, or -1 if none was found */
@@ -495,12 +844,6 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
/** \brief return the num of the first column with the given name, if none was found this creates a new column with no rows and returns its num */
int ensureColumnNum(const QString& name);
- /** \brief returns the JKQTPColumn object for the \a i -th column in the store */
- JKQTPColumn getColumn(size_t i) const;
-
-
- /** \brief returns the JKQTPColumn object for the \a i -th column in the store */
- JKQTPColumn getColumn(int i) const;
/** \brief returns the maximum number of rows in all columns */
size_t getMaxRows();
@@ -580,9 +923,10 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{
/** \brief return a list with all columns available in the datastore */
QStringList getColumnNames() const;
- /** \brief add a column with \a rows entries from the array \a data,
- * ownership of the memory behind \a data is transfered to the datastore */
- size_t addInternalColumn(double *data, size_t rows, const QString& name);
+
+ friend class JKQTPColumn;
+ friend class JKQTPDatastoreItem;
+ friend class JKQTPDatastoreModel;
};
@@ -603,8 +947,10 @@ class JKQTP_LIB_EXPORT JKQTPColumn {
QString name;
/** \brief pointer to the datastore object used to manage the data of the plot */
JKQTPDatastore* datastore;
-
+ /** \brief is this item valid?/usable? */
bool valid;
+ /** \brief number of columns, if interpreted as a row-major image */
+ size_t imageColumns;
protected:
inline JKQTPDatastore* getDatastore() { return datastore; }
@@ -616,23 +962,22 @@ class JKQTP_LIB_EXPORT JKQTPColumn {
* The use of this constructor is mandatory. The default constructor (no arguments) is hidden. Also note
* that you cannot change the binding of a column to a datastore object after creation of the column.
*/
- JKQTPColumn(JKQTPDatastore* datastore, const QString& name=QString(""), size_t datastoreItem=0, size_t datastoreOffset=0);
+ JKQTPColumn(JKQTPDatastore* datastore, const QString& name=QString(""), size_t datastoreItem=0, size_t datastoreOffset=0, size_t imageColumns=1);
inline bool isValid() const { return valid; }
/** \brief class destructor */
- ~JKQTPColumn() ;
+ ~JKQTPColumn() =default;
/*! \brief sets the property name ( \copybrief name ) to the specified \a __value. \details Description of the parameter name is: \copydoc JKQTPColumn::name
\see JKQTPColumn::name for more information */
- inline void setName (const QString& __value)
- {
- this->name = __value;
- }
+ void setName (const QString& __value);
/*! \brief returns the property name ( \copybrief name ). \see name for more information */
- inline QString getName () const
- {
- return this->name;
- }
+ QString getName () const;
+
+ /*! \copydoc imageColumns */
+ void setImageColumns (size_t __value);
+ /*! \copydoc imageColumns */
+ inline size_t getImageColumns () const { return imageColumns; }
/** \brief returns the number of rows in this column (accesses the datastore) */
size_t getRows() const;
@@ -681,13 +1026,32 @@ class JKQTP_LIB_EXPORT JKQTPColumn {
/** \brief sets the element at (x,y) in the column, where the data is interpreted as a row-major ordered Matrix of the given width
*
- * This method accesses the datastore and returns the double value stored in the \a n'th row of the according
+ * This method accesses the datastore and returns the double value stored in the \c (y*width+x)'th row of the according
* column.
*/
inline void setPixelValue(size_t x, size_t y, size_t width, double val) {
setValue(y*width+x, val);
}
+
+ /** \brief sets the element at (x,y) in the column, where the data is interpreted as a row-major ordered Matrix of the width imageWidth
+ *
+ * This method accesses the datastore and returns the double value stored in the \c (y*imageColumns+x)'th row of the according
+ * column.
+ */
+ inline void setPixelValue(size_t x, size_t y, double val) {
+ setValue(y*imageColumns+x, val);
+ }
+
+ /** \brief returns the element at (x,y) in the column, where the data is interpreted as a row-major ordered Matrix of the width imageWidth
+ *
+ * This method accesses the datastore and returns the double value stored in the \c (y*imageColumns+x)'th row of the according
+ * column.
+ */
+ inline double getPixelValue(size_t x, size_t y) const {
+ return getValue(y*imageColumns+x);
+ }
+
/** \brief returns a pointer to the datastore item representing this column */
inline JKQTPDatastoreItem* getDatastoreItem() const { return datastore->getItem(datastoreItem); }
@@ -893,6 +1257,57 @@ inline double JKQTPColumn::getValue(int n) const {
return datastore->getItem(datastoreItem)->get(datastoreOffset, static_cast(n));
}
+////////////////////////////////////////////////////////////////////////////////////////////////
+size_t JKQTPDatastore::getRows(size_t column) const {
+ return columns.value(column).getRows();
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+const double *JKQTPDatastore::getColumnPointer(int column, size_t row) const
+{
+ if (column<0) return nullptr;
+ return columns.value(static_cast(column)).getPointer(row);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+double *JKQTPDatastore::getColumnPointer(int column, size_t row)
+{
+ if (column<0) return nullptr;
+ return columns[static_cast(column)].getPointer(row);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+size_t JKQTPDatastore::getColumnImageWidth(int column)
+{
+ if (column<0) return 0;
+ return columns[static_cast(column)].getImageColumns();
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+size_t JKQTPDatastore::getColumnImageHeight(int column)
+{
+ if (column<0) return 0;
+ return columns[static_cast(column)].getRows()/columns[static_cast(column)].getImageColumns();
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+size_t JKQTPDatastore::getRows(int column) const {
+ if (column<0) return 0;
+ return columns.value(static_cast(column)).getRows();
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+const double *JKQTPDatastore::getColumnPointer(size_t column, size_t row) const
+{
+ return columns.value(column).getPointer(row);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+double *JKQTPDatastore::getColumnPointer(size_t column, size_t row)
+{
+ return columns[column].getPointer(row);
+}
+
////////////////////////////////////////////////////////////////////////////////////////////////
inline double JKQTPDatastore::get(size_t column, size_t row) const {
return columns[column].getValue(row);
@@ -928,6 +1343,80 @@ inline void JKQTPDatastore::set(int column, size_t row, double value) {
set(static_cast(column), static_cast(row), value);
}
+////////////////////////////////////////////////////////////////////////////////////////////////
+inline double JKQTPDatastore::getPixel(size_t column, size_t x, size_t y) const {
+ return columns.value(column).getPixelValue(x, y);
+}
+////////////////////////////////////////////////////////////////////////////////////////////////
+inline void JKQTPDatastore::setPixel(size_t column, size_t x, size_t y, double value) {
+ return columns[column].setPixelValue(x, y, value);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+void JKQTPDatastore::setAll(size_t column, double value)
+{
+ columns[column].setAll(value);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+void JKQTPDatastore::scaleColumnValues(size_t column, double factor)
+{
+ columns[column].scale(factor);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+void JKQTPDatastore::inc(size_t column, size_t row, double increment)
+{
+ columns[column].incValue(row, increment);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+void JKQTPDatastore::dec(size_t column, size_t row, double decrement)
+{
+ columns[column].decValue(row, decrement);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+template
+inline size_t JKQTPDatastore::addCopiedImageAsColumn(const T* data, size_t width, size_t height, const QString& name, size_t stride, size_t start){
+ size_t col=addCopiedColumn(data, width*height, stride, start, name);
+ columns[col].setImageColumns(width);
+ return col;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+template
+inline size_t JKQTPDatastore::addCopiedImageAsColumn(const TContainer& data, size_t width, const QString& name){
+ size_t col= addCopiedColumn(data, name);
+ columns[col].setImageColumns(width);
+ return col;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+template
+size_t JKQTPDatastore::addCopiedImageAsColumnTranspose(const T* data, size_t width, size_t height, const QString& name, size_t stride, size_t start){
+ double* temp=static_cast(malloc(width*height*sizeof(double)));
+
+ for (size_t x=0; x(data[start+(y*width+x)*stride]);
+ }
+
+ }
+
+ size_t idx=addInternalColumn(temp, width*height, name);
+ columns[idx].setImageColumns(height);
+ return idx;
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////
+template
+inline size_t JKQTPDatastore::addCopiedImageAsColumnTranspose(const QVector& data, size_t width, const QString& name) {
+ return addCopiedImageAsColumnTranspose(data.data(), width, static_cast(data.size())/width, name);
+}
#endif // JKQTPDATASTORAGE_H
diff --git a/lib/jkqtplotter/jkqtpgraphsbarchart.cpp b/lib/jkqtplotter/jkqtpgraphsbarchart.cpp
index c7080af1f4..ca590d140d 100644
--- a/lib/jkqtplotter/jkqtpgraphsbarchart.cpp
+++ b/lib/jkqtplotter/jkqtpgraphsbarchart.cpp
@@ -84,7 +84,7 @@ void JKQTPBarVerticalGraph::draw(JKQTPEnhancedPainter& painter) {
QBrush b=getFillBrush(painter, parent);
- int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows());
+ int imax=qMin(datastore->getRows(static_cast(xColumn)), datastore->getRows(static_cast(yColumn)));
int imin=0;
if (imaxgetDatastore();
int imin=0;
- int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows());
+ int imax=qMin(datastore->getRows(static_cast(xColumn)), datastore->getRows(static_cast(yColumn)));
if (imaxgetDatastore();
int imin=0;
- int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows());
+ int imax=qMin(datastore->getRows(static_cast(xColumn)), datastore->getRows(static_cast(yColumn)));
if (imaxgetColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows());
+ int imax=qMin(datastore->getRows(static_cast(xColumn)), datastore->getRows(static_cast(yColumn)));
int imin=0;
if (imaxgetDatastore();
int imin=0;
- int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(xColumn)).getRows());
+ int imax=qMin(datastore->getRows(static_cast(xColumn)), datastore->getRows(static_cast(xColumn)));
if (imaxgetDatastore();
int imin=0;
- int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows());
+ int imax=qMin(datastore->getRows(static_cast(xColumn)), datastore->getRows(static_cast(yColumn)));
if (imaxgetDatastore();
int imin=0;
- int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows());
+ int imax=qMin(datastore->getRows(static_cast(xColumn)), datastore->getRows(static_cast(yColumn)));
if (imaxgetDatastore();
int imin=0;
- int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows());
+ int imax=qMin(datastore->getRows(static_cast(xColumn)), datastore->getRows(static_cast(yColumn)));
if (imaxgetDatastore();
int imin=0;
- int imax=qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows());
+ int imax=qMin(datastore->getRows(static_cast(xColumn)), datastore->getRows(static_cast(yColumn)));
if (imaxgetDatastore();
int imin=0;
- int imax=static_cast(datastore->getColumn(column).getRows());
+ int imax=static_cast(datastore->getRows(column));
if (imin<0) imin=0;
if (imax<0) imax=0;
@@ -402,6 +402,42 @@ void JKQTPXYGraph::setDataSortOrder(int __value) {
sortData=static_cast(__value);
}
+void JKQTPXYGraph::setXYColumns(size_t xCol, size_t yCol)
+{
+ setXColumn(xCol);
+ setYColumn(yCol);
+}
+
+void JKQTPXYGraph::setXYColumns(int xCol, int yCol)
+{
+ setXColumn(xCol);
+ setYColumn(yCol);
+}
+
+void JKQTPXYGraph::setXYColumns(std::pair xyColPair)
+{
+ setXColumn(xyColPair.first);
+ setYColumn(xyColPair.second);
+}
+
+void JKQTPXYGraph::setXYColumns(std::pair xyColPair)
+{
+ setXColumn(xyColPair.first);
+ setYColumn(xyColPair.second);
+}
+
+void JKQTPXYGraph::setXYColumns(QPair xyColPair)
+{
+ setXColumn(xyColPair.first);
+ setYColumn(xyColPair.second);
+}
+
+void JKQTPXYGraph::setXYColumns(QPair xyColPair)
+{
+ setXColumn(xyColPair.first);
+ setYColumn(xyColPair.second);
+}
+
double JKQTPXYGraph::hitTest(const QPointF &posSystem, QPointF *closestSpotSystem, QString *label, HitTestMode mode) const
{
@@ -547,7 +583,7 @@ bool JKQTPSingleColumnGraph::getIndexRange(int &imin, int &imax) const
JKQTPDatastore* datastore=parent->getDatastore();
imin=0;
- imax=static_cast(datastore->getColumn(static_cast(dataColumn)).getRows());
+ imax=static_cast(datastore->getRows(static_cast(dataColumn)));
if (imaxgetDatastore();
imin=0;
- imax=static_cast(qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()));
+ imax=static_cast(qMin(datastore->getRows(static_cast(xColumn)), datastore->getRows(static_cast(yColumn))));
if (imax\copydoc sortData \see sortData for more information */
void setDataSortOrder(int __value);
+ /** \brief sets xColumn and yColumn at the same time */
+ void setXYColumns(size_t xCol, size_t yCol);
+ /** \brief sets xColumn and yColumn at the same time */
+ void setXYColumns(int xCol, int yCol);
+ /** \brief sets xColumn and yColumn at the same time */
+ void setXYColumns(std::pair xyColPair);
+ /** \brief sets xColumn and yColumn at the same time */
+ void setXYColumns(std::pair xyColPair);
+ /** \brief sets xColumn and yColumn at the same time */
+ void setXYColumns(QPair xyColPair);
+ /** \brief sets xColumn and yColumn at the same time */
+ void setXYColumns(QPair xyColPair);
+
/** \brief Implmentation of JKQTPPlotElement::hitTest(), which searches through all graph points defined by xColumn and yColumn
* and returns a general x/y-label, also taking into account possibly known errors to the graphs (if it is derived
diff --git a/lib/jkqtplotter/jkqtpgraphsbaseerrors.cpp b/lib/jkqtplotter/jkqtpgraphsbaseerrors.cpp
index 4049aecb48..c96eb7aff9 100644
--- a/lib/jkqtplotter/jkqtpgraphsbaseerrors.cpp
+++ b/lib/jkqtplotter/jkqtpgraphsbaseerrors.cpp
@@ -82,7 +82,7 @@ void JKQTPGraphErrorStyleMixin::setErrorColorFromGraphColor(QColor graphColor)
QPen JKQTPGraphErrorStyleMixin::getErrorLinePen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const
{
QPen p=m_errorLinePen;
- p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_errorLineWidth)));
+ p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_errorLineWidth)));
return p;
}
@@ -282,8 +282,8 @@ void JKQTPGraphErrorStyleMixin::intPlotXYErrorIndicators(JKQTPEnhancedPainter& p
painter.setPen(p);
size_t imaxx=0, imaxy=0;
- if (xColumn>=0) imaxx=datastore->getColumn(static_cast(xColumn)).getRows();
- if (yColumn>=0) imaxy=datastore->getColumn(static_cast(yColumn)).getRows();
+ if (xColumn>=0) imaxx=datastore->getRows(static_cast(xColumn));
+ if (yColumn>=0) imaxy=datastore->getRows(static_cast(yColumn));
size_t imax=qMin(imaxx, imaxy);
size_t imin=0;
if (imax=0 && i>=0 && i(ds->getColumn(xErrorColumn).getRows())) {
+ if (ds && xErrorColumn>=0 && i>=0 && i(ds->getRows(xErrorColumn))) {
return ds->get(xErrorColumn, static_cast(i));
}
return 0.0;
@@ -640,9 +640,9 @@ double JKQTPXGraphErrorData::getXErrorL(int i, JKQTPDatastore *ds) const
{
if (ds) {
if (xErrorSymmetric) {
- if (xErrorColumn>=0 && i>=0 && i(ds->getColumn(xErrorColumn).getRows())) return ds->get(xErrorColumn, static_cast(i));
+ if (xErrorColumn>=0 && i>=0 && i(ds->getRows(xErrorColumn))) return ds->get(xErrorColumn, static_cast(i));
} else {
- if (xErrorColumnLower>=0 && i>=0 && i(ds->getColumn(xErrorColumnLower).getRows())) return ds->get(xErrorColumnLower, static_cast(i));
+ if (xErrorColumnLower>=0 && i>=0 && i(ds->getRows(xErrorColumnLower))) return ds->get(xErrorColumnLower, static_cast(i));
}
}
return 0.0;
@@ -706,7 +706,7 @@ void JKQTPYGraphErrorData::setYErrorColumnLower(int __value) {
double JKQTPYGraphErrorData::getYErrorU(int i, JKQTPDatastore *ds) const
{
- if (ds && yErrorColumn>=0 && i>=0 && i(ds->getColumn(yErrorColumn).getRows())) {
+ if (ds && yErrorColumn>=0 && i>=0 && i(ds->getRows(yErrorColumn))) {
return ds->get(yErrorColumn, static_cast(i));
}
return 0.0;
@@ -716,9 +716,9 @@ double JKQTPYGraphErrorData::getYErrorL(int i, JKQTPDatastore *ds) const
{
if (ds) {
if (yErrorSymmetric) {
- if (yErrorColumn>=0 && i>=0 && i(ds->getColumn(yErrorColumn).getRows())) return ds->get(yErrorColumn, static_cast(i));
+ if (yErrorColumn>=0 && i>=0 && i(ds->getRows(yErrorColumn))) return ds->get(yErrorColumn, static_cast(i));
} else {
- if (yErrorColumnLower>=0 && i>=0 && i(ds->getColumn(yErrorColumnLower).getRows())) return ds->get(yErrorColumnLower, static_cast(i));
+ if (yErrorColumnLower>=0 && i>=0 && i(ds->getRows(yErrorColumnLower))) return ds->get(yErrorColumnLower, static_cast(i));
}
}
return 0.0;
diff --git a/lib/jkqtplotter/jkqtpgraphsbasestylingmixins.cpp b/lib/jkqtplotter/jkqtpgraphsbasestylingmixins.cpp
index ab4c46fec4..cba1bf3d6b 100644
--- a/lib/jkqtplotter/jkqtpgraphsbasestylingmixins.cpp
+++ b/lib/jkqtplotter/jkqtpgraphsbasestylingmixins.cpp
@@ -135,7 +135,7 @@ QBrush JKQTPGraphLineStyleMixin::getLineBrush() const
QPen JKQTPGraphLineStyleMixin::getLinePen(JKQTPEnhancedPainter& painter, JKQTBasePlotter* parent) const {
QPen p=m_linePen;
- p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_lineWidth)));
+ p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_lineWidth)));
return p;
}
@@ -239,7 +239,7 @@ double JKQTPGraphSymbolStyleMixin::getSymbolLineWidth() const
QPen JKQTPGraphSymbolStyleMixin::getSymbolPen(JKQTPEnhancedPainter& painter, JKQTBasePlotter* parent) const {
QPen p;
p.setColor(m_symbolColor);
- p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_symbolLineWidth)));
+ p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_symbolLineWidth)));
p.setStyle(Qt::SolidLine);
p.setJoinStyle(Qt::RoundJoin);
p.setCapStyle(Qt::RoundCap);
diff --git a/lib/jkqtplotter/jkqtpgraphsboxplot.cpp b/lib/jkqtplotter/jkqtpgraphsboxplot.cpp
index e720155900..2602ea4401 100644
--- a/lib/jkqtplotter/jkqtpgraphsboxplot.cpp
+++ b/lib/jkqtplotter/jkqtpgraphsboxplot.cpp
@@ -71,7 +71,7 @@ void JKQTPBoxplotVerticalGraph::draw(JKQTPEnhancedPainter& painter) {
drawErrorsBefore(painter);
- int imax=static_cast(datastore->getColumn(static_cast(posColumn)).getRows());
+ int imax=static_cast(datastore->getRows(static_cast(posColumn)));
int imin=0;
if (imaxgetDatastore();
int imin=0;
- int imax=static_cast(datastore->getColumn(static_cast(posColumn)).getRows());
+ int imax=static_cast(datastore->getRows(static_cast(posColumn)));
if (imaxgetDatastore();
int imin=0;
- int imax=datastore->getColumn(medianColumn).getRows();
+ int imax=datastore->getRows(medianColumn);
if (imaxgetDatastore();
int imin=0;
- int imax=datastore->getColumn(medianColumn).getRows();
+ int imax=datastore->getRows(medianColumn);
if (imaxgetDatastore();
int imin=0;
- int imax=static_cast(datastore->getColumn(static_cast(posColumn)).getRows());
+ int imax=static_cast(datastore->getRows(static_cast(posColumn)));
if (imax(datastore->getColumn(static_cast(posColumn)).getRows());
+ int imax=static_cast(datastore->getRows(static_cast(posColumn)));
int imin=0;
if (imaxgetDatastore();
int imin=0;
- int imax=static_cast(datastore->getColumn(static_cast(posColumn)).getRows());
+ int imax=static_cast(datastore->getRows(static_cast(posColumn)));
if (imaxpt2px(painter, parent->getLineWidthMultiplier()*whiskerLineWidth)));
+ pw.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*whiskerLineWidth)));
pw.setJoinStyle(Qt::MiterJoin);
pw.setCapStyle(Qt::FlatCap);
return pw;
@@ -513,7 +513,7 @@ QBrush JKQTPGraphBoxplotStyleMixin::getWhiskerCapLineBrush() const
QPen JKQTPGraphBoxplotStyleMixin::getWhiskerCapPen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const
{
QPen pw=m_whiskerCapLinePen;
- pw.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*whiskerCapLineWidth)));
+ pw.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*whiskerCapLineWidth)));
pw.setJoinStyle(Qt::MiterJoin);
return pw;
}
@@ -529,7 +529,7 @@ QPen JKQTPGraphBoxplotStyleMixin::getWhiskerCapPen(JKQTPEnhancedPainter &painter
QPen JKQTPGraphBoxplotStyleMixin::getMedianPen(JKQTPEnhancedPainter &painter, JKQTBasePlotter *parent) const
{
QPen pw=m_medianLinePen;
- pw.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*medianLineWidth)));
+ pw.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*medianLineWidth)));
pw.setJoinStyle(Qt::MiterJoin);
pw.setCapStyle(Qt::FlatCap);
return pw;
@@ -537,7 +537,7 @@ QPen JKQTPGraphBoxplotStyleMixin::getMedianPen(JKQTPEnhancedPainter &painter, JK
QPen JKQTPGraphBoxplotStyleMixin::getMeanSymbolPen(JKQTPEnhancedPainter& painter, JKQTBasePlotter* parent) const {
QPen p=m_meanSymbolLinePen;
- p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_meanSymbolLineWidth)));
+ p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_meanSymbolLineWidth)));
p.setStyle(Qt::SolidLine);
p.setJoinStyle(Qt::RoundJoin);
p.setCapStyle(Qt::RoundCap);
@@ -546,7 +546,7 @@ QPen JKQTPGraphBoxplotStyleMixin::getMeanSymbolPen(JKQTPEnhancedPainter& painter
QPen JKQTPGraphBoxplotStyleMixin::getMeanLinePen(JKQTPEnhancedPainter& painter, JKQTBasePlotter* parent) const {
QPen p=m_meanSymbolLinePen;
- p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_meanSymbolLineWidth)));
+ p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*m_meanSymbolLineWidth)));
p.setJoinStyle(Qt::MiterJoin);
p.setCapStyle(Qt::FlatCap);
return p;
diff --git a/lib/jkqtplotter/jkqtpgraphscontour.cpp b/lib/jkqtplotter/jkqtpgraphscontour.cpp
index 218046dce3..33585e02e3 100644
--- a/lib/jkqtplotter/jkqtpgraphscontour.cpp
+++ b/lib/jkqtplotter/jkqtpgraphscontour.cpp
@@ -216,7 +216,7 @@ bool JKQTPContour::getRelativeLevels() const
void JKQTPContour::setImageColumn(size_t columnID)
{
datatype=JKQTPMathImageBase::DoubleArray;
- data=parent->getDatastore()->getColumn(columnID).getPointer(0);
+ data=parent->getDatastore()->getColumnPointer(columnID,0);
}
diff --git a/lib/jkqtplotter/jkqtpgraphsevaluatedfunction.cpp b/lib/jkqtplotter/jkqtpgraphsevaluatedfunction.cpp
index f70b543367..56250db3f2 100644
--- a/lib/jkqtplotter/jkqtpgraphsevaluatedfunction.cpp
+++ b/lib/jkqtplotter/jkqtpgraphsevaluatedfunction.cpp
@@ -263,7 +263,7 @@ void JKQTPXFunctionLineGraph::collectParameters()
iparams.clear();
JKQTPDatastore* datastore=parent->getDatastore();
int imin=0;
- int imax=datastore->getColumn(parameterColumn).getRows();
+ int imax=datastore->getRows(parameterColumn);
for (int i=imin; iget(parameterColumn,i);
@@ -286,7 +286,7 @@ void JKQTPXFunctionLineGraph::collectParameters()
ierrorparams.clear();
JKQTPDatastore* datastore=parent->getDatastore();
int imin=0;
- int imax=datastore->getColumn(errorParameterColumn).getRows();
+ int imax=datastore->getRows(errorParameterColumn);
for (int i=imin; iget(errorParameterColumn,i);
@@ -361,7 +361,7 @@ void JKQTPXFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
QPen ep=painter.pen();
ep.setColor(errorColor);
- ep.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, errorLineWidth*parent->getLineWidthMultiplier())));
+ ep.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, errorLineWidth*parent->getLineWidthMultiplier())));
ep.setStyle(errorStyle);
ep.setJoinStyle(Qt::RoundJoin);
@@ -540,7 +540,7 @@ void JKQTPYFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) {
QPen ep=painter.pen();
ep.setColor(errorColor);
- ep.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, errorLineWidth*parent->getLineWidthMultiplier())));
+ ep.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, parent->pt2px(painter, errorLineWidth*parent->getLineWidthMultiplier())));
ep.setStyle(errorStyle);
ep.setJoinStyle(Qt::RoundJoin);
@@ -723,7 +723,7 @@ QBrush JKQTPXFunctionLineGraph::getErrorBrush(JKQTPEnhancedPainter& /*painter*/)
QPen JKQTPXFunctionLineGraph::getErrorLinePen(JKQTPEnhancedPainter& painter) const {
QPen p;
p.setColor(errorColor);
- p.setWidthF(qMax(JKQTPlotterDrawinTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*errorLineWidth)));
+ p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH,parent->pt2px(painter, parent->getLineWidthMultiplier()*errorLineWidth)));
p.setStyle(errorStyle);
p.setJoinStyle(Qt::RoundJoin);
p.setCapStyle(Qt::RoundCap);
diff --git a/lib/jkqtplotter/jkqtpgraphsfilledcurve.cpp b/lib/jkqtplotter/jkqtpgraphsfilledcurve.cpp
index 35ded99016..c0f0bff33e 100644
--- a/lib/jkqtplotter/jkqtpgraphsfilledcurve.cpp
+++ b/lib/jkqtplotter/jkqtpgraphsfilledcurve.cpp
@@ -148,7 +148,7 @@ bool JKQTPFilledVerticalRangeGraph::getYMinMax(double &miny, double &maxy, doubl
JKQTPDatastore* datastore=parent->getDatastore();
int imin=0;
- int imax=static_cast(qMin(qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()), datastore->getColumn(static_cast(yColumn2)).getRows()));
+ int imax=static_cast(qMin(qMin(datastore->getRows(static_cast(xColumn)), datastore->getRows(static_cast(yColumn))), datastore->getRows(static_cast(yColumn2))));
if (imax(qMin(qMin(datastore->getColumn(static_cast(xColumn)).getRows(), datastore->getColumn(static_cast(yColumn)).getRows()), datastore->getColumn(static_cast(yColumn2)).getRows()));
+ int imax=static_cast(qMin(qMin(datastore->getRows(static_cast(xColumn)), datastore->getRows(static_cast(yColumn))), datastore->getRows(static_cast(yColumn2))));
int imin=0;
if (imax