diff --git a/JKQtPlotterBuildAllExamples.pro b/JKQtPlotterBuildAllExamples.pro index 5ae541cb5f..d7c36770c2 100644 --- a/JKQtPlotterBuildAllExamples.pro +++ b/JKQtPlotterBuildAllExamples.pro @@ -1,17 +1,18 @@ TEMPLATE = subdirs SUBDIRS += jkqtplotterlib \ - jkqtplotterlib_sharedlib \ + jkqtplotterlib_sharedlib \ jkqtmathtextlib \ jkqtmathtextlib_sharedlib \ + jkqtpcommonlib \ + jkqtpcommonlib_sharedlib \ jkqtfastplotterlib \ jkqtfastplotterlib_sharedlib \ - jkqtphighrestimerlib \ jkqtmathtext_simpletest \ jkqtplot_test \ jkqtplotter_simpletest \ - test_multiplot \ - jkqtfastplotter_test + test_multiplot \ + jkqtfastplotter_test jkqtplotterlib.file = staticlib/jkqtplotterlib/jkqtplotterlib.pro @@ -20,13 +21,14 @@ jkqtplotterlib_sharedlib.file = sharedlib/jkqtplotterlib/jkqtplotterlib.pro jkqtmathtextlib.file = staticlib/jkqtmathtextlib/jkqtmathtextlib.pro jkqtmathtextlib_sharedlib.file = sharedlib/jkqtmathtextlib/jkqtmathtextlib.pro +jkqtpcommonlib.file = staticlib/jkqtpcommonlib/jkqtpcommonlib.pro +jkqtpcommonlib_sharedlib.file = sharedlib/jkqtpcommonlib/jkqtpcommonlib.pro + jkqtfastplotterlib.file = staticlib/jkqtfastplotterlib/jkqtfastplotterlib.pro jkqtfastplotterlib_sharedlib.file = sharedlib/jkqtfastplotterlib/jkqtfastplotterlib.pro -jkqtphighrestimerlib.file = staticlib/jkqtphighrestimerlib/jkqtphighrestimerlib.pro - jkqtmathtext_simpletest.subdir = examples/jkqtmathtext_simpletest -jkqtmathtext_simpletest.depends = jkqtmathtextlib jkqtphighrestimerlib +jkqtmathtext_simpletest.depends = jkqtmathtextlib jkqtmathtext_test.subdir = examples/jkqtmathtext_test jkqtmathtext_test.depends = jkqtplotterlib diff --git a/doc/dox/examples_and_tutorials.dox b/doc/dox/examples_and_tutorials.dox index 2f10578167..e3571b09a1 100644 --- a/doc/dox/examples_and_tutorials.dox +++ b/doc/dox/examples_and_tutorials.dox @@ -146,13 +146,16 @@ All test-projects are Qt-projects that use qmake to build. You can load them int -\subsection jkqtp_extut_datamanagement Data Management +\subsection jkqtp_extut_datamanagement Data Management & Statistics
Screenshot Description Notes
\image html simpletest_datastore_small.png \subpage JKQTPlotterBasicJKQTPDatastore Basic Data Management with JKQTPDatastore
Copying data into a JKQTPDatastore
Editing data inside a JKQTPDatastore
Editing Image Data in a JKQTPDatastore +
\image html simpletest_datastore_statistics_small.png + \subpage JKQTPlotterBasicJKQTPDatastoreStatistics + Advanced 1-Dimensional Statistical Computation with JKQTPODatastore (and the internal statistics library, see \ref jkqtptools_math_statistics )
diff --git a/doc/dox/jkqtplotter.dox b/doc/dox/jkqtplotter.dox index 4395c2c6ed..0d7114fe5f 100644 --- a/doc/dox/jkqtplotter.dox +++ b/doc/dox/jkqtplotter.dox @@ -11,43 +11,108 @@ functionaly groups. \defgroup jkqtptools_algorithms Diverse Algorithms \ingroup jkqtptools -\defgroup jkqtptools_math Mathematical Computations & Equation Parsing +\defgroup jkqtptools_math Mathematical Computations & Expression Parsing \ingroup jkqtptools -\defgroup jkqtptools_math_basic Basic Math Functions +\defgroup jkqtptools_math_basic Mathematical Functions & Tools \ingroup jkqtptools_math -\defgroup jkqtptools_math_statistics Tools for Statistical Computations -\ingroup jkqtptools_math +This group assembles a variety of mathematical tool functions that are used in different places. \defgroup jkqtptools_math_array Data Array Tools \ingroup jkqtptools_math +Functions in this group form the basis for the statistics (\ref jkqtptools_math_statistics ) and linear algebra libraries (\ref jkqtptools_math_linalg ), by providing allocation and freeing of (aligned) memory arrays. + +\seeJKQTPlotterBasicJKQTPDatastoreStatistics + \defgroup jkqtptools_math_linalg Linear Algebra Tools \ingroup jkqtptools_math +This group assembles a basic set of linear algebra methods, including matrix inversion, which are required e.g. by the statistics library (\ref jkqtptools_math_statistics ) + +\defgroup jkqtptools_math_statistics Statistical Computations +\ingroup jkqtptools_math + +This group contains a statistics library, which offers several basic methods and is based on an iterator interface: + - \ref jkqtptools_math_statistics_basic + - \ref jkqtptools_math_statistics_regression + - \ref jkqtptools_math_statistics_1dhist + - \ref jkqtptools_math_statistics_2dhist + - \ref jkqtptools_math_statistics_1dkde + - \ref jkqtptools_math_statistics_2dkde +. + + +All statistics functions use an iterator-based interface, comparable to the interface of the algorithms in the C++ standard template library. To this end, the class `JKQTPDatastore` provides an iterator interface to its columns, using the functions `JKQTPDatastore::begin()` and `JKQTPDatastore::end()`. Both functions simply receive the column ID as parameter and exist in a const and a mutable variant. the latter allows to also edit the data. In addition the function `JKQTPDatastore::backInserter()` returns a back-inserter iterator (like generated for STL containers with `std::back_inserter(container)`) that also allows to append to the column. + +Note that the iterator interface allows to use these functions with any container that provides such iterators (e.g. `std::vector`, `std::list`, `std::set`, `QVector`...). + +Code using one of these statistics functions therefore may look e.g. like this: +\code + // mean of a column in a JKQTPDatastore: + double mean=jkqtpstatAverage(datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1)); + + // mean of a std::vector + std::vector data {1,2,4,5,7,8,10,2,1,3,5}; + double meanvec=jkqtpstatAverage(data.begin(), data.end()); +\endcode + +All statistics functions use all values in the given range and convert each value to a `double`, using `jkqtp_todouble()`. The return values is always a dohble. Therefore you can use these functions to calculate statistics of ranges of any type that can be converted to `double`. Values that do not result in a valid `double`are not used in calculating the statistics. Therefore you can exclude values by setting them `JKQTP_DOUBLE_NAN` (i.e. "not a number"). + +\see see for detailed examples: \ref JKQTPlotterBasicJKQTPDatastoreStatistics + +\defgroup jkqtptools_math_statistics_basic Basic statistics +\ingroup jkqtptools_math_statistics + +\defgroup jkqtptools_math_statistics_regression Regression Analysis +\ingroup jkqtptools_math_statistics + +\defgroup jkqtptools_math_statistics_1dhist 1-dimensional Histograms +\ingroup jkqtptools_math_statistics + +\defgroup jkqtptools_math_statistics_2dhist 2-dimensional Histograms +\ingroup jkqtptools_math_statistics + +\defgroup jkqtptools_math_statistics_1dkde 1-dimensional Kernel Density Estimates +\ingroup jkqtptools_math_statistics + +\defgroup jkqtptools_math_statistics_2dkde 2-dimensional Kernel Density Estimates +\ingroup jkqtptools_math_statistics + + + \defgroup jkqtptools_string String/String-Conversion Tool Functions \ingroup jkqtptools +Offers diverse function to convert different datatypes (e.g. double, int, diverse enums) to and from strings and for string manipulation. + \defgroup jkqtptools_qt Additional Tools for Qt \ingroup jkqtptools + \defgroup jkqtptools_qtwidgets Additional Widgets for Qt \ingroup jkqtptools \defgroup jkqtptools_drawing Drawing & Graphics Tools \ingroup jkqtptools +Specialized drawing functions used by the plotters and LaTeX renderers. + \defgroup jkqtptools_debugging Debugging Tools \ingroup jkqtptools +Functions that help during debugging (e.g. an assert function/macro). + \defgroup jkqtptools_codestructuring Code Structuring Tools \ingroup jkqtptools +Classes and functions that help to structure the code (e.g. RAII constructs) + \defgroup jkqtptools_enums Enums for JKQTPlotter (including String Conversion) \ingroup jkqtptools - +Assembles diverse ENUMs required by JKQTPlotter. @@ -150,7 +215,7 @@ With these there are usually two variants of one type of graph: One without erro This approach allows to keep interfaces and appearance recognizeable over different graph classes and locates the source code for a feature like error indicators in a single/in few class(es). -Another example of such a class is JKQTPColorPaletteTools, which provides functions that allow to use color palettes. It is +Another example of such a class is JKQTPColorPaletteStyleAndToolsMixin, which provides functions that allow to use color palettes. It is mainly used for the \ref jkqtplotter_imagelots "Image/Matrix graphs", but also by e.g. JKQTPXYParametrizedScatterGraph. diff --git a/doc/dox/whatsnew.dox b/doc/dox/whatsnew.dox index f522a5cddb..31cb734e34 100644 --- a/doc/dox/whatsnew.dox +++ b/doc/dox/whatsnew.dox @@ -44,6 +44,8 @@ Changes, compared to \ref page_whatsnew_V2018_08 "v2018.08" include:
  • new: advanced styling options for boxplots + example for the styling: \ref JKQTPlotterBoxplotStyling
  • new: notched boxplots, see: \ref JKQTPlotterBoxplotStyling
  • new: several new plot symbols, see: JKQTPGraphSymbols
  • +
  • new: Statistics library with functions to calculate histograms, regression, kernel density estimates, ... see: \ref jkqtptools_statistics
  • +
  • new: iterator interface and improved documentation for JKQTPDatastore
  • changed: removed old selection-code and replaced by general highlighting feature
  • changed: JKQTPStepHorizontalGraph has been renamed to JKQTPSpecialLineHorizontalGraph (vertical variants also) and have gained additional features (baseline for filling and drawing of symbols)
  • changed: filled curve graphs (e.g. JKQTPSpecialLineHorizontalGraph) are now merely a specializedly initialized JKQTPSpecialLineHorizontalGraph
  • diff --git a/examples/README.md b/examples/README.md index 8fe326a4ac..37c2b96767 100644 --- a/examples/README.md +++ b/examples/README.md @@ -59,22 +59,12 @@ All test-projects are Qt-projects that use qmake to build. You can load them int -## Data Management +## Data Management (Tutorials) & Statistics | 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) | [Tutorial: Basic Usage of JKQTPDatastore](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore) | Basic Data Management with JKQTPDatastore
    Copying data into a JKQTPDatastore
    Editing data inside a JKQTPDatastore
    Editing Image Data in a 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_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 | - +| [![](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/simpletest_datastore_statistics_small.png)](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore_statistics) | [Tutorial: Advanced 1-Dimensional Statistics with JKQTPDatastore](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore_statistics) | Advanced 1-Dimensional Statistical Computation with JKQTPDatastore (and the internal statistics library) | ## More Complex Examples diff --git a/examples/jkqtmathtext_test/jkqtmathtext_test.pro b/examples/jkqtmathtext_test/jkqtmathtext_test.pro index 74047f327f..e1b0095f3b 100644 --- a/examples/jkqtmathtext_test/jkqtmathtext_test.pro +++ b/examples/jkqtmathtext_test/jkqtmathtext_test.pro @@ -39,13 +39,9 @@ DEPENDPATH += ../../lib ../../staticlib/jkqtmathtextlib INCLUDEPATH += ../../lib CONFIG (debug, debug|release) { DEPENDPATH += ../../staticlib/jkqtmathtextlib/debug - DEPENDPATH += ../../staticlib/jkqtphighrestimerlib/debug LIBS += -L../../staticlib/jkqtmathtextlib/debug -ljkqtmathtextlib_debug - LIBS += -L../../staticlib/jkqtphighrestimerlib/debug -ljkqtphighrestimerlib_debug } else { DEPENDPATH += ../../staticlib/jkqtmathtextlib/release - DEPENDPATH += ../../staticlib/jkqtphighrestimerlib/release LIBS += -L../../staticlib/jkqtmathtextlib/release -ljkqtmathtextlib - LIBS += -L../../staticlib/jkqtphighrestimerlib/release -ljkqtphighrestimerlib } message("LIBS = $$LIBS") diff --git a/examples/jkqtmathtext_test/jkqtmathtext_test_and_lib.pro b/examples/jkqtmathtext_test/jkqtmathtext_test_and_lib.pro index 46dee4912a..d10db5053c 100644 --- a/examples/jkqtmathtext_test/jkqtmathtext_test_and_lib.pro +++ b/examples/jkqtmathtext_test/jkqtmathtext_test_and_lib.pro @@ -1,9 +1,8 @@ TEMPLATE = subdirs -SUBDIRS += jkqtmathtextlib jkqtphighrestimerlib jkqtmathtext_test +SUBDIRS += jkqtmathtextlib jkqtmathtext_test jkqtmathtextlib.file = ../../staticlib/jkqtmathtextlib/jkqtmathtextlib.pro -jkqtphighrestimerlib.file = ../../staticlib/jkqtphighrestimerlib/jkqtphighrestimerlib.pro jkqtmathtext_test.file=$$PWD/jkqtmathtext_test.pro -jkqtmathtext_test.depends = jkqtmathtextlib jkqtphighrestimerlib +jkqtmathtext_test.depends = jkqtmathtextlib diff --git a/examples/jkqtmathtext_test/testform.h b/examples/jkqtmathtext_test/testform.h index 1e671a9bb3..ccf6d49718 100644 --- a/examples/jkqtmathtext_test/testform.h +++ b/examples/jkqtmathtext_test/testform.h @@ -4,7 +4,7 @@ #include #include #include "jkqtmathtext/jkqtmathtext.h" -#include "jkqtplottertools/jkqtphighrestimer.h" +#include "jkqtcommon/jkqtphighrestimer.h" #include #include diff --git a/examples/jkqtplot_test/TestWidgetBarcharts.h b/examples/jkqtplot_test/TestWidgetBarcharts.h index 24512de86a..fac5b574ac 100644 --- a/examples/jkqtplot_test/TestWidgetBarcharts.h +++ b/examples/jkqtplot_test/TestWidgetBarcharts.h @@ -17,7 +17,7 @@ #include "jkqtplotter/jkqtpgraphsparsedfunction.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplottergui/jkqtpgraphsmodel.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #define N1 200 #define N2 50 diff --git a/examples/jkqtplot_test/TestWidgetContourPlots.h b/examples/jkqtplot_test/TestWidgetContourPlots.h index a600ed1993..25fa78c021 100644 --- a/examples/jkqtplot_test/TestWidgetContourPlots.h +++ b/examples/jkqtplot_test/TestWidgetContourPlots.h @@ -18,7 +18,7 @@ #include "jkqtplotter/jkqtpgraphsparsedfunction.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplottergui/jkqtpgraphsmodel.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #define N1 200 #define N2 50 diff --git a/examples/jkqtplot_test/TestWidgetEmptyPlot.h b/examples/jkqtplot_test/TestWidgetEmptyPlot.h index a586646564..568111c476 100644 --- a/examples/jkqtplot_test/TestWidgetEmptyPlot.h +++ b/examples/jkqtplot_test/TestWidgetEmptyPlot.h @@ -17,7 +17,7 @@ #include "jkqtplotter/jkqtpgraphsparsedfunction.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplottergui/jkqtpgraphsmodel.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #define N1 200 #define N2 50 diff --git a/examples/jkqtplot_test/TestWidgetFunctionPlots.h b/examples/jkqtplot_test/TestWidgetFunctionPlots.h index fe7174f29d..8e2c30b7ce 100644 --- a/examples/jkqtplot_test/TestWidgetFunctionPlots.h +++ b/examples/jkqtplot_test/TestWidgetFunctionPlots.h @@ -18,7 +18,7 @@ #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplottergui/jkqtpgraphsmodel.h" #include "jkqtplottergui/jkqtpcomboboxes.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #define N1 200 #define N2 50 diff --git a/examples/jkqtplot_test/TestWidgetGeometry.h b/examples/jkqtplot_test/TestWidgetGeometry.h index 76497db22c..7ed199115d 100644 --- a/examples/jkqtplot_test/TestWidgetGeometry.h +++ b/examples/jkqtplot_test/TestWidgetGeometry.h @@ -17,7 +17,7 @@ #include "jkqtplotter/jkqtpgraphsparsedfunction.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplottergui/jkqtpgraphsmodel.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #define N1 200 #define N2 50 diff --git a/examples/jkqtplot_test/TestWidgetGraphs.h b/examples/jkqtplot_test/TestWidgetGraphs.h index a17776d35d..8b4927bd41 100644 --- a/examples/jkqtplot_test/TestWidgetGraphs.h +++ b/examples/jkqtplot_test/TestWidgetGraphs.h @@ -17,7 +17,7 @@ #include "jkqtplotter/jkqtpgraphsparsedfunction.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplottergui/jkqtpgraphsmodel.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #define N1 200 #define N2 50 diff --git a/examples/jkqtplot_test/TestWidgetImages.h b/examples/jkqtplot_test/TestWidgetImages.h index 98b89898d0..3fe86945d1 100644 --- a/examples/jkqtplot_test/TestWidgetImages.h +++ b/examples/jkqtplot_test/TestWidgetImages.h @@ -17,7 +17,7 @@ #include "jkqtplotter/jkqtpgraphsparsedfunction.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplottergui/jkqtpgraphsmodel.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #define N1 200 #define N2 50 diff --git a/examples/jkqtplot_test/TestWidgetLogGraphs.h b/examples/jkqtplot_test/TestWidgetLogGraphs.h index 59f377c0f2..f8cdf55cf0 100644 --- a/examples/jkqtplot_test/TestWidgetLogGraphs.h +++ b/examples/jkqtplot_test/TestWidgetLogGraphs.h @@ -17,7 +17,7 @@ #include "jkqtplotter/jkqtpgraphsparsedfunction.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplottergui/jkqtpgraphsmodel.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" diff --git a/examples/jkqtplot_test/TestWidgetParamScatterPlots.h b/examples/jkqtplot_test/TestWidgetParamScatterPlots.h index 97eed9f545..41ac5f9712 100644 --- a/examples/jkqtplot_test/TestWidgetParamScatterPlots.h +++ b/examples/jkqtplot_test/TestWidgetParamScatterPlots.h @@ -17,7 +17,7 @@ #include "jkqtplotter/jkqtpgraphsparsedfunction.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplottergui/jkqtpgraphsmodel.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #define N1 200 #define N2 50 diff --git a/examples/jkqtplot_test/TestWidgetRGBImages.h b/examples/jkqtplot_test/TestWidgetRGBImages.h index 436b31efba..6d75521901 100644 --- a/examples/jkqtplot_test/TestWidgetRGBImages.h +++ b/examples/jkqtplot_test/TestWidgetRGBImages.h @@ -18,7 +18,7 @@ #include "jkqtplotter/jkqtpgraphsparsedfunction.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplottergui/jkqtpgraphsmodel.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #define N1 200 #define N2 50 diff --git a/examples/simpletest_datastore/README.md b/examples/simpletest_datastore/README.md index f5f491c050..78779e5918 100644 --- a/examples/simpletest_datastore/README.md +++ b/examples/simpletest_datastore/README.md @@ -1,6 +1,6 @@ # Tutorial (JKQTPlotter): Basic Usage of JKQTPDatastore {#JKQTPlotterBasicJKQTPDatastore} -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. +This tutorial project (see `./examples/simpletest_datastore/`) explains several options of JKQTPDatastore, which is the class used to centrally store the data for (most) graphs on a JKQTPlotter widget. [TOC] @@ -140,6 +140,22 @@ 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) +## Iterator Interface + +Alternatively you can also access the column via a C++ iterator: +```.cpp + auto itX=datastore->begin(colX)) + auto itY=datastore->begin(colY)) + for (; itX!=datastore->end(colX); ++itX, ++itY) { + const double x=double(i)/double(Ndata)*8.0*M_PI; + *itX=x; + *itY=sin(x); + } +``` + +This, together with `JKQTPDatastore::backInserter()` allows to use `JKQTDatastore` together with algorithms from the C++ standard template libarary and other templated algorithms based on the same iterator-based interfaces (e.g. in boost). + + ## Generating Columns Preinitialized Columns @@ -177,6 +193,15 @@ You can use the methods `JKQTPDatastore::appendToColumn()` and `JKQTPDatastore:: ``` Note that this operation changes the column length (number of rows). If the memory was externally managed before, it will be internally managed afterwards! If the first append is called on a column that cannot be extended, the contents will be copied and the column will reference the new, internally managed, memory afterwards. +Alterantively there is also a `std::back_inserter`-like interface to append to a column: +```.cpp + auto it=datastore->backInserter(columnID); + for (double ii=10; ii<=20; ii++) *++it=ii; +``` + +This, together with `JKQTPDatastore::begin()` and `JKQTPDatatstore::end()` allows to use `JKQTDatastore` together with algorithms from the C++ standard template libarary and other templated algorithms based on the same iterator-based interfaces (e.g. in boost). + + ## Using Data from one Column to Calculate Another diff --git a/examples/simpletest_datastore_statistics/README.md b/examples/simpletest_datastore_statistics/README.md new file mode 100644 index 0000000000..7f844e0b9b --- /dev/null +++ b/examples/simpletest_datastore_statistics/README.md @@ -0,0 +1,235 @@ +# Tutorial (JKQTPlotter): Advanced 1-Dimensional Statistics with JKQTPDatastore {#JKQTPlotterBasicJKQTPDatastoreStatistics} + +This tutorial project (see `./examples/simpletest_datastore_statistics/`) explains several advanced functions of JKQTPDatastore in combination with the statistics library conatined in JKQTPlotter. + +[TOC] + +The source code of the main application can be found in [`jkqtplotter_simpletest_datastore_statistics.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore_statistics/jkqtplotter_simpletest_datastore_statistics.cpp). +This tutorial cites only parts of this code to demonstrate different ways of working with data for the graphs. + +## Generating different sets of random numbers + +The code segments below will fill four instances of JKQTPlotter with different statistical plots. All these plots are based on three sets of random numbers generated as shown here: +```.cpp + size_t randomdatacol1=datastore1->addColumn("random data 1"); + size_t randomdatacol2=datastore1->addColumn("random data 2"); + size_t randomdatacol3=datastore1->addColumn("random data 3"); + std::random_device rd; // random number generators: + std::mt19937 gen{rd()}; + std::uniform_int_distribution<> ddecide(0,1); + std::normal_distribution<> d1{0,1}; + std::normal_distribution<> d2{6,1.2}; + for (size_t i=0; i<150; i++) { + double v=0; + const int decide=ddecide(gen); + if (decide==0) v=d1(gen); + else v=d2(gen); + datastore1->appendToColumn(randomdatacol1, v); + if (decide==0) datastore1->appendToColumn(randomdatacol2, v); + else datastore1->appendToColumn(randomdatacol3, v); + } +``` + +The column `randomdatacol1` will contain 150 random numbers. Each one is drawn either from a normal dirstribution N(0,1) (`d1`) or N(6,1.2) (`d2`). the decision, which of the two to use is based on the result of a third random distribution ddecide, which only returns 0 or 1. The two columns `randomdatacol2` and `randomdatacol3` only collect the random numbers drawn from `d1` or `d2` respectively. +The three columns are generated empyt by calling `JKQTPDatastore::addColumn()` with only a name. Then the actual values are added by calling `JKQTPDatastore::appendToColumn()`. + + +## Basic Statistics + +The three sets of random numbers from above can be visualized e.g. by a `JKQTPPeakStreamGraph` graph with code as follows: +```.cpp + JKQTPPeakStreamGraph* gData1; + plot1box->addGraph(gData1=new JKQTPPeakStreamGraph(plot1box)); + gData1->setDataColumn(randomdatacol1); + gData1->setBaseline(-0.1); + gData1->setPeakHeight(-0.05); + gData1->setDrawBaseline(false); +``` + +This (if repeated for all three columns) results in a plot like this: + +![jkqtplotter_simpletest_datastore_statistics_dataonly](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_datastore_statistics_dataonly.png) + +Based on the raw data we can now use JKQTPlotter's statistics library to calculate some basic properties, like the average (`jkqtpstatAverage()`) or the standard deviation (`jkqtpstatStdDev()`): + +```.cpp + size_t N=0; + double mean=jkqtpstatAverage(datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), &N); + double std=jkqtpstatStdDev(datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1)); +``` + +Both statistics functions (the same as all statistics functions in the library) use an iterator-based interface, comparable to the interface of the algorithms in the C++ standard template library. To this end, the class `JKQTPDatastore` provides an iterator interface to its columns, using the functions `JKQTPDatastore::begin()` and `JKQTPDatastore::end()`. Both functions simply receive the column ID as parameter and exist in a const and a mutable variant. the latter allows to also edit the data. In addition the function `JKQTPDatastore::backInserter()` returns a back-inserter iterator (like generated for STL containers with `std::back_inserter(container)`) that also allows to append to the column. + +note that the iterator interface allows to use these functions with any container that provides such iterators (e.g. `std::vector`, `std::list`, `std::set`, `QVector`...). + +The output of these functions is shown in the image above in the plot legend/key. + +Of course, several other functions exist that calculate basic statistics from a column, e.g.: + - average/mean: `jkqtpstatAverage()`, `jkqtpstatWeightedAverage()` + - number of usable values in a range:`jkqtpstatCount()` + - minimum/maximum: `jkqtpstatMinMax()`, `jkqtpstatMin()`, `jkqtpstatMax()` + - sum: `jkqtpstatSum()` + - variance: `jkqtpstatVariance()`, `jkqtpstatWeightedVariance()` + - standard deviation: `jkqtpstatStdDev()`, `jkqtpstatWeightedStdDev()` + - skewnes`jkqtpstatSkewness()` + - statistical moments: `jkqtpstatCentralMoment()`, `jkqtpstatMoment()` + - correlation coefficients: `jkqtpstatCorrelationCoefficient()` + - median: `jkqtpstatMedian()` + - quantile: `jkqtpstatQuantile()` + - (N)MAD: `jkqtpstatMAD()`, `jkqtpstatNMAD()` + - 5-Number Summary (e.g. for boxplots): `jkqtpstat5NumberStatistics()`, `jkqtpstat5NumberStatisticsAndOutliers()`, `jkqtpstat5NumberStatisticsOfSortedVector()`, `jkqtpstat5NumberStatisticsAndOutliersOfSortedVector()` + +All these functions use all values in the given range and convert each value to a `double`, using `jkqtp_todouble()`. The return values is always a dohble. Therefore you can use these functions to calculate statistics of ranges of any type that can be converted to `double`. Values that do not result in a valid `double`are not used in calculating the statistics. Therefore you can exclude values by setting them `JKQTP_DOUBLE_NAN` (i.e. "not a number"). + + +## Boxplots + +### Standard Boxplots + +As mentioned above and shown in several other examples, JKQTPlotter supports [Boxplots](https://en.wikipedia.org/wiki/Box_plot) with the classes `JKQTPBoxplotHorizontalElement`, `JKQTPBoxplotVerticalElement`, as well as `JKQTPBoxplotHorizontal` and `JKQTPBoxplotVertical`. You can then use the 5-Number Summray functions from the statistics library to calculate the data for such a boxplot (e.g. `jkqtpstat5NumberStatistics()`) and set it up by hand. Code would look roughly like this: +```.cpp + JKQTPStat5NumberStatistics stat=jkqtpstat5NumberStatistics(data.begin(), data.end(), 0.25, .5); + JKQTPBoxplotVerticalElement* res=new JKQTPBoxplotVerticalElement(plotter); + res->setMin(stat.minimum); + res->setMax(stat.maximum); + res->setMedian(stat.median); + res->setMean(jkqtpstatAverage(first, last)); + res->setPercentile25(stat.quantile1); + res->setPercentile75(stat.quantile2); + res->setMedianConfidenceIntervalWidth(stat.IQRSignificanceEstimate()); + res->setDrawMean(true); + res->setDrawNotch(true); + res->setDrawMedian(true); + res->setDrawMinMax(true); + res->setDrawBox(true); + res->setPos(boxposX); + plotter->addGraph(res); +``` + +In order to save you the work of writing out this code, the statistics library provides "adaptors", such as `jkqtpstatAddVBoxplot()`, which basically implements the code above. Then drawing a boxplot is reduced to: + +```.cpp + JKQTPBoxplotHorizontalElement* gBox2=jkqtpstatAddHBoxplot(plot1box->getPlotter(), datastore1->begin(randomdatacol2), datastore1->end(randomdatacol2), -0.25); + gBox2->setColor(gData2->getKeyLabelColor()); + gBox2->setBoxWidthAbsolute(16); +``` + +Here `-0.25`indicates the location (on the y-axis) of the boxplot. and the plot is calculated for the data in the `JKQTPDatastore` column `randomdatacol2`. + +![jkqtplotter_simpletest_datastore_statistics_boxplots_simple](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_datastore_statistics_boxplots_simple.png) + +### Boxplots with Outliers + +Usually the boxplot draws its whiskers at the minimum and maximum value of the dataset. But if your data contains a lot of outliers, it may make sense to draw them e.g. at the 3% and 97% quantiles and the draw the outliers as additional data points. This can also be done with `jkqtpstat5NumberStatistics()`, as you can specify the minimum and maximum quantile (default is 0 and 1, i.e. the true minimum and maximum) and the resulting object contains a vector with the outlier values. Then you could add them to the JKQTPDatastore and add a scatter plot that displays them. Also this task is sped up by an "adaptor". Simply call + +```.cpp + std::pair gBox1; + gBox1=jkqtpstatAddHBoxplotAndOutliers(plot1box->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -0.3, + 0.25, 0.75, // 1. and 3. Quartile for the boxplot box + 0.03, 0.97 // Quantiles for the boxplot box whiskers' ends + ); +``` + +As you can see this restuns the `JKQTPBoxplotHorizontalElement` and in addition a `JKQTPSingleColumnSymbolsGraph` for the display of the outliers. The result looks like this: + +![jkqtplotter_simpletest_datastore_statistics_boxplots_outliers](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_datastore_statistics_boxplots_outliers.png) + + + +## Histograms + +Calculating 1D-Histograms is supported by several functions from the statistics library, e.g. `jkqtpstatHistogram1DAutoranged()`. You can use the result to fill new columns in a `JKQTPDatastore`, which can then be used to draw the histogram (here wit 15 bins, spanning the full data range): + +```.cpp + size_t histcolX=plotter->getDatastore()->addColumn(histogramcolumnBaseName+", bins"); + size_t histcolY=plotter->getDatastore()->addColumn(histogramcolumnBaseName+", values"); + jkqtpstatHistogram1DAutoranged(first, last, plotter->getDatastore()->backInserter(histcolX), plotter->getDatastore()->backInserter(histcolY), 15); + JKQTPBarVerticalGraph* resO=new JKQTPBarVerticalGraph(plotter); + resO->setXColumn(histcolX); + resO->setYColumn(histcolY); + resO->setTitle(histogramcolumnBaseName); + plotter->addGraph(resO); +``` + +Again there are "adaptors" which significanty reduce the amount of coude you have to type: + +```.cpp + JKQTPBarVerticalGraph* hist1=jkqtpstatAddHHistogram1DAutoranged(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), 15); +``` + +The resulting plot looks like this (the distributions used to generate the random data are also shown as line plots!): + +![jkqtplotter_simpletest_datastore_statistics_hist](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_datastore_statistics_hist.png) + + + +## Kernel Density Estimates (KDE) + +Especially when only few samples from a distribution are available, histograms are not good at representing the underlying data distribution. In such cases, [Kernel Density Estimates (KDE)](https://en.wikipedia.org/wiki/Kernel_density_estimation) can help, which are basically a smoothed variant of a histogram. The statistics library supports calculating them via e.g. `jkqtpstatKDE1D()`: + +```.cpp + size_t kdecolX=plotter->getDatastore()->addColumn(KDEcolumnBaseName+", bins"); + size_t kdecolY=plotter->getDatastore()->addColumn(KDEcolumnBaseName+", values"); + jkqtpstatKDE1D(first, last, -5.0,0.01,10.0, plotter->getDatastore()->backInserter(kdecolX), plotter->getDatastore()->backInserter(kdecolY), kernel, kdeBandwidth); + JKQTPXYLineGraph* resO=new JKQTPXYLineGraph(plotter); + resO->setXColumn(kdecolX); + resO->setYColumn(kdecolY); + resO->setTitle(KDEcolumnBaseName); + resO->setDrawLine(true); + resO->setSymbolType(JKQTPNoSymbol); + plotter->addGraph(resO); +``` + +The function accepts different kernel functions (any C++ functor `double f(double x)`) and provides a set of default kernels, e.g. + - `jkqtpstatKernel1DEpanechnikov()` + - `jkqtpstatKernel1DGaussian()` + - `jkqtpstatKernel1DUniform()` + - ... + +The three parameters `-5.0, 0.01, 10.0` tell the function `jkqtpstatKDE1D()` to evaluate the KDE at positions between -5 and 10, in steps of 0.01. + +Finally the bandwidth constrols the smoothing and the statistics library provides a simple function to estimate it automatically from the data: +```.cpp + double kdeBandwidth=jkqtpstatEstimateKDEBandwidth(datastore1->begin(randomdatacol1subset), datastore1->end(randomdatacol1subset)); +``` + +Again a shortcut "adaptor" simplifies this task: + +```.cpp + JKQTPXYLineGraph* kde2=jkqtpstatAddHKDE1D(plot1kde->getPlotter(), datastore1->begin(randomdatacol1subset), datastore1->end(randomdatacol1subset), + // evaluate at locations between -5 and 10, in steps of 0.01 (equivalent to the line above, but without pre-calculating a vector) + -5.0,0.01,10.0, + // use a gaussian kernel + &jkqtpstatKernel1DEpanechnikov, + // estimate the bandwidth + kdeBandwidth); +``` + +Plots that result from such calls look like this: + +![jkqtplotter_simpletest_datastore_statistics_kde](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_datastore_statistics_kde.png) + + +## Cummulative Histograms and KDEs + +Both histograms and KDEs support a parameter `bool cummulative`, which allows to accumulate the data after calculation and drawing cummulative histograms/KDEs: + +```.cpp + JKQTPBarVerticalGraph* histcum2=jkqtpstatAddHHistogram1DAutoranged(plot1cum->getPlotter(), datastore1->begin(randomdatacol2), datastore1->end(randomdatacol2), + // bin width + 0.1, + // normalized, cummulative + false, true); +``` + +![jkqtplotter_simpletest_datastore_statistics_cumhistkde](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_datastore_statistics_cumhistkde.png) + + + +## Screenshot of the full Program + +The output of the full test program [`jkqtplotter_simpletest_datastore_statistics.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_datastore_statistics/jkqtplotter_simpletest_datastore_statistics.cpp) looks like this: + +![jkqtplotter_simpletest_datastore_statistics](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/jkqtplotter_simpletest_datastore_statistics.png) + + diff --git a/examples/simpletest_datastore_statistics/jkqtplotter_simpletest_datastore_statistics.cpp b/examples/simpletest_datastore_statistics/jkqtplotter_simpletest_datastore_statistics.cpp new file mode 100644 index 0000000000..ce3fcfc6d2 --- /dev/null +++ b/examples/simpletest_datastore_statistics/jkqtplotter_simpletest_datastore_statistics.cpp @@ -0,0 +1,289 @@ +/** \example jkqtplotter_simpletest_datastore_statistics.cpp + * Explains how to use the internal statistics library (see \ref jkqtptools_statistics ) together with JKQTPDatastore to generate advanced plots for 1-dimensional data. + * + * \ref JKQTPlottersimpletest_datastore_statistics + */ + +#include +#include "jkqtplotter/jkqtplotter.h" +#include "jkqtplotter/jkqtpgraphspeakstream.h" +#include "jkqtplotter/jkqtpgraphsboxplot.h" +#include "jkqtplotter/jkqtpgraphsstatisticsadaptors.h" +#include "jkqtplotter/jkqtpgraphsevaluatedfunction.h" +#include "jkqtcommon/jkqtpstatisticstools.h" +#include "jkqtcommon/jkqtpstringtools.h" +#include +#include + + +int main(int argc, char* argv[]) +{ + QApplication app(argc, argv); + + + // 1. create a window with several plotters and get a pointer to the internal datastores (for convenience) + QWidget mainWidget; + QGridLayout* lay; + mainWidget.setLayout(lay=new QGridLayout); + JKQTPlotter* plot1=new JKQTPlotter(&mainWidget); + plot1->getPlotter()->setPlotLabel("Histograms and KDE"); + JKQTPDatastore* datastore1=plot1->getDatastore(); + lay->addWidget(plot1,1,0); + JKQTPlotter* plot1cum=new JKQTPlotter(datastore1, &mainWidget); + plot1cum->getPlotter()->setPlotLabel("Cummulative Histogram"); + lay->addWidget(plot1cum,1,1); + JKQTPlotter* plot1kde=new JKQTPlotter(datastore1, &mainWidget); + plot1kde->getPlotter()->setPlotLabel("Kernel Density Estimate"); + lay->addWidget(plot1kde,0,1); + JKQTPlotter* plot1box=new JKQTPlotter(datastore1, &mainWidget); + plot1box->getPlotter()->setPlotLabel("Boxplots"); + lay->addWidget(plot1box,0,0); + + + // 2. Now we create two vectors with random values + // vector 1: The values are drawn from two different normal distributions d1 and d2, + // where for each datapoint the distribution is chosen randomly (by ddecide) + // vector 2: same values as in vector 1, if the value is drawn from d1 + // vector 3: same values as in vector 1, if the value is drawn from d2 + size_t randomdatacol1=datastore1->addColumn("random data 1"); + size_t randomdatacol2=datastore1->addColumn("random data 2"); + size_t randomdatacol3=datastore1->addColumn("random data 3"); + std::random_device rd; // random number generators: + std::mt19937 gen{rd()}; + std::uniform_int_distribution<> ddecide(0,1); + std::normal_distribution<> d1{0,1}; + std::normal_distribution<> d2{6,1.2}; + for (size_t i=0; i<150; i++) { + double v=0; + const int decide=ddecide(gen); + if (decide==0) v=d1(gen); + else v=d2(gen); + datastore1->appendToColumn(randomdatacol1, v); + if (decide==0) datastore1->appendToColumn(randomdatacol2, v); + else datastore1->appendToColumn(randomdatacol3, v); + } + QString d1_latex="$\\mathcal{N}("+jkqtp_floattolatexqstr(d1.mean(), 1)+","+jkqtp_floattolatexqstr(d1.stddev(), 1)+")$"; + QString d2_latex="$\\mathcal{N}("+jkqtp_floattolatexqstr(d2.mean(), 1)+","+jkqtp_floattolatexqstr(d2.stddev(), 1)+")$"; + + // 3.1. To visualize the data, a simple JKQTPPeakStreamGraph is used: + JKQTPPeakStreamGraph* gData1; + plot1box->addGraph(gData1=new JKQTPPeakStreamGraph(plot1box)); + gData1->setDataColumn(randomdatacol1); + gData1->setBaseline(-0.1); + gData1->setPeakHeight(-0.05); + gData1->setDrawBaseline(false); + // 3.2. We calculate some basic statistics of that column and display it in the graph legend (via the graph title): + // Here we use functions of the statistics library for the first time. The statistics library uses an iterator interface + // scheme, much like the algorithms of the C++ standard library. Therefore we the iterator interface of JKQTPDatastore + // when calling the statistics functions. + size_t N=0; + double mean=jkqtpstatAverage(datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), &N); + double std=jkqtpstatStdDev(datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1)); + gData1->setTitle(QString("random data $"+d1_latex+"+"+d2_latex+"$: $\\overline{X_1}=%1, \\sigma_{X_1}=%2, N_{X_3}=%3$").arg(jkqtp_floattolatexqstr(mean, 2)).arg(jkqtp_floattolatexqstr(std, 2)).arg(N)); + + // 3.3. same as 3.1-3.2, but for the second and thirdcolumn of data: + JKQTPPeakStreamGraph* gData2; + plot1box->addGraph(gData2=new JKQTPPeakStreamGraph(plot1box)); + gData2->setDataColumn(randomdatacol2); + gData2->setBaseline(-0.1); + gData2->setPeakHeight(0.05); + gData2->setDrawBaseline(false); + N=0; + mean=jkqtpstatAverage(datastore1->begin(randomdatacol2), datastore1->end(randomdatacol2), &N); + std=jkqtpstatStdDev(datastore1->begin(randomdatacol2), datastore1->end(randomdatacol2)); + gData2->setTitle(QString("random data subset $"+d1_latex+"$: $\\overline{X_2}=%1, \\sigma_{X_3}=%2, N_{X_3}=%3$").arg(jkqtp_floattolatexqstr(mean, 2)).arg(jkqtp_floattolatexqstr(std, 2)).arg(N)); + JKQTPPeakStreamGraph* gData3; + plot1box->addGraph(gData3=new JKQTPPeakStreamGraph(plot1box)); + gData3->setDataColumn(randomdatacol3); + gData3->setBaseline(-0.15); + gData3->setPeakHeight(-0.05); + gData3->setDrawBaseline(false); + N=0; + mean=jkqtpstatAverage(datastore1->begin(randomdatacol3), datastore1->end(randomdatacol3), &N); + std=jkqtpstatStdDev(datastore1->begin(randomdatacol3), datastore1->end(randomdatacol3)); + gData3->setTitle(QString("random data subset $"+d2_latex+"$: $\\overline{X_3}=%1, \\sigma_{X_3}=%2, N_{X_3}=%3$").arg(jkqtp_floattolatexqstr(mean, 2)).arg(jkqtp_floattolatexqstr(std, 2)).arg(N)); + + + // 3.4. Now we calculate a 5-Value Summary of the two datasets and use it to plot corresponding boxplots + // This can be done by hand, or you can call jkqtpstatAddHBoxplot() which saves some typing. This function + // uses jkqtpstat5NumberStatistics() internally to calculate the statistics. + JKQTPBoxplotHorizontalElement* gBox2=jkqtpstatAddHBoxplot(plot1box->getPlotter(), datastore1->begin(randomdatacol2), datastore1->end(randomdatacol2), -0.25); + gBox2->setColor(gData2->getKeyLabelColor()); + gBox2->setBoxWidthAbsolute(16); + JKQTPBoxplotHorizontalElement* gBox3=jkqtpstatAddHBoxplot(plot1box->getPlotter(), datastore1->begin(randomdatacol3), datastore1->end(randomdatacol3), -0.35); + gBox3->setColor(gData3->getKeyLabelColor()); + gBox3->setBoxWidthAbsolute(16); + // 3.5. In addition to jkqtpstatAddHBoxplot() there is also jkqtpstatAddHBoxplotAndOutliers(), which generates two graphs: + // one JKQTPBoxplotHorizontalElement for the boxplot and one JKQTPSingleColumnSymbolsGraph for the outliers + // Note that this function generates additional data columns in the datastore of the provided plotter to represent + // the outlier locations. + // jkqtpstatAddHBoxplotAndOutliers() calculates the 3% and 97% Quantiles for the boxplots whiskers' ends. You can change that + // by supplying other quantiles to the call + std::pair gBox1=jkqtpstatAddHBoxplotAndOutliers(plot1box->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -0.3); + // jkqtpstatAddHBoxplotAndOutliers() calculates the 3% and 97% Quantiles for the boxplots whiskers' ends. You can change that + // by supplying other quantiles to the call + //std::pair gBox1=jkqtpstatAddHBoxplotAndOutliers(plot1box->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -0.3, + // 0.25, 0.75, // 1. and 3. Quartile for the boxplot box + // 0.05, 0.95 // Quantiles for the boxplot box whiskers' ends + // ); + gBox1.first->setColor(gData1->getKeyLabelColor()); + gBox1.second->setColor(gData1->getKeyLabelColor()); + gBox1.second->setSymbolType(JKQTPGraphSymbols::JKQTPCircle); + gBox1.second->setSymbolSize(7); + gBox1.first->setBoxWidthAbsolute(16); + // the simple alternative would have been: + //JKQTPBoxplotHorizontalElement* gBox1; + //plot1box->addGraph(gBox1=jkqtpstatAddHBoxplot(plot1box->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1))); + //gBox1->setPos(-0.3); + //gBox1->setColor(gData1->getKeyLabelColor()); + //gBox1->setBoxWidthAbsolute(16); + + + + + // 4.1. We repeat the JKQTPPeakStreamGraph visualization from above: + plot1->addGraph(gData1=new JKQTPPeakStreamGraph(plot1)); + gData1->setDataColumn(randomdatacol1); + gData1->setBaseline(-0.1); + gData1->setPeakHeight(-0.05); + gData1->setDrawBaseline(false); + gData1->setTitle("random data $"+d1_latex+"+"+d2_latex+"$"); + + // 4.2. same as 3.1-3.2, but for the second and thirdcolumn of data: + plot1->addGraph(gData2=new JKQTPPeakStreamGraph(plot1)); + gData2->setDataColumn(randomdatacol2); + gData2->setBaseline(-0.1); + gData2->setPeakHeight(0.05); + gData2->setDrawBaseline(false); + gData2->setTitle("random data subset $"+d1_latex+"$"); + plot1->addGraph(gData3=new JKQTPPeakStreamGraph(plot1)); + gData3->setDataColumn(randomdatacol3); + gData3->setBaseline(-0.15); + gData3->setPeakHeight(-0.05); + gData3->setDrawBaseline(false); + gData3->setTitle("random data subset $"+d2_latex+"$"); + + // 4.3. for comparison we add plots of the initial distributions: + plot1->addGraph(new JKQTPXFunctionLineGraph(std::bind(&jkqtp_gaussdist, std::placeholders::_1, d1.mean(), d1.stddev()), d1_latex, plot1)); + plot1->addGraph(new JKQTPXFunctionLineGraph(std::bind(&jkqtp_gaussdist, std::placeholders::_1, d2.mean(), d2.stddev()), d2_latex, plot1)); + + + + // 4.1. next we calculate a histogram of the data and add a plot to the graph: + JKQTPBarVerticalGraph* hist1=jkqtpstatAddHHistogram1DAutoranged(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), 15); + // here the bins are defined by the full range of the data and the bin count (15) is specified + // alternatively you could specify the bin width and the number would be calculated automatically: + //JKQTPBarVerticalGraph* hist1=jkqtpstatAddHHistogram1DAutoranged(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), 0.5); + // a third option is to define the bins via a vector of values (lower borders): + //std::vector bins{-2,-1.5,-1,-0.75,-0.5,-0.25,0,0.25,0.5,0.75,1,1.5,2,2.5,3,4,5,6,7,8,9,10}; + //JKQTPBarVerticalGraph* hist1=jkqtpstatAddHHistogram1D(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), bins.begin(), bins.end()); + hist1->setColor(QColorWithAlphaF(gData1->getKeyLabelColor(), 0.5)); // use same color as gData1, but with alpha set to 0.5 (50% transparency) + + + + + // 5.1. instead of histograms, it can also make sense to calculate Kernel Density Estimates, especially when only few datapoints are available. + // To demonstrate this, we first calculate take a subset of the values in randomdatacol1 as a small test dataset. + size_t randomdatacol1subset=datastore1->copyColumn(randomdatacol1, 1, 7, "subset of "+datastore1->getColumnName(randomdatacol1)); + JKQTPPeakStreamGraph* gData2kde; + plot1kde->addGraph(gData2kde=new JKQTPPeakStreamGraph(plot1kde)); + gData2kde->setDataColumn(randomdatacol1subset); + gData2kde->setBaseline(-0.05); + gData2kde->setPeakHeight(-0.1); + gData2kde->setDrawBaseline(false); + gData2kde->setTitle("data"); + // first we plot the histogram of this dataset, with 0.5 bin width: + JKQTPBarVerticalGraph* hist1kde=jkqtpstatAddHHistogram1DAutoranged(plot1kde->getPlotter(), datastore1->begin(randomdatacol1subset), datastore1->end(randomdatacol1subset), 0.5); + hist1kde->setTitle("histogram"); + hist1kde->setColor(QColorWithAlphaF(gData2kde->getKeyLabelColor(), 0.25)); // use same color as gData1, but with alpha set to 0.5 (50% transparency) + // 5.2. now we first extimate the bandwidth: + double kdeBandwidth=jkqtpstatEstimateKDEBandwidth(datastore1->begin(randomdatacol1subset), datastore1->end(randomdatacol1subset)); + // and generate a vector of positions, where we want to evaluate the KDE: + std::vector xKDE; + for (double x=-5; x<=10; x+=0.01) xKDE.push_back(x); + // now the KDE can be added (gaussian kernel, evaluated at the positions in xKDE): + JKQTPXYLineGraph* kde1=jkqtpstatAddHKDE1D(plot1kde->getPlotter(), datastore1->begin(randomdatacol1subset), datastore1->end(randomdatacol1subset), + // evaluate at locations in xKDE + xKDE.begin(), xKDE.end(), + // use a gaussian kernel + &jkqtpstatKernel1DGaussian, + // estimate the bandwidth + kdeBandwidth); + kde1->setTitle("KDE, gaussian, $\\mbox{BW}="+jkqtp_floattolatexqstr(kdeBandwidth, 3)+"$"); + JKQTPXYLineGraph* kde11=jkqtpstatAddHKDE1D(plot1kde->getPlotter(), datastore1->begin(randomdatacol1subset), datastore1->end(randomdatacol1subset), + // evaluate at locations in xKDE + xKDE.begin(), xKDE.end(), + // use a gaussian kernel + &jkqtpstatKernel1DGaussian, + // a very small bandwidth + 0.1); + kde11->setTitle("KDE, gaussian, $\\mbox{BW}="+jkqtp_floattolatexqstr(0.1, 3)+"$"); + // here a second KDE with a different kernel (Epanechnikov) and the range of evaluation positions defined via three numbers: + JKQTPXYLineGraph* kde2=jkqtpstatAddHKDE1D(plot1kde->getPlotter(), datastore1->begin(randomdatacol1subset), datastore1->end(randomdatacol1subset), + // evaluate at locations between -5 and 10, in steps of 0.01 (equivalent to the line above, but without pre-calculating a vector) + -5.0,0.01,10.0, + // use a gaussian kernel + &jkqtpstatKernel1DEpanechnikov, + // estimate the bandwidth + kdeBandwidth); + kde2->setTitle("KDE, epanechnikov, $\\mbox{BW}="+jkqtp_floattolatexqstr(kdeBandwidth, 3)+"$"); + kde1->setColor(QColorWithAlphaF(gData2kde->getKeyLabelColor(), 0.5)); // use same color as gData1, but with alpha set to 0.5 (50% transparency) + // 5.3. for comparison we add plots of the initial distributions: + plot1kde->addGraph(new JKQTPXFunctionLineGraph(std::bind(&jkqtp_gaussdist, std::placeholders::_1, d1.mean(), d1.stddev()), d1_latex, plot1)); + plot1kde->addGraph(new JKQTPXFunctionLineGraph(std::bind(&jkqtp_gaussdist, std::placeholders::_1, d2.mean(), d2.stddev()), d2_latex, plot1)); + + + + // 6.1. now we calculate a cummulative histogram: + JKQTPPeakStreamGraph* gData2com; + plot1cum->addGraph(gData2com=new JKQTPPeakStreamGraph(plot1cum)); + gData2com->setDataColumn(randomdatacol2); + gData2com->setBaseline(-1); + gData2com->setPeakHeight(-10); + gData2com->setDrawBaseline(false); + JKQTPBarVerticalGraph* histcum2=jkqtpstatAddHHistogram1DAutoranged(plot1cum->getPlotter(), datastore1->begin(randomdatacol2), datastore1->end(randomdatacol2), + // bin width + 0.1, + // normalized, cummulative + false, true); + histcum2->setColor(QColorWithAlphaF(gData2com->getKeyLabelColor(), 0.2)); // use same color as gData1, but with alpha set to 0.5 (50% transparency) + // 6.2. also a kernel density estimate can be accumulated: + JKQTPXYLineGraph* kdecum2=jkqtpstatAddHKDE1D(plot1cum->getPlotter(), datastore1->begin(randomdatacol2), datastore1->end(randomdatacol2), + // evaluate at locations between -3.5 and 3.5, in steps of 0.01 + -3.5,0.01,3.5, + // use a uniform/box kernel + &jkqtpstatKernel1DUniform, + // estimate the bandwidth + jkqtpstatEstimateKDEBandwidth(datastore1->begin(randomdatacol2), datastore1->end(randomdatacol2)), + // cummulative KDE: + true); + kdecum2->setColor(gData2com->getKeyLabelColor()); // use same color as gData1, but with alpha set to 0.5 (50% transparency) + + + // autoscale the plot so the graph is contained + plot1->zoomToFit(); + plot1->setGrid(false); + plot1->getXAxis()->setShowZeroAxis(false); + plot1->getPlotter()->setKeyBackgroundColor(QColorWithAlphaF("white", 0.25), Qt::SolidPattern); + plot1->setY(-0.25, 0.45); + plot1cum->zoomToFit(); + plot1cum->setGrid(false); + plot1cum->getXAxis()->setShowZeroAxis(false); + plot1cum->getPlotter()->setKeyBackgroundColor(QColorWithAlphaF("white", 0.25), Qt::SolidPattern); + plot1kde->zoomToFit(); + plot1kde->setGrid(false); + plot1kde->getXAxis()->setShowZeroAxis(false); + plot1kde->getPlotter()->setKeyBackgroundColor(QColorWithAlphaF("white", 0.25), Qt::SolidPattern); + plot1kde->setY(-0.155, 0.45); + plot1box->zoomToFit(); + plot1box->setGrid(false); + plot1box->getXAxis()->setShowZeroAxis(false); + plot1box->getPlotter()->setKeyBackgroundColor(QColorWithAlphaF("white", 0.25), Qt::SolidPattern); + plot1box->setY(-0.4, 0.0); + + // show plotter and make it a decent size + mainWidget.show(); + mainWidget.resize(1200,800); + + return app.exec(); +} diff --git a/examples/simpletest_datastore_statistics/jkqtplotter_simpletest_datastore_statistics.pro b/examples/simpletest_datastore_statistics/jkqtplotter_simpletest_datastore_statistics.pro new file mode 100644 index 0000000000..aeae323cfd --- /dev/null +++ b/examples/simpletest_datastore_statistics/jkqtplotter_simpletest_datastore_statistics.pro @@ -0,0 +1,26 @@ +# source code for this simple demo +SOURCES = jkqtplotter_simpletest_datastore_statistics.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_statistics + +# 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_statistics/jkqtplotter_simpletest_datastore_statistics_and_lib.pro b/examples/simpletest_datastore_statistics/jkqtplotter_simpletest_datastore_statistics_and_lib.pro new file mode 100644 index 0000000000..1b65492102 --- /dev/null +++ b/examples/simpletest_datastore_statistics/jkqtplotter_simpletest_datastore_statistics_and_lib.pro @@ -0,0 +1,8 @@ +TEMPLATE = subdirs + +SUBDIRS += jkqtplotterlib jkqtplotter_simpletest_datastore_statistics + +jkqtplotterlib.file = ../../staticlib/jkqtplotterlib/jkqtplotterlib.pro + +jkqtplotter_simpletest_datastore_statistics.file=$$PWD/jkqtplotter_simpletest_datastore_statistics.pro +jkqtplotter_simpletest_datastore_statistics.depends = jkqtplotterlib diff --git a/examples/simpletest_dateaxes/jkqtplotter_simpletest_dateaxes.cpp b/examples/simpletest_dateaxes/jkqtplotter_simpletest_dateaxes.cpp index 0f1abb6c46..431a9a80e5 100644 --- a/examples/simpletest_dateaxes/jkqtplotter_simpletest_dateaxes.cpp +++ b/examples/simpletest_dateaxes/jkqtplotter_simpletest_dateaxes.cpp @@ -12,7 +12,7 @@ #include "jkqtplotter/jkqtplotter.h" #include "jkqtplotter/jkqtpgraphsscatter.h" #include "jkqtplotter/jkqtpgraphsgeometric.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtplotter/jkqtpgraphsfilledcurve.h" void drawWithDateAxis(JKQTPlotter& plot) { diff --git a/examples/simpletest_errorbarstyles/jkqtplotter_simpletest_errorbarstyles.cpp b/examples/simpletest_errorbarstyles/jkqtplotter_simpletest_errorbarstyles.cpp index 63dfe92786..5fb391e2da 100644 --- a/examples/simpletest_errorbarstyles/jkqtplotter_simpletest_errorbarstyles.cpp +++ b/examples/simpletest_errorbarstyles/jkqtplotter_simpletest_errorbarstyles.cpp @@ -7,7 +7,7 @@ #include #include "jkqtplotter/jkqtplotter.h" #include "jkqtplotter/jkqtpgraphsscatter.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" int main(int argc, char* argv[]) diff --git a/examples/simpletest_logaxes/jkqtplotter_simpletest_logaxes.cpp b/examples/simpletest_logaxes/jkqtplotter_simpletest_logaxes.cpp index 546494fdd2..218760349c 100644 --- a/examples/simpletest_logaxes/jkqtplotter_simpletest_logaxes.cpp +++ b/examples/simpletest_logaxes/jkqtplotter_simpletest_logaxes.cpp @@ -8,7 +8,7 @@ #include "jkqtplotter/jkqtplotter.h" #include "jkqtplotter/jkqtpgraphsscatter.h" #include "jkqtplotter/jkqtpgraphsgeometric.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #define sqr(x) ((x)*(x)) diff --git a/examples/simpletest_parsedfunctionplot/README.md b/examples/simpletest_parsedfunctionplot/README.md index 90c0782976..a60f5f8d84 100644 --- a/examples/simpletest_parsedfunctionplot/README.md +++ b/examples/simpletest_parsedfunctionplot/README.md @@ -10,7 +10,7 @@ Adding an evaluated funtion to a graph is very simple: parsedFunc->setFunction("sin(x*8)*exp(-x/4)"); parsedFunc->setTitle("user function"); ``` -As you can see a graph of the type `JKQTPXParsedFunctionLineGraph` is used, which plots a function that depends on the variable `x`. The given function is parsed and evaluated (see [`lib/jkqtplottertools/jkqtpmathparser.h`](https://github.com/jkriege2/JKQTPlotter/blob/master/lib/jkqtplottertools/jkqtpmathparser.h) for details on the features of the math parser). An intelligent drawing algorithm chooses the number of control points for drawing a smooth graph, with sufficient amount of details, by evaluating locally the slope of the function. +As you can see a graph of the type `JKQTPXParsedFunctionLineGraph` is used, which plots a function that depends on the variable `x`. The given function is parsed and evaluated (see [`lib/jkqtcommon/jkqtpmathparser.h`](https://github.com/jkriege2/JKQTPlotter/blob/master/lib/jkqtcommon/jkqtpmathparser.h) for details on the features of the math parser). An intelligent drawing algorithm chooses the number of control points for drawing a smooth graph, with sufficient amount of details, by evaluating locally the slope of the function. In the example in [`test/simpletest_parsedfunctionplot/simpletest_parsedfunctionplot.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/simpletest_parsedfunctionplot/simpletest_parsedfunctionplot.cpp) we do not simply set a fixed function, but add a `QLineEdit` which allows to edit the function and redraws it, once ENTER is pressed: ```.cpp diff --git a/examples/simpletest_stepplots/jkqtplotter_simpletest_stepplots.cpp b/examples/simpletest_stepplots/jkqtplotter_simpletest_stepplots.cpp index 2041059990..b81f951c59 100644 --- a/examples/simpletest_stepplots/jkqtplotter_simpletest_stepplots.cpp +++ b/examples/simpletest_stepplots/jkqtplotter_simpletest_stepplots.cpp @@ -8,7 +8,7 @@ #include "jkqtplotter/jkqtplotter.h" #include "jkqtplotter/jkqtpgraphsscatter.h" #include "jkqtplotter/jkqtpgraphsspecialline.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" int main(int argc, char* argv[]) { diff --git a/examples/simpletest_stepplots/jkqtplotter_simpletest_stepplots_vertical.cpp b/examples/simpletest_stepplots/jkqtplotter_simpletest_stepplots_vertical.cpp index 5d37c033ce..999088e700 100644 --- a/examples/simpletest_stepplots/jkqtplotter_simpletest_stepplots_vertical.cpp +++ b/examples/simpletest_stepplots/jkqtplotter_simpletest_stepplots_vertical.cpp @@ -8,7 +8,7 @@ #include "jkqtplotter/jkqtplotter.h" #include "jkqtplotter/jkqtpgraphsscatter.h" #include "jkqtplotter/jkqtpgraphsspecialline.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" int main(int argc, char* argv[]) { diff --git a/examples/simpletest_symbols_and_styles/jkqtplotter_simpletest_symbols_and_styles.cpp b/examples/simpletest_symbols_and_styles/jkqtplotter_simpletest_symbols_and_styles.cpp index dee36e61e8..a7e9bcee4a 100644 --- a/examples/simpletest_symbols_and_styles/jkqtplotter_simpletest_symbols_and_styles.cpp +++ b/examples/simpletest_symbols_and_styles/jkqtplotter_simpletest_symbols_and_styles.cpp @@ -7,7 +7,7 @@ #include #include "jkqtplotter/jkqtplotter.h" #include "jkqtplotter/jkqtpgraphsscatter.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" int main(int argc, char* argv[]) diff --git a/lib/README.md b/lib/README.md index 389a994067..853da3147c 100644 --- a/lib/README.md +++ b/lib/README.md @@ -7,6 +7,7 @@ If you use QMake and simply want to include all necessary files into your projec - `jkqtplotter.pri` contains all files in this library, including `JKQTFastPlotter` and `JKQTMathText` - `jkqtfastplotter.pri` contains only those files from this directory which are necessary to build `JKQTFastPlotter` - `jkqtmathtext.pri` contains only those files from this directory which are necessary to build `JKQTMathText` +- `jkqtpcommon.pri` common support library for all libraries above (math tools, basic drawing tools, ...) ### Build static libraries In the directory [`../staticlib`](../staticlib) you will find several Project files that build a static library of the full JKQTPlotter (including JKQTFastPlotter and JKMathText), or of subsets of this library. You can then link against these libs in your project. diff --git a/lib/common.pri b/lib/common.pri deleted file mode 100644 index 07e5ad83cc..0000000000 --- a/lib/common.pri +++ /dev/null @@ -1,33 +0,0 @@ - -!win32-msvc* { - QMAKE_CXXFLAGS += -fexceptions -} else { - QMAKE_CXXFLAGS += /EHsc - # /std:c++14 - # To enable M_PI, M_E,... - DEFINES += _USE_MATH_DEFINES - # To fix error: C2338: va_start argument must not - # have reference type and must not be parenthesized - DEFINES += _CRT_NO_VA_START_VALIDATION -} - -HEADERS += $$PWD/jkqtcommon/jkqtp_imexport.h \ - $$PWD/jkqtcommon/jkqtptools.h \ - $$PWD/jkqtcommon/jkqtptoolsdebugging.h \ - $$PWD/jkqtcommon/jkqtpcommonmathtools.h \ - $$PWD/jkqtcommon/jkqtpalgorithms.h \ - $$PWD/jkqtcommon/jkqtpstringtools.h - - -SOURCES += $$PWD/jkqtcommon/jkqtptools.cpp \ - $$PWD/jkqtcommon/jkqtptoolsdebugging.cpp \ - $$PWD/jkqtcommon/jkqtpcommonmathtools.cpp \ - $$PWD/jkqtcommon/jkqtpalgorithms.cpp \ - $$PWD/jkqtcommon/jkqtpstringtools.cpp - -INCLUDEPATH += $$PWD - -QT += core gui -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport - -CONFIG += c++11 diff --git a/lib/jkqtcommon/jkqtparraytools.cpp b/lib/jkqtcommon/jkqtparraytools.cpp new file mode 100644 index 0000000000..15a14b0d06 --- /dev/null +++ b/lib/jkqtcommon/jkqtparraytools.cpp @@ -0,0 +1,24 @@ +/* + Copyright (c) 2008-2019 Jan W. Krieger () + + last modification: $LastChangedDate$ (revision $Rev$) + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + + + +#include "jkqtparraytools.h" + + diff --git a/lib/jkqtcommon/jkqtparraytools.h b/lib/jkqtcommon/jkqtparraytools.h new file mode 100644 index 0000000000..41f9dbd341 --- /dev/null +++ b/lib/jkqtcommon/jkqtparraytools.h @@ -0,0 +1,223 @@ +/* + Copyright (c) 2008-2019 Jan W. Krieger () + + last modification: $LastChangedDate$ (revision $Rev$) + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + + +#ifndef JKQTPARRAYTOOLS_H_INCLUDED +#define JKQTPARRAYTOOLS_H_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "jkqtcommon/jkqtp_imexport.h" + + +#ifdef _OPENMP +# include +#endif + +#ifndef __LINUX__ +# if defined(linux) +# define __LINUX__ +# endif +#endif + +#ifdef __LINUX__ +#include +#include +#endif + +#ifndef JKQTP_ALIGNMENT_BYTES +#define JKQTP_ALIGNMENT_BYTES 32 +#endif + + + + + +/*! \brief malloc() for use herein (aligned on some systems!) + \ingroup jkqtptools_math_array + +*/ +inline void* jkqtpArrayMalloc(size_t size) { +// std::cout<<"statisticsMalloc("< +inline void jkqtpArraySwap(T* a, long long l, long long r){ + const T tmp=a[l]; + a[l]=a[r]; + a[r]=tmp; +} + +/*! \brief swap two elements \a l and \a r in an array \a a + \ingroup jkqtptools_math_array + +*/ +template +inline void jkqtpArraySwapV(std::vector& a, long long l, long long r){ + const T tmp=a[l]; + a[l]=a[r]; + a[r]=tmp; +} + + + +/*! \brief duplicate an array of data + \ingroup jkqtptools_math_array + + \note use jkqtpArrayFree() to free the memory!!! +*/ +template +inline T* jkqtpArrayDuplicate(const T* dataIn, long long N) { +// std::cout<<"statisticsDuplicateArray("<(jkqtpArrayMalloc(N*sizeof(T))); + if (out) memcpy(out, dataIn, N*sizeof(T)); + return out; +} + + + + +/*! \brief this class ensures that the given pointer is jkqtpArrayFreed when the class is destroyed. + \ingroup jkqtptools_math_array + +*/ +template +class JKQTPArrayScopedPointer { + public: + inline explicit JKQTPArrayScopedPointer(T* pnt) { + pntr=pnt; + } + inline explicit JKQTPArrayScopedPointer() { + pntr=nullptr; + } + inline explicit JKQTPArrayScopedPointer(const JKQTPArrayScopedPointer& other) { + pntr=other.pntr; + } + + + ~JKQTPArrayScopedPointer() { + if (pntr) jkqtpArrayFree(pntr); + } + + + inline JKQTPArrayScopedPointer& operator=(T* p) { + pntr=p; + return *this; + } + + inline JKQTPArrayScopedPointer& operator=(const JKQTPArrayScopedPointer& p) { + pntr=p.pntr; + return *this; + } + + inline T& operator*() const { return *pntr; } + inline T* operator->() const { return pntr; } + inline T* data() const { return pntr; } + inline T& operator[](long long i) { + return pntr[i]; + } + inline const T& operator[](long long i) const { + return pntr[i]; + } + + + + private: + T* pntr; +}; + +#endif // JKQTPARRAYTOOLS_H_INCLUDED + + diff --git a/lib/jkqtplottertools/jkqtpimagetools.cpp b/lib/jkqtcommon/jkqtpbasicimagetools.cpp similarity index 84% rename from lib/jkqtplottertools/jkqtpimagetools.cpp rename to lib/jkqtcommon/jkqtpbasicimagetools.cpp index 75457029b8..deef202231 100644 --- a/lib/jkqtplottertools/jkqtpimagetools.cpp +++ b/lib/jkqtcommon/jkqtpbasicimagetools.cpp @@ -17,16 +17,11 @@ along with this program. If not, see . */ -#include "jkqtplottertools/jkqtpimagetools.h" +#include "jkqtcommon/jkqtpbasicimagetools.h" #include #include #include #include -#ifndef NO_JKQTPLOTTER -#include "jkqtplotter/jkqtpbaseelements.h" -#include "jkqtplotter/jkqtpbaseplotter.h" -#include "jkqtplottertools/jkqtpdrawingtools.h" -#endif #ifdef QT_XML_LIB # include #endif @@ -1821,323 +1816,6 @@ QImage JKQTPMathImageGetAlphaPaletteImage(int *lut, int lut_size, int width, int -#ifndef NO_JKQTPLOTTER - - - -JKQTPColorPaletteTools::JKQTPColorPaletteTools(JKQTBasePlotter *parent) -{ - cbParent=parent; - colorBarRightAxis=new JKQTPVerticalIndependentAxis(0, 100, 0, 100, parent); - colorBarRightAxis->setDrawMode1(JKQTPCADMLine); - colorBarRightAxis->setDrawMode2(JKQTPCADMcomplete); - colorBarRightAxis->setAxisLabel(""); - colorBarRightAxis->setMinTicks(3); - colorBarRightAxis->setShowZeroAxis(false); - colorBarRightAxis->setMinorTicks(0); - colorBarRightAxis->setTickOutsideLength(0); - colorBarRightAxis->setMinorTickOutsideLength(0); - colorBarTopAxis=new JKQTPHorizontalIndependentAxis(0, 100, 0, 100, parent); - colorBarTopAxis->setDrawMode1(JKQTPCADMLine); - colorBarTopAxis->setDrawMode2(JKQTPCADMcomplete); - colorBarTopAxis->setAxisLabel(""); - colorBarTopAxis->setMinTicks(3); - colorBarTopAxis->setShowZeroAxis(false); - colorBarTopAxis->setMinorTicks(0); - colorBarTopAxis->setTickOutsideLength(0); - colorBarTopAxis->setMinorTickOutsideLength(0); - - - this->palette=JKQTPMathImageMATLAB; - this->imageNameFontName=parent->getDefaultTextFontName(); - this->imageNameFontSize=parent->getDefaultTextSize(); - this->imageName=""; - this->showColorBar=true; - this->colorBarWidth=14; - this->colorBarRelativeHeight=0.75; - this->autoImageRange=true; - this->imageMin=0; - this->imageMax=1; - this->colorBarOffset=4; - this->rangeMinFailAction=JKQTPMathImageLastPaletteColor; - this->rangeMaxFailAction=JKQTPMathImageLastPaletteColor; - this->rangeMinFailColor=QColor("black"); - this->rangeMaxFailColor=QColor("black"); - this->nanColor=QColor("black"); - this->infColor=QColor("black"); - this->colorBarTopVisible=false; - this->colorBarRightVisible=true; - - if (parent) this->palette=parent->getCurrentPlotterStyle().defaultPalette; - -} - -JKQTPColorPaletteTools::~JKQTPColorPaletteTools() -= default; - -void JKQTPColorPaletteTools::cbGetOutsideSize(JKQTPEnhancedPainter& painter, int& leftSpace, int& rightSpace, int& topSpace, int& bottomSpace) { - Q_UNUSED(leftSpace); - Q_UNUSED(bottomSpace); - if (showColorBar) { - double internalDataMin=getInternalDataMin(); - double internalDataMax=getInternalDataMax(); - cbGetDataMinMax(internalDataMin, internalDataMax); - if (colorBarRightVisible) { - rightSpace+=cbParent->pt2px(painter, colorBarWidth+colorBarOffset); - colorBarRightAxis->setRange(internalDataMin, internalDataMax); - colorBarRightAxis->setAxisWidth(colorBarRelativeHeight*cbParent->getPlotHeight()); - QSizeF s1=colorBarRightAxis->getSize2(painter); - QSizeF s2=colorBarRightAxis->getSize1(painter); - QSizeF names=cbParent->getTextSizeSize(imageNameFontName, imageNameFontSize*cbParent->getFontSizeMultiplier(), imageName, painter); - rightSpace+=qMax(static_cast(s1.width()+s2.width()), static_cast(names.width())); - } - if (colorBarTopVisible) { - //topSpace+=cbParent->pt2px(painter, colorBarWidth+colorBarOffset); - colorBarTopAxis->setRange(internalDataMin, internalDataMax); - colorBarTopAxis->setAxisWidth(colorBarRelativeHeight*cbParent->getPlotWidth()); - QSizeF s1=colorBarTopAxis->getSize2(painter); - QSizeF s2=colorBarTopAxis->getSize1(painter); - QSizeF names=cbParent->getTextSizeSize(imageNameFontName, imageNameFontSize*cbParent->getFontSizeMultiplier(), imageName, painter); - topSpace+=cbParent->pt2px(painter, colorBarWidth+colorBarOffset)+qMax(static_cast(s1.height()+s2.height()), static_cast(names.height())); - } - } -} - -void JKQTPColorPaletteTools::cbDrawOutside(JKQTPEnhancedPainter& painter, QRect leftSpace, QRect rightSpace, QRect topSpace, QRect bottomSpace) { - Q_UNUSED(leftSpace); - Q_UNUSED(bottomSpace); - if (showColorBar) { - double internalDataMin=getInternalDataMin(); - double internalDataMax=getInternalDataMax(); - cbGetDataMinMax(internalDataMin, internalDataMax); - if (colorBarRightVisible) { - painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); - - static const uint8_t h=1; - static const uint8_t dSize = 200*h; - uint8_t d[dSize];//, dd[200*h]; - for (int i=0; i<200; i++) { - for (int j=0; j(d, h, 200, b, palette, 0, 199); - - - QSizeF names=cbParent->getTextSizeSize(imageNameFontName, imageNameFontSize*cbParent->getFontSizeMultiplier(), imageName, painter); - - double icolorBarRelativeHeight=colorBarRelativeHeight; - int barHeight=rightSpace.height()*icolorBarRelativeHeight; - if (barHeight<1) barHeight=1; - // find a height for the bar that allows to show the image name - while ((barHeight>1) && ((rightSpace.height()-barHeight)/2pt2px(painter, colorBarOffset), rightSpace.top()+(rightSpace.height()-barHeight)/2, cbParent->pt2px(painter, colorBarWidth), barHeight); - painter.drawImage(cb, b.mirrored(true, false)); - QPen p=painter.pen(); - p.setColor(colorBarRightAxis->getAxisColor()); - p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, cbParent->pt2px(painter, colorBarRightAxis->getLineWidth()*cbParent->getLineWidthMultiplier()))); - painter.setPen(p); - painter.drawRect(cb); - - colorBarRightAxis->setRange(internalDataMin, internalDataMax); - colorBarRightAxis->setAxisWidth(cb.height()); - colorBarRightAxis->setAxisOffset(cb.top()); - colorBarRightAxis->setOtherAxisOffset(cb.left()); - colorBarRightAxis->setOtherAxisWidth(cb.width()); - colorBarRightAxis->drawAxes(painter); - - - - cbParent->getMathText()->setFontSize(imageNameFontSize*cbParent->getFontSizeMultiplier()); - cbParent->getMathText()->setFontRomanOrSpecial(imageNameFontName); - cbParent->getMathText()->parse(imageName); - cbParent->getMathText()->draw(painter, Qt::AlignHCenter|Qt::AlignVCenter, QRect(rightSpace.x(), rightSpace.y(), rightSpace.width(), (rightSpace.height()-barHeight)/2)); - - - } - if (colorBarTopVisible) { - painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); - - static const uint8_t h=1; - static const uint8_t dSize = 200*h; - uint8_t d[dSize];//, dd[200*h]; - for (int i=0; i<200; i++) { - for (int j=0; j(d,h,200, b, palette, 0, 199); - - QSizeF names=cbParent->getTextSizeSize(imageNameFontName, imageNameFontSize*cbParent->getFontSizeMultiplier(), imageName, painter); - - double icolorBarRelativeHeight=colorBarRelativeHeight; - int barWidth=topSpace.width()*icolorBarRelativeHeight; - if (barWidth<1) barWidth=1; - // find a height for the bar that allows to show the image name - while ((barWidth>1) && ((topSpace.width()-barWidth)/2pt2px(painter, colorBarOffset+(colorBarWidth)), barWidth, cbParent->pt2px(painter, colorBarWidth)); - //qDebug()<<"t: "<getAxisColor()); - p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, cbParent->pt2px(painter, colorBarTopAxis->getLineWidth()*cbParent->getLineWidthMultiplier()))); - painter.setPen(p); - painter.drawRect(cb); - - - colorBarTopAxis->setRange(internalDataMin, internalDataMax); - colorBarTopAxis->setAxisWidth(cb.width()); - colorBarTopAxis->setAxisOffset(cb.left()); - colorBarTopAxis->setOtherAxisOffset(cb.top()); - colorBarTopAxis->setOtherAxisWidth(cb.height()); - colorBarTopAxis->drawAxes(painter); - - - - cbParent->getMathText()->setFontSize(imageNameFontSize*cbParent->getFontSizeMultiplier()); - cbParent->getMathText()->setFontRomanOrSpecial(imageNameFontName); - cbParent->getMathText()->parse(imageName); - cbParent->getMathText()->draw(painter, Qt::AlignHCenter|Qt::AlignVCenter, QRect(topSpace.right()-(topSpace.width()-barWidth)/2, topSpace.y(), (topSpace.width()-barWidth)/2, topSpace.height())); - - - } - } -} - - -QStringList JKQTPColorPaletteTools::getPalettes() { - return JKQTPImagePlot_getPredefinedPalettes(); -} - -int JKQTPColorPaletteTools::getPalettesCount() -{ - return getPalettes().size(); -} - -QIcon JKQTPColorPaletteTools::getPaletteIcon(int i) { - QImage img=getPaletteImage(i, JKQTPImageTools::PALETTE_ICON_WIDTH); - QPixmap pix(JKQTPImageTools::PALETTE_ICON_WIDTH,8); - QRect r(0,0,JKQTPImageTools::PALETTE_ICON_WIDTH-1,7); - QPainter p(&pix); - p.drawImage(r, img); - p.setPen(QPen(QColor("black"))); - p.drawRect(r); - p.end(); - return QIcon(pix); - -} - -QIcon JKQTPColorPaletteTools::getPaletteIcon(JKQTPMathImageColorPalette palette) { - return getPaletteIcon(static_cast(palette)); -} - -QImage JKQTPColorPaletteTools::getPaletteImage(int i, int width) -{ - QImage img; - double* pic=static_cast(malloc(width*sizeof(double))); - for (int j=0; j(pic, width, 1, img, (JKQTPMathImageColorPalette)i, 0, width-1); - free(pic); - return img; -} - -QImage JKQTPColorPaletteTools::getPaletteImage(JKQTPMathImageColorPalette palette, int width) -{ - return getPaletteImage(static_cast(palette), width); -} - -QIcon JKQTPColorPaletteTools::getPaletteKeyIcon(int i) -{ - QImage img=getPaletteKeyImage(i, JKQTPImageTools::PALETTE_ICON_WIDTH, JKQTPImageTools::PALETTE_IMAGEICON_HEIGHT); - QPixmap pix(JKQTPImageTools::PALETTE_ICON_WIDTH,JKQTPImageTools::PALETTE_IMAGEICON_HEIGHT); - QRect r(0,0,JKQTPImageTools::PALETTE_ICON_WIDTH-1,JKQTPImageTools::PALETTE_IMAGEICON_HEIGHT-1); - QPainter p(&pix); - p.drawImage(r, img); - p.setPen(QPen(QColor("black"))); - p.drawRect(r); - p.end(); - return QIcon(pix); -} - -QIcon JKQTPColorPaletteTools::getPaletteKeyIcon(JKQTPMathImageColorPalette palette) -{ - return getPaletteIcon(static_cast(palette)); -} - -QImage JKQTPColorPaletteTools::getPaletteKeyImage(int i, int width, int height) -{ - QImage img; - - const double x01=double(width)/3.0; - const double y01=double(height)/3.0*2.0; - const double w1x=double(width*width)/(5.0*5.0); - const double w1y=double(height*height)/(2.0*2.0); - const double x02=double(width)/3.0*2.0; - const double y02=double(height)/4.0; - const double w2x=double(width*width)/(8.0*8.0); - const double w2y=double(height*height)/(8.0*8.0); - - double* pic=static_cast(malloc(width*height*sizeof(double))); - double mmax=0; - for (int j=0; jmmax) mmax=pic[j]; - } - JKQTPImagePlot_array2image(pic, width, height, img, (JKQTPMathImageColorPalette)i, 0, mmax); - free(pic); - return img; -} - -QImage JKQTPColorPaletteTools::getPaletteKeyImage(JKQTPMathImageColorPalette palette, int width, int height) -{ - return getPaletteKeyImage(static_cast(palette), width, height); -} - - -void JKQTPColorPaletteTools::setPalette(int pal) { - palette=(JKQTPMathImageColorPalette)pal; -} - -void JKQTPColorPaletteTools::cbSetParent(JKQTBasePlotter* parent) { - cbParent=parent; - colorBarRightAxis->setParent(parent); - colorBarTopAxis->setParent(parent); - -} - -double JKQTPColorPaletteTools::getInternalDataMin() const -{ - return 0; -} - -double JKQTPColorPaletteTools::getInternalDataMax() const -{ - return 0; -} - -#endif - - - QString JKQTPMathImageColorPalette2String(JKQTPMathImageColorPalette p) { diff --git a/lib/jkqtplottertools/jkqtpimagetools.h b/lib/jkqtcommon/jkqtpbasicimagetools.h similarity index 72% rename from lib/jkqtplottertools/jkqtpimagetools.h rename to lib/jkqtcommon/jkqtpbasicimagetools.h index 2397501690..7846f12a4f 100644 --- a/lib/jkqtplottertools/jkqtpimagetools.h +++ b/lib/jkqtcommon/jkqtpbasicimagetools.h @@ -18,8 +18,8 @@ */ -#ifndef JKQTPIMAGETOOLS_H -#define JKQTPIMAGETOOLS_H +#ifndef JKQTPBASICIMAGETOOLS_H +#define JKQTPBASICIMAGETOOLS_H #include #include #include @@ -29,15 +29,6 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" - -#ifndef NO_JKQTPLOTTER -#include "jkqtcommon/jkqtptools.h" - -class JKQTPVerticalIndependentAxis; // forward -class JKQTPHorizontalIndependentAxis; // forward -class JKQTBasePlotter; // forward -#endif /*! \brief tool structure that summarizes several static properties \ingroup jkqtptools_qt @@ -807,333 +798,4 @@ QIcon JKQTP_LIB_EXPORT JKQTPMathImageGetPaletteIcon(JKQTPMathImageColorPalette p -#ifndef NO_JKQTPLOTTER - -/*! \brief if a class is derived from this class, it may use color bars - \ingroup jkqtplotter_imagelots_tools - */ -class JKQTP_LIB_EXPORT JKQTPColorPaletteTools { - public: - - JKQTPColorPaletteTools(JKQTBasePlotter *parent); - virtual ~JKQTPColorPaletteTools(); - - /*! \brief get list with all available palettes */ - static QStringList getPalettes() ; - /*! \brief get list with all available palettes */ - static int getPalettesCount() ; - /*! \brief get QIcon representing the given palette */ - static QIcon getPaletteIcon(int i) ; - /*! \brief get QIcon representing the given palette */ - static QIcon getPaletteIcon(JKQTPMathImageColorPalette palette) ; - /*! \brief get QIcon representing the given palette */ - static QImage getPaletteImage(int i, int width) ; - /*! \brief get QIcon representing the given palette */ - static QImage getPaletteImage(JKQTPMathImageColorPalette palette, int width) ; - - /*! \brief get QIcon representing the given palette */ - static QIcon getPaletteKeyIcon(int i) ; - /*! \brief get QIcon representing the given palette */ - static QIcon getPaletteKeyIcon(JKQTPMathImageColorPalette palette) ; - /*! \brief get QIcon representing the given palette */ - static QImage getPaletteKeyImage(int i, int width, int height) ; - /*! \brief get QIcon representing the given palette */ - static QImage getPaletteKeyImage(JKQTPMathImageColorPalette palette, int width, int height) ; - - - - void setPalette(int pal); - - /*! \brief if the graph plots outside the actual plot field of view (e.g. color bars, scale bars, ...) - - \note If you want to draw outside, then you'll also have to implement drawOutside() - */ - void cbGetOutsideSize(JKQTPEnhancedPainter& painter, int& leftSpace, int& rightSpace, int& topSpace, int& bottomSpace); - - /*! \brief plots outside the actual plot field of view (e.g. color bars, scale bars, ...) - - \note If you want to draw outside, then you'll also have to implement getOutsideSize(), so enough space is reserved - - The four value supplied tell the method where to draw (inside one of the rectangles). - */ - void cbDrawOutside(JKQTPEnhancedPainter& painter, QRect leftSpace, QRect rightSpace, QRect topSpace, QRect bottomSpace); - - - void cbSetParent(JKQTBasePlotter* parent); - - - /** \brief determine min/max data value of the image */ - virtual void cbGetDataMinMax(double& imin, double& imax)=0; - - - virtual double getInternalDataMin() const ; - virtual double getInternalDataMax() const ; - - - protected: - JKQTBasePlotter* cbParent; - - - /** \brief top color bar visible */ - bool colorBarTopVisible; - /** \brief right color bar visible */ - bool colorBarRightVisible; - /** \brief name of the image displayed above color bar (may contain LaTeX markup!) */ - QString imageName; - /** \brief font name when displaying imageName */ - QString imageNameFontName; - /** \brief font size in points when displaying imageName */ - double imageNameFontSize; - /** \brief palette for plotting an image */ - JKQTPMathImageColorPalette palette; - /** \brief indicate whether to display a color bar */ - bool showColorBar; - /** \brief width of the color bar */ - int colorBarWidth; - /** \brief height of the color bar, as multiple of plotHeight */ - double colorBarRelativeHeight; - /** \brief indicates whether to estimate min/max of the image automatically */ - bool autoImageRange; - /** \brief image value range minimum */ - double imageMin; - /** \brief image value range maximum */ - double imageMax; - /** \brief offset between outside space border and color bar */ - int colorBarOffset; - /** \brief which action to take if a color is below \a imageMin and \a autoImageRange \c ==false */ - JKQTPMathImageColorRangeFailAction rangeMinFailAction; - /** \brief which action to take if a color is above \a imageMax and \a autoImageRange \c ==false */ - JKQTPMathImageColorRangeFailAction rangeMaxFailAction; - /** \brief color to use for some settings of \a rangeMinFailAction */ - QColor rangeMinFailColor; - /** \brief color to use for some settings of \a rangeMaxFailAction */ - QColor rangeMaxFailColor; - /** \brief color to use for a not-a-number value */ - QColor nanColor; - /** \brief color to use for an infinity value */ - QColor infColor; - - - /** \brief object used for color bar axes - * - * \note this axis has some kind of a special role. It is used to format color bar axes - */ - JKQTPVerticalIndependentAxis* colorBarRightAxis; - JKQTPHorizontalIndependentAxis* colorBarTopAxis; - - - - public: - - /*! \copydoc palette */ - inline virtual void setPalette(const JKQTPMathImageColorPalette & __value) - { - this->palette = __value; - } - /*! \copydoc palette */ - inline virtual JKQTPMathImageColorPalette getPalette() const - { - return this->palette; - } - /*! \copydoc rangeMinFailAction */ - inline virtual void setRangeMinFailAction(const JKQTPMathImageColorRangeFailAction & __value) - { - this->rangeMinFailAction = __value; - } - /*! \copydoc rangeMinFailAction */ - inline virtual JKQTPMathImageColorRangeFailAction getActionRangeMinFail() const - { - return this->rangeMinFailAction; - } - /*! \copydoc rangeMaxFailAction */ - inline virtual void setRangeMaxFailAction(const JKQTPMathImageColorRangeFailAction & __value) - { - this->rangeMaxFailAction = __value; - } - /*! \copydoc rangeMaxFailAction */ - inline virtual JKQTPMathImageColorRangeFailAction getActionRangeMaxFail() const - { - return this->rangeMaxFailAction; - } - /*! \copydoc rangeMinFailColor */ - inline virtual void setRangeMinFailColor(const QColor & __value) - { - this->rangeMinFailColor = __value; - } - /*! \copydoc rangeMinFailColor */ - inline virtual QColor getRangeMinFailColor() const - { - return this->rangeMinFailColor; - } - /*! \copydoc rangeMaxFailColor */ - inline virtual void setRangeMaxFailColor(const QColor & __value) - { - this->rangeMaxFailColor = __value; - } - /*! \copydoc rangeMaxFailColor */ - inline virtual QColor getRangeMaxFailColor() const - { - return this->rangeMaxFailColor; - } - /*! \copydoc nanColor */ - inline virtual void setNanColor(const QColor & __value) - { - this->nanColor = __value; - } - /*! \copydoc nanColor */ - inline virtual QColor getNanColor() const - { - return this->nanColor; - } - /*! \copydoc infColor */ - inline virtual void setInfColor(const QColor & __value) - { - this->infColor = __value; - } - /*! \copydoc infColor */ - inline virtual QColor getInfColor() const - { - return this->infColor; - } - /*! \copydoc showColorBar */ - inline virtual void setShowColorBar(bool __value) - { - this->showColorBar = __value; - } - /*! \copydoc showColorBar */ - inline virtual bool getShowColorBar() const - { - return this->showColorBar; - } - /*! \copydoc colorBarWidth */ - inline virtual void setColorBarWidth(int __value) - { - this->colorBarWidth = __value; - } - /*! \copydoc colorBarWidth */ - inline virtual int getColorBarWidth() const - { - return this->colorBarWidth; - } - /*! \copydoc colorBarOffset */ - inline virtual void setColorBarOffset(int __value) - { - this->colorBarOffset = __value; - } - /*! \copydoc colorBarOffset */ - inline virtual int getColorBarOffset() const - { - return this->colorBarOffset; - } - /*! \copydoc colorBarRelativeHeight */ - inline virtual void setColorBarRelativeHeight(double __value) - { - this->colorBarRelativeHeight = __value; - } - /*! \copydoc colorBarRelativeHeight */ - inline virtual double getColorBarRelativeHeight() const - { - return this->colorBarRelativeHeight; - } - /*! \copydoc imageMin */ - inline virtual void setImageMin(double __value) - { - this->imageMin = __value; - } - /*! \copydoc imageMin */ - inline virtual double getImageMin() const - { - return this->imageMin; - } - /*! \copydoc imageMax */ - inline virtual void setImageMax(double __value) - { - this->imageMax = __value; - } - /*! \copydoc imageMax */ - inline virtual double getImageMax() const - { - return this->imageMax; - } - /*! \copydoc autoImageRange */ - inline virtual void setAutoImageRange(bool __value) - { - this->autoImageRange = __value; - } - /*! \copydoc autoImageRange */ - inline virtual bool getAutoImageRange() const - { - return this->autoImageRange; - } - /*! \copydoc imageName */ - inline virtual void setImageName(const QString & __value) - { - this->imageName = __value; - } - /*! \copydoc imageName */ - inline virtual QString getImageName() const - { - return this->imageName; - } - /*! \copydoc imageNameFontName */ - inline virtual void setImageNameFontName(const QString & __value) - { - this->imageNameFontName = __value; - } - /*! \copydoc imageNameFontName */ - inline virtual QString getImageNameFontName() const - { - return this->imageNameFontName; - } - /*! \copydoc imageNameFontSize */ - inline virtual void setImageNameFontSize(double __value) - { - this->imageNameFontSize = __value; - } - /*! \copydoc imageNameFontSize */ - inline virtual double getImageNameFontSize() const - { - return this->imageNameFontSize; - } - /*! \copydoc colorBarRightAxis */ - inline JKQTPVerticalIndependentAxis* getColorBarRightAxis() { - return this->colorBarRightAxis; - } - /*! \copydoc colorBarTopAxis */ - inline JKQTPHorizontalIndependentAxis* getColorBarTopAxis() { - return this->colorBarTopAxis; - } - /*! \copydoc colorBarRightAxis */ - inline const JKQTPVerticalIndependentAxis* getColorBarRightAxis() const { - return this->colorBarRightAxis; - } - /*! \copydoc colorBarTopAxis */ - inline const JKQTPHorizontalIndependentAxis* getColorBarTopAxis() const { - return this->colorBarTopAxis; - } - /*! \copydoc colorBarTopVisible */ - inline virtual void setColorBarTopVisible(bool __value) - { - this->colorBarTopVisible = __value; - } - /*! \copydoc colorBarTopVisible */ - inline virtual bool getColorBarTopVisible() const - { - return this->colorBarTopVisible; - } - /*! \copydoc colorBarRightVisible */ - inline virtual void setColorBarRightVisible(bool __value) - { - this->colorBarRightVisible = __value; - } - /*! \copydoc colorBarRightVisible */ - inline virtual bool getColorBarRightVisible() const - { - return this->colorBarRightVisible; - } - -}; -#endif - - -#endif // JKQTPIMAGETOOLS_H +#endif // JKQTPBASICIMAGETOOLS_H diff --git a/lib/jkqtcommon/jkqtpcodestructuring.cpp b/lib/jkqtcommon/jkqtpcodestructuring.cpp new file mode 100644 index 0000000000..c8b0b78fb8 --- /dev/null +++ b/lib/jkqtcommon/jkqtpcodestructuring.cpp @@ -0,0 +1,24 @@ +/* +Copyright (c) 2008-2019 Jan W. Krieger () + + + + + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + + + +#include "jkqtcommon/jkqtpcodestructuring.h" diff --git a/lib/jkqtcommon/jkqtpcodestructuring.h b/lib/jkqtcommon/jkqtpcodestructuring.h new file mode 100644 index 0000000000..408605d171 --- /dev/null +++ b/lib/jkqtcommon/jkqtpcodestructuring.h @@ -0,0 +1,124 @@ +/* + Copyright (c) 2008-2019 Jan W. Krieger (, ) + + + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + + + +#ifndef JKQTPCODESTRUCTURING_H_INCLUDED +#define JKQTPCODESTRUCTURING_H_INCLUDED +#include + + +/** \brief C++11 finally construct (executes a callable-object when the edestructor is executed) + * \ingroup jkqtptools_codestructuring + * + * Typical usage: + * \code + * { + * // the instruction 'painter.restore()' will be executed at the end + * // of the block, when __finalpaint is destroyed (see (*) below) + * JKQTPFinalAct __finalpaint([&painter]() { painter.restore(); }); + * + * // ... + * // do something ... + * // ... + * + * } // (*) 'painter.restore()' is executed before the end of this block! + * \endcode + * + * \see JKQTPFinally() + */ +template +class JKQTPFinalAct +{ +public: + explicit JKQTPFinalAct(F f) noexcept + : f_(std::move(f)), invoke_(true) {} + + JKQTPFinalAct(JKQTPFinalAct&& other) noexcept + : f_(std::move(other.f_)), + invoke_(other.invoke_) + { + other.invoke_ = false; + } + + JKQTPFinalAct(const JKQTPFinalAct&) = delete; + JKQTPFinalAct& operator=(const JKQTPFinalAct&) = delete; + + ~JKQTPFinalAct() noexcept + { + if (invoke_) f_(); + } + +private: + F f_; + bool invoke_; +}; + +/** \brief C++11 finally construct (executes a callable-object at the end of a scope) + * \ingroup jkqtptools_codestructuring + * + * Typical usage: + * \code + * { + * // the instruction 'painter.restore()' will be executed at the end + * // of the block, when __finalpaint is destroyed (see (*) below) + * auto __finalpaint=JKQTPFinally([&painter]() { painter.restore(); }); + * + * // ... + * // do something ... + * // ... + * + * } // (*) 'painter.restore()' is executed before the end of this block! + * \endcode + * + * \see JKQTPFinalAct + */ +template +inline JKQTPFinalAct JKQTPFinally(const F& f) noexcept +{ + return JKQTPFinalAct(f); +} + +/** \brief C++11 finally construct (executes a callable-object at the end of a scope) + * \ingroup jkqtptools_codestructuring + * + * Typical usage: + * \code + * { + * // the instruction 'painter.restore()' will be executed at the end + * // of the block, when __finalpaint is destroyed (see (*) below) + * auto __finalpaint=JKQTPFinally([&painter]() { painter.restore(); }); + * + * // ... + * // do something ... + * // ... + * + * } // (*) 'painter.restore()' is executed before the end of this block! + * \endcode + * + * \see JKQTPFinalAct + */ +template +inline JKQTPFinalAct JKQTPFinally(F&& f) noexcept +{ + return JKQTPFinalAct(std::forward(f)); +} + + +#endif // JKQTPCODESTRUCTURING_H_INCLUDED diff --git a/lib/jkqtcommon/jkqtpcommonmathtools.h b/lib/jkqtcommon/jkqtpcommonmathtools.h deleted file mode 100644 index f8c498f5cd..0000000000 --- a/lib/jkqtcommon/jkqtpcommonmathtools.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - Copyright (c) 2008-2019 Jan W. Krieger (, ) - - - - This software is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - - - -#ifndef JKQTPCOMMONMATHTOOLS_H_INCLUDED -#define JKQTPCOMMONMATHTOOLS_H_INCLUDED -#include "jkqtcommon/jkqtp_imexport.h" -#include -#include -#include -#include - - - -/*! \brief \f$ \sqrt{\pi}=2.50662827463 \f$ - \ingroup jkqtptools_math_basic - -*/ -#define JKQTPSTATISTICS_SQRT_2PI 2.50662827463 - - -/** \brief double-value NotANumber - * \ingroup jkqtptools_math_basic - */ -#define JKQTP_DOUBLE_NAN (std::numeric_limits::signaling_NaN()) - -/** \brief float-value NotANumber - * \ingroup jkqtptools_math_basic - */ -#define JKQTP_FLOAT_NAN (std::numeric_limits::signaling_NaN()) - -/** \brief double-value NotANumber - * \ingroup jkqtptools_math_basic - */ -#define JKQTP_NAN JKQTP_DOUBLE_NAN - -/** \brief wandelt einen Datentyp in einen double um, wird von JKQTPDatastore zur Wandlung benutzt - * \ingroup jkqtptools_math_basic - * - * Diese Funktion nutzt per default static_cast(), kann aber für spezielle Datentypen überschrieben werden, etwa für bool -*/ -template -inline constexpr double jkqtp_todouble(const T& d) { - return static_cast(d); -} - - -/** \brief wandelt einen boolean in einen double um, wird von JKQTPDatastore zur Wandlung benutzt, - * Spezialisierung für bool (true -> 1.0, false -> 0.0) - * \ingroup jkqtptools_math_basic */ -template<> -inline constexpr double jkqtp_todouble(const bool& d) { - return static_cast((d)?1.0:0.0); -} - - -/** \brief round a double using round() and convert it to a specified type T (static_cast!) - * \ingroup jkqtptools_math_basic */ -template -inline T jkqtp_roundTo(const double& v) { - return static_cast(round(v)); -} - - -/** \brief compare two floats \a a and \a b for euqality, where any difference smaller than \a epsilon is seen as equality - * \ingroup jkqtptools_math_basic */ -inline bool jkqtp_approximatelyEqual(float a, float b, float epsilon=2.0*std::numeric_limits::epsilon()) -{ - return fabsf(a - b) <= epsilon; -} - -/** \brief compare two doubles \a a and \a b for euqality, where any difference smaller than \a epsilon is seen as equality - * \ingroup jkqtptools_math_basic */ -inline bool jkqtp_approximatelyEqual(double a, double b, double epsilon=2.0*std::numeric_limits::epsilon()) -{ - return fabs(a - b) <= epsilon; -} - -/** \brief returns the quare of the value \a v, i.e. \c v*v - * \ingroup jkqtptools_math_basic */ -template -inline T jkqtp_sqr(const T& v) { - return v*v; -} - - -/*! \brief 4-th power of a number - \ingroup jkqtptools_math_basic - -*/ -template -inline T jkqtp_pow4(T x) { - const T xx=x*x; - return xx*xx; -} - -/*! \brief cube of a number - \ingroup jkqtptools_math_basic - -*/ -template -inline T jkqtp_cube(T x) { - return x*x*x; -} - - -/*! \brief calculates the sign of number \a x - \ingroup jkqtptools_math_basic -*/ -template -inline T jkqtp_sign(T x) { - if (x<0) return -1; - //else if (x==0) return 0; - else return 1; -} - -/** \brief calculate the distance between two QPointF points - * \ingroup jkqtptools_math_basic - * - */ -inline double jkqtp_distance(const QPointF& p1, const QPointF& p2){ - return sqrt(jkqtp_sqr(p1.x()-p2.x())+jkqtp_sqr(p1.y()-p2.y())); -} - -/** \brief calculate the distance between two QPoint points - * \ingroup jkqtptools_math_basic - * - */ -inline double jkqtp_distance(const QPoint& p1, const QPoint& p2){ - return sqrt(jkqtp_sqr(p1.x()-p2.x())+jkqtp_sqr(p1.y()-p2.y())); -} - -/** \brief check whether the dlotaing point number is OK (i.e. non-inf, non-NAN) - * \ingroup jkqtptools_math_basic - */ -template -inline bool JKQTPIsOKFloat(T v) { - return std::isfinite(v)&&(!std::isinf(v))&&(!std::isnan(v)); -} - - -#endif // JKQTPCOMMONMATHTOOLS_H_INCLUDED diff --git a/lib/jkqtcommon/jkqtpdrawingtools.cpp b/lib/jkqtcommon/jkqtpdrawingtools.cpp new file mode 100644 index 0000000000..0a5b2dd04f --- /dev/null +++ b/lib/jkqtcommon/jkqtpdrawingtools.cpp @@ -0,0 +1,406 @@ +/* +Copyright (c) 2008-2019 Jan W. Krieger () + + + + + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + +#include "jkqtcommon/jkqtpdrawingtools.h" +#include "jkqtcommon/jkqtpenhancedpainter.h" +#include + +const double JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH= 0.02; + + + +QString JKQTPGraphSymbols2String(JKQTPGraphSymbols pos) { + switch(pos) { + case JKQTPDot: return "symbol_dot"; + case JKQTPCross: return "symbol_cross"; + case JKQTPPlus: return "symbol_plus"; + case JKQTPCircle: return "symbol_circle"; + case JKQTPFilledCircle: return "symbol_filled_circle"; + case JKQTPRect: return "symbol_rect"; + case JKQTPFilledRect: return "symbol_filled_rect"; + case JKQTPTriangle: return "symbol_triangle"; + case JKQTPFilledTriangle: return "symbol_filled_triangle"; + case JKQTPDownTriangle: return "symbol_down_triangle"; + case JKQTPFilledDownTriangle: return "symbol_filled_down_triangle"; + case JKQTPTarget: return "symbol_target"; + case JKQTPstar: return "symbol_star"; + case JKQTPFilledStar: return "symbol_filled_star"; + case JKQTPDiamond: return "symbol_diamond"; + case JKQTPFilledDiamond: return "symbol_filled_diamond"; + case JKQTPPentagon: return "symbol_pentagon"; + case JKQTPAsterisc: return "symbol_asterisc"; + case JKQTPAsterisc6: return "symbol_asterisc6"; + case JKQTPAsterisc8: return "symbol_asterisc8"; + case JKQTPFilledPentagon: return "symbol_filled_pentagon"; + case JKQTPHexagon: return "symbol_hexagon"; + case JKQTPFilledHexagon: return "symbol_filled_hexagon"; + case JKQTPOctagon: return "symbol_octagon"; + case JKQTPFilledOctagon: return "symbol_filled_octagon"; + case JKQTPRectCross: return "symbol_rect_cross"; + case JKQTPRectPlus: return "symbol_rect_plus"; + case JKQTPNoSymbol: return "none"; + case JKQTPDiamondPlus: return "symbol_diamond_plus"; + case JKQTPDiamondCross: return "symbol_diamond_cross"; + case JKQTPCircleCross: return "symbol_circle_cross"; + case JKQTPCirclePlus: return "symbol_circle_plus"; + case JKQTPUpDownTriangle: return "symbol_updowntriangle"; + case JKQTPFilledUpDownTriangle: return "symbol_filled_updowntriangle"; + case JKQTPSantaClauseHouse: return "symbol_santaclause"; + case JKQTPFilledSantaClauseHouse: return "symbol_filled_santaclause"; + case JKQTPHourglass: return "symbol_hourglass"; + case JKQTPFilledHourglass: return "symbol_filled_hourglass"; + case JKQTPHorizontalHourglass: return "symbol_horizontal_hourglass"; + case JKQTPFilledHorizontalHourglass: return "symbol_filled_horizontal_hourglass"; + case JKQTPRectTriangle: return "symbol_rect_triangle"; + case JKQTPRectDownTriangle: return "symbol_rect_downtriangle"; + case JKQTPRectLeftTriangle: return "symbol_rect_lefttriangle"; + case JKQTPRectRightTriangle: return "symbol_rect_righttriangle"; + case JKQTPLeftTriangle: return "symbol_left_triangle"; + case JKQTPFilledLeftTriangle: return "symbol_filled_left_triangle"; + case JKQTPRightTriangle: return "symbol_right_triangle"; + case JKQTPFilledRightTriangle: return "symbol_filled_right_triangle"; + case JKQTPTripod: return "symbol_tripod"; + case JKQTPDownTripod: return "symbol_down_tripod"; + case JKQTPLeftTripod: return "symbol_left_tripod"; + case JKQTPRightTripod: return "symbol_right_tripod"; + case JKQTPFilledCurvedTriangle: return "symbol_filled_curved_triangle"; + case JKQTPFilledDownCurvedTriangle: return "symbol_filled_down_curved_triangle"; + case JKQTPFilledLeftCurvedTriangle: return "symbol_filled_left_curved_triangle"; + case JKQTPFilledRightCurvedTriangle: return "symbol_filled_right_curved_triangle"; + case JKQTPCurvedTriangle: return "symbol_curved_triangle"; + case JKQTPDownCurvedTriangle: return "symbol_down_curved_triangle"; + case JKQTPLeftCurvedTriangle: return "symbol_left_curved_triangle"; + case JKQTPRightCurvedTriangle: return "symbol_right_curved_triangle"; + case JKQTPPeace: return "symbol_peace"; + case JKQTPFemale: return "symbol_female"; + case JKQTPMale: return "symbol_male"; + case JKQTPCirclePeace: return "symbol_circle_peace"; + case JKQTPSymbolCount: JKQTPGraphSymbols2String(JKQTPMaxSymbolID); + } + return ""; +} + +QString JKQTPGraphSymbols2NameString(JKQTPGraphSymbols pos) { + switch(pos) { + case JKQTPDot: return QObject::tr("dot"); + case JKQTPCross: return QObject::tr("cross"); + case JKQTPPlus: return QObject::tr("plus"); + case JKQTPCircle: return QObject::tr("circle"); + case JKQTPFilledCircle: return QObject::tr("filled circle"); + case JKQTPRect: return QObject::tr("rectangle"); + case JKQTPFilledRect: return QObject::tr("filled rectangle"); + case JKQTPTriangle: return QObject::tr("triangle"); + case JKQTPFilledTriangle: return QObject::tr("filled triangle"); + case JKQTPDownTriangle: return QObject::tr("down triangle"); + case JKQTPFilledDownTriangle: return QObject::tr("filled down triangle"); + case JKQTPstar: return QObject::tr("star"); + case JKQTPFilledStar: return QObject::tr("filled star"); + case JKQTPDiamond: return QObject::tr("diamond"); + case JKQTPFilledDiamond: return QObject::tr("filled diamond"); + case JKQTPPentagon: return QObject::tr("pentagon"); + case JKQTPFilledPentagon: return QObject::tr("filled pentagon"); + case JKQTPHexagon: return QObject::tr("hexagon"); + case JKQTPFilledHexagon: return QObject::tr("filled hexagon"); + case JKQTPOctagon: return QObject::tr("octagon"); + case JKQTPFilledOctagon: return QObject::tr("filled octagon"); + case JKQTPTarget: return QObject::tr("target"); + case JKQTPAsterisc: return QObject::tr("asterisc, 5-arm"); + case JKQTPAsterisc6: return QObject::tr("asterisc, 6-arm"); + case JKQTPAsterisc8: return QObject::tr("asterisc, 8-arm"); + case JKQTPRectCross: return QObject::tr("square with cross"); + case JKQTPRectPlus: return QObject::tr("square with plus"); + case JKQTPNoSymbol: return QObject::tr("none"); + case JKQTPDiamondPlus: return QObject::tr("diamond with plus"); + case JKQTPDiamondCross: return QObject::tr("diamond with cross"); + case JKQTPCircleCross: return QObject::tr("circled cross"); + case JKQTPCirclePlus: return QObject::tr("circled plus"); + case JKQTPUpDownTriangle: return QObject::tr("up/down triangle"); + case JKQTPFilledUpDownTriangle: return QObject::tr("filled up/down triangle"); + case JKQTPSantaClauseHouse: return QObject::tr("santa clause"); + case JKQTPFilledSantaClauseHouse: return QObject::tr("filled santa clause"); + case JKQTPHourglass: return QObject::tr("hourglass"); + case JKQTPFilledHourglass: return QObject::tr("filled hourglass"); + case JKQTPHorizontalHourglass: return QObject::tr("horizontal hourglass"); + case JKQTPFilledHorizontalHourglass: return QObject::tr("filled horizontal hourglass"); + case JKQTPRectTriangle: return QObject::tr("rectangle with triangle"); + case JKQTPRectDownTriangle: return QObject::tr("rectangle with downwards triangle"); + case JKQTPRectLeftTriangle: return QObject::tr("rectangle with leftwards triangle"); + case JKQTPRectRightTriangle: return QObject::tr("rectangle with rightwards triangle"); + case JKQTPLeftTriangle: return QObject::tr("left triangle"); + case JKQTPFilledLeftTriangle: return QObject::tr("filled left triangle"); + case JKQTPRightTriangle: return QObject::tr("right triangle"); + case JKQTPFilledRightTriangle: return QObject::tr("filled right triangle"); + case JKQTPTripod: return QObject::tr("tripod"); + case JKQTPDownTripod: return QObject::tr("down tripod"); + case JKQTPLeftTripod: return QObject::tr("left tripod"); + case JKQTPRightTripod: return QObject::tr("right tripod"); + case JKQTPFilledCurvedTriangle: return QObject::tr("filled curved triangle"); + case JKQTPFilledDownCurvedTriangle: return QObject::tr("filled down curved triangle"); + case JKQTPFilledLeftCurvedTriangle: return QObject::tr("filled left curved triangle"); + case JKQTPFilledRightCurvedTriangle: return QObject::tr("filled right curved triangle"); + case JKQTPCurvedTriangle: return QObject::tr("curved triangle"); + case JKQTPDownCurvedTriangle: return QObject::tr("down curved triangle"); + case JKQTPLeftCurvedTriangle: return QObject::tr("left curved triangle"); + case JKQTPRightCurvedTriangle: return QObject::tr("right curved triangle"); + case JKQTPPeace: return QObject::tr("peace"); + case JKQTPFemale: return QObject::tr("female"); + case JKQTPMale: return QObject::tr("male"); + case JKQTPCirclePeace: return QObject::tr("circled peace"); + case JKQTPSymbolCount: JKQTPGraphSymbols2NameString(JKQTPMaxSymbolID); + } + return ""; +} +JKQTPGraphSymbols String2JKQTPGraphSymbols(const QString& pos) { + QString s=pos.trimmed().toLower(); + if (s=="symbol_dot"||s=="dot"||s==".") return JKQTPDot; + if (s=="symbol_cross"||s=="cross"||s=="x") return JKQTPCross; + if (s=="symbol_plus"||s=="plus"||s=="+") return JKQTPPlus; + if (s=="symbol_circle"||s=="circle"||s=="o") return JKQTPCircle; + if (s=="symbol_filled_circle"||s=="filled_circle"||s=="fo") return JKQTPFilledCircle; + if (s=="symbol_rect"||s=="rect"||s=="r") return JKQTPRect; + if (s=="symbol_filled_rect"||s=="filled_rect"||s=="fr") return JKQTPFilledRect; + if (s=="symbol_triangle"||s=="triangle"||s=="^") return JKQTPTriangle; + if (s=="symbol_filled_triangle"||s=="filled_triangle"||s=="f^") return JKQTPFilledTriangle; + if (s=="symbol_down_triangle"||s=="down_triangle"||s=="v") return JKQTPDownTriangle; + if (s=="symbol_filles_down_triangle"||s=="filles_down_triangle"||s=="symbol_filled_down_triangle"||s=="filled_down_triangle"||s=="fv") return JKQTPFilledDownTriangle; + if (s=="symbol_target"||s=="target"||s=="t") return JKQTPTarget; + if (s=="symbol_star"||s=="star"||s=="s") return JKQTPstar; + if (s=="symbol_filled_star"||s=="filled_star"||s=="fs") return JKQTPFilledStar; + if (s=="symbol_diamond"||s=="diamond"||s=="d") return JKQTPDiamond; + if (s=="symbol_filled_diamond"||s=="filled_diamond"||s=="fd") return JKQTPFilledDiamond; + if (s=="symbol_pentagon"||s=="pentagon"||s=="p") return JKQTPPentagon; + if (s=="symbol_filled_pentagon"||s=="filled_pentagon"||s=="fp") return JKQTPFilledPentagon; + if (s=="symbol_hexagon"||s=="hexagon"||s=="h") return JKQTPHexagon; + if (s=="symbol_filled_hexagon"||s=="filled_hexagon"||s=="fh") return JKQTPFilledHexagon; + if (s=="symbol_octagon"||s=="octagon"||s=="h") return JKQTPOctagon; + if (s=="symbol_filled_octagon"||s=="filled_octagon"||s=="fh") return JKQTPFilledOctagon; + if (s=="symbol_asterisc"||s=="asterisc"||s=="*") return JKQTPAsterisc; + if (s=="symbol_asterisc6"||s=="asterisc6"||s=="*6") return JKQTPAsterisc6; + if (s=="symbol_asterisc8"||s=="asterisc8"||s=="*8") return JKQTPAsterisc8; + if (s=="symbol_rect_cross"||s=="rect_cross"||s=="rx") return JKQTPRectCross; + if (s=="symbol_rect_plus"||s=="rect_plus"||s=="r+") return JKQTPRectPlus; + if (s=="symbol_diamond_plus" || s=="diamond_plus") return JKQTPDiamondPlus; + if (s=="symbol_diamond_cross" || s=="diamond_cross") return JKQTPDiamondCross; + if (s=="symbol_circle_cross" || s=="circle_cross") return JKQTPCircleCross; + if (s=="symbol_circle_plus" || s=="circle_plus") return JKQTPCirclePlus; + if (s=="symbol_updowntriangle" || s=="updowntriangle") return JKQTPUpDownTriangle; + if (s=="symbol_filled_updowntriangle" || s=="filled_updowntriangle") return JKQTPFilledUpDownTriangle; + if (s=="symbol_santaclause" || s=="santaclause") return JKQTPSantaClauseHouse; + if (s=="symbol_filled_santaclause" || s=="filled_santaclause") return JKQTPFilledSantaClauseHouse; + if (s=="symbol_hourglass" || s=="hourglass") return JKQTPHourglass; + if (s=="symbol_filled_hourglass" || s=="filled_hourglass") return JKQTPFilledHourglass; + if (s=="symbol_horizontal_hourglass" || s=="horizontal_hourglass") return JKQTPHorizontalHourglass; + if (s=="symbol_filled_horizontal_hourglass" || s=="filled_horizontal_hourglass") return JKQTPFilledHorizontalHourglass; + if (s=="symbol_rect_triangle" || s=="rect_triangle") return JKQTPRectTriangle; + if (s=="symbol_rect_downtriangle" || s=="rect_downtriangle") return JKQTPRectDownTriangle; + if (s=="symbol_rect_lefttriangle" || s=="rect_lefttriangle") return JKQTPRectLeftTriangle; + if (s=="symbol_rect_righttriangle" || s=="rect_righttriangle") return JKQTPRectRightTriangle; + if (s=="symbol_left_triangle" || s=="left_triangle") return JKQTPLeftTriangle; + if (s=="symbol_filled_left_triangle" || s=="filled_left_triangle") return JKQTPFilledLeftTriangle; + if (s=="symbol_right_triangle" || s=="right_triangle") return JKQTPRightTriangle; + if (s=="symbol_filled_right_triangle" || s=="filled_right_triangle") return JKQTPFilledRightTriangle; + if (s=="symbol_tripod" || s=="tripod") return JKQTPTripod; + if (s=="symbol_down_tripod" || s=="down_tripod") return JKQTPDownTripod; + if (s=="symbol_left_tripod" || s=="left_tripod") return JKQTPLeftTripod; + if (s=="symbol_right_tripod" || s=="right_tripod") return JKQTPRightTripod; + if (s=="symbol_filled_curved_triangle" || s=="filled_curved_triangle") return JKQTPFilledCurvedTriangle; + if (s=="symbol_filled_down_curved_triangle" || s=="filled_down_curved_triangle") return JKQTPFilledDownCurvedTriangle; + if (s=="symbol_filled_left_curved_triangle" || s=="filled_left_curved_triangle") return JKQTPFilledLeftCurvedTriangle; + if (s=="symbol_filled_right_curved_triangle" || s=="filled_right_curved_triangle") return JKQTPFilledRightCurvedTriangle; + if (s=="symbol_curved_triangle" || s=="curved_triangle") return JKQTPCurvedTriangle; + if (s=="symbol_down_curved_triangle" || s=="down_curved_triangle") return JKQTPDownCurvedTriangle; + if (s=="symbol_left_curved_triangle" || s=="left_curved_triangle") return JKQTPLeftCurvedTriangle; + if (s=="symbol_right_curved_triangle" || s=="right_curved_triangle") return JKQTPRightCurvedTriangle; + if (s=="symbol_peace" || s=="peace") return JKQTPPeace; + if (s=="symbol_circle_peace" || s=="circle_peace") return JKQTPCirclePeace; + if (s=="symbol_female" || s=="female") return JKQTPFemale; + if (s=="symbol_male" || s=="male") return JKQTPMale; + + return JKQTPNoSymbol; +} + + + + + + +QPolygonF jkqtpRotateRect(QRectF r, double angle) { + QPolygonF p; + QMatrix m; + m.rotate(angle); + p.append(m.map(r.bottomLeft())); + p.append(m.map(r.bottomRight())); + p.append(m.map(r.topRight())); + p.append(m.map(r.topLeft())); + return p; +} + + + +; + + + +QVector JKQTPDrawEllipse(double x, double y, double a, double b, double angle_start, double angle_end, double alpha, int controlPoints, QPointF* x_start, QPointF* x_end) { + QVector result; + double start=angle_start*M_PI/180.0; + double stop=angle_end*M_PI/180.0; + double step=(stop-start)/static_cast(controlPoints); + while (fabs(stop-start)/step<10) step=step/2.0; + double sina=sin(1.0*alpha/180.0*M_PI); + double cosa=cos(1.0*alpha/180.0*M_PI); + QPointF xp(x+a*cos(start)*cosa-b*sin(start)*sina, y+a*cos(start)*sina+b*sin(start)*cosa); + result.append(xp); + if (x_start) *x_start = xp; + double t=start+step; + for (int i=1; i JKQTPUnifyLinesToPolygons(const QVector &lines, double distanceThreshold, int searchMaxSurroundingElements) +{ +#ifdef JKQTBP_AUTOTIMER + JKQTPAutoOutputTimer jkaat(QString("JKQTPUnifyLinesToPolygons(%1, %2, %3)").arg(lines.size()).arg(distanceThreshold).arg(searchMaxSurroundingElements)); +#endif + QList res; + res.reserve(lines.size()); + + // first simply convert all lines to polygons + for (const QLineF& l: lines) { + QPolygonF p; + p< polygons start "<=0; k--) { + res[i].prepend(res[j].at(k)); + } + res.removeAt(j); + } else if (jkqtp_distance(res[i].last(),res[j].first())<=distanceThreshold) { + found=true; + for (int k=1; k=0; k--) { + res[i].append(res[j].at(k)); + } + res.removeAt(j); + } else { + j++; + } + } + res[i]=JKQTPCleanPolygon(res[i], distanceThreshold); + i++; + } + //qDebug()<<" iter "< polygons left "< inbetween; + int i=1; + while (i0) { + for (const QPointF& pi: inbetween) { + pmean=QPointF(pmean.x()+pi.x()/static_cast(inbetween.size()), pmean.y()+pi.y()/static_cast(inbetween.size())); + } + } else { + pmean=poly[i]; + } + p<0) { + for (const QPointF& pi: inbetween) { + pmean=QPointF(pmean.x()+pi.x()/static_cast(inbetween.size()), pmean.y()+pi.y()/static_cast(inbetween.size())); + } + } else { + pmean=p0; + } + + if (jkqtp_distance(pmean, poly.last())>distanceThreshold) { + p<, ) + + + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + + +#ifndef JKQTPDRAWINGTOOLS_H_INCLUDED +#define JKQTPDRAWINGTOOLS_H_INCLUDED +#include "jkqtcommon/jkqtp_imexport.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "jkqtcommon/jkqtpmathtools.h" +#include "jkqtcommon/jkqtpcodestructuring.h" + +class JKQTPEnhancedPainter; // forward + + + +/*! \brief tool class with static values used by JKQTPlotter/JKQTBasePlotter + \ingroup jkqtptools_drawing + */ +JKQTP_LIB_EXPORT struct JKQTPlotterDrawingTools { + /** \brief smallest linewidth any line in JKQTPlotter/JKQTBasePlotter may have + */ + static const double ABS_MIN_LINEWIDTH; +}; + + + + +/** \brief symbols that can be used to plot a datapoint for a graph + * \ingroup jkqtptools_drawing + */ +enum JKQTPGraphSymbols { + JKQTPNoSymbol=0, /*!< \brief plots no symbol at all (usefull together with error bars) */ + JKQTPDot, /*!< \brief a small dot \image html symbols/symbol_dot.png */ + JKQTPCross, /*!< \brief a X cross \image html symbols/symbol_cross.png */ + JKQTPPlus, /*!< \brief a + cross \image html symbols/symbol_plus.png */ + JKQTPCircle, /*!< \brief an unfilled circle \image html symbols/symbol_circle.png */ + JKQTPFilledCircle, /*!< \brief a filled circle \image html symbols/symbol_filled_circle.png */ + JKQTPRect, /*!< \brief an unfilled rectangle \image html symbols/symbol_rect.png */ + JKQTPFilledRect, /*!< \brief a filled rectangle \image html symbols/symbol_filled_rect.png */ + JKQTPTriangle, /*!< \brief an unfilled triangle (tip at top) \image html symbols/symbol_triangle.png */ + JKQTPFilledTriangle, /*!< \brief a filled triangle (tip at top) \image html symbols/symbol_filled_triangle.png */ + JKQTPDiamond, /*!< \brief an unfilled diamond \image html symbols/symbol_diamond.png */ + JKQTPFilledDiamond, /*!< \brief a filled diamond \image html symbols/symbol_filled_diamond.png */ + JKQTPstar, /*!< \brief an unfilled diamond \image html symbols/symbol_star.png */ + JKQTPFilledStar, /*!< \brief a filled diamond \image html symbols/symbol_filled_star.png */ + JKQTPPentagon, /*!< \brief an unfilled pentagon \image html symbols/symbol_pentagon.png */ + JKQTPFilledPentagon, /*!< \brief a filled pentagon \image html symbols/symbol_filled_pentagon.png */ + JKQTPAsterisc, /*!< \brief an asterisc star with 5 arms \image html symbols/symbol_asterisc.png */ + JKQTPHourglass, /*!< \brief an hour glass symbol \image html symbols/symbol_hourglass.png */ + JKQTPFilledHourglass, /*!< \brief a filled hour glass symbol \image html symbols/symbol_filled_hourglass.png */ + JKQTPCurvedTriangle, /*!< \brief a curved triangle\image html symbols/symbol_curved_triangle.png */ + JKQTPFilledCurvedTriangle, /*!< \brief a filled curved triangle\image html symbols/symbol_filled_curved_triangle.png */ + JKQTPHexagon, /*!< \brief an unfilled hexagon \image html symbols/symbol_hexagon.png */ + JKQTPFilledHexagon, /*!< \brief a filled hexagon \image html symbols/symbol_filled_hexagon.png */ + + JKQTPRectCross, /*!< \brief a square symbol with a cross inside \image html symbols/symbol_rect_cross.png */ + JKQTPRectPlus, /*!< \brief a square symbol with a plus inside \image html symbols/symbol_rect_plus.png */ + JKQTPRectTriangle, /*!< \brief a square symbol with a triangle inside \image html symbols/symbol_rect_triangle.png */ + JKQTPRectDownTriangle, /*!< \brief a square symbol with a triangle (tip to the bottom) inside \image html symbols/symbol_rect_downtriangle.png */ + JKQTPRectLeftTriangle, /*!< \brief a square symbol with a triangle (tip to the left) inside \image html symbols/symbol_rect_lefttriangle.png */ + JKQTPRectRightTriangle, /*!< \brief a square symbol with a triangle (tip to the right) inside \image html symbols/symbol_rect_righttriangle.png */ + + JKQTPCircleCross, /*!< \brief a circle symbol with a cross inside \image html symbols/symbol_circle_cross.png */ + JKQTPCirclePlus, /*!< \brief a circle symbol with a plus inside \image html symbols/symbol_circle_plus.png */ + JKQTPCirclePeace, /*!< \brief a circled peace symbol \image html symbols/symbol_circle_peace.png */ + + JKQTPDiamondPlus, /*!< \brief a diamond symbol with a plus inside \image html symbols/symbol_diamond_plus.png */ + JKQTPDiamondCross, /*!< \brief a diamond symbol with a cross inside \image html symbols/symbol_diamond_cross.png */ + + JKQTPTripod, /*!< \brief a tripod symbol \image html symbols/symbol_tripod.png */ + JKQTPDownTripod, /*!< \brief a tripod symbol, pointing down \image html symbols/symbol_down_tripod.png */ + JKQTPLeftTripod, /*!< \brief a tripod symbol, pointing to the left \image html symbols/symbol_left_tripod.png */ + JKQTPRightTripod, /*!< \brief a tripod symbol, pointing to the right \image html symbols/symbol_right_tripod.png */ + JKQTPAsterisc6, /*!< \brief an asterisc star with 6 arms \image html symbols/symbol_asterisc6.png */ + JKQTPAsterisc8, /*!< \brief an asterisc star with 8 arms \image html symbols/symbol_asterisc8.png */ + JKQTPPeace, /*!< \brief a peace symbol \image html symbols/symbol_peace.png */ + JKQTPTarget, /*!< \brief a target symbol (circle with cross) \image html symbols/symbol_target.png */ + + JKQTPDownTriangle, /*!< \brief an unfilled triangle (tip at bottom) \image html symbols/symbol_down_triangle.png */ + JKQTPFilledDownTriangle, /*!< \brief a filled triangle (tip at bottom) \image html symbols/symbol_filled_down_triangle.png */ + JKQTPLeftTriangle, /*!< \brief an unfilled triangle (tip to the left) \image html symbols/symbol_left_triangle.png */ + JKQTPFilledLeftTriangle, /*!< \brief a filled triangle (tip to the left) \image html symbols/symbol_filled_left_triangle.png */ + JKQTPRightTriangle, /*!< \brief an unfilled triangle (tip to the right) \image html symbols/symbol_right_triangle.png */ + JKQTPFilledRightTriangle, /*!< \brief a filled triangle (tip to the right) \image html symbols/symbol_filled_right_triangle.png */ + JKQTPDownCurvedTriangle, /*!< \brief a curved triangle, pointing down \image html symbols/symbol_down_curved_triangle.png */ + JKQTPFilledDownCurvedTriangle, /*!< \brief a filled curved triangle, pointing down \image html symbols/symbol_filled_down_curved_triangle.png */ + JKQTPLeftCurvedTriangle, /*!< \brief a curved triangle, pointing to the left \image html symbols/symbol_left_curved_triangle.png */ + JKQTPFilledLeftCurvedTriangle, /*!< \brief a filled curved triangle, pointing to the left \image html symbols/symbol_filled_left_curved_triangle.png */ + JKQTPRightCurvedTriangle, /*!< \brief a curved triangle, pointing to the right \image html symbols/symbol_right_curved_triangle.png */ + JKQTPFilledRightCurvedTriangle, /*!< \brief a filled curved triangle, pointing to the right \image html symbols/symbol_filled_right_curved_triangle.png */ + JKQTPOctagon, /*!< \brief an unfilled octagon \image html symbols/symbol_octagon.png */ + JKQTPFilledOctagon, /*!< \brief a filled octagon \image html symbols/symbol_filled_octagon.png */ + JKQTPUpDownTriangle, /*!< \brief a overlay of an up and a down triangle symbol \image html symbols/symbol_updowntriangle.png */ + JKQTPFilledUpDownTriangle, /*!< \brief a filled version of the overlay of an up and a down triangle \image html symbols/symbol_filled_updowntriangle.png */ + JKQTPHorizontalHourglass, /*!< \brief a horizontal hour glass symbol \image html symbols/symbol_horizontal_hourglass.png */ + JKQTPFilledHorizontalHourglass, /*!< \brief a filled horizontal hour glass symbol \image html symbols/symbol_filled_horizontal_hourglass.png */ + + JKQTPSantaClauseHouse, /*!< \brief a small house symbol ("Das is das haus vom Nicolaus") \image html symbols/symbol_santaclause.png */ + JKQTPFilledSantaClauseHouse, /*!< \brief a filled small house symbol ("Das is das haus vom Nicolaus") \image html symbols/symbol_filled_santaclause.png */ + + JKQTPMale, /*!< \brief a male symbol \image html symbols/symbol_male.png */ + JKQTPFemale, /*!< \brief a female symbol \image html symbols/symbol_female.png */ + + JKQTPSymbolCount, /*!< \brief can be used to iterate over all symbols using: for (int i=0; i(JKQTPSymbolCount); i++) { JKQTPGraphSymbols s=static_cast(i); ... } */ + JKQTPMaxSymbolID=JKQTPSymbolCount-1, /*!< \brief points to the last available symbol, can be used to iterate over all symbols: for (int i=0; i<=static_cast(JKQTPMaxSymbolID); i++) { JKQTPGraphSymbols s=static_cast(i); ... } */ + JKQTPDefaultSymbol=JKQTPCross, /*!< \brief a default symbol used for plotting */ +}; + +/** \brief converts a JKQTPGraphSymbols variable into a identifier string + * \ingroup jkqtptools_drawing + */ +JKQTP_LIB_EXPORT QString JKQTPGraphSymbols2String(JKQTPGraphSymbols pos); +/** \brief converts a JKQTPGraphSymbols variable into a human-readable string + * \ingroup jkqtptools_drawing + */ +JKQTP_LIB_EXPORT QString JKQTPGraphSymbols2NameString(JKQTPGraphSymbols pos); + +/** \brief converts a String into a JKQTPGraphSymbols + * \ingroup jkqtptools_drawing + */ +JKQTP_LIB_EXPORT JKQTPGraphSymbols String2JKQTPGraphSymbols(const QString& pos); + + + + +/** \brief rotate a rectangle by given angle (rotates all points around the center of the rectangle and returns it as a QPolygonF) + * \ingroup jkqtptools_drawing + */ +JKQTP_LIB_EXPORT QPolygonF jkqtpRotateRect(QRectF r, double angle); + +/*! \brief plot the specified symbol at pixel position x,y + \ingroup jkqtptools_drawing + + \tparam TPainter Type of \a painter: A class like JKQTPEnhancedPainter or QPainter + \param painter the QPainter to draw to + \param x x-coordinate of the symbol center + \param y y-coordinate of the symbol center + \param symbol type of the symbol to plot, see JKQTPGraphSymbols + \param size size (width/height) of the symbol around (\a x , \a y) + \param symbolLineWidth width of the lines used to draw the symbol + \param color color of the symbol lines + \param fillColor color of the symbol filling + */ +template +inline void JKQTPPlotSymbol(TPainter& painter, double x, double y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor); + +/*! \brief plot the specified symbol at pixel position x,y + \ingroup jkqtptools_drawing + + \param paintDevice the paint device to draw on + \param x x-coordinate of the symbol center + \param y y-coordinate of the symbol center + \param symbol type of the symbol to plot, see JKQTPGraphSymbols + \param size size (width/height) of the symbol around (\a x , \a y) + \param symbolLineWidth width of the lines used to draw the symbol + \param color color of the symbol lines + \param fillColor color of the symbol filling + */ +JKQTP_LIB_EXPORT void JKQTPPlotSymbol(QPaintDevice& paintDevice, double x, double y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor); + + +/*! \brief plot an arrow between positions (x1,y1) and (x2,y2) + \ingroup jkqtptools_drawing + + \param painter the QPainter to draw to + \param x1 first x-coordinate of the arrow + \param y1 first y-coordinate of the arrow + \param x2 second x-coordinate of the arrow + \param y2 second y-coordinate of the arrow + \param symbol type of the symbol to plot, see JKQTPGraphSymbols + \param size size (width/height) of the symbol around (\a x , \a y) + \param symbolLineWidth width of the lines used to draw the symbol + \param color color of the symbol lines + \param fillColor color of the symbol filling + */ +//JKQTP_LIB_EXPORT void JKQTPPlotArrow(JKQTPEnhancedPainter& painter, int x, int y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor); + + +/*! \brief draw an ellipse without setting pen or brush, or saving the painter! + \ingroup jkqtptools_drawing + + \return a QVector with points that may be used for drawing + \param x center of ellipse (x-coordinate) + \param y center of ellipse (y-coordinate) + \param a half axis in x-direction + \param b half axis in y-direction + \param angle_start starting angle of ellipse section + \param angle_end ending angle of ellipse section + \param alpha rotation angle of ellipse + \param controlPoints the number of points to use for drawing + \param[out] x_start first point of ellipse + \param[out] x_end last point of ellipse + + \note all angles are given in degrees [0..360] +*/ +JKQTP_LIB_EXPORT QVector JKQTPDrawEllipse(double x, double y, double a, double b, double angle_start=0, double angle_end=360, double alpha=0, int controlPoints=180, QPointF* x_start=nullptr, QPointF* x_end=nullptr); + +/*! \brief draw a tooltip, using the current brush and pen of the provided painter + \ingroup jkqtptools_drawing + + \tparam TPainter Type of \a painter: A class like JKQTPEnhancedPainter or QPainter + \param painter QPainter-like object to use for painting + \param x x-coordinate of position the tooltip points to + \param y y-coordinate of position the tooltip points to + \param rect rectangle of the main tooltip area +*/ +template +inline void JKQTPDrawTooltip(TPainter& painter, double x, double y, const QRectF& rect); + + +/** \brief cleans a polygon by uniting all consecutive points that were closer than distanceThreshold are united + * \ingroup jkqtptools_drawing + * + * \param poly polygon to clean + * \param distanceThreshold if two end-points are closer together as this value, they are united to a single point + * \return a cleaned polygon, where all consecutive points that were closer than distanceThreshold are united + */ +JKQTP_LIB_EXPORT QPolygonF JKQTPCleanPolygon(const QPolygonF& poly, double distanceThreshold=0.3); + +/** \brief takes a list of QLineF objesct \a lines and tries to combine as many of them as possible to QPolygonF objects. + * Note: This method implements an incomplete algorithm with \a searchMaxSurroundingElements>0, as solving + * the complete problem is very time-consuming (cubic runtime) + * \ingroup jkqtptools_drawing + * + * \param lines line segments to unify + * \param distanceThreshold if two end-points are closer together as this value, they are united to a single point + * \param searchMaxSurroundingElements limits the search for a connected polygon to at most this number of neighbors + * \return a vector of QPolygonF objects, which contain longer line-segments formed from \a lines + */ +JKQTP_LIB_EXPORT QVector JKQTPUnifyLinesToPolygons(const QVector& lines, double distanceThreshold=0.3, int searchMaxSurroundingElements=10); + + + + + + + + + + + +template +inline void JKQTPPlotSymbol(TPainter& painter, double x, double y, JKQTPGraphSymbols symbol, double symbolSize, double symbolLineWidth, QColor color, QColor fillColor) { + painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); + QPen p=painter.pen(); + p.setColor(color); + p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, symbolLineWidth)); + p.setStyle(Qt::SolidLine); + p.setCapStyle(Qt::FlatCap); + painter.setPen(p); + QBrush b=painter.brush(); + b.setColor(fillColor); + b.setStyle(Qt::SolidPattern); + const double w=symbolSize; + const double w2=w/2.0; + const double w45=fabs(w*cos(45.0/180.0*M_PI)); + const double w3=w/3.0; + + // calculate star cordinates as static values + static int star5_items=0; + static double star5cordsx[10]; + static double star5cordsy[10]; + if (star5_items==0) { + star5_items=5; + double angle=360.0/double(star5_items)/180.0*M_PI; + for (int i=0; i(i)+0.5)*angle; + star5cordsx[i*2]=sin(a); + star5cordsx[i*2+1]=0.5*sin(a+angle/2.0); + star5cordsy[i*2]=cos(a); + star5cordsy[i*2+1]=0.5*cos(a+angle/2.0); + } + } + static int star6_items=0; + static double star6cordsx[12]; + static double star6cordsy[12]; + if (star6_items==0) { + star6_items=6; + double angle=360.0/double(star6_items)/180.0*M_PI; + for (int i=0; i(i)+0.5)*angle; + star6cordsx[i*2]=sin(a); + star6cordsx[i*2+1]=0.5*sin(a+angle/2.0); + star6cordsy[i*2]=cos(a); + star6cordsy[i*2+1]=0.5*cos(a+angle/2.0); + } + } + static int star8_items=0; + static double star8cordsx[16]; + static double star8cordsy[16]; + if (star8_items==0) { + star8_items=8; + double angle=360.0/double(star8_items)/180.0*M_PI; + for (int i=0; i(i)+0.5)*angle; + star8cordsx[i*2]=sin(a); + star8cordsx[i*2+1]=0.5*sin(a+angle/2.0); + star8cordsy[i*2]=cos(a); + star8cordsy[i*2+1]=0.5*cos(a+angle/2.0); + } + } + + switch(symbol) { + case JKQTPDot: + painter.drawPoint(QPointF(x,y)); + break; + case JKQTPCross:{ + QPainterPath path; + path.moveTo(x-w2,y-w2); + path.lineTo(x+w2,y+w2); + path.moveTo(x-w2,y+w2); + path.lineTo(x+w2,y-w2); + painter.drawPath(path); + } + break; + case JKQTPPlus:{ + QVector lines; + lines< lines; + lines< lines; + lines< lines; + lines< lines; + lines< lines; + lines< lines; + lines< lines; + lines< lines; + lines< lines; + lines< +inline void JKQTPDrawTooltip(TPainter& painter, double x, double y, const QRectF& rect) +{ + QPolygonF poly; + if (yrect.bottom()) { + poly<rect.left()) { + poly<) -#include "jkqtplottertools/jkqtpenhancedpainter.h" +#include "jkqtcommon/jkqtpenhancedpainter.h" diff --git a/lib/jkqtplottertools/jkqtpenhancedpainter.h b/lib/jkqtcommon/jkqtpenhancedpainter.h similarity index 100% rename from lib/jkqtplottertools/jkqtpenhancedpainter.h rename to lib/jkqtcommon/jkqtpenhancedpainter.h diff --git a/lib/jkqtplottertools/jkqtphighrestimer.cpp b/lib/jkqtcommon/jkqtphighrestimer.cpp similarity index 100% rename from lib/jkqtplottertools/jkqtphighrestimer.cpp rename to lib/jkqtcommon/jkqtphighrestimer.cpp diff --git a/lib/jkqtplottertools/jkqtphighrestimer.h b/lib/jkqtcommon/jkqtphighrestimer.h similarity index 100% rename from lib/jkqtplottertools/jkqtphighrestimer.h rename to lib/jkqtcommon/jkqtphighrestimer.h diff --git a/lib/jkqtcommon/jkqtplinalgtools.cpp b/lib/jkqtcommon/jkqtplinalgtools.cpp new file mode 100644 index 0000000000..313861b5c4 --- /dev/null +++ b/lib/jkqtcommon/jkqtplinalgtools.cpp @@ -0,0 +1,23 @@ +/* + Copyright (c) 2008-2019 Jan W. Krieger () + + last modification: $LastChangedDate$ (revision $Rev$) + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + + + +#include "jkqtplinalgtools.h" + diff --git a/lib/jkqtcommon/jkqtplinalgtools.h b/lib/jkqtcommon/jkqtplinalgtools.h new file mode 100644 index 0000000000..7958c9b064 --- /dev/null +++ b/lib/jkqtcommon/jkqtplinalgtools.h @@ -0,0 +1,866 @@ +/* + Copyright (c) 2008-2019 Jan W. Krieger () + + last modification: $LastChangedDate$ (revision $Rev$) + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + + +#ifndef JKQTPLINALGTOOLS_H_INCLUDED +#define JKQTPLINALGTOOLS_H_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "jkqtcommon/jkqtp_imexport.h" +#include "jkqtcommon/jkqtparraytools.h" +#include "jkqtcommon/jkqtpmathtools.h" +#include "jkqtcommon/jkqtpstringtools.h" + +#ifdef _OPENMP +# include +#endif + + +#ifndef JKQTP_ALIGNMENT_BYTES +#define JKQTP_ALIGNMENT_BYTES 32 +#endif + + +#ifdef JKQTP_STATISTICS_TOOLS_MAY_USE_EIGEN3 +# include +# include +# include +# include +# include +#endif + + + + + +/** \brief calculate the index of the entry in line \a l and column \a c + * in a row-major matrix with \a C columns + * \ingroup jkqtptools_math_linalg + * + * You can use this to access a matrix with L rows and C columns: + * \code + * for (long l=0; l +inline void jkqtplinalgPrintMatrix(T* matrix, long L, long C, int width=9, int precision=3, char mode='f') { + for (long l=0; l0) std::cout<<", "; + std::cout.precision(precision); + std::cout.width(width); + if (mode=='f') std::cout< +inline std::string jkqtplinalgMatrixToString(T* matrix, long L, long C, int width=9, int precision=3, const std::string& mode=std::string("g")) { + std::string format="%"+jkqtp_inttostr(width)+std::string(".")+jkqtp_inttostr(precision)+std::string("l")+mode; + std::ostringstream ost; + for (long l=0; l0) ost<<", "; + char buf[500]; + sprintf(buf, format.c_str(), jkqtp_todouble(matrix[jkqtplinalgMatIndex(l,c,C)])); + ost<=-1) { + r=jkqtp_boundedRoundTo(0,255.0-fval*127.0,255); + g=jkqtp_boundedRoundTo(0,255.0-fval*127.0,255); + } else if (val>0 && val<=1) { + b=jkqtp_boundedRoundTo(0,255.0-fval*127.0,255); + g=jkqtp_boundedRoundTo(0,255.0-fval*127.0,255); + } else if (val<-1) { + r=127; + g=127; + b=255; + } else if (val>1) { + r=255; + g=127; + b=127; + } +} + +/** \brief maps the number range -1 ... +1 to a non-linear color-scale lightblue - white - lightred (used for coloring matrices!) + * \ingroup jkqtptools_math_linalg + * + * \param val the value to convert + * \param[out] r returns the red value (0..255) + * \param[out] g returns the green value (0..255) + * \param[out] b returns the blue value (0..255) +*/ +inline void jkqtplinalgPM1ToNonlinRWBColors(double val, uint8_t& r, uint8_t& g, uint8_t& b, double gamma=0.5){ + if (val<0) { + jkqtplinalgPM1ToRWBColors(-1.0*pow(-val,gamma),r,g,b); + } else { + jkqtplinalgPM1ToRWBColors(pow(val,gamma),r,g,b); + } +} +/** \brief convert the given LxC matrix to std::string, encoded as HTML table + * \ingroup jkqtptools_math_linalg + * + * + * \tparam type of the matrix cells (typically double or float) + * \param L number of lines/rows in the matrix + * \param C number of columns in the matrix + * \param width width (in characters) of each cell in the output (used for formatting) + * \param precision precision (in digits) for string-conversions in the output (used for formatting) + * \param mode the (printf()) string conversion mode for output of the cell values + * \param tableformat this is inserted into the \c tag (may contain HTML property definitions) + * \param prenumber this is inserted before each number (may contain HTML markup) + * \param postnumber this is inserted after each number (may contain HTML markup) + * \param colorcoding if \c true, teh cell backgrounds are color-coded + * \param zeroIsWhite if \c the color-coding is forced to white for 0 and then encodes in positive/negative direction with colors (red and blue) + * \param[out] colorlabel outputs a label explaining the auto-generated color-coding + * \param nonlinColors if \c true, a non-linear color-coding is used + * \param nonlinColorsGamma gamma-value for a non-linear color-coding + * \param colortableformat lie \a tableformat, but for the legend table output in \a colorLabel + * + * \see jkqtplinalgPM1ToNonlinRWBColors() and jkqtplinalgPM1ToRWBColors() +*/ +template +inline std::string jkqtplinalgMatrixToHTMLString(T* matrix, long L, long C, int width=9, int precision=3, const std::string& mode=std::string("g"), const std::string& tableformat=std::string(), const std::string& prenumber=std::string(), const std::string& postnumber=std::string(), bool colorcoding=false, bool zeroIsWhite=true, std::string* colorlabel=nullptr, bool nonlinColors=false, double nonlinColorsGamma=0.25, const std::string& colortableformat=std::string()) { + std::ostringstream ost; + ost<<"\n"; + std::string format="%"+jkqtp_inttostr(width)+std::string(".")+jkqtp_inttostr(precision)+std::string("l")+mode; + double minv=0, maxv=0; + if (colorcoding) { + jkqtpstatMinMax(matrix, L*C, minv, maxv); + } + for (long l=0; l"; + for (long c=0; c0) valrel=fabs(val/maxv); + } else { + valrel=((val-minv)/(maxv-minv)-0.5)*2.0; + } + if (nonlinColors) { + jkqtplinalgPM1ToNonlinRWBColors(valrel, r,g,b, nonlinColorsGamma); + } else { + jkqtplinalgPM1ToRWBColors(valrel, r,g,b); + } + char buf[500]; + sprintf(buf, " bgcolor=\"#%02X%02X%02X\"", int(r), int(g), int(b)); + cols=buf; + } + ost<<""; + } + ost<<"\n"; + } + ost<<"
    "; + ost.precision(precision); + ost.width(width); + char buf[500]; + sprintf(buf, format.c_str(), val); + ost<
    "; + + if (colorcoding && colorlabel) { + char buf[8192]; + uint8_t rm=255,gm=255,bm=255; + uint8_t rmc=255,gmc=255,bmc=255; + uint8_t rc=255,gc=255,bc=255; + uint8_t rcp=255,gcp=255,bcp=255; + uint8_t rp=255,gp=255,bp=255; + double vm=minv; + double vc=0; + double vp=maxv; + if (!zeroIsWhite) { + vc=(maxv+minv)/2.0; + } + if (nonlinColors) { + jkqtplinalgPM1ToNonlinRWBColors(-1, rm, gm, bm, nonlinColorsGamma); + jkqtplinalgPM1ToNonlinRWBColors(-0.5, rmc, gmc, bmc, nonlinColorsGamma); + jkqtplinalgPM1ToNonlinRWBColors(0, rc, gc, bc, nonlinColorsGamma); + jkqtplinalgPM1ToNonlinRWBColors(0.5, rcp, gcp, bcp, nonlinColorsGamma); + jkqtplinalgPM1ToNonlinRWBColors(1, rp, gp, bp, nonlinColorsGamma); + } else { + jkqtplinalgPM1ToRWBColors(-1, rm, gm, bm); + jkqtplinalgPM1ToRWBColors(-0.5, rmc, gmc, bmc); + jkqtplinalgPM1ToRWBColors(0, rc, gc, bc); + jkqtplinalgPM1ToRWBColors(0.5, rcp, gcp, bcp); + jkqtplinalgPM1ToRWBColors(1, rp, gp, bp); + } + sprintf(buf, "
    " + "" + "" + "" + "" + "" + "
     %9.3lg    —    %9.3lg    —    %9.3lg 
    ", colortableformat.c_str(), int(rm), int(gm), int(bm), vm, int(rmc), int(gmc), int(bmc), int(rc), int(gc), int(bc), vc, int(rcp), int(gcp), int(bcp), int(rp), int(gp), int(bp), vp); + (*colorlabel)=std::string(buf); + } + return ost.str(); +} + +/** \brief dot-product between two vectors \a vec1 and \a vec2, each with a length of \a N entries + * \ingroup jkqtptools_math_linalg + * + * \tparam T of the vector cells (typically double or float) + * \param vec1 first vector + * \param vec2 second vector + * \param N number of entries in \a vec1 and \a vec2 + */ +template +inline T jkqtplinalgDotProduct(const T* vec1, const T* vec2, long N) { + T res=0; + for (long l=0; l +inline void jkqtplinalgTransposeMatrix(T* matrix, long N) { + for (long l=0; l +inline void jkqtplinalgTransposeMatrix(T* matrix, long L, long C) { + JKQTPArrayScopedPointer t(jkqtpArrayDuplicate(matrix, L*C)); + for (long l=0; l +inline void jkqtplinalgMatrixSwapLines(T* m, long l1, long l2, long C) { + for (long c=0; c +inline void jkqtplinalgMatrixProduct(const T* M1, long L1, long C1, const T* M2, long L2, long C2, T* M) { + if (M1!=M &&M2!=M) { + + for (long l=0; l MM(jkqtpArrayDuplicate(M1, L1*C1)); + jkqtplinalgMatrixProduct(MM,L1,C1,M2,L2,C2,M); + } else if (M1!=M && M2==M) { + JKQTPArrayScopedPointer MM(jkqtpArrayDuplicate(M1, L1*C1)); + jkqtplinalgMatrixProduct(M1,L1,C1,MM,L2,C2,M); + } else if (M1==M && M2==M) { + JKQTPArrayScopedPointer MM(jkqtpArrayDuplicate(M1, L1*C1)); + jkqtplinalgMatrixProduct(MM,L1,C1,MM,L2,C2,M); + } +} + + +/*! \brief matrix-matrix product of two NxN matrices + \ingroup jkqtptools_math_linalg + + \param M1 matrix 1, size: NxN + \param M2 matrix 1, size: NxN + \param N number os rows/columns in the matrices \a M1, \a M2 and \a M + \param[out] M output matrix M=M1*M2, size: NxN +*/ +template +inline void jkqtplinalgMatrixProduct(const T* M1, const T* M2, long N, T* M) { + jkqtplinalgMatrixProduct(M1,N,N,M2,N,N,M); +} + + + + + + +/*! \brief performs a Gauss-Jordan eliminaion on a LxC matrix m + \ingroup jkqtptools_math_linalg + + For a matrix equation \f[ A\cdot\vec{x}=\vec{b} \f] the input matrix is \f[ \left[A | \vec{b}\right] \f] for matrix inversion it is + \f[ \left[A | I_L\right] \f] where \f$ I_L \f$ is the unit matrix with LxL entries. + + \tparam T of the matrix cells (typically double or float) + \param m the matrix + \param L number of rows in the matrix + \param C number of columns in the matrix + + \see http://www.virtual-maxim.de/matrix-invertieren-in-c-plus-plus/ +*/ +template +inline bool jkqtplinalgGaussJordan(T* m, long L, long C) { + + const long N=L; + + //std::cout<<"\nstep 0:\n"; + //linalgPrintMatrix(m, N, C); + + // first we perform a Gauss-elimination, which transforms the matrix in the left half of m into upper triangular form + for (long k=0; k matrix is not invertible + // the determinant of an upper triangular marix equals the product of the diagonal elements + T det=1.0; + for (long k=0; k0; k--) { + //std::cout<<"\nstep J"<=0; i--) { + const T s=m[jkqtplinalgMatIndex(i,k,C)]/m[jkqtplinalgMatIndex(k,k,C)]; + for (long c=k; c +inline bool jkqtplinalgMatrixInversion(const T* matrix, T* matrix_out, long N) { +#ifdef JKQTP_STATISTICS_TOOLS_MAY_USE_EIGEN3 + if (N==2) { + Eigen::Map > eA(matrix); + Eigen::Map > eO(matrix_out); + eO=eA.inverse(); + //std::cout<<"\n--------------------------------------\n2x2 input matrix\n"< > eA(matrix); + Eigen::Map > eO(matrix_out); + //std::cout<<"\n--------------------------------------\n3x3 input matrix\n"< > eA(matrix); + Eigen::Map > eO(matrix_out); + //std::cout<<"\n--------------------------------------\n4x4 input matrix\n"< > eA(matrix,N,N); + Eigen::Map > eO(matrix_out,N,N); + eO=eA.inverse(); + //std::cout<<"\n--------------------------------------\nNxN input matrix\n"< m; + m.resize(msize); + for (long i=0; i +inline bool jkqtplinalgMatrixInversion(T* matrix, long N) { + return jkqtplinalgMatrixInversion(matrix, matrix, N); +} + + + +/*! \brief solve a system of N linear equations \f$ A\cdot\vec{x}=B \f$ simultaneously for C columns in B + \ingroup jkqtptools_math_linalg + + \param A an NxN matrix of coefficients + \param B an NxC marix + \param N number of equations + \param C number of columns in B + \param result_out a NxC matrix with the results after the inversion of the system of equations + \return \c true on success + + \note This function uses the Gauss-Jordan algorithm + \note It is save to call \c jkqtpstatLinSolve(A,B,N,C,B) with the same argument for B and result_out. Then the input will be overwritten with the new matrix! +*/ +template +inline bool jkqtplinalgLinSolve(const T* A, const T* B, long N, long C, T* result_out) { +#if defined(JKQTP_STATISTICS_TOOLS_MAY_USE_EIGEN3) && (!defined(STATISTICS_TOOLS_linalgLinSolve_EIGENMETHOD_noeigen)) + if (N==2 && C==1) { + Eigen::Map > eA(A); + Eigen::Matrix eB; + Eigen::Map > x(result_out); + + eB=Eigen::Map >(B,2,1); +# ifdef STATISTICS_TOOLS_linalgLinSolve_EIGENMETHOD_fullPivLu + x=eA.fullPivLu().solve(eB); +# elif defined(STATISTICS_TOOLS_linalgLinSolve_EIGENMETHOD_householderQr) + x=eA.householderQr().solve(eB); +# elif defined(STATISTICS_TOOLS_linalgLinSolve_EIGENMETHOD_fullPivHouseholderQr) + x=eA.fullPivHouseholderQr().solve(eB); +# elif defined(STATISTICS_TOOLS_linalgLinSolve_EIGENMETHOD_jacobiSvd) + x=eA.jacobiSVD().solve(eB); +# elif defined(STATISTICS_TOOLS_linalgLinSolve_EIGENMETHOD_colPivHouseholderQr) + x=eA.colPivHouseholderQr().solve(eB); +# else + x=eA.fullPivLu().solve(eB); +# endif + } else if (N==3 && C==1) { + Eigen::Map > eA(A); + Eigen::Matrix eB; + Eigen::Map > x(result_out); + + eB=Eigen::Map >(B,3,1); + +# ifdef STATISTICS_TOOLS_linalgLinSolve_EIGENMETHOD_fullPivLu + x=eA.fullPivLu().solve(eB); +# elif defined(STATISTICS_TOOLS_linalgLinSolve_EIGENMETHOD_householderQr) + x=eA.householderQr().solve(eB); +# elif defined(STATISTICS_TOOLS_linalgLinSolve_EIGENMETHOD_fullPivHouseholderQr) + x=eA.fullPivHouseholderQr().solve(eB); +# elif defined(STATISTICS_TOOLS_linalgLinSolve_EIGENMETHOD_jacobiSvd) + x=eA.jacobiSVD().solve(eB); +# elif defined(STATISTICS_TOOLS_linalgLinSolve_EIGENMETHOD_colPivHouseholderQr) + x=eA.colPivHouseholderQr().solve(eB); +# else + x=eA.fullPivLu().solve(eB); +# endif + } else { + Eigen::Map > eA(A,N,N); + Eigen::Matrix eB(N,C); + Eigen::Map > x(result_out,N,C); + + eB=Eigen::Map >(B,N,C); + +# ifdef STATISTICS_TOOLS_linalgLinSolve_EIGENMETHOD_fullPivLu + x=eA.fullPivLu().solve(eB); +# elif defined(STATISTICS_TOOLS_linalgLinSolve_EIGENMETHOD_householderQr) + x=eA.householderQr().solve(eB); +# elif defined(STATISTICS_TOOLS_linalgLinSolve_EIGENMETHOD_fullPivHouseholderQr) + x=eA.fullPivHouseholderQr().solve(eB); +# elif defined(STATISTICS_TOOLS_linalgLinSolve_EIGENMETHOD_jacobiSvd) + x=eA.jacobiSVD().solve(eB); +# elif defined(STATISTICS_TOOLS_linalgLinSolve_EIGENMETHOD_colPivHouseholderQr) + x=eA.colPivHouseholderQr().solve(eB); +# else + x=eA.fullPivLu().solve(eB); +# endif + } + return true; +#else + // first build a N*(N+C) matrix of the form + // + // <---- N ----> <---- C ----> + // ^ A11 A12 ... | B11 B12 ... + // | A21 A22 ... | B21 B22 ... + // N ... ... ... | ..... + // | ... ... ... | ..... + // v ... ... ... | ..... + // + const long msize=N*(N+C); + JKQTPArrayScopedPointer m(static_cast(jkqtpArrayMalloc(msize*sizeof(T)))); // use scoped pointer to ensure, that m is free'd, when the function is ending + for (long l=0; l +inline bool jkqtplinalgLinSolve(const T* A, T* B, long N, long C) { + return jkqtplinalgLinSolve(A,B,N,C,B); +} + + +/*! \brief solve a system of N linear equations \f$ A\cdot\vec{x}=\vec{b} \f$ + \ingroup jkqtptools_math_linalg + + \param A an NxN matrix of coefficients + \param b an N-entry vector + \param N number of equations + \param C number of columns in B + \param[out] result_out a N-entry vector with the result + \return \c true on success + + \note This function uses the Gauss-Jordan algorithm + \note It is save to call \c jkqtpstatLinSolve(A,B,N,C,B) with the same argument for B and result_out. Then the input will be overwritten with the new matrix! +*/ +template +inline bool jkqtplinalgLinSolve(const T* A, const T* b, long N, T* result_out) { + return jkqtplinalgLinSolve(A, b, N, 1, result_out); +} + +/*! \brief solve a system of N linear equations \f$ A\cdot\vec{x}=\vec{b} \f$ + \ingroup jkqtptools_math_linalg + + \param A an NxN matrix of coefficients + \param[in,out] b an N-entry vector (also receives the result) + \param N number of equations + \param C number of columns in B + \return \c true on success + + \note This function uses the Gauss-Jordan algorithm + \note It is save to call \c jkqtpstatLinSolve(A,B,N,C,B) with the same argument for B and result_out. Then the input will be overwritten with the new matrix! +*/ +template +inline bool jkqtplinalgLinSolve(const T* A, T* b, long N) { + return jkqtplinalgLinSolve(A,b,N,1,b); +} + + + + +/*! \brief determinant the given NxN matrix + \ingroup jkqtptools_math_linalg + + \tparam T of the matrix cells (typically double or float) + \param a the matrix for which to calculate the determinant + \param N number of rows and columns in the matrix + \return the determinant of \a a + + \note for large matrices this algorithm is very slow, think about defining the macro JKQTP_STATISTICS_TOOLS_MAY_USE_EIGEN3 to use faster methods from the EIGEN library! +*/ +template +inline T jkqtplinalgMatrixDeterminant(const T* a, long N) { +#ifdef JKQTP_STATISTICS_TOOLS_MAY_USE_EIGEN3 + if (N < 1) { /* Error */ + return NAN; + } else if (N == 1) { /* Shouldn't get used */ + return a[jkqtplinalgMatIndex(0,0,N)]; + } else if (N == 2) { + return a[jkqtplinalgMatIndex(0,0,N)] * a[jkqtplinalgMatIndex(1,1,N)] - a[jkqtplinalgMatIndex(1,0,N)] * a[jkqtplinalgMatIndex(0,1,N)]; + } else if (N==3){ + Eigen::Map > eA(a); + return eA.determinant(); + } else if (N==4){ + Eigen::Map > eA(a); + return eA.determinant(); + } else { + Eigen::Map > eA(a,N,N); + return eA.determinant(); + } +#else + long i,j,j1,j2; + T det = 0; + + if (N < 1) { /* Error */ + det=NAN; + } else if (N == 1) { /* Shouldn't get used */ + det = a[jkqtplinalgMatIndex(0,0,N)]; + } else if (N == 2) { + det = a[jkqtplinalgMatIndex(0,0,N)] * a[jkqtplinalgMatIndex(1,1,N)] - a[jkqtplinalgMatIndex(1,0,N)] * a[jkqtplinalgMatIndex(0,1,N)]; + } else { + det = 0; + for (j1=0;j1 m(static_cast(jkqtpArrayCalloc((N-1)*(N-1),sizeof(T *)))); + + for (i=1;i #include - -#ifndef __WINDOWS__ -# ifndef __LINUX__ -# warning("these methods are ment to be used under windows or linux ... no other system were tested") -# endif -#endif +#include "jkqtcommon/jkqtpstringtools.h" /* This just distinguishes between the different path formats on Windows and Unix: * - on Windows you use a backslash '\' do separate directories @@ -603,6 +598,22 @@ namespace { // anonymous namespace to limit availability to this module (CPP-fil } +void JKQTPMathParser::jkmpError(const std::string &st) { + if (jkmathparser_exception_function!=nullptr) { + jkmathparser_exception_function(st); + } else { + throw jkmpException(st); + } +} + +void JKQTPMathParser::setException_function(JKQTPMathParser::jkmpexceptionf exception_function) { + jkmathparser_exception_function=exception_function; +} + +void JKQTPMathParser::resetException_function() { + jkmathparser_exception_function=nullptr; +} + std::string JKQTPMathParser::tokentostring(JKQTPMathParser::jkmpTokenType token) { switch(token) { case END: return "END"; @@ -678,7 +689,7 @@ std::string JKQTPMathParser::currenttokentostring() { /****************************************************************************************** - * jkMathParser + * JKQTPMathParser ******************************************************************************************/ // class constructor @@ -783,6 +794,16 @@ JKQTPMathParser::~JKQTPMathParser() clearVariables(); } +void JKQTPMathParser::setData(void *__value) +{ + this->data = __value; +} + +void *JKQTPMathParser::getData() const +{ + return this->data; +} + void JKQTPMathParser::addVariableDouble(const std::string& ni, double* v) { std::string name=strip(ni); @@ -903,6 +924,8 @@ void JKQTPMathParser::deleteVariable(const std::string& name) { } } +void JKQTPMathParser::clearFunctions() {functions.clear();} + void JKQTPMathParser::clearVariables(){ if (variables.size()>0) { @@ -987,8 +1010,20 @@ JKQTPMathParser::jkmpEvaluateFunc JKQTPMathParser::getFunctionDef(const std::str return nullptr; } +bool JKQTPMathParser::tempvariableExists(const std::string &name){ + if (tempvariables.size()<=0) return false; + for (int i=tempvariables.size()-1; i>=0; i--) { + if (tempvariables[i].name==name) return true; + } + return false; +} + +bool JKQTPMathParser::variableExists(const std::string &name){ return tempvariableExists(name)||(variables.find(name)!=variables.end()); } + +bool JKQTPMathParser::functionExists(const std::string &name){ return !(functions.find(name)==functions.end()); } + void JKQTPMathParser::addTempVariable(const std::string& name, JKQTPMathParser::jkmpResult value) { - jkmpTempVariable v; + jkmpTempVariable v; v.name=name; v.type=value.type; v.internal=true; @@ -1312,7 +1347,7 @@ JKQTPMathParser::jkmpNode* JKQTPMathParser::primary(bool get){ } case NAME: { - //jkMathParser::jkmpNode* def=nullptr; + //JKQTPMathParser::jkmpNode* def=nullptr; std::string varname=StringValue; getToken(); if (CurrentToken == ASSIGN) { // assign a variable name @@ -1412,7 +1447,7 @@ std::string JKQTPMathParser::readDelim(char delimiter){ while(program->get(ch)) { if (ch==delimiter ) { - char ch1=program->peek(); + const char ch1=static_cast(program->peek()); if (ch1==delimiter) { program->get(ch); res=res+delimiter; @@ -1714,27 +1749,22 @@ JKQTPMathParser::jkmpResult JKQTPMathParser::jkmpBinaryBoolNode::evaluate(){ res.type=JKQTPMathParser::jkmpBool; res.boolean=l.boolean&&r.boolean; return res; - break; case jkmpLOPor: res.type=JKQTPMathParser::jkmpBool; res.boolean=l.boolean||r.boolean; return res; - break; case jkmpLOPnor: res.type=JKQTPMathParser::jkmpBool; res.boolean=!(l.boolean||r.boolean); return res; - break; case jkmpLOPxor: res.type=JKQTPMathParser::jkmpBool; res.boolean=(l.boolean&& (!r.boolean))||(r.boolean&& (!l.boolean)); return res; - break; case jkmpLOPnand: res.type=JKQTPMathParser::jkmpBool; res.boolean=!(l.boolean&&r.boolean); return res; - break; default: parser->jkmpError("unknown error"); } res.isValid=false; @@ -1776,6 +1806,8 @@ JKQTPMathParser::jkmpResult JKQTPMathParser::jkmpNodeList::evaluate(){ return res; } +int JKQTPMathParser::jkmpNodeList::getCount() {return list.size();} + JKQTPMathParser::jkmpNodeList::jkmpNodeList(JKQTPMathParser *p) { setParser(p); setParent(nullptr); } JKQTPMathParser::jkmpNodeList::~jkmpNodeList() = default; @@ -1820,7 +1852,7 @@ JKQTPMathParser::jkmpResult JKQTPMathParser::jkmpFunctionNode::evaluate() { data[i]=child[i]->evaluate(); } } -// jkMathParser::jkmpResult r= getParser()->evaluateFunction(fun, data,n); +// JKQTPMathParser::jkmpResult r= getParser()->evaluateFunction(fun, data,n); return function(data,n, parser); } @@ -1848,6 +1880,24 @@ JKQTPMathParser::jkmpResult::jkmpResult() boolean=false; /*!< \brief contains result if \c type==jkmpBool */ } +std::string JKQTPMathParser::jkmpResult::toString() { + switch(type) { + case jkmpDouble: return jkqtp_floattostr(num); + case jkmpString: return str; + case jkmpBool: return jkqtp_booltostr(boolean); + } + return ""; +} + +std::string JKQTPMathParser::jkmpResult::toTypeString() { + switch(type) { + case jkmpDouble: return jkqtp_floattostr(num)+" [number]"; + case jkmpString: return str+" [string]"; + case jkmpBool: return jkqtp_booltostr(boolean)+" [bool]"; + } + return ""; +} + JKQTPMathParser::jkmpVariable::jkmpVariable() { type=jkmpDouble; /*!< \brief type of the variable */ @@ -1881,6 +1931,26 @@ JKQTPMathParser::jkmpResult JKQTPMathParser::jkmpConstantNode::evaluate() { retu JKQTPMathParser::jkmpException::~jkmpException() = default; +JKQTPMathParser::jkmpException::jkmpException() { + errormessage="unknown error"; +} + +JKQTPMathParser::jkmpException::jkmpException(const std::string &msg) { + errormessage=msg; +} + +std::string JKQTPMathParser::jkmpException::getMessage() const { + return errormessage; +} + const char *JKQTPMathParser::jkmpException::what() const noexcept { return getMessage().c_str(); } + +JKQTPMathParser *JKQTPMathParser::jkmpNode::getParser(){ return parser; } + +void JKQTPMathParser::jkmpNode::setParser(JKQTPMathParser *mp){ parser=mp; } + +JKQTPMathParser::jkmpNode *JKQTPMathParser::jkmpNode::getParent(){ return parent; } + +void JKQTPMathParser::jkmpNode::setParent(JKQTPMathParser::jkmpNode *par) { parent=par; } diff --git a/lib/jkqtplottertools/jkqtpmathparser.h b/lib/jkqtcommon/jkqtpmathparser.h similarity index 87% rename from lib/jkqtplottertools/jkqtpmathparser.h rename to lib/jkqtcommon/jkqtpmathparser.h index aba6347393..3a79f043ae 100644 --- a/lib/jkqtplottertools/jkqtpmathparser.h +++ b/lib/jkqtcommon/jkqtpmathparser.h @@ -29,7 +29,7 @@ */ /** -* \defgroup jkmpultil utilities for jkMathParser function parser class +* \defgroup jkmpultil utilities for JKQTPMathParser function parser class * \ingroup jkmp */ @@ -54,7 +54,6 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" #ifndef JKQTPMATHPARSER_H @@ -84,7 +83,7 @@ memory is provided by the calling program. The parser supports a variable assign operation \code a=\endcode which allows to define new variables during evaluation. There are some mathematical standard constants - registered by calling jkMathParser::addStandardVariables(): + registered by calling JKQTPMathParser::addStandardVariables(): - \c pi = \f$ \pi \f$ - \c e = \f$ \exp(1) \f$ - \c sqrt2 = \f$ \sqrt{2} \f$ @@ -110,8 +109,8 @@ - \c kB = \f$ k_B=1.380650424\cdot 10^{-23}\;\mathrm{\frac{J}{K}} \f$ (Boltzman constant) - \c kB_eV = \f$ k_B=8.61734315\cdot 10^{-5}\;\mathrm{\frac{eV}{K}} \f$ (Boltzman constant) . - You can add user-defined contants by calling jkMathParser::addVariableDouble() - jkMathParser::addVariableBoolean() or jkMathParser::addVariableString() + You can add user-defined contants by calling JKQTPMathParser::addVariableDouble() + JKQTPMathParser::addVariableBoolean() or JKQTPMathParser::addVariableString() \section jkmp_functions functions: @@ -135,11 +134,11 @@ - cmdparam, argv . - these functions are registere by calling jkMathParser::addStandardFunctions(). - you can add new functions by calling jkMathParser::addFunction(); + these functions are registered by calling JKQTPMathParser::addStandardFunctions(). + you can add new functions by calling JKQTPMathParser::addFunction(); \section jkmp_resultsofparsing result of parsing and evaluation: - The result of calling jkMathParser::parse() + The result of calling JKQTPMathParser::parse() will be a tree-like structure in memory. The parse() function will return a pointer to the root node of this structure. All nodes inherit from jkmpNode class. To evaluate such a structure simply call jkmpNode::evaluate() @@ -189,7 +188,7 @@ \section jkmp_example Simple Example of Usage \code try { - jkMathParser mp; // instanciate + JKQTPMathParser mp; // instanciate jkmpNode* n; jkmpResult r; // parse some numeric expression @@ -237,7 +236,7 @@ } int main() { - jkMathParser mp; + JKQTPMathParser mp; mp.setException_function(error); // make error ahndler known ... } @@ -248,7 +247,7 @@ class JKQTPMathParser protected: void* data; - /** \brief the possible tokens that can be recognized by the tokenizer in jkMathParser::getToken() + /** \brief the possible tokens that can be recognized by the tokenizer in JKQTPMathParser::getToken() * \ingroup jkmpultil */ enum jkmpTokenType { @@ -333,24 +332,10 @@ class JKQTPMathParser bool boolean; /*!< \brief contains result if \c type==jkmpBool */ /** \brief convert the value this struct representens into a std::string */ - inline std::string toString() { - switch(type) { - case jkmpDouble: return jkqtp_floattostr(num); - case jkmpString: return str; - case jkmpBool: return jkqtp_booltostr(boolean); - } - return ""; - } + std::string toString(); /** \brief convert the value this struct representens into a std::string and adds the name of the datatype in \c [...] */ - inline std::string toTypeString() { - switch(type) { - case jkmpDouble: return jkqtp_floattostr(num)+" [number]"; - case jkmpString: return str+" [string]"; - case jkmpBool: return jkqtp_booltostr(boolean)+" [bool]"; - } - return ""; - } + std::string toTypeString(); }; @@ -386,7 +371,7 @@ class JKQTPMathParser * * If you want to add more math functions (like sin, cos , abs ...) to the * parser, you will have to implement it with this prototype and then register - * it with jkMathParser::addFunction(). The first parameter points to an array + * it with JKQTPMathParser::addFunction(). The first parameter points to an array * containing the input parameters while the second one specifies the number * of supplied parameters. The result has to be of type jkmpResult. * @@ -433,17 +418,17 @@ class JKQTPMathParser /** \brief evaluate this node */ virtual jkmpResult evaluate()=0; - /** \brief return a pointer to the jkMathParser */ - inline JKQTPMathParser* getParser(){ return parser; } + /** \brief return a pointer to the JKQTPMathParser */ + JKQTPMathParser *getParser(); - /** \brief set the jkMathParser */ - inline void setParser(JKQTPMathParser* mp){ parser=mp; } + /** \brief set the JKQTPMathParser */ + void setParser(JKQTPMathParser* mp); /** \brief returns a pointer to the parent node */ - inline jkmpNode* getParent(){ return parent; } + jkmpNode *getParent(); /** \brief sets the parent node */ - inline void setParent(jkmpNode* par) { parent=par; } + void setParent(jkmpNode* par); }; @@ -461,7 +446,7 @@ class JKQTPMathParser * \param op the operation to be performed: add (+), subtract (-), multiply (*), divide (/), a to the power of b (a^b) * \param l left child node/operand * \param r right child node/operand - * \param p a pointer to a jkMathParser object + * \param p a pointer to a JKQTPMathParser object * \param par a pointer to the parent node */ jkmpBinaryArithmeticNode(char op, jkmpNode* l, jkmpNode* r, JKQTPMathParser* p, jkmpNode* par); @@ -486,7 +471,7 @@ class JKQTPMathParser * \param op the operation to be performed: (a)nd, (o)r, (x)or, (n)or, nand (A) * \param l left child node/operand * \param r right child node/operand - * \param p a pointer to a jkMathParser object + * \param p a pointer to a JKQTPMathParser object * \param par a pointer to the parent node */ jkmpBinaryBoolNode(char op, jkmpNode* l, jkmpNode* r, JKQTPMathParser* p, jkmpNode* par); @@ -511,7 +496,7 @@ class JKQTPMathParser * \param op the operation to be performed: != (!), == (=), >= (b), <= (a), (>), (<) * \param l left child node/operand * \param r right child node/operand - * \param p a pointer to a jkMathParser object + * \param p a pointer to a JKQTPMathParser object * \param par a pointer to the parent node */ jkmpCompareNode(char op, jkmpNode* l, jkmpNode* r, JKQTPMathParser* p, jkmpNode* par); @@ -535,7 +520,7 @@ class JKQTPMathParser /** \brief constructor for a jkmpUnaryNode * \param op the operation to be performed: (!), (-) * \param c child node/operand - * \param p a pointer to a jkMathParser object + * \param p a pointer to a JKQTPMathParser object * \param par a pointer to the parent node */ jkmpUnaryNode(char op, jkmpNode* c, JKQTPMathParser* p, jkmpNode* par); @@ -563,7 +548,7 @@ class JKQTPMathParser /** \brief constructor for a jkmpVariableAssignNode * \param var name of the variable to assign to * \param c child node/right-hand-side expression - * \param p a pointer to a jkMathParser object + * \param p a pointer to a JKQTPMathParser object * \param par a pointer to the parent node */ jkmpVariableAssignNode(const std::string& var, jkmpNode* c, JKQTPMathParser* p, jkmpNode* par); @@ -582,7 +567,7 @@ class JKQTPMathParser public: /** \brief constructor for a jkmpConstantNode * \param d the value of the constant - * \param p a pointer to a jkMathParser object + * \param p a pointer to a JKQTPMathParser object * \param par a pointer to the parent node */ jkmpConstantNode(jkmpResult d, JKQTPMathParser* p, jkmpNode* par); @@ -601,7 +586,7 @@ class JKQTPMathParser public: /** \brief constructor for a jkmpVariableNode * \param name name of the variable - * \param p a pointer to a jkMathParser object + * \param p a pointer to a JKQTPMathParser object * \param par a pointer to the parent node */ jkmpVariableNode(const std::string& name, JKQTPMathParser* p, jkmpNode* par); @@ -615,7 +600,7 @@ class JKQTPMathParser * \ingroup jkmpNodes * * When initialized this class will get the function description that is - * linked to the supplied function name from jkMathParser object. This + * linked to the supplied function name from JKQTPMathParser object. This * information is saved locally and won't be changed when evaluating! * * Functions may have 8 parameters at the most. @@ -631,7 +616,7 @@ class JKQTPMathParser * \param name name of the function * \param c a pointer to an array of jkmpNode objects that represent the parameter expressions * \param num number of children in c - * \param p a pointer to a jkMathParser object + * \param p a pointer to a JKQTPMathParser object * \param par a pointer to the parent node */ jkmpFunctionNode(const std::string& name, jkmpNode** c, unsigned char num, JKQTPMathParser* p, jkmpNode* par); @@ -654,7 +639,7 @@ class JKQTPMathParser std::vector list; public: /** \brief constructor for a jkmpNodeList - * \param p a pointer to a jkMathParser object + * \param p a pointer to a JKQTPMathParser object */ jkmpNodeList(JKQTPMathParser* p); @@ -668,7 +653,7 @@ class JKQTPMathParser virtual jkmpResult evaluate() override; /** \brief get the number of nodes in the list */ - inline int getCount() {return list.size();}; + int getCount(); }; /*@}*/ @@ -694,25 +679,19 @@ class JKQTPMathParser std::string errormessage; public: /** \brief class constructors */ - inline jkmpException() { - errormessage="unknown error"; - } + jkmpException(); /** \brief constructor with supplied error message */ - inline jkmpException(const std::string& msg) { - errormessage=msg; - } + jkmpException(const std::string& msg); /** \brief class destructors */ virtual ~jkmpException() override; /** \brief returns the assigned errormessage */ - inline std::string getMessage() const { - return errormessage; - } + std::string getMessage() const; /** \brief returns the error description as C string */ - virtual const char* what() const throw(); + virtual const char* what() const noexcept override; }; /** \brief type for a custom error handler. This an alternative error handling @@ -722,13 +701,7 @@ class JKQTPMathParser /** \brief function that throws an exception or calls an error handler * \ingroup jkmpErrorhandling */ - inline void jkmpError(const std::string& st) { - if (jkmathparser_exception_function!=nullptr) { - jkmathparser_exception_function(st); - } else { - throw jkmpException(st); - } - } + void jkmpError(const std::string& st); private: /** \brief if this is nullptr then an exception may be thrown otherwise this should point to an error handler that will be called. @@ -738,15 +711,11 @@ class JKQTPMathParser public: /** \brief activate error handling by use of an exception function * \ingroup jkmpErrorhandling */ - inline void setException_function(jkmpexceptionf exception_function) { - jkmathparser_exception_function=exception_function; - } + void setException_function(jkmpexceptionf exception_function); /** \brief deactivate error handling by use of an exception function * \ingroup jkmpErrorhandling */ - inline void resetException_function() { - jkmathparser_exception_function=nullptr; - } + void resetException_function(); protected: @@ -828,15 +797,9 @@ class JKQTPMathParser virtual ~JKQTPMathParser(); /*! \copydoc data */ - inline virtual void setData(void* __value) - { - this->data = __value; - } + virtual void setData(void* __value); /*! \copydoc data */ - inline virtual void* getData() const - { - return this->data; - } + virtual void* getData() const; /** \brief register a new function * \param name name of the new function @@ -909,19 +872,13 @@ class JKQTPMathParser jkmpEvaluateFunc getFunctionDef(const std::string& name); /** \brief tests whether a temporary variable exists */ - inline bool tempvariableExists(const std::string& name){ - if (tempvariables.size()<=0) return false; - for (int i=tempvariables.size()-1; i>=0; i--) { - if (tempvariables[i].name==name) return true; - } - return false; - } + bool tempvariableExists(const std::string& name); /** \brief tests whether a variable exists */ - inline bool variableExists(const std::string& name){ return tempvariableExists(name)||(variables.find(name)!=variables.end()); }; + bool variableExists(const std::string& name); /** \brief tests whether a function exists */ - inline bool functionExists(const std::string& name){ return !(functions.find(name)==functions.end()); }; + bool functionExists(const std::string& name); /** \brief deletes all defined variables. the memory of internal variables * will be released. the external memory will not be released. @@ -932,7 +889,7 @@ class JKQTPMathParser void deleteVariable(const std::string& name); /** \brief clears the list of internal functions*/ - inline void clearFunctions() {functions.clear();} + void clearFunctions(); /** \brief registers standard variables*/ void addStandardVariables(); diff --git a/lib/jkqtcommon/jkqtpcommonmathtools.cpp b/lib/jkqtcommon/jkqtpmathtools.cpp similarity index 91% rename from lib/jkqtcommon/jkqtpcommonmathtools.cpp rename to lib/jkqtcommon/jkqtpmathtools.cpp index 2e5057cec9..cf20a159cc 100644 --- a/lib/jkqtcommon/jkqtpcommonmathtools.cpp +++ b/lib/jkqtcommon/jkqtpmathtools.cpp @@ -21,5 +21,7 @@ Copyright (c) 2008-2019 Jan W. Krieger () -#include "jkqtcommon/jkqtpcommonmathtools.h" +#include "jkqtcommon/jkqtpmathtools.h" #include + + diff --git a/lib/jkqtcommon/jkqtpmathtools.h b/lib/jkqtcommon/jkqtpmathtools.h new file mode 100644 index 0000000000..a2eb4691a4 --- /dev/null +++ b/lib/jkqtcommon/jkqtpmathtools.h @@ -0,0 +1,258 @@ +/* + Copyright (c) 2008-2019 Jan W. Krieger (, ) + + + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + + + +#ifndef jkqtpmathtools_H_INCLUDED +#define jkqtpmathtools_H_INCLUDED +#include "jkqtcommon/jkqtp_imexport.h" +#include +#include +#include +#include + + + +/*! \brief \f$ \sqrt{2\pi}=2.50662827463 \f$ + \ingroup jkqtptools_math_basic + +*/ +#define JKQTPSTATISTICS_SQRT_2PI 2.50662827463 + + +/** \brief double-value NotANumber + * \ingroup jkqtptools_math_basic + */ +#define JKQTP_DOUBLE_NAN (std::numeric_limits::signaling_NaN()) + +/** \brief float-value NotANumber + * \ingroup jkqtptools_math_basic + */ +#define JKQTP_FLOAT_NAN (std::numeric_limits::signaling_NaN()) + +/** \brief double-value NotANumber + * \ingroup jkqtptools_math_basic + */ +#define JKQTP_NAN JKQTP_DOUBLE_NAN + +/** \brief double-value epsilon + * \ingroup jkqtptools_math_basic + */ +#define JKQTP_DOUBLE_EPSILON (std::numeric_limits::epsilon()) + +/** \brief float-value epsilon + * \ingroup jkqtptools_math_basic + */ +#define JKQTP_FLOAT_EPSILON (std::numeric_limits::epsilon()) + +/** \brief double-value NotANumber + * \ingroup jkqtptools_math_basic + */ +#define JKQTP_EPSILON JKQTP_DOUBLE_EPSILON + +/** \brief converts a boolean to a double, is used to convert boolean to double by JKQTPDatastore + * \ingroup jkqtptools_math_basic + * + * This function uses static_cast() by default, but certain specializations (e.g. for bool) are + * readily available. + * + * \callergraph + */ +template +inline constexpr double jkqtp_todouble(const T& d) { + return static_cast(d); +} + + +/** \brief converts a boolean to a double, is used to convert boolean to double by JKQTPDatastore + * \ingroup jkqtptools_math_basic + * + * Specialisation of the generic template jkqtp_todouble() with (true -> 1.0, false -> 0.0) + * + * \callergraph + */ +template<> +inline constexpr double jkqtp_todouble(const bool& d) { + return static_cast((d)?1.0:0.0); +} + + +/** \brief round a double \a v using round() and convert it to a specified type T (static_cast!) + * \ingroup jkqtptools_math_basic + * + * \tparam T a numeric datatype (int, double, ...) + * \param v the value to round and cast + * + * this is equivalent to + * \code + * static_cast(round(v)); + * \endcode + * + * \callergraph + */ +template +inline T jkqtp_roundTo(const double& v) { + return static_cast(round(v)); +} + + +/** \brief round a double \a v using round() and convert it to a specified type T (static_cast!). + * Finally the value is bounded to the range \a min ... \a max + * \ingroup jkqtptools_math_basic + * + * \tparam T a numeric datatype (int, double, ...) + * \param min minimum output value + * \param v the value to round and cast + * \param max maximum output value + * + * this is equivalent to + * \code + * qBound(min, static_cast(round(v)), max); + * \endcode + */ +template +inline T jkqtp_boundedRoundTo(T min, const double& v, T max) { + return qBound(min, static_cast(round(v)), max); +} + +/** \brief round a double \a v using round() and convert it to a specified type T (static_cast!). + * Finally the value is bounded to the range \c std::numeric_limits::min() ... \c std::numeric_limits::max() + * \ingroup jkqtptools_math_basic + * + * \tparam T a numeric datatype (int, double, ...) + * \param v the value to round and cast + * + * this is equivalent to + * \code + * jkqtp_boundedRoundTo(std::numeric_limits::min(), v, std::numeric_limits::max()) + * \endcode + */ +template +inline T jkqtp_boundedRoundTo(const double& v) { + return jkqtp_boundedRoundTo(std::numeric_limits::min(), v, std::numeric_limits::max()); +} + +/** \brief bounds a value \a v to the given range \a min ... \a max + * \ingroup jkqtptools_math_basic + * + * \tparam T a numeric datatype (int, double, ...) + * \param min minimum output value + * \param v the value to round and cast + * \param max maximum output value + */ +template +inline T jkqtp_bounded(T min, T v, T max) { + if (vmax) return max; + return v; +} + +/** \brief compare two floats \a a and \a b for euqality, where any difference smaller than \a epsilon is seen as equality + * \ingroup jkqtptools_math_basic */ +inline bool jkqtp_approximatelyEqual(float a, float b, float epsilon=2.0f*JKQTP_FLOAT_EPSILON) +{ + return fabsf(a - b) <= epsilon; +} + +/** \brief compare two doubles \a a and \a b for euqality, where any difference smaller than \a epsilon is seen as equality + * \ingroup jkqtptools_math_basic */ +inline bool jkqtp_approximatelyEqual(double a, double b, double epsilon=2.0*JKQTP_DOUBLE_EPSILON) +{ + return fabs(a - b) <= epsilon; +} + +/** \brief returns the given value \a v (i.e. identity function) + * \ingroup jkqtptools_math_basic */ +template +inline T jkqtp_identity(const T& v) { + return v; +} + +/** \brief returns the quare of the value \a v, i.e. \c v*v + * \ingroup jkqtptools_math_basic */ +template +inline T jkqtp_sqr(const T& v) { + return v*v; +} + + +/*! \brief 4-th power of a number + \ingroup jkqtptools_math_basic + +*/ +template +inline T jkqtp_pow4(T x) { + const T xx=x*x; + return xx*xx; +} + +/*! \brief cube of a number + \ingroup jkqtptools_math_basic + +*/ +template +inline T jkqtp_cube(T x) { + return x*x*x; +} + + +/*! \brief calculates the sign of number \a x + \ingroup jkqtptools_math_basic +*/ +template +inline T jkqtp_sign(T x) { + if (x<0) return -1; + //else if (x==0) return 0; + else return 1; +} + +/** \brief calculate the distance between two QPointF points + * \ingroup jkqtptools_math_basic + * + */ +inline double jkqtp_distance(const QPointF& p1, const QPointF& p2){ + return sqrt(jkqtp_sqr(p1.x()-p2.x())+jkqtp_sqr(p1.y()-p2.y())); +} + +/** \brief calculate the distance between two QPoint points + * \ingroup jkqtptools_math_basic + * + */ +inline double jkqtp_distance(const QPoint& p1, const QPoint& p2){ + return sqrt(jkqtp_sqr(p1.x()-p2.x())+jkqtp_sqr(p1.y()-p2.y())); +} + +/** \brief check whether the dlotaing point number is OK (i.e. non-inf, non-NAN) + * \ingroup jkqtptools_math_basic + */ +template +inline bool JKQTPIsOKFloat(T v) { + return std::isfinite(v)&&(!std::isinf(v))&&(!std::isnan(v)); +} + +/** \brief evaluates a gaussian propability density function + * \ingroup jkqtptools_math_basic + * + * \f[ f(x,\mu, \sigma)=\frac{1}{\sqrt{2\pi\sigma^2}}\cdot\exp\left(-\frac{(x-\mu)^2}{2\sigma^2}\right) + */ +inline double jkqtp_gaussdist(double x, double mu=0.0, double sigma=1.0) { + return exp(-0.5*jkqtp_sqr(x-mu)/jkqtp_sqr(sigma))/sqrt(2.0*M_PI*sigma*sigma); +} + +#endif // jkqtpmathtools_H_INCLUDED diff --git a/lib/jkqtcommon/jkqtpstatisticstools.cpp b/lib/jkqtcommon/jkqtpstatisticstools.cpp new file mode 100644 index 0000000000..956df70b01 --- /dev/null +++ b/lib/jkqtcommon/jkqtpstatisticstools.cpp @@ -0,0 +1,106 @@ +/* + Copyright (c) 2008-2019 Jan W. Krieger () + + last modification: $LastChangedDate$ (revision $Rev$) + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + + + +#include "jkqtpstatisticstools.h" + + +double jkqtpstatKernel1DGaussian(double t) { + return exp(-0.5*t*t)/JKQTPSTATISTICS_SQRT_2PI; +} + + +double jkqtpstatKernel1DCauchy(double t) { + return 1.0/(M_PI*(1.0+t*t)); +} + + + +double jkqtpstatKernel1DPicard(double t) { + return exp(-0.5*fabs(t))/2.0; +} + + +double jkqtpstatKernel1DEpanechnikov(double t) { + return (fabs(t)<1.0)?(0.75*(1.0-t*t)):0.0; +} + + +double jkqtpstatKernel1DUniform(double t) { + return (fabs(t)<=1.0)?0.5:0.0; +} + + +double jkqtpstatKernel1DTriangle(double t) { + return (fabs(t)<=1.0)?(1.0-fabs(t)):0.0; +} + + + +double jkqtpstatKernel1DQuartic(double t) { + return (fabs(t)<=1.0)?(15.0/16.0*jkqtp_sqr(1.0-t*t)):0.0; +} + + +double jkqtpstatKernel1DTriweight(double t) { + return (fabs(t)<1.0)?(35.0/32.0*jkqtp_cube(1.0-t*t)):0.0; +} + + + +double jkqtpstatKernel1DTricube(double t) { + return (fabs(t)<1.0)?(70.0/81.0*jkqtp_cube(1.0-jkqtp_cube(fabs(t)))):0.0; +} + + +double jkqtpstatKernel1DCosine(double t) { + return (fabs(t)<1.0)?(M_PI/4.0*cos(t*M_PI/2.0)):0.0; +} + + +double jkqtpstatKernel2DGaussian(double tx, double ty) +{ + return exp(-0.5*(tx*tx+ty*ty))/(2.0*M_PI); +} + +double jkqtpstatKernel2DUniform(double tx, double ty) { + return (fabs(tx)<1.0 && fabs(ty)<=1.0)?0.25:0.0; +} + +JKQTPStat5NumberStatistics::JKQTPStat5NumberStatistics(): + minimum(JKQTP_DOUBLE_NAN), + minimumQuantile(0), + quantile1(JKQTP_DOUBLE_NAN), + quantile1Spec(0.25), + median(JKQTP_DOUBLE_NAN), + quantile2(JKQTP_DOUBLE_NAN), + quantile2Spec(0.75), + maximum(JKQTP_DOUBLE_NAN), + maximumQuantile(1), + N(0) +{} + +double JKQTPStat5NumberStatistics::IQR() const { + return quantile2-quantile1; +} + +double JKQTPStat5NumberStatistics::IQRSignificanceEstimate() const { + return 2.0*(1.58*(IQR()))/sqrt(static_cast(N)); +} diff --git a/lib/jkqtcommon/jkqtpstatisticstools.h b/lib/jkqtcommon/jkqtpstatisticstools.h new file mode 100644 index 0000000000..0be24ea86e --- /dev/null +++ b/lib/jkqtcommon/jkqtpstatisticstools.h @@ -0,0 +1,1430 @@ +/* + Copyright (c) 2008-2019 Jan W. Krieger () + + last modification: $LastChangedDate$ (revision $Rev$) + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + + +#ifndef JKQTPSTATISTICSTOOLS_H_INCLUDED +#define JKQTPSTATISTICSTOOLS_H_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "jkqtcommon/jkqtp_imexport.h" +#include "jkqtcommon/jkqtplinalgtools.h" +#include "jkqtcommon/jkqtparraytools.h" + + +#ifdef _OPENMP +# include +#endif + + + + + + + +/*! \brief calculates the average of a given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return Average of the data returned between \a first and \a last (excluding invalid doubles). + If the given range \a first ... \a last is empty, NAN is returned + + This function implements: + \f[ \overline{X}=\frac{1}{N}\cdot\sum\limits_{i=1}^{N}X_i \f] + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline double jkqtpstatAverage(InputIt first, InputIt last, size_t* Noutput=nullptr) { + double sum=0; + size_t NN=0; + for (auto it=first; it!=last; ++it) { + const double v=jkqtp_todouble(*it); + if (JKQTPIsOKFloat(v)) { + sum=sum+v; + NN++; + } + } + if (Noutput) *Noutput=NN; + if (NN<=0) return JKQTP_DOUBLE_NAN; + else return sum/static_cast(NN); +} + + + +/*! \brief calculates the weighted average of a given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \tparam InputWeightIt standard iterator type of \a firstWeight + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param firstWeight iterator pointing to the first item in the weights dataset \f$ w_i \f$ + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return weighted average of the data returned between \a first and \a last (excluding invalid doubles). + If the given range \a first ... \a last is empty, NAN is returned + + This function implements: + \f[ \overline{X}=\frac{\sum\limits_{i=1}^{N}w_i\cdot X_i}{\sum\limits_{i=1}^{N}w_i} \f] + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline double jkqtpstatWeightedAverage(InputIt first, InputIt last, InputWeightIt firstWeight, size_t* Noutput=nullptr) { + double sum=0; + double sumW=0; + size_t NN=0; + auto itW=firstWeight; + for (auto it=first; it!=last; ++it,++itW) { + const double v=jkqtp_todouble(*it); + const double w=jkqtp_todouble(*itW); + if (JKQTPIsOKFloat(v)) { + sum=sum+v*w; + sumW=sumW+w; + NN++; + } + } + if (Noutput) *Noutput=NN; + if (NN<=0) return JKQTP_DOUBLE_NAN; + else return sum/sumW; +} + + + +/*! \brief calculates the number of valid values in the given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \return number of valid values between \a first and \a last (excluding invalid doubles). + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline size_t jkqtpstatCount(InputIt first, InputIt last) { + double sum=0; + size_t NN=0; + for (auto it=first; it!=last; ++it) { + const double v=jkqtp_todouble(*it); + if (JKQTPIsOKFloat(v)) { + sum=sum+v; + NN++; + } + } + return NN; +} + + + + +/*! \brief calculates the minimum and maximum values in the given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param[out] min receives the minimum element value + \param[out] max receives the maximum element value + \param[out] minPos receives the location of the minimum element value + \param[out] maxPos receives the location of the minimum maximum element value + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline void jkqtpstatMinMax(InputIt first, InputIt last, double& min, double& max, InputIt* minPos=nullptr, InputIt* maxPos=nullptr, size_t* Noutput=nullptr) { + size_t NN=0; + bool firstV=true; + InputIt minp=last; + InputIt maxp=last; + for (auto it=first; it!=last; ++it) { + const double v=jkqtp_todouble(*it); + if (JKQTPIsOKFloat(v)) { + if (firstV) { + min=v; + max=v; + minp=it; + maxp=it; + firstV=false; + } else { + if (vmax) { + max=v; + maxp=it; + } + } + NN++; + } + } + if (NN<=0) { + min=JKQTP_DOUBLE_NAN; + max=JKQTP_DOUBLE_NAN; + } + if (Noutput) *Noutput=NN; + if (minPos) *minPos=minp; + if (maxPos) *maxPos=maxp; +} + + + + + +/*! \brief calculates the minimum value in the given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param[out] minPos receives the location of the minimum element value + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return the minimum value from the given range + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline double jkqtpstatMinimum(InputIt first, InputIt last, InputIt* minPos=nullptr, size_t* Noutput=nullptr) { + size_t NN=0; + bool firstV=true; + InputIt minp=last; + double min=JKQTP_DOUBLE_NAN; + for (auto it=first; it!=last; ++it) { + const double v=jkqtp_todouble(*it); + if (JKQTPIsOKFloat(v)) { + if (firstV) { + min=v; + minp=it; + firstV=false; + } else { + if (v +inline double jkqtpstatMaximum(InputIt first, InputIt last, InputIt* maxPos=nullptr, size_t* Noutput=nullptr) { + size_t NN=0; + bool firstV=true; + InputIt maxp=last; + double max=JKQTP_DOUBLE_NAN; + for (auto it=first; it!=last; ++it) { + const double v=jkqtp_todouble(*it); + if (JKQTPIsOKFloat(v)) { + if (firstV) { + max=v; + maxp=it; + firstV=false; + } else { + if (v>max) { + max=v; + maxp=it; + } + } + NN++; + } + } + if (Noutput) *Noutput=NN; + if (maxPos) *maxPos=maxp; + return max; +} + + + +/*! \brief calculates the sum of a given data range \a first ... \a last of values, + modifying each value with a given functor \a modifierFunctor before accumulating + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \tparam FF a functor type + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return Sum of modified data returned between \a first and \a last (excluding invalid doubles). + If the given range \a first ... \a last is empty, 0 is returned + + This function implements: + \f[ \sum(X)=\cdot\sum\limits_{i=1}^{N}\mbox{modifierFunctor}(X_i) \f] + + This function allows to e.g. calculate the sum of squares by calling + \code + jkqtpstatModifiedSum(first, last, [](double v) { return v*v; }); + jkqtpstatModifiedSum(first, last, &jkqtp_sqr); + \endcode + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline double jkqtpstatModifiedSum(InputIt first, InputIt last, FF modifierFunctor, size_t* Noutput=nullptr) { + double sum=0; + size_t NN=0; + for (auto it=first; it!=last; ++it) { + const double v=jkqtp_todouble(*it); + if (JKQTPIsOKFloat(v)) { + sum=sum+modifierFunctor(v); + NN++; + } + } + if (Noutput) *Noutput=NN; + if (NN<=0) return 0; + else return sum; +} + + + +/*! \brief calculates the sum of a given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return Sum of the data returned between \a first and \a last (excluding invalid doubles). + If the given range \a first ... \a last is empty, 0 is returned + + This function implements: + \f[ \sum(X)=\cdot\sum\limits_{i=1}^{N}X_i \f] + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline double jkqtpstatSum(InputIt first, InputIt last, size_t* Noutput=nullptr) { + return jkqtpstatSum(first, last, &jkqtp_identity, Noutput); +} + +/*! \brief calculates the sum of squares of a given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return Sum of squares of the data returned between \a first and \a last (excluding invalid doubles). + If the given range \a first ... \a last is empty, 0 is returned + + This function implements: + \f[ \sum(X)=\cdot\sum\limits_{i=1}^{N}X_i^2 \f] + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline double jkqtpstatSumSqr(InputIt first, InputIt last, size_t* Noutput=nullptr) { + return jkqtpstatSum(first, last, &jkqtp_sqr, Noutput); +} + + +/*! \brief calculates the vector of cummulative (or partial) sums of a given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \tparam OutputIt standard output iterator type + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param[out] output This iterator is used to store the results, use e.g. a std::back_inserter + \return vector of cummulative (or partial) sums returned between \a first and \a last (excluding invalid doubles). + For invalid values, the last sum is re-inserted, so the returned vector has the same number of entries + as the range \a first ... \a last + + This function implements: + \f[ \sum(X)_j=\cdot\sum\limits_{i=1}^{j}X_i \f] + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline void jkqtpstatCumSum(InputIt first, InputIt last, OutputIt output) { + double sum=0; + for (auto it=first; it!=last; ++it) { + const double v=jkqtp_todouble(*it); + if (JKQTPIsOKFloat(v)) { + sum=sum+v; + } + *++output=sum; + } +} + + +/*! \brief filters the given data range \a first ... \a last for good floats (using JKQTPIsOKFloat() ) + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \tparam OutputIt standard output iterator type + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param[out] output This iterator is used to store the results, use e.g. a std::back_inserter + \return number of elementes put into \a output + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline size_t jkqtpstatFilterGoodFloat(InputIt first, InputIt last, OutputIt output) { + size_t NN=0; + for (auto it=first; it!=last; ++it) { + const double v=jkqtp_todouble(*it); + if (JKQTPIsOKFloat(v)) { + *++output=v; + NN++; + } + } + return NN; +} + + + + + + + + + + +/*! \brief calculates the variance of a given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \tparam InputWeightIt standard iterator type of \a firstWeight + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param[out] averageOut returns (optionally) the average of the dataset + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return Variance of the data returned between \a first and \a last (excluding invalid doubles). + If the given range \a first ... \a last is empty, 0 is returned + + This function implements: + \f[ \sigma_X=\text{Var}(X)=\frac{1}{N-1}\cdot\sum\limits_{i=1}^{N}(X_i-\overline{X})^2=\frac{1}{N-1}\cdot\left(\sum_{i=1}^NX_i^2-\frac{1}{N}\cdot\left(\sum_{i=1}^NX_i\right)^2\right) \f] + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline double jkqtpstatVariance(InputIt first, InputIt last, double* averageOut=nullptr, size_t* Noutput=nullptr) { + double sum=0; + double sum2=0; + size_t NN=0; + for (auto it=first; it!=last; ++it) { + const double v=jkqtp_todouble(*it); + if (JKQTPIsOKFloat(v)) { + sum=sum+v; + sum2=sum2+v*v; + NN++; + } + } + if (averageOut) { + if (NN<=0) *averageOut=JKQTP_DOUBLE_NAN; + else *averageOut=sum/static_cast(NN); + } + if (Noutput) *Noutput=NN; + if (NN<=1) return 0; + else return ( sum2 - sum*sum/static_cast(NN) ) / static_cast(NN-1); +} + + + +/*! \brief calculates the variance of a given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param[out] averageOut returns (optionally) the average of the dataset + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return standard deviation of the data returned between \a first and \a last (excluding invalid doubles). + If the given range \a first ... \a last is empty, 0 is returned + + This function implements: + \f[ \sigma_X=\sqrt{\frac{1}{N-1}\cdot\sum\limits_{i=1}^{N}(X_i-\overline{X})^2}= \f] + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline double jkqtpstatStdDev(InputIt first, InputIt last, double* averageOut=nullptr, size_t* Noutput=nullptr) { + return sqrt(jkqtpstatVariance(first, last, averageOut, Noutput)); +} + + + + +/*! \brief calculates the weighted variance of a given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \tparam InputWeightIt standard iterator type of \a firstWeight + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param firstWeight iterator pointing to the first item in the weights dataset \f$ w_i \f$ + \param[out] averageOut returns (optionally) the average of the dataset + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return weighted standard deviation of the data returned between \a first and \a last (excluding invalid doubles). + If the given range \a first ... \a last is empty, 0 is returned + + This function implements: + \f[ \text{Var}(v)=\frac{\sum\limits_{i=1}^{N}w_i\cdot (v_i-\overline{v})^2}{\sum\limits_{i=1}^{N}w_i} \f] + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline double jkqtpstatWeightedVariance(InputIt first, InputIt last, InputWeightIt firstWeight, double* averageOut=nullptr, size_t* Noutput=nullptr) { + double avg=jkqtpstatWeightedAverage(first, last, firstWeight); + double sum2=0; + double sumW=0; + size_t NN=0; + auto itW=firstWeight; + for (auto it=first; it!=last; ++it,++itW) { + const double v=jkqtp_todouble(*it)-avg; + const double w=jkqtp_todouble(*itW); + if (JKQTPIsOKFloat(v)) { + sum2=sum2+v*v*w; + sumW=sumW+w; + NN++; + } + } + if (averageOut) *averageOut=avg; + if (Noutput) *Noutput=NN; + if (NN<=0) return 0; + else return sum2/sumW; +} + + + +/*! \brief calculates the weighted standard deviation of a given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \tparam InputWeightIt standard iterator type of \a firstWeight + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param firstWeight iterator pointing to the first item in the weights dataset \f$ w_i \f$ + \param[out] averageOut returns (optionally) the average of the dataset + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return weighted standard deviation of the data returned between \a first and \a last (excluding invalid doubles). + If the given range \a first ... \a last is empty, 0 is returned + + This function implements: + \f[ \sigma_v=\sqrt{\frac{\sum\limits_{i=1}^{N}w_i\cdot (v_i-\overline{v})^2}{\sum\limits_{i=1}^{N}w_i}} \f] + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline double jkqtpstatWeightedStdDev(InputIt first, InputIt last, InputWeightIt firstWeight, double* averageOut=nullptr, size_t* Noutput=nullptr) { + return sqrt(jkqtpstatWeightedVariance(first, last, firstWeight, averageOut, Noutput)); +} + + + + +/*! \brief calculates the skewness of a given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param[out] averageOut returns (optionally) the average of the dataset + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return skewness \f$ \gamma_1 \f$ of the data returned between \a first and \a last (excluding invalid doubles). + If the given range \a first ... \a last is empty, 0 is returned + + This function implements: + \f[ \gamma_1=\mathbb{E}\left[\left(\frac{X-\mu}{\sigma}\right)^3\right]= \frac{m_3}{m_2^{3/2}} = \frac{\frac{1}{n} \sum_{i=1}^n (x_i-\overline{x})^3}{\left(\frac{1}{n} \sum_{i=1}^n (x_i-\overline{x})^2\right)^{3/2}} \f] + where \f$\mu\f$ is the mean and \f$\sigma\f$ the standard deviation of a random variable \f$X\f$ and \f$\overline{x}\f$ is the average (calculated using jkqtpstatAverage() ) of + the input dataset \f$ x_i\f$. + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline double jkqtpstatSkewness(InputIt first, InputIt last, double* averageOut=nullptr, size_t* Noutput=nullptr) { + double avg=jkqtpstatAverage(first, last); + double sum3=0; + double sum2=0; + size_t NN=0; + for (auto it=first; it!=last; ++it) { + const double v=jkqtp_todouble(*it)-avg; + if (JKQTPIsOKFloat(v)) { + sum3=sum3+jkqtp_cube(v); + sum2=sum2+jkqtp_sqr(v); + NN++; + } + } + if (averageOut) *averageOut=avg; + if (Noutput) *Noutput=NN; + if (NN<=0) return 0; + const double down=jkqtp_cube(sum2/double(NN)); + return sum3/double(NN)/sqrt(down); +} + + + + +/*! \brief calculates the given central moment \f$ \langle (X-\mu)^o\rangle \f$ of a given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param order oder \f$ o \f$ of the central moment \f$ \langle (X-\mu)^o\rangle \f$ + \param[out] averageOut returns (optionally) the average of the dataset + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return the given central moment \f$ \langle (X-\mu)^o\rangle \f$ of the data returned between \a first and \a last (excluding invalid doubles). + If the given range \a first ... \a last is empty, 0 is returned + + This function implements: + \f[ \langle (X-\mu)^o\rangle= \mathbb{E}\left[\left(X-\mu\right)^o\right] \f] + where \f$\mu\f$ is the mean of a random variable \f$X\f$ and \f$\overline{x}\f$ is the average (calculated using jkqtpstatAverage() ) of + the input dataset \f$ x_i\f$. + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline double jkqtpstatCentralMoment(InputIt first, InputIt last, int order, double* averageOut=nullptr, size_t* Noutput=nullptr) { + double avg=jkqtpstatAverage(first, last); + double sum=0; + size_t NN=0; + for (auto it=first; it!=last; ++it) { + const double v=jkqtp_todouble(*it)-avg; + if (JKQTPIsOKFloat(v)) { + sum=sum+pow(v, order); + NN++; + } + } + if (averageOut) *averageOut=avg; + if (Noutput) *Noutput=NN; + if (NN<=0) return 0; + return sum/double(NN); +} + + + + +/*! \brief calculates the given (non-central) moment \f$ \langle X^o\rangle \f$ of a given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param order oder \f$ o \f$ of the central moment \f$ \langle X^o\rangle \f$ + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return the given moment \f$ \langle X^o\rangle \f$ of the data returned between \a first and \a last (excluding invalid doubles). + If the given range \a first ... \a last is empty, 0 is returned + + This function implements: + \f[ \langle X^n\rangle= \mathbb{E}\left[X^n\right] \f] + where \f$\mu\f$ is the mean of a random variable \f$X\f$ and \f$\overline{x}\f$ is the average (calculated using jkqtpstatAverage() ) of + the input dataset \f$ x_i\f$. + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline double jkqtpstatMoment(InputIt first, InputIt last, int order, size_t* Noutput=nullptr) { + double sum=0; + size_t NN=0; + for (auto it=first; it!=last; ++it) { + const double v=jkqtp_todouble(*it); + if (JKQTPIsOKFloat(v)) { + sum=sum+pow(v, order); + NN++; + } + } + if (Noutput) *Noutput=NN; + if (NN<=0) return 0; + return sum/double(NN); +} + + + + +/*! \briefcalculate empirical (Pearson's) correlation coefficient between two given data ranges \a first1 ... \a last1 and \a first2 ... \a last2 + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt1 standard iterator type of \a first1 and \a last1. + \tparam InputIt2 standard iterator type of \a first2 and \a last2. + \param first1 iterator pointing to the first item in the first dataset to use \f$ X_1 \f$ + \param last1 iterator pointing behind the last item in the first dataset to use \f$ X_N \f$ + \param first2 iterator pointing to the second item in the first dataset to use \f$ Y_1 \f$ + \param[out] averageOut1 returns (optionally) the average of the first dataset \f$ X_i \f$ + \param[out] averageOut2 returns (optionally) the average of the second dataset \f$ Y_i \f$ + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return pearson's correlation coefficient + If the given range \a first1 ... \a last1 is empty, JKQTP_DOUBLE_NAN is returned + + This function implements: + \f[ \text{Kor}(x,y)=\frac{\sum\limits_{i=0}^{N-1}(x_i-\overline{x})(y_i-\overline{y})}{\sqrt{\sum\limits_{i=0}^{N-1}(x_i-\overline{x})^2\cdot\sum\limits_{i=0}^{N-1}(y_i-\overline{y})^2}} \f] + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. + + \see https://en.wikipedia.org/wiki/Pearson_correlation_coefficient +*/ +template +inline double jkqtpstatCorrelationCoefficient(InputIt1 first1, InputIt1 last1, InputIt2 first2, double* averageOut1=nullptr, double* averageOut2=nullptr, size_t* Noutput=nullptr) { + double xbar=0; + double ybar=0; + size_t NN=0; + auto it2=first2; + for (auto it=first1; it!=last1; ++it,++it2) { + const double xm=jkqtp_todouble(*it); + const double ym=jkqtp_todouble(*it2); + if (JKQTPIsOKFloat(xm) && JKQTPIsOKFloat(ym)) { + xbar=xbar+xm; + ybar=ybar+ym; + NN++; + } + } + if (Noutput) *Noutput=NN; + if (averageOut1) { + if (NN<=0) *averageOut1=JKQTP_DOUBLE_NAN; + else *averageOut1=xbar/static_cast(NN); + } + if (averageOut2) { + if (NN<=0) *averageOut2=JKQTP_DOUBLE_NAN; + else *averageOut2=ybar/static_cast(NN); + } + if (NN<=0) return JKQTP_DOUBLE_NAN; + + xbar=xbar/NN; + ybar=ybar/NN; + double sumxy=0; + double sumx=0; + double sumy=0; + it2=first2; + for (auto it=first1; it!=last1; ++it,++it2) { + const double xm=jkqtp_todouble(*it); + const double ym=jkqtp_todouble(*it2); + if (JKQTPIsOKFloat(xm) && JKQTPIsOKFloat(ym)) { + sumxy=sumxy+xm*ym; + sumx=sumx+xm*xm; + sumy=sumy+ym*ym; + } + } + return sumxy/sqrt(sumx*sumy); +} + + + + +/*! \brief calculates the median of a given sorted (!) data vector + \ingroup jkqtptools_math_statistics_basic + + \tparam TVector a type, compatible with std::vector (i,e, providing size(), []-element access and iterators) + \param data a sorted vector with values + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return the median of \a data + If \a data is empty, NAN is returned + +*/ +template +inline double jkqtpstatMedianOfSortedVector(const TVector& data, size_t* Noutput=nullptr) { + if (data.size()<=0) { + if (Noutput) *Noutput=0; + return JKQTP_DOUBLE_NAN; + } else { + if (Noutput) *Noutput=data.size(); + if (data.size()==1) return data[0]; + else if (data.size()%2==0) return (data[(data.size()-1)/2]+data[(data.size()-1)/2+1])/2.0; + else return data[(data.size()-1)/2]; + } +} + + + + + +/*! \brief calculates the Five-Number Statistical Summary (minimum, median, maximum and two user-defined quantiles (as well as derived from these the inter quartile range)) of a sorted vector + \ingroup jkqtptools_math_statistics_basic + + \tparam TVector a type, compatible with std::vector (i,e, providing size(), []-element access and iterators) + \param data a sorted vector with values + \param[out] minimum optionally returns the minimum value of the array + \param minimumQuantile specifies a quantile for the return value minimum (default is 0 for the real minimum, but you could e.g. use 0.05 for the 5% quantile! + \param[out] median optionally returns the median value of the array + \param[out] maximum optionally returns the maximum value of the array + \param maximumQuantile specifies a quantile for the return value maximum (default is 1 for the real maximum, but you could e.g. use 0.95 for the 95% quantile! + \param quantile1Spec specifies which quantile to calculate for \a qantile1 (range: 0..1) + \param[out] quantile1 optionally returns the first quantile of the array (specified by \a quantile1Spec ) + \param quantile2Spec specifies which quantile to calculate for \a qantile2 (range: 0..1) + \param[out] quantile2 optionally returns the second quantile of the array (specified by \a quantile2Spec ) + \param[out] IQR interquartile range, i.e. the range between \a quantile1 and \a quantile2 + \param[out] IQRSignificance significance range of the interquartile range, calculated as \f[ 2\cdot\frac{1.58\cdot \mbox{IQR}}{\sqrt{N}} \f] \see https://en.wikipedia.org/wiki/Box_plot + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + + \note This operation implies an internal copy of the data, as well as sorting it! + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. + + \see https://en.wikipedia.org/wiki/Five-number_summary, jkqtpstatAddVBoxplotAndOutliers, jkqtpstatAddHBoxplotAndOutliers, jkqtpstatAddVBoxplot, jkqtpstatAddHBoxplot, \ref JKQTPlottersimpletest_datastore_statistics +*/ +template +inline void jkqtpstat5NumberStatisticsOfSortedVector(const TVector& data, double* minimum=nullptr, double minimumQuantile=0, double* median=nullptr, double* maximum=nullptr, double maximumQuantile=1, double* quantile1=nullptr, double quantile1Spec=0.25, double* quantile2=nullptr, double quantile2Spec=0.75, double* IQR=nullptr, double* IQRSignificance=nullptr, size_t* Noutput=nullptr) { + if (data.size()<=0) { + if (minimum) *minimum=JKQTP_DOUBLE_NAN; + if (maximum) *maximum=JKQTP_DOUBLE_NAN; + if (median) *median=JKQTP_DOUBLE_NAN; + if (quantile1) *quantile1=JKQTP_DOUBLE_NAN; + if (quantile1) *quantile1=JKQTP_DOUBLE_NAN; + if (Noutput) *Noutput=0; + } else { + const double qmin=data[jkqtp_bounded(0, static_cast(minimumQuantile*static_cast(data.size()-1)), data.size()-1)]; + const double qmax=data[jkqtp_bounded(0, static_cast(maximumQuantile*static_cast(data.size()-1)), data.size()-1)]; + if (minimum) *minimum=qmin; + if (maximum) *maximum=qmax; + if (median) { + *median= jkqtpstatMedianOfSortedVector(data); + } + const double q1=data[jkqtp_bounded(0, static_cast(quantile1Spec*static_cast(data.size()-1)), data.size()-1)]; + const double q2=data[jkqtp_bounded(0, static_cast(quantile2Spec*static_cast(data.size()-1)), data.size()-1)]; + if (quantile1) { + *quantile1=q1; + } + if (quantile2) { + *quantile2=q2; + } + if (IQR) { + *IQR=q2-q1; + } + if (IQRSignificance) { + *IQRSignificance=2.0*(1.58*(q2-q1))/sqrt(static_cast(data.size())); + } + if (Noutput) *Noutput=data.size(); + } +} + +/*! \brief calculates the Five-Number Statistical Summary (minimum, median, maximum and two user-defined quantiles (as well as derived from these the inter quartile range)) of a sorted vector + \ingroup jkqtptools_math_statistics_basic + + \tparam TVector a type, compatible with std::vector (i,e, providing size(), []-element access and iterators) + \param data a sorted vector with values + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param outliersout output iterator that receives the outliers, smaller than minimum and larger than maximum + \param[out] minimum optionally returns the minimum value of the array + \param minimumQuantile specifies a quantile for the return value minimum (default is 0 for the real minimum, but you could e.g. use 0.05 for the 5% quantile!) + \param[out] median optionally returns the median value of the array + \param[out] maximum optionally returns the maximum value of the array + \param maximumQuantile specifies a quantile for the return value maximum (default is 1 for the real maximum, but you could e.g. use 0.95 for the 95% quantile!) + \param quantile1Spec specifies which quantile to calculate for \a qantile1 (range: 0..1) + \param[out] quantile1 optionally returns the first quantile of the array (specified by \a quantile1Spec ) + \param quantile2Spec specifies which quantile to calculate for \a qantile2 (range: 0..1) + \param[out] quantile2 optionally returns the second quantile of the array (specified by \a quantile2Spec ) + \param[out] IQR interquartile range, i.e. the range between \a quantile1 and \a quantile2 + \param[out] IQRSignificance significance range of the interquartile range, calculated as \f[ 2\cdot\frac{1.58\cdot \mbox{IQR}}{\sqrt{N}} \f] \see https://en.wikipedia.org/wiki/Box_plot + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + + \note This operation implies an internal copy of the data, as well as sorting it! + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. + + \see https://en.wikipedia.org/wiki/Five-number_summary, jkqtpstatAddVBoxplotAndOutliers, jkqtpstatAddHBoxplotAndOutliers, jkqtpstatAddVBoxplot, jkqtpstatAddHBoxplot, \ref JKQTPlottersimpletest_datastore_statistics +*/ +template +inline void jkqtpstat5NumberStatisticsAndOutliersOfSortedVector(const TVector& data, OutputIt outliersout, double* minimum=nullptr, double minimumQuantile=0, double* median=nullptr, double* maximum=nullptr, double maximumQuantile=1, double* quantile1=nullptr, double quantile1Spec=0.25, double* quantile2=nullptr, double quantile2Spec=0.75, double* IQR=nullptr, double* IQRSignificance=nullptr, size_t* Noutput=nullptr) { + if (data.size()<=0) { + if (minimum) *minimum=JKQTP_DOUBLE_NAN; + if (maximum) *maximum=JKQTP_DOUBLE_NAN; + if (median) *median=JKQTP_DOUBLE_NAN; + if (quantile1) *quantile1=JKQTP_DOUBLE_NAN; + if (quantile1) *quantile1=JKQTP_DOUBLE_NAN; + if (Noutput) *Noutput=0; + } else { + const double qmin=data[jkqtp_bounded(0, static_cast(minimumQuantile*static_cast(data.size()-1)), data.size()-1)]; + const double qmax=data[jkqtp_bounded(0, static_cast(maximumQuantile*static_cast(data.size()-1)), data.size()-1)]; + if (minimum) *minimum=qmin; + if (maximum) *maximum=qmax; + for (auto it=data.begin(); it!=data.end(); ++it) { + if (*itqmax) { + *++outliersout=*it; + } + } + if (median) { + *median= jkqtpstatMedianOfSortedVector(data); + } + const double q1=data[jkqtp_bounded(0, static_cast(quantile1Spec*static_cast(data.size()-1)), data.size()-1)]; + const double q2=data[jkqtp_bounded(0, static_cast(quantile2Spec*static_cast(data.size()-1)), data.size()-1)]; + if (quantile1) { + *quantile1=q1; + } + if (quantile2) { + *quantile2=q2; + } + if (IQR) { + *IQR=q2-q1; + } + if (IQRSignificance) { + *IQRSignificance=2.0*(1.58*(q2-q1))/sqrt(static_cast(data.size())); + } + if (Noutput) *Noutput=data.size(); + } +} + + + +/*! \brief calculates the Five-Number Statistical Summary (minimum, median, maximum and two user-defined quantiles (as well as derived from these the inter quartile range)) of a given data range \a first ... \a last (5-value statistics, e.g. used for boxplots) + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param[out] minimum optionally returns the minimum value of the array + \param minimumQuantile specifies a quantile for the return value minimum (default is 0 for the real minimum, but you could e.g. use 0.05 for the 5% quantile! + \param[out] median optionally returns the median value of the array + \param[out] maximum optionally returns the maximum value of the array + \param maximumQuantile specifies a quantile for the return value maximum (default is 1 for the real maximum, but you could e.g. use 0.95 for the 95% quantile! + \param quantile1Spec specifies which quantile to calculate for \a qantile1 (range: 0..1) + \param[out] quantile1 optionally returns the first quantile of the array (specified by \a quantile1Spec ) + \param quantile2Spec specifies which quantile to calculate for \a qantile2 (range: 0..1) + \param[out] quantile2 optionally returns the second quantile of the array (specified by \a quantile2Spec ) + \param[out] IQR interquartile range, i.e. the range between \a quantile1 and \a quantile2 + \param[out] IQRSignificance significance range of the interquartile range, calculated as \f[ 2\cdot\frac{1.58\cdot \mbox{IQR}}{\sqrt{N}} \f] \see https://en.wikipedia.org/wiki/Box_plot + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + + \note This operation implies an internal copy of the data, as well as sorting it! + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. + + \see https://en.wikipedia.org/wiki/Five-number_summary, jkqtpstatAddVBoxplotAndOutliers, jkqtpstatAddHBoxplotAndOutliers, jkqtpstatAddVBoxplot, jkqtpstatAddHBoxplot, \ref JKQTPlottersimpletest_datastore_statistics +*/ +template +inline void jkqtpstat5NumberStatistics(InputIt first, InputIt last, double* minimum=nullptr, double minimumQuantile=0, double* median=nullptr, double* maximum=nullptr, double maximumQuantile=1, double quantile1Spec=0.25, double* quantile1=nullptr, double quantile2Spec=0.75, double* quantile2=nullptr, double* IQR=nullptr, double* IQRSignificance=nullptr, size_t* Noutput=nullptr) { + std::vector dataFiltered; + jkqtpstatFilterGoodFloat(first, last, std::back_inserter(dataFiltered)); + std::sort(dataFiltered.begin(), dataFiltered.end()); + jkqtpstat5NumberStatisticsOfSortedVector(dataFiltered, minimum, minimumQuantile, median, maximum, maximumQuantile, quantile1, quantile1Spec, quantile2, quantile2Spec, IQR, IQRSignificance, Noutput); +} + +/*! \brief calculates the Five-Number Statistical Summary (minimum, median, maximum and two user-defined quantiles (as well as derived from these the inter quartile range)) of a given data range \a first ... \a last (5-value statistics, e.g. used for boxplots) + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \tparam OutputIt standard output iterator type used for the outliers output \a outliersout, use e.g. std::back_inserter + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param outliersout output iterator that receives the outliers, smaller than minimum and larger than maximum + \param[out] minimum optionally returns the minimum value of the array + \param minimumQuantile specifies a quantile for the return value minimum (default is 0 for the real minimum, but you could e.g. use 0.05 for the 5% quantile!) + \param[out] median optionally returns the median value of the array + \param[out] maximum optionally returns the maximum value of the array + \param maximumQuantile specifies a quantile for the return value maximum (default is 1 for the real maximum, but you could e.g. use 0.95 for the 95% quantile!) + \param quantile1Spec specifies which quantile to calculate for \a qantile1 (range: 0..1) + \param[out] quantile1 optionally returns the first quantile of the array (specified by \a quantile1Spec ) + \param quantile2Spec specifies which quantile to calculate for \a qantile2 (range: 0..1) + \param[out] quantile2 optionally returns the second quantile of the array (specified by \a quantile2Spec ) + \param[out] IQR interquartile range, i.e. the range between \a quantile1 and \a quantile2 + \param[out] IQRSignificance significance range of the interquartile range, calculated as \f[ 2\cdot\frac{1.58\cdot \mbox{IQR}}{\sqrt{N}} \f] \see https://en.wikipedia.org/wiki/Box_plot + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + + \note This operation implies an internal copy of the data, as well as sorting it! + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. + + \see https://en.wikipedia.org/wiki/Five-number_summary, jkqtpstatAddVBoxplotAndOutliers, jkqtpstatAddHBoxplotAndOutliers, jkqtpstatAddVBoxplot, jkqtpstatAddHBoxplot, \ref JKQTPlottersimpletest_datastore_statistics +*/ +template +inline void jkqtpstat5NumberStatisticsAndOutliers(InputIt first, InputIt last, OutputIt outliersout, double* minimum=nullptr, double minimumQuantile=0, double* median=nullptr, double* maximum=nullptr, double maximumQuantile=1, double* quantile1=nullptr, double quantile1Spec=0.25, double* quantile2=nullptr, double quantile2Spec=0.75, double* IQR=nullptr, double* IQRSignificance=nullptr, size_t* Noutput=nullptr) { + std::vector dataFiltered; + jkqtpstatFilterGoodFloat(first, last, std::back_inserter(dataFiltered)); + std::sort(dataFiltered.begin(), dataFiltered.end()); + jkqtpstat5NumberStatisticsAndOutliersOfSortedVector(dataFiltered, outliersout, minimum, minimumQuantile, median, maximum, maximumQuantile, quantile1, quantile1Spec, quantile2, quantile2Spec, IQR, IQRSignificance, Noutput); +} + +/*! \brief represents the Five-Number Statistical Summary (minimum, median, maximum and two user-defined quantiles (as well as derived from these the inter quartile range)) + \ingroup jkqtptools_math_statistics_basic + \see https://en.wikipedia.org/wiki/Five-number_summary, jkqtpstat5NumberStatistics() +*/ +struct JKQTPStat5NumberStatistics { + JKQTPStat5NumberStatistics(); + + /** \brief minimum value */ + double minimum; + /** \brief specifies a quantile for the return value minimum (default is 0 for the real minimum, but you could e.g. use 0.05 for the 5% quantile!) */ + double minimumQuantile; + /** \brief first quantile value (specified by quantile1Spec) */ + double quantile1; + /** \brief specifies the first quantile (range: 0..1) */ + double quantile1Spec; + /** \brief median value */ + double median; + /** \brief second quantile value (specified by quantile1Spec) */ + double quantile2; + /** \brief specifies the second quantile (range: 0..1) */ + double quantile2Spec; + /** \brief maximum value */ + double maximum; + /** \brief specifies a quantile for the return value maximum (default is 1 for the real maximum, but you could e.g. use 0.95 for the 95% quantile!) */ + double maximumQuantile; + /** \brief number of values used to calculate the summary */ + size_t N; + /** \brief the interquarzile range */ + double IQR() const; + /** \brief interquartile range, calculated as \f[ 2\cdot\frac{1.58\cdot \mbox{IQR}}{\sqrt{N}} \f] \see https://en.wikipedia.org/wiki/Box_plot */ + double IQRSignificanceEstimate() const; + /** \brief list with the outlier values maximum */ + std::vector outliers; +}; + +/*! \brief calculates the Five-Number Statistical Summary (minimum, median, maximum and two user-defined quantiles (as well as derived from these the inter quartile range)) of a given data range \a first ... \a last (5-value statistics, e.g. used for boxplots) + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param quantile1Spec specifies which quantile to calculate for \a qantile1 (range: 0..1) + \param quantile2Spec specifies which quantile to calculate for \a qantile2 (range: 0..1) + \param minimumQuantile specifies a quantile for the return value minimum (default is 0 for the real minimum, but you could e.g. use 0.05 for the 5% quantile!) + \param maximumQuantile specifies a quantile for the return value maximum (default is 1 for the real maximum, but you could e.g. use 0.95 for the 95% quantile!) + \return the Five-Number Statistical Summary in a JKQTPStat5NumberStatistics + + \note This operation implies an internal copy of the data, as well as sorting it! + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. + + \see https://en.wikipedia.org/wiki/Five-number_summary, jkqtpstatAddVBoxplotAndOutliers, jkqtpstatAddHBoxplotAndOutliers, jkqtpstatAddVBoxplot, jkqtpstatAddHBoxplot, \ref JKQTPlottersimpletest_datastore_statistics +*/ +template +inline JKQTPStat5NumberStatistics jkqtpstat5NumberStatistics(InputIt first, InputIt last, double quantile1Spec=0.25, double quantile2Spec=0.75, double minimumQuantile=0, double maximumQuantile=1.0) { + JKQTPStat5NumberStatistics res; + jkqtpstat5NumberStatisticsAndOutliers(first, last, std::back_inserter(res.outliers), &(res.minimum), minimumQuantile, &(res.median), &(res.maximum), maximumQuantile, &(res.quantile1), quantile1Spec,&(res.quantile2),quantile2Spec, nullptr,nullptr,&(res.N)); + return res; +} + + +/*! \brief calculates the median of a given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return the median of the data returned between \a first and \a last (excluding invalid doubles). + If the given range \a first ... \a last is empty, NAN is returned + + \note This operation implies an internal copy of the data, as well as sorting it! + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline double jkqtpstatMedian(InputIt first, InputIt last, size_t* Noutput=nullptr) { + std::vector dataFiltered; + jkqtpstatFilterGoodFloat(first, last, std::back_inserter(dataFiltered)); + std::sort(dataFiltered.begin(), dataFiltered.end()); + return jkqtpstatMedianOfSortedVector(dataFiltered, Noutput); +} + + +/*! \brief calculates the \a quantile -th quantile of a given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param quantile the given quantile, range 0..1 (e.g. 0.25 for the 25% quartile ...) + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return the \a quantile -th quantile of the data returned between \a first and \a last (excluding invalid doubles). + If the given range \a first ... \a last is empty, NAN is returned + + \note This operation implies an internal copy of the data, as well as sorting it! + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. +*/ +template +inline double jkqtpstatQuantile(InputIt first, InputIt last, double quantile, size_t* Noutput=nullptr) { + std::vector dataFiltered; + jkqtpstatFilterGoodFloat(first, last, std::back_inserter(dataFiltered)); + std::sort(dataFiltered.begin(), dataFiltered.end()); + if (dataFiltered.size()<=0) { + if (Noutput) *Noutput=0; + return JKQTP_DOUBLE_NAN; + } else { + if (Noutput) *Noutput=dataFiltered.size(); + return dataFiltered[jkqtp_bounded(0, static_cast(quantile*static_cast(dataFiltered.size()-1)), dataFiltered.size()-1)]; + } +} + + + +/*! \brief calculates the median absolute deviation about the median (MAD) of a given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param[out] median optionally returns the median value in this variable + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return the median absolute deviation about the median (MAD) of the data returned between \a first and \a last (excluding invalid doubles). + If the given range \a first ... \a last is empty, NAN is returned + + This function calculates + \f[ \mbox{MAD}(\vec{x})=\mbox{Med}\left\{|\vec{x}-\mbox{Med}(\vec{x})|\right\} \f] + + + \note This operation implies an internal copy of the data, as well as sorting it! + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. + + \see https://en.wikipedia.org/wiki/Median_absolute_deviation and Ricardo A. Maronna, R. Douglas Martin, Victor J. Yohai: "Robust Statistics: Theory and Methods", Wiley, 2006, ISBN: 978-0-470-01092-1 +*/ +template +inline double jkqtpstatMAD(InputIt first, InputIt last, double* median=nullptr, size_t* Noutput=nullptr) { + std::vector dataFiltered; + jkqtpstatFilterGoodFloat(first, last, std::back_inserter(dataFiltered)); + std::sort(dataFiltered.begin(), dataFiltered.end()); + if (dataFiltered.size()<=0) { + if (Noutput) *Noutput=0; + if (median) *median=JKQTP_DOUBLE_NAN; + return JKQTP_DOUBLE_NAN; + } else { + if (Noutput) *Noutput=dataFiltered.size(); + double med=jkqtpstatMedianOfSortedVector(dataFiltered); + if (median) *median=med; + for(double& v: dataFiltered) { + v=fabs(v-med); + } + std::sort(dataFiltered.begin(), dataFiltered.end()); + return jkqtpstatMedianOfSortedVector(dataFiltered); + } +} + + + +/*! \brief calculates the normalized median absolute deviation about the median (NMAD) of a given data range \a first ... \a last + \ingroup jkqtptools_math_statistics_basic + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param[out] median optionally returns the median value in this variable + \param[out] Noutput optionally returns the number of accumulated valid values in this variable + \return the normalized median absolute deviation about the median (NMAD) of the data returned between \a first and \a last (excluding invalid doubles). + If the given range \a first ... \a last is empty, NAN is returned + + This function calculates + \f[ \mbox{NMAD}(\vec{x})=\frac{\mbox{MAD}(\vec{x})}{0.6745}=\frac{\mbox{Med}\left\{|\vec{x}-\mbox{Med}(\vec{x})|\right\}}{0.6745} \f] + + + \note This operation implies an internal copy of the data, as well as sorting it! + + \note Each value is the specified range is converted to a double using jkqtp_todouble(). + Entries in the range that are invalid double (using JKQTPIsOKFloat() ) + are ignored when calculating. + + \see https://en.wikipedia.org/wiki/Median_absolute_deviation and Ricardo A. Maronna, R. Douglas Martin, Victor J. Yohai: "Robust Statistics: Theory and Methods", Wiley, 2006, ISBN: 978-0-470-01092-1 +*/ +template +inline double jkqtpstatNMAD(InputIt first, InputIt last, double* median=nullptr, size_t* Noutput=nullptr) { + return jkqtpstatMAD(first, last, median, Noutput)/0.6745; +} + + + + +/*! \brief defines where the returned x-coordinates (in histogramXOut) lie inside a histogram bin + \ingroup jkqtptools_math_statistics_1dhist + \see jkqtpstatHistogram() +*/ +enum class JKQTPStatHistogramBinXMode { + XIsLeft, /*!< \brief x-location is the left edge of the bin */ + XIsMid, /*!< \brief x-location is the middle of the bin */ + XIsRight /*!< \brief x-location is the right edge of the bin */ +}; + +/*! \brief calculate an autoranged 1-dimensional histogram from the given data range \a first ... \a last, bins defined by their number + \ingroup jkqtptools_math_statistics_1dhist + + \tparam InputIt standard iterator type of \a first and \a last. + \tparam OutputIt standard output iterator type used for the outliers output \a histogramXOut and \a histogramYOut, use e.g. std::back_inserter + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param[out] histogramXOut output iterator that receives x-positions of the histogram bins. Location of this value inside the bin range is defined by \a binXMode + \param[out] histogramYOut output iterator that receives counts/frequencies of the histogram bins + \param bins number of bins in the output histogram + \param normalized indicates whether the histogram has to be normalized + \param cummulative if \c true, a cummulative histogram is calculated + \param binXMode defines where the returned x-coordinates (in histogramXOut) lie inside the histogram bin (see JKQTPStatHistogramBinXMode) + + \see jkqtpstatAddHHistogram1DAutoranged() +*/ +template +inline void jkqtpstatHistogram1DAutoranged(InputIt first, InputIt last, OutputIt histogramXOut, OutputIt histogramYOut, int bins=11, bool normalized=true, bool cummulative=false, JKQTPStatHistogramBinXMode binXMode=JKQTPStatHistogramBinXMode::XIsLeft) { + double minV=0, maxV=0; + size_t N=0; + jkqtpstatMinMax(first, last, minV, maxV, nullptr, nullptr, &N); + + std::vector histX; + std::vector histY; + + const double range=maxV-minV; + const double binw=range/static_cast(bins); + + // initialize the histogram + for (int i=0; i(i)*binw); + histY.push_back(0); + } + + // calculate the histogram + for (auto it=first; it!=last; ++it) { + const double v=jkqtp_todouble(*it); + if (JKQTPIsOKFloat(v)) { + size_t b=jkqtp_bounded(0, static_cast(floor((v-minV)/binw)), bins-1); + histY[b]++; + } + } + + + // output the histogram + double xoffset=0; + if (binXMode==JKQTPStatHistogramBinXMode::XIsRight) xoffset=binw; + if (binXMode==JKQTPStatHistogramBinXMode::XIsMid) xoffset=binw/2.0; + + double NNorm=1; + if (normalized) { + NNorm=static_cast(N); + } + double h=0; + for (size_t i=0; i +inline void jkqtpstatHistogram1DAutoranged(InputIt first, InputIt last, OutputIt histogramXOut, OutputIt histogramYOut, double binWidth, bool normalized=true, bool cummulative=false, JKQTPStatHistogramBinXMode binXMode=JKQTPStatHistogramBinXMode::XIsLeft) { + double minV=0, maxV=0; + size_t N=0; + jkqtpstatMinMax(first, last, minV, maxV, nullptr, nullptr, &N); + + std::vector histX; + std::vector histY; + + const double range=maxV-minV; + const double binw=binWidth; + const int bins=static_cast(ceil(range/binWidth)); + + // initialize the histogram + for (int i=0; i(i)*binw); + histY.push_back(0); + } + + // calculate the histogram + for (auto it=first; it!=last; ++it) { + const double v=jkqtp_todouble(*it); + if (JKQTPIsOKFloat(v)) { + size_t b=jkqtp_bounded(0, static_cast(floor((v-minV)/binw)), bins-1); + histY[b]++; + } + } + + + // output the histogram + double xoffset=0; + if (binXMode==JKQTPStatHistogramBinXMode::XIsRight) xoffset=binw; + if (binXMode==JKQTPStatHistogramBinXMode::XIsMid) xoffset=binw/2.0; + + double NNorm=1; + if (normalized) { + NNorm=static_cast(N); + } + double h=0; + for (size_t i=0; i +inline void jkqtpstatHistogram1D(InputIt first, InputIt last, BinsInputIt binsFirst, BinsInputIt binsLast, OutputIt histogramXOut, OutputIt histogramYOut, bool normalized=true, bool cummulative=false, JKQTPStatHistogramBinXMode binXMode=JKQTPStatHistogramBinXMode::XIsLeft) { + double minV=0, maxV=0; + size_t N=0; + jkqtpstatMinMax(first, last, minV, maxV, nullptr, nullptr, &N); + + std::vector histX; + std::vector histY; + + + // initialize the histogram + for (auto it=binsFirst; it!=binsLast; ++it) { + histX.push_back(jkqtp_todouble(*it)); + histY.push_back(0); + } + std::sort(histX.begin(), histX.end()); + + // calculate the histogram + for (auto it=first; it!=last; ++it) { + const double v=jkqtp_todouble(*it); + if (JKQTPIsOKFloat(v)) { + auto itb=std::lower_bound(histX.begin(), histX.end(), v); + size_t bin=jkqtp_bounded(0,static_cast(abs(std::distance(histX.begin(), itb))), histY.size()-1); + histY[bin]++; + } + } + + + // output the histogram + double NNorm=1; + if (normalized) { + NNorm=static_cast(N); + } + double h=0; + for (size_t i=0; i(i)-1>0) binw=histX[histX.size()-1]-histX[histX.size()-2]; + else if (i-1.23\\cdot 10^{-5}) + * \ingroup jkqtptools_string + */ +JKQTP_LIB_EXPORT QString jkqtp_floattolatexqstr(double data, int past_comma=5, bool remove_trail0=false, double belowIsZero=1e-16, double minNoExponent=1e-3, double maxNoExponent=1e4); +/** \brief convert a double to a string, encoding powers of ten as exponent with HTML tags + * \ingroup jkqtptools_string + */ +JKQTP_LIB_EXPORT QString jkqtp_floattohtmlqstr(double data, int past_comma=5, bool remove_trail0=false, double belowIsZero=1e-16, double minNoExponent=1e-3, double maxNoExponent=1e4); + /** \brief convert a character to a string * \ingroup jkqtptools_string */ diff --git a/lib/jkqtcommon/jkqtptoolsdebugging.h b/lib/jkqtcommon/jkqtptoolsdebugging.h index a424358695..17467159d1 100644 --- a/lib/jkqtcommon/jkqtptoolsdebugging.h +++ b/lib/jkqtcommon/jkqtptoolsdebugging.h @@ -66,6 +66,100 @@ class JKQTP_LIB_EXPORT JKQTPAutoOutputTimer : public QElapsedTimer }; +/** \brief dynamic assertion, throws a \c std::runtime_error exception if \a condition is \c false + * \ingroup jkqtptools_debugging + * + * \param condition the condition to check + * \param message a user-provided error message + * \param expression the expression (as a string) that was used to calculate \a condition + * \param file filename where the exception occured + * \param line line in file \a file where the exception occured + * + * \see JKQTPASSERT_M(), JKQTPASSERT() for macros that use this function and automatically stringify the expression and add file and line + */ +inline void jkqtp_assert(bool condition, const std::string& message, const std::string expression, const std::string& file, int line) +{ + if (!condition) { + throw std::runtime_error(message+" (expression: "+expression+", file: "+file+":"+std::to_string(line)+")"); + } +} +/** \brief dynamic assertion, throws a \c std::runtime_error exception if \a condition is \c false + * \ingroup jkqtptools_debugging + * + * \param condition the condition to check + * \param message a user-provided error message + * \param expression the expression (as a string) that was used to calculate \a condition + * \param file filename where the exception occured + * \param line line in file \a file where the exception occured + * \param function calling function + * + * \see JKQTPASSERT_M(), JKQTPASSERT() for macros that use this function and automatically stringify the expression and add file and line + */ +inline void jkqtp_assert(bool condition, const std::string& message, const std::string expression, const std::string& file, int line, const std::string& function) +{ + if (!condition) { + throw std::runtime_error(message+" (expression: "+expression+", function: "+function+", file: "+file+":"+std::to_string(line)+")"); + } +} + +/** \brief dynamic assertion, throws a \c std::runtime_error exception if \a condition is \c false + * \ingroup jkqtptools_debugging + * + * \param condition the condition to check + * \param expression the expression (as a string) that was used to calculate \a condition + * \param file filename where the exception occured + * \param line line in file \a file where the exception occured + * \param function calling function + * + * \see JKQTPASSERT_M(), JKQTPASSERT() for macros that use this function and automatically stringify the expression and add file and line + */ +inline void jkqtp_assert(bool condition, const std::string expression, const std::string& file, int line, const std::string& function) +{ + if (!condition) { + throw std::runtime_error("assertion failed (expression: "+expression+", function: "+function+", file: "+file+":"+std::to_string(line)+")"); + } +} + +/** \brief dynamic assertion, throws a \c std::runtime_error exception if \a condition is \c false + * \ingroup jkqtptools_debugging + * + * \param condition the condition to check + * \param expression the expression (as a string) that was used to calculate \a condition + * \param file filename where the exception occured + * \param line line in file \a file where the exception occured + * + * \see JKQTPASSERT_M(), JKQTPASSERT() for macros that use this function and automatically stringify the expression and add file and line + */ +inline void jkqtp_assert(bool condition, const std::string expression, const std::string& file, int line) +{ + if (!condition) { + throw std::runtime_error("assertion failed (expression: "+expression+", file: "+file+":"+std::to_string(line)+")"); + } +} + +/** \brief dynamic assertion, throws a \c std::runtime_error exception if \a condition is \c false + * \ingroup jkqtptools_debugging + * + * \param condition the condition to check + * \param message a user-provided error message + * + * \see JKQTPASSERT_M(), JKQTPASSERT() + */ +inline void jkqtp_assert(bool condition, const std::string& message) +{ + if (!condition) { + throw std::runtime_error(message); + } +} + +/** \brief dynamic assertion, throws an exception with the given \a message, when the given condition \a condition evaluates to \c false + * \ingroup jkqtptools_debugging + */ +#define JKQTPASSERT_M(condition, message) jkqtp_assert(condition, message, #condition, __FILE__, __LINE__, __FUNCTION__) +/** \brief dynamic assertion, throws an exception with the given \a message, when the given condition \a condition evaluates to \c false + * \ingroup jkqtptools_debugging + */ +#define JKQTPASSERT(condition) jkqtp_assert(condition, #condition, __FILE__, __LINE__, __FUNCTION__) #endif // JKQTPDEBUGGINGTOOLS_H_INCLUDED diff --git a/lib/jkqtplottertools/jkqttools.cpp b/lib/jkqtcommon/jkqttools.cpp similarity index 100% rename from lib/jkqtplottertools/jkqttools.cpp rename to lib/jkqtcommon/jkqttools.cpp diff --git a/lib/jkqtplottertools/jkqttools.h b/lib/jkqtcommon/jkqttools.h similarity index 100% rename from lib/jkqtplottertools/jkqttools.h rename to lib/jkqtcommon/jkqttools.h diff --git a/lib/jkqtfastplotter.pri b/lib/jkqtfastplotter.pri index 456e428707..825a63d31a 100644 --- a/lib/jkqtfastplotter.pri +++ b/lib/jkqtfastplotter.pri @@ -1,17 +1,18 @@ -# uncomment this line to prevent linking in of the XITS fonts -#DEFINES += NO_XITS_FONTS -include($$PWD/common.pri) +isEmpty(JKQTP_FASTPLOTTER_PRI_INCLUDED) { + JKQTP_FASTPLOTTER_PRI_INCLUDED = 1 + + INCLUDEPATH += $PWD -HEADERS += $$PWD/jkqtfastplotter/jkqtfastplotter.h \ - $$PWD/jkqtplottertools/jkqtphighrestimer.h + HEADERS += $$PWD/jkqtfastplotter/jkqtfastplotter.h -SOURCES += $$PWD/jkqtfastplotter/jkqtfastplotter.cpp \ - $$PWD/jkqtplottertools/jkqtphighrestimer.cpp + SOURCES += $$PWD/jkqtfastplotter/jkqtfastplotter.cpp -RESOURCES += $$PWD/jkqtplotterressources/jkqtpbaseplotter.qrc + RESOURCES += $$PWD/jkqtplotterressources/jkqtpbaseplotter.qrc -QT += opengl + QT += opengl + +} diff --git a/lib/jkqtfastplotter/jkqtfastplotter.cpp b/lib/jkqtfastplotter/jkqtfastplotter.cpp index 970e076dda..7abc3bf0e4 100644 --- a/lib/jkqtfastplotter/jkqtfastplotter.cpp +++ b/lib/jkqtfastplotter/jkqtfastplotter.cpp @@ -20,7 +20,7 @@ #include "jkqtfastplotter.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtcommon/jkqtpcodestructuring.h" #include #include #include @@ -47,7 +47,7 @@ var=(settings).value((group)+(varname), var).varconvert; const double JKQTFastPlotter::ABS_MIN_LINEWIDTH=0.05; -const int JKQTFastPlotter::LUTSIZE=256; +const size_t JKQTFastPlotter::LUTSIZE=256; JKQTFPPlot::JKQTFPPlot(JKQTFastPlotter* parent): QObject(parent) @@ -1119,7 +1119,7 @@ void JKQTFPXRangePlot::drawGraph(QPainter& painter) { painter.setPen(p); painter.fillRect(r, b); if (showCenterline) { - painter.drawLine(parent->x2p(centerline), parent->getInternalPlotBorderTop(), parent->x2p(centerline), parent->getInternalPlotBorderTop()+parent->getPlotHeight()); + painter.drawLine(QLineF(parent->x2p(centerline), parent->getInternalPlotBorderTop(), parent->x2p(centerline), parent->getInternalPlotBorderTop()+parent->getPlotHeight())); } painter.drawRect(r); } @@ -1276,7 +1276,7 @@ void JKQTFPimagePlot::drawGraph(QPainter& painter) { painter.drawImage(QRectF(pxmin, pymax, dx, dy), img.transformed(trans)); if (drawColorBar && parent->getPlotHeight()>3) { uint8_t d[200]; - for (int i=0; i<200; i++) d[i]=i; + for (uint8_t i=0; i<200; i++) d[i]=i; QImage b(1, 200, QImage::Format_ARGB32); JKQTFPimagePlot_array2image(d, 1, 200, b, palette, 0, 199); //std::cout<<"bar.width="<getInternalPlotBorderLeft(), parent->getInternalPlotBorderTop()), QPointF(parent->getInternalPlotBorderLeft()+parent->getPlotWidth(), parent->getInternalPlotBorderTop()+parent->getPlotHeight())); double borderfraction=0.1; - int yDistance=static_cast(parent->getPlotHeight())*borderfraction; + int yDistance=static_cast(static_cast(parent->getPlotHeight())*borderfraction); QPen p(color); p.setWidthF(qMax(JKQTFastPlotter::ABS_MIN_LINEWIDTH, lineWidth)); @@ -1447,7 +1447,7 @@ void JKQTFPQScaleBarXPlot::drawGraph(QPainter& painter) { painter.drawLine(QLineF(xx1, yy1, xx2, yy2)); painter.setFont(font); QFontMetrics fm=painter.fontMetrics(); - painter.drawText(xx1+(xx2-xx1)/2-fm.width(s)/2, yy1+3*lineWidth+fm.ascent(), s); + painter.drawText(static_cast(xx1+(xx2-xx1)/2-fm.width(s)/2), static_cast(yy1+3*lineWidth+fm.ascent()), s); } else if (position==JKQTFPQScaleBarXPlot::TopLeft) { yy1=parent->getInternalPlotBorderTop()+yDistance; yy2=yy1; @@ -1458,7 +1458,7 @@ void JKQTFPQScaleBarXPlot::drawGraph(QPainter& painter) { painter.drawLine(QLineF(xx1, yy1, xx2, yy2)); painter.setFont(font); QFontMetrics fm=painter.fontMetrics(); - painter.drawText(xx1+(xx2-xx1)/2-fm.width(s)/2, yy1+3*lineWidth+fm.ascent(), s); + painter.drawText(static_cast(xx1+(xx2-xx1)/2-fm.width(s)/2), static_cast(yy1+3*lineWidth+fm.ascent()), s); } else if (position==JKQTFPQScaleBarXPlot::BottomLeft) { yy1=parent->getInternalPlotBorderTop()+parent->getPlotHeight()-yDistance; yy2=yy1; @@ -1469,7 +1469,7 @@ void JKQTFPQScaleBarXPlot::drawGraph(QPainter& painter) { painter.drawLine(QLineF(xx1, yy1, xx2, yy2)); painter.setFont(font); QFontMetrics fm=painter.fontMetrics(); - painter.drawText(xx1+(xx2-xx1)/2-fm.width(s)/2, yy1-3*lineWidth-fm.descent(), s); + painter.drawText(static_cast(xx1+(xx2-xx1)/2-fm.width(s)/2), static_cast(yy1-3*lineWidth-fm.descent()), s); } else if (position==JKQTFPQScaleBarXPlot::BottomRight) { yy1=parent->getInternalPlotBorderTop()+parent->getPlotHeight()-yDistance; yy2=yy1; @@ -1480,7 +1480,7 @@ void JKQTFPQScaleBarXPlot::drawGraph(QPainter& painter) { painter.drawLine(QLineF(xx1, yy1, xx2, yy2)); painter.setFont(font); QFontMetrics fm=painter.fontMetrics(); - painter.drawText(xx1+(xx2-xx1)/2-fm.width(s)/2, yy1-3*lineWidth-fm.descent(), s); + painter.drawText(static_cast(xx1+(xx2-xx1)/2-fm.width(s)/2), static_cast(yy1-3*lineWidth-fm.descent()), s); } diff --git a/lib/jkqtfastplotter/jkqtfastplotter.h b/lib/jkqtfastplotter/jkqtfastplotter.h index 49bfef791c..e9d66a9d93 100644 --- a/lib/jkqtfastplotter/jkqtfastplotter.h +++ b/lib/jkqtfastplotter/jkqtfastplotter.h @@ -42,9 +42,8 @@ #include #include -#include "jkqtcommon/jkqtptools.h" #ifdef DEBUG_TIMING -# include "jkqtplottertools/jkqtphighrestimer.h" +# include "jkqtcommon/jkqtphighrestimer.h" #endif @@ -100,7 +99,7 @@ class JKQTP_LIB_EXPORT JKQTFastPlotter : public QGLWidget { /*! \brief size of the lookup tables used by JKQTFPimagePlot_array2image() */ - static const int LUTSIZE; + static const size_t LUTSIZE; protected: /** \brief indicates whether to do full repaint (system and data) at the next repaint (any of the repaint meothods) */ @@ -1907,7 +1906,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i if ((*plut)==nullptr) { (*plut)=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); if ((*plut)!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=l/static_cast(JKQTFastPlotter::LUTSIZE); (*plut)[l]=qRgb(static_cast(255.0*v), 0, 0); } @@ -1922,7 +1921,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i if ((*plut)==nullptr) { (*plut)=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); if ((*plut)!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=l/static_cast(JKQTFastPlotter::LUTSIZE); (*plut)[l]=qRgb(0, static_cast(255.0*v), 0); } @@ -1937,7 +1936,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i if ((*plut)==nullptr) { (*plut)=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); if ((*plut)!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=l/static_cast(JKQTFastPlotter::LUTSIZE); (*plut)[l]=qRgb(0, 0, static_cast(255.0*v)); } @@ -1954,7 +1953,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i if ((*plut)==nullptr) { (*plut)=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); if ((*plut)!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=l/static_cast(JKQTFastPlotter::LUTSIZE); (*plut)[l]=qRgb(static_cast(255.0*v), static_cast(255.0*v), @@ -1971,7 +1970,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i if ((*plut)==nullptr) { (*plut)=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); if ((*plut)!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=l/static_cast(JKQTFastPlotter::LUTSIZE); (*plut)[l]=qRgb(static_cast(255.0*(1.0-v)), 0, 0); } @@ -1986,7 +1985,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i if ((*plut)==nullptr) { (*plut)=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); if ((*plut)!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=l/static_cast(JKQTFastPlotter::LUTSIZE); (*plut)[l]=qRgb(0, static_cast(255.0*(1.0-v)), 0); } @@ -2000,7 +1999,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i if ((*plut)==nullptr) { (*plut)=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); if ((*plut)!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=l/static_cast(JKQTFastPlotter::LUTSIZE); (*plut)[l]=qRgb(0, 0, static_cast(255.0*(1.0-v))); } @@ -2014,7 +2013,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i if ((*plut)==nullptr) { (*plut)=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); if ((*plut)!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=1.0-(l/static_cast(JKQTFastPlotter::LUTSIZE)); (*plut)[l]=qRgb(static_cast(255.0*v), static_cast(255.0*v), @@ -2031,7 +2030,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i if ((*plut)==nullptr) { (*plut)=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); if ((*plut)!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=l/static_cast(JKQTFastPlotter::LUTSIZE); double r = 382.5 - 1020.0 * std::abs(v - 0.75); if (r > 255.0) @@ -2064,7 +2063,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i if ((*plut)==nullptr) { (*plut)=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); if ((*plut)!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=l/static_cast(JKQTFastPlotter::LUTSIZE); double r = 796.875*v - 199.21875; if (r > 255.0) @@ -2090,7 +2089,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i if ((*plut)==nullptr) { (*plut)=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); if ((*plut)!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=l/static_cast(JKQTFastPlotter::LUTSIZE); int h = static_cast(floor(6*v)); double f = 6*v-double(h); @@ -2116,7 +2115,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i if ((*plut)==nullptr) { (*plut)=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); if ((*plut)!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=l/static_cast(JKQTFastPlotter::LUTSIZE); int h = static_cast(floor(6.0-6.0*v)); double f = 6.0-6.0*v-double(h); @@ -2143,7 +2142,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i lut_rainbow=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); //std::cout<<"!!! creating rainbow lut\n"; if (lut_rainbow!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=l/static_cast(JKQTFastPlotter::LUTSIZE); double r = 255.0*std::abs(2.0*v-0.5); if (r > 255.0) @@ -2165,7 +2164,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i if ((*plut)==nullptr) { (*plut)=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); if ((*plut)!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=l/static_cast(JKQTFastPlotter::LUTSIZE); double r = 765.0*v; if (r > 255.0) @@ -2192,7 +2191,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i if ((*plut)==nullptr) { (*plut)=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); if ((*plut)!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=l/static_cast(JKQTFastPlotter::LUTSIZE); double r = 765.0*v-510.0; if (r < 0.0) @@ -2213,7 +2212,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i if ((*plut)==nullptr) { (*plut)=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); if ((*plut)!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=l/static_cast(JKQTFastPlotter::LUTSIZE); double r = (v/0.32-0.78125); if (r < 0.0) r = 0.0; @@ -2242,7 +2241,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i if ((*plut)==nullptr) { (*plut)=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); if ((*plut)!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=l/static_cast(JKQTFastPlotter::LUTSIZE); double r = sqrt(sqrt(v)); if (r < 0.0) r = 0.0; @@ -2269,7 +2268,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i if ((*plut)==nullptr) { (*plut)=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); if ((*plut)!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=l/static_cast(JKQTFastPlotter::LUTSIZE); double r = v*0.5; if (r < 0.0) r = 0.0; @@ -2295,7 +2294,7 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i if ((*plut)==nullptr) { (*plut)=static_cast(malloc((JKQTFastPlotter::LUTSIZE+2)*sizeof(QRgb))); if ((*plut)!=nullptr) { - for (int l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { + for (size_t l=0; l<=JKQTFastPlotter::LUTSIZE; l++) { double v=l/static_cast(JKQTFastPlotter::LUTSIZE); double r = (v < 0.5) ? 128.0*sin(M_PI*(2.0*v-0.5))+128.0 : 255.0; if (r > 255.0) @@ -2323,8 +2322,8 @@ inline void JKQTFPimagePlot_array2image(T* dbl, int width, int height, QImage &i for (int j=0; j(img.scanLine(height-1-j)); for (int i=0; i JKQTFastPlotter::LUTSIZE) ? JKQTFastPlotter::LUTSIZE : v); + int v = static_cast((dbl[j*width+i]-min)/delta*static_cast(JKQTFastPlotter::LUTSIZE)); + v = (v < 0) ? 0 : ( (v > static_cast(JKQTFastPlotter::LUTSIZE)) ? static_cast(JKQTFastPlotter::LUTSIZE) : v); line[i]=lut_used[v]; } } @@ -2574,22 +2573,22 @@ class JKQTP_LIB_EXPORT JKQTFPimagePlot: public JKQTFPPlot { public slots: void setRotation(int rotation) { if (this->rotation!=rotation) { - this->rotation=(JKQTFPColorPalette)rotation; + this->rotation=rotation; replot(); } } void setPalette(int palette) { if (this->palette!=palette) { - this->palette=(JKQTFPColorPalette)palette; + this->palette=static_cast(palette); replot(); } - }; + } void setPalette(JKQTFPColorPalette palette) { if (this->palette!=palette) { this->palette=palette; replot(); } - }; + } void setColorMin(uint32_t colorMin) { if (this->colorMin!=colorMin) { this-> colorMin= colorMin; @@ -2633,17 +2632,19 @@ class JKQTP_LIB_EXPORT JKQTFPimagePlot: public JKQTFPPlot { - /*! \brief convert a 2D image (as 1D array) into a QImage and puts the image values into one color channel (set by \a channel). \ingroup jkqtfastplotter */ template -inline void JKQTFPRGBImageOverlayPlot_array2image(T* dbl, int width, int height, QImage &img, int channel, T minColor, T maxColor) +inline void JKQTFPRGBImageOverlayPlot_array2image(T* dbl, int width, int height, QImage &img, int channel, double minColor_, double maxColor_) { if (!dbl) return; + T minColor=static_cast(minColor_); + T maxColor=static_cast(maxColor_); + #ifdef DEBUG_TIMING JKQTPHighResTimer timer; double time_sum=0; @@ -2973,7 +2974,7 @@ class JKQTP_LIB_EXPORT JKQTFPRGBImageOverlayPlot: public JKQTFPPlot { public slots: inline void setRotation(int rotation) { if (this->rotation!=rotation) { - this->rotation=(JKQTFPColorPalette)rotation; + this->rotation=rotation; replot(); } } @@ -3234,7 +3235,7 @@ class JKQTP_LIB_EXPORT JKQTFPimageOverlayPlot: public JKQTFPPlot { public slots: inline void setRotation(int rotation) { if (this->rotation!=rotation) { - this->rotation=(JKQTFPColorPalette)rotation; + this->rotation=rotation; replot(); } } @@ -3243,7 +3244,7 @@ class JKQTP_LIB_EXPORT JKQTFPimageOverlayPlot: public JKQTFPPlot { this->color=color; replot(); } - }; + } }; @@ -3365,7 +3366,7 @@ class JKQTP_LIB_EXPORT JKQTFPQScaleBarXPlot: public JKQTFPPlot { } public slots: void setPosition(int pos) { - setPosition((Position)pos); + setPosition(static_cast(pos)); } }; diff --git a/lib/jkqtmathtext.pri b/lib/jkqtmathtext.pri index cb2c082909..e1abe4ecfc 100644 --- a/lib/jkqtmathtext.pri +++ b/lib/jkqtmathtext.pri @@ -1,15 +1,17 @@ -# uncomment this line to prevent linking in of the XITS fonts -#DEFINES += NO_XITS_FONTS -include($$PWD/common.pri) +isEmpty(JKQTP_MATHTEXT_PRI_INCLUDED) { + JKQTP_MATHTEXT_PRI_INCLUDED = 1 -HEADERS += $$PWD/jkqtmathtext/jkqtmathtext.h + INCLUDEPATH += $PWD -SOURCES += $$PWD/jkqtmathtext/jkqtmathtext.cpp + HEADERS += $$PWD/jkqtmathtext/jkqtmathtext.h + SOURCES += $$PWD/jkqtmathtext/jkqtmathtext.cpp -include($$PWD/jkqtplotterressources/math_fonts/xits.pri) -DEFINES += AUTOLOAD_XITS_FONTS + include($$PWD/jkqtplotterressources/math_fonts/xits.pri) + DEFINES += AUTOLOAD_XITS_FONTS + DEFINES += USE_XITS_FONTS -#win32:LIBS += -lgdi32 + #win32:LIBS += -lgdi32 +} diff --git a/lib/jkqtmathtext/jkqtmathtext.cpp b/lib/jkqtmathtext/jkqtmathtext.cpp index 01d24111cb..32d83dee35 100644 --- a/lib/jkqtmathtext/jkqtmathtext.cpp +++ b/lib/jkqtmathtext/jkqtmathtext.cpp @@ -20,7 +20,9 @@ #include "jkqtmathtext/jkqtmathtext.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtcommon/jkqtpcodestructuring.h" +#include "jkqtcommon/jkqtpstringtools.h" +#include #include #include #include diff --git a/lib/jkqtmathtext/jkqtmathtext.h b/lib/jkqtmathtext/jkqtmathtext.h index d7d518aa9b..00de86ed29 100644 --- a/lib/jkqtmathtext/jkqtmathtext.h +++ b/lib/jkqtmathtext/jkqtmathtext.h @@ -36,7 +36,6 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" #include "jkqtcommon/jkqtp_imexport.h" #include #include diff --git a/lib/jkqtpcommon.pri b/lib/jkqtpcommon.pri new file mode 100644 index 0000000000..af9236e06c --- /dev/null +++ b/lib/jkqtpcommon.pri @@ -0,0 +1,56 @@ +# include guard against multiple inclusion +isEmpty(JKQTP_COMMON_PRI_INCLUDED) { + JKQTP_COMMON_PRI_INCLUDED = 1 + + !win32-msvc* { + QMAKE_CXXFLAGS += -fexceptions + } else { + QMAKE_CXXFLAGS += /EHsc + # /std:c++14 + # To enable M_PI, M_E,... + DEFINES += _USE_MATH_DEFINES + # To fix error: C2338: va_start argument must not + # have reference type and must not be parenthesized + DEFINES += _CRT_NO_VA_START_VALIDATION + } + + HEADERS += $$PWD/jkqtcommon/jkqtp_imexport.h \ + $$PWD/jkqtcommon/jkqtptoolsdebugging.h \ + $$PWD/jkqtcommon/jkqtpmathtools.h \ + $$PWD/jkqtcommon/jkqtpalgorithms.h \ + $$PWD/jkqtcommon/jkqtpstringtools.h \ + $$PWD/jkqtcommon/jkqtplinalgtools.h \ + $$PWD/jkqtcommon/jkqtpcodestructuring.h \ + $$PWD/jkqtcommon/jkqtpbasicimagetools.h \ + $$PWD/jkqtcommon/jkqtpdrawingtools.h \ + $$PWD/jkqtcommon/jkqtpenhancedpainter.h \ + $$PWD/jkqtcommon/jkqtphighrestimer.h \ + $$PWD/jkqtcommon/jkqtpmathparser.h \ + $$PWD/jkqtcommon/jkqttools.h \ + $$PWD/jkqtcommon/jkqtparraytools.h \ + $$PWD/jkqtcommon/jkqtpstatisticstools.h + + + SOURCES += $$PWD/jkqtcommon/jkqtptoolsdebugging.cpp \ + $$PWD/jkqtcommon/jkqtpmathtools.cpp \ + $$PWD/jkqtcommon/jkqtpalgorithms.cpp \ + $$PWD/jkqtcommon/jkqtpstringtools.cpp \ + $$PWD/jkqtcommon/jkqtplinalgtools.cpp \ + $$PWD/jkqtcommon/jkqtpcodestructuring.cpp \ + $$PWD/jkqtcommon/jkqtpbasicimagetools.cpp \ + $$PWD/jkqtcommon/jkqtpdrawingtools.cpp \ + $$PWD/jkqtcommon/jkqtpenhancedpainter.cpp \ + $$PWD/jkqtcommon/jkqtphighrestimer.cpp \ + $$PWD/jkqtcommon/jkqtpmathparser.cpp \ + $$PWD/jkqtcommon/jkqttools.cpp \ + $$PWD/jkqtcommon/jkqtparraytools.cpp \ + $$PWD/jkqtcommon/jkqtpstatisticstools.cpp + + + INCLUDEPATH += $$PWD + + QT += core gui + greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport + + CONFIG += c++11 +} diff --git a/lib/jkqtplotter.pri b/lib/jkqtplotter.pri index 3a61b2637e..d95c3e53df 100644 --- a/lib/jkqtplotter.pri +++ b/lib/jkqtplotter.pri @@ -2,106 +2,99 @@ #DEFINES += NO_XITS_FONTS -include($$PWD/common.pri) + +isEmpty(JKQTP_PLOTTER_PRI_INCLUDED) { + JKQTP_PLOTTER_PRI_INCLUDED = 1 + + INCLUDEPATH += $PWD -HEADERS += \ - $$PWD/jkqtfastplotter/jkqtfastplotter.h \ - $$PWD/jkqtmathtext/jkqtmathtext.h \ - $$PWD/jkqtplotter/jkqtpbaseelements.h \ - $$PWD/jkqtplotter/jkqtpbaseplotter.h \ - $$PWD/jkqtplotter/jkqtpdatastorage.h \ - $$PWD/jkqtplotter/jkqtpelementsoverlay.h \ - $$PWD/jkqtplotter/jkqtpgraphsscatter.h \ - $$PWD/jkqtplotter/jkqtpgraphsrange.h \ - $$PWD/jkqtplotter/jkqtpgraphsspecialline.h \ - $$PWD/jkqtplotter/jkqtpgraphsbarchart.h \ - $$PWD/jkqtplotter/jkqtpgraphsbase.h \ - $$PWD/jkqtplotter/jkqtpgraphsbaseerrors.h \ - $$PWD/jkqtplotter/jkqtpgraphsbasestylingmixins.h \ - $$PWD/jkqtplotter/jkqtpgraphsboxplot.h \ - $$PWD/jkqtplotter/jkqtpgraphsboxplotstylingmixins.h \ - $$PWD/jkqtplotter/jkqtpgraphsevaluatedfunction.h \ - $$PWD/jkqtplotter/jkqtpgraphsfilledcurve.h \ - $$PWD/jkqtplotter/jkqtpgraphsgeometric.h \ - $$PWD/jkqtplotter/jkqtpgraphsimage.h \ - $$PWD/jkqtplotter/jkqtpgraphsimpulses.h \ - $$PWD/jkqtplotter/jkqtpgraphsparsedfunction.h \ - $$PWD/jkqtplotter/jkqtpgraphspeakstream.h \ - $$PWD/jkqtplotter/jkqtpgraphssinglecolumnsymbols.h \ - $$PWD/jkqtplotter/jkqtpgraphsimageoverlays.h \ - $$PWD/jkqtplotter/jkqtpgraphscontour.h \ - $$PWD/jkqtplotter/jkqtpgraphsimagergb.h \ - $$PWD/jkqtplotter/jkqtplotter.h \ - $$PWD/jkqtplotter/jkqtplotterstyle.h \ - $$PWD/jkqtplotter/jkqtpbaseplotterstyle.h \ - $$PWD/jkqtplotter/jkqtpcoordinateaxes.h \ - $$PWD/jkqtplotter/jkqtpcoordinateaxesstyle.h \ - $$PWD/jkqtplottergui/jkqtpcomboboxes.h \ - $$PWD/jkqtplottergui/jkqtpenhancedspinboxes.h \ - $$PWD/jkqtplottergui/jkqtpenhancedtableview.h \ - $$PWD/jkqtplottergui/jkqtpgraphsmodel.h \ - $$PWD/jkqtplottergui/jkvanishqtoolbar.h \ - $$PWD/jkqtplottertools/jkqtpdrawingtools.h \ - $$PWD/jkqtplottertools/jkqtpenhancedpainter.h \ - $$PWD/jkqtplottertools/jkqtphighrestimer.h \ - $$PWD/jkqtplottertools/jkqtpimagetools.h \ - $$PWD/jkqtplottertools/jkqtpmathparser.h \ - $$PWD/jkqtplottertools/jkqttools.h \ - $$PWD/jkqtplotter/jkqtpkeystyle.h + HEADERS += \ + $$PWD/jkqtplotter/jkqtptools.h \ + $$PWD/jkqtplotter/jkqtpbaseelements.h \ + $$PWD/jkqtplotter/jkqtpbaseplotter.h \ + $$PWD/jkqtplotter/jkqtpdatastorage.h \ + $$PWD/jkqtplotter/jkqtpelementsoverlay.h \ + $$PWD/jkqtplotter/jkqtpgraphsscatter.h \ + $$PWD/jkqtplotter/jkqtpgraphsrange.h \ + $$PWD/jkqtplotter/jkqtpgraphsspecialline.h \ + $$PWD/jkqtplotter/jkqtpgraphsbarchart.h \ + $$PWD/jkqtplotter/jkqtpgraphsbase.h \ + $$PWD/jkqtplotter/jkqtpgraphsbaseerrors.h \ + $$PWD/jkqtplotter/jkqtpgraphsbasestylingmixins.h \ + $$PWD/jkqtplotter/jkqtpgraphsboxplot.h \ + $$PWD/jkqtplotter/jkqtpgraphsboxplotstylingmixins.h \ + $$PWD/jkqtplotter/jkqtpgraphsevaluatedfunction.h \ + $$PWD/jkqtplotter/jkqtpgraphsfilledcurve.h \ + $$PWD/jkqtplotter/jkqtpgraphsgeometric.h \ + $$PWD/jkqtplotter/jkqtpgraphsimage.h \ + $$PWD/jkqtplotter/jkqtpgraphsimpulses.h \ + $$PWD/jkqtplotter/jkqtpgraphsparsedfunction.h \ + $$PWD/jkqtplotter/jkqtpgraphspeakstream.h \ + $$PWD/jkqtplotter/jkqtpgraphssinglecolumnsymbols.h \ + $$PWD/jkqtplotter/jkqtpgraphsimageoverlays.h \ + $$PWD/jkqtplotter/jkqtpgraphscontour.h \ + $$PWD/jkqtplotter/jkqtpgraphsimagergb.h \ + $$PWD/jkqtplotter/jkqtpgraphsstatisticsadaptors.h \ + $$PWD/jkqtplotter/jkqtplotter.h \ + $$PWD/jkqtplotter/jkqtplotterstyle.h \ + $$PWD/jkqtplotter/jkqtpkeystyle.h \ + $$PWD/jkqtplotter/jkqtpbaseplotterstyle.h \ + $$PWD/jkqtplotter/jkqtpcoordinateaxes.h \ + $$PWD/jkqtplotter/jkqtpcoordinateaxesstyle.h \ + $$PWD/jkqtplottergui/jkqtpcomboboxes.h \ + $$PWD/jkqtplottergui/jkqtpenhancedspinboxes.h \ + $$PWD/jkqtplottergui/jkqtpenhancedtableview.h \ + $$PWD/jkqtplottergui/jkqtpgraphsmodel.h \ + $$PWD/jkqtplottergui/jkvanishqtoolbar.h \ + $$PWD/jkqtplotter/jkqtpimagetools.h -SOURCES += \ - $$PWD/jkqtfastplotter/jkqtfastplotter.cpp \ - $$PWD/jkqtmathtext/jkqtmathtext.cpp \ - $$PWD/jkqtplotter/jkqtpbaseelements.cpp \ - $$PWD/jkqtplotter/jkqtpbaseplotter.cpp \ - $$PWD/jkqtplotter/jkqtpdatastorage.cpp \ - $$PWD/jkqtplotter/jkqtpelementsoverlay.cpp \ - $$PWD/jkqtplotter/jkqtpgraphsscatter.cpp \ - $$PWD/jkqtplotter/jkqtpgraphsrange.cpp \ - $$PWD/jkqtplotter/jkqtpgraphsspecialline.cpp \ - $$PWD/jkqtplotter/jkqtpgraphsbarchart.cpp \ - $$PWD/jkqtplotter/jkqtpgraphsbase.cpp \ - $$PWD/jkqtplotter/jkqtpgraphsbaseerrors.cpp \ - $$PWD/jkqtplotter/jkqtpgraphsbasestylingmixins.cpp \ - $$PWD/jkqtplotter/jkqtpgraphsboxplot.cpp \ - $$PWD/jkqtplotter/jkqtpgraphsboxplotstylingmixins.cpp \ - $$PWD/jkqtplotter/jkqtpgraphsevaluatedfunction.cpp \ - $$PWD/jkqtplotter/jkqtpgraphsfilledcurve.cpp \ - $$PWD/jkqtplotter/jkqtpgraphsgeometric.cpp \ - $$PWD/jkqtplotter/jkqtpgraphsimage.cpp \ - $$PWD/jkqtplotter/jkqtpgraphsimpulses.cpp \ - $$PWD/jkqtplotter/jkqtpgraphsparsedfunction.cpp \ - $$PWD/jkqtplotter/jkqtpgraphspeakstream.cpp \ - $$PWD/jkqtplotter/jkqtpgraphssinglecolumnsymbols.cpp \ - $$PWD/jkqtplotter/jkqtpgraphsimageoverlays.cpp \ - $$PWD/jkqtplotter/jkqtpgraphscontour.cpp \ - $$PWD/jkqtplotter/jkqtpgraphsimagergb.cpp \ - $$PWD/jkqtplotter/jkqtplotter.cpp \ - $$PWD/jkqtplotter/jkqtplotterstyle.cpp \ - $$PWD/jkqtplotter/jkqtpbaseplotterstyle.cpp \ - $$PWD/jkqtplotter/jkqtpcoordinateaxes.cpp \ - $$PWD/jkqtplotter/jkqtpcoordinateaxesstyle.cpp \ - $$PWD/jkqtplottergui/jkqtpcomboboxes.cpp \ - $$PWD/jkqtplottergui/jkqtpenhancedspinboxes.cpp \ - $$PWD/jkqtplottergui/jkqtpenhancedtableview.cpp \ - $$PWD/jkqtplottergui/jkqtpgraphsmodel.cpp \ - $$PWD/jkqtplottergui/jkvanishqtoolbar.cpp \ - $$PWD/jkqtplottertools/jkqtpdrawingtools.cpp \ - $$PWD/jkqtplottertools/jkqtpenhancedpainter.cpp \ - $$PWD/jkqtplottertools/jkqtphighrestimer.cpp \ - $$PWD/jkqtplottertools/jkqtpimagetools.cpp \ - $$PWD/jkqtplottertools/jkqtpmathparser.cpp \ - $$PWD/jkqtplottertools/jkqttools.cpp \ - $$PWD/jkqtplotter/jkqtpkeystyle.cpp + + SOURCES += \ + $$PWD/jkqtplotter/jkqtptools.cpp \ + $$PWD/jkqtplotter/jkqtpbaseelements.cpp \ + $$PWD/jkqtplotter/jkqtpbaseplotter.cpp \ + $$PWD/jkqtplotter/jkqtpdatastorage.cpp \ + $$PWD/jkqtplotter/jkqtpelementsoverlay.cpp \ + $$PWD/jkqtplotter/jkqtpgraphsscatter.cpp \ + $$PWD/jkqtplotter/jkqtpgraphsrange.cpp \ + $$PWD/jkqtplotter/jkqtpgraphsspecialline.cpp \ + $$PWD/jkqtplotter/jkqtpgraphsbarchart.cpp \ + $$PWD/jkqtplotter/jkqtpgraphsbase.cpp \ + $$PWD/jkqtplotter/jkqtpgraphsbaseerrors.cpp \ + $$PWD/jkqtplotter/jkqtpgraphsbasestylingmixins.cpp \ + $$PWD/jkqtplotter/jkqtpgraphsboxplot.cpp \ + $$PWD/jkqtplotter/jkqtpgraphsboxplotstylingmixins.cpp \ + $$PWD/jkqtplotter/jkqtpgraphsevaluatedfunction.cpp \ + $$PWD/jkqtplotter/jkqtpgraphsfilledcurve.cpp \ + $$PWD/jkqtplotter/jkqtpgraphsgeometric.cpp \ + $$PWD/jkqtplotter/jkqtpgraphsimage.cpp \ + $$PWD/jkqtplotter/jkqtpgraphsimpulses.cpp \ + $$PWD/jkqtplotter/jkqtpgraphsparsedfunction.cpp \ + $$PWD/jkqtplotter/jkqtpgraphspeakstream.cpp \ + $$PWD/jkqtplotter/jkqtpgraphssinglecolumnsymbols.cpp \ + $$PWD/jkqtplotter/jkqtpgraphsimageoverlays.cpp \ + $$PWD/jkqtplotter/jkqtpgraphscontour.cpp \ + $$PWD/jkqtplotter/jkqtpgraphsimagergb.cpp \ + $$PWD/jkqtplotter/jkqtpgraphsstatisticsadaptors.cpp \ + $$PWD/jkqtplotter/jkqtplotter.cpp \ + $$PWD/jkqtplotter/jkqtplotterstyle.cpp \ + $$PWD/jkqtplotter/jkqtpkeystyle.cpp \ + $$PWD/jkqtplotter/jkqtpbaseplotterstyle.cpp \ + $$PWD/jkqtplotter/jkqtpcoordinateaxes.cpp \ + $$PWD/jkqtplotter/jkqtpcoordinateaxesstyle.cpp \ + $$PWD/jkqtplottergui/jkqtpcomboboxes.cpp \ + $$PWD/jkqtplottergui/jkqtpenhancedspinboxes.cpp \ + $$PWD/jkqtplottergui/jkqtpenhancedtableview.cpp \ + $$PWD/jkqtplottergui/jkqtpgraphsmodel.cpp \ + $$PWD/jkqtplottergui/jkvanishqtoolbar.cpp \ + $$PWD/jkqtplotter/jkqtpimagetools.cpp -RESOURCES += $$PWD/jkqtplotterressources/jkqtpbaseplotter.qrc \ - $$PWD/jkqtplotterressources/jkqtpstyles.qrc + RESOURCES += $$PWD/jkqtplotterressources/jkqtpbaseplotter.qrc \ + $$PWD/jkqtplotterressources/jkqtpstyles.qrc -QT += xml svg opengl + QT += xml svg opengl -include($$PWD/jkqtplotterressources/math_fonts/xits.pri) -DEFINES += AUTOLOAD_XITS_FONTS -DEFINES += USE_XITS_FONTS +} diff --git a/lib/jkqtplotter/jkqtpbaseplotter.cpp b/lib/jkqtplotter/jkqtpbaseplotter.cpp index adccb96f51..fcfff97cb7 100644 --- a/lib/jkqtplotter/jkqtpbaseplotter.cpp +++ b/lib/jkqtplotter/jkqtpbaseplotter.cpp @@ -532,7 +532,7 @@ void JKQTBasePlotter::propagateStyle() { xAxis->setCurrentAxisStyle(plotterStyle.xAxisStyle); yAxis->setCurrentAxisStyle(plotterStyle.yAxisStyle); for (int i=0; i(graphs[i]); + JKQTPColorPaletteStyleAndToolsMixin* palTools=dynamic_cast(graphs[i]); if (palTools) { palTools->getColorBarRightAxis()->setCurrentAxisStyle(plotterStyle.rightColorbarAxisStyle); palTools->getColorBarTopAxis()->setCurrentAxisStyle(plotterStyle.topColorbarAxisStyle); diff --git a/lib/jkqtplotter/jkqtpbaseplotter.h b/lib/jkqtplotter/jkqtpbaseplotter.h index f267cf2309..0e0f565337 100644 --- a/lib/jkqtplotter/jkqtpbaseplotter.h +++ b/lib/jkqtplotter/jkqtpbaseplotter.h @@ -17,13 +17,13 @@ along with this program. If not, see . */ -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtplotter/jkqtpdatastorage.h" #include "jkqtplotter/jkqtpbaseplotterstyle.h" #include "jkqtmathtext/jkqtmathtext.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtpelementsoverlay.h" -#include "jkqtplottertools/jkqtpenhancedpainter.h" +#include "jkqtcommon/jkqtpenhancedpainter.h" #include "jkqtplottergui/jkqtpenhancedspinboxes.h" #include diff --git a/lib/jkqtplotter/jkqtpbaseplotterstyle.cpp b/lib/jkqtplotter/jkqtpbaseplotterstyle.cpp index 0dc2c42589..453fa075ad 100644 --- a/lib/jkqtplotter/jkqtpbaseplotterstyle.cpp +++ b/lib/jkqtplotter/jkqtpbaseplotterstyle.cpp @@ -1,7 +1,7 @@ #include "jkqtpbaseplotterstyle.h" #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" JKQTBasePlotterStyle::JKQTBasePlotterStyle(): debugShowRegionBoxes(false), diff --git a/lib/jkqtplotter/jkqtpbaseplotterstyle.h b/lib/jkqtplotter/jkqtpbaseplotterstyle.h index b67c572f43..014e1eba17 100644 --- a/lib/jkqtplotter/jkqtpbaseplotterstyle.h +++ b/lib/jkqtplotter/jkqtpbaseplotterstyle.h @@ -20,11 +20,14 @@ #ifndef JKQTBASEPLOTTERSTYLE_H #define JKQTBASEPLOTTERSTYLE_H -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" +#include "jkqtplotter/jkqtpimagetools.h" #include "jkqtplotter/jkqtpcoordinateaxesstyle.h" #include "jkqtplotter/jkqtpkeystyle.h" -#include "jkqtplottertools/jkqtpimagetools.h" +#include "jkqtplotter/jkqtpimagetools.h" #include "jkqtcommon/jkqtp_imexport.h" +#include "jkqtcommon/jkqtpdrawingtools.h" +#include "jkqtcommon/jkqtpbasicimagetools.h" #include #include #include diff --git a/lib/jkqtplotter/jkqtpcoordinateaxes.cpp b/lib/jkqtplotter/jkqtpcoordinateaxes.cpp index 3bf7e70deb..ea012a872a 100644 --- a/lib/jkqtplotter/jkqtpcoordinateaxes.cpp +++ b/lib/jkqtplotter/jkqtpcoordinateaxes.cpp @@ -19,7 +19,7 @@ #include "jkqtplotter/jkqtpcoordinateaxes.h" #include "jkqtplotter/jkqtpbaseplotter.h" -#include "jkqtplottertools/jkqtpdrawingtools.h" +#include "jkqtcommon/jkqtpdrawingtools.h" #include #include #include diff --git a/lib/jkqtplotter/jkqtpcoordinateaxes.h b/lib/jkqtplotter/jkqtpcoordinateaxes.h index 1fd685fc61..885f5fe8f6 100644 --- a/lib/jkqtplotter/jkqtpcoordinateaxes.h +++ b/lib/jkqtplotter/jkqtpcoordinateaxes.h @@ -28,7 +28,7 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtmathtext/jkqtmathtext.h" #include "jkqtcommon/jkqtp_imexport.h" #include "jkqtplotter/jkqtpcoordinateaxesstyle.h" diff --git a/lib/jkqtplotter/jkqtpcoordinateaxesstyle.h b/lib/jkqtplotter/jkqtpcoordinateaxesstyle.h index a54abf2e32..aa513fdb6b 100644 --- a/lib/jkqtplotter/jkqtpcoordinateaxesstyle.h +++ b/lib/jkqtplotter/jkqtpcoordinateaxesstyle.h @@ -23,7 +23,7 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtcommon/jkqtp_imexport.h" class JKQTBasePlotterStyle; // forward diff --git a/lib/jkqtplotter/jkqtpdatastorage.cpp b/lib/jkqtplotter/jkqtpdatastorage.cpp index 73023b54ac..e93ee76c59 100644 --- a/lib/jkqtplotter/jkqtpdatastorage.cpp +++ b/lib/jkqtplotter/jkqtpdatastorage.cpp @@ -287,7 +287,8 @@ size_t JKQTPDatastore::addColumn(JKQTPColumn col) { } //////////////////////////////////////////////////////////////////////////////////////////////// -JKQTPDatastore::JKQTPDatastore() +JKQTPDatastore::JKQTPDatastore(): + m_invalidColumn(new JKQTPColumn) { maxItemID=0; maxColumnsID=0; @@ -299,6 +300,114 @@ JKQTPDatastore::~JKQTPDatastore() { clear(); } +//////////////////////////////////////////////////////////////////////////////////////////////// +JKQTPDatastore::ColumnIterator JKQTPDatastore::begin() +{ + return columns.begin(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +JKQTPDatastore::ColumnIterator JKQTPDatastore::end() +{ + return columns.end(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +JKQTPDatastore::ConstColumnIterator JKQTPDatastore::begin() const +{ + return columns.begin(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +JKQTPDatastore::ConstColumnIterator JKQTPDatastore::end() const +{ + return columns.end(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +JKQTPColumnIterator JKQTPDatastore::begin(int i) +{ + if (i<0) return m_invalidColumn->end(); + auto it=columns.find(static_cast(i)); + if (it==columns.end()) return m_invalidColumn->end(); + else return it->begin(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +JKQTPColumnIterator JKQTPDatastore::end(int i) +{ + if (i<0) return m_invalidColumn->end(); + auto it=columns.find(static_cast(i)); + if (it==columns.end()) return m_invalidColumn->end(); + else return it->end(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +JKQTPColumnConstIterator JKQTPDatastore::begin(int i) const +{ + if (i<0) return m_invalidColumn->end(); + auto it=columns.find(static_cast(i)); + if (it==columns.end()) return m_invalidColumn->end(); + else return it->begin(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +JKQTPColumnConstIterator JKQTPDatastore::end(int i) const +{ + if (i<0) return m_invalidColumn->end(); + auto it=columns.find(static_cast(i)); + if (it==columns.end()) return m_invalidColumn->end(); + else return it->end(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +JKQTPColumnIterator JKQTPDatastore::begin(size_t i) +{ + auto it=columns.find(i); + if (it==columns.end()) return m_invalidColumn->end(); + else return it->begin(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +JKQTPColumnIterator JKQTPDatastore::end(size_t i) +{ + auto it=columns.find(i); + if (it==columns.end()) return m_invalidColumn->end(); + else return it->end(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +JKQTPColumnConstIterator JKQTPDatastore::begin(size_t i) const +{ + auto it=columns.find(i); + if (it==columns.end()) return m_invalidColumn->end(); + else return it->begin(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +JKQTPColumnConstIterator JKQTPDatastore::end(size_t i) const +{ + auto it=columns.find(i); + if (it==columns.end()) return m_invalidColumn->end(); + else return it->end(); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +JKQTPColumnBackInserter JKQTPDatastore::backInserter(int i) +{ + auto it=columns.find(i); + if (i<0 || it==columns.end()) return JKQTPColumnBackInserter(this, std::numeric_limits::max()); + else return JKQTPColumnBackInserter(this, static_cast(i)); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +JKQTPColumnBackInserter JKQTPDatastore::backInserter(size_t i) +{ + auto it=columns.find(i); + if (it==columns.end()) return JKQTPColumnBackInserter(this, std::numeric_limits::max()); + else return JKQTPColumnBackInserter(this, static_cast(i)); +} + //////////////////////////////////////////////////////////////////////////////////////////////// void JKQTPDatastore::clear(){ maxItemID=0; @@ -386,6 +495,15 @@ int JKQTPDatastore::getColumnNum(const QString& name) { return -1; } +//////////////////////////////////////////////////////////////////////////////////////////////// +QString JKQTPDatastore::getColumnName(size_t column) +{ + auto it=columns.find(column); + + if (it==columns.end()) return ""; + else return it->getName(); +} + //////////////////////////////////////////////////////////////////////////////////////////////// int JKQTPDatastore::ensureColumnNum(const QString& name) { if (columns.size()<=0) return -1; @@ -488,36 +606,28 @@ size_t JKQTPDatastore::addCopiedItem(const double* data, size_t rows) { //////////////////////////////////////////////////////////////////////////////////////////////// size_t JKQTPDatastore::addColumnForItem(size_t itemID, size_t columnInItem, const QString& name) { - /*JKQTPColumn c(this, name, itemID, columnInItem); - columns.push_back(c); - return columns.size()-1;*/ return addColumn(JKQTPColumn(this, name, itemID, columnInItem)); }; //////////////////////////////////////////////////////////////////////////////////////////////// size_t JKQTPDatastore::addColumn(size_t rows, const QString& name) { - //items.push_back(new JKQTPDatastoreItem(1, rows)); - //return addColumnForItem(items.size()-1, 0, name); size_t item= addItem(new JKQTPDatastoreItem(1, rows)); return addColumnForItem(item, 0, name); }; +//////////////////////////////////////////////////////////////////////////////////////////////// +size_t JKQTPDatastore::addColumn(const QString& name) { + return addColumn(0, name); +}; + //////////////////////////////////////////////////////////////////////////////////////////////// size_t JKQTPDatastore::addColumn(double* data, size_t rows, const QString& name) { - //items.push_back(new JKQTPDatastoreItem(JKQTPSingleColumn, data, 1, rows)); - //std::cout<<"added item\n"; - //size_t it=items.size()-1; - //std::cout<<"adding column\n"; size_t it=addItem(new JKQTPDatastoreItem(JKQTPDatastoreItemFormat::SingleColumn, data, 1, rows)); return addColumnForItem(it, 0, name); }; //////////////////////////////////////////////////////////////////////////////////////////////// size_t JKQTPDatastore::addInternalColumn(double* data, size_t rows, const QString& name) { - //items.push_back(new JKQTPDatastoreItem(JKQTPSingleColumn, data, 1, rows)); - //std::cout<<"added item\n"; - //size_t it=items.size()-1; - //std::cout<<"adding column\n"; size_t it=addItem(new JKQTPDatastoreItem(JKQTPDatastoreItemFormat::SingleColumn, data, 1, rows,true)); return addColumnForItem(it, 0, name); } diff --git a/lib/jkqtplotter/jkqtpdatastorage.h b/lib/jkqtplotter/jkqtpdatastorage.h index b3364a6880..6baabe08ae 100644 --- a/lib/jkqtplotter/jkqtpdatastorage.h +++ b/lib/jkqtplotter/jkqtpdatastorage.h @@ -20,10 +20,13 @@ #include "jkqtcommon/jkqtp_imexport.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" +#include "jkqtcommon/jkqtptoolsdebugging.h" #include #include #include +#include +#include #include #include #include @@ -39,8 +42,11 @@ class JKQTPColumn; // forward declaration +class JKQTPColumnIterator; // forward declaration +class JKQTPColumnConstIterator; // forward declaration class JKQTPDatastoreItem; // foward declaration class JKQTPDatastoreModel; // forward declaration +class JKQTPColumnBackInserter; // forward declaration /** \brief the types of data in one JKQTdatastoreItem @@ -79,18 +85,163 @@ enum class JKQTPDatastoreItemFormat { MatrixRow, /*!< \brief a 1D C-array of doubles that represents a number of rows (C standard representation of matrices). The data is stored row after row (=row-major).*/ }; -/** \brief This class manages chunks of memory that are used for column data in JKQTBasePlotter descendents - * \ingroup jkqtpdatastorage - * - * \see \ref JKQTPlotterBasicJKQTPDatastore 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 - * to access the rest you will simply have to destroy all JKQTPColumn that point to the item with their - * JKQTPColumns:datastoreItem property. - * - * \verbatim +/*! \brief This class manages data columns (with entries of type \c double ), used by JKQTPlotter/JKQTBasePlotter to represent data for plots + \ingroup jkqtpdatastorage + + \see \ref JKQTPlotterBasicJKQTPDatastore for a detailed description of how to use this class for data management! + + + \section jkqtpdatastore_column_management Column Management + + \subsection jkqtpdatastore_column_management_generation Column Generation/Deletion + + A JKQTPDatastore manages a set of data columns. Each column is a continuous vector of numbers. Optionally it can be interpreted + as a 2D image. In the latter case, the data is assumed to be ordered in row-major ordering (i.e. row for row). + + You can generate new columns e.g. by: + - addColumn() which either generates internally managed (and extensible) columns, or accepts a simple \c double* pointer + to external. In the latter case owner-ship may be transferred to the datastore, but can also retain externally. + - addImageColumn() adds a column that should be interpreted as an image with given width and height (i.e. a row-major + matrix with \c width columns and \c height rows. + - copyColumn() duplicates an existing column + - addCopiedColumn() copies an external dataset into the datastore. e.g. with code like: + \code + QVector X, Y; + const int Ndata=100; + for (int i=0; isetXColumn(datastore->addCopiedColumn(X, "x")); + linegraph->setYColumn(datastore->addCopiedColumn(Y, "y")); + \endcode + - addLinearColumn() adds a column with linearly increasing numbers (in a given range) + - addLogColumn() and addDecadeLogColumn() add columns with logarithmically spaced values + - addLinearGridColumns() adds two columns which represent x- and y- coordinates of points + on a rectangular grid (useful for calculating image data) + - addCalculatedColumn() calculates a column, based on row numbers and a C++ functor + - addColumnCalculatedFromColumn() calculates a column, based on another column data + - addCopiedMap() copies data from a std::map/QMap into two columns + - ... several more functions for specific cases exist. + - Also note that there are even library extensions that allow to import data directly from OpenCV matrices: JKQTPCopyCvMatToColumn() + . + + Of course columns can also be deleted by calling: + - deleteColumn() + - deleteAllColumns() + - deleteAllPrefixedColumns() + - clear() + . + + \subsection jkqtpdatastore_column_management_props Column Properties + + The properties of columns may be accessed using: + - getRows() returns the number of rows in a specific column + - getColumnPointer() returns a pointer to the data in the column + - getColumnChecksum() calculated a checksum over the data in the column + - getColumnNames() / getColumnName() + . + + \subsection jkqtpdatastore_column_management_modify Modify Column Contents + + You can modify all data in a column by functions like: + - setAll() + - scaleColumnValues() + . + + Also you can access a single entry from a column, using: + - set() / get() set/read a column entry + - inc() / dec() increment/decrement a column entry + - appendToColumn() (adds a single row/new value to a column, if the column was not internally managed before, it will be copied into a new internal memory segment by the first call to this function!) + - appendFromContainerToColumn() (adds several rows from a container to a column, if the column was not internally managed before, it will be copied into a new internal memory segment by the first call to this function!) + . + + \subsection jkqtpdatastore_column_management_iterators Iterator Interface + + In addition to teh fucntions above, JKQTPDatastore also provides C++-style iteratos to read the data from a column: + - begin() + - end() + . + + ... and also a \c std::back_inserter -style interface to append data to columns: + - backInserter() + . + + These allow to use the C++ standard algorithms to work with columns and also enabled the + library \ref jkqtptools_math_statistics in this software package. You can use the functions + above e.g. for code like: + + \code + auto inserter it=datastore->backInserter(datastore->addColumn("new column")); + for (auto it=datastore->begin(col1); it!=datastore->begin(col1) ++it) { + *++inserter=sqrt(*it); + } + \endcode + + or simply + + \code + // mean of a column in a JKQTPDatastore: + double mean=jkqtpstatAverage(datastore1->begin(col1), datastore1->end(col1)); + \endcode + + Also there are functions to add data from iterator-defined ranges, e.g.: + - addCopiedColumn() + - addCopiedMap() + - appendToColumn() + . + + + \subsection jkqtpdatastore_column_management_images Image Column + + JKQTPDatastore stores the width and height of the represented image as metadata with any image column. + This metadata is used to provide convenience access to the image pixels with: + - setPixel() + - getPixel() + . + + The image width/height are read using: + - getColumnImageWidth() + - getColumnImageHeight() + . + + This allows to write code like: + \code + for (int iy=0; iy<10; iy++) { + for (int ix=0; ix<10; ix++) { + datastore->setPixel(imgColumn, ix, iy, sin(ix*iy/30.0)); + } + } + \endcode + + \section jkqtpdatastore_dataio Data Output + + JKQTPDatastore provides several functions that allow to store its contents into files: + - saveCSV + - saveSYLK() + - saveMatlab() + - saveDIF() + . + + ... and function to read data into different data structures: + - getData() + . + + + + + \section jkqtpdatastore_internals Internal Working + + 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 + to access the rest you will simply have to destroy all JKQTPColumn that point to the item with their + JKQTPColumns:datastoreItem property. + + \verbatim +- JKQTPDatastore ---------------------+ std::vector: | | +- JKQTPColumn ----------------+ @@ -118,10 +269,10 @@ enum class JKQTPDatastoreItemFormat { \endverbatim - * - * In addition the JKQTPDatastore manages a std::vector which may be used to access the data chunks in the logical - * notion of data columns. This class provides a set of interface methods for this list: - * + + In addition the JKQTPDatastore manages a std::vector which may be used to access the data chunks in the logical + notion of data columns. This class provides a set of interface methods for this list: + */ class JKQTP_LIB_EXPORT JKQTPDatastore{ private: @@ -130,7 +281,20 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{ /** \brief a std::vector of all columns that may be used to access the managed chunks of memory. */ QMap columns; + /** \brief an internal invalid column object, used e.g. to return invalid column iterators + * \internal + */ + std::unique_ptr m_invalidColumn; + + /** \brief internal variable to keep track about the highest item ID (in items) used so far + * \internal + * \see items + */ size_t maxItemID; + /** \brief internal variable to keep track about the highest column ID (in columns) used so far + * \internal + * \see columns + */ size_t maxColumnsID; protected: @@ -200,13 +364,48 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{ * 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; + /** \brief mutable iterator for columns in the JKQTPDatastore (\c ColumnIterator::first: column number, \c ColumnIterator::second: column data) */ + typedef QMap::iterator ColumnIterator; + /** \brief constant iterator for columns in the JKQTPDatastore (\c ColumnIterator::first: column number, \c ColumnIterator::second: column data) */ + typedef QMap::const_iterator ConstColumnIterator; + + /** \brief returns an iterator to the first column in the JKQTPDatastore \see ColumnIterator */ + ColumnIterator begin(); + /** \brief returns an iterator behind the last column in the JKQTPDatastore \see ColumnIterator */ + ColumnIterator end(); + /** \brief returns a const iterator to the first column in the JKQTPDatastore \see ConstColumnIterator */ + ConstColumnIterator begin() const; + /** \brief returns a const iterator behind the last column in the JKQTPDatastore \see ConstColumnIterator */ + ConstColumnIterator end() const; public: + /** \brief class constructor, generates an empty datastore */ JKQTPDatastore(); /** \brief class destructor, destroys all subordered JKQTPDatastoreItem objects */ ~JKQTPDatastore(); + /** \brief returns an iterator to the first data entry in the \a i -th column in the JKQTPDatastore \see JKQTPColumn::iterator */ + JKQTPColumnIterator begin(int i); + /** \brief returns an iterator behind the last data entry data in the \a i -th column in the JKQTPDatastore \see JKQTPColumn::iterator */ + JKQTPColumnIterator end(int i); + /** \brief returns a const iterator to the first data entry in the \a i -th column in the JKQTPDatastore \see JKQTPColumn::const_iterator */ + JKQTPColumnConstIterator begin(int i) const; + /** \brief returns a const iterator behind the last data entry data in the \a i -th column in the JKQTPDatastore \see JKQTPColumn::const_iterator */ + JKQTPColumnConstIterator end(int i) const; + /** \brief returns an iterator to the first data entry in the \a i -th column in the JKQTPDatastore \see JKQTPColumn::iterator */ + JKQTPColumnIterator begin(size_t i); + /** \brief returns an iterator behind the last data entry data in the \a i -th column in the JKQTPDatastore \see JKQTPColumn::iterator */ + JKQTPColumnIterator end(size_t i); + /** \brief returns a const iterator to the first data entry in the \a i -th column in the JKQTPDatastore \see JKQTPColumn::const_iterator */ + JKQTPColumnConstIterator begin(size_t i) const; + /** \brief returns a const iterator behind the last data entry data in the \a i -th column in the JKQTPDatastore \see JKQTPColumn::const_iterator */ + JKQTPColumnConstIterator end(size_t i) const; + + /** \brief returns a back-inserter iterator (JKQTPColumnBackInserter) to the \a i -th column in the JKQTPDatastore \see JKQTPColumnBackInserter */ + JKQTPColumnBackInserter backInserter(int i); + /** \brief returns a back-inserter iterator (JKQTPColumnBackInserter) to the \a i -th column in the JKQTPDatastore \see JKQTPColumnBackInserter */ + JKQTPColumnBackInserter backInserter(size_t i); /** \brief deletes all items from the datastore and possibly frees the memory they manage */ void clear(); @@ -274,7 +473,7 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{ inline void set(int column, size_t row, double value); /** \brief adds a value \a value to the column \a column. This changes the column length (number of rows). If the memory was externally managed before, it will be internally managed afterwards */ inline void appendToColumn(size_t column, double value); - /** \brief adds a values in cintainer \a values to the column \a column. This changes the column length (number of rows). If the memory was externally managed before, it will be internally managed afterwards + /** \brief adds a values in container \a values to the column \a column. This changes the column length (number of rows). If the memory was externally managed before, it will be internally managed afterwards * * \tparam TContainer a container with standard iterators * \param column the column to extend @@ -282,6 +481,15 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{ */ template inline void appendFromContainerToColumn(size_t column, const TContainer& values); + /** \brief adds a values from a range \a first ... \a last (defined by C++ iterators) to the column \a column. This changes the column length (number of rows). If the memory was externally managed before, it will be internally managed afterwards + * + * \tparam TIterator a standard C++ iterator + * \param column the column to extend + * \param first points to the first value in the range of values to add + * \param last points behind the last value in the range of values to add + */ + template + inline void appendToColumn(size_t column, TIterator first, TIterator last); /** \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 ; @@ -318,6 +526,13 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{ */ size_t addColumn(size_t rows, const QString& name=QString("")); + /** \brief add a new and empty column to the datastore and return its column ID. The new item uses internal memory management. + * \param name name for the column + * \return the ID of the newly created column + * \see \ref JKQTPlotterBasicJKQTPDatastore + */ + size_t addColumn(const QString& name=QString("")); + /** \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! * @@ -429,9 +644,48 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{ size_t copyColumn(size_t old_column, const QString& name=QString("")); + /** \brief add one column to the datastore. It will be filled with the values from \a first ... \a last + * + * \tparam TIterator a standard C++ iterator + * \param first points to the first value in the range of values to add + * \param last points behind the last value in the range of values to add + * \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.begin(), X.end(), "x")); + * linegraph->setYColumn(datastore->addCopiedColumn(Y.begin(), Y.end(), "y")); + * \endcode + * + * \see \ref JKQTPlotterBasicJKQTPDatastore + */ + template + size_t addCopiedColumn(TIterator first, TIterator last, const QString& name=QString("")) { + const size_t N=static_cast(abs(std::distance(first,last))); + double* d=static_cast(malloc(static_cast(N)*sizeof(double))); + if (N>0) { + size_t r=0; + for (auto it=first; it!=last; ++it) { + d[r]=jkqtp_todouble(*it); + r++; + } + } + size_t itemid=addInternalItem(d, N); + return addColumnForItem(itemid, 0, name); + } + /** \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, which need to support standard C++ iterators. The contents needs to be convertible to double. * \param data data vector to be copied * \param name name for the column * \return the ID of the newly created column @@ -454,20 +708,9 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{ */ template size_t addCopiedColumn(const TContainer& data, const QString& name=QString("")) { - const size_t N=static_cast(data.size()); - double* d=static_cast(malloc(static_cast(N)*sizeof(double))); - if (N>0) { - size_t r=0; - for (auto it=data.begin(); it!=data.end(); ++it) { - d[r]=jkqtp_todouble(*it); - r++; - } - } - size_t itemid=addInternalItem(d, N); - return addColumnForItem(itemid, 0, name); + return addCopiedColumn(data.begin(), data.end(), name); } - /** \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. @@ -719,6 +962,45 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{ } + /** \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 + * \see \ref JKQTPlotterBasicJKQTPDatastore, jkqtp_todouble() + * + * \tparam TIterator a standard C++ iterator for a map, dereferencing with \a it->first and \a it->second + * \param first points to the first value in the range of values to add + * \param last points behind the last value in the range of values to add + * \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.begin(), datamap.end(), "map_x", "map_y")); + * linegraph->setTitle(QObject::tr("copied map")); + * \endcode + */ + template + std::pair addCopiedMap(TIterator first, TIterator last, const QString& nameKey=QString("map_key"), const QString& nameValue=QString("map_value")) { + const size_t N=static_cast(abs(std::distance(first,last))); + double* xvals=static_cast(malloc(N*sizeof(double))); + double* yvals=static_cast(malloc(N*sizeof(double))); + size_t i=0; + for (auto it=first; it!=last; ++it) { + xvals[i]=(jkqtp_todouble(it->first)); + yvals[i]=(jkqtp_todouble(it->second)); + i++; + } + const size_t cx=addInternalColumn(xvals, N, nameKey); + const size_t cy=addInternalColumn(yvals, N, nameValue); + return std::pair(cx,cy); + } + /** \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 * \see \ref JKQTPlotterBasicJKQTPDatastore, jkqtp_todouble() @@ -744,24 +1026,12 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{ */ template std::pair addCopiedMap(const TContainer& c, const QString& nameKey=QString("map_key"), const QString& nameValue=QString("map_value")) { - 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[i]=(jkqtp_todouble(it->first)); - yvals[i]=(jkqtp_todouble(it->second)); - i++; - } - const size_t cx=addInternalColumn(xvals, N, nameKey); - const size_t cy=addInternalColumn(yvals, N, nameValue); - return std::pair(cx,cy); + return addCopiedMap(c.begin(), c.end(), nameKey, nameValue); } - /** \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 JKQTPlotterBasicJKQTPDatastore @@ -863,6 +1133,9 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{ /** \brief return the num of the first column with the given name, or -1 if none was found */ int getColumnNum(const QString& name); + /** \brief return the title of the first column with the given name, or -1 if none was found */ + QString getColumnName(size_t column); + /** \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); @@ -946,6 +1219,9 @@ class JKQTP_LIB_EXPORT JKQTPDatastore{ /** \brief return a list with all columns available in the datastore */ QStringList getColumnNames() const; + + + friend class JKQTPColumn; friend class JKQTPDatastoreItem; friend class JKQTPDatastoreModel; @@ -966,19 +1242,23 @@ class JKQTP_LIB_EXPORT JKQTPColumn { size_t datastoreItem; /** \brief offset, if the datastore item contains more than one column */ size_t datastoreOffset; - /** \brief a name describing the column */ - 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; + /** \brief pointer to the datastore object used to manage the data of the plot */ + JKQTPDatastore* datastore; + /** \brief a name describing the column */ + QString name; + /** \brief is this item valid?/usable? */ + bool valid; protected: inline JKQTPDatastore* getDatastore() { return datastore; } inline const JKQTPDatastore* getDatastore() const { return datastore; } public: + typedef JKQTPColumnIterator iterator; + typedef JKQTPColumnConstIterator const_iterator; + + JKQTPColumn(); /** \brief class constructor that binds the column to a specific datastore object. * @@ -989,9 +1269,6 @@ class JKQTP_LIB_EXPORT JKQTPColumn { inline bool isValid() const { return valid; } - /** \brief class destructor */ - ~JKQTPColumn() =default; - /*! \copydoc name */ void setName (const QString& __value); /*! \copydoc name */ @@ -1022,6 +1299,22 @@ class JKQTP_LIB_EXPORT JKQTPColumn { * column. */ inline double getValue(int n) const; + /** \brief returns a reference to the \a n -th row in this column (possibly throwing an exception if it does not exist!) + * + * This method accesses the datastore and returns the double value stored in the \a n'th row of the according + * column. + * + * \see iterator + */ + inline double& at(int n); + /** \brief returns a reference to the \a n -th row in this column (possibly throwing an exception if it does not exist!) + * + * This method accesses the datastore and returns the double value stored in the \a n'th row of the according + * column. + * + * \see const_iterator + */ + inline const double& at(int n) const; /** \brief gets a pointer to the n-th value in the column */ double* getPointer(size_t n=0) ; /** \brief gets a pointer to the n-th value in the column */ @@ -1107,11 +1400,318 @@ class JKQTP_LIB_EXPORT JKQTPColumn { /*! \copydoc datastoreOffset */ \ inline size_t getDatastoreOffset() const \ { return this->datastoreOffset; } + + /** \brief returns an iterator to the internal data + * \see JKQTPColumnIterator */ + inline iterator begin(); + /** \brief returns an iterator to the internal data + * \see JKQTPColumnIterator */ + inline iterator end(); + + /** \brief returns an iterator to the internal data + * \see JKQTPColumnIterator */ + inline const_iterator begin() const; + /** \brief returns an iterator to the internal data + * \see JKQTPColumnIterator */ + inline const_iterator end() const; + + + friend class JKQTPColumnIterator; + friend class JKQTPColumnConstIterator; +}; + +/** \brief iterator over the data in the column of a JKQTPDatastore + * \ingroup jkqtpdatastorage + * + * \see JKQTPColumn, JKQTPDatastore::begin(), JKQTPDatastore::end(), JKQTPDatastore, JKQTPConstColumnIterator + */ +class JKQTPColumnIterator { + private: + /** \brief references the column this iterator iterates over */ + JKQTPColumn* col_; + /** \brief current row in col_ this iterator points to */ + int pos_; + protected: + /** \brief constructs an iterator for the data represented by \a col, starting with row \a startpos */ + inline JKQTPColumnIterator(JKQTPColumn* col, int startpos=0) : col_(col), pos_(startpos) { } + public: + typedef JKQTPColumnIterator self_type; + typedef double value_type; + typedef double& reference; + typedef const double& const_reference; + typedef double* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef int difference_type; + /** \brief constructs an invalid iterator */ + inline JKQTPColumnIterator() : col_(nullptr), pos_(-1) { } + inline JKQTPColumnIterator(const JKQTPColumnIterator&)=default; + inline JKQTPColumnIterator(JKQTPColumnIterator&&)=default; + inline JKQTPColumnIterator& operator=(const JKQTPColumnIterator&)=default; + inline JKQTPColumnIterator& operator=(JKQTPColumnIterator&&)=default; + inline self_type operator++(int /*junk*/) { self_type i = *this; pos_++; return i; } + inline self_type operator++() { pos_++; return *this; } + inline self_type operator--(int /*junk*/) { self_type i = *this; pos_--; return i; } + inline self_type operator--() { pos_--; return *this; } + inline self_type operator+=(int inc) { pos_+=inc; return *this; } + inline self_type operator-=(int dec) { pos_-=dec; return *this; } + /** \brief dereferences the iterator, throws an exception if the iterator is invalid (see isValid() ) or the value does not exist in the column */ + inline reference operator*() { + JKQTPASSERT(col_!=nullptr && pos_>=0 && pos_(col_->getRows())); + return col_->at(pos_); + } + /** \brief dereferences the iterator, throws an exception if the iterator is invalid (see isValid() ) or the value does not exist in the column */ + inline const_reference operator*() const { + JKQTPASSERT(col_!=nullptr && pos_>=0 && pos_(col_->getRows())); + return col_->at(pos_); + } + /** \brief comparison operator (equals) + * + * two iterators are equal, if: + * - they are both invalid (see isValid() ) + * - they point to the same column and are both invalid (isValid()) or equal to end() + * - they point to the same column and the same row therein + * . + * + * \see operator!=() + * */ + inline bool operator==(const self_type& rhs) const { + if (!isValid() && !rhs.isValid()) return true; + if (col_ == rhs.col_) { + if ((pos_<0 || pos_>=static_cast(rhs.col_->getRows())) && (pos_<0 || rhs.pos_>=static_cast(rhs.col_->getRows()))) return true; + return pos_==rhs.pos_; + } + return false; + } + /** \brief comparison operator (unequals), inverse result of operator==() + * + * \see operator==() + * */ + inline bool operator!=(const self_type& rhs) const { return !this->operator==(rhs); } + /** \brief checks the iterator for validity (i.e. points to an existing column and position is in a valid range) */ + inline bool isValid() const { + return col_ && pos_>=0 && pos_(col_->getRows()); + } + /** \copydoc isValid() */ + inline operator bool() const { return isValid(); } + /** \brief returns the referenced position/row, or -1 for an invalid iterator */ + inline int getPosition() const { + if (!isValid()) return -1; + return pos_; + } + /** \brief returns the referenced position/row interpreted as an image pixel, returns (-1,-1) for an invalid operator */ + inline QPoint getImagePosition() const { + if (!isValid()) return QPoint(-1,-1); + return QPoint(pos_ % static_cast(col_->getImageColumns()), pos_ / static_cast(col_->getImageColumns())); + } + /** \brief returns the referenced position/row interpreted as an image pixel, x-component, returns -1 for an invalid operator */ + inline int getImagePositionX() const { + if (!isValid()) return -1; + return pos_ % static_cast(col_->getImageColumns()); + } + /** \brief returns the referenced position/row interpreted as an image pixel, y-component, returns -1 for an invalid operator */ + inline int getImagePositionY() const { + if (!isValid()) return -1; + return pos_ / static_cast(col_->getImageColumns()); + } + /*! \brief if the data in the column is interpreted as an image, this is the number of columns (x-dimension) of the image + \see JKQTPColumn::imageColumns */ + inline size_t getImageColumns () const { + if (!isValid()) return 0; + return col_->getImageColumns(); + } + /*! \brief if the data in the column is interpreted as an image, this is the number of rows (y-dimension) of the image + \see JKQTPColumn::imageColumns */ + inline size_t getImageRows () const { + if (!isValid()) return 0; + return col_->getRows() / col_->getImageColumns(); + } + friend class JKQTPColumnConstIterator; + friend class JKQTPColumn; + protected: + /** \brief returns the referenced column */ + inline JKQTPColumn* getColumn() { return col_; } + /** \brief returns the referenced column */ + inline const JKQTPColumn* getColumn() const { return col_; } }; + + +/** \brief iterator, which allows to insert into a column of a JKQTPDatastore + * \ingroup jkqtpdatastorage + * + * \see JKQTPDatastore::backInserter(), JKQTPDatastore, http://www.cplusplus.com/reference/iterator/insert_iterator/ + */ +class JKQTPColumnBackInserter { + private: + /** \brief references the datastore to access */ + JKQTPDatastore* ds_; + /** \brief references the column to access */ + size_t col_; + protected: + /** \brief constructs an iterator for the data represented by \a col, starting with row \a startpos */ + inline JKQTPColumnBackInserter(JKQTPDatastore* ds, size_t col) : ds_(ds), col_(col) { } + public: + typedef JKQTPColumnBackInserter self_type; + typedef double value_type; + typedef double& reference; + typedef const double& const_reference; + typedef double* pointer; + typedef std::output_iterator_tag iterator_category; + typedef int difference_type; + /** \brief constructs an invalid iterator */ + inline JKQTPColumnBackInserter() : ds_(nullptr), col_(0) { } + inline JKQTPColumnBackInserter(const JKQTPColumnBackInserter&)=default; + inline JKQTPColumnBackInserter(JKQTPColumnBackInserter&&)=default; + inline JKQTPColumnBackInserter& operator=(const JKQTPColumnBackInserter&)=default; + inline JKQTPColumnBackInserter& operator=(JKQTPColumnBackInserter&&)=default; + inline JKQTPColumnBackInserter& operator=(const double& val) { + JKQTPASSERT(ds_); + ds_->appendToColumn(col_, val); + return *this; + } + inline JKQTPColumnBackInserter& operator=(double&& val) { + JKQTPASSERT(ds_); + ds_->appendToColumn(col_, std::move(val)); + return *this; + } + inline self_type operator++(int /*junk*/) { return *this; } + inline self_type operator++() { return *this; } + inline self_type operator*() { + return *this; + } + friend class JKQTPDatastore; +}; + +/** \brief iterator over the data in the column of a JKQTPDatastore + * \ingroup jkqtpdatastorage + * + * \see JKQTPColumn, JKQTPDatastore::begin(), JKQTPDatastore::end(), JKQTPDatastore, JKQTPColumnIterator + */ +class JKQTPColumnConstIterator { + private: + /** \brief references the column this iterator iterates over */ + const JKQTPColumn* col_; + /** \brief current row in col_ this iterator points to */ + int pos_; + protected: + /** \brief constructs an iterator for the data represented by \a col, starting with row \a startpos */ + inline JKQTPColumnConstIterator(const JKQTPColumn* col, int startpos=0) : col_(col), pos_(startpos) { } + public: + typedef JKQTPColumnConstIterator self_type; + typedef double value_type; + typedef const double& reference; + typedef reference const_reference; + typedef const double* pointer; + typedef std::forward_iterator_tag iterator_category; + typedef int difference_type; + /** \brief constructs an invalid iterator */ + inline JKQTPColumnConstIterator() : col_(nullptr), pos_(-1) { } + inline JKQTPColumnConstIterator(const JKQTPColumnConstIterator&)=default; + inline JKQTPColumnConstIterator(JKQTPColumnConstIterator&&)=default; + inline JKQTPColumnConstIterator(const JKQTPColumnIterator& rhs): col_(rhs.col_), pos_(rhs.pos_) {} + inline JKQTPColumnConstIterator(JKQTPColumnIterator&& rhs): + col_(std::move(rhs.col_)), pos_(std::move(rhs.pos_)) + { + rhs.col_=nullptr; + rhs.pos_=-1; + } + inline JKQTPColumnConstIterator& operator=(const JKQTPColumnConstIterator&)=default; + inline JKQTPColumnConstIterator& operator=(JKQTPColumnConstIterator&&)=default; + inline JKQTPColumnConstIterator& operator=(const JKQTPColumnIterator&rhs){ + col_=rhs.col_; + pos_=rhs.pos_; + return *this; + } + inline JKQTPColumnConstIterator& operator=(JKQTPColumnIterator&&rhs){ + col_=rhs.col_; + pos_=rhs.pos_; + rhs.col_=nullptr; + rhs.pos_=-1; + return *this; + } + inline self_type operator++(int /*junk*/) { self_type i = *this; pos_++; return i; } + inline self_type operator++() { pos_++; return *this; } + inline self_type operator--(int /*junk*/) { self_type i = *this; pos_--; return i; } + inline self_type operator--() { pos_--; return *this; } + inline self_type operator+=(int inc) { pos_+=inc; return *this; } + inline self_type operator-=(int dec) { pos_-=dec; return *this; } + /** \brief dereferences the iterator, throws an exception if the iterator is invalid (see isValid() ) or the value does not exist in the column */ + inline reference operator*() const { + JKQTPASSERT(col_!=nullptr && pos_>=0 && pos_(col_->getRows())); + return col_->at(pos_); + } + /** \brief comparison operator (equals) + * + * two iterators are equal, if: + * - they are both invalid (see isValid() ) + * - they point to the same column and are both invalid (isValid()) or equal to end() + * - they point to the same column and the same row therein + * . + * + * \see operator!=() + * */ + inline bool operator==(const self_type& rhs) const { + if (col_ == nullptr && rhs.col_==nullptr) return true; + if (col_ == rhs.col_) { + if ((pos_<0 || pos_>=static_cast(rhs.col_->getRows())) && (pos_<0 || rhs.pos_>=static_cast(rhs.col_->getRows()))) return true; + return pos_==rhs.pos_; + } + return false; + } + /** \brief comparison operator (unequals), inverse result of operator==() + * + * \see operator==() + * */ + inline bool operator!=(const self_type& rhs) const { return !this->operator==(rhs); } + /** \brief checks the iterator for validity (i.e. points to an existing column and position is in a valid range) */ + inline bool isValid() const { + return col_ && pos_>=0 && pos_(col_->getRows()); + } + /** \copydoc isValid() */ + inline operator bool() const { return isValid(); } + /** \brief returns the referenced position/row, or -1 for an invalid iterator */ + inline int getPosition() const { + if (!isValid()) return -1; + return pos_; + } + /** \brief returns the referenced position/row interpreted as an image pixel, returns (-1,-1) for an invalid operator */ + inline QPoint getImagePosition() const { + if (!isValid()) return QPoint(-1,-1); + return QPoint(pos_ % static_cast(col_->getImageColumns()), pos_ / static_cast(col_->getImageColumns())); + } + /** \brief returns the referenced position/row interpreted as an image pixel, x-component, returns -1 for an invalid operator */ + inline int getImagePositionX() const { + if (!isValid()) return -1; + return pos_ % static_cast(col_->getImageColumns()); + } + /** \brief returns the referenced position/row interpreted as an image pixel, y-component, returns -1 for an invalid operator */ + inline int getImagePositionY() const { + if (!isValid()) return -1; + return pos_ / static_cast(col_->getImageColumns()); + } + /*! \brief if the data in the column is interpreted as an image, this is the number of columns (x-dimension) of the image + \see JKQTPColumn::imageColumns */ + inline size_t getImageColumns () const { + if (!isValid()) return 0; + return col_->getImageColumns(); + } + /*! \brief if the data in the column is interpreted as an image, this is the number of rows (y-dimension) of the image + \see JKQTPColumn::imageColumns */ + inline size_t getImageRows () const { + if (!isValid()) return 0; + return col_->getRows() / col_->getImageColumns(); + } + + friend class JKQTPColumn; + protected: + /** \brief returns the referenced column */ + inline const JKQTPColumn* getColumn() const { return col_; } +}; + + /** \brief this represents one chunk of memory which can represent one or more columns of data for JKQTBasePlotter. * See JKQTPDatastore for more information. * \ingroup jkqtpdatastorage @@ -1133,25 +1733,26 @@ class JKQTP_LIB_EXPORT JKQTPColumn { */ class JKQTP_LIB_EXPORT JKQTPDatastoreItem { private: + /** \brief how data is represented in this JKQTPDatastoreItem */ enum class StorageType { - Internal, - External, - Vector + Internal, /*!< \brief data is stored in an internally managed (=owned, i.e. freed in the destructor) C-array */ + External, /*!< \brief data is stored in an externally managed (=not owned) C-array */ + Vector /*!< \brief data is stored in the internal \a QVector datavec */ }; /** \brief a pointer to the actual data */ double* data; - /** \brief iif \a storageType is \c StorageType::Vector, the data is actually save here and data contains a pointer to the data in datavec */ - QVector datavec; - /** \brief specifies whether the datastore manages the memory (\c true ) or whether the user application does this (\c false ) .*/ - StorageType storageType; - /** \brief Specifies whether memory for the data has been allocated. This is only used, when \c internal==true. */ - bool allocated; /** \brief as data may also point to a matrix, this specifies the number of columns in this element (default: 1) */ size_t columns; /** \brief number of rows in this item */ size_t rows; + /** \brief iif \a storageType is \c StorageType::Vector, the data is actually save here and data contains a pointer to the data in datavec */ + QVector datavec; /** \brief memory format of the data in this item */ JKQTPDatastoreItemFormat dataformat; + /** \brief specifies whether the datastore manages the memory (\c true ) or whether the user application does this (\c false ) .*/ + StorageType storageType; + /** \brief Specifies whether memory for the data has been allocated. This is only used, when \c internal==true. */ + bool allocated; protected: /** \brief hidden default constructor */ JKQTPDatastoreItem(); @@ -1176,7 +1777,9 @@ class JKQTP_LIB_EXPORT JKQTPDatastoreItem { { return columns; } - /** \brief returns the data at the position (\a column, \a row ). The column index specifies the column inside THIS item, not the global column number. */ + /** \brief returns the data at the position (\a column, \a row ). + * + * \note The column index specifies the column inside THIS item, not the global column number. */ inline double get(size_t column, size_t row) { if (data!=nullptr) switch(dataformat) { case JKQTPDatastoreItemFormat::SingleColumn: @@ -1190,6 +1793,41 @@ class JKQTP_LIB_EXPORT JKQTPDatastoreItem { } + /** \brief returns a reference to the data at the position (\a column, \a row ). Throws an exception when the entry does not exist! + * + * \note The column index specifies the column inside THIS item, not the global column number. */ + inline double& at(size_t column, size_t row) { + if (data!=nullptr) { + switch(dataformat) { + case JKQTPDatastoreItemFormat::SingleColumn: + return data[row]; + case JKQTPDatastoreItemFormat::MatrixColumn: + return data[column*rows+row]; + case JKQTPDatastoreItemFormat::MatrixRow: + return data[row*columns+column]; + } + } + throw std::out_of_range("index does not exist in JKQTPDatastoreItem"); + } + + /** \brief returns a const reference to the data at the position (\a column, \a row ). Throws an exception when the entry does not exist! + * + * \note The column index specifies the column inside THIS item, not the global column number. */ + inline const double& at(size_t column, size_t row) const { + if (data!=nullptr) { + switch(dataformat) { + case JKQTPDatastoreItemFormat::SingleColumn: + return data[row]; + case JKQTPDatastoreItemFormat::MatrixColumn: + return data[column*rows+row]; + case JKQTPDatastoreItemFormat::MatrixRow: + return data[row*columns+column]; + } + } + throw std::out_of_range("index does not exist in JKQTPDatastoreItem"); + } + + /** \brief returns the data at the position (\a column, \a row ). The column index specifies the column inside THIS item, not the global column number. */ inline double* getPointer(size_t column, size_t row) { if (data!=nullptr) switch(dataformat) { @@ -1275,6 +1913,7 @@ class JKQTP_LIB_EXPORT JKQTPDatastoreItem { } return false; } + }; @@ -1330,6 +1969,27 @@ quint16 JKQTPColumn::calculateChecksum() const return qChecksum(reinterpret_cast(getPointer(0)), static_cast(getRows()*sizeof(double))); } +//////////////////////////////////////////////////////////////////////////////////////////////// +JKQTPColumn::iterator JKQTPColumn::begin() { + return JKQTPColumn::iterator(this, 0); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +JKQTPColumn::iterator JKQTPColumn::end() { + return JKQTPColumn::iterator(this, -1); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +JKQTPColumn::const_iterator JKQTPColumn::begin() const { + return JKQTPColumn::const_iterator(this, 0); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +JKQTPColumn::const_iterator JKQTPColumn::end() const { + return JKQTPColumn::const_iterator(this, -1); +} + + //////////////////////////////////////////////////////////////////////////////////////////////// inline double JKQTPColumn::getValue(size_t n) const { if (!datastore) return JKQTP_NAN; @@ -1345,6 +2005,20 @@ inline double JKQTPColumn::getValue(int n) const { return datastore->getItem(datastoreItem)->get(datastoreOffset, static_cast(n)); } +//////////////////////////////////////////////////////////////////////////////////////////////// +inline const double& JKQTPColumn::at(int n) const { + JKQTPASSERT(datastore && datastore->getItem(datastoreItem)); + JKQTPASSERT(n>=0); + return datastore->getItem(datastoreItem)->at(datastoreOffset, static_cast(n)); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +inline double& JKQTPColumn::at(int n) { + JKQTPASSERT(datastore && datastore->getItem(datastoreItem)); + JKQTPASSERT(n>=0); + return datastore->getItem(datastoreItem)->at(datastoreOffset, static_cast(n)); +} + //////////////////////////////////////////////////////////////////////////////////////////////// size_t JKQTPDatastore::getRows(size_t column) const { return columns.value(column).getRows(); @@ -1451,7 +2125,14 @@ void JKQTPDatastore::appendToColumn(size_t column, double value) template void JKQTPDatastore::appendFromContainerToColumn(size_t column, const TContainer &values) { - for(auto it=values.begin(); it!=values.end(); it++) { + appendToColumn(column, values.begin(), values.end()); +} + +//////////////////////////////////////////////////////////////////////////////////////////////// +template +inline void JKQTPDatastore::appendToColumn(size_t column, TIterator first, TIterator last) +{ + for(auto it=first; it!=last; it++) { appendToColumn(column, *it); } } diff --git a/lib/jkqtplotter/jkqtpelementsoverlay.cpp b/lib/jkqtplotter/jkqtpelementsoverlay.cpp index ae42fea915..bcbc4256d6 100644 --- a/lib/jkqtplotter/jkqtpelementsoverlay.cpp +++ b/lib/jkqtplotter/jkqtpelementsoverlay.cpp @@ -21,8 +21,8 @@ #include "jkqtplotter/jkqtpelementsoverlay.h" #include "jkqtplotter/jkqtpbaseplotter.h" -#include "jkqtcommon/jkqtptools.h" -#include "jkqtplottertools/jkqtpdrawingtools.h" +#include "jkqtplotter/jkqtptools.h" +#include "jkqtcommon/jkqtpdrawingtools.h" #include #include diff --git a/lib/jkqtplotter/jkqtpelementsoverlay.h b/lib/jkqtplotter/jkqtpelementsoverlay.h index 56f338f3c3..670c4044c7 100644 --- a/lib/jkqtplotter/jkqtpelementsoverlay.h +++ b/lib/jkqtplotter/jkqtpelementsoverlay.h @@ -22,7 +22,7 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtcommon/jkqtp_imexport.h" #include "jkqtplotter/jkqtpgraphsbasestylingmixins.h" diff --git a/lib/jkqtplotter/jkqtpgraphsbarchart.cpp b/lib/jkqtplotter/jkqtpgraphsbarchart.cpp index 1363733538..cda5049542 100644 --- a/lib/jkqtplotter/jkqtpgraphsbarchart.cpp +++ b/lib/jkqtplotter/jkqtpgraphsbarchart.cpp @@ -24,7 +24,7 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtplotter/jkqtpgraphsimage.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtplotter.h" diff --git a/lib/jkqtplotter/jkqtpgraphsbarchart.h b/lib/jkqtplotter/jkqtpgraphsbarchart.h index a9ed4a6f50..ae64ac2daa 100644 --- a/lib/jkqtplotter/jkqtpgraphsbarchart.h +++ b/lib/jkqtplotter/jkqtpgraphsbarchart.h @@ -20,9 +20,9 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtcommon/jkqtp_imexport.h" -#include "jkqtplottertools/jkqtpimagetools.h" +#include "jkqtplotter/jkqtpimagetools.h" #include "jkqtplotter/jkqtpgraphsbase.h" #include "jkqtplotter/jkqtpgraphsbaseerrors.h" #include "jkqtplotter/jkqtpgraphsbasestylingmixins.h" diff --git a/lib/jkqtplotter/jkqtpgraphsbase.cpp b/lib/jkqtplotter/jkqtpgraphsbase.cpp index 496f3b6f30..159a25fefb 100644 --- a/lib/jkqtplotter/jkqtpgraphsbase.cpp +++ b/lib/jkqtplotter/jkqtpgraphsbase.cpp @@ -24,7 +24,7 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtplotter/jkqtpgraphsimage.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtplotter.h" @@ -167,11 +167,11 @@ QString JKQTPPlotElement::formatHitTestDefaultLabel(double x, double y, int inde if (errgx->getXErrorColumn()>=0) { if (errgx->getXErrorColumnLower()>=0) { xerrstr=QString("\\:+%1\\:-%2") - .arg(QString::fromStdString(jkqtp_floattolatexstr(datastore->get(errgx->getXErrorColumn(),static_cast(index)), 3))) - .arg(QString::fromStdString(jkqtp_floattolatexstr(datastore->get(errgx->getXErrorColumnLower(),static_cast(index)), 3))); + .arg(jkqtp_floattolatexqstr(datastore->get(errgx->getXErrorColumn(),static_cast(index)), 3)) + .arg(jkqtp_floattolatexqstr(datastore->get(errgx->getXErrorColumnLower(),static_cast(index)), 3)); } else { xerrstr=QString("{\\:}{\\pm}%1") - .arg(QString::fromStdString(jkqtp_floattolatexstr(datastore->get(errgx->getXErrorColumn(),static_cast(index)), 3))); + .arg(jkqtp_floattolatexqstr(datastore->get(errgx->getXErrorColumn(),static_cast(index)), 3)); } } } @@ -183,15 +183,15 @@ QString JKQTPPlotElement::formatHitTestDefaultLabel(double x, double y, int inde if (errgy->getYErrorColumn()>=0) { if (errgy->getYErrorColumnLower()>=0) { yerrstr=QString("\\:+%1\\:-%2") - .arg(QString::fromStdString(jkqtp_floattolatexstr(datastore->get(errgy->getYErrorColumn(),static_cast(index)), 3))) - .arg(QString::fromStdString(jkqtp_floattolatexstr(datastore->get(errgy->getYErrorColumnLower(),static_cast(index)), 3))); + .arg(jkqtp_floattolatexqstr(datastore->get(errgy->getYErrorColumn(),static_cast(index)), 3)) + .arg(jkqtp_floattolatexqstr(datastore->get(errgy->getYErrorColumnLower(),static_cast(index)), 3)); } else { yerrstr=QString("{\\:}{\\pm}%1") - .arg(QString::fromStdString(jkqtp_floattolatexstr(datastore->get(errgy->getYErrorColumn(),static_cast(index)), 3))); + .arg(jkqtp_floattolatexqstr(datastore->get(errgy->getYErrorColumn(),static_cast(index)), 3)); } } } - return QString("\\ensuremath{\\left[{\\:}%1%3{\\;},{\\;}%2%4{\\:}\\right]}").arg(QString::fromStdString(jkqtp_floattolatexstr(x, 3))).arg(QString::fromStdString(jkqtp_floattolatexstr(y, 3))).arg(xerrstr).arg(yerrstr); + return QString("\\ensuremath{\\left[{\\:}%1%3{\\;},{\\;}%2%4{\\:}\\right]}").arg(jkqtp_floattolatexqstr(x, 3)).arg(jkqtp_floattolatexqstr(y, 3)).arg(xerrstr).arg(yerrstr); } @@ -506,6 +506,7 @@ JKQTPSingleColumnGraph::JKQTPSingleColumnGraph(JKQTPlotter *parent): void JKQTPSingleColumnGraph::setDataColumn(int __value) { this->dataColumn = __value; + if (this->title.size()==0 && parent && __value>=0) this->title=parent->getDatastore()->getColumnName(static_cast(__value)); } int JKQTPSingleColumnGraph::getDataColumn() const @@ -515,6 +516,7 @@ int JKQTPSingleColumnGraph::getDataColumn() const void JKQTPSingleColumnGraph::setDataColumn(size_t __value) { this->dataColumn = static_cast(__value); + if (this->title.size()==0 && parent) this->title=parent->getDatastore()->getColumnName(__value); } void JKQTPSingleColumnGraph::setDataSortOrder(JKQTPSingleColumnGraph::DataSortOrder __value) diff --git a/lib/jkqtplotter/jkqtpgraphsbase.h b/lib/jkqtplotter/jkqtpgraphsbase.h index d02ed15c8d..7cffdfdee6 100644 --- a/lib/jkqtplotter/jkqtpgraphsbase.h +++ b/lib/jkqtplotter/jkqtpgraphsbase.h @@ -23,9 +23,9 @@ #include #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtpbaseplotter.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtcommon/jkqtp_imexport.h" -#include "jkqtplottertools/jkqtpimagetools.h" +#include "jkqtplotter/jkqtpimagetools.h" #ifndef JKQTPGRAPHSBASE_H #define JKQTPGRAPHSBASE_H diff --git a/lib/jkqtplotter/jkqtpgraphsbaseerrors.cpp b/lib/jkqtplotter/jkqtpgraphsbaseerrors.cpp index c08bb2b4e1..a5cc6007e4 100644 --- a/lib/jkqtplotter/jkqtpgraphsbaseerrors.cpp +++ b/lib/jkqtplotter/jkqtpgraphsbaseerrors.cpp @@ -24,7 +24,7 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtplotter/jkqtpgraphsimage.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtplotter.h" diff --git a/lib/jkqtplotter/jkqtpgraphsbaseerrors.h b/lib/jkqtplotter/jkqtpgraphsbaseerrors.h index 34a32391f5..ce64c71089 100644 --- a/lib/jkqtplotter/jkqtpgraphsbaseerrors.h +++ b/lib/jkqtplotter/jkqtpgraphsbaseerrors.h @@ -24,9 +24,9 @@ #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtpbaseplotter.h" #include "jkqtplotter/jkqtpgraphsbase.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtcommon/jkqtp_imexport.h" -#include "jkqtplottertools/jkqtpimagetools.h" +#include "jkqtplotter/jkqtpimagetools.h" #ifndef JKQTPGRAPHSBASEERROR_H #define JKQTPGRAPHSBASEERROR_H diff --git a/lib/jkqtplotter/jkqtpgraphsbasestylingmixins.h b/lib/jkqtplotter/jkqtpgraphsbasestylingmixins.h index e2fd696b94..84bfce9c16 100644 --- a/lib/jkqtplotter/jkqtpgraphsbasestylingmixins.h +++ b/lib/jkqtplotter/jkqtpgraphsbasestylingmixins.h @@ -22,9 +22,9 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtcommon/jkqtp_imexport.h" -#include "jkqtplottertools/jkqtpdrawingtools.h" +#include "jkqtcommon/jkqtpdrawingtools.h" #ifndef jkqtpgraphsbasestylingmixins_H diff --git a/lib/jkqtplotter/jkqtpgraphsboxplot.cpp b/lib/jkqtplotter/jkqtpgraphsboxplot.cpp index e49b369055..8db59bafe4 100644 --- a/lib/jkqtplotter/jkqtpgraphsboxplot.cpp +++ b/lib/jkqtplotter/jkqtpgraphsboxplot.cpp @@ -24,7 +24,7 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtplotter/jkqtpgraphsimage.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtplotter.h" @@ -50,6 +50,7 @@ JKQTPBoxplotVerticalGraph::JKQTPBoxplotVerticalGraph(JKQTBasePlotter* parent): sortData=Unsorted; initBoxplotStyle(parent, parentPlotStyle); + setMeanSymbolType(JKQTPPlus); } @@ -123,19 +124,19 @@ void JKQTPBoxplotVerticalGraph::draw(JKQTPEnhancedPainter& painter) { QStringList labelValues, labelNames; int labMedian=-1, labMean=-1, labMin=-1, labMax=-1, labQ25=-1, labQ75=-1; labelNames<<"pos"; - labelValues<=0 && JKQTPIsOKFloat(minv)) { labelNames<<"\\min"; labelValues<=0 && JKQTPIsOKFloat(p25v)) { labelNames<<"q_{25}"; labelValues<=0 && JKQTPIsOKFloat(minv)) { labelNames<<"\\min"; labelValues<=0 && JKQTPIsOKFloat(p25v)) { labelNames<<"q_{25}"; labelValues<=0 && JKQTPIsOKFloat(medianv)) { if (medianConfidenceColumn>=0 && JKQTPIsOKFloat(medConf)) { - labelNames<<"\\median"; labelValues<<(QString::fromStdString(jkqtp_floattolatexstr(medianv, 3))+"\\:{\\pm}\\:"+QString::fromStdString(jkqtp_floattolatexstr(medConf, 3))); labMedian=labelValues.size()-1; + labelNames<<"\\median"; labelValues<<(jkqtp_floattolatexqstr(medianv, 3)+"\\:{\\pm}\\:"+jkqtp_floattolatexqstr(medConf, 3)); labMedian=labelValues.size()-1; } else { - labelNames<<"\\median"; labelValues<=0 && JKQTPIsOKFloat(meanv)) { labelNames<<"\\mu"; labelValues<=0 && JKQTPIsOKFloat(p75v)) { labelNames<<"q_{75}"; labelValues<=0 && JKQTPIsOKFloat(maxv)) { labelNames<<"\\max"; labelValues<=0 && JKQTPIsOKFloat(meanv)) { labelNames<<"\\mu"; labelValues<=0 && JKQTPIsOKFloat(p75v)) { labelNames<<"q_{75}"; labelValues<=0 && JKQTPIsOKFloat(maxv)) { labelNames<<"\\max"; labelValues<=0 && JKQTPIsOKFloat(minv)) { labelNames<<"\\min"; labelValues<=0 && JKQTPIsOKFloat(p25v)) { labelNames<<"q_{25}"; labelValues<=0 && JKQTPIsOKFloat(minv)) { labelNames<<"\\min"; labelValues<=0 && JKQTPIsOKFloat(p25v)) { labelNames<<"q_{25}"; labelValues<=0 && JKQTPIsOKFloat(medianv)) { if (medianConfidenceColumn>=0 && JKQTPIsOKFloat(medConf)) { - labelNames<<"\\median"; labelValues<<(QString::fromStdString(jkqtp_floattolatexstr(medianv, 3))+"\\:{\\pm}\\:"+QString::fromStdString(jkqtp_floattolatexstr(medConf, 3))); labMedian=labelValues.size()-1; + labelNames<<"\\median"; labelValues<<(jkqtp_floattolatexqstr(medianv, 3)+"\\:{\\pm}\\:"+jkqtp_floattolatexqstr(medConf, 3)); labMedian=labelValues.size()-1; } else { - labelNames<<"\\median"; labelValues<=0 && JKQTPIsOKFloat(meanv)) { labelNames<<"\\mu"; labelValues<=0 && JKQTPIsOKFloat(p75v)) { labelNames<<"q_{75}"; labelValues<=0 && JKQTPIsOKFloat(maxv)) { labelNames<<"\\max"; labelValues<=0 && JKQTPIsOKFloat(meanv)) { labelNames<<"\\mu"; labelValues<=0 && JKQTPIsOKFloat(p75v)) { labelNames<<"q_{75}"; labelValues<=0 && JKQTPIsOKFloat(maxv)) { labelNames<<"\\max"; labelValues<pt2px(painter,getBoxWidthAbsolute()); double xma=x+w/2.0; @@ -1063,6 +1065,11 @@ QColor JKQTPBoxplotVerticalElement::getKeyLabelColor() const { return getLineColor(); } +void JKQTPBoxplotVerticalElement::setColor(QColor c) +{ + setBoxplotColor(c, getParent()); +} + @@ -1172,19 +1179,19 @@ void JKQTPBoxplotHorizontalElement::draw(JKQTPEnhancedPainter& painter) { QStringList labelValues, labelNames; int labMedian=-1, labMean=-1, labMin=-1, labMax=-1, labQ25=-1, labQ75=-1; labelNames<<"pos"; - labelValues<pt2px(painter,getBoxWidthAbsolute()); double yma=y+w/2.0; diff --git a/lib/jkqtplotter/jkqtpgraphsboxplot.h b/lib/jkqtplotter/jkqtpgraphsboxplot.h index f8a226b4af..0c2e14e052 100644 --- a/lib/jkqtplotter/jkqtpgraphsboxplot.h +++ b/lib/jkqtplotter/jkqtpgraphsboxplot.h @@ -21,9 +21,9 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtcommon/jkqtp_imexport.h" -#include "jkqtplottertools/jkqtpimagetools.h" +#include "jkqtplotter/jkqtpimagetools.h" #include "jkqtplotter/jkqtpgraphsbase.h" #include "jkqtplotter/jkqtpgraphsboxplotstylingmixins.h" #include "jkqtplotter/jkqtpgraphsbasestylingmixins.h" @@ -102,7 +102,7 @@ class JKQTP_LIB_EXPORT JKQTPBoxplotVerticalGraph: public JKQTPGraph, public JKQT Q_OBJECT public: - /** \brief Sortierordnung für Daten in einem JKQTPBoxplotVerticalGraph (oder seinen Kindern) */ + /** \brief Sort order in a JKQTPBoxplotVerticalGraph (or one of its child classes) */ enum DataSortOrder { Unsorted=0, Sorted=1 @@ -321,6 +321,8 @@ class JKQTP_LIB_EXPORT JKQTPBoxplotVerticalElement: public JKQTPPlotObject, publ virtual void drawKeyMarker(JKQTPEnhancedPainter& painter, QRectF& rect) override; /** \brief returns the color to be used for the key label */ virtual QColor getKeyLabelColor() const override; + /*! \brief set the color of the graph (colors all elements, based on the given color \a c )*/ + virtual void setColor(QColor c); /** \brief get the maximum and minimum x-value of the graph diff --git a/lib/jkqtplotter/jkqtpgraphsboxplotstylingmixins.cpp b/lib/jkqtplotter/jkqtpgraphsboxplotstylingmixins.cpp index 68c84b5ce1..9919391b48 100644 --- a/lib/jkqtplotter/jkqtpgraphsboxplotstylingmixins.cpp +++ b/lib/jkqtplotter/jkqtpgraphsboxplotstylingmixins.cpp @@ -24,7 +24,7 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtplotter/jkqtpgraphsimage.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtplotter.h" @@ -83,6 +83,7 @@ void JKQTPGraphBoxplotStyleMixin::initBoxplotStyle(JKQTBasePlotter *parent, int setWhiskerLineColor(getLineColor()); setWhiskerCapLineColor(getLineColor()); setMedianLineColor(getLineColor()); + setMeanSymbolType(JKQTPPlus); if (m_meanSymbolSize>0) { boxWidthAbsolute=m_meanSymbolSize*3.0; diff --git a/lib/jkqtplotter/jkqtpgraphsboxplotstylingmixins.h b/lib/jkqtplotter/jkqtpgraphsboxplotstylingmixins.h index 2bf42f5959..a9b0fe394f 100644 --- a/lib/jkqtplotter/jkqtpgraphsboxplotstylingmixins.h +++ b/lib/jkqtplotter/jkqtpgraphsboxplotstylingmixins.h @@ -20,7 +20,7 @@ #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtcommon/jkqtp_imexport.h" #include "jkqtplotter/jkqtpgraphsbase.h" #include "jkqtplotter/jkqtpgraphsbasestylingmixins.h" diff --git a/lib/jkqtplotter/jkqtpgraphscontour.cpp b/lib/jkqtplotter/jkqtpgraphscontour.cpp index 725160a55f..66c20820f7 100644 --- a/lib/jkqtplotter/jkqtpgraphscontour.cpp +++ b/lib/jkqtplotter/jkqtpgraphscontour.cpp @@ -20,9 +20,9 @@ #include "jkqtplotter/jkqtpgraphscontour.h" #include "jkqtplotter/jkqtpbaseplotter.h" -#include "jkqtplottertools/jkqtpimagetools.h" -#include "jkqtcommon/jkqtptools.h" -#include "jkqtplottertools/jkqtpenhancedpainter.h" +#include "jkqtplotter/jkqtpimagetools.h" +#include "jkqtplotter/jkqtptools.h" +#include "jkqtcommon/jkqtpenhancedpainter.h" #include "jkqtplotter/jkqtplotter.h" #include "jkqtpgraphscontour.h" #include diff --git a/lib/jkqtplotter/jkqtpgraphscontour.h b/lib/jkqtplotter/jkqtpgraphscontour.h index cb5df34c34..5128674558 100644 --- a/lib/jkqtplotter/jkqtpgraphscontour.h +++ b/lib/jkqtplotter/jkqtpgraphscontour.h @@ -28,12 +28,12 @@ #include #include #include "jkqtplotter/jkqtpgraphsscatter.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtpgraphsimage.h" #include "jkqtplotter/jkqtpgraphsbasestylingmixins.h" #include "jkqtcommon/jkqtp_imexport.h" -#include "jkqtplottertools/jkqtpimagetools.h" +#include "jkqtplotter/jkqtpimagetools.h" diff --git a/lib/jkqtplotter/jkqtpgraphsevaluatedfunction.cpp b/lib/jkqtplotter/jkqtpgraphsevaluatedfunction.cpp index b31c6adc6f..3d61eeba2e 100644 --- a/lib/jkqtplotter/jkqtpgraphsevaluatedfunction.cpp +++ b/lib/jkqtplotter/jkqtpgraphsevaluatedfunction.cpp @@ -24,7 +24,7 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtplotter/jkqtpgraphsimage.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtplotter.h" @@ -82,6 +82,46 @@ JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(JKQTPlotter* parent): } +JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title_, JKQTBasePlotter *parent): + JKQTPXFunctionLineGraph(parent) +{ + title=title_; + plotFunction=jkqtpPlotFunctionType(); + simplePlotFunction=f; + functionType=SpecialFunction::UserFunction; + clearData(); +} + +JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title_, JKQTPlotter *parent): + JKQTPXFunctionLineGraph(parent) +{ + title=title_; + plotFunction=jkqtpPlotFunctionType(); + simplePlotFunction=f; + functionType=SpecialFunction::UserFunction; + clearData(); +} + +JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title_, JKQTBasePlotter *parent): + JKQTPXFunctionLineGraph(parent) +{ + title=title_; + plotFunction=jkqtpPlotFunctionType(); + simplePlotFunction=std::move(f); + functionType=SpecialFunction::UserFunction; + clearData(); +} + +JKQTPXFunctionLineGraph::JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title_, JKQTPlotter *parent): + JKQTPXFunctionLineGraph(parent) +{ + title=title_; + plotFunction=jkqtpPlotFunctionType(); + simplePlotFunction=std::move(f); + functionType=SpecialFunction::UserFunction; + clearData(); +} + JKQTPXFunctionLineGraph::~JKQTPXFunctionLineGraph() { clearData(); @@ -519,6 +559,16 @@ JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(JKQTBasePlotter *parent):JKQTPX JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(JKQTPlotter *parent):JKQTPYFunctionLineGraph(parent->getPlotter()) {} +JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title, JKQTBasePlotter *parent):JKQTPXFunctionLineGraph(f, title, parent) {} + +JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(const jkqtpSimplePlotFunctionType &f, const QString &title, JKQTPlotter *parent):JKQTPXFunctionLineGraph(f, title, parent) {} + + +JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title, JKQTBasePlotter *parent):JKQTPXFunctionLineGraph(std::move(f), title, parent) {} + + +JKQTPYFunctionLineGraph::JKQTPYFunctionLineGraph(jkqtpSimplePlotFunctionType &&f, const QString &title, JKQTPlotter *parent):JKQTPXFunctionLineGraph(std::move(f), title, parent) {} + void JKQTPYFunctionLineGraph::draw(JKQTPEnhancedPainter& painter) { #ifdef JKQTBP_AUTOTIMER JKQTPAutoOutputTimer jkaaot("JKQTPYFunctionLineGraph::draw"); diff --git a/lib/jkqtplotter/jkqtpgraphsevaluatedfunction.h b/lib/jkqtplotter/jkqtpgraphsevaluatedfunction.h index d8ff8d05fa..e98f40887e 100644 --- a/lib/jkqtplotter/jkqtpgraphsevaluatedfunction.h +++ b/lib/jkqtplotter/jkqtpgraphsevaluatedfunction.h @@ -84,6 +84,14 @@ class JKQTP_LIB_EXPORT JKQTPXFunctionLineGraph: public JKQTPGraph, public JKQTPG /** \brief class constructor */ JKQTPXFunctionLineGraph(JKQTPlotter* parent); + /** \brief class constructor */ + JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionType & f, const QString& title, JKQTBasePlotter* parent=nullptr); + /** \brief class constructor */ + JKQTPXFunctionLineGraph(const jkqtpSimplePlotFunctionType & f, const QString& title, JKQTPlotter* parent); + /** \brief class constructor */ + JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTBasePlotter* parent=nullptr); + /** \brief class constructor */ + JKQTPXFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTPlotter* parent); /** \brief class destructor */ virtual ~JKQTPXFunctionLineGraph() override; @@ -392,6 +400,14 @@ class JKQTP_LIB_EXPORT JKQTPYFunctionLineGraph: public JKQTPXFunctionLineGraph { JKQTPYFunctionLineGraph(JKQTBasePlotter* parent=nullptr); /** \brief class constructor */ JKQTPYFunctionLineGraph(JKQTPlotter* parent); + /** \brief class constructor */ + JKQTPYFunctionLineGraph(const jkqtpSimplePlotFunctionType & f, const QString& title, JKQTBasePlotter* parent=nullptr); + /** \brief class constructor */ + JKQTPYFunctionLineGraph(const jkqtpSimplePlotFunctionType & f, const QString& title, JKQTPlotter* parent); + /** \brief class constructor */ + JKQTPYFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTBasePlotter* parent=nullptr); + /** \brief class constructor */ + JKQTPYFunctionLineGraph(jkqtpSimplePlotFunctionType && f, const QString& title, JKQTPlotter* parent); /** \brief plots the graph to the plotter object specified as parent */ virtual void draw(JKQTPEnhancedPainter& painter) override; diff --git a/lib/jkqtplotter/jkqtpgraphsfilledcurve.cpp b/lib/jkqtplotter/jkqtpgraphsfilledcurve.cpp index d95fb3346d..68df6fcd87 100644 --- a/lib/jkqtplotter/jkqtpgraphsfilledcurve.cpp +++ b/lib/jkqtplotter/jkqtpgraphsfilledcurve.cpp @@ -24,7 +24,7 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtplotter/jkqtpgraphsimage.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtplotter.h" diff --git a/lib/jkqtplotter/jkqtpgraphsgeometric.cpp b/lib/jkqtplotter/jkqtpgraphsgeometric.cpp index f98dd51f15..df190b1c6c 100644 --- a/lib/jkqtplotter/jkqtpgraphsgeometric.cpp +++ b/lib/jkqtplotter/jkqtpgraphsgeometric.cpp @@ -515,7 +515,7 @@ void JKQTPGeoInfiniteLine::draw(JKQTPEnhancedPainter& painter) { if (l.length()>0) { painter.drawLine(l); addHitTestData(x, y, formatHitTestDefaultLabel(x,y)+ - QString(", \\ensuremath{\\mathrm{\\mathbf{d}}y/\\mathrm{\\mathbf{d}}x\\;=\\;%1/%2\\;=\\;%3\\;=\\;%4\\degree}").arg(QString::fromStdString(jkqtp_floattolatexstr(dy, 3))).arg(QString::fromStdString(jkqtp_floattolatexstr(dx, 3))).arg(QString::fromStdString(jkqtp_floattolatexstr(dy/dx, 3))).arg(QString::fromStdString(jkqtp_floattolatexstr(atan2(dy,dx), 1)))); + QString(", \\ensuremath{\\mathrm{\\mathbf{d}}y/\\mathrm{\\mathbf{d}}x\\;=\\;%1/%2\\;=\\;%3\\;=\\;%4\\degree}").arg(jkqtp_floattolatexqstr(dy, 3)).arg(jkqtp_floattolatexqstr(dx, 3)).arg(jkqtp_floattolatexqstr(dy/dx, 3)).arg(jkqtp_floattolatexqstr(atan2(dy,dx), 1))); addHitTestData(x1, y1); addHitTestData(x2, y2); } diff --git a/lib/jkqtplotter/jkqtpgraphsgeometric.h b/lib/jkqtplotter/jkqtpgraphsgeometric.h index 3e59473140..c5c65ae274 100644 --- a/lib/jkqtplotter/jkqtpgraphsgeometric.h +++ b/lib/jkqtplotter/jkqtpgraphsgeometric.h @@ -23,7 +23,7 @@ #include #include "jkqtplotter/jkqtpgraphsscatter.h" #include "jkqtplotter/jkqtpgraphsbasestylingmixins.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtcommon/jkqtp_imexport.h" #include "jkqtmathtext/jkqtmathtext.h" diff --git a/lib/jkqtplotter/jkqtpgraphsimage.cpp b/lib/jkqtplotter/jkqtpgraphsimage.cpp index 2568c3477c..f9f7b02242 100644 --- a/lib/jkqtplotter/jkqtpgraphsimage.cpp +++ b/lib/jkqtplotter/jkqtpgraphsimage.cpp @@ -20,9 +20,9 @@ #include "jkqtplotter/jkqtpgraphsimage.h" #include "jkqtplotter/jkqtpbaseplotter.h" -#include "jkqtplottertools/jkqtpimagetools.h" -#include "jkqtcommon/jkqtptools.h" -#include "jkqtplottertools/jkqtpenhancedpainter.h" +#include "jkqtplotter/jkqtpimagetools.h" +#include "jkqtplotter/jkqtptools.h" +#include "jkqtcommon/jkqtpenhancedpainter.h" #include "jkqtplotter/jkqtplotter.h" #include #include diff --git a/lib/jkqtplotter/jkqtpgraphsimage.h b/lib/jkqtplotter/jkqtpgraphsimage.h index 6a820ea3fc..61b91c160e 100644 --- a/lib/jkqtplotter/jkqtpgraphsimage.h +++ b/lib/jkqtplotter/jkqtpgraphsimage.h @@ -27,10 +27,10 @@ #include #include #include "jkqtplotter/jkqtpgraphsscatter.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtcommon/jkqtp_imexport.h" -#include "jkqtplottertools/jkqtpimagetools.h" +#include "jkqtplotter/jkqtpimagetools.h" diff --git a/lib/jkqtplotter/jkqtpgraphsimageoverlays.cpp b/lib/jkqtplotter/jkqtpgraphsimageoverlays.cpp index b6c00805aa..c53038646a 100644 --- a/lib/jkqtplotter/jkqtpgraphsimageoverlays.cpp +++ b/lib/jkqtplotter/jkqtpgraphsimageoverlays.cpp @@ -20,9 +20,9 @@ #include "jkqtplotter/jkqtpgraphsimageoverlays.h" #include "jkqtplotter/jkqtpbaseplotter.h" -#include "jkqtplottertools/jkqtpimagetools.h" -#include "jkqtcommon/jkqtptools.h" -#include "jkqtplottertools/jkqtpenhancedpainter.h" +#include "jkqtplotter/jkqtpimagetools.h" +#include "jkqtplotter/jkqtptools.h" +#include "jkqtcommon/jkqtpenhancedpainter.h" #include "jkqtplotter/jkqtplotter.h" #include #include diff --git a/lib/jkqtplotter/jkqtpgraphsimageoverlays.h b/lib/jkqtplotter/jkqtpgraphsimageoverlays.h index d5d9a8bb32..a3d3f5d2d2 100644 --- a/lib/jkqtplotter/jkqtpgraphsimageoverlays.h +++ b/lib/jkqtplotter/jkqtpgraphsimageoverlays.h @@ -27,11 +27,11 @@ #include #include #include "jkqtplotter/jkqtpgraphsscatter.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtpgraphsimage.h" #include "jkqtcommon/jkqtp_imexport.h" -#include "jkqtplottertools/jkqtpimagetools.h" +#include "jkqtplotter/jkqtpimagetools.h" diff --git a/lib/jkqtplotter/jkqtpgraphsimagergb.cpp b/lib/jkqtplotter/jkqtpgraphsimagergb.cpp index 11ba38c006..79a1625220 100644 --- a/lib/jkqtplotter/jkqtpgraphsimagergb.cpp +++ b/lib/jkqtplotter/jkqtpgraphsimagergb.cpp @@ -20,9 +20,9 @@ #include "jkqtplotter/jkqtpgraphsimagergb.h" #include "jkqtplotter/jkqtpbaseplotter.h" -#include "jkqtplottertools/jkqtpimagetools.h" -#include "jkqtcommon/jkqtptools.h" -#include "jkqtplottertools/jkqtpenhancedpainter.h" +#include "jkqtplotter/jkqtpimagetools.h" +#include "jkqtplotter/jkqtptools.h" +#include "jkqtcommon/jkqtpenhancedpainter.h" #include "jkqtplotter/jkqtplotter.h" #include #include diff --git a/lib/jkqtplotter/jkqtpgraphsimagergb.h b/lib/jkqtplotter/jkqtpgraphsimagergb.h index e803e2eb75..a6d832c29f 100644 --- a/lib/jkqtplotter/jkqtpgraphsimagergb.h +++ b/lib/jkqtplotter/jkqtpgraphsimagergb.h @@ -27,10 +27,10 @@ #include #include #include "jkqtplotter/jkqtpgraphsimage.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtcommon/jkqtp_imexport.h" -#include "jkqtplottertools/jkqtpimagetools.h" +#include "jkqtplotter/jkqtpimagetools.h" diff --git a/lib/jkqtplotter/jkqtpgraphsimpulses.cpp b/lib/jkqtplotter/jkqtpgraphsimpulses.cpp index 96204f0b79..8246aab2de 100644 --- a/lib/jkqtplotter/jkqtpgraphsimpulses.cpp +++ b/lib/jkqtplotter/jkqtpgraphsimpulses.cpp @@ -24,7 +24,7 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtplotter/jkqtpgraphsimage.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtplotter.h" diff --git a/lib/jkqtplotter/jkqtpgraphsparsedfunction.cpp b/lib/jkqtplotter/jkqtpgraphsparsedfunction.cpp index 85cc4d1c40..230f23ba0a 100644 --- a/lib/jkqtplotter/jkqtpgraphsparsedfunction.cpp +++ b/lib/jkqtplotter/jkqtpgraphsparsedfunction.cpp @@ -21,7 +21,7 @@ #include "jkqtplotter/jkqtpgraphsscatter.h" #include "jkqtplotter/jkqtpbaseplotter.h" #include "jkqtplotter/jkqtplotter.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include #include #include diff --git a/lib/jkqtplotter/jkqtpgraphsparsedfunction.h b/lib/jkqtplotter/jkqtpgraphsparsedfunction.h index 7b714028f1..c7409b98c6 100644 --- a/lib/jkqtplotter/jkqtpgraphsparsedfunction.h +++ b/lib/jkqtplotter/jkqtpgraphsparsedfunction.h @@ -24,8 +24,8 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" -#include "jkqtplottertools/jkqtpmathparser.h" +#include "jkqtplotter/jkqtptools.h" +#include "jkqtcommon/jkqtpmathparser.h" #include "jkqtcommon/jkqtp_imexport.h" #include "jkqtplotter/jkqtpgraphsevaluatedfunction.h" diff --git a/lib/jkqtplotter/jkqtpgraphspeakstream.cpp b/lib/jkqtplotter/jkqtpgraphspeakstream.cpp index d6c36c1432..79ee24037f 100644 --- a/lib/jkqtplotter/jkqtpgraphspeakstream.cpp +++ b/lib/jkqtplotter/jkqtpgraphspeakstream.cpp @@ -24,10 +24,10 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtplotter.h" -#include "jkqtplottertools/jkqtpdrawingtools.h" +#include "jkqtcommon/jkqtpdrawingtools.h" #define SmallestGreaterZeroCompare_xvsgz() if ((xvsgz>10.0*DBL_MIN)&&((smallestGreaterZero<10.0*DBL_MIN) || (xvsgz #include #include -#include "jkqtcommon/jkqtptools.h" -#include "jkqtplottertools/jkqtpimagetools.h" +#include "jkqtplotter/jkqtptools.h" +#include "jkqtplotter/jkqtpimagetools.h" #include "jkqtplotter/jkqtpgraphsimage.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtplotter.h" diff --git a/lib/jkqtplotter/jkqtpgraphsrange.h b/lib/jkqtplotter/jkqtpgraphsrange.h index 56573b24ab..a7bbca98ad 100644 --- a/lib/jkqtplotter/jkqtpgraphsrange.h +++ b/lib/jkqtplotter/jkqtpgraphsrange.h @@ -21,11 +21,11 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtcommon/jkqtp_imexport.h" -#include "jkqtplottertools/jkqtpdrawingtools.h" +#include "jkqtcommon/jkqtpdrawingtools.h" #include "jkqtplotter/jkqtpgraphsbase.h" -#include "jkqtplottertools/jkqtpenhancedpainter.h" +#include "jkqtcommon/jkqtpenhancedpainter.h" #include "jkqtplotter/jkqtpgraphsbaseerrors.h" #include "jkqtplotter/jkqtpgraphsbasestylingmixins.h" #ifndef jkqtpgraphsrange_H @@ -36,7 +36,7 @@ class JKQTBasePlotter; class JKQTPlotter; class JKQTPCoordinateAxis; class JKQTPDatastore; -//class JKQTPColorPaletteTools; +//class JKQTPColorPaletteStyleAndToolsMixin; diff --git a/lib/jkqtplotter/jkqtpgraphsscatter.cpp b/lib/jkqtplotter/jkqtpgraphsscatter.cpp index 6d621bfc5d..0fb3a97be8 100644 --- a/lib/jkqtplotter/jkqtpgraphsscatter.cpp +++ b/lib/jkqtplotter/jkqtpgraphsscatter.cpp @@ -24,8 +24,8 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" -#include "jkqtplottertools/jkqtpimagetools.h" +#include "jkqtplotter/jkqtptools.h" +#include "jkqtplotter/jkqtpimagetools.h" #include "jkqtplotter/jkqtpgraphsimage.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtplotter.h" @@ -311,7 +311,7 @@ void JKQTPXYLineErrorGraph::drawErrorsBefore(JKQTPEnhancedPainter &painter) JKQTPXYParametrizedScatterGraph::JKQTPXYParametrizedScatterGraph(JKQTBasePlotter *parent): JKQTPXYLineGraph(parent), - JKQTPColorPaletteTools(parent) + JKQTPColorPaletteStyleAndToolsMixin(parent) { sizeColumn=-1; colorColumn=-1; @@ -808,15 +808,6 @@ bool JKQTPXYParametrizedScatterGraph::usesColumn(int c) const return (c==colorColumn) || (c==sizeColumn) || (c==symbolColumn) || (c==linewidthColumn) || JKQTPXYLineGraph::usesColumn(c); } -double JKQTPXYParametrizedScatterGraph::getInternalDataMin() const -{ - return 0; -} - -double JKQTPXYParametrizedScatterGraph::getInternalDataMax() const -{ - return 0; -} double JKQTPXYParametrizedScatterGraph::getLocalSymbolSize(int i) { diff --git a/lib/jkqtplotter/jkqtpgraphsscatter.h b/lib/jkqtplotter/jkqtpgraphsscatter.h index 3dab4a0966..626d10a56d 100644 --- a/lib/jkqtplotter/jkqtpgraphsscatter.h +++ b/lib/jkqtplotter/jkqtpgraphsscatter.h @@ -22,11 +22,11 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtcommon/jkqtp_imexport.h" -#include "jkqtplottertools/jkqtpdrawingtools.h" +#include "jkqtcommon/jkqtpdrawingtools.h" #include "jkqtplotter/jkqtpgraphsbase.h" -#include "jkqtplottertools/jkqtpenhancedpainter.h" +#include "jkqtcommon/jkqtpenhancedpainter.h" #include "jkqtplotter/jkqtpgraphsbaseerrors.h" #include "jkqtplotter/jkqtpgraphsrange.h" #include "jkqtplotter/jkqtpgraphsbasestylingmixins.h" @@ -39,7 +39,7 @@ class JKQTBasePlotter; class JKQTPlotter; class JKQTPCoordinateAxis; class JKQTPDatastore; -//class JKQTPColorPaletteTools; +//class JKQTPColorPaletteStyleAndToolsMixin; @@ -111,7 +111,7 @@ class JKQTP_LIB_EXPORT JKQTPXYLineGraph: public JKQTPXYGraph, public JKQTPGraphL \see JKQTPXYParametrizedErrorScatterGraph, \ref JKQTPlotterParamScatter , \ref JKQTPlotterParamScatterImage */ -class JKQTP_LIB_EXPORT JKQTPXYParametrizedScatterGraph: public JKQTPXYLineGraph, public JKQTPColorPaletteTools { +class JKQTP_LIB_EXPORT JKQTPXYParametrizedScatterGraph: public JKQTPXYLineGraph, public JKQTPColorPaletteStyleAndToolsMixin { Q_OBJECT public: /** \brief functor, which converts the value of the symbol column (at a location x,y) into a JKQTPGraphSymbols */ @@ -301,9 +301,6 @@ class JKQTP_LIB_EXPORT JKQTPXYParametrizedScatterGraph: public JKQTPXYLineGraph, /** \copydoc JKQTPGraph::usesColumn() */ virtual bool usesColumn(int c) const override; - - virtual double getInternalDataMin() const override; - virtual double getInternalDataMax() const override; protected: /** \brief this column contains the symbol size in pt */ int sizeColumn; diff --git a/lib/jkqtplotter/jkqtpgraphssinglecolumnsymbols.cpp b/lib/jkqtplotter/jkqtpgraphssinglecolumnsymbols.cpp index 4a120bc1ac..93ae9adee9 100644 --- a/lib/jkqtplotter/jkqtpgraphssinglecolumnsymbols.cpp +++ b/lib/jkqtplotter/jkqtpgraphssinglecolumnsymbols.cpp @@ -24,10 +24,10 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtplotter.h" -#include "jkqtplottertools/jkqtpdrawingtools.h" +#include "jkqtcommon/jkqtpdrawingtools.h" #include #define SmallestGreaterZeroCompare_xvsgz() if ((xvsgz>10.0*DBL_MIN)&&((smallestGreaterZero<10.0*DBL_MIN) || (xvsgz #include #include -#include "jkqtcommon/jkqtptools.h" -#include "jkqtplottertools/jkqtpimagetools.h" +#include "jkqtplotter/jkqtptools.h" +#include "jkqtplotter/jkqtpimagetools.h" #include "jkqtplotter/jkqtpgraphsimage.h" #include "jkqtplotter/jkqtpbaseelements.h" #include "jkqtplotter/jkqtplotter.h" diff --git a/lib/jkqtplotter/jkqtpgraphsspecialline.h b/lib/jkqtplotter/jkqtpgraphsspecialline.h index 1cd8819fdf..dc011f2ac0 100644 --- a/lib/jkqtplotter/jkqtpgraphsspecialline.h +++ b/lib/jkqtplotter/jkqtpgraphsspecialline.h @@ -21,11 +21,11 @@ #include #include #include -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtcommon/jkqtp_imexport.h" -#include "jkqtplottertools/jkqtpdrawingtools.h" +#include "jkqtcommon/jkqtpdrawingtools.h" #include "jkqtplotter/jkqtpgraphsbase.h" -#include "jkqtplottertools/jkqtpenhancedpainter.h" +#include "jkqtcommon/jkqtpenhancedpainter.h" #include "jkqtplotter/jkqtpgraphsbaseerrors.h" #include "jkqtplotter/jkqtpgraphsrange.h" #include "jkqtplotter/jkqtpgraphsbasestylingmixins.h" @@ -38,7 +38,7 @@ class JKQTBasePlotter; class JKQTPlotter; class JKQTPCoordinateAxis; class JKQTPDatastore; -//class JKQTPColorPaletteTools; +//class JKQTPColorPaletteStyleAndToolsMixin; diff --git a/lib/jkqtplotter/jkqtpgraphsstatisticsadaptors.cpp b/lib/jkqtplotter/jkqtpgraphsstatisticsadaptors.cpp new file mode 100644 index 0000000000..9f28f1e96a --- /dev/null +++ b/lib/jkqtplotter/jkqtpgraphsstatisticsadaptors.cpp @@ -0,0 +1,24 @@ +/* + Copyright (c) 2008-2019 Jan W. Krieger () + + + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + + + +#include "jkqtplotter/jkqtpgraphsstatisticsadaptors.h" +#include "jkqtplotter/jkqtplotter.h" + diff --git a/lib/jkqtplotter/jkqtpgraphsstatisticsadaptors.h b/lib/jkqtplotter/jkqtpgraphsstatisticsadaptors.h new file mode 100644 index 0000000000..60167eb4c3 --- /dev/null +++ b/lib/jkqtplotter/jkqtpgraphsstatisticsadaptors.h @@ -0,0 +1,619 @@ +/* + Copyright (c) 2008-2019 Jan W. Krieger () + + + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + + +#include "jkqtcommon/jkqtp_imexport.h" +#include "jkqtcommon/jkqtpstatisticstools.h" +#include "jkqtplotter/jkqtpgraphsboxplot.h" +#include "jkqtplotter/jkqtpgraphsscatter.h" +#include "jkqtplotter/jkqtpgraphssinglecolumnsymbols.h" +#include "jkqtplotter/jkqtpgraphsbarchart.h" + +#ifndef JKQTPGRAPHSSTATISTICSADAPTORS_H_INCLUDED +#define JKQTPGRAPHSSTATISTICSADAPTORS_H_INCLUDED + +/*! \brief add a JKQTPBoxplotHorizontalElement to the given plotter, where the boxplot values are calculated from the data range \a first ... \a last + \ingroup jkqtptools_math_statistics + \ingroup jkqtplotter_statgraphs + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param boxposY y-coordinate of the boxplot + \param quantile1Spec specifies which quantile to calculate for \a qantile1 (range: 0..1) + \param quantile2Spec specifies which quantile to calculate for \a qantile2 (range: 0..1) + \param minimumQuantile specifies a quantile for the return value minimum (default is 0 for the real minimum, but you could e.g. use 0.05 for the 5% quantile!) + \param maximumQuantile specifies a quantile for the return value maximum (default is 1 for the real maximum, but you could e.g. use 0.95 for the 95% quantile!) + \param[out] statOutput optionally returns the internally calculated statistics as a JKQTPStat5NumberStatistics + \return a boxplot element with its values initialized from the given data range + + Example: + \code + jkqtpstatAddHBoxplot(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -0.3); + \endcode + + \see \ref JKQTPlottersimpletest_datastore_statistics, jkqtpstat5NumberStatistics() +*/ +template +inline JKQTPBoxplotHorizontalElement* jkqtpstatAddHBoxplot(JKQTBasePlotter* plotter, InputIt first, InputIt last, double boxposY, double quantile1Spec=0.25, double quantile2Spec=0.75, double minimumQuantile=0, double maximumQuantile=1.0, JKQTPStat5NumberStatistics* statOutput=nullptr) { + JKQTPStat5NumberStatistics stat=jkqtpstat5NumberStatistics(first, last, quantile1Spec, quantile2Spec, minimumQuantile, maximumQuantile); + if (statOutput) *statOutput=stat; + JKQTPBoxplotHorizontalElement* res=new JKQTPBoxplotHorizontalElement(plotter); + res->setMin(stat.minimum); + res->setMax(stat.maximum); + res->setMedian(stat.median); + res->setMean(jkqtpstatAverage(first, last)); + res->setPercentile25(stat.quantile1); + res->setPercentile75(stat.quantile2); + res->setMedianConfidenceIntervalWidth(stat.IQRSignificanceEstimate()); + res->setDrawMean(true); + res->setDrawNotch(true); + res->setDrawMedian(true); + res->setDrawMinMax(true); + res->setDrawBox(true); + res->setPos(boxposY); + plotter->addGraph(res); + return res; +} + + +/*! \brief add a JKQTPBoxplotVerticalElement to the given plotter, where the boxplot values are calculated from the data range \a first ... \a last + \ingroup jkqtptools_math_statistics + \ingroup jkqtplotter_statgraphs + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param boxposX x-coordinate of the boxplot + \param quantile1Spec specifies which quantile to calculate for \a qantile1 (range: 0..1) + \param quantile2Spec specifies which quantile to calculate for \a qantile2 (range: 0..1) + \param minimumQuantile specifies a quantile for the return value minimum (default is 0 for the real minimum, but you could e.g. use 0.05 for the 5% quantile!) + \param maximumQuantile specifies a quantile for the return value maximum (default is 1 for the real maximum, but you could e.g. use 0.95 for the 95% quantile!) + \param[out] statOutput optionally returns the internally calculated statistics as a JKQTPStat5NumberStatistics + \return a boxplot element with its values initialized from the given data range + + Example: + \code + jkqtpstatAddVBoxplot(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -0.3); + \endcode + + \see \ref JKQTPlottersimpletest_datastore_statistics, jkqtpstat5NumberStatistics() +*/ +template +inline JKQTPBoxplotVerticalElement* jkqtpstatAddVBoxplot(JKQTBasePlotter* plotter, InputIt first, InputIt last, double boxposX, double quantile1Spec=0.25, double quantile2Spec=0.75, double minimumQuantile=0, double maximumQuantile=1.0, JKQTPStat5NumberStatistics* statOutput=nullptr) { + JKQTPStat5NumberStatistics stat=jkqtpstat5NumberStatistics(first, last, quantile1Spec, quantile2Spec, minimumQuantile, maximumQuantile); + if (statOutput) *statOutput=stat; + JKQTPBoxplotVerticalElement* res=new JKQTPBoxplotVerticalElement(plotter); + res->setMin(stat.minimum); + res->setMax(stat.maximum); + res->setMedian(stat.median); + res->setMean(jkqtpstatAverage(first, last)); + res->setPercentile25(stat.quantile1); + res->setPercentile75(stat.quantile2); + res->setMedianConfidenceIntervalWidth(stat.IQRSignificanceEstimate()); + res->setDrawMean(true); + res->setDrawNotch(true); + res->setDrawMedian(true); + res->setDrawMinMax(true); + res->setDrawBox(true); + res->setPos(boxposX); + plotter->addGraph(res); + return res; +} + + + +/*! \brief add a JKQTPBoxplotHorizontalElement and a JKQTPSingleColumnSymbolsGraph for outliers to the given plotter, where the boxplot values are calculated from the data range \a first ... \a last + \ingroup jkqtptools_math_statistics + \ingroup jkqtplotter_statgraphs + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param boxposY y-coordinate of the outliers (and the boxplot) + \param quantile1Spec specifies which quantile to calculate for \a qantile1 (range: 0..1) + \param quantile2Spec specifies which quantile to calculate for \a qantile2 (range: 0..1) + \param minimumQuantile specifies a quantile for the return value minimum (default is 0 for the real minimum, but you could e.g. use 0.05 for the 5% quantile!) + \param maximumQuantile specifies a quantile for the return value maximum (default is 1 for the real maximum, but you could e.g. use 0.95 for the 95% quantile!) + \param outliercolumnBaseName this string is used in building the column names for the outlier columns + \param[out] statOutput optionally returns the internally calculated statistics as a JKQTPStat5NumberStatistics + \return a boxplot element with its values initialized from the given data range + + Example: + \code + jkqtpstatAddHBoxplotAndOutliers(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -0.3); + jkqtpstatAddHBoxplotAndOutliers(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -0.3, + 0.25, 0.75, // 1. and 3. Quartile for the boxplot box + 0.05, 0.95 // Quantiles for the boxplot box whiskers' ends + \endcode + + \see \ref JKQTPlottersimpletest_datastore_statistics, jkqtpstat5NumberStatistics() +*/ +template +inline std::pair jkqtpstatAddHBoxplotAndOutliers(JKQTBasePlotter* plotter, InputIt first, InputIt last, double boxposY, double quantile1Spec=0.25, double quantile2Spec=0.75, double minimumQuantile=0.03, double maximumQuantile=0.97, const QString& outliercolumnBaseName=QString("boxplot"), JKQTPStat5NumberStatistics* statOutput=nullptr) { + JKQTPStat5NumberStatistics stat=jkqtpstat5NumberStatistics(first, last, quantile1Spec, quantile2Spec, minimumQuantile, maximumQuantile); + if (statOutput) *statOutput=stat; + JKQTPBoxplotHorizontalElement* resB=new JKQTPBoxplotHorizontalElement(plotter); + resB->setMin(stat.minimum); + resB->setMax(stat.maximum); + resB->setMedian(stat.median); + resB->setMean(jkqtpstatAverage(first, last)); + resB->setPercentile25(stat.quantile1); + resB->setPercentile75(stat.quantile2); + resB->setMedianConfidenceIntervalWidth(stat.IQRSignificanceEstimate()); + resB->setDrawMean(true); + resB->setDrawNotch(true); + resB->setDrawMedian(true); + resB->setDrawMinMax(true); + resB->setDrawBox(true); + resB->setPos(boxposY); + JKQTPSingleColumnSymbolsGraph* resO=new JKQTPSingleColumnSymbolsGraph(plotter); + resO->setDataColumn(plotter->getDatastore()->addCopiedColumn(stat.outliers, outliercolumnBaseName)); + resO->setPosition(boxposY); + resO->setPositionScatterStyle(JKQTPSingleColumnSymbolsGraph::NoScatter); + resO->setDataDirection(JKQTPSingleColumnSymbolsGraph::DataDirection::X); + resO->setColor(resB->getKeyLabelColor()); + resO->setTitle(""); + + plotter->addGraph(resB); + plotter->addGraph(resO); + return std::pair(resB, resO); +} + + + +/*! \brief add a JKQTPBoxplotVerticalElement and a JKQTPSingleColumnSymbolsGraph for outliers to the given plotter, where the boxplot values are calculated from the data range \a first ... \a last + \ingroup jkqtptools_math_statistics + \ingroup jkqtplotter_statgraphs + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param boxposX x-coordinate of the outliers (and the boxplot) + \param quantile1Spec specifies which quantile to calculate for \a qantile1 (range: 0..1) + \param quantile2Spec specifies which quantile to calculate for \a qantile2 (range: 0..1) + \param minimumQuantile specifies a quantile for the return value minimum (default is 0.03, i.e. the 3% quantile!) + \param maximumQuantile specifies a quantile for the return value maximum (default is 0.97, i.e. the 97% quantile!) + \param outliercolumnBaseName this string is used in building the column names for the outlier columns + \param[out] statOutput optionally returns the internally calculated statistics as a JKQTPStat5NumberStatistics + \return a boxplot element with its values initialized from the given data range + + Example: + \code + jkqtpstatAddVBoxplotAndOutliers(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -0.3); + jkqtpstatAddVBoxplotAndOutliers(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), -0.3, + 0.25, 0.75, // 1. and 3. Quartile for the boxplot box + 0.05, 0.95 // Quantiles for the boxplot box whiskers' ends + \endcode + + \see \ref JKQTPlottersimpletest_datastore_statistics, jkqtpstat5NumberStatistics() +*/ +template +inline std::pair jkqtpstatAddVBoxplotAndOutliers(JKQTBasePlotter* plotter, InputIt first, InputIt last, double boxposX, double quantile1Spec=0.25, double quantile2Spec=0.75, double minimumQuantile=0.03, double maximumQuantile=0.97, const QString& outliercolumnBaseName=QString("boxplot"), JKQTPStat5NumberStatistics* statOutput=nullptr) { + JKQTPStat5NumberStatistics stat=jkqtpstat5NumberStatistics(first, last, quantile1Spec, quantile2Spec, minimumQuantile, maximumQuantile); + if (statOutput) *statOutput=stat; + JKQTPBoxplotVerticalElement* resB=new JKQTPBoxplotVerticalElement(plotter); + resB->setMin(stat.minimum); + resB->setMax(stat.maximum); + resB->setMedian(stat.median); + resB->setMean(jkqtpstatAverage(first, last)); + resB->setPercentile25(stat.quantile1); + resB->setPercentile75(stat.quantile2); + resB->setMedianConfidenceIntervalWidth(stat.IQRSignificanceEstimate()); + resB->setDrawMean(true); + resB->setDrawNotch(true); + resB->setDrawMedian(true); + resB->setDrawMinMax(true); + resB->setDrawBox(true); + resB->setPos(boxposX); + JKQTPSingleColumnSymbolsGraph* resO=new JKQTPSingleColumnSymbolsGraph(plotter); + resO->setDataColumn(plotter->getDatastore()->addCopiedColumn(stat.outliers, outliercolumnBaseName)); + resO->setPosition(boxposX); + resO->setPositionScatterStyle(JKQTPSingleColumnSymbolsGraph::NoScatter); + resO->setDataDirection(JKQTPSingleColumnSymbolsGraph::DataDirection::Y); + resO->setColor(resB->getKeyLabelColor()); + + + plotter->addGraph(resB); + plotter->addGraph(resO); + return std::pair(resB, resO); +} + + + +/*! \brief calculate an autoranged histogram and add a JKQTPBarVerticalGraph to the given plotter, where the histogram is calculated from the data range \a first ... \a last, bins defined by their number + \ingroup jkqtptools_math_statistics_1dhist + \ingroup jkqtplotter_statgraphs + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param bins number of bins in the resulting histogram + \param histogramcolumnBaseName this string is used in building the column names for the outlier columns + \param normalized indicates whether the histogram has to be normalized + \param cummulative if \c true, a cummulative histogram is calculated + \return a graph class pointer (of type \a GraphClass ) displaying the histogram data + + Example: + \code + jkqtpstatAddHHistogram1DAutoranged(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), 11); + \endcode + + \see \ref JKQTPlottersimpletest_datastore_statistics, jkqtpstatHistogram1DAutoranged(), JKQTPBarVerticalGraph +*/ +template +inline JKQTPBarVerticalGraph* jkqtpstatAddHHistogram1DAutoranged(JKQTBasePlotter* plotter, InputIt first, InputIt last, int bins=11, bool normalized=true, bool cummulative=false, const QString& histogramcolumnBaseName=QString("histogram")) { + size_t histcolX=plotter->getDatastore()->addColumn(histogramcolumnBaseName+", bins"); + size_t histcolY=plotter->getDatastore()->addColumn(histogramcolumnBaseName+", values"); + jkqtpstatHistogram1DAutoranged(first, last, plotter->getDatastore()->backInserter(histcolX), plotter->getDatastore()->backInserter(histcolY), bins, normalized, cummulative, JKQTPStatHistogramBinXMode::XIsMid); + JKQTPBarVerticalGraph* resO=new JKQTPBarVerticalGraph(plotter); + resO->setXColumn(histcolX); + resO->setYColumn(histcolY); + resO->setTitle(histogramcolumnBaseName); + plotter->addGraph(resO); + return resO; +} + + + +/*! \brief calculate an autoranged histogram and add a JKQTPBarVerticalGraph to the given plotter, where the histogram is calculated from the data range \a first ... \a last, bins defined by their width + \ingroup jkqtptools_math_statistics_1dhist + \ingroup jkqtplotter_statgraphs + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param binWidth width of the bins + \param histogramcolumnBaseName this string is used in building the column names for the histogram columns + \param normalized indicates whether the histogram has to be normalized + \param cummulative if \c true, a cummulative histogram is calculated + \return a graph class pointer (of type \a GraphClass ) displaying the histogram data + + Example: + \code + jkqtpstatAddHHistogram1DAutoranged(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), 0.5); + \endcode + + \see \ref JKQTPlottersimpletest_datastore_statistics, jkqtpstatHistogram1DAutoranged(), JKQTPBarVerticalGraph +*/ +template +inline JKQTPBarVerticalGraph* jkqtpstatAddHHistogram1DAutoranged(JKQTBasePlotter* plotter, InputIt first, InputIt last, double binWidth, bool normalized=true, bool cummulative=false, const QString& histogramcolumnBaseName=QString("histogram")) { + size_t histcolX=plotter->getDatastore()->addColumn(histogramcolumnBaseName+", bins"); + size_t histcolY=plotter->getDatastore()->addColumn(histogramcolumnBaseName+", values"); + jkqtpstatHistogram1DAutoranged(first, last, plotter->getDatastore()->backInserter(histcolX), plotter->getDatastore()->backInserter(histcolY), binWidth, normalized, cummulative, JKQTPStatHistogramBinXMode::XIsMid); + JKQTPBarVerticalGraph* resO=new JKQTPBarVerticalGraph(plotter); + resO->setXColumn(histcolX); + resO->setYColumn(histcolY); + resO->setTitle(histogramcolumnBaseName); + plotter->addGraph(resO); + return resO; +} + + +/*! \brief calculate an autoranged histogram and add a JKQTPBarVerticalGraph to the given plotter, where the histogram is calculated from the data range \a first ... \a last, bins defined by their width + \ingroup jkqtptools_math_statistics_1dhist + \ingroup jkqtplotter_statgraphs + + \tparam InputIt standard iterator type of \a first and \a last. + \tparam BinsInputIt standard iterator type of \a binsFirst and \a binsLast. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param binsFirst iterator pointing to the first item in the set of histogram bins + \param binsLast iterator pointing behind the last item in the set of histogram bins + \param histogramcolumnBaseName this string is used in building the column names for the histogram columns + \param normalized indicates whether the histogram has to be normalized + \param cummulative if \c true, a cummulative histogram is calculated + \return a graph class pointer (of type \a GraphClass ) displaying the histogram data + + Example: + \code + std::vector bins{-2,-1.5,-1,-0.75,-0.5,-0.25,0,0.25,0.5,0.75,1,1.5,2,2.5,3,4,5,6,7,8,9,10}; + jkqtpstatAddHHistogram1D(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), bins.begin(), bins.end()); + \endcode + + \see \ref JKQTPlottersimpletest_datastore_statistics, jkqtpstatHistogram1D(), JKQTPBarVerticalGraph +*/ +template +inline JKQTPBarVerticalGraph* jkqtpstatAddHHistogram1D(JKQTBasePlotter* plotter, InputIt first, InputIt last, BinsInputIt binsFirst, BinsInputIt binsLast, bool normalized=true, bool cummulative=false, const QString& histogramcolumnBaseName=QString("histogram")) { + size_t histcolX=plotter->getDatastore()->addColumn(histogramcolumnBaseName+", bins"); + size_t histcolY=plotter->getDatastore()->addColumn(histogramcolumnBaseName+", values"); + jkqtpstatHistogram1D(first, last, binsFirst, binsLast, plotter->getDatastore()->backInserter(histcolX), plotter->getDatastore()->backInserter(histcolY), normalized, cummulative, JKQTPStatHistogramBinXMode::XIsMid); + JKQTPBarVerticalGraph* resO=new JKQTPBarVerticalGraph(plotter); + resO->setXColumn(histcolX); + resO->setYColumn(histcolY); + resO->setTitle(histogramcolumnBaseName); + plotter->addGraph(resO); + return resO; +} + + +/*! \brief calculate an autoranged histogram and add a JKQTPBarHorizontalGraph to the given plotter, where the histogram is calculated from the data range \a first ... \a last, bins defined by their number + \ingroup jkqtptools_math_statistics_1dhist + \ingroup jkqtplotter_statgraphs + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param bins number of bins in the resulting histogram + \param histogramcolumnBaseName this string is used in building the column names for the histogram columns + \param normalized indicates whether the histogram has to be normalized + \param cummulative if \c true, a cummulative histogram is calculated + \return a graph class pointer (of type \a GraphClass ) displaying the histogram data + + Example: + \code + jkqtpstatAddVHistogram1DAutoranged(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), 11); + \endcode + + \see \ref JKQTPlottersimpletest_datastore_statistics, jkqtpstatHistogram1DAutoranged(), JKQTPBarHorizontalGraph +*/ +template +inline JKQTPBarHorizontalGraph* jkqtpstatAddVHistogram1DAutoranged(JKQTBasePlotter* plotter, InputIt first, InputIt last, int bins=11, bool normalized=true, bool cummulative=false, const QString& histogramcolumnBaseName=QString("histogram")) { + size_t histcolX=plotter->getDatastore()->addColumn(histogramcolumnBaseName+", bins"); + size_t histcolY=plotter->getDatastore()->addColumn(histogramcolumnBaseName+", values"); + jkqtpstatHistogram1DAutoranged(first, last, plotter->getDatastore()->backInserter(histcolX), plotter->getDatastore()->backInserter(histcolY), bins, normalized, cummulative, JKQTPStatHistogramBinXMode::XIsMid); + JKQTPBarHorizontalGraph* resO=new JKQTPBarHorizontalGraph(plotter); + resO->setXColumn(histcolX); + resO->setYColumn(histcolY); + resO->setTitle(histogramcolumnBaseName); + plotter->addGraph(resO); + return resO; +} + + + +/*! \brief calculate an autoranged histogram and add a JKQTPBarHorizontalGraph to the given plotter, where the histogram is calculated from the data range \a first ... \a last, bins defined by their width + \ingroup jkqtptools_math_statistics_1dhist + \ingroup jkqtplotter_statgraphs + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param binWidth width of the bins + \param histogramcolumnBaseName this string is used in building the column names for the histogram columns + \param normalized indicates whether the histogram has to be normalized + \param cummulative if \c true, a cummulative histogram is calculated + \return a graph class pointer (of type \a GraphClass ) displaying the histogram data + + Example: + \code + jkqtpstatAddVHistogram1DAutoranged(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), 0.5); + \endcode + + \see \ref JKQTPlottersimpletest_datastore_statistics, jkqtpstatHistogram1DAutoranged(), JKQTPBarHorizontalGraph +*/ +template +inline JKQTPBarHorizontalGraph* jkqtpstatAddVHistogram1DAutoranged(JKQTBasePlotter* plotter, InputIt first, InputIt last, double binWidth, bool normalized=true, bool cummulative=false, const QString& histogramcolumnBaseName=QString("histogram")) { + size_t histcolX=plotter->getDatastore()->addColumn(histogramcolumnBaseName+", bins"); + size_t histcolY=plotter->getDatastore()->addColumn(histogramcolumnBaseName+", values"); + jkqtpstatHistogram1DAutoranged(first, last, plotter->getDatastore()->backInserter(histcolX), plotter->getDatastore()->backInserter(histcolY), binWidth, normalized, cummulative, JKQTPStatHistogramBinXMode::XIsMid); + JKQTPBarHorizontalGraph* resO=new JKQTPBarHorizontalGraph(plotter); + resO->setXColumn(histcolX); + resO->setYColumn(histcolY); + resO->setTitle(histogramcolumnBaseName); + plotter->addGraph(resO); + return resO; +} + + +/*! \brief calculate an autoranged histogram and add a JKQTPBarHorizontalGraph to the given plotter, where the histogram is calculated from the data range \a first ... \a last, bins defined by their width + \ingroup jkqtptools_math_statistics_1dhist + \ingroup jkqtplotter_statgraphs + + \tparam InputIt standard iterator type of \a first and \a last. + \tparam BinsInputIt standard iterator type of \a binsFirst and \a binsLast. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param binsFirst iterator pointing to the first item in the set of histogram bins + \param binsLast iterator pointing behind the last item in the set of histogram bins + \param histogramcolumnBaseName this string is used in building the column names for the histogram columns + \param normalized indicates whether the histogram has to be normalized + \param cummulative if \c true, a cummulative histogram is calculated + \return a graph class pointer (of type \a GraphClass ) displaying the histogram data + + Example: + \code + std::vector bins{-2,-1.5,-1,-0.75,-0.5,-0.25,0,0.25,0.5,0.75,1,1.5,2,2.5,3,4,5,6,7,8,9,10}; + jkqtpstatAddVHistogram1D(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), bins.begin(), bins.end()); + \endcode + + \see \ref JKQTPlottersimpletest_datastore_statistics, jkqtpstatHistogram1D(), JKQTPBarHorizontalGraph +*/ +template +inline JKQTPBarHorizontalGraph* jkqtpstatAddVHistogram1D(JKQTBasePlotter* plotter, InputIt first, InputIt last, BinsInputIt binsFirst, BinsInputIt binsLast, bool normalized=true, bool cummulative=false, const QString& histogramcolumnBaseName=QString("histogram")) { + size_t histcolX=plotter->getDatastore()->addColumn(histogramcolumnBaseName+", bins"); + size_t histcolY=plotter->getDatastore()->addColumn(histogramcolumnBaseName+", values"); + jkqtpstatHistogram1D(first, last, binsFirst, binsLast, plotter->getDatastore()->backInserter(histcolX), plotter->getDatastore()->backInserter(histcolY), normalized, cummulative, JKQTPStatHistogramBinXMode::XIsMid); + JKQTPBarHorizontalGraph* resO=new JKQTPBarHorizontalGraph(plotter); + resO->setXColumn(histcolX); + resO->setYColumn(histcolY); + resO->setTitle(histogramcolumnBaseName); + plotter->addGraph(resO); + return resO; +} + + + + + + + + + + + + +/*! \brief calculate an autoranged KDE and add a JKQTPXYLineGraph to the given plotter, where the KDE is calculated from the data range \a first ... \a last, bins defined by their number + \ingroup jkqtptools_math_statistics_1dhist + \ingroup jkqtplotter_statgraphs + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param Nout number of points in the resulting KDE + \param kernel the kernel function to use (e.g. jkqtpstatKernel1DGaussian() ) + \param bandwidth bandwidth used for the KDE + \param cummulative if \c true, a cummulative KDE is calculated + \param KDEcolumnBaseName this string is used in building the column names for the KDE data columns + \return a graph class pointer (of type \a GraphClass ) displaying the KDE data + + Example: + \code + jkqtpstatAddHKDE1DAutoranged(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), 200); + \endcode + + \see \ref JKQTPlottersimpletest_datastore_statistics, jkqtpstatKDE1DAutoranged(), JKQTPXYLineGraph +*/ +template +inline JKQTPXYLineGraph* jkqtpstatAddHKDE1DAutoranged(JKQTBasePlotter* plotter, InputIt first, InputIt last, int Nout=100, const std::function& kernel=std::function(&jkqtpstatKernel1DGaussian), double bandwidth=1.0, bool cummulative=false, const QString& KDEcolumnBaseName=QString("KDE")) { + size_t histcolX=plotter->getDatastore()->addColumn(KDEcolumnBaseName+", positions"); + size_t histcolY=plotter->getDatastore()->addColumn(KDEcolumnBaseName+", values"); + jkqtpstatKDE1DAutoranged(first, last, plotter->getDatastore()->backInserter(histcolX), plotter->getDatastore()->backInserter(histcolY), Nout, kernel, bandwidth, cummulative); + JKQTPXYLineGraph* resO=new JKQTPXYLineGraph(plotter); + resO->setXColumn(histcolX); + resO->setYColumn(histcolY); + resO->setTitle(KDEcolumnBaseName); + resO->setDrawLine(true); + resO->setSymbolType(JKQTPNoSymbol); + plotter->addGraph(resO); + return resO; +} + + + +/*! \brief calculate an autoranged KDE and add a JKQTPXYLineGraph to the given plotter, where the KDE is calculated from the data range \a first ... \a last, bins defined by their width + \ingroup jkqtptools_math_statistics_1dhist + \ingroup jkqtplotter_statgraphs + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param binWidth width of the bins + \param kernel the kernel function to use (e.g. jkqtpstatKernel1DGaussian() ) + \param bandwidth bandwidth used for the KDE + \param cummulative if \c true, a cummulative KDE is calculated + \param KDEcolumnBaseName this string is used in building the column names for the KDE data columns + \return a graph class pointer (of type \a GraphClass ) displaying the KDE data + + Example: + \code + jkqtpstatAddHKDE1DAutoranged(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), 0.01); + \endcode + + \see \ref JKQTPlottersimpletest_datastore_statistics, jkqtpstatKDE1DAutoranged(), JKQTPXYLineGraph +*/ +template +inline JKQTPXYLineGraph* jkqtpstatAddHKDE1DAutoranged(JKQTBasePlotter* plotter, InputIt first, InputIt last, double binWidth, const std::function& kernel=std::function(&jkqtpstatKernel1DGaussian), double bandwidth=1.0, bool cummulative=false, const QString& KDEcolumnBaseName=QString("KDE")) { + size_t histcolX=plotter->getDatastore()->addColumn(KDEcolumnBaseName+", bins"); + size_t histcolY=plotter->getDatastore()->addColumn(KDEcolumnBaseName+", values"); + jkqtpstatKDE1DAutoranged(first, last, plotter->getDatastore()->backInserter(histcolX), plotter->getDatastore()->backInserter(histcolY), binWidth, kernel, bandwidth, cummulative); + JKQTPXYLineGraph* resO=new JKQTPXYLineGraph(plotter); + resO->setXColumn(histcolX); + resO->setYColumn(histcolY); + resO->setTitle(KDEcolumnBaseName); + resO->setDrawLine(true); + resO->setSymbolType(JKQTPNoSymbol); + plotter->addGraph(resO); + return resO; +} + + +/*! \brief calculate an autoranged KDE and add a JKQTPXYLineGraph to the given plotter, where the KDE is calculated from the data range \a first ... \a last, bins defined by their width + \ingroup jkqtptools_math_statistics_1dhist + \ingroup jkqtplotter_statgraphs + + \tparam InputIt standard iterator type of \a first and \a last. + \tparam BinsInputIt standard iterator type of \a binsFirst and \a binsLast. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param binsFirst iterator pointing to the first item in the set of KDE bins + \param binsLast iterator pointing behind the last item in the set of KDE bins + \param kernel the kernel function to use (e.g. jkqtpstatKernel1DGaussian() ) + \param bandwidth bandwidth used for the KDE + \param cummulative if \c true, a cummulative KDE is calculated + \param KDEcolumnBaseName this string is used in building the column names for the KDE data columns + \return a graph class pointer (of type \a GraphClass ) displaying the KDE data + + Example: + \code + std::vector bins{-2,-1.5,-1,-0.75,-0.5,-0.25,0,0.25,0.5,0.75,1,1.5,2,2.5,3,4,5,6,7,8,9,10}; + jkqtpstatAddHKDE1D(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), bins.begin(), bins.end()); + \endcode + + \see \ref JKQTPlottersimpletest_datastore_statistics, jkqtpstatKDE1D(), JKQTPXYLineGraph +*/ +template +inline JKQTPXYLineGraph* jkqtpstatAddHKDE1D(JKQTBasePlotter* plotter, InputIt first, InputIt last, BinsInputIt binsFirst, BinsInputIt binsLast, const std::function& kernel=std::function(&jkqtpstatKernel1DGaussian), double bandwidth=1.0, bool cummulative=false, const QString& KDEcolumnBaseName=QString("KDE")) { + size_t histcolX=plotter->getDatastore()->addColumn(KDEcolumnBaseName+", bins"); + size_t histcolY=plotter->getDatastore()->addColumn(KDEcolumnBaseName+", values"); + jkqtpstatKDE1D(first, last, binsFirst, binsLast, plotter->getDatastore()->backInserter(histcolX), plotter->getDatastore()->backInserter(histcolY), kernel, bandwidth, cummulative); + JKQTPXYLineGraph* resO=new JKQTPXYLineGraph(plotter); + resO->setXColumn(histcolX); + resO->setYColumn(histcolY); + resO->setTitle(KDEcolumnBaseName); + resO->setDrawLine(true); + resO->setSymbolType(JKQTPNoSymbol); + plotter->addGraph(resO); + return resO; +} + +/*! \brief calculate an autoranged KDE and add a JKQTPXYLineGraph to the given plotter, where the KDE is calculated from the data range \a first ... \a last, evaluation positions are given by the range \a binXLeft ... \a binXRight (in steps of \a binxDelta ) + \ingroup jkqtptools_math_statistics_1dhist + \ingroup jkqtplotter_statgraphs + + \tparam InputIt standard iterator type of \a first and \a last. + \param first iterator pointing to the first item in the dataset to use \f$ X_1 \f$ + \param last iterator pointing behind the last item in the dataset to use \f$ X_N \f$ + \param binXLeft first x-position, where to evaluate the KDE + \param binXDelta distance between two x-positions at which the KDE is evaluated + \param binXRight last x-position, where to evaluate the KDE + \param kernel the kernel function to use (e.g. jkqtpstatKernel1DGaussian() ) + \param bandwidth bandwidth used for the KDE + \param cummulative if \c true, a cummulative KDE is calculated + \param KDEcolumnBaseName this string is used in building the column names for the KDE data columns + \return a graph class pointer (of type \a GraphClass ) displaying the KDE data + + Example: + \code + std::vector bins{-2,-1.5,-1,-0.75,-0.5,-0.25,0,0.25,0.5,0.75,1,1.5,2,2.5,3,4,5,6,7,8,9,10}; + jkqtpstatAddHKDE1D(plot1->getPlotter(), datastore1->begin(randomdatacol1), datastore1->end(randomdatacol1), bins.begin(), bins.end()); + \endcode + + \see \ref JKQTPlottersimpletest_datastore_statistics, jkqtpstatKDE1D(), JKQTPXYLineGraph +*/ +template +inline JKQTPXYLineGraph* jkqtpstatAddHKDE1D(JKQTBasePlotter* plotter, InputIt first, InputIt last, double binXLeft, double binXDelta, double binXRight, const std::function& kernel=std::function(&jkqtpstatKernel1DGaussian), double bandwidth=1.0, bool cummulative=false, const QString& KDEcolumnBaseName=QString("KDE")) { + size_t histcolX=plotter->getDatastore()->addColumn(KDEcolumnBaseName+", bins"); + size_t histcolY=plotter->getDatastore()->addColumn(KDEcolumnBaseName+", values"); + jkqtpstatKDE1D(first, last, binXLeft, binXDelta, binXRight, plotter->getDatastore()->backInserter(histcolX), plotter->getDatastore()->backInserter(histcolY), kernel, bandwidth, cummulative); + JKQTPXYLineGraph* resO=new JKQTPXYLineGraph(plotter); + resO->setXColumn(histcolX); + resO->setYColumn(histcolY); + resO->setTitle(KDEcolumnBaseName); + resO->setDrawLine(true); + resO->setSymbolType(JKQTPNoSymbol); + plotter->addGraph(resO); + return resO; +} + + + + + +#endif // JKQTPGRAPHSSTATISTICSADAPTORS_H_INCLUDED diff --git a/lib/jkqtplotter/jkqtpimagetools.cpp b/lib/jkqtplotter/jkqtpimagetools.cpp new file mode 100644 index 0000000000..1ab4f0094a --- /dev/null +++ b/lib/jkqtplotter/jkqtpimagetools.cpp @@ -0,0 +1,540 @@ +/* + Copyright (c) 2008-2019 Jan W. Krieger () + + + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + +#include "jkqtplotter/jkqtpimagetools.h" +#include +#include +#include +#include +#include "jkqtplotter/jkqtpbaseelements.h" +#include "jkqtplotter/jkqtpbaseplotter.h" +#include "jkqtcommon/jkqtpdrawingtools.h" +#ifdef QT_XML_LIB +# include +#endif + + + + + +JKQTPColorPaletteStyleAndToolsMixin::JKQTPColorPaletteStyleAndToolsMixin(JKQTBasePlotter *parent) +{ + cbParent=parent; + colorBarRightAxis=new JKQTPVerticalIndependentAxis(0, 100, 0, 100, parent); + colorBarRightAxis->setDrawMode1(JKQTPCADMLine); + colorBarRightAxis->setDrawMode2(JKQTPCADMcomplete); + colorBarRightAxis->setAxisLabel(""); + colorBarRightAxis->setMinTicks(3); + colorBarRightAxis->setShowZeroAxis(false); + colorBarRightAxis->setMinorTicks(0); + colorBarRightAxis->setTickOutsideLength(0); + colorBarRightAxis->setMinorTickOutsideLength(0); + colorBarTopAxis=new JKQTPHorizontalIndependentAxis(0, 100, 0, 100, parent); + colorBarTopAxis->setDrawMode1(JKQTPCADMLine); + colorBarTopAxis->setDrawMode2(JKQTPCADMcomplete); + colorBarTopAxis->setAxisLabel(""); + colorBarTopAxis->setMinTicks(3); + colorBarTopAxis->setShowZeroAxis(false); + colorBarTopAxis->setMinorTicks(0); + colorBarTopAxis->setTickOutsideLength(0); + colorBarTopAxis->setMinorTickOutsideLength(0); + + + this->palette=JKQTPMathImageMATLAB; + this->imageNameFontName=parent->getDefaultTextFontName(); + this->imageNameFontSize=parent->getDefaultTextSize(); + this->imageName=""; + this->showColorBar=true; + this->colorBarWidth=14; + this->colorBarRelativeHeight=0.75; + this->autoImageRange=true; + this->imageMin=0; + this->imageMax=1; + this->colorBarOffset=4; + this->rangeMinFailAction=JKQTPMathImageLastPaletteColor; + this->rangeMaxFailAction=JKQTPMathImageLastPaletteColor; + this->rangeMinFailColor=QColor("black"); + this->rangeMaxFailColor=QColor("black"); + this->nanColor=QColor("black"); + this->infColor=QColor("black"); + this->colorBarTopVisible=false; + this->colorBarRightVisible=true; + + if (parent) this->palette=parent->getCurrentPlotterStyle().defaultPalette; + +} + +JKQTPColorPaletteStyleAndToolsMixin::~JKQTPColorPaletteStyleAndToolsMixin() += default; + +void JKQTPColorPaletteStyleAndToolsMixin::cbGetOutsideSize(JKQTPEnhancedPainter& painter, int& leftSpace, int& rightSpace, int& topSpace, int& bottomSpace) { + Q_UNUSED(leftSpace); + Q_UNUSED(bottomSpace); + if (showColorBar) { + double internalDataMin=0; + double internalDataMax=0; + cbGetDataMinMax(internalDataMin, internalDataMax); + if (colorBarRightVisible) { + rightSpace+=cbParent->pt2px(painter, colorBarWidth+colorBarOffset); + colorBarRightAxis->setRange(internalDataMin, internalDataMax); + colorBarRightAxis->setAxisWidth(colorBarRelativeHeight*cbParent->getPlotHeight()); + QSizeF s1=colorBarRightAxis->getSize2(painter); + QSizeF s2=colorBarRightAxis->getSize1(painter); + QSizeF names=cbParent->getTextSizeSize(imageNameFontName, imageNameFontSize*cbParent->getFontSizeMultiplier(), imageName, painter); + rightSpace+=qMax(static_cast(s1.width()+s2.width()), static_cast(names.width())); + } + if (colorBarTopVisible) { + //topSpace+=cbParent->pt2px(painter, colorBarWidth+colorBarOffset); + colorBarTopAxis->setRange(internalDataMin, internalDataMax); + colorBarTopAxis->setAxisWidth(colorBarRelativeHeight*cbParent->getPlotWidth()); + QSizeF s1=colorBarTopAxis->getSize2(painter); + QSizeF s2=colorBarTopAxis->getSize1(painter); + QSizeF names=cbParent->getTextSizeSize(imageNameFontName, imageNameFontSize*cbParent->getFontSizeMultiplier(), imageName, painter); + topSpace+=cbParent->pt2px(painter, colorBarWidth+colorBarOffset)+qMax(static_cast(s1.height()+s2.height()), static_cast(names.height())); + } + } +} + +void JKQTPColorPaletteStyleAndToolsMixin::cbDrawOutside(JKQTPEnhancedPainter& painter, QRect leftSpace, QRect rightSpace, QRect topSpace, QRect bottomSpace) { + Q_UNUSED(leftSpace); + Q_UNUSED(bottomSpace); + if (showColorBar) { + double internalDataMin=0; + double internalDataMax=0; + cbGetDataMinMax(internalDataMin, internalDataMax); + if (colorBarRightVisible) { + painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); + + static const uint8_t h=1; + static const uint8_t dSize = 200*h; + uint8_t d[dSize];//, dd[200*h]; + for (int i=0; i<200; i++) { + for (int j=0; j(d, h, 200, b, palette, 0, 199); + + + QSizeF names=cbParent->getTextSizeSize(imageNameFontName, imageNameFontSize*cbParent->getFontSizeMultiplier(), imageName, painter); + + double icolorBarRelativeHeight=colorBarRelativeHeight; + int barHeight=rightSpace.height()*icolorBarRelativeHeight; + if (barHeight<1) barHeight=1; + // find a height for the bar that allows to show the image name + while ((barHeight>1) && ((rightSpace.height()-barHeight)/2pt2px(painter, colorBarOffset), rightSpace.top()+(rightSpace.height()-barHeight)/2, cbParent->pt2px(painter, colorBarWidth), barHeight); + painter.drawImage(cb, b.mirrored(true, false)); + QPen p=painter.pen(); + p.setColor(colorBarRightAxis->getAxisColor()); + p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, cbParent->pt2px(painter, colorBarRightAxis->getLineWidth()*cbParent->getLineWidthMultiplier()))); + painter.setPen(p); + painter.drawRect(cb); + + colorBarRightAxis->setRange(internalDataMin, internalDataMax); + colorBarRightAxis->setAxisWidth(cb.height()); + colorBarRightAxis->setAxisOffset(cb.top()); + colorBarRightAxis->setOtherAxisOffset(cb.left()); + colorBarRightAxis->setOtherAxisWidth(cb.width()); + colorBarRightAxis->drawAxes(painter); + + + + cbParent->getMathText()->setFontSize(imageNameFontSize*cbParent->getFontSizeMultiplier()); + cbParent->getMathText()->setFontRomanOrSpecial(imageNameFontName); + cbParent->getMathText()->parse(imageName); + cbParent->getMathText()->draw(painter, Qt::AlignHCenter|Qt::AlignVCenter, QRect(rightSpace.x(), rightSpace.y(), rightSpace.width(), (rightSpace.height()-barHeight)/2)); + + + } + if (colorBarTopVisible) { + painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); + + static const uint8_t h=1; + static const uint8_t dSize = 200*h; + uint8_t d[dSize];//, dd[200*h]; + for (int i=0; i<200; i++) { + for (int j=0; j(d,h,200, b, palette, 0, 199); + + QSizeF names=cbParent->getTextSizeSize(imageNameFontName, imageNameFontSize*cbParent->getFontSizeMultiplier(), imageName, painter); + + double icolorBarRelativeHeight=colorBarRelativeHeight; + int barWidth=topSpace.width()*icolorBarRelativeHeight; + if (barWidth<1) barWidth=1; + // find a height for the bar that allows to show the image name + while ((barWidth>1) && ((topSpace.width()-barWidth)/2pt2px(painter, colorBarOffset+(colorBarWidth)), barWidth, cbParent->pt2px(painter, colorBarWidth)); + //qDebug()<<"t: "<getAxisColor()); + p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, cbParent->pt2px(painter, colorBarTopAxis->getLineWidth()*cbParent->getLineWidthMultiplier()))); + painter.setPen(p); + painter.drawRect(cb); + + + colorBarTopAxis->setRange(internalDataMin, internalDataMax); + colorBarTopAxis->setAxisWidth(cb.width()); + colorBarTopAxis->setAxisOffset(cb.left()); + colorBarTopAxis->setOtherAxisOffset(cb.top()); + colorBarTopAxis->setOtherAxisWidth(cb.height()); + colorBarTopAxis->drawAxes(painter); + + + + cbParent->getMathText()->setFontSize(imageNameFontSize*cbParent->getFontSizeMultiplier()); + cbParent->getMathText()->setFontRomanOrSpecial(imageNameFontName); + cbParent->getMathText()->parse(imageName); + cbParent->getMathText()->draw(painter, Qt::AlignHCenter|Qt::AlignVCenter, QRect(topSpace.right()-(topSpace.width()-barWidth)/2, topSpace.y(), (topSpace.width()-barWidth)/2, topSpace.height())); + + + } + } +} + + +QStringList JKQTPColorPaletteStyleAndToolsMixin::getPalettes() { + return JKQTPImagePlot_getPredefinedPalettes(); +} + +int JKQTPColorPaletteStyleAndToolsMixin::getPalettesCount() +{ + return getPalettes().size(); +} + +QIcon JKQTPColorPaletteStyleAndToolsMixin::getPaletteIcon(int i) { + QImage img=getPaletteImage(i, JKQTPImageTools::PALETTE_ICON_WIDTH); + QPixmap pix(JKQTPImageTools::PALETTE_ICON_WIDTH,8); + QRect r(0,0,JKQTPImageTools::PALETTE_ICON_WIDTH-1,7); + QPainter p(&pix); + p.drawImage(r, img); + p.setPen(QPen(QColor("black"))); + p.drawRect(r); + p.end(); + return QIcon(pix); + +} + +QIcon JKQTPColorPaletteStyleAndToolsMixin::getPaletteIcon(JKQTPMathImageColorPalette palette) { + return getPaletteIcon(static_cast(palette)); +} + +QImage JKQTPColorPaletteStyleAndToolsMixin::getPaletteImage(int i, int width) +{ + QImage img; + double* pic=static_cast(malloc(width*sizeof(double))); + for (int j=0; j(pic, width, 1, img, (JKQTPMathImageColorPalette)i, 0, width-1); + free(pic); + return img; +} + +QImage JKQTPColorPaletteStyleAndToolsMixin::getPaletteImage(JKQTPMathImageColorPalette palette, int width) +{ + return getPaletteImage(static_cast(palette), width); +} + +QIcon JKQTPColorPaletteStyleAndToolsMixin::getPaletteKeyIcon(int i) +{ + QImage img=getPaletteKeyImage(i, JKQTPImageTools::PALETTE_ICON_WIDTH, JKQTPImageTools::PALETTE_IMAGEICON_HEIGHT); + QPixmap pix(JKQTPImageTools::PALETTE_ICON_WIDTH,JKQTPImageTools::PALETTE_IMAGEICON_HEIGHT); + QRect r(0,0,JKQTPImageTools::PALETTE_ICON_WIDTH-1,JKQTPImageTools::PALETTE_IMAGEICON_HEIGHT-1); + QPainter p(&pix); + p.drawImage(r, img); + p.setPen(QPen(QColor("black"))); + p.drawRect(r); + p.end(); + return QIcon(pix); +} + +QIcon JKQTPColorPaletteStyleAndToolsMixin::getPaletteKeyIcon(JKQTPMathImageColorPalette palette) +{ + return getPaletteIcon(static_cast(palette)); +} + +QImage JKQTPColorPaletteStyleAndToolsMixin::getPaletteKeyImage(int i, int width, int height) +{ + QImage img; + + const double x01=double(width)/3.0; + const double y01=double(height)/3.0*2.0; + const double w1x=double(width*width)/(5.0*5.0); + const double w1y=double(height*height)/(2.0*2.0); + const double x02=double(width)/3.0*2.0; + const double y02=double(height)/4.0; + const double w2x=double(width*width)/(8.0*8.0); + const double w2y=double(height*height)/(8.0*8.0); + + double* pic=static_cast(malloc(width*height*sizeof(double))); + double mmax=0; + for (int j=0; jmmax) mmax=pic[j]; + } + JKQTPImagePlot_array2image(pic, width, height, img, (JKQTPMathImageColorPalette)i, 0, mmax); + free(pic); + return img; +} + +QImage JKQTPColorPaletteStyleAndToolsMixin::getPaletteKeyImage(JKQTPMathImageColorPalette palette, int width, int height) +{ + return getPaletteKeyImage(static_cast(palette), width, height); +} + + +void JKQTPColorPaletteStyleAndToolsMixin::setPalette(int pal) { + palette=(JKQTPMathImageColorPalette)pal; +} + +void JKQTPColorPaletteStyleAndToolsMixin::cbSetParent(JKQTBasePlotter* parent) { + cbParent=parent; + colorBarRightAxis->setParent(parent); + colorBarTopAxis->setParent(parent); + +} + +void JKQTPColorPaletteStyleAndToolsMixin::setPalette(const JKQTPMathImageColorPalette &__value) +{ + this->palette = __value; +} + +JKQTPMathImageColorPalette JKQTPColorPaletteStyleAndToolsMixin::getPalette() const +{ + return this->palette; +} + +void JKQTPColorPaletteStyleAndToolsMixin::setRangeMinFailAction(const JKQTPMathImageColorRangeFailAction &__value) +{ + this->rangeMinFailAction = __value; +} + +JKQTPMathImageColorRangeFailAction JKQTPColorPaletteStyleAndToolsMixin::getActionRangeMinFail() const +{ + return this->rangeMinFailAction; +} + +void JKQTPColorPaletteStyleAndToolsMixin::setRangeMaxFailAction(const JKQTPMathImageColorRangeFailAction &__value) +{ + this->rangeMaxFailAction = __value; +} + +JKQTPMathImageColorRangeFailAction JKQTPColorPaletteStyleAndToolsMixin::getActionRangeMaxFail() const +{ + return this->rangeMaxFailAction; +} + +void JKQTPColorPaletteStyleAndToolsMixin::setRangeMinFailColor(const QColor &__value) +{ + this->rangeMinFailColor = __value; +} + +QColor JKQTPColorPaletteStyleAndToolsMixin::getRangeMinFailColor() const +{ + return this->rangeMinFailColor; +} + +void JKQTPColorPaletteStyleAndToolsMixin::setRangeMaxFailColor(const QColor &__value) +{ + this->rangeMaxFailColor = __value; +} + +QColor JKQTPColorPaletteStyleAndToolsMixin::getRangeMaxFailColor() const +{ + return this->rangeMaxFailColor; +} + +void JKQTPColorPaletteStyleAndToolsMixin::setNanColor(const QColor &__value) +{ + this->nanColor = __value; +} + +QColor JKQTPColorPaletteStyleAndToolsMixin::getNanColor() const +{ + return this->nanColor; +} + +void JKQTPColorPaletteStyleAndToolsMixin::setInfColor(const QColor &__value) +{ + this->infColor = __value; +} + +QColor JKQTPColorPaletteStyleAndToolsMixin::getInfColor() const +{ + return this->infColor; +} + +void JKQTPColorPaletteStyleAndToolsMixin::setShowColorBar(bool __value) +{ + this->showColorBar = __value; +} + +bool JKQTPColorPaletteStyleAndToolsMixin::getShowColorBar() const +{ + return this->showColorBar; +} + +void JKQTPColorPaletteStyleAndToolsMixin::setColorBarWidth(int __value) +{ + this->colorBarWidth = __value; +} + +int JKQTPColorPaletteStyleAndToolsMixin::getColorBarWidth() const +{ + return this->colorBarWidth; +} + +void JKQTPColorPaletteStyleAndToolsMixin::setColorBarOffset(int __value) +{ + this->colorBarOffset = __value; +} + +int JKQTPColorPaletteStyleAndToolsMixin::getColorBarOffset() const +{ + return this->colorBarOffset; +} + +void JKQTPColorPaletteStyleAndToolsMixin::setColorBarRelativeHeight(double __value) +{ + this->colorBarRelativeHeight = __value; +} + +double JKQTPColorPaletteStyleAndToolsMixin::getColorBarRelativeHeight() const +{ + return this->colorBarRelativeHeight; +} + +void JKQTPColorPaletteStyleAndToolsMixin::setImageMin(double __value) +{ + this->imageMin = __value; +} + +double JKQTPColorPaletteStyleAndToolsMixin::getImageMin() const +{ + return this->imageMin; +} + +void JKQTPColorPaletteStyleAndToolsMixin::setImageMax(double __value) +{ + this->imageMax = __value; +} + +double JKQTPColorPaletteStyleAndToolsMixin::getImageMax() const +{ + return this->imageMax; +} + +void JKQTPColorPaletteStyleAndToolsMixin::setAutoImageRange(bool __value) +{ + this->autoImageRange = __value; +} + +bool JKQTPColorPaletteStyleAndToolsMixin::getAutoImageRange() const +{ + return this->autoImageRange; +} + +void JKQTPColorPaletteStyleAndToolsMixin::setImageName(const QString &__value) +{ + this->imageName = __value; +} + +QString JKQTPColorPaletteStyleAndToolsMixin::getImageName() const +{ + return this->imageName; +} + +void JKQTPColorPaletteStyleAndToolsMixin::setImageNameFontName(const QString &__value) +{ + this->imageNameFontName = __value; +} + +QString JKQTPColorPaletteStyleAndToolsMixin::getImageNameFontName() const +{ + return this->imageNameFontName; +} + +void JKQTPColorPaletteStyleAndToolsMixin::setImageNameFontSize(double __value) +{ + this->imageNameFontSize = __value; +} + +double JKQTPColorPaletteStyleAndToolsMixin::getImageNameFontSize() const +{ + return this->imageNameFontSize; +} + +JKQTPVerticalIndependentAxis *JKQTPColorPaletteStyleAndToolsMixin::getColorBarRightAxis() { + return this->colorBarRightAxis; +} + +JKQTPHorizontalIndependentAxis *JKQTPColorPaletteStyleAndToolsMixin::getColorBarTopAxis() { + return this->colorBarTopAxis; +} + +const JKQTPVerticalIndependentAxis *JKQTPColorPaletteStyleAndToolsMixin::getColorBarRightAxis() const { + return this->colorBarRightAxis; +} + +const JKQTPHorizontalIndependentAxis *JKQTPColorPaletteStyleAndToolsMixin::getColorBarTopAxis() const { + return this->colorBarTopAxis; +} + +void JKQTPColorPaletteStyleAndToolsMixin::setColorBarTopVisible(bool __value) +{ + this->colorBarTopVisible = __value; +} + +bool JKQTPColorPaletteStyleAndToolsMixin::getColorBarTopVisible() const +{ + return this->colorBarTopVisible; +} + +void JKQTPColorPaletteStyleAndToolsMixin::setColorBarRightVisible(bool __value) +{ + this->colorBarRightVisible = __value; +} + +bool JKQTPColorPaletteStyleAndToolsMixin::getColorBarRightVisible() const +{ + return this->colorBarRightVisible; +} + diff --git a/lib/jkqtplotter/jkqtpimagetools.h b/lib/jkqtplotter/jkqtpimagetools.h new file mode 100644 index 0000000000..3fd6c0337e --- /dev/null +++ b/lib/jkqtplotter/jkqtpimagetools.h @@ -0,0 +1,243 @@ +/* + Copyright (c) 2008-2019 Jan W. Krieger () + + + + This software is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License (LGPL) as published by + the Free Software Foundation, either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License (LGPL) for more details. + + You should have received a copy of the GNU Lesser General Public License (LGPL) + along with this program. If not, see . +*/ + + +#ifndef JKQTPIMAGETOOLS_H +#define JKQTPIMAGETOOLS_H +#include +#include +#include +#include +#include "jkqtcommon/jkqtp_imexport.h" +#include "jkqtcommon/jkqtpbasicimagetools.h" +#include +#include +#include +#include +#include "jkqtplotter/jkqtptools.h" + +class JKQTPVerticalIndependentAxis; // forward +class JKQTPHorizontalIndependentAxis; // forward +class JKQTBasePlotter; // forward + +/*! \brief if a class is derived from this class, it may use color bars + \ingroup jkqtplotter_imagelots_tools + */ +class JKQTP_LIB_EXPORT JKQTPColorPaletteStyleAndToolsMixin { + Q_GADGET + public: + + JKQTPColorPaletteStyleAndToolsMixin(JKQTBasePlotter *parent); + virtual ~JKQTPColorPaletteStyleAndToolsMixin(); + + /*! \brief get list with all available palettes */ + static QStringList getPalettes() ; + /*! \brief get list with all available palettes */ + static int getPalettesCount() ; + /*! \brief get QIcon representing the given palette */ + static QIcon getPaletteIcon(int i) ; + /*! \brief get QIcon representing the given palette */ + static QIcon getPaletteIcon(JKQTPMathImageColorPalette palette) ; + /*! \brief get QIcon representing the given palette */ + static QImage getPaletteImage(int i, int width) ; + /*! \brief get QIcon representing the given palette */ + static QImage getPaletteImage(JKQTPMathImageColorPalette palette, int width) ; + + /*! \brief get QIcon representing the given palette */ + static QIcon getPaletteKeyIcon(int i) ; + /*! \brief get QIcon representing the given palette */ + static QIcon getPaletteKeyIcon(JKQTPMathImageColorPalette palette) ; + /*! \brief get QIcon representing the given palette */ + static QImage getPaletteKeyImage(int i, int width, int height) ; + /*! \brief get QIcon representing the given palette */ + static QImage getPaletteKeyImage(JKQTPMathImageColorPalette palette, int width, int height) ; + + + + + /*! \brief if the graph plots outside the actual plot field of view (e.g. color bars, scale bars, ...) + + \note If you want to draw outside, then you'll also have to implement drawOutside() + */ + void cbGetOutsideSize(JKQTPEnhancedPainter& painter, int& leftSpace, int& rightSpace, int& topSpace, int& bottomSpace); + + /*! \brief plots outside the actual plot field of view (e.g. color bars, scale bars, ...) + + \note If you want to draw outside, then you'll also have to implement getOutsideSize(), so enough space is reserved + + The four value supplied tell the method where to draw (inside one of the rectangles). + */ + void cbDrawOutside(JKQTPEnhancedPainter& painter, QRect leftSpace, QRect rightSpace, QRect topSpace, QRect bottomSpace); + + + /** \brief set the parent class for internal objects (e.g. color bars) */ + void cbSetParent(JKQTBasePlotter* parent); + + + /** \brief determine min/max data value of the image */ + virtual void cbGetDataMinMax(double& imin, double& imax)=0; + + + + + /*! \copydoc palette */ + void setPalette(int pal); + /*! \copydoc palette */ + void setPalette(const JKQTPMathImageColorPalette & __value); + /*! \copydoc palette */ + JKQTPMathImageColorPalette getPalette() const; + /*! \copydoc rangeMinFailAction */ + void setRangeMinFailAction(const JKQTPMathImageColorRangeFailAction & __value); + /*! \copydoc rangeMinFailAction */ + JKQTPMathImageColorRangeFailAction getActionRangeMinFail() const; + /*! \copydoc rangeMaxFailAction */ + void setRangeMaxFailAction(const JKQTPMathImageColorRangeFailAction & __value); + /*! \copydoc rangeMaxFailAction */ + JKQTPMathImageColorRangeFailAction getActionRangeMaxFail() const; + /*! \copydoc rangeMinFailColor */ + void setRangeMinFailColor(const QColor & __value); + /*! \copydoc rangeMinFailColor */ + QColor getRangeMinFailColor() const; + /*! \copydoc rangeMaxFailColor */ + void setRangeMaxFailColor(const QColor & __value); + /*! \copydoc rangeMaxFailColor */ + QColor getRangeMaxFailColor() const; + /*! \copydoc nanColor */ + void setNanColor(const QColor & __value); + /*! \copydoc nanColor */ + QColor getNanColor() const; + /*! \copydoc infColor */ + void setInfColor(const QColor & __value); + /*! \copydoc infColor */ + QColor getInfColor() const; + /*! \copydoc showColorBar */ + void setShowColorBar(bool __value); + /*! \copydoc showColorBar */ + bool getShowColorBar() const; + /*! \copydoc colorBarWidth */ + void setColorBarWidth(int __value); + /*! \copydoc colorBarWidth */ + int getColorBarWidth() const; + /*! \copydoc colorBarOffset */ + void setColorBarOffset(int __value); + /*! \copydoc colorBarOffset */ + int getColorBarOffset() const; + /*! \copydoc colorBarRelativeHeight */ + void setColorBarRelativeHeight(double __value); + /*! \copydoc colorBarRelativeHeight */ + double getColorBarRelativeHeight() const; + /*! \copydoc imageMin */ + void setImageMin(double __value); + /*! \copydoc imageMin */ + double getImageMin() const; + /*! \copydoc imageMax */ + void setImageMax(double __value); + /*! \copydoc imageMax */ + double getImageMax() const; + /*! \copydoc autoImageRange */ + void setAutoImageRange(bool __value); + /*! \copydoc autoImageRange */ + bool getAutoImageRange() const; + /*! \copydoc imageName */ + void setImageName(const QString & __value); + /*! \copydoc imageName */ + QString getImageName() const; + /*! \copydoc imageNameFontName */ + void setImageNameFontName(const QString & __value); + /*! \copydoc imageNameFontName */ + QString getImageNameFontName() const; + /*! \copydoc imageNameFontSize */ + void setImageNameFontSize(double __value); + /*! \copydoc imageNameFontSize */ + double getImageNameFontSize() const; + /*! \copydoc colorBarRightAxis */ + JKQTPVerticalIndependentAxis* getColorBarRightAxis(); + /*! \copydoc colorBarTopAxis */ + JKQTPHorizontalIndependentAxis* getColorBarTopAxis(); + /*! \copydoc colorBarRightAxis */ + const JKQTPVerticalIndependentAxis* getColorBarRightAxis() const; + /*! \copydoc colorBarTopAxis */ + const JKQTPHorizontalIndependentAxis* getColorBarTopAxis() const; + /*! \copydoc colorBarTopVisible */ + void setColorBarTopVisible(bool __value); + /*! \copydoc colorBarTopVisible */ + bool getColorBarTopVisible() const; + /*! \copydoc colorBarRightVisible */ + void setColorBarRightVisible(bool __value); + /*! \copydoc colorBarRightVisible */ + bool getColorBarRightVisible() const; + + + protected: + JKQTBasePlotter* cbParent; + + + /** \brief top color bar visible */ + bool colorBarTopVisible; + /** \brief right color bar visible */ + bool colorBarRightVisible; + /** \brief name of the image displayed above color bar (may contain LaTeX markup!) */ + QString imageName; + /** \brief font name when displaying imageName */ + QString imageNameFontName; + /** \brief font size in points when displaying imageName */ + double imageNameFontSize; + /** \brief palette for plotting an image */ + JKQTPMathImageColorPalette palette; + /** \brief indicate whether to display a color bar */ + bool showColorBar; + /** \brief width of the color bar */ + int colorBarWidth; + /** \brief height of the color bar, as multiple of plotHeight */ + double colorBarRelativeHeight; + /** \brief indicates whether to estimate min/max of the image automatically */ + bool autoImageRange; + /** \brief image value range minimum */ + double imageMin; + /** \brief image value range maximum */ + double imageMax; + /** \brief offset between outside space border and color bar */ + int colorBarOffset; + /** \brief which action to take if a color is below \a imageMin and \a autoImageRange \c ==false */ + JKQTPMathImageColorRangeFailAction rangeMinFailAction; + /** \brief which action to take if a color is above \a imageMax and \a autoImageRange \c ==false */ + JKQTPMathImageColorRangeFailAction rangeMaxFailAction; + /** \brief color to use for some settings of \a rangeMinFailAction */ + QColor rangeMinFailColor; + /** \brief color to use for some settings of \a rangeMaxFailAction */ + QColor rangeMaxFailColor; + /** \brief color to use for a not-a-number value */ + QColor nanColor; + /** \brief color to use for an infinity value */ + QColor infColor; + + + /** \brief object used for color bar axes + * + * \note this axis has some kind of a special role. It is used to format color bar axes + */ + JKQTPVerticalIndependentAxis* colorBarRightAxis; + JKQTPHorizontalIndependentAxis* colorBarTopAxis; + + + +}; + + +#endif // JKQTPIMAGETOOLS_H diff --git a/lib/jkqtplotter/jkqtpkeystyle.h b/lib/jkqtplotter/jkqtpkeystyle.h index 2c4bd9a9cd..af33a20173 100644 --- a/lib/jkqtplotter/jkqtpkeystyle.h +++ b/lib/jkqtplotter/jkqtpkeystyle.h @@ -20,7 +20,7 @@ #ifndef JKQTPSTYLE_H #define JKQTPSTYLE_H -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtcommon/jkqtp_imexport.h" #include #include diff --git a/lib/jkqtplotter/jkqtplotter.cpp b/lib/jkqtplotter/jkqtplotter.cpp index 8520b6eae7..aa92963304 100644 --- a/lib/jkqtplotter/jkqtplotter.cpp +++ b/lib/jkqtplotter/jkqtplotter.cpp @@ -525,7 +525,7 @@ void JKQTPlotter::paintUserAction() { getPlotter()->getMathText()->draw(painter, Qt::AlignBottom, rec); } - txt=QString::fromStdString(jkqtp_floattolatexstr(dy, 3)); + txt=jkqtp_floattolatexqstr(dy, 3); getPlotter()->getMathText()->parse("\\delta_{y}="+txt); getPlotter()->getMathText()->getSizeDetail(painter, w, a, d, so); //double dyh=a+d; diff --git a/lib/jkqtplotter/jkqtplotter.h b/lib/jkqtplotter/jkqtplotter.h index 7eb7a746bb..18880fd27f 100644 --- a/lib/jkqtplotter/jkqtplotter.h +++ b/lib/jkqtplotter/jkqtplotter.h @@ -41,7 +41,7 @@ #include "jkqtplotter/jkqtpbaseplotter.h" #include "jkqtplotter/jkqtplotterstyle.h" #include "jkqtplotter/jkqtpbaseplotterstyle.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtcommon/jkqtp_imexport.h" #include "jkqtplottergui/jkvanishqtoolbar.h" #include diff --git a/lib/jkqtplotter/jkqtplotterstyle.cpp b/lib/jkqtplotter/jkqtplotterstyle.cpp index b664aeb401..a1159868ff 100644 --- a/lib/jkqtplotter/jkqtplotterstyle.cpp +++ b/lib/jkqtplotter/jkqtplotterstyle.cpp @@ -1,7 +1,7 @@ #include "jkqtplotterstyle.h" #include -#include "jkqtplottertools/jkqttools.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtcommon/jkqttools.h" +#include "jkqtplotter/jkqtptools.h" JKQTPlotterStyle::JKQTPlotterStyle(): maxTooltipDistance(16), diff --git a/lib/jkqtplotter/jkqtplotterstyle.h b/lib/jkqtplotter/jkqtplotterstyle.h index 9067ab2f99..b27f697a7c 100644 --- a/lib/jkqtplotter/jkqtplotterstyle.h +++ b/lib/jkqtplotter/jkqtplotterstyle.h @@ -20,7 +20,7 @@ #ifndef JKQTPLOTTERSTYLE_H #define JKQTPLOTTERSTYLE_H -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtcommon/jkqtp_imexport.h" #include #include diff --git a/lib/jkqtcommon/jkqtptools.cpp b/lib/jkqtplotter/jkqtptools.cpp similarity index 55% rename from lib/jkqtcommon/jkqtptools.cpp rename to lib/jkqtplotter/jkqtptools.cpp index c82fd13fde..3beeeb7615 100644 --- a/lib/jkqtcommon/jkqtptools.cpp +++ b/lib/jkqtplotter/jkqtptools.cpp @@ -21,8 +21,8 @@ Copyright (c) 2008-2019 Jan W. Krieger () -#include "jkqtcommon/jkqtptools.h" -#include "jkqtplottertools/jkqtpenhancedpainter.h" +#include "jkqtplotter/jkqtptools.h" +#include "jkqtcommon/jkqtpenhancedpainter.h" #include #include #include @@ -239,221 +239,6 @@ JKQTPErrorPlotstyle String2JKQTPErrorPlotstyle(const QString& pos) { -QString JKQTPGraphSymbols2String(JKQTPGraphSymbols pos) { - switch(pos) { - case JKQTPDot: return "symbol_dot"; - case JKQTPCross: return "symbol_cross"; - case JKQTPPlus: return "symbol_plus"; - case JKQTPCircle: return "symbol_circle"; - case JKQTPFilledCircle: return "symbol_filled_circle"; - case JKQTPRect: return "symbol_rect"; - case JKQTPFilledRect: return "symbol_filled_rect"; - case JKQTPTriangle: return "symbol_triangle"; - case JKQTPFilledTriangle: return "symbol_filled_triangle"; - case JKQTPDownTriangle: return "symbol_down_triangle"; - case JKQTPFilledDownTriangle: return "symbol_filled_down_triangle"; - case JKQTPTarget: return "symbol_target"; - case JKQTPstar: return "symbol_star"; - case JKQTPFilledStar: return "symbol_filled_star"; - case JKQTPDiamond: return "symbol_diamond"; - case JKQTPFilledDiamond: return "symbol_filled_diamond"; - case JKQTPPentagon: return "symbol_pentagon"; - case JKQTPAsterisc: return "symbol_asterisc"; - case JKQTPAsterisc6: return "symbol_asterisc6"; - case JKQTPAsterisc8: return "symbol_asterisc8"; - case JKQTPFilledPentagon: return "symbol_filled_pentagon"; - case JKQTPHexagon: return "symbol_hexagon"; - case JKQTPFilledHexagon: return "symbol_filled_hexagon"; - case JKQTPOctagon: return "symbol_octagon"; - case JKQTPFilledOctagon: return "symbol_filled_octagon"; - case JKQTPRectCross: return "symbol_rect_cross"; - case JKQTPRectPlus: return "symbol_rect_plus"; - case JKQTPNoSymbol: return "none"; - case JKQTPDiamondPlus: return "symbol_diamond_plus"; - case JKQTPDiamondCross: return "symbol_diamond_cross"; - case JKQTPCircleCross: return "symbol_circle_cross"; - case JKQTPCirclePlus: return "symbol_circle_plus"; - case JKQTPUpDownTriangle: return "symbol_updowntriangle"; - case JKQTPFilledUpDownTriangle: return "symbol_filled_updowntriangle"; - case JKQTPSantaClauseHouse: return "symbol_santaclause"; - case JKQTPFilledSantaClauseHouse: return "symbol_filled_santaclause"; - case JKQTPHourglass: return "symbol_hourglass"; - case JKQTPFilledHourglass: return "symbol_filled_hourglass"; - case JKQTPHorizontalHourglass: return "symbol_horizontal_hourglass"; - case JKQTPFilledHorizontalHourglass: return "symbol_filled_horizontal_hourglass"; - case JKQTPRectTriangle: return "symbol_rect_triangle"; - case JKQTPRectDownTriangle: return "symbol_rect_downtriangle"; - case JKQTPRectLeftTriangle: return "symbol_rect_lefttriangle"; - case JKQTPRectRightTriangle: return "symbol_rect_righttriangle"; - case JKQTPLeftTriangle: return "symbol_left_triangle"; - case JKQTPFilledLeftTriangle: return "symbol_filled_left_triangle"; - case JKQTPRightTriangle: return "symbol_right_triangle"; - case JKQTPFilledRightTriangle: return "symbol_filled_right_triangle"; - case JKQTPTripod: return "symbol_tripod"; - case JKQTPDownTripod: return "symbol_down_tripod"; - case JKQTPLeftTripod: return "symbol_left_tripod"; - case JKQTPRightTripod: return "symbol_right_tripod"; - case JKQTPFilledCurvedTriangle: return "symbol_filled_curved_triangle"; - case JKQTPFilledDownCurvedTriangle: return "symbol_filled_down_curved_triangle"; - case JKQTPFilledLeftCurvedTriangle: return "symbol_filled_left_curved_triangle"; - case JKQTPFilledRightCurvedTriangle: return "symbol_filled_right_curved_triangle"; - case JKQTPCurvedTriangle: return "symbol_curved_triangle"; - case JKQTPDownCurvedTriangle: return "symbol_down_curved_triangle"; - case JKQTPLeftCurvedTriangle: return "symbol_left_curved_triangle"; - case JKQTPRightCurvedTriangle: return "symbol_right_curved_triangle"; - case JKQTPPeace: return "symbol_peace"; - case JKQTPFemale: return "symbol_female"; - case JKQTPMale: return "symbol_male"; - case JKQTPCirclePeace: return "symbol_circle_peace"; - case JKQTPSymbolCount: JKQTPGraphSymbols2String(JKQTPMaxSymbolID); - } - return ""; -} - -QString JKQTPGraphSymbols2NameString(JKQTPGraphSymbols pos) { - switch(pos) { - case JKQTPDot: return QObject::tr("dot"); - case JKQTPCross: return QObject::tr("cross"); - case JKQTPPlus: return QObject::tr("plus"); - case JKQTPCircle: return QObject::tr("circle"); - case JKQTPFilledCircle: return QObject::tr("filled circle"); - case JKQTPRect: return QObject::tr("rectangle"); - case JKQTPFilledRect: return QObject::tr("filled rectangle"); - case JKQTPTriangle: return QObject::tr("triangle"); - case JKQTPFilledTriangle: return QObject::tr("filled triangle"); - case JKQTPDownTriangle: return QObject::tr("down triangle"); - case JKQTPFilledDownTriangle: return QObject::tr("filled down triangle"); - case JKQTPstar: return QObject::tr("star"); - case JKQTPFilledStar: return QObject::tr("filled star"); - case JKQTPDiamond: return QObject::tr("diamond"); - case JKQTPFilledDiamond: return QObject::tr("filled diamond"); - case JKQTPPentagon: return QObject::tr("pentagon"); - case JKQTPFilledPentagon: return QObject::tr("filled pentagon"); - case JKQTPHexagon: return QObject::tr("hexagon"); - case JKQTPFilledHexagon: return QObject::tr("filled hexagon"); - case JKQTPOctagon: return QObject::tr("octagon"); - case JKQTPFilledOctagon: return QObject::tr("filled octagon"); - case JKQTPTarget: return QObject::tr("target"); - case JKQTPAsterisc: return QObject::tr("asterisc, 5-arm"); - case JKQTPAsterisc6: return QObject::tr("asterisc, 6-arm"); - case JKQTPAsterisc8: return QObject::tr("asterisc, 8-arm"); - case JKQTPRectCross: return QObject::tr("square with cross"); - case JKQTPRectPlus: return QObject::tr("square with plus"); - case JKQTPNoSymbol: return QObject::tr("none"); - case JKQTPDiamondPlus: return QObject::tr("diamond with plus"); - case JKQTPDiamondCross: return QObject::tr("diamond with cross"); - case JKQTPCircleCross: return QObject::tr("circled cross"); - case JKQTPCirclePlus: return QObject::tr("circled plus"); - case JKQTPUpDownTriangle: return QObject::tr("up/down triangle"); - case JKQTPFilledUpDownTriangle: return QObject::tr("filled up/down triangle"); - case JKQTPSantaClauseHouse: return QObject::tr("santa clause"); - case JKQTPFilledSantaClauseHouse: return QObject::tr("filled santa clause"); - case JKQTPHourglass: return QObject::tr("hourglass"); - case JKQTPFilledHourglass: return QObject::tr("filled hourglass"); - case JKQTPHorizontalHourglass: return QObject::tr("horizontal hourglass"); - case JKQTPFilledHorizontalHourglass: return QObject::tr("filled horizontal hourglass"); - case JKQTPRectTriangle: return QObject::tr("rectangle with triangle"); - case JKQTPRectDownTriangle: return QObject::tr("rectangle with downwards triangle"); - case JKQTPRectLeftTriangle: return QObject::tr("rectangle with leftwards triangle"); - case JKQTPRectRightTriangle: return QObject::tr("rectangle with rightwards triangle"); - case JKQTPLeftTriangle: return QObject::tr("left triangle"); - case JKQTPFilledLeftTriangle: return QObject::tr("filled left triangle"); - case JKQTPRightTriangle: return QObject::tr("right triangle"); - case JKQTPFilledRightTriangle: return QObject::tr("filled right triangle"); - case JKQTPTripod: return QObject::tr("tripod"); - case JKQTPDownTripod: return QObject::tr("down tripod"); - case JKQTPLeftTripod: return QObject::tr("left tripod"); - case JKQTPRightTripod: return QObject::tr("right tripod"); - case JKQTPFilledCurvedTriangle: return QObject::tr("filled curved triangle"); - case JKQTPFilledDownCurvedTriangle: return QObject::tr("filled down curved triangle"); - case JKQTPFilledLeftCurvedTriangle: return QObject::tr("filled left curved triangle"); - case JKQTPFilledRightCurvedTriangle: return QObject::tr("filled right curved triangle"); - case JKQTPCurvedTriangle: return QObject::tr("curved triangle"); - case JKQTPDownCurvedTriangle: return QObject::tr("down curved triangle"); - case JKQTPLeftCurvedTriangle: return QObject::tr("left curved triangle"); - case JKQTPRightCurvedTriangle: return QObject::tr("right curved triangle"); - case JKQTPPeace: return QObject::tr("peace"); - case JKQTPFemale: return QObject::tr("female"); - case JKQTPMale: return QObject::tr("male"); - case JKQTPCirclePeace: return QObject::tr("circled peace"); - case JKQTPSymbolCount: JKQTPGraphSymbols2NameString(JKQTPMaxSymbolID); - } - return ""; -} -JKQTPGraphSymbols String2JKQTPGraphSymbols(const QString& pos) { - QString s=pos.trimmed().toLower(); - if (s=="symbol_dot"||s=="dot"||s==".") return JKQTPDot; - if (s=="symbol_cross"||s=="cross"||s=="x") return JKQTPCross; - if (s=="symbol_plus"||s=="plus"||s=="+") return JKQTPPlus; - if (s=="symbol_circle"||s=="circle"||s=="o") return JKQTPCircle; - if (s=="symbol_filled_circle"||s=="filled_circle"||s=="fo") return JKQTPFilledCircle; - if (s=="symbol_rect"||s=="rect"||s=="r") return JKQTPRect; - if (s=="symbol_filled_rect"||s=="filled_rect"||s=="fr") return JKQTPFilledRect; - if (s=="symbol_triangle"||s=="triangle"||s=="^") return JKQTPTriangle; - if (s=="symbol_filled_triangle"||s=="filled_triangle"||s=="f^") return JKQTPFilledTriangle; - if (s=="symbol_down_triangle"||s=="down_triangle"||s=="v") return JKQTPDownTriangle; - if (s=="symbol_filles_down_triangle"||s=="filles_down_triangle"||s=="symbol_filled_down_triangle"||s=="filled_down_triangle"||s=="fv") return JKQTPFilledDownTriangle; - if (s=="symbol_target"||s=="target"||s=="t") return JKQTPTarget; - if (s=="symbol_star"||s=="star"||s=="s") return JKQTPstar; - if (s=="symbol_filled_star"||s=="filled_star"||s=="fs") return JKQTPFilledStar; - if (s=="symbol_diamond"||s=="diamond"||s=="d") return JKQTPDiamond; - if (s=="symbol_filled_diamond"||s=="filled_diamond"||s=="fd") return JKQTPFilledDiamond; - if (s=="symbol_pentagon"||s=="pentagon"||s=="p") return JKQTPPentagon; - if (s=="symbol_filled_pentagon"||s=="filled_pentagon"||s=="fp") return JKQTPFilledPentagon; - if (s=="symbol_hexagon"||s=="hexagon"||s=="h") return JKQTPHexagon; - if (s=="symbol_filled_hexagon"||s=="filled_hexagon"||s=="fh") return JKQTPFilledHexagon; - if (s=="symbol_octagon"||s=="octagon"||s=="h") return JKQTPOctagon; - if (s=="symbol_filled_octagon"||s=="filled_octagon"||s=="fh") return JKQTPFilledOctagon; - if (s=="symbol_asterisc"||s=="asterisc"||s=="*") return JKQTPAsterisc; - if (s=="symbol_asterisc6"||s=="asterisc6"||s=="*6") return JKQTPAsterisc6; - if (s=="symbol_asterisc8"||s=="asterisc8"||s=="*8") return JKQTPAsterisc8; - if (s=="symbol_rect_cross"||s=="rect_cross"||s=="rx") return JKQTPRectCross; - if (s=="symbol_rect_plus"||s=="rect_plus"||s=="r+") return JKQTPRectPlus; - if (s=="symbol_diamond_plus" || s=="diamond_plus") return JKQTPDiamondPlus; - if (s=="symbol_diamond_cross" || s=="diamond_cross") return JKQTPDiamondCross; - if (s=="symbol_circle_cross" || s=="circle_cross") return JKQTPCircleCross; - if (s=="symbol_circle_plus" || s=="circle_plus") return JKQTPCirclePlus; - if (s=="symbol_updowntriangle" || s=="updowntriangle") return JKQTPUpDownTriangle; - if (s=="symbol_filled_updowntriangle" || s=="filled_updowntriangle") return JKQTPFilledUpDownTriangle; - if (s=="symbol_santaclause" || s=="santaclause") return JKQTPSantaClauseHouse; - if (s=="symbol_filled_santaclause" || s=="filled_santaclause") return JKQTPFilledSantaClauseHouse; - if (s=="symbol_hourglass" || s=="hourglass") return JKQTPHourglass; - if (s=="symbol_filled_hourglass" || s=="filled_hourglass") return JKQTPFilledHourglass; - if (s=="symbol_horizontal_hourglass" || s=="horizontal_hourglass") return JKQTPHorizontalHourglass; - if (s=="symbol_filled_horizontal_hourglass" || s=="filled_horizontal_hourglass") return JKQTPFilledHorizontalHourglass; - if (s=="symbol_rect_triangle" || s=="rect_triangle") return JKQTPRectTriangle; - if (s=="symbol_rect_downtriangle" || s=="rect_downtriangle") return JKQTPRectDownTriangle; - if (s=="symbol_rect_lefttriangle" || s=="rect_lefttriangle") return JKQTPRectLeftTriangle; - if (s=="symbol_rect_righttriangle" || s=="rect_righttriangle") return JKQTPRectRightTriangle; - if (s=="symbol_left_triangle" || s=="left_triangle") return JKQTPLeftTriangle; - if (s=="symbol_filled_left_triangle" || s=="filled_left_triangle") return JKQTPFilledLeftTriangle; - if (s=="symbol_right_triangle" || s=="right_triangle") return JKQTPRightTriangle; - if (s=="symbol_filled_right_triangle" || s=="filled_right_triangle") return JKQTPFilledRightTriangle; - if (s=="symbol_tripod" || s=="tripod") return JKQTPTripod; - if (s=="symbol_down_tripod" || s=="down_tripod") return JKQTPDownTripod; - if (s=="symbol_left_tripod" || s=="left_tripod") return JKQTPLeftTripod; - if (s=="symbol_right_tripod" || s=="right_tripod") return JKQTPRightTripod; - if (s=="symbol_filled_curved_triangle" || s=="filled_curved_triangle") return JKQTPFilledCurvedTriangle; - if (s=="symbol_filled_down_curved_triangle" || s=="filled_down_curved_triangle") return JKQTPFilledDownCurvedTriangle; - if (s=="symbol_filled_left_curved_triangle" || s=="filled_left_curved_triangle") return JKQTPFilledLeftCurvedTriangle; - if (s=="symbol_filled_right_curved_triangle" || s=="filled_right_curved_triangle") return JKQTPFilledRightCurvedTriangle; - if (s=="symbol_curved_triangle" || s=="curved_triangle") return JKQTPCurvedTriangle; - if (s=="symbol_down_curved_triangle" || s=="down_curved_triangle") return JKQTPDownCurvedTriangle; - if (s=="symbol_left_curved_triangle" || s=="left_curved_triangle") return JKQTPLeftCurvedTriangle; - if (s=="symbol_right_curved_triangle" || s=="right_curved_triangle") return JKQTPRightCurvedTriangle; - if (s=="symbol_peace" || s=="peace") return JKQTPPeace; - if (s=="symbol_circle_peace" || s=="circle_peace") return JKQTPCirclePeace; - if (s=="symbol_female" || s=="female") return JKQTPFemale; - if (s=="symbol_male" || s=="male") return JKQTPMale; - - return JKQTPNoSymbol; -} - - - - - - QString JKQTPSpecialLineType2String(JKQTPSpecialLineType pos) { switch(pos) { diff --git a/lib/jkqtcommon/jkqtptools.h b/lib/jkqtplotter/jkqtptools.h similarity index 65% rename from lib/jkqtcommon/jkqtptools.h rename to lib/jkqtplotter/jkqtptools.h index 6e5bf755f4..a59ed12aa4 100644 --- a/lib/jkqtcommon/jkqtptools.h +++ b/lib/jkqtplotter/jkqtptools.h @@ -43,32 +43,11 @@ #include #include #include -#include "jkqtpstringtools.h" -#include "jkqtptoolsdebugging.h" -#include "jkqtpcommonmathtools.h" -#include "jkqtpalgorithms.h" - - -#ifndef __WINDOWS__ -# if defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32) -# define __WINDOWS__ -# endif -#endif - -#ifndef __LINUX__ -# if defined(linux) -# define __LINUX__ -# endif -#endif - -#undef JKTOOLS_TIMER_USE_TIME -#if defined(__WINDOWS__) - #include -#elif defined(__LINUX__) - #include -#else - #define JKTOOLS_TIMER_USE_TIME -#endif +#include "jkqtcommon/jkqtpstringtools.h" +#include "jkqtcommon/jkqtptoolsdebugging.h" +#include "jkqtcommon/jkqtpmathtools.h" +#include "jkqtcommon/jkqtpalgorithms.h" +#include "jkqtcommon/jkqtpcodestructuring.h" @@ -78,103 +57,6 @@ class JKQTPEnhancedPainter; // forward class JKQTBasePlotter; // forward declaration -/** \brief C++11 finally construct (executes a callable-object when the edestructor is executed) - * \ingroup jkqtptools_codestructuring - * - * Typical usage: - * \code - * { - * // the instruction 'painter.restore()' will be executed at the end - * // of the block, when __finalpaint is destroyed (see (*) below) - * JKQTPFinalAct __finalpaint([&painter]() { painter.restore(); }); - * - * // ... - * // do something ... - * // ... - * - * } // (*) 'painter.restore()' is executed before the end of this block! - * \endcode - * - * \see JKQTPFinally() - */ -template -class JKQTPFinalAct -{ -public: - explicit JKQTPFinalAct(F f) noexcept - : f_(std::move(f)), invoke_(true) {} - - JKQTPFinalAct(JKQTPFinalAct&& other) noexcept - : f_(std::move(other.f_)), - invoke_(other.invoke_) - { - other.invoke_ = false; - } - - JKQTPFinalAct(const JKQTPFinalAct&) = delete; - JKQTPFinalAct& operator=(const JKQTPFinalAct&) = delete; - - ~JKQTPFinalAct() noexcept - { - if (invoke_) f_(); - } - -private: - F f_; - bool invoke_; -}; - -/** \brief C++11 finally construct (executes a callable-object at the end of a scope) - * \ingroup jkqtptools_codestructuring - * - * Typical usage: - * \code - * { - * // the instruction 'painter.restore()' will be executed at the end - * // of the block, when __finalpaint is destroyed (see (*) below) - * auto __finalpaint=JKQTPFinally([&painter]() { painter.restore(); }); - * - * // ... - * // do something ... - * // ... - * - * } // (*) 'painter.restore()' is executed before the end of this block! - * \endcode - * - * \see JKQTPFinalAct - */ -template -inline JKQTPFinalAct JKQTPFinally(const F& f) noexcept -{ - return JKQTPFinalAct(f); -} - -/** \brief C++11 finally construct (executes a callable-object at the end of a scope) - * \ingroup jkqtptools_codestructuring - * - * Typical usage: - * \code - * { - * // the instruction 'painter.restore()' will be executed at the end - * // of the block, when __finalpaint is destroyed (see (*) below) - * auto __finalpaint=JKQTPFinally([&painter]() { painter.restore(); }); - * - * // ... - * // do something ... - * // ... - * - * } // (*) 'painter.restore()' is executed before the end of this block! - * \endcode - * - * \see JKQTPFinalAct - */ -template -inline JKQTPFinalAct JKQTPFinally(F&& f) noexcept -{ - return JKQTPFinalAct(std::forward(f)); -} - - /** \brief Styles in which to mark single positions during user actions in JKQTPlotter * \ingroup jkqtpplottersupprt @@ -435,7 +317,7 @@ JKQTP_LIB_EXPORT JKQTPCADrawMode String2JKQTPCADrawMode(const QString& pos); * \ingroup jkqtpplottersupprt */ enum JKQTPCALabelType { JKQTPCALTdefault, /*!< \brief simply print the numbers \image html JKQTPCALTdefault.png */ - JKQTPCALTexponentCharacter, /*!< \brief print the numbers and show a unit character, i.e. \c 5µ for \f$ 5\cdot 10^{-6} \f$ , \c 3k for \f$ 3\cdot 10^3 \f$ ... */ + JKQTPCALTexponentCharacter, /*!< \brief print the numbers and show a unit character, i.e. 5μ for \f$ 5\cdot 10^{-6} \f$ , \c 3k for \f$ 3\cdot 10^3 \f$ ... */ JKQTPCALTexponent, /*!< \brief show numbers in exponential for, e.g. \f$ 3\cdot 10^5 \f$ ... \image html JKQTPCALTexponent.png */ JKQTPCALTdate, /*!< \brief show numbers as dates \image html JKQTPCALTdate.png */ JKQTPCALTtime, /*!< \brief show numbers as times \image html JKQTPCALTtime.png*/ @@ -604,102 +486,6 @@ enum JKQTPGraphPlotstyle { JKQTPStepsY /*!< \brief plot x=f(y), as a step curve */ }; -/** \brief symbols that can be used to plot a datapoint for a graph - * \ingroup jkqtptools_drawing - */ -enum JKQTPGraphSymbols { - JKQTPNoSymbol=0, /*!< \brief plots no symbol at all (usefull together with error bars) */ - JKQTPDot, /*!< \brief a small dot \image html symbols/symbol_dot.png */ - JKQTPCross, /*!< \brief a X cross \image html symbols/symbol_cross.png */ - JKQTPPlus, /*!< \brief a + cross \image html symbols/symbol_plus.png */ - JKQTPCircle, /*!< \brief an unfilled circle \image html symbols/symbol_circle.png */ - JKQTPFilledCircle, /*!< \brief a filled circle \image html symbols/symbol_filled_circle.png */ - JKQTPRect, /*!< \brief an unfilled rectangle \image html symbols/symbol_rect.png */ - JKQTPFilledRect, /*!< \brief a filled rectangle \image html symbols/symbol_filled_rect.png */ - JKQTPTriangle, /*!< \brief an unfilled triangle (tip at top) \image html symbols/symbol_triangle.png */ - JKQTPFilledTriangle, /*!< \brief a filled triangle (tip at top) \image html symbols/symbol_filled_triangle.png */ - JKQTPDiamond, /*!< \brief an unfilled diamond \image html symbols/symbol_diamond.png */ - JKQTPFilledDiamond, /*!< \brief a filled diamond \image html symbols/symbol_filled_diamond.png */ - JKQTPstar, /*!< \brief an unfilled diamond \image html symbols/symbol_star.png */ - JKQTPFilledStar, /*!< \brief a filled diamond \image html symbols/symbol_filled_star.png */ - JKQTPPentagon, /*!< \brief an unfilled pentagon \image html symbols/symbol_pentagon.png */ - JKQTPFilledPentagon, /*!< \brief a filled pentagon \image html symbols/symbol_filled_pentagon.png */ - JKQTPAsterisc, /*!< \brief an asterisc star with 5 arms \image html symbols/symbol_asterisc.png */ - JKQTPHourglass, /*!< \brief an hour glass symbol \image html symbols/symbol_hourglass.png */ - JKQTPFilledHourglass, /*!< \brief a filled hour glass symbol \image html symbols/symbol_filled_hourglass.png */ - JKQTPCurvedTriangle, /*!< \brief a curved triangle\image html symbols/symbol_curved_triangle.png */ - JKQTPFilledCurvedTriangle, /*!< \brief a filled curved triangle\image html symbols/symbol_filled_curved_triangle.png */ - JKQTPHexagon, /*!< \brief an unfilled hexagon \image html symbols/symbol_hexagon.png */ - JKQTPFilledHexagon, /*!< \brief a filled hexagon \image html symbols/symbol_filled_hexagon.png */ - - JKQTPRectCross, /*!< \brief a square symbol with a cross inside \image html symbols/symbol_rect_cross.png */ - JKQTPRectPlus, /*!< \brief a square symbol with a plus inside \image html symbols/symbol_rect_plus.png */ - JKQTPRectTriangle, /*!< \brief a square symbol with a triangle inside \image html symbols/symbol_rect_triangle.png */ - JKQTPRectDownTriangle, /*!< \brief a square symbol with a triangle (tip to the bottom) inside \image html symbols/symbol_rect_downtriangle.png */ - JKQTPRectLeftTriangle, /*!< \brief a square symbol with a triangle (tip to the left) inside \image html symbols/symbol_rect_lefttriangle.png */ - JKQTPRectRightTriangle, /*!< \brief a square symbol with a triangle (tip to the right) inside \image html symbols/symbol_rect_righttriangle.png */ - - JKQTPCircleCross, /*!< \brief a circle symbol with a cross inside \image html symbols/symbol_circle_cross.png */ - JKQTPCirclePlus, /*!< \brief a circle symbol with a plus inside \image html symbols/symbol_circle_plus.png */ - JKQTPCirclePeace, /*!< \brief a circled peace symbol \image html symbols/symbol_circle_peace.png */ - - JKQTPDiamondPlus, /*!< \brief a diamond symbol with a plus inside \image html symbols/symbol_diamond_plus.png */ - JKQTPDiamondCross, /*!< \brief a diamond symbol with a cross inside \image html symbols/symbol_diamond_cross.png */ - - JKQTPTripod, /*!< \brief a tripod symbol \image html symbols/symbol_tripod.png */ - JKQTPDownTripod, /*!< \brief a tripod symbol, pointing down \image html symbols/symbol_down_tripod.png */ - JKQTPLeftTripod, /*!< \brief a tripod symbol, pointing to the left \image html symbols/symbol_left_tripod.png */ - JKQTPRightTripod, /*!< \brief a tripod symbol, pointing to the right \image html symbols/symbol_right_tripod.png */ - JKQTPAsterisc6, /*!< \brief an asterisc star with 6 arms \image html symbols/symbol_asterisc6.png */ - JKQTPAsterisc8, /*!< \brief an asterisc star with 8 arms \image html symbols/symbol_asterisc8.png */ - JKQTPPeace, /*!< \brief a peace symbol \image html symbols/symbol_peace.png */ - JKQTPTarget, /*!< \brief a target symbol (circle with cross) \image html symbols/symbol_target.png */ - - JKQTPDownTriangle, /*!< \brief an unfilled triangle (tip at bottom) \image html symbols/symbol_down_triangle.png */ - JKQTPFilledDownTriangle, /*!< \brief a filled triangle (tip at bottom) \image html symbols/symbol_filled_down_triangle.png */ - JKQTPLeftTriangle, /*!< \brief an unfilled triangle (tip to the left) \image html symbols/symbol_left_triangle.png */ - JKQTPFilledLeftTriangle, /*!< \brief a filled triangle (tip to the left) \image html symbols/symbol_filled_left_triangle.png */ - JKQTPRightTriangle, /*!< \brief an unfilled triangle (tip to the right) \image html symbols/symbol_right_triangle.png */ - JKQTPFilledRightTriangle, /*!< \brief a filled triangle (tip to the right) \image html symbols/symbol_filled_right_triangle.png */ - JKQTPDownCurvedTriangle, /*!< \brief a curved triangle, pointing down \image html symbols/symbol_down_curved_triangle.png */ - JKQTPFilledDownCurvedTriangle, /*!< \brief a filled curved triangle, pointing down \image html symbols/symbol_filled_down_curved_triangle.png */ - JKQTPLeftCurvedTriangle, /*!< \brief a curved triangle, pointing to the left \image html symbols/symbol_left_curved_triangle.png */ - JKQTPFilledLeftCurvedTriangle, /*!< \brief a filled curved triangle, pointing to the left \image html symbols/symbol_filled_left_curved_triangle.png */ - JKQTPRightCurvedTriangle, /*!< \brief a curved triangle, pointing to the right \image html symbols/symbol_right_curved_triangle.png */ - JKQTPFilledRightCurvedTriangle, /*!< \brief a filled curved triangle, pointing to the right \image html symbols/symbol_filled_right_curved_triangle.png */ - JKQTPOctagon, /*!< \brief an unfilled octagon \image html symbols/symbol_octagon.png */ - JKQTPFilledOctagon, /*!< \brief a filled octagon \image html symbols/symbol_filled_octagon.png */ - JKQTPUpDownTriangle, /*!< \brief a overlay of an up and a down triangle symbol \image html symbols/symbol_updowntriangle.png */ - JKQTPFilledUpDownTriangle, /*!< \brief a filled version of the overlay of an up and a down triangle \image html symbols/symbol_filled_updowntriangle.png */ - JKQTPHorizontalHourglass, /*!< \brief a horizontal hour glass symbol \image html symbols/symbol_horizontal_hourglass.png */ - JKQTPFilledHorizontalHourglass, /*!< \brief a filled horizontal hour glass symbol \image html symbols/symbol_filled_horizontal_hourglass.png */ - - JKQTPSantaClauseHouse, /*!< \brief a small house symbol ("Das is das haus vom Nicolaus") \image html symbols/symbol_santaclause.png */ - JKQTPFilledSantaClauseHouse, /*!< \brief a filled small house symbol ("Das is das haus vom Nicolaus") \image html symbols/symbol_filled_santaclause.png */ - - JKQTPMale, /*!< \brief a male symbol \image html symbols/symbol_male.png */ - JKQTPFemale, /*!< \brief a female symbol \image html symbols/symbol_female.png */ - - JKQTPSymbolCount, /*!< \brief can be used to iterate over all symbols using: for (int i=0; i(JKQTPSymbolCount); i++) { JKQTPGraphSymbols s=static_cast(i); ... } */ - JKQTPMaxSymbolID=JKQTPSymbolCount-1, /*!< \brief points to the last available symbol, can be used to iterate over all symbols: for (int i=0; i<=static_cast(JKQTPMaxSymbolID); i++) { JKQTPGraphSymbols s=static_cast(i); ... } */ - JKQTPDefaultSymbol=JKQTPCross, /*!< \brief a default symbol used for plotting */ -}; - -/** \brief converts a JKQTPGraphSymbols variable into a identifier string - * \ingroup jkqtptools_drawing - */ -JKQTP_LIB_EXPORT QString JKQTPGraphSymbols2String(JKQTPGraphSymbols pos); -/** \brief converts a JKQTPGraphSymbols variable into a human-readable string - * \ingroup jkqtptools_drawing - */ -JKQTP_LIB_EXPORT QString JKQTPGraphSymbols2NameString(JKQTPGraphSymbols pos); - -/** \brief converts a String into a JKQTPGraphSymbols - * \ingroup jkqtptools_drawing - */ -JKQTP_LIB_EXPORT JKQTPGraphSymbols String2JKQTPGraphSymbols(const QString& pos); - - /** \brief plot styles for the error information diff --git a/lib/jkqtplottergui/jkqtpcomboboxes.cpp b/lib/jkqtplottergui/jkqtpcomboboxes.cpp index 17b2a8668e..e0c77cb387 100644 --- a/lib/jkqtplottergui/jkqtpcomboboxes.cpp +++ b/lib/jkqtplottergui/jkqtpcomboboxes.cpp @@ -21,7 +21,7 @@ #include "jkqtplottergui/jkqtpcomboboxes.h" #include "jkqtplotter/jkqtpbaseplotter.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include diff --git a/lib/jkqtplottergui/jkqtpcomboboxes.h b/lib/jkqtplottergui/jkqtpcomboboxes.h index fc8b9521e6..b7475c8ad1 100644 --- a/lib/jkqtplottergui/jkqtpcomboboxes.h +++ b/lib/jkqtplottergui/jkqtpcomboboxes.h @@ -26,8 +26,8 @@ #include "jkqtcommon/jkqtp_imexport.h" #include "jkqtplotter/jkqtpgraphsimage.h" #include -#include "jkqtplottertools/jkqtpimagetools.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtpimagetools.h" +#include "jkqtplotter/jkqtptools.h" diff --git a/lib/jkqtplottergui/jkqtpenhancedtableview.cpp b/lib/jkqtplottergui/jkqtpenhancedtableview.cpp index ec604ab463..f701f45535 100644 --- a/lib/jkqtplottergui/jkqtpenhancedtableview.cpp +++ b/lib/jkqtplottergui/jkqtpenhancedtableview.cpp @@ -34,8 +34,8 @@ Copyright (c) 2008-2019 Jan W. Krieger () #include #include #include -#include "jkqtcommon/jkqtptools.h" -#include "jkqtplottertools/jkqtpenhancedpainter.h" +#include "jkqtplotter/jkqtptools.h" +#include "jkqtcommon/jkqtpenhancedpainter.h" diff --git a/lib/jkqtplottergui/jkqtpgraphsmodel.cpp b/lib/jkqtplottergui/jkqtpgraphsmodel.cpp index 14c75ad747..db13ce9712 100644 --- a/lib/jkqtplottergui/jkqtpgraphsmodel.cpp +++ b/lib/jkqtplottergui/jkqtpgraphsmodel.cpp @@ -21,7 +21,7 @@ #include "jkqtplottergui/jkqtpgraphsmodel.h" #include "jkqtplotter/jkqtpbaseplotter.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include "jkqtplotter/jkqtpgraphsscatter.h" #include diff --git a/lib/jkqtplottergui/jkvanishqtoolbar.h b/lib/jkqtplottergui/jkvanishqtoolbar.h index 26ed31732b..e1bacd6ca3 100644 --- a/lib/jkqtplottergui/jkvanishqtoolbar.h +++ b/lib/jkqtplottergui/jkvanishqtoolbar.h @@ -22,7 +22,7 @@ #ifndef jkvanishqtoolbar_H #define jkvanishqtoolbar_H #include "jkqtcommon/jkqtp_imexport.h" -#include "jkqtcommon/jkqtptools.h" +#include "jkqtplotter/jkqtptools.h" #include /** \brief a modified QToolBar which vanishes when the mouse leaves the toolbar. diff --git a/lib/jkqtplottertools/jkqtpdrawingtools.cpp b/lib/jkqtplottertools/jkqtpdrawingtools.cpp deleted file mode 100644 index e43a704718..0000000000 --- a/lib/jkqtplottertools/jkqtpdrawingtools.cpp +++ /dev/null @@ -1,789 +0,0 @@ -/* -Copyright (c) 2008-2019 Jan W. Krieger () - - - - - - This software is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License (LGPL) as published by - the Free Software Foundation, either version 2.1 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License (LGPL) for more details. - - You should have received a copy of the GNU Lesser General Public License (LGPL) - along with this program. If not, see . -*/ - -#include "jkqtplottertools/jkqtpdrawingtools.h" -#include "jkqtplottertools/jkqtpenhancedpainter.h" -#include - -const double JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH= 0.02; - - - -QPolygonF jkqtpRotateRect(QRectF r, double angle) { - QPolygonF p; - QMatrix m; - m.rotate(angle); - p.append(m.map(r.bottomLeft())); - p.append(m.map(r.bottomRight())); - p.append(m.map(r.topRight())); - p.append(m.map(r.topLeft())); - return p; -} - -void JKQTPPlotSymbol(QPaintDevice& paintDevice, double x, double y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor) { - JKQTPEnhancedPainter p(&paintDevice); - JKQTPPlotSymbol(p, x, y, symbol, size, symbolLineWidth, color, fillColor); -} - -void JKQTPPlotSymbol(JKQTPEnhancedPainter& painter, double x, double y, JKQTPGraphSymbols symbol, double symbolSize, double symbolLineWidth, QColor color, QColor fillColor) { - painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();}); - QPen p=painter.pen(); - p.setColor(color); - p.setWidthF(qMax(JKQTPlotterDrawingTools::ABS_MIN_LINEWIDTH, symbolLineWidth)); - p.setStyle(Qt::SolidLine); - p.setCapStyle(Qt::FlatCap); - painter.setPen(p); - QBrush b=painter.brush(); - b.setColor(fillColor); - b.setStyle(Qt::SolidPattern); - const double w=symbolSize; - const double w2=w/2.0; - const double w45=fabs(w*cos(45.0/180.0*M_PI)); - const double w3=w/3.0; - - // calculate star cordinates as static values - static int star5_items=0; - static double star5cordsx[10]; - static double star5cordsy[10]; - if (star5_items==0) { - star5_items=5; - double angle=360.0/double(star5_items)/180.0*M_PI; - for (int i=0; i(i)+0.5)*angle; - star5cordsx[i*2]=sin(a); - star5cordsx[i*2+1]=0.5*sin(a+angle/2.0); - star5cordsy[i*2]=cos(a); - star5cordsy[i*2+1]=0.5*cos(a+angle/2.0); - } - } - static int star6_items=0; - static double star6cordsx[12]; - static double star6cordsy[12]; - if (star6_items==0) { - star6_items=6; - double angle=360.0/double(star6_items)/180.0*M_PI; - for (int i=0; i(i)+0.5)*angle; - star6cordsx[i*2]=sin(a); - star6cordsx[i*2+1]=0.5*sin(a+angle/2.0); - star6cordsy[i*2]=cos(a); - star6cordsy[i*2+1]=0.5*cos(a+angle/2.0); - } - } - static int star8_items=0; - static double star8cordsx[16]; - static double star8cordsy[16]; - if (star8_items==0) { - star8_items=8; - double angle=360.0/double(star8_items)/180.0*M_PI; - for (int i=0; i(i)+0.5)*angle; - star8cordsx[i*2]=sin(a); - star8cordsx[i*2+1]=0.5*sin(a+angle/2.0); - star8cordsy[i*2]=cos(a); - star8cordsy[i*2+1]=0.5*cos(a+angle/2.0); - } - } - - switch(symbol) { - case JKQTPDot: - painter.drawPoint(QPointF(x,y)); - break; - case JKQTPCross:{ - QPainterPath path; - path.moveTo(x-w2,y-w2); - path.lineTo(x+w2,y+w2); - path.moveTo(x-w2,y+w2); - path.lineTo(x+w2,y-w2); - painter.drawPath(path); - } - break; - case JKQTPPlus:{ - QVector lines; - lines< lines; - lines< lines; - lines< lines; - lines< lines; - lines< lines; - lines< lines; - lines< lines; - lines< lines; - lines< lines; - lines< JKQTPDrawEllipse(double x, double y, double a, double b, double angle_start, double angle_end, double alpha, int controlPoints, QPointF* x_start, QPointF* x_end) { - QVector result; - double start=angle_start*M_PI/180.0; - double stop=angle_end*M_PI/180.0; - double step=(stop-start)/static_cast(controlPoints); - while (fabs(stop-start)/step<10) step=step/2.0; - double sina=sin(1.0*alpha/180.0*M_PI); - double cosa=cos(1.0*alpha/180.0*M_PI); - QPointF xp(x+a*cos(start)*cosa-b*sin(start)*sina, y+a*cos(start)*sina+b*sin(start)*cosa); - result.append(xp); - if (x_start) *x_start = xp; - double t=start+step; - for (int i=1; irect.bottom()) { - poly<rect.left()) { - poly< JKQTPUnifyLinesToPolygons(const QVector &lines, double distanceThreshold, int searchMaxSurroundingElements) -{ -#ifdef JKQTBP_AUTOTIMER - JKQTPAutoOutputTimer jkaat(QString("JKQTPUnifyLinesToPolygons(%1, %2, %3)").arg(lines.size()).arg(distanceThreshold).arg(searchMaxSurroundingElements)); -#endif - QList res; - res.reserve(lines.size()); - - // first simply convert all lines to polygons - for (const QLineF& l: lines) { - QPolygonF p; - p< polygons start "<=0; k--) { - res[i].prepend(res[j].at(k)); - } - res.removeAt(j); - } else if (jkqtp_distance(res[i].last(),res[j].first())<=distanceThreshold) { - found=true; - for (int k=1; k=0; k--) { - res[i].append(res[j].at(k)); - } - res.removeAt(j); - } else { - j++; - } - } - res[i]=JKQTPCleanPolygon(res[i], distanceThreshold); - i++; - } - //qDebug()<<" iter "< polygons left "< inbetween; - int i=1; - while (i0) { - for (const QPointF& pi: inbetween) { - pmean=QPointF(pmean.x()+pi.x()/static_cast(inbetween.size()), pmean.y()+pi.y()/static_cast(inbetween.size())); - } - } else { - pmean=poly[i]; - } - p<0) { - for (const QPointF& pi: inbetween) { - pmean=QPointF(pmean.x()+pi.x()/static_cast(inbetween.size()), pmean.y()+pi.y()/static_cast(inbetween.size())); - } - } else { - pmean=p0; - } - - if (jkqtp_distance(pmean, poly.last())>distanceThreshold) { - p<, ) - - - - This software is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation, either version 2.1 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . -*/ - - -#ifndef JKQTPDRAWINGTOOLS_H_INCLUDED -#define JKQTPDRAWINGTOOLS_H_INCLUDED -#include "jkqtcommon/jkqtp_imexport.h" -#include "jkqtcommon/jkqtptools.h" -#include - -class JKQTPEnhancedPainter; // forward - - - -/*! \brief tool class with static values used by JKQTPlotter/JKQTBasePlotter - \ingroup jkqtptools_drawing - */ -JKQTP_LIB_EXPORT struct JKQTPlotterDrawingTools { - /** \brief smallest linewidth any line in JKQTPlotter/JKQTBasePlotter may have - */ - static const double ABS_MIN_LINEWIDTH; -}; - - -/** \brief rotate a rectangle by given angle (rotates all points around the center of the rectangle and returns it as a QPolygonF) - * \ingroup jkqtptools_drawing - */ -JKQTP_LIB_EXPORT QPolygonF jkqtpRotateRect(QRectF r, double angle); - -/*! \brief plot the specified symbol at pixel position x,y - \ingroup jkqtptools_drawing - - \param painter the QPainter to draw to - \param x x-coordinate of the symbol center - \param y y-coordinate of the symbol center - \param symbol type of the symbol to plot, see JKQTPGraphSymbols - \param size size (width/height) of the symbol around (\a x , \a y) - \param symbolLineWidth width of the lines used to draw the symbol - \param color color of the symbol lines - \param fillColor color of the symbol filling - */ -JKQTP_LIB_EXPORT void JKQTPPlotSymbol(JKQTPEnhancedPainter& painter, double x, double y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor); - -/*! \brief plot the specified symbol at pixel position x,y - \ingroup jkqtptools_drawing - - \param paintDevice the paint device to draw on - \param x x-coordinate of the symbol center - \param y y-coordinate of the symbol center - \param symbol type of the symbol to plot, see JKQTPGraphSymbols - \param size size (width/height) of the symbol around (\a x , \a y) - \param symbolLineWidth width of the lines used to draw the symbol - \param color color of the symbol lines - \param fillColor color of the symbol filling - */ -JKQTP_LIB_EXPORT void JKQTPPlotSymbol(QPaintDevice& paintDevice, double x, double y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor); - - -/*! \brief plot an arrow between positions (x1,y1) and (x2,y2) - \ingroup jkqtptools_drawing - - \param painter the QPainter to draw to - \param x1 first x-coordinate of the arrow - \param y1 first y-coordinate of the arrow - \param x2 second x-coordinate of the arrow - \param y2 second y-coordinate of the arrow - \param symbol type of the symbol to plot, see JKQTPGraphSymbols - \param size size (width/height) of the symbol around (\a x , \a y) - \param symbolLineWidth width of the lines used to draw the symbol - \param color color of the symbol lines - \param fillColor color of the symbol filling - */ -//JKQTP_LIB_EXPORT void JKQTPPlotArrow(JKQTPEnhancedPainter& painter, int x, int y, JKQTPGraphSymbols symbol, double size, double symbolLineWidth, QColor color, QColor fillColor); - - -/*! \brief draw an ellipse without setting pen or brush, or saving the painter! - \ingroup jkqtptools_drawing - - \return a QVector with points that may be used for drawing - \param x center of ellipse (x-coordinate) - \param y center of ellipse (y-coordinate) - \param a half axis in x-direction - \param b half axis in y-direction - \param angle_start starting angle of ellipse section - \param angle_end ending angle of ellipse section - \param alpha rotation angle of ellipse - \param controlPoints the number of points to use for drawing - \param[out] x_start first point of ellipse - \param[out] x_end last point of ellipse - - \note all angles are given in degrees [0..360] -*/ -JKQTP_LIB_EXPORT QVector JKQTPDrawEllipse(double x, double y, double a, double b, double angle_start=0, double angle_end=360, double alpha=0, int controlPoints=180, QPointF* x_start=nullptr, QPointF* x_end=nullptr); - -/*! \brief draw a tooltip, using the current brush and pen of the provided painter - \ingroup jkqtptools_drawing - - \param painter JKQTPEnhancedPainter to use for painting - \param x x-coordinate of position the tooltip points to - \param y y-coordinate of position the tooltip points to - \param rect rectangle of the main tooltip area -*/ -JKQTP_LIB_EXPORT void JKQTPDrawTooltip(JKQTPEnhancedPainter& painter, double x, double y, const QRectF& rect); - - -/** \brief cleans a polygon by uniting all consecutive points that were closer than distanceThreshold are united - * \ingroup jkqtptools_drawing - * - * \param poly polygon to clean - * \param distanceThreshold if two end-points are closer together as this value, they are united to a single point - * \return a cleaned polygon, where all consecutive points that were closer than distanceThreshold are united - */ -JKQTP_LIB_EXPORT QPolygonF JKQTPCleanPolygon(const QPolygonF& poly, double distanceThreshold=0.3); - -/** \brief takes a list of QLineF objesct \a lines and tries to combine as many of them as possible to QPolygonF objects. - * Note: This method implements an incomplete algorithm with \a searchMaxSurroundingElements>0, as solving - * the complete problem is very time-consuming (cubic runtime) - * \ingroup jkqtptools_drawing - * - * \param lines line segments to unify - * \param distanceThreshold if two end-points are closer together as this value, they are united to a single point - * \param searchMaxSurroundingElements limits the search for a connected polygon to at most this number of neighbors - * \return a vector of QPolygonF objects, which contain longer line-segments formed from \a lines - */ -JKQTP_LIB_EXPORT QVector JKQTPUnifyLinesToPolygons(const QVector& lines, double distanceThreshold=0.3, int searchMaxSurroundingElements=10); - -#endif // JKQTPDRAWINGTOOLS_H_INCLUDED diff --git a/screenshots/jkqtplotter_simpletest_datastore_statistics.png b/screenshots/jkqtplotter_simpletest_datastore_statistics.png new file mode 100644 index 0000000000..2c06042e01 Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_datastore_statistics.png differ diff --git a/screenshots/jkqtplotter_simpletest_datastore_statistics_boxplots.png b/screenshots/jkqtplotter_simpletest_datastore_statistics_boxplots.png new file mode 100644 index 0000000000..ba9a0d0595 Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_datastore_statistics_boxplots.png differ diff --git a/screenshots/jkqtplotter_simpletest_datastore_statistics_boxplots_outliers.png b/screenshots/jkqtplotter_simpletest_datastore_statistics_boxplots_outliers.png new file mode 100644 index 0000000000..e630fea7f7 Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_datastore_statistics_boxplots_outliers.png differ diff --git a/screenshots/jkqtplotter_simpletest_datastore_statistics_boxplots_simple.png b/screenshots/jkqtplotter_simpletest_datastore_statistics_boxplots_simple.png new file mode 100644 index 0000000000..6c4327bbce Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_datastore_statistics_boxplots_simple.png differ diff --git a/screenshots/jkqtplotter_simpletest_datastore_statistics_cumhistkde.png b/screenshots/jkqtplotter_simpletest_datastore_statistics_cumhistkde.png new file mode 100644 index 0000000000..46e69286bf Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_datastore_statistics_cumhistkde.png differ diff --git a/screenshots/jkqtplotter_simpletest_datastore_statistics_dataonly.png b/screenshots/jkqtplotter_simpletest_datastore_statistics_dataonly.png new file mode 100644 index 0000000000..8604889d2a Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_datastore_statistics_dataonly.png differ diff --git a/screenshots/jkqtplotter_simpletest_datastore_statistics_hist.png b/screenshots/jkqtplotter_simpletest_datastore_statistics_hist.png new file mode 100644 index 0000000000..d45bbb292e Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_datastore_statistics_hist.png differ diff --git a/screenshots/jkqtplotter_simpletest_datastore_statistics_kde.png b/screenshots/jkqtplotter_simpletest_datastore_statistics_kde.png new file mode 100644 index 0000000000..0c43a2f0e2 Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_datastore_statistics_kde.png differ diff --git a/screenshots/jkqtplotter_simpletest_datastore_statistics_small.png b/screenshots/jkqtplotter_simpletest_datastore_statistics_small.png new file mode 100644 index 0000000000..d9bc79ca40 Binary files /dev/null and b/screenshots/jkqtplotter_simpletest_datastore_statistics_small.png differ diff --git a/sharedlib/jkqtfastplotterlib/jkqtfastplotterlib.pro b/sharedlib/jkqtfastplotterlib/jkqtfastplotterlib.pro index 248ca6a706..b99661b757 100644 --- a/sharedlib/jkqtfastplotterlib/jkqtfastplotterlib.pro +++ b/sharedlib/jkqtfastplotterlib/jkqtfastplotterlib.pro @@ -13,3 +13,4 @@ win32 { } include(../../lib/jkqtfastplotter.pri) +include(../../lib/jkqtpcommon.pri) diff --git a/sharedlib/jkqtmathtextlib/jkqtmathtextlib.pro b/sharedlib/jkqtmathtextlib/jkqtmathtextlib.pro index a17e8e3460..9e397cc29b 100644 --- a/sharedlib/jkqtmathtextlib/jkqtmathtextlib.pro +++ b/sharedlib/jkqtmathtextlib/jkqtmathtextlib.pro @@ -13,3 +13,4 @@ win32 { } include(../../lib/jkqtmathtext.pri) +include(../../lib/jkqtpcommon.pri) diff --git a/sharedlib/jkqtpcommonlib/jkqtpcommonlib.pro b/sharedlib/jkqtpcommonlib/jkqtpcommonlib.pro new file mode 100644 index 0000000000..8154b81b5e --- /dev/null +++ b/sharedlib/jkqtpcommonlib/jkqtpcommonlib.pro @@ -0,0 +1,15 @@ +# uncomment this line to prevent linking in of the XITS fonts +#DEFINES += NO_XITS_FONTS +TARGET = jkqtpcommonlib +CONFIG (debug, debug|release): TARGET = jkqtplotterlib_debug + +TEMPLATE = lib +CONFIG += dll +CONFIG += create_prl + +win32 { + DEFINES += JKQTP_LIB_IN_DLL + DEFINES += JKQTP_LIB_EXPORT_LIBRARY +} + +include(../../lib/jkqtpcommon.pri) diff --git a/sharedlib/jkqtplotterlib/jkqtplotterlib.pro b/sharedlib/jkqtplotterlib/jkqtplotterlib.pro index 8542d97036..5f5cd8380a 100644 --- a/sharedlib/jkqtplotterlib/jkqtplotterlib.pro +++ b/sharedlib/jkqtplotterlib/jkqtplotterlib.pro @@ -13,3 +13,6 @@ win32 { } include(../../lib/jkqtplotter.pri) +include(../../lib/jkqtpcommon.pri) +include(../../lib/jkqtmathtext.pri) +include(../../lib/jkqtfastplotter.pri) \ No newline at end of file diff --git a/staticlib/jkqtfastplotterlib/jkqtfastplotterlib.pro b/staticlib/jkqtfastplotterlib/jkqtfastplotterlib.pro index c4fa091740..95a56b0c7a 100644 --- a/staticlib/jkqtfastplotterlib/jkqtfastplotterlib.pro +++ b/staticlib/jkqtfastplotterlib/jkqtfastplotterlib.pro @@ -8,3 +8,4 @@ CONFIG+=staticlib CONFIG += create_prl include(../../lib/jkqtfastplotter.pri) +include(../../lib/jkqtpcommon.pri) diff --git a/staticlib/jkqtmathtextlib/jkqtmathtextlib.pro b/staticlib/jkqtmathtextlib/jkqtmathtextlib.pro index b1188b6b36..aef93bbc7d 100644 --- a/staticlib/jkqtmathtextlib/jkqtmathtextlib.pro +++ b/staticlib/jkqtmathtextlib/jkqtmathtextlib.pro @@ -8,3 +8,4 @@ CONFIG += staticlib CONFIG += create_prl include(../../lib/jkqtmathtext.pri) +include(../../lib/jkqtpcommon.pri) diff --git a/staticlib/jkqtpcommonlib/jkqtpcommonlib.pro b/staticlib/jkqtpcommonlib/jkqtpcommonlib.pro new file mode 100644 index 0000000000..3247558c54 --- /dev/null +++ b/staticlib/jkqtpcommonlib/jkqtpcommonlib.pro @@ -0,0 +1,10 @@ +# uncomment this line to prevent linking in of the XITS fonts +#DEFINES += NO_XITS_FONTS +TARGET = jkqtpcommonlib +CONFIG (debug, debug|release): TARGET = jkqtmathtextlib_debug + +TEMPLATE = lib +CONFIG += staticlib +CONFIG += create_prl + +include(../../lib/jkqtpcommon.pri) diff --git a/staticlib/jkqtphighrestimerlib/jkqtphighrestimerlib.pro b/staticlib/jkqtphighrestimerlib/jkqtphighrestimerlib.pro deleted file mode 100644 index a7aa4dca03..0000000000 --- a/staticlib/jkqtphighrestimerlib/jkqtphighrestimerlib.pro +++ /dev/null @@ -1,13 +0,0 @@ -TARGET = jkqtphighrestimerlib -CONFIG (debug, debug|release): TARGET = jkqtphighrestimerlib_debug - -TEMPLATE = lib -CONFIG += staticlib -CONFIG += create_prl - -HEADERS += \ - ../../lib/jkqtplottertools/jkqtphighrestimer.h - -SOURCES += \ - ../../lib/jkqtplottertools/jkqtphighrestimer.cpp - diff --git a/staticlib/jkqtplotterlib/jkqtplotterlib.pro b/staticlib/jkqtplotterlib/jkqtplotterlib.pro index 3545e8d65a..b2cd517fab 100644 --- a/staticlib/jkqtplotterlib/jkqtplotterlib.pro +++ b/staticlib/jkqtplotterlib/jkqtplotterlib.pro @@ -9,4 +9,7 @@ CONFIG += create_prl #DEFINES += JKQTBP_AUTOTIMER +include(../../lib/jkqtpcommon.pri) include(../../lib/jkqtplotter.pri) +include(../../lib/jkqtmathtext.pri) +include(../../lib/jkqtfastplotter.pri)