NEW: secondary axes: added functionality to manage additional secondary axes in a JKQTPBasePlotter and to select which x-/y-Axis to use for drawing a JKQTPPlotElement, see also issue #87

This commit is contained in:
jkriege2 2023-03-23 13:55:18 +01:00
parent 8b482a191c
commit f61b46b96b
109 changed files with 1246 additions and 341 deletions

View File

@ -180,6 +180,7 @@ if(JKQtPlotter_BUILD_EXAMPLES)
rgbimageplot_qt/rgbimageplot_qt,rgbimageplot_qt_upsidedown/--iteratefunctorsteps
mandelbrot
geo_coordinateaxis0
second_axis/second_axis,second_axis_hor
#speed
)
@ -207,6 +208,7 @@ if(JKQtPlotter_BUILD_EXAMPLES)
impulsesplot/JKQTPImpulsesVerticalGraph,JKQTPImpulsesVerticalGraph_Symbols,JKQTPImpulsesHorizontalGraph,JKQTPImpulsesVerticalErrorGraph,JKQTPImpulsesHorizontalErrorGraph,JKQTPImpulsesVerticalGraphNoBaseline,JKQTPImpulsesVerticalGraph_SymbolsNoBaseline,JKQTPImpulsesHorizontalGraphNoBaseline,JKQTPImpulsesVerticalErrorGraphNoBaseline,JKQTPImpulsesHorizontalErrorGraphNoBaseline,JKQTPImpulsesVerticalGraphBaseline,JKQTPImpulsesVerticalGraph_SymbolsBaseline,JKQTPImpulsesHorizontalGraphBaseline,JKQTPImpulsesVerticalErrorGraphBaseline,JKQTPImpulsesHorizontalErrorGraphBaseline/--iteratefunctorsteps--smallscreenshotplot
symbols_and_errors/JKQTPXYLineErrorGraph_JKQTPErrorBars,JKQTPXYLineErrorGraph_JKQTPErrorLines,JKQTPXYLineErrorGraph_JKQTPErrorPolygons/--iteratefunctorsteps--iteratefunctorsteps_suppressinitial--smallscreenshotplot
boxplot/JKQTPBoxplotVerticalGraph,JKQTPBoxplotHorizontalGraph/--iteratefunctorsteps--iteratefunctorsteps_suppressinitial--smallscreenshotplot
second_axis/JKQTBasePlotter_addSecondaryYAxis,JKQTBasePlotter_addSecondaryXAxis
)

View File

@ -122,9 +122,12 @@ All test-projects are Qt-projects that use qmake to build. You can load them int
<tr><td> \image html logaxes_small.png
<td> \subpage JKQTPlotterLogAxes
<td> `JKQTPXYLineGraph` and `JKQTPGeoText` <br> C++ vector of data <br> logarithmic axes and styling <br> plot line styles <br> internal LaTeX parser <br> add commenting text to a graph
<tr><td> \image html dateaxes_timeaxis_small.png
<td> \subpage JKQTPlotterDateTimeAxes
<tr><td> \image html dateaxes_timeaxis_small.png
<td> \subpage JKQTPlotterDateTimeAxes
<td> `JKQTPXYLineGraph` and `JKQTPFilledVerticalRangeGraph` <br> C++ vector of data <br> date/time axes <br> plot min/max range graph <br> internal LaTeX parser <br> data from CSV files
<tr><td> \image html second_axis_small.png
<td> \subpage JKQTPlotterSecondaryAxes
<td> plottig with secondary axes, `JKQTPBasePlotter::addSecondaryXAxis()`/`JKQTPBasePlotter::addSecondaryYAxis()`
<tr><td> \image html advancedlineandfillstyling_small.png
<td> \subpage JKQTPlotterAdvancedLineAndFillStyling
<td> `JKQTPXYLineGraph`, `JKQTPSpecialLineHorizontalGraph` and `JKQTPBarVerticalGraph` <br> C++ vector of data <br> advanced line styling and filling

View File

@ -18,6 +18,7 @@
derived from JKQTPPlotAnnotationElement
<li> \b key is the legend of the plot, showing a list of the graphs, each represented by a <b>entry marker</b> (showing the graphs color/symbol/...) and a <b>entry title</b>.
<li> <b>coordinate axis</b> is each of the x- or y-axis (there might be addition axes, e.g. when showing a color-scale). Each coordinate axis is composed from several elements: the axis line itself, an <b>axis label</b>, axis <b> ticks</b> and corresponding <b>tick labels</b> (major and a second set of minor ticks in between are available)
<li> <b>secondary coordinate axis</b> you can add additional secondary x- and y-axes to a plot, which are shown stacked, beside the plot.
<li> <b>zero axis</b>: a pair of axes through the origin \c x=0 and \c y=0 of the coordinate system
<li> \b grid a grid of horizontal/vertical lines, drawn behind the graph and providing visual guidance for the viewer of the graph. The grid is actually a part of the coordinate axes, as the lines are positioned at the same position as the axis ticks
<li> <b>minor grid</b> in addition to the grid, corresponding to the major axis ticks, you can add additional lines that correspond to the minor axis ticks

View File

@ -29,7 +29,6 @@ This page lists several todos and wishes for future version of JKQTPlotter
<li>plot: legend positioning as combination of 3 values: inside|outside + left|center|right + top|vcenter|bottom</li>
<li>plot: refactor print preview/export preview code </li>
<li>plot: rework layouting of legends: there are some inconsistencies/too large gaps ...</li>
<li>plot: secondary axes: independent and dependent (i.e. with transformation function from primary axis)</li>
<li>sryling: better styling/more styling options for data-tooltips</li>
<li>styling: color gradients as fill-styles in style-INIs</li>
<li>styling: style.ini with glowing colors in dark background ("techno" or "cyberpunk")</li>

View File

@ -67,6 +67,7 @@ Changes, compared to \ref page_whatsnew_V4_0_0 "v4.0.0" include:
<li>NEW: barcharts can be colored by a user-specified functor</li>
<li>NEW: you can provide a custom draw functor to barcharts to completely customize their look</li>
<li>NEW: barcharts and impulse graphs may now draw their baseline as stylable line (default: off)</li>
<li>NEW: secondary axes: added functionality to manage additional secondary axes in a JKQTPBasePlotter and to select which x-/y-Axis to use for drawing a JKQTPPlotElement</li>
</ul></li>
<li>JKQTMathText:<ul>

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -91,6 +91,7 @@ add_subdirectory(rgbimageplot_opencv)
add_subdirectory(rgbimageplot_qt)
add_subdirectory(scatter)
add_subdirectory(scatter_customsymbol)
add_subdirectory(second_axis)
add_subdirectory(speed)
add_subdirectory(stackedbars)
add_subdirectory(stepplots)

View File

@ -0,0 +1,34 @@
cmake_minimum_required(VERSION 3.16)
set(EXAMPLE_NAME second_axis)
set(EXENAME jkqtptest_${EXAMPLE_NAME})
message( STATUS ".. Building Example ${EXAMPLE_NAME}" )
# Set up source files
set(SOURCES second_axis.cpp )
set(HEADERS )
set(RESOURCES )
set(UIS )
add_executable(${EXENAME} WIN32 ${SOURCES} ${HEADERS} ${RESOURCES} ${UIS})
target_link_libraries(${EXENAME} JKQTPExampleToolsLib)
target_include_directories(${EXENAME} PRIVATE ../../lib)
if(JKQtPlotter_BUILD_STATIC_LIBS)
target_link_libraries(${EXENAME} JKQTPlotterLib)
elseif(JKQtPlotter_BUILD_SHARED_LIBS)
target_link_libraries(${EXENAME} JKQTPlotterSharedLib)
endif()
# precomiled headers to speed up compilation
if (JKQtPlotter_BUILD_WITH_PRECOMPILED_HEADERS)
target_precompile_headers(${EXENAME} REUSE_FROM jkqtptest_simpletest)
endif (JKQtPlotter_BUILD_WITH_PRECOMPILED_HEADERS)
# Installation
install(TARGETS ${EXENAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
#Installation of Qt DLLs on Windows
jkqtplotter_deployqt(${EXENAME})

View File

@ -0,0 +1,135 @@
# Example (JKQTPlotter): Barchart With Two-Color Fill-Mode {#JKQTPlotterBarchartsTwoColorFilling}
This project (see [`second_axis`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/second_axis) shows how to plot with multiple axes.
The source code of the main application is (see [`second_axis.cpp`](https://github.com/jkriege2/JKQtPlotter/tree/master/examples/second_axis/second_axis.cpp).
In the code we take these step to set up a plot with two secondary axes and three graphs:
1./2. create a plotter and create columns with different dataset:
```.cpp
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
JKQTPDatastore* ds=plot.getDatastore();
// 2. now we create two columns for key and value
size_t columnX=ds->addLinearColumn(40, 0,10,"x");
size_t columnY1=ds->addColumnCalculatedFromColumn(columnX, [](double x) { return x; }, "y1");
size_t columnY2=ds->addColumnCalculatedFromColumn(columnX, [](double x) { return cos(x); }, "y2");
size_t columnY3=ds->addColumnCalculatedFromColumn(columnX, [](double x) { return x*x; }, "y3");
```
3. create a second y-axis and set its formating options, so it only draws an axis on the right
```.cpp
auto yAxisRef2=plot.getPlotter()->addSecondaryYAxis(new JKQTPVerticalAxis(plot.getPlotter(), JKQTPPrimaryAxis));
plot.getYAxis(yAxisRef2)->setDrawGrid(false);
plot.getYAxis(yAxisRef2)->setDrawMode1(JKQTPCADMnone);
plot.getYAxis(yAxisRef2)->setDrawMode2(JKQTPCADMcomplete);
plot.getYAxis(yAxisRef2)->setDrawMode0(JKQTPCADMnone);
plot.getYAxis(yAxisRef2)->setShowZeroAxis(false);
```
... and ctreate third y-axis
```.cpp
auto yAxisRef3=plot.getPlotter()->addSecondaryYAxis(new JKQTPVerticalAxis(plot.getPlotter(), JKQTPPrimaryAxis));
plot.getYAxis(yAxisRef3)->setDrawGrid(false);
plot.getYAxis(yAxisRef3)->setDrawMode1(JKQTPCADMnone);
plot.getYAxis(yAxisRef3)->setDrawMode2(JKQTPCADMcomplete);
plot.getYAxis(yAxisRef3)->setDrawMode0(JKQTPCADMnone);
plot.getYAxis(yAxisRef3)->setShowZeroAxis(false);
```
... reformat the major y-axis, so it does not draw on the right and thus the secondary axis yAxisRef2 replaces it there. If this step is omitted, the secondary axes stack on the right of the primary.
```.cpp
plot.getYAxis()->setDrawMode2(JKQTPCADMnone);
plot.getYAxis()->setColor(graph1->getLineColor());
```
3. create graph in the plot, which plots the dataset:
3.1 the first graph uses the default (primary) x/y-axes
```.cpp
JKQTPXYLineGraph* graph1=new JKQTPXYLineGraph(&plot);
graph1->setKeyColumn(columnX);
graph1->setValueColumn(columnY1);
plot.addGraph(graph1);
plot.getYAxis()->setAxisLabel("graph1");
```
3.2 the second graph uses the default (primary) x-axis, but the secondary axis yAxisRef2 as y-axis
```.cpp
JKQTPXYLineGraph* graph2=new JKQTPXYLineGraph(&plot);
graph2->setKeyColumn(columnX);
graph2->setValueColumn(columnY2);
plot.addGraph(graph2);
```
tell graph2 to use this axis
```.cpp
graph2->setYAxis(yAxisRef2);
```
set axis color to match graph2's color
```.cpp
plot.getYAxis(yAxisRef2)->setColor(graph2->getLineColor());
```
set axis label
```.cpp
plot.getYAxis(yAxisRef2)->setAxisLabel("graph2");
```
3.3 the third graph uses the default (primary) x-axis, but the secondary axis yAxisRef3 as y-axis
```.cpp
JKQTPXYLineGraph* graph3=new JKQTPXYLineGraph(&plot);
graph3->setKeyColumn(columnX);
graph3->setValueColumn(columnY3);
plot.addGraph(graph3);
plot.getYAxis(yAxisRef3)->setColor(graph3->getLineColor());
plot.getYAxis(yAxisRef3)->setAxisLabel("graph3");
graph3->setYAxis(yAxisRef3);
```
4. autoscale the plot so the graph is contained. This auto-scales all axes using the graphs (and their data) as assigned to the axes, i.e.:
- all 3 graphs for x-axis,
- graph1 for primary y-axis,
- graph2 for secondary axis yAxisRef2
- graph3 for secondary axis yAxisRef3
```.cpp
plot.zoomToFit();
```
5. show plotter and make it a decent size
```.cpp
plot.setWindowTitle(title);
plot.show();
plot.resize(500,400);
```
The result looks like this:
![second_axis](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/second_axis.png)
If we set seondary axes for the x-axis instead of the y-axis, i.e. use
```.cpp
// ...
auto xAxisRef2=plot.getPlotter()->addSecondaryXAxis(new JKQTPHorizontalAxis(plot.getPlotter(), JKQTPPrimaryAxis));
// ...
```
we get a plot like this:
![second_axis_hor](https://raw.githubusercontent.com/jkriege2/JKQtPlotter/master/screenshots/second_axis_hor.png)

View File

@ -0,0 +1,160 @@
/** \example second_axis.cpp
* Shows how to draw Barcharts with different colors above and below the baseline in a JKQTPlotter
*
* \ref JKQTPlotterSecondaryAxes
*/
#include "jkqtpexampleapplication.h"
#include <QApplication>
#include "jkqtplotter/jkqtplotter.h"
#include "jkqtplotter/graphs/jkqtplines.h"
#include "jkqtpexampleapplication.h"
void exampleSecondYAxis(JKQTPlotter& plot, const QString& title)
{
// 1. create a plotter window and get a pointer to the internal datastore (for convenience)
JKQTPDatastore* ds=plot.getDatastore();
// 2. now we create two columns for key and value
size_t columnX=ds->addLinearColumn(40, 0,10,"x");
size_t columnY1=ds->addColumnCalculatedFromColumn(columnX, [](double x) { return x; }, "y1");
size_t columnY2=ds->addColumnCalculatedFromColumn(columnX, [](double x) { return cos(x); }, "y2");
size_t columnY3=ds->addColumnCalculatedFromColumn(columnX, [](double x) { return x*x; }, "y3");
// 3. create a second y-axis and set its formating options, so it only draws an axis on the right
auto yAxisRef2=plot.getPlotter()->addSecondaryYAxis(new JKQTPVerticalAxis(plot.getPlotter(), JKQTPPrimaryAxis));
plot.getYAxis(yAxisRef2)->setDrawGrid(false);
plot.getYAxis(yAxisRef2)->setDrawMode1(JKQTPCADMnone);
plot.getYAxis(yAxisRef2)->setDrawMode2(JKQTPCADMcomplete);
plot.getYAxis(yAxisRef2)->setDrawMode0(JKQTPCADMnone);
plot.getYAxis(yAxisRef2)->setShowZeroAxis(false);
// ... and ctreate third y-axis
auto yAxisRef3=plot.getPlotter()->addSecondaryYAxis(new JKQTPVerticalAxis(plot.getPlotter(), JKQTPPrimaryAxis));
plot.getYAxis(yAxisRef3)->setDrawGrid(false);
plot.getYAxis(yAxisRef3)->setDrawMode1(JKQTPCADMnone);
plot.getYAxis(yAxisRef3)->setDrawMode2(JKQTPCADMcomplete);
plot.getYAxis(yAxisRef3)->setDrawMode0(JKQTPCADMnone);
plot.getYAxis(yAxisRef3)->setShowZeroAxis(false);
// ... reformat the major y-axis, so it does not draw on the right and thus the secondary axis yAxisRef2 replaces it there
// if this step is omitted, the secondary axes stack on the right of the primary.
plot.getYAxis()->setDrawMode2(JKQTPCADMnone);
plot.getYAxis()->setAxisLabel("graph1");
// 3. create graph in the plot, which plots the dataset:
// 3.1 the first graph uses the default (primary) x/y-axes
JKQTPXYLineGraph* graph1=new JKQTPXYLineGraph(&plot);
graph1->setKeyColumn(columnX);
graph1->setValueColumn(columnY1);
plot.addGraph(graph1);
plot.getYAxis()->setColor(graph1->getLineColor());
// 3.2 the second graph uses the default (primary) x-axis, but the secondary axis yAxisRef2 as y-axis
JKQTPXYLineGraph* graph2=new JKQTPXYLineGraph(&plot);
graph2->setKeyColumn(columnX);
graph2->setValueColumn(columnY2);
plot.addGraph(graph2);
// tell graph2 to use this axis
graph2->setYAxis(yAxisRef2);
// set axis color to match graph2's color
plot.getYAxis(yAxisRef2)->setColor(graph2->getLineColor());
// set axis label
plot.getYAxis(yAxisRef2)->setAxisLabel("graph2");
// 3.3 the third graph uses the default (primary) x-axis, but the secondary axis yAxisRef3 as y-axis
JKQTPXYLineGraph* graph3=new JKQTPXYLineGraph(&plot);
graph3->setKeyColumn(columnX);
graph3->setValueColumn(columnY3);
plot.addGraph(graph3);
plot.getYAxis(yAxisRef3)->setColor(graph3->getLineColor());
plot.getYAxis(yAxisRef3)->setAxisLabel("graph3");
graph3->setYAxis(yAxisRef3);
// 4. autoscale the plot so the graph is contained
// This auto-scales all axes using the graphs (and their data) as assigned to the axes!
// i.e. all 3 graphs for x-axis,
// graph1 for primary y-axis,
// graph2 for secondary axis yAxisRef2
// graph3 for secondary axis yAxisRef3
plot.zoomToFit();
// 5. show plotter and make it a decent size
plot.setWindowTitle(title);
plot.show();
plot.resize(500,400);
}
void exampleSecondXAxis(JKQTPlotter& plot, const QString& title)
{
// same as above, but with swapped x- and y-axes!!!
JKQTPDatastore* ds=plot.getDatastore();
size_t columnY=ds->addLinearColumn(30, 0,12,"y");
size_t columnX1=ds->addColumnCalculatedFromColumn(columnY, [](double x) { return x; }, "x1");
size_t columnX2=ds->addColumnCalculatedFromColumn(columnY, [](double x) { return cos(x); }, "x2");
size_t columnX3=ds->addColumnCalculatedFromColumn(columnY, [](double x) { return x*x; }, "x3");
JKQTPXYLineGraph* graph1=new JKQTPXYLineGraph(&plot);
graph1->setXColumn(columnX1);
graph1->setYColumn(columnY);
plot.addGraph(graph1);
JKQTPXYLineGraph* graph2=new JKQTPXYLineGraph(&plot);
graph2->setXColumn(columnX2);
graph2->setYColumn(columnY);
plot.addGraph(graph2);
JKQTPXYLineGraph* graph3=new JKQTPXYLineGraph(&plot);
graph3->setXColumn(columnX3);
graph3->setYColumn(columnY);
plot.addGraph(graph3);
plot.getXAxis()->setDrawMode2(JKQTPCADMLineTicksTickLabels);
plot.getXAxis()->setColor(graph1->getLineColor());
plot.getXAxis()->setAxisLabel("graph1");
auto xAxisRef2=plot.getPlotter()->addSecondaryXAxis(new JKQTPHorizontalAxis(plot.getPlotter(), JKQTPPrimaryAxis));
plot.getXAxis(xAxisRef2)->setDrawGrid(false);
plot.getXAxis(xAxisRef2)->setDrawMode1(JKQTPCADMnone);
plot.getXAxis(xAxisRef2)->setDrawMode2(JKQTPCADMcomplete);
plot.getXAxis(xAxisRef2)->setDrawMode0(JKQTPCADMnone);
plot.getXAxis(xAxisRef2)->setShowZeroAxis(false);
plot.getXAxis(xAxisRef2)->setColor(graph2->getLineColor());
plot.getXAxis(xAxisRef2)->setAxisLabel("graph2");
graph2->setXAxis(xAxisRef2);
auto xAxisRef3=plot.getPlotter()->addSecondaryXAxis(new JKQTPHorizontalAxis(plot.getPlotter(), JKQTPPrimaryAxis));
plot.getXAxis(xAxisRef3)->setDrawGrid(false);
plot.getXAxis(xAxisRef3)->setDrawMode1(JKQTPCADMnone);
plot.getXAxis(xAxisRef3)->setDrawMode2(JKQTPCADMcomplete);
plot.getXAxis(xAxisRef3)->setDrawMode0(JKQTPCADMnone);
plot.getXAxis(xAxisRef3)->setShowZeroAxis(false);
plot.getXAxis(xAxisRef3)->setColor(graph3->getLineColor());
plot.getXAxis(xAxisRef3)->setAxisLabel("graph3");
graph3->setXAxis(xAxisRef3);
plot.zoomToFit();
plot.setWindowTitle(title);
plot.show();
plot.resize(400,500);
}
int main(int argc, char* argv[])
{
JKQTPAppSettingController highDPIController(argc,argv);
JKQTPExampleApplication app(argc, argv);
JKQTPlotter plotsecondY;
exampleSecondYAxis(plotsecondY, "1: Second Y-Axis");
JKQTPlotter plotsecondX;
exampleSecondXAxis(plotsecondX, "2: Second X-Axis");
return app.exec();
}

View File

@ -115,7 +115,7 @@ if(JKQtPlotter_BUILD_STATIC_LIBS)
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${lib_name}Version.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY AnyNewerVersion )
add_library(${oldlib_name} ALIAS ${oldlib_name})
add_library(${oldlib_name} ALIAS ${lib_name})
endif()

View File

@ -68,9 +68,9 @@ void JKQTPBarVerticalGraph::draw(JKQTPEnhancedPainter& painter) {
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
// double x0=transformX(0);
// if (parent->getXAxis()->isLogAxis()) x0=transformX(parent->getXAxis()->getMin());
// if (getXAxis()->isLogAxis()) x0=transformX(getXAxis()->getMin());
double y0=transformY(0);
if (parent->getYAxis()->isLogAxis()) y0=transformY(parent->getYAxis()->getMin());
if (getYAxis()->isLogAxis()) y0=transformY(getYAxis()->getMin());
double delta=1;
double deltap=0;
double deltam=0;
@ -248,9 +248,9 @@ void JKQTPBarHorizontalGraph::draw(JKQTPEnhancedPainter& painter) {
if (getIndexRange(imin, imax)) {
double x0=transformX(0);
if (parent->getXAxis()->isLogAxis()) x0=transformX(parent->getXAxis()->getMin());
if (getXAxis()->isLogAxis()) x0=transformX(getXAxis()->getMin());
// double y0=transformY(0);
// if (parent->getYAxis()->isLogAxis()) y0=transformY(parent->getYAxis()->getMin());
// if (getYAxis()->isLogAxis()) y0=transformY(getYAxis()->getMin());
{
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
intSortData();

View File

@ -224,12 +224,12 @@ void JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::drawXGraph(JKQTPEnhancedP
double y0=transformY(0);
if (parent->getYAxis()->isLogAxis()) y0=transformY(parent->getYAxis()->getMin());
if (getYAxis()->isLogAxis()) y0=transformY(getYAxis()->getMin());
bool first=false;
QPolygonF filledPolygon, linePolygon, errorLineTop, errorLineBottom;
QList<QPointF> epTop, epBottom;
double yami=qMin(transformY(parent->getYAxis()->getMin()),transformY(parent->getYAxis()->getMax()));
double yama=qMax(transformY(parent->getYAxis()->getMin()),transformY(parent->getYAxis()->getMax()));
double yami=qMin(transformY(getYAxis()->getMin()),transformY(getYAxis()->getMax()));
double yama=qMax(transformY(getYAxis()->getMin()),transformY(getYAxis()->getMax()));
double dypix=fabs(yama-yami);
yami=yami-2.0*dypix;
yama=yama+2.0*dypix;
@ -351,12 +351,12 @@ void JKQTPEvaluatedFunctionWithErrorsGraphDrawingBase::drawYGraph(JKQTPEnhancedP
double x0=transformX(0);
if (parent->getXAxis()->isLogAxis()) x0=transformX(parent->getXAxis()->getMin());
if (getXAxis()->isLogAxis()) x0=transformX(getXAxis()->getMin());
bool first=false;
QPolygonF filledPolygon, linePolygon, errorLineTop, errorLineBottom;
QList<QPointF> epTop, epBottom;
double xami=qMin(transformY(parent->getXAxis()->getMin()),transformY(parent->getXAxis()->getMax()));
double xama=qMax(transformY(parent->getXAxis()->getMin()),transformY(parent->getXAxis()->getMax()));
double xami=qMin(transformY(getXAxis()->getMin()),transformY(getXAxis()->getMax()));
double xama=qMax(transformY(getXAxis()->getMin()),transformY(getXAxis()->getMax()));
double dxpix=fabs(xama-xami);
xami=xami-2.0*dxpix;
xama=xama+2.0*dxpix;

View File

@ -146,10 +146,10 @@ void JKQTPFilledCurveXGraph::draw(JKQTPEnhancedPainter& painter) {
double xold=-1;
//double yold=-1;
double y0=transformY(getBaseline());
if (parent->getYAxis()->isLogAxis()) {
y0=transformY(parent->getYAxis()->getMin());
if (getBaseline()>0 && getBaseline()>parent->getYAxis()->getMin()) y0=transformY(getBaseline());
else y0=transformY(parent->getYAxis()->getMin());
if (getYAxis()->isLogAxis()) {
y0=transformY(getYAxis()->getMin());
if (getBaseline()>0 && getBaseline()>getYAxis()->getMin()) y0=transformY(getBaseline());
else y0=transformY(getYAxis()->getMin());
}
bool subsequentItem=false;
intSortData();
@ -270,9 +270,9 @@ void JKQTPFilledCurveYGraph::draw(JKQTPEnhancedPainter &painter)
//double xold=-1;
double yold=-1;
double x0=transformX(getBaseline());
if (parent->getXAxis()->isLogAxis()) {
if (getBaseline()>0 && getBaseline()>parent->getXAxis()->getMin()) x0=transformX(getBaseline());
else x0=transformX(parent->getXAxis()->getMin());
if (getXAxis()->isLogAxis()) {
if (getBaseline()>0 && getBaseline()>getXAxis()->getMin()) x0=transformX(getBaseline());
else x0=transformX(getXAxis()->getMin());
}
bool first=false;
intSortData();

View File

@ -104,7 +104,7 @@ void JKQTPGeoLine::draw(JKQTPEnhancedPainter& painter) {
QPointF xx2(transformX(x2), transformY(y2));
if ( QLineF(xx1, xx2).length()>0) {
if ((getDrawMode()==DrawAsGraphicElement) || (getParent()->getXAxis()->isLinearAxis() && getParent()->getYAxis()->isLinearAxis())) {
if ((getDrawMode()==DrawAsGraphicElement) || (getXAxis()->isLinearAxis() && getYAxis()->isLinearAxis())) {
// for linear axes, we can simply draw a line
const double angle1=atan2(xx2.y()-xx1.y(), xx2.x()-xx1.x());
const double angle2=atan2(xx1.y()-xx2.y(), xx1.x()-xx2.x());
@ -115,10 +115,10 @@ void JKQTPGeoLine::draw(JKQTPEnhancedPainter& painter) {
painter.drawLine(QLineF(lx1, lx2));
} else {
QLineF line(QPointF(x1,y1), QPointF(x2,y2));
const double xmin=parent->getXAxis()->getMin();
const double xmax=parent->getXAxis()->getMax();
const double ymin=parent->getYAxis()->getMin();
const double ymax=parent->getYAxis()->getMax();
const double xmin=getXAxis()->getMin();
const double xmax=getXAxis()->getMax();
const double ymin=getYAxis()->getMin();
const double ymax=getYAxis()->getMax();
const QRectF bbox(QPointF(xmin, ymin), QPointF(xmax, ymax));
bool drawHead=bbox.contains(line.p2());
bool drawTail=bbox.contains(line.p1());
@ -283,10 +283,10 @@ void JKQTPGeoInfiniteLine::draw(JKQTPEnhancedPainter& painter) {
clearHitTestData();
reserveHitTestData(2);
double xmin=parent->getXAxis()->getMin();
double xmax=parent->getXAxis()->getMax();
double ymin=parent->getYAxis()->getMin();
double ymax=parent->getYAxis()->getMax();
double xmin=getXAxis()->getMin();
double xmax=getXAxis()->getMax();
double ymin=getYAxis()->getMin();
double ymax=getYAxis()->getMax();
QRectF bbox(QPointF(xmin, ymin), QPointF(xmax, ymax));
bool doDraw=false;
double x2=x, y2=y;
@ -404,7 +404,7 @@ void JKQTPGeoInfiniteLine::draw(JKQTPEnhancedPainter& painter) {
if (line.length()>0) {
QPointF xx1;
double angle1=0;
if ((getDrawMode()==DrawAsGraphicElement) || (getParent()->getXAxis()->isLinearAxis() && getParent()->getYAxis()->isLinearAxis())) {
if ((getDrawMode()==DrawAsGraphicElement) || (getXAxis()->isLinearAxis() && getYAxis()->isLinearAxis())) {
painter.drawLine(line);
xx1=QPointF(transformX(x),transformY(y));
angle1=atan2(line.dy(), line.dx());
@ -579,7 +579,7 @@ void JKQTPGeoPolyLines::draw(JKQTPEnhancedPainter& painter) {
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.setPen(getLinePen(painter, parent));
painter.setBrush(getLineColor());
if ((getDrawMode()==DrawAsGraphicElement) || (getParent()->getXAxis()->isLinearAxis() && getParent()->getYAxis()->isLinearAxis())) {
if ((getDrawMode()==DrawAsGraphicElement) || (getXAxis()->isLinearAxis() && getYAxis()->isLinearAxis())) {
QVector<QPointF> path=transform(points);
angle1=atan2(path[1].y()-path[0].y(), path[1].x()-path[0].x());
angle2=atan2(path[path.size()-2].y()-path[path.size()-1].y(), path[path.size()-2].x()-path[path.size()-1].x());

View File

@ -132,7 +132,7 @@ void JKQTPGeoRectangle::draw(JKQTPEnhancedPainter& painter) {
QPolygonF poly=getPolygon();
reserveHitTestData(poly.size());
QPolygonF rect;
if ((getDrawMode()==DrawAsGraphicElement) || (getParent()->getXAxis()->isLinearAxis() && getParent()->getYAxis()->isLinearAxis())) {
if ((getDrawMode()==DrawAsGraphicElement) || (getXAxis()->isLinearAxis() && getYAxis()->isLinearAxis())) {
rect=transform(poly);
} else {
auto fTransform=std::bind([](const JKQTPGeometricPlotElement* plot, const QPointF& p) { return plot->transform(p); }, this, std::placeholders::_1);
@ -313,7 +313,7 @@ void JKQTPGeoPolygon::draw(JKQTPEnhancedPainter& painter) {
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
painter.setPen(getLinePen(painter, parent));
painter.setBrush(getFillBrush(painter, parent));
if ((getDrawMode()==DrawAsGraphicElement) || (getParent()->getXAxis()->isLinearAxis() && getParent()->getYAxis()->isLinearAxis())) {
if ((getDrawMode()==DrawAsGraphicElement) || (getXAxis()->isLinearAxis() && getYAxis()->isLinearAxis())) {
painter.drawPolygon(transform(points));
} else {
// for non-linear axes, a line might not be drawn as a line, so we need to segment the line (i.e. linear function in coordinate space)

View File

@ -206,9 +206,9 @@ void JKQTPImpulsesHorizontalGraph::draw(JKQTPEnhancedPainter& painter) {
if (getIndexRange(imin, imax)) {
double x0=transformX(getBaseline());
if (parent->getXAxis()->isLogAxis()) {
if (getBaseline()>0 && getBaseline()>parent->getXAxis()->getMin()) x0=transformX(getBaseline());
else x0=transformX(parent->getXAxis()->getMin());
if (getXAxis()->isLogAxis()) {
if (getBaseline()>0 && getBaseline()>getXAxis()->getMin()) x0=transformX(getBaseline());
else x0=transformX(getXAxis()->getMin());
}
QVector<QLineF> lines;
@ -364,9 +364,9 @@ void JKQTPImpulsesVerticalGraph::draw(JKQTPEnhancedPainter& painter) {
double y0=transformY(getBaseline());
if (parent->getYAxis()->isLogAxis()) {
if (getBaseline()>0 && getBaseline()>parent->getYAxis()->getMin()) y0=transformY(getBaseline());
else y0=transformY(parent->getYAxis()->getMin());
if (getYAxis()->isLogAxis()) {
if (getBaseline()>0 && getBaseline()>getYAxis()->getMin()) y0=transformY(getBaseline());
else y0=transformY(getYAxis()->getMin());
}
QVector<QLineF> lines;
QVector<QPointF> points;

View File

@ -78,10 +78,10 @@ void JKQTPXYLineGraph::draw(JKQTPEnhancedPainter& painter) {
const QPen p=getLinePen(painter, parent);
const QPen penSelection=getHighlightingLinePen(painter, parent);
const auto symType=getSymbolType();
const double xmin=transformX(parent->getXAxis()->getMin());
const double xmax=transformX(parent->getXAxis()->getMax());
const double ymin=transformY(parent->getYAxis()->getMin());
const double ymax=transformY(parent->getYAxis()->getMax());
const double xmin=transformX(getXAxis()->getMin());
const double xmax=transformX(getXAxis()->getMax());
const double ymin=transformY(getYAxis()->getMin());
const double ymax=transformY(getYAxis()->getMax());
const double symbolSize=parent->pt2px(painter, getSymbolSize());
const QMarginsF clipMargins=(symType==JKQTPNoSymbol)?QMarginsF(0,0,0,0):QMarginsF(symbolSize,symbolSize,symbolSize,symbolSize);
const QRectF cliprect=QRectF(qMin(xmin,xmax),qMin(ymin,ymax),fabs(xmax-xmin),fabs(ymax-ymin))+clipMargins;
@ -108,7 +108,7 @@ void JKQTPXYLineGraph::draw(JKQTPEnhancedPainter& painter) {
//if (isHighlighted() && getSymbolType()!=JKQTPNoSymbol) {
//JKQTPPlotSymbol(painter, x, y, JKQTPFilledCircle, parent->pt2px(painter, symbolSize*1.5), parent->pt2px(painter, symbolWidth*parent->getLineWidthMultiplier()), penSelection.color(), penSelection.color(),getSymbolFont());
//}
if ((!parent->getXAxis()->isLogAxis() || xv>0.0) && (!parent->getYAxis()->isLogAxis() || yv>0.0) ) {
if ((!getXAxis()->isLogAxis() || xv>0.0) && (!getYAxis()->isLogAxis() || yv>0.0) ) {
if (symType!=JKQTPNoSymbol && cliprect.contains(x,y)) {
if (drawLineInForeground) plotStyledSymbol(parent, painter, x, y);
else symbols.push_back({x,y});

View File

@ -255,10 +255,10 @@ void JKQTPHorizontalRange::draw(JKQTPEnhancedPainter& painter) {
double c=transformY(rangeCenter);
double cmi=transformY(rangeMin);
double cma=transformY(rangeMax);
double smi=transformY(parent->getYAxis()->getMin());
double sma=transformY(parent->getYAxis()->getMax());
double mi=transformX(parent->getXAxis()->getMin());
double ma=transformX(parent->getXAxis()->getMax());
double smi=transformY(getYAxis()->getMin());
double sma=transformY(getYAxis()->getMax());
double mi=transformX(getXAxis()->getMin());
double ma=transformX(getXAxis()->getMax());
if (!unlimitedSizeMin) mi=transformX(sizeMin);
if (!unlimitedSizeMax) ma=transformX(sizeMax);
//std::cout<<"hor: rangeMin="<<rangeMin<<" -> "<<cmi<<std::endl;
@ -380,10 +380,10 @@ void JKQTPVerticalRange::draw(JKQTPEnhancedPainter& painter) {
double c=transformX(rangeCenter);
double cmi=transformX(rangeMin);
double cma=transformX(rangeMax);
double mi=transformY(parent->getYAxis()->getMin());
double ma=transformY(parent->getYAxis()->getMax());
double smi=transformX(parent->getXAxis()->getMin());
double sma=transformX(parent->getXAxis()->getMax());
double mi=transformY(getYAxis()->getMin());
double ma=transformY(getYAxis()->getMax());
double smi=transformX(getXAxis()->getMin());
double sma=transformX(getXAxis()->getMax());
if (!unlimitedSizeMin) mi=transformY(sizeMin);
if (!unlimitedSizeMax) ma=transformY(sizeMax);
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});

View File

@ -78,10 +78,10 @@ void JKQTPXYScatterGraph::draw(JKQTPEnhancedPainter& painter) {
//qDebug()<<"JKQTPXYScatterGraph::draw(): "<<2;
const auto symType=getSymbolType();
const double xmin=transformX(parent->getXAxis()->getMin());
const double xmax=transformX(parent->getXAxis()->getMax());
const double ymin=transformY(parent->getYAxis()->getMin());
const double ymax=transformY(parent->getYAxis()->getMax());
const double xmin=transformX(getXAxis()->getMin());
const double xmax=transformX(getXAxis()->getMax());
const double ymin=transformY(getYAxis()->getMin());
const double ymax=transformY(getYAxis()->getMax());
const double symbolSize=parent->pt2px(painter, getSymbolSize());
const QMarginsF clipMargins=(symType==JKQTPNoSymbol)?QMarginsF(0,0,0,0):QMarginsF(symbolSize,symbolSize,symbolSize,symbolSize);
const QRectF cliprect=QRectF(qMin(xmin,xmax),qMin(ymin,ymax),fabs(xmax-xmin),fabs(ymax-ymin))+clipMargins;
@ -102,7 +102,7 @@ void JKQTPXYScatterGraph::draw(JKQTPEnhancedPainter& painter) {
//if (isHighlighted() && getSymbolType()!=JKQTPNoSymbol) {
//JKQTPPlotSymbol(painter, x, y, JKQTPFilledCircle, parent->pt2px(painter, symbolSize*1.5), parent->pt2px(painter, symbolWidth*parent->getLineWidthMultiplier()), penSelection.color(), penSelection.color());
//}
if ((!parent->getXAxis()->isLogAxis() || xv>0.0) && (!parent->getYAxis()->isLogAxis() || yv>0.0) ) {
if ((!getXAxis()->isLogAxis() || xv>0.0) && (!getYAxis()->isLogAxis() || yv>0.0) ) {
if (symType!=JKQTPNoSymbol && cliprect.contains(x,y)) plotStyledSymbol(parent, painter, x, y);
}
}
@ -364,7 +364,7 @@ void JKQTPXYParametrizedScatterGraph::draw(JKQTPEnhancedPainter &painter)
linewidths<<lineW;
}
if ((!parent->getXAxis()->isLogAxis() || xv>0.0) && (!parent->getYAxis()->isLogAxis() || yv>0.0) ) {
if ((!getXAxis()->isLogAxis() || xv>0.0) && (!getYAxis()->isLogAxis() || yv>0.0) ) {
if (isHighlighted() && getSymbolType()!=JKQTPNoSymbol && symbolColumn<0) {
JKQTPPlotSymbol(painter, x, y, JKQTPFilledCircle,symbSize*1.25, parent->pt2px(painter, getSymbolLineWidth()*parent->getLineWidthMultiplier()), penSelection.color(), penSelection.color(),getSymbolFont());
} else {

View File

@ -128,10 +128,10 @@ void JKQTPSpecialLineHorizontalGraph::draw(JKQTPEnhancedPainter& painter) {
QPen ph=getHighlightingLinePen(painter, parent);
QPen np(Qt::NoPen);
QBrush b=getFillBrush(painter, parent);
const double xmin=transformX(parent->getXAxis()->getMin());
const double xmax=transformX(parent->getXAxis()->getMax());
const double ymin=transformY(parent->getYAxis()->getMin());
const double ymax=transformY(parent->getYAxis()->getMax());
const double xmin=transformX(getXAxis()->getMin());
const double xmax=transformX(getXAxis()->getMax());
const double ymin=transformY(getYAxis()->getMin());
const double ymax=transformY(getYAxis()->getMax());
const auto symType=getSymbolType();
const double symbolSize=parent->pt2px(painter, getSymbolSize());
const QMarginsF clipMargins=(symType==JKQTPNoSymbol)?QMarginsF(0,0,0,0):QMarginsF(symbolSize,symbolSize,symbolSize,symbolSize);
@ -149,9 +149,9 @@ void JKQTPSpecialLineHorizontalGraph::draw(JKQTPEnhancedPainter& painter) {
double xold=-1;
double yold=-1;
double y0=transformY(getBaseline());
if (parent->getYAxis()->isLogAxis()) {
if (getBaseline()>0 && getBaseline()>parent->getYAxis()->getMin()) y0=transformY(getBaseline());
else y0=transformY(parent->getYAxis()->getMin());
if (getYAxis()->isLogAxis()) {
if (getBaseline()>0 && getBaseline()>getYAxis()->getMin()) y0=transformY(getBaseline());
else y0=transformY(getYAxis()->getMin());
}
bool firstPoint=true;
intSortData();
@ -336,10 +336,10 @@ void JKQTPSpecialLineVerticalGraph::draw(JKQTPEnhancedPainter& painter) {
QPen ph=getHighlightingLinePen(painter, parent);
QPen np(Qt::NoPen);
QBrush b=getFillBrush(painter, parent);
const double xmin=transformX(parent->getXAxis()->getMin());
const double xmax=transformX(parent->getXAxis()->getMax());
const double ymin=transformY(parent->getYAxis()->getMin());
const double ymax=transformY(parent->getYAxis()->getMax());
const double xmin=transformX(getXAxis()->getMin());
const double xmax=transformX(getXAxis()->getMax());
const double ymin=transformY(getYAxis()->getMin());
const double ymax=transformY(getYAxis()->getMax());
const auto symType=getSymbolType();
const double symbolSize=parent->pt2px(painter, getSymbolSize());
const QMarginsF clipMargins=(symType==JKQTPNoSymbol)?QMarginsF(0,0,0,0):QMarginsF(symbolSize,symbolSize,symbolSize,symbolSize);
@ -357,9 +357,9 @@ void JKQTPSpecialLineVerticalGraph::draw(JKQTPEnhancedPainter& painter) {
double xold=-1;
double yold=-1;
double x0=transformX(getBaseline());
if (parent->getXAxis()->isLogAxis()) {
if (getBaseline()>0 && getBaseline()>parent->getXAxis()->getMin()) x0=transformX(getBaseline());
else x0=transformX(parent->getXAxis()->getMin());
if (getXAxis()->isLogAxis()) {
if (getBaseline()>0 && getBaseline()>getXAxis()->getMin()) x0=transformX(getBaseline());
else x0=transformX(getXAxis()->getMin());
}
bool first=false;
intSortData();

View File

@ -48,16 +48,10 @@
#ifdef QFWIDLIB_LIBRARY
# include "qftools.h"
#endif
#include "jkqtplotter/graphs/jkqtpboxplot.h"
#include "jkqtplotter/graphs/jkqtpbarchart.h"
#include "jkqtplotter/graphs/jkqtpfilledcurve.h"
#include "jkqtplotter/graphs/jkqtpspecialline.h"
#include "jkqtplotter/graphs/jkqtpimpulses.h"
#include "jkqtplotter/graphs/jkqtpscatter.h"
#include "jkqtplotter/graphs/jkqtpgeometric.h"
#include "jkqtplotter/graphs/jkqtpimage.h"
#include "jkqtplotter/graphs/jkqtpimagergb.h"
#include "jkqtmathtext/jkqtmathtext.h"
#include <algorithm>
static QString globalUserSettigsFilename="";
static QString globalUserSettigsPrefix="";
@ -302,6 +296,15 @@ JKQTBasePlotter::~JKQTBasePlotter(){
if (datastoreInternal && datastore!=nullptr) delete datastore;
delete xAxis;
delete yAxis;
for (const auto& ax: qAsConst(secondaryYAxis)) {
delete ax;
}
secondaryYAxis.clear();
for (const auto& ax: qAsConst(secondaryXAxis)) {
delete ax;
}
secondaryXAxis.clear();
}
void JKQTBasePlotter::setGrid(bool val) {
@ -345,8 +348,8 @@ void JKQTBasePlotter::setMinorGridStyle(Qt::PenStyle __value)
}
void JKQTBasePlotter::setShowZeroAxes(bool showX, bool showY) {
getXAxis()->setShowZeroAxis(showX);
getYAxis()->setShowZeroAxis(showY);
xAxis->setShowZeroAxis(showX);
yAxis->setShowZeroAxis(showY);
}
void JKQTBasePlotter::setShowZeroAxes(bool showXY) {
@ -410,10 +413,10 @@ void JKQTBasePlotter::initSettings() {
gridPrintingCurrentY=0;
internalPlotBorderLeft_notIncludingOutsidePlotSections=internalPlotBorderLeft=plotterStyle.plotBorderLeft;
internalPlotBorderRight_notIncludingOutsidePlotSections=internalPlotBorderRight=plotterStyle.plotBorderRight;
internalPlotBorderTop_notIncludingOutsidePlotSections=internalPlotBorderTop=plotterStyle.plotBorderTop;
internalPlotBorderBottom_notIncludingOutsidePlotSections=internalPlotBorderBottom=plotterStyle.plotBorderBottom;
internalPlotBorderLeft_notIncludingAxisAndOutsidePlotSections=internalPlotBorderLeft_notIncludingOutsidePlotSections=internalPlotBorderLeft=plotterStyle.plotBorderLeft;
internalPlotBorderRight_notIncludingAxisAndOutsidePlotSections=internalPlotBorderRight_notIncludingOutsidePlotSections=internalPlotBorderRight=plotterStyle.plotBorderRight;
internalPlotBorderTop_notIncludingAxisAndOutsidePlotSections=internalPlotBorderTop_notIncludingOutsidePlotSections=internalPlotBorderTop=plotterStyle.plotBorderTop;
internalPlotBorderBottom_notIncludingAxisAndOutsidePlotSections=internalPlotBorderBottom_notIncludingOutsidePlotSections=internalPlotBorderBottom=plotterStyle.plotBorderBottom;
//plotWidth=700;
//plotHeight=150;
@ -434,14 +437,18 @@ void JKQTBasePlotter::initSettings() {
void JKQTBasePlotter::zoomIn(double factor) {
//std::cout<<(double)event->delta()/120.0<<": "<<factor<<std::endl;
double xmin=p2x(static_cast<long>(round(static_cast<double>(internalPlotWidth)/2.0-static_cast<double>(internalPlotWidth)/(2.0*factor))));
double xmax=p2x(static_cast<long>(round(static_cast<double>(internalPlotWidth)/2.0+static_cast<double>(internalPlotWidth)/(2.0*factor))));
double ymin=p2y(static_cast<long>(round(static_cast<double>(internalPlotHeight)/2.0+static_cast<double>(internalPlotHeight)/(2.0*factor))));
double ymax=p2y(static_cast<long>(round(static_cast<double>(internalPlotHeight)/2.0-static_cast<double>(internalPlotHeight)/(2.0*factor))));
for (auto ax: getXAxes(true)) {
const double xmin=ax->p2x(static_cast<long>(round(static_cast<double>(internalPlotWidth)/2.0-static_cast<double>(internalPlotWidth)/(2.0*factor))));
const double xmax=ax->p2x(static_cast<long>(round(static_cast<double>(internalPlotWidth)/2.0+static_cast<double>(internalPlotWidth)/(2.0*factor))));
ax->setRange(xmin, xmax);
}
for (auto ax: getYAxes(true)) {
const double ymin=ax->p2x(static_cast<long>(round(static_cast<double>(internalPlotHeight)/2.0+static_cast<double>(internalPlotHeight)/(2.0*factor))));
const double ymax=ax->p2x(static_cast<long>(round(static_cast<double>(internalPlotHeight)/2.0-static_cast<double>(internalPlotHeight)/(2.0*factor))));
ax->setRange(ymin, ymax);
}
xAxis->setRange(xmin, xmax);
yAxis->setRange(ymin, ymax);
if (emitPlotSignals) emit plotUpdated();
if (emitSignals) emit zoomChangedLocally(xAxis->getMin(), xAxis->getMax(), yAxis->getMin(), yAxis->getMax(), this);
}
@ -721,22 +728,36 @@ void JKQTBasePlotter::correctXYRangeForAspectRatio(double& xminn, double& xmaxx,
}
void JKQTBasePlotter::setXY(double xminn, double xmaxx, double yminn, double ymaxx) {
void JKQTBasePlotter::setXY(double xminn, double xmaxx, double yminn, double ymaxx, bool affectsSecondaryAxes) {
correctXYRangeForAspectRatio(xminn, xmaxx, yminn, ymaxx);
const double xminpix=xAxis->x2p(xminn);
const double xmaxpix=xAxis->x2p(xmaxx);
const double yminpix=yAxis->x2p(yminn);
const double ymaxpix=yAxis->x2p(ymaxx);
xAxis->setRange(xminn, xmaxx);
yAxis->setRange(yminn, ymaxx);
if (affectsSecondaryAxes) {
for (auto ax: getXAxes(false)) {
ax->setRange(ax->p2x(xminpix), ax->p2x(xmaxpix));
}
for (auto ax: getYAxes(false)) {
ax->setRange(ax->p2x(yminpix), ax->p2x(ymaxpix));
}
}
if (emitSignals) emit zoomChangedLocally(xAxis->getMin(), xAxis->getMax(), yAxis->getMin(), yAxis->getMax(), this);
}
void JKQTBasePlotter::setX(double xminn, double xmaxx){
setXY(xminn, xmaxx, yAxis->getMin(), yAxis->getMax());
void JKQTBasePlotter::setX(double xminn, double xmaxx, bool affectsSecondaryAxes){
setXY(xminn, xmaxx, yAxis->getMin(), yAxis->getMax(), affectsSecondaryAxes);
}
void JKQTBasePlotter::setY(double yminn, double ymaxx) {
setXY(xAxis->getMin(), xAxis->getMax(), yminn, ymaxx);
void JKQTBasePlotter::setY(double yminn, double ymaxx, bool affectsSecondaryAxes) {
setXY(xAxis->getMin(), xAxis->getMax(), yminn, ymaxx, affectsSecondaryAxes);
}
void JKQTBasePlotter::setAbsoluteX(double xminn, double xmaxx) {
@ -820,7 +841,7 @@ void JKQTBasePlotter::calcPlotScaling(JKQTPEnhancedPainter& painter){
/*if (displayMousePosition) {
QFontMetrics fm=fontMetrics();
QString test="<EFBFBD>Aquator";
QString test="Aquator";
int labelHeight=fm.size(Qt::TextSingleLine, test).height()*1.5;
//if (mousePosLabel!=nullptr) labelHeight=mousePosLabel->height();
internalPlotBorderTop=internalPlotBorderTop+(labelHeight-plotBorderTop)*1.1;
@ -837,15 +858,27 @@ void JKQTBasePlotter::calcPlotScaling(JKQTPEnhancedPainter& painter){
s=yAxis->getSize2(painter);
internalPlotBorderRight+=s.width();
internalPlotBorderTop_notIncludingAxisAndOutsidePlotSections=internalPlotBorderTop;
internalPlotBorderLeft_notIncludingAxisAndOutsidePlotSections=internalPlotBorderLeft;
internalPlotBorderBottom_notIncludingAxisAndOutsidePlotSections=internalPlotBorderBottom;
internalPlotBorderRight_notIncludingAxisAndOutsidePlotSections=internalPlotBorderRight;
// read size required by secondary axes
for (const auto& ax: qAsConst(secondaryYAxis)) {
internalPlotBorderLeft+=ax->getSize1(painter).width()+plotterStyle.secondaryAxisSeparation;
internalPlotBorderRight+=ax->getSize2(painter).width()+plotterStyle.secondaryAxisSeparation;
}
for (const auto& ax: qAsConst(secondaryXAxis)) {
internalPlotBorderBottom+=ax->getSize1(painter).height()+plotterStyle.secondaryAxisSeparation;
internalPlotBorderTop+=ax->getSize2(painter).height()+plotterStyle.secondaryAxisSeparation;
}
internalPlotBorderTop_notIncludingOutsidePlotSections=internalPlotBorderTop;
internalPlotBorderLeft_notIncludingOutsidePlotSections=internalPlotBorderLeft;
internalPlotBorderBottom_notIncludingOutsidePlotSections=internalPlotBorderBottom;
internalPlotBorderRight_notIncludingOutsidePlotSections=internalPlotBorderRight;
// read additional space required by graphs
for (int i=0; i<graphs.size(); i++) {
if (graphs[i]->isVisible()) {
@ -925,8 +958,9 @@ void JKQTBasePlotter::calcPlotScaling(JKQTPEnhancedPainter& painter){
}
xAxis->calcPlotScaling(true);
yAxis->calcPlotScaling(true);
for (auto ax: getAxes(true)) {
ax->calcPlotScaling(true);
}
////////////////////////////////////////////////////////////////////
// ENSURE ASPECT RATIO OF PLOT 1x1 PIXELS (if activated)
@ -948,8 +982,9 @@ void JKQTBasePlotter::calcPlotScaling(JKQTPEnhancedPainter& painter){
}
xAxis->setRange(xmid-newPlotWidth/2.0, xmid+newPlotWidth/2.0);
yAxis->setRange(ymid-newPlotHeight/2.0, ymid+newPlotHeight/2.0);
xAxis->calcPlotScaling(true);
yAxis->calcPlotScaling(true);
for (auto ax: getAxes(true)) {
ax->calcPlotScaling(true);
}
}
@ -963,8 +998,10 @@ void JKQTBasePlotter::drawSystemGrid(JKQTPEnhancedPainter& painter) {
JKQTPAutoOutputTimer jkaaot("JKQTBasePlotter::drawSystemGrid");
#endif
//qDebug()<<"start JKQTBasePlotter::drawSystemGrid";
xAxis->drawGrids(painter);
yAxis->drawGrids(painter);
for (auto ax: getAxes(true)) {
ax->drawGrids(painter);
}
//qDebug()<<" end JKQTBasePlotter::drawSystemGrid";
}
@ -972,9 +1009,24 @@ void JKQTBasePlotter::drawSystemXAxis(JKQTPEnhancedPainter& painter) {
#ifdef JKQTBP_AUTOTIMER
JKQTPAutoOutputTimer jkaaot("JKQTBasePlotter::drawSystemXAxis");
#endif
//qDebug()<<"start JKQTBasePlotter::drawSystemXAxis";
//qDebug()<<"start JKQTBasePlotter::drawSystemXAxis";
xAxis->drawAxes(painter);
//qDebug()<<" end JKQTBasePlotter::drawSystemXAxis";
if (secondaryXAxis.size()>0) {
double ibMove1=xAxis->getSize1(painter).height();
if (ibMove1>0) ibMove1+=plotterStyle.secondaryAxisSeparation;
double ibMove2=xAxis->getSize2(painter).height();
if (ibMove2>0) ibMove1+=plotterStyle.secondaryAxisSeparation;
for (auto& ax: secondaryXAxis) {
ax->drawAxes(painter, ibMove1, ibMove2);
const double add1=ax->getSize1(painter).height();
const double add2=ax->getSize2(painter).height();
if (add1>0) ibMove1+=add1+plotterStyle.secondaryAxisSeparation;
if (add2>0) ibMove2+=add2+plotterStyle.secondaryAxisSeparation;
}
}
}
void JKQTBasePlotter::drawSystemYAxis(JKQTPEnhancedPainter& painter) {
@ -984,6 +1036,21 @@ void JKQTBasePlotter::drawSystemYAxis(JKQTPEnhancedPainter& painter) {
//qDebug()<<"start JKQTBasePlotter::drawSystemYAxis";
yAxis->drawAxes(painter);
//qDebug()<<" end JKQTBasePlotter::drawSystemYAxis";
if (secondaryYAxis.size()>0) {
double ibMove1=yAxis->getSize1(painter).width();
if (ibMove1>0) ibMove1+=plotterStyle.secondaryAxisSeparation;
double ibMove2=yAxis->getSize2(painter).width();
if (ibMove2>0) ibMove1+=plotterStyle.secondaryAxisSeparation;
for (auto& ax: secondaryYAxis) {
ax->drawAxes(painter, ibMove1, ibMove2);
const double add1=ax->getSize1(painter).width();
const double add2=ax->getSize2(painter).width();
if (add1>0) ibMove1+=add1+plotterStyle.secondaryAxisSeparation;
if (add2>0) ibMove2+=add2+plotterStyle.secondaryAxisSeparation;
}
}
}
@ -1332,6 +1399,12 @@ void JKQTBasePlotter::drawPlot(JKQTPEnhancedPainter& painter) {
p.setStyle(Qt::DotLine);
painter.setPen(p);
painter.drawRect(QRectF(internalPlotBorderLeft_notIncludingOutsidePlotSections, internalPlotBorderTop_notIncludingOutsidePlotSections, widgetWidth-internalPlotBorderLeft_notIncludingOutsidePlotSections-internalPlotBorderRight_notIncludingOutsidePlotSections, widgetHeight-internalPlotBorderTop_notIncludingOutsidePlotSections-internalPlotBorderBottom_notIncludingOutsidePlotSections));
p.setColor(QColor("goldenrod"));
col=p.color(); col.setAlphaF(0.8f); p.setColor(col);
p.setWidthF(plotterStyle.debugRegionLineWidth);
p.setStyle(Qt::DotLine);
painter.setPen(p);
painter.drawRect(QRectF(internalPlotBorderLeft_notIncludingAxisAndOutsidePlotSections, internalPlotBorderTop_notIncludingAxisAndOutsidePlotSections, widgetWidth-internalPlotBorderLeft_notIncludingAxisAndOutsidePlotSections-internalPlotBorderRight_notIncludingAxisAndOutsidePlotSections, widgetHeight-internalPlotBorderTop_notIncludingAxisAndOutsidePlotSections-internalPlotBorderBottom_notIncludingAxisAndOutsidePlotSections));
p.setColor(QColor("yellow"));
col=p.color(); col.setAlphaF(0.8f); p.setColor(col);
p.setWidthF(plotterStyle.debugRegionLineWidth);
@ -2439,6 +2512,11 @@ void JKQTBasePlotter::drawNonGrid(JKQTPEnhancedPainter& painter, const QPoint& p
emitPlotSignals=oldEmitPlotSignals;
}
void JKQTBasePlotter::updateSecondaryAxes()
{
}
void JKQTBasePlotter::setEmittingPlotSignalsEnabled(bool __value)
{
this->emitPlotSignals = __value;
@ -3227,20 +3305,95 @@ const JKQTMathText *JKQTBasePlotter::getMathText() const {
return &mathText;
}
JKQTPHorizontalAxis *JKQTBasePlotter::getXAxis() {
return xAxis;
JKQTPHorizontalAxisBase *JKQTBasePlotter::getXAxis(JKQTPCoordinateAxisRef axis) {
if (axis==JKQTPPrimaryAxis) return xAxis;
else return secondaryXAxis[axis];
}
JKQTPVerticalAxis *JKQTBasePlotter::getYAxis() {
return yAxis;
JKQTPVerticalAxisBase *JKQTBasePlotter::getYAxis(JKQTPCoordinateAxisRef axis) {
if (axis==JKQTPPrimaryAxis) return yAxis;
else return secondaryYAxis[axis];
}
const JKQTPHorizontalAxis *JKQTBasePlotter::getXAxis() const {
return xAxis;
const JKQTPHorizontalAxisBase *JKQTBasePlotter::getXAxis(JKQTPCoordinateAxisRef axis) const {
if (axis==JKQTPPrimaryAxis) return xAxis;
else return secondaryXAxis[axis];
}
const JKQTPVerticalAxis *JKQTBasePlotter::getYAxis() const {
return yAxis;
const JKQTPVerticalAxisBase *JKQTBasePlotter::getYAxis(JKQTPCoordinateAxisRef axis) const {
if (axis==JKQTPPrimaryAxis) return yAxis;
else return secondaryYAxis[axis];
}
bool JKQTBasePlotter::hasXAxis(JKQTPCoordinateAxisRef axis) const
{
return secondaryXAxis.contains(axis);
}
bool JKQTBasePlotter::hasYAxis(JKQTPCoordinateAxisRef axis) const
{
return secondaryYAxis.contains(axis);
}
QSet<JKQTPCoordinateAxisRef> JKQTBasePlotter::getAvailableXAxisRefs(bool includePrimary) const
{
QSet<JKQTPCoordinateAxisRef> res(secondaryXAxis.keyBegin(),secondaryXAxis.keyEnd());
if (includePrimary) res.insert(JKQTPPrimaryAxis);
return res;
}
QSet<JKQTPCoordinateAxisRef> JKQTBasePlotter::getAvailableYAxisRefs(bool includePrimary) const
{
QSet<JKQTPCoordinateAxisRef> res(secondaryYAxis.keyBegin(),secondaryYAxis.keyEnd());
if (includePrimary) res.insert(JKQTPPrimaryAxis);
return res;
}
QMap<JKQTPCoordinateAxisRef, JKQTPHorizontalAxisBase *> JKQTBasePlotter::getXAxes(bool includePrimary)
{
QMap<JKQTPCoordinateAxisRef, JKQTPHorizontalAxisBase *> res=secondaryXAxis;
if (includePrimary) res[JKQTPPrimaryAxis]=xAxis;
return res;
}
QMap<JKQTPCoordinateAxisRef, JKQTPVerticalAxisBase *> JKQTBasePlotter::getYAxes(bool includePrimary)
{
QMap<JKQTPCoordinateAxisRef, JKQTPVerticalAxisBase *> res=secondaryYAxis;
if (includePrimary) res[JKQTPPrimaryAxis]=yAxis;
return res;
}
QList<JKQTPCoordinateAxis *> JKQTBasePlotter::getAxes(bool includePrimaries)
{
QList<JKQTPCoordinateAxis *> res;
if (includePrimaries) res<<xAxis<<yAxis;
for (auto& ax: secondaryXAxis) res<<ax;
for (auto& ax: secondaryYAxis) res<<ax;
return res;
}
JKQTPCoordinateAxisRef JKQTBasePlotter::addSecondaryXAxis(JKQTPHorizontalAxisBase *axis)
{
const auto keys=secondaryXAxis.keys();
JKQTPCoordinateAxisRef ref=JKQTPSecondaryAxis;
if (keys.size()>0) {
ref=static_cast<JKQTPCoordinateAxisRef>(static_cast<int>(*std::max_element(keys.begin(), keys.end()))+1);
}
secondaryXAxis[ref]=axis;
axis->setParent(this);
return ref;
}
JKQTPCoordinateAxisRef JKQTBasePlotter::addSecondaryYAxis(JKQTPVerticalAxisBase *axis)
{
const auto keys=secondaryYAxis.keys();
JKQTPCoordinateAxisRef ref=JKQTPSecondaryAxis;
if (keys.size()>0) {
ref=static_cast<JKQTPCoordinateAxisRef>(static_cast<int>(*std::max_element(keys.begin(), keys.end()))+1);
}
secondaryYAxis[ref]=axis;
axis->setParent(this);
return ref;
}
QAction *JKQTBasePlotter::getActionSavePlot() const {
@ -4565,13 +4718,14 @@ void JKQTBasePlotter::saveUserSettings() const
void JKQTBasePlotter::getGraphsXMinMax(double& minx, double& maxx, double& smallestGreaterZero) {
bool JKQTBasePlotter::getGraphsXMinMax(double& minx, double& maxx, double& smallestGreaterZero, const PlotElementPreciate& predicate) {
bool start=true;
minx=0;
maxx=0;
smallestGreaterZero=0;
size_t count=0;
for (int i=0; i<graphs.size(); i++) {
if (graphs[i]->isVisible()) {
if (graphs[i]->isVisible() && predicate(graphs[i])) {
double gminx=0;
double gmaxx=0;
@ -4589,6 +4743,7 @@ void JKQTBasePlotter::getGraphsXMinMax(double& minx, double& maxx, double& small
//std::cout<<" "<<i<<": gminx="<<gminx<<" gmaxx="<<gmaxx<<" minx="<<minx<<" maxx="<<maxx<<std::endl;
start=false;
count++;
} else {
//std::cout<<" -> "<<i<<": "<<graphs[i]->getTitle().toStdString()<<": FALSE"<<std::endl;
}
@ -4596,15 +4751,17 @@ void JKQTBasePlotter::getGraphsXMinMax(double& minx, double& maxx, double& small
//std::cout<<" -> "<<i<<": "<<graphs[i]->getTitle().toStdString()<<": INVISIBLE"<<std::endl;
}
}
return count>0;
}
void JKQTBasePlotter::getGraphsYMinMax(double& miny, double& maxy, double& smallestGreaterZero) {
bool JKQTBasePlotter::getGraphsYMinMax(double& miny, double& maxy, double& smallestGreaterZero, const PlotElementPreciate &predicate) {
bool start=true;
miny=0;
maxy=0;
smallestGreaterZero=0;
size_t count=0;
for (int i=0; i<graphs.size(); i++) {
if (graphs[i]->isVisible()) {
if (graphs[i]->isVisible() && predicate(graphs[i])) {
double gminy=0;
double gmaxy=0;
double gsmallestGreaterZero=0;
@ -4618,105 +4775,82 @@ void JKQTBasePlotter::getGraphsYMinMax(double& miny, double& maxy, double& small
xvsgz=gminy; if ((xvsgz>10.0*DBL_MIN)&&((smallestGreaterZero<10.0*DBL_MIN) || (xvsgz<smallestGreaterZero))) smallestGreaterZero=xvsgz;
start=false;
count++;
}
}
}
return count>0;
}
void JKQTBasePlotter::zoomToFit(bool zoomX, bool zoomY, bool includeX0, bool includeY0, double scaleX, double scaleY) {
// std::cout<<"JKQTBasePlotter::zoomToFit():\n";
if (graphs.size()<=0) return;
if (zoomX) {
double xxmin=0;
double xxmax=0;
double xsmallestGreaterZero=0;
getGraphsXMinMax(xxmin, xxmax, xsmallestGreaterZero);
//std::cout<<" xxmin="<<xxmin<<" xxmax="<<xxmax<<std::endl;
auto calcLocScaling=[](JKQTPCoordinateAxis* axis, double &xxmin, double&xxmax, double&xsmallestGreaterZero, bool include0, double scale) -> bool {
if (JKQTPIsOKFloat(xxmin) && JKQTPIsOKFloat(xxmax)) {
bool doScale=true;
if (fabs(xxmin-xxmax)<1e-305) {
xxmin=xAxis->getMin();
xxmax=xAxis->getMax();
xxmin=axis->getMin();
xxmax=axis->getMax();
doScale=false;
}
if (xAxis->isLogAxis()) {
if (axis->isLogAxis()) {
if ((xxmin<=1e-305)&&(xxmax<=1e-305)) {xxmin=0.1; xxmax=1.0; }
else if ((xxmin<=1e-305)&&(xxmax>0)) {
if (xsmallestGreaterZero>10.0*DBL_MIN) xxmin=xsmallestGreaterZero;
else xxmin=xxmax/xAxis->getLogAxisBase();
else xxmin=xxmax/axis->getLogAxisBase();
}
if (doScale) {
double d=scaleX*(log(xxmax)-log(xxmin)); // new width
double d=scale*(log(xxmax)-log(xxmin)); // new width
double c=(log(xxmax)+log(xxmin))/2.0; // center of interval
xxmin=exp(c-d/2.0);
xxmax=exp(c+d/2.0);
}
} else if (doScale) {
double d=scaleX*(xxmax-xxmin); // new width
double d=scale*(xxmax-xxmin); // new width
double c=(xxmax+xxmin)/2.0; // center of interval
xxmin=c-d/2.0;
xxmax=c+d/2.0;
}
if (includeX0 && !xAxis->isLogAxis()) {
if (include0 && !axis->isLogAxis()) {
if (xxmin>0) xxmin=0;
else if (xxmax<0) xxmax=0;
}
//std::cout<<" => xxmin="<<xxmin<<" xxmax="<<xxmax<<std::endl;
if (JKQTPIsOKFloat(xxmin) && JKQTPIsOKFloat(xxmax)) {
setX(xxmin, xxmax);
axis->setRange(xxmin, xxmax);
} else if (!JKQTPIsOKFloat(xxmin) && JKQTPIsOKFloat(xxmax)) {
setX(getXMin(), xxmax);
axis->setRange(axis->getMin(), xxmax);
} else if (JKQTPIsOKFloat(xxmin) && !JKQTPIsOKFloat(xxmax)) {
setX(xxmin, getXMax());
axis->setRange(xxmin, axis->getMax());
}
return doScale;
}
return false;
};
if (zoomX) {
const auto axes=getXAxes();
for (auto it=axes.begin(); it!=axes.end(); ++it) {
double xxmin=0;
double xxmax=0;
double xsmallestGreaterZero=0;
if (getGraphsXMinMax(xxmin, xxmax, xsmallestGreaterZero, filterPlotElementByXAxis(it.key()))) {
calcLocScaling(it.value(), xxmin, xxmax, xsmallestGreaterZero, includeX0, scaleX);
}
}
}
if (zoomY) {
double yymin=0;
double yymax=0;
double ysmallestGreaterZero=0;
getGraphsYMinMax(yymin, yymax, ysmallestGreaterZero);
//std::cout<<" yymin="<<yymin<<" yymax="<<yymax<<std::endl;
bool doScale=true;
if (fabs(yymin-yymax)<1e-305) {
yymin=yAxis->getMin();
yymax=yAxis->getMax();
doScale=false;
}
if (yAxis->getLogAxis()) {
if ((yymin<=1e-305)&&(yymax<=1e-305)) {yymin=0.1; yymax=1.0; }
else if ((yymin<=1e-305)&&(yymax>0)) {
if (ysmallestGreaterZero>10.0*DBL_MIN) yymin=ysmallestGreaterZero;
else yymin=yymax/yAxis->getLogAxisBase();
const auto axes=getYAxes();
for (auto it=axes.begin(); it!=axes.end(); ++it) {
double xxmin=0;
double xxmax=0;
double xsmallestGreaterZero=0;
if (getGraphsYMinMax(xxmin, xxmax, xsmallestGreaterZero, filterPlotElementByYAxis(it.key()))) {
calcLocScaling(it.value(), xxmin, xxmax, xsmallestGreaterZero, includeY0, scaleY);
}
if (doScale) {
double d=scaleY*(log(yymax)-log(yymin)); // new width
double c=(log(yymax)+log(yymin))/2.0; // center of interval
yymin=exp(c-d/2.0);
yymax=exp(c+d/2.0);
}
} else if (doScale) {
double d=scaleY*(yymax-yymin); // new width
double c=(yymax+yymin)/2.0; // center of interval
yymin=c-d/2.0;
yymax=c+d/2.0;
}
if (includeY0 && !yAxis->getLogAxis()) {
if (yymin>0) yymin=0;
else if (yymax<0) yymax=0;
}
//std::cout<<" => yymin="<<yymin<<" yymax="<<yymax<<std::endl;
if (JKQTPIsOKFloat(yymin) && JKQTPIsOKFloat(yymax)) {
setY(yymin, yymax);
} else if (!JKQTPIsOKFloat(yymin) && JKQTPIsOKFloat(yymax)) {
setY(getYMin(), yymax);
} else if (JKQTPIsOKFloat(yymin) && !JKQTPIsOKFloat(yymax)) {
setY(yymin, getYMax());
}
}
//std::cout<<"end of zoomToFit\n";
//setXY(xxmin, xxmax, yymin, yymax);
@ -5075,8 +5209,9 @@ void JKQTBasePlotter::showPlotData() {
void JKQTBasePlotter::setEmittingSignalsEnabled(bool enabled)
{
emitSignals=enabled;
xAxis->setDoUpdateScaling(enabled);
yAxis->setDoUpdateScaling(enabled);
for (auto ax: getAxes(true)) {
ax->setDoUpdateScaling(enabled);
}
}
@ -5295,3 +5430,7 @@ void JKQTBasePlotter::JKQTPPen::setSymbolType(JKQTPGraphSymbols symbol)
{
m_symbol=symbol;
}
bool JKQTBasePlotter::filterPlotElementByXAxis::operator()(const JKQTPPlotElement *el) const { return el->getXAxisRef()==ref; }
bool JKQTBasePlotter::filterPlotElementByYAxis::operator()(const JKQTPPlotElement *el) const { return el->getYAxisRef()==ref; }

View File

@ -93,6 +93,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPPaintDeviceAdapter {
virtual QPaintDevice* createPaintdeviceMM(const QString& filename, double widthMM, double heightMM) const;
};
/** \brief base class for 2D plotter classes (used by the plotter widget JKQTPlotter)
* \ingroup jkqtpplotterclasses
*
@ -137,12 +138,49 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPPaintDeviceAdapter {
*
*
* \section jkqtplotter_base_grids_baseplotter Axis Ticks and Grids
* - The plotting of coordinate axes and grids, as well as coordinate transforms is done by
* JKQTPCoordinateAxis descendents (see documentation there)
* .
*
* \subsection jkqtplotter_base_grids_baseplotter_majoraxes Major Coordinate Axes
*
* JKQTBasePlotter - by default - has two major axes: A horizontal x-axis and a vertical y-axis.
*
* The plotting of coordinate axes and grids, as well as coordinate transforms is done by
* JKQTPCoordinateAxis descendents (see documentation there).
*
* If you want to set the axis properties, use getXAxis() or getYAxis() to get a pointer to the axis objects which then
* may be used to set the axis properties.
*
* \subsection jkqtplotter_base_grids_baseplotter_secondaryaxes Secondary Coordinate Axes
*
* In addition a plot may contain secondary axes, as shown below:
*
* \image html JKQTBasePlotter_addSecondaryYAxis.png
*
* You can add additional x-axes using addSecondaryXAxis() and y-axes using addSecondaryYAxis().
* These functions return a JKQTPCoordinateAxisRef, which can be used to reference these axes, when
* calling function like getXAxis() here the default-parameter call getXAxis(JKQTPPrimaryAxis) returns
* the primary axis (JKQTPPrimaryAxis may be omitted) and calling getXAxis(JKQTPSecondaryAxis) will return
* the first secondary axis and so on.
*
* In graphs (derived from JKQTPPlotElement) you can use JKQTPPlotElement::setXAxis() and JKQTPPlotElement::setYAxis()
* with a JKQTPCoordinateAxisRef as parameter to tell plots to use another axis.
*
* Using a JKQTPCoordinateAxisRef instead of a pointer to a JKQTPCoordinateAxis allows to exchange the axes in the plot,
* while not breaking the graphs.
*
* Here is a code example of how to use secondary axes:
* \code
* // construct a new x-axis-object
* JKQTPHorizontalAxisBase* secXAxis=new JKQTPHorizontalAxis(plot.getPlotter(), JKQTPPrimaryAxis)
* // add it to the plot
* auto xAxisRef2=plot.getPlotter()->addSecondaryXAxis(secXAxis);
* // ... now you can access it:
* plot.getXAxis(xAxisRef2)->setShowZeroAxis(false);
* // ... and use it for graphs:
* graph2->setXAxis(xAxisRef2);
* \endcode
*
* \see addSecondaryXAxis(), addSecondaryYAxis(), getXAxis(), getYAxis()
*
*
* \section jkqtbaseplotter_appearance_and_style Appearance & Styling of the Graph
*
@ -656,6 +694,13 @@ class JKQTPLOTTER_LIB_EXPORT JKQTBasePlotter: public QObject {
*/
void drawNonGrid(JKQTPEnhancedPainter& painter, const QPoint& pos=QPoint(0,0));
/** \brief updates the secondary axes
*
* The plot may contain (in addition to its primary axes) also secondary axes, that depend in their
* scaling (min,max, ...) on the primmary axes of the plot. This function updates/recalculates the
* scaling of these axes.
*/
void updateSecondaryAxes();
/** \brief emit plotUpdated() */
void redrawPlot() { if (emitPlotSignals) emit plotUpdated(); }
@ -826,17 +871,98 @@ class JKQTPLOTTER_LIB_EXPORT JKQTBasePlotter: public QObject {
JKQTMathText* getMathText();
/** \brief returns the internal JKQTMathText, used to render text with LaTeX markup */
const JKQTMathText *getMathText() const;
/** \brief returns the x-axis objet of the plot */
JKQTPHorizontalAxis *getXAxis();
/** \brief returns the y-axis objet of the plot */
JKQTPVerticalAxis* getYAxis();
/** \brief returns the x-axis objet of the plot */
const JKQTPHorizontalAxis* getXAxis() const;
/** \brief returns the y-axis objet of the plot */
const JKQTPVerticalAxis *getYAxis() const;
/** \brief returns the x-axis objet of the plot
*
* \see \ref jkqtplotter_base_grids_baseplotter
*/
JKQTPHorizontalAxisBase *getXAxis(JKQTPCoordinateAxisRef axis=JKQTPPrimaryAxis);
/** \brief returns the y-axis objet of the plot
*
* \see \ref jkqtplotter_base_grids_baseplotter
*/
JKQTPVerticalAxisBase* getYAxis(JKQTPCoordinateAxisRef axis=JKQTPPrimaryAxis);
/** \brief returns the x-axis objet of the plot
*
* \see \ref jkqtplotter_base_grids_baseplotter
*/
const JKQTPHorizontalAxisBase* getXAxis(JKQTPCoordinateAxisRef axis=JKQTPPrimaryAxis) const;
/** \brief returns the y-axis objet of the plot
*
* \see \ref jkqtplotter_base_grids_baseplotter
*/
const JKQTPVerticalAxisBase *getYAxis(JKQTPCoordinateAxisRef axis=JKQTPPrimaryAxis) const;
/** \brief returns whether an x-axis \a axis is registered with the plotter
*
* \note For \a axis \c ==JKQTPPrimaryAxis this function returns always \c true
*/
bool hasXAxis(JKQTPCoordinateAxisRef axis=JKQTPPrimaryAxis) const;
/** \brief returns whether a y-axis \a axis is registered with the plotter
*
* \note For \a axis \c ==JKQTPPrimaryAxis this function returns always \c true
*/
bool hasYAxis(JKQTPCoordinateAxisRef axis=JKQTPPrimaryAxis) const;
/** \brief returns the set of available x-axes (including the primary, if \c true is given as parameter) */
QSet<JKQTPCoordinateAxisRef> getAvailableXAxisRefs(bool includePrimary=false) const;
/** \brief returns the set of available y-axes (including the primary, if \c true is given as parameter) */
QSet<JKQTPCoordinateAxisRef> getAvailableYAxisRefs(bool includePrimary=false) const;
/** \brief returns all available x-axes */
QMap<JKQTPCoordinateAxisRef, JKQTPHorizontalAxisBase*> getXAxes(bool includePrimary=true);
/** \brief returns all available y-axes */
QMap<JKQTPCoordinateAxisRef, JKQTPVerticalAxisBase*> getYAxes(bool includePrimary=true);
/** \brief returns all available x- or y-axes */
QList<JKQTPCoordinateAxis*> getAxes(bool includePrimaries=true);
/** \brief adds a secondary x-axis
*
* \params axis the JKQTPHorizontalAxisBase object to add
* \returns a reference to this axis
*
* Usage is simple:
* \code
* // construct a new x-axis-object
* JKQTPHorizontalAxisBase* secXAxis=new JKQTPHorizontalAxis(plot.getPlotter(), JKQTPPrimaryAxis)
* // add it to the plot
* auto xAxisRef2=plot.getPlotter()->addSecondaryXAxis(secXAxis);
* // ... now you can access it:
* plot.getXAxis(xAxisRef2)->setShowZeroAxis(false);
* // ... and use it for graphs:
* graph2->setXAxis(xAxisRef2);
* \endcode
*
*
* Here is an example output:
*
* \image html JKQTBasePlotter_addSecondaryXAxis.png
*
* \see \ref jkqtplotter_base_grids_baseplotter_secondaryaxes , \subpage JKQTPlotterSecondaryAxes
*/
JKQTPCoordinateAxisRef addSecondaryXAxis(JKQTPHorizontalAxisBase* axis);
/** \brief adds a secondary y-axis
*
* \params axis the JKQTPVerticalAxisBase object to add
* \returns a reference to this axis
*
* Usage is simple:
* \code
* // construct a new y-axis-object
* JKQTPVerticalAxisBase* secYAxis=new JKQTPVerticalAxis(plot.getPlotter(), JKQTPPrimaryAxis)
* // add it to the plot
* auto yAxisRef2=plot.getPlotter()->addSecondaryYAxis(secYAxis);
* // ... now you can access it:
* plot.getYAxis(yAxisRef2)->setShowZeroAxis(false);
* // ... and use it for graphs:
* graph2->setYAxis(yAxisRef2);
* \endcode
*
* Here is an example output:
*
* \image html JKQTBasePlotter_addSecondaryYAxis.png
*
* \see \ref jkqtplotter_base_grids_baseplotter_secondaryaxes , \subpage JKQTPlotterSecondaryAxes
*/
JKQTPCoordinateAxisRef addSecondaryYAxis(JKQTPVerticalAxisBase* axis);
/** \copydoc actSavePlot */
/** \copydoc actSavePlot */
QAction* getActionSavePlot() const;
/** \copydoc actSaveData */
QAction* getActionSaveData() const;
@ -953,22 +1079,62 @@ class JKQTPLOTTER_LIB_EXPORT JKQTBasePlotter: public QObject {
}
}
/** \brief Functor which can be used as filter predicate for getGraphsXMinMax() or getGraphsYMinMax()
*
* \see getGraphsXMinMax(), getGraphsYMinMax(), allPlotElements
*/
typedef std::function<bool(const JKQTPPlotElement*)> PlotElementPreciate;
/** \brief Functor which does not apply any filter to JKQTPPlotElement, e.g. in getGraphsXMinMax() or getGraphsYMinMax()
*
* \see getGraphsXMinMax(), getGraphsYMinMax(), PlotElementPreciate
*/
struct JKQTPLOTTER_LIB_EXPORT allPlotElements {
inline bool operator()(const JKQTPPlotElement*) const { return true; };
};
/** \brief filter functor which accepts only those JKQTPPlotElement where JKQTPPlotElement::getXAxisRef()
* returns the JKQTPCoordinateAxisRef supplied to the constructor, e.g. in getGraphsXMinMax() or getGraphsYMinMax()
*
* \see getGraphsXMinMax(), getGraphsYMinMax(), PlotElementPreciate
*/
struct JKQTPLOTTER_LIB_EXPORT filterPlotElementByXAxis {
inline explicit filterPlotElementByXAxis(JKQTPCoordinateAxisRef ref_): ref(ref_) {};
inline bool operator()(const JKQTPPlotElement* el) const;
private:
JKQTPCoordinateAxisRef ref;
};
/** \brief filter functor which accepts only those JKQTPPlotElement where JKQTPPlotElement::getYAxisRef()
* returns the JKQTPCoordinateAxisRef supplied to the constructor, e.g. in getGraphsXMinMax() or getGraphsYMinMax()
*
* \see getGraphsXMinMax(), getGraphsYMinMax(), PlotElementPreciate
*/
struct JKQTPLOTTER_LIB_EXPORT filterPlotElementByYAxis {
inline explicit filterPlotElementByYAxis(JKQTPCoordinateAxisRef ref_): ref(ref_) {};
inline bool operator()(const JKQTPPlotElement* el) const;
private:
JKQTPCoordinateAxisRef ref;
};
/** \brief get the maximum and minimum x-value over all graphs in the plot
* \param[out] minx smallest x value
* \param[out] maxx largest x value
* \param[out] smallestGreaterZero smallest data point which is >0 (needed for scaling of logarithmic axes)
* \param predicate a PlotElementPreciate, which can be used to limit the JKQTPPlotElement to be evaluated
* \returns \c true if at least one matching graph was found and evaluated succcessfully
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
void getGraphsXMinMax(double& minx, double& maxx, double& smallestGreaterZero);
bool getGraphsXMinMax(double& minx, double& maxx, double& smallestGreaterZero, const PlotElementPreciate &predicate=allPlotElements());
/** \brief get the maximum and minimum y-value over all graphs in the plot
* \param[out] miny smallest y value
* \param[out] maxy largest y value
* \param[out] smallestGreaterZero smallest data point which is >0 (needed for scaling of logarithmic axes)
* \param predicate a PlotElementPreciate, which can be used to limit the JKQTPPlotElement to be evaluated
* \returns \c true if at least one matching graph was found and evaluated succcessfully
*
* The result is given in the two parameters which are call-by-reference parameters!
*/
void getGraphsYMinMax(double& miny, double& maxy, double& smallestGreaterZero);
bool getGraphsYMinMax(double& miny, double& maxy, double& smallestGreaterZero, const PlotElementPreciate &predicate=allPlotElements());
/** \brief denotes, which axes to synchronize in synchronizeToMaster() */
@ -1226,6 +1392,9 @@ class JKQTPLOTTER_LIB_EXPORT JKQTBasePlotter: public QObject {
*
* \param xminn absolute minimum of x-axis
* \param xmaxx absolute maximum of x-axis
* \param affectsSecondaryAxes if \c true, the secondary axes are affectedtoo, by using a relative zooming scheme,
* i.e. if a major axis range shrinks by 50%, also the secondary ranges shrink by 50%
* [default: \c false]
*
* \note You cannot expand the x-range outside the absolute x-range set e.g. by setAbsoluteX()!
* Also the range will be limited to possible values (e.g. to positive values if you use
@ -1236,12 +1405,15 @@ class JKQTPLOTTER_LIB_EXPORT JKQTBasePlotter: public QObject {
*
* \see setY(), setXY(), zoomToFit(), setAbsoluteXY(), JKQTPlotter::setY()
*/
void setX(double xminn, double xmaxx);
void setX(double xminn, double xmaxx, bool affectsSecondaryAxes=false);
/** \brief sets the y-range of the plot (minimum and maximum y-value on the y-axis)
*
* \param yminn absolute minimum of y-axis
* \param ymaxx absolute maximum of y-axis
* \param affectsSecondaryAxes if \c true, the secondary axes are affectedtoo, by using a relative zooming scheme,
* i.e. if a major axis range shrinks by 50%, also the secondary ranges shrink by 50%
* [default: \c false]
*
* \note You cannot expand the y-range outside the absolute y-range set e.g. by setAbsoluteY()!
* Also the range will be limited to possible values (e.g. to positive values if you use
@ -1252,7 +1424,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTBasePlotter: public QObject {
*
* \see setX(), setXY(), zoomToFit(), setAbsoluteXY(), JKQTPlotter::setX()
*/
void setY(double yminn, double ymaxx);
void setY(double yminn, double ymaxx, bool affectsSecondaryAxes=false);
/** \brief sets the x- and y-range of the plot (minimum and maximum values on the x-/y-axis)
*
@ -1260,6 +1432,9 @@ class JKQTPLOTTER_LIB_EXPORT JKQTBasePlotter: public QObject {
* \param xmaxx absolute maximum of x-axis
* \param yminn absolute minimum of y-axis
* \param ymaxx absolute maximum of y-axis
* \param affectsSecondaryAxes if \c true, the secondary axes are affectedtoo, by using a relative zooming scheme,
* i.e. if a major axis range shrinks by 50%, also the secondary ranges shrink by 50%
* [default: \c false]
*
* \note You cannot expand the ranges outside the absolute ranges set e.g. by setAbsoluteXY()!
* Also the range will be limited to possible values (e.g. to positive values if you use
@ -1270,7 +1445,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTBasePlotter: public QObject {
*
* \see setX(), setX(), zoomToFit(), setAbsoluteXY(), JKQTPlotter::setXY()
*/
void setXY(double xminn, double xmaxx, double yminn, double ymaxx);
void setXY(double xminn, double xmaxx, double yminn, double ymaxx, bool affectsSecondaryAxes=false);
/** \brief sets absolutely limiting x-range of the plot
*
@ -1873,8 +2048,12 @@ class JKQTPLOTTER_LIB_EXPORT JKQTBasePlotter: public QObject {
/** \brief object used for the x-axis */
JKQTPHorizontalAxis* xAxis;
/** \brief objects used a secondary x-axes */
QMap<JKQTPCoordinateAxisRef, JKQTPHorizontalAxisBase*> secondaryXAxis;
/** \brief object used for the y-axis */
JKQTPVerticalAxis* yAxis;
/** \brief objects used a secondary y-axes */
QMap<JKQTPCoordinateAxisRef, JKQTPVerticalAxisBase*> secondaryYAxis;
/** \brief filename for the ini file in which to save the user settings
* \see jkqtplotter_base_userprops
@ -2031,6 +2210,40 @@ class JKQTPLOTTER_LIB_EXPORT JKQTBasePlotter: public QObject {
*/
double internalPlotBorderRight_notIncludingOutsidePlotSections;
/** \brief <b>calculated value:</b> free space between widget top border and (plot+drawOutside) top border (including coordinate axes)
* \internal
*
* \image html plot_widget_orientation.png
*
* \note This property is an intermediate storage for calculated values. Do not change directly!
*/
double internalPlotBorderTop_notIncludingAxisAndOutsidePlotSections;
/** \brief <b>calculated value:</b> free space between widget left border and (plot+drawOutside) left border (including coordinate axes)
* \internal
*
* \image html plot_widget_orientation.png
*
* \note This property is an intermediate storage for calculated values. Do not change directly!
*/
double internalPlotBorderLeft_notIncludingAxisAndOutsidePlotSections;
/** \brief <b>calculated value:</b> free space between widget right border and (plot+drawOutside) right border (including coordinate axes)
* \internal
*
* \image html plot_widget_orientation.png
*
* \note This property is an intermediate storage for calculated values. Do not change directly!
*/
double internalPlotBorderBottom_notIncludingAxisAndOutsidePlotSections;
/** \brief <b>calculated value:</b> free space between widget bottom border and (plot+drawOutside) bottom border (including coordinate axes)
* \internal
*
* \image html plot_widget_orientation.png
*
* \note This property is an intermediate storage for calculated values. Do not change directly!
*/
double internalPlotBorderRight_notIncludingAxisAndOutsidePlotSections;
/** \brief <b>calculated value:</b> plot width in pixel inside the widget (calculated by calcPlotScaling() from plotBorderLeft, plotBorderRight and widgetWidth)
*
* \image html plot_widget_orientation.png

View File

@ -31,6 +31,7 @@ JKQTBasePlotterStyle::JKQTBasePlotterStyle():
keyStyle(*this),
xAxisStyle(*this),
yAxisStyle(*this),
secondaryAxisSeparation(6),
rightColorbarAxisStyle(*this),
topColorbarAxisStyle(*this),
graphsStyle(*this)
@ -63,6 +64,7 @@ void JKQTBasePlotterStyle::loadSettings(const QSettings &settings, const QString
defaultTextColor=jkqtp_String2QColor(settings.value(group+"text_default_color", jkqtp_QColor2String(defaultStyle.defaultTextColor)).toString());
defaultFontSize=settings.value(group+"text_default_size", defaultStyle.defaultFontSize).toDouble();
defaultFontName=settings.value(group+"text_default_font_name", defaultStyle.defaultFontName).toString();
secondaryAxisSeparation=settings.value(group+"secondary_axis_separation", defaultStyle.secondaryAxisSeparation).toDouble();
keyStyle.loadSettings(settings, group+"key/", defaultStyle.keyStyle);
xAxisStyle.loadSettings(settings, group+"axis_x/", defaultStyle.xAxisStyle);
@ -101,6 +103,7 @@ void JKQTBasePlotterStyle::saveSettings(QSettings &settings, const QString &grou
settings.setValue(group+"plot_frame_color", jkqtp_QColor2String(plotFrameColor));
settings.setValue(group+"plot_frame_width", plotFrameWidth);
settings.setValue(group+"plot_frame_rounded", plotFrameRounding);
settings.setValue(group+"secondary_axis_separation", secondaryAxisSeparation);
keyStyle.saveSettings(settings, group+"key/");
xAxisStyle.saveSettings(settings, group+"axis_x/");

View File

@ -160,6 +160,8 @@ class JKQTPLOTTER_LIB_EXPORT JKQTBasePlotterStyle {
JKQTPCoordinateAxisStyle xAxisStyle;
/** \brief style of the y-axis of the main coordinate system */
JKQTPCoordinateAxisStyle yAxisStyle;
/** \brief separation between two seondary axes in pt */
double secondaryAxisSeparation;
/** \brief style of the coordinate axes used to display colorbars in the right */
JKQTPColorbarCoordinateAxisStyle rightColorbarAxisStyle;
/** \brief style of the coordinate axes used to display colorbars at the top */

View File

@ -82,6 +82,7 @@ void JKQTPCoordinateAxis::setParent(JKQTBasePlotter* parent) {
void JKQTPCoordinateAxis::redrawPlot() {
//if (paramsChanged) {
calcPlotScaling();
parent->updateSecondaryAxes();
parent->redrawPlot();
//}
}
@ -1140,6 +1141,18 @@ void JKQTPCoordinateAxis::setTickLabelColor(QColor c) {
redrawPlot();
}
void JKQTPCoordinateAxis::setColor(QColor c)
{
setAxisColor(c);
setGridColor(c.lighter());
setMinorGridColor(c.lighter());
setLabelColor(c);
setMinorTickColor(c);
setMinorTickLabelColor(c);
setTickColor(c);
setTickLabelColor(c);
}
std::pair<QSizeF,QSizeF> JKQTPCoordinateAxis::getSize0(JKQTPEnhancedPainter &/*painter*/)
{
return std::pair<QSizeF,QSizeF>(QSizeF(0,0),QSizeF(0,0));
@ -1276,7 +1289,7 @@ double JKQTPCoordinateAxis::getZeroAxisPos(bool *drawZeroAxis) {
JKQTPVerticalAxis::JKQTPVerticalAxis(JKQTBasePlotter* parent):
JKQTPVerticalAxisBase::JKQTPVerticalAxisBase(JKQTBasePlotter* parent):
JKQTPCoordinateAxis(parent)
{
//axisPrefix="yaxis_";
@ -1288,15 +1301,8 @@ JKQTPVerticalAxis::JKQTPVerticalAxis(JKQTBasePlotter* parent):
}
}
double JKQTPVerticalAxis::getParentPlotWidth() const {
return parent->getPlotHeight();
}
double JKQTPVerticalAxis::getParentPlotOffset() const {
return parent->getInternalPlotBorderTop();
}
std::pair<QSizeF,QSizeF> JKQTPVerticalAxis::getSize0(JKQTPEnhancedPainter& painter) {
std::pair<QSizeF,QSizeF> JKQTPVerticalAxisBase::getSize0(JKQTPEnhancedPainter& painter) {
if (axisStyle.drawMode0==JKQTPCADMnone) return std::pair<QSizeF,QSizeF>(QSizeF(0,0),QSizeF(0,0));
double ptwidth=0;
double ptwidth_r=0;
@ -1326,7 +1332,7 @@ std::pair<QSizeF,QSizeF> JKQTPVerticalAxis::getSize0(JKQTPEnhancedPainter& paint
}
QSizeF JKQTPVerticalAxis::getSize1(JKQTPEnhancedPainter& painter) {
QSizeF JKQTPVerticalAxisBase::getSize1(JKQTPEnhancedPainter& painter) {
if (axisStyle.drawMode1==JKQTPCADMnone) return QSize(0,0);
double ptwidth=axisStyle.axisLineOffset;
const double arrowSize=((axisStyle.drawMode1&(JKQTPCADMMinArrow|JKQTPCADMMinFilledArrow|JKQTPCADMMaxArrow|JKQTPCADMMaxFilledArrow))!=int(0))?(axisStyle.getArrowSize(painter, parent)/2.0):0.0;
@ -1346,7 +1352,7 @@ QSizeF JKQTPVerticalAxis::getSize1(JKQTPEnhancedPainter& painter) {
return QSizeF(qMax(parent->pt2px(painter, ptwidth)+labwidth, arrowSize), getParentPlotWidth()).expandedTo(getSize0(painter).first);
}
QSizeF JKQTPVerticalAxis::getSize2(JKQTPEnhancedPainter& painter) {
QSizeF JKQTPVerticalAxisBase::getSize2(JKQTPEnhancedPainter& painter) {
if (axisStyle.drawMode2==JKQTPCADMnone) return QSize(0,0);
double ptwidth=axisStyle.axisLineOffset;
const double arrowSize=((axisStyle.drawMode2&(JKQTPCADMMinArrow|JKQTPCADMMinFilledArrow|JKQTPCADMMaxArrow|JKQTPCADMMaxFilledArrow))!=int(0))?(axisStyle.getArrowSize(painter, parent)/2.0):0.0;
@ -1366,26 +1372,7 @@ QSizeF JKQTPVerticalAxis::getSize2(JKQTPEnhancedPainter& painter) {
return QSizeF(qMax(arrowSize, parent->pt2px(painter, ptwidth)+labwidth), getParentPlotWidth()).expandedTo(getSize0(painter).second);
}
double JKQTPVerticalAxis::getParentOtheraxisOffset() const {
return parent->x2p(parent->getXMin());
}
double JKQTPVerticalAxis::parentOtherAxisX2P(double x) const
{
return parent->x2p(x);
}
double JKQTPVerticalAxis::getParentOtheraxisWidth() const {
return fabs(parent->x2p(parent->getXMax())-parent->x2p(parent->getXMin()));
}
bool JKQTPVerticalAxis::getParentOtheraxisInverted() const
{
return parent->getXAxis()->getInverted();
}
void JKQTPVerticalAxis::drawGrids(JKQTPEnhancedPainter& painter) {
void JKQTPVerticalAxisBase::drawGrids(JKQTPEnhancedPainter& painter) {
//qDebug()<<" start JKQTPVerticalAxis::drawGrids(";
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
QPen pg=painter.pen();
@ -1459,7 +1446,7 @@ void JKQTPVerticalAxis::drawGrids(JKQTPEnhancedPainter& painter) {
//qDebug()<<" end JKQTPVerticalAxis::drawGrids(";
}
void JKQTPVerticalAxis::drawTickLabel1(JKQTPEnhancedPainter &painter, double xx, double yy, double labelOffset, const QString& label, double fontSize, bool isMinor)
void JKQTPVerticalAxisBase::drawTickLabel1(JKQTPEnhancedPainter &painter, double xx, double yy, double labelOffset, const QString& label, double fontSize, bool isMinor)
{
getParentMathText()->setFontSize(fontSize*parent->getFontSizeMultiplier());
getParentMathText()->setFontSpecial(getParent()->getCurrentPlotterStyle().defaultFontName);
@ -1498,7 +1485,7 @@ void JKQTPVerticalAxis::drawTickLabel1(JKQTPEnhancedPainter &painter, double xx,
}
}
void JKQTPVerticalAxis::drawTickLabel2(JKQTPEnhancedPainter &painter, double xx, double yy, double labelOffset, const QString &label, double fontSize, bool isMinor)
void JKQTPVerticalAxisBase::drawTickLabel2(JKQTPEnhancedPainter &painter, double xx, double yy, double labelOffset, const QString &label, double fontSize, bool isMinor)
{
getParentMathText()->setFontSize(fontSize*parent->getFontSizeMultiplier());
getParentMathText()->setFontSpecial(getParent()->getCurrentPlotterStyle().defaultFontName);
@ -1540,7 +1527,7 @@ void JKQTPVerticalAxis::drawTickLabel2(JKQTPEnhancedPainter &painter, double xx,
}
void JKQTPVerticalAxis::drawAxisLabel1(JKQTPEnhancedPainter &painter, double left, double bottom, QSizeF labelMax, JKQTPCADrawMode drawMode) {
void JKQTPVerticalAxisBase::drawAxisLabel1(JKQTPEnhancedPainter &painter, double left, double bottom, QSizeF labelMax, JKQTPCADrawMode drawMode) {
double labelOffset=parent->pt2px(painter, axisStyle.labelDistance);
if (drawMode.testFlag(JKQTPCADMTicks)) labelOffset+=parent->pt2px(painter, axisStyle.tickOutsideLength);
if (drawMode.testFlag(JKQTPCADMTickLabels)) {
@ -1586,7 +1573,7 @@ void JKQTPVerticalAxis::drawAxisLabel1(JKQTPEnhancedPainter &painter, double lef
painter.resetTransform();
}
void JKQTPVerticalAxis::drawAxisLabel2(JKQTPEnhancedPainter &painter, double right, double bottom, QSizeF labelMax, JKQTPCADrawMode drawMode) {
void JKQTPVerticalAxisBase::drawAxisLabel2(JKQTPEnhancedPainter &painter, double right, double bottom, QSizeF labelMax, JKQTPCADrawMode drawMode) {
double labelOffset=parent->pt2px(painter, axisStyle.labelDistance);
if (drawMode.testFlag(JKQTPCADMTicks)) labelOffset+=parent->pt2px(painter, axisStyle.tickOutsideLength);
if (drawMode.testFlag(JKQTPCADMTickLabels)) {
@ -1633,7 +1620,7 @@ void JKQTPVerticalAxis::drawAxisLabel2(JKQTPEnhancedPainter &painter, double rig
painter.resetTransform();
}
void JKQTPVerticalAxis::drawAxes(JKQTPEnhancedPainter& painter) {
void JKQTPVerticalAxisBase::drawAxes(JKQTPEnhancedPainter& painter, int move1, int move2) {
#ifdef JKQTBP_AUTOTIMER
JKQTPAutoOutputTimer jkaat(QString("JKQTPEnhancedPainter[%1]::drawAxes()").arg(objectName()));
#endif
@ -1657,8 +1644,8 @@ void JKQTPVerticalAxis::drawAxes(JKQTPEnhancedPainter& painter) {
right=getParentOtheraxisOffset()+getParentOtheraxisWidth();//;
}
// move axes outside plot rectangle, if required
left-=parent->pt2px(painter, axisStyle.axisLineOffset);
right+=parent->pt2px(painter, axisStyle.axisLineOffset);
left-=parent->pt2px(painter, axisStyle.axisLineOffset)+move1;
right+=parent->pt2px(painter, axisStyle.axisLineOffset)+move2;
double ticklabelOffset1PT=axisStyle.tickLabelDistance; // offset of tick labels from axis 1
@ -1912,9 +1899,56 @@ void JKQTPVerticalAxis::drawAxes(JKQTPEnhancedPainter& painter) {
JKQTPVerticalAxis::JKQTPVerticalAxis(JKQTBasePlotter* parent, JKQTPCoordinateAxisRef otherAxisRef_):
JKQTPVerticalAxisBase(parent), otherAxisRef(otherAxisRef_)
{
//axisPrefix="yaxis_";
scaleSign=-1;
if (parent) {
axisStyle=parent->getCurrentPlotterStyle().yAxisStyle;
} else {
axisStyle=JKQTPGetSystemDefaultBaseStyle().yAxisStyle;
}
}
double JKQTPVerticalAxis::getParentPlotWidth() const {
return parent->getPlotHeight();
}
double JKQTPVerticalAxis::getParentPlotOffset() const {
return parent->getInternalPlotBorderTop();
}
double JKQTPVerticalAxis::getParentOtheraxisOffset() const {
return getOtherAxis()->x2p(getOtherAxis()->getMin());
}
double JKQTPVerticalAxis::parentOtherAxisX2P(double x) const
{
return getOtherAxis()->x2p(x);
}
JKQTPCoordinateAxisRef JKQTPVerticalAxis::getOtherAxisRef() const {
return otherAxisRef;
}
const JKQTPCoordinateAxis *JKQTPVerticalAxis::getOtherAxis() const {
return parent->getXAxis(otherAxisRef);
}
double JKQTPVerticalAxis::getParentOtheraxisWidth() const {
return fabs(getOtherAxis()->x2p(getOtherAxis()->getMax())-getOtherAxis()->x2p(getOtherAxis()->getMin()));
}
bool JKQTPVerticalAxis::getParentOtheraxisInverted() const
{
return getOtherAxis()->getInverted();
}
JKQTPVerticalIndependentAxis::JKQTPVerticalIndependentAxis(double _axisOffset, double _axisWidth, double _otherAxisOffset, double _otherAxisWidth, JKQTBasePlotter* parent):
JKQTPVerticalAxis(parent),
JKQTPVerticalAxisBase(parent),
axisOffset(_axisOffset),
axisWidth(_axisWidth),
otherAxisWidth(_otherAxisOffset),
@ -1992,7 +2026,7 @@ double JKQTPVerticalIndependentAxis::parentOtherAxisX2P(double x) const
JKQTPHorizontalAxis::JKQTPHorizontalAxis(JKQTBasePlotter* parent):
JKQTPHorizontalAxisBase::JKQTPHorizontalAxisBase(JKQTBasePlotter* parent):
JKQTPCoordinateAxis(parent)
{
//axisPrefix="xaxis_";
@ -2005,15 +2039,8 @@ JKQTPHorizontalAxis::JKQTPHorizontalAxis(JKQTBasePlotter* parent):
}
double JKQTPHorizontalAxis::getParentPlotWidth() const {
return parent->getPlotWidth();
}
double JKQTPHorizontalAxis::getParentPlotOffset() const {
return parent->getInternalPlotBorderLeft();
}
std::pair<QSizeF,QSizeF> JKQTPHorizontalAxis::getSize0(JKQTPEnhancedPainter& painter) {
std::pair<QSizeF,QSizeF> JKQTPHorizontalAxisBase::getSize0(JKQTPEnhancedPainter& painter) {
if (axisStyle.drawMode0==JKQTPCADMnone) return std::pair<QSizeF,QSizeF>(QSizeF(0,0),QSizeF(0,0));
double ptheight=0;
double ptheight_t=0;
@ -2043,7 +2070,7 @@ std::pair<QSizeF,QSizeF> JKQTPHorizontalAxis::getSize0(JKQTPEnhancedPainter& pai
);
}
QSizeF JKQTPHorizontalAxis::getSize1(JKQTPEnhancedPainter& painter) {
QSizeF JKQTPHorizontalAxisBase::getSize1(JKQTPEnhancedPainter& painter) {
if (axisStyle.drawMode1==JKQTPCADMnone) return QSize(0,0);
double ptheight=axisStyle.axisLineOffset;
const double arrowSize=((axisStyle.drawMode1&(JKQTPCADMMinArrow|JKQTPCADMMinFilledArrow|JKQTPCADMMaxArrow|JKQTPCADMMaxFilledArrow))!=int(0))?(axisStyle.getArrowSize(painter, parent)/2.0):0.0;
@ -2063,7 +2090,7 @@ QSizeF JKQTPHorizontalAxis::getSize1(JKQTPEnhancedPainter& painter) {
return QSizeF(getParentPlotWidth(), qMax(arrowSize,parent->pt2px(painter, ptheight)+labheight)).expandedTo(getSize0(painter).first);
}
QSizeF JKQTPHorizontalAxis::getSize2(JKQTPEnhancedPainter& painter) {
QSizeF JKQTPHorizontalAxisBase::getSize2(JKQTPEnhancedPainter& painter) {
if (axisStyle.drawMode2==JKQTPCADMnone) return QSize(0,0);
double ptheight=axisStyle.axisLineOffset;
const double arrowSize=((axisStyle.drawMode2&(JKQTPCADMMinArrow|JKQTPCADMMinFilledArrow|JKQTPCADMMaxArrow|JKQTPCADMMaxFilledArrow))!=int(0))?(axisStyle.getArrowSize(painter, parent)/2.0):0.0;
@ -2084,24 +2111,7 @@ QSizeF JKQTPHorizontalAxis::getSize2(JKQTPEnhancedPainter& painter) {
}
double JKQTPHorizontalAxis::getParentOtheraxisOffset() const {
return parent->y2p(parent->getYMax());
}
double JKQTPHorizontalAxis::parentOtherAxisX2P(double x) const
{
return parent->y2p(x);
}
double JKQTPHorizontalAxis::getParentOtheraxisWidth() const {
return fabs(parent->y2p(parent->getYMax())-parent->y2p(parent->getYMin()));
}
bool JKQTPHorizontalAxis::getParentOtheraxisInverted() const
{
return parent->getYAxis()->getInverted();
}
void JKQTPHorizontalAxis::drawGrids(JKQTPEnhancedPainter& painter) {
void JKQTPHorizontalAxisBase::drawGrids(JKQTPEnhancedPainter& painter) {
painter.save(); auto __finalpaint=JKQTPFinally([&painter]() {painter.restore();});
//double right=x2p(axismax);
//double left=x2p(axismin);
@ -2165,7 +2175,7 @@ void JKQTPHorizontalAxis::drawGrids(JKQTPEnhancedPainter& painter) {
}
void JKQTPHorizontalAxis::drawTickLabel1(JKQTPEnhancedPainter &painter, double xx, double yy, double labelOffset, const QString &label, double fontSize, double ascentMax, double /*descentMax*/, bool isMinor)
void JKQTPHorizontalAxisBase::drawTickLabel1(JKQTPEnhancedPainter &painter, double xx, double yy, double labelOffset, const QString &label, double fontSize, double ascentMax, double /*descentMax*/, bool isMinor)
{
getParentMathText()->setFontSize(fontSize*parent->getFontSizeMultiplier());
getParentMathText()->setFontSpecial(getParent()->getCurrentPlotterStyle().defaultFontName);
@ -2194,7 +2204,7 @@ void JKQTPHorizontalAxis::drawTickLabel1(JKQTPEnhancedPainter &painter, double x
}
}
void JKQTPHorizontalAxis::drawTickLabel2(JKQTPEnhancedPainter &painter, double xx, double yy, double labelOffset, const QString &label, double fontSize, double /*ascentMax*/, double descentMax, bool isMinor)
void JKQTPHorizontalAxisBase::drawTickLabel2(JKQTPEnhancedPainter &painter, double xx, double yy, double labelOffset, const QString &label, double fontSize, double /*ascentMax*/, double descentMax, bool isMinor)
{
getParentMathText()->setFontSize(fontSize*parent->getFontSizeMultiplier());
getParentMathText()->setFontSpecial(getParent()->getCurrentPlotterStyle().defaultFontName);
@ -2223,7 +2233,7 @@ void JKQTPHorizontalAxis::drawTickLabel2(JKQTPEnhancedPainter &painter, double x
}
void JKQTPHorizontalAxis::drawAxisLabel1(JKQTPEnhancedPainter &painter, double left, double bottom, QSizeF labelMax, JKQTPCADrawMode drawMode) {
void JKQTPHorizontalAxisBase::drawAxisLabel1(JKQTPEnhancedPainter &painter, double left, double bottom, QSizeF labelMax, JKQTPCADrawMode drawMode) {
double labelOffset=parent->pt2px(painter, axisStyle.labelDistance);
if (drawMode.testFlag(JKQTPCADMTicks)) labelOffset+=parent->pt2px(painter, axisStyle.tickOutsideLength);
if (drawMode.testFlag(JKQTPCADMTickLabels)) {
@ -2269,12 +2279,12 @@ void JKQTPHorizontalAxis::drawAxisLabel1(JKQTPEnhancedPainter &painter, double l
}
}
void JKQTPHorizontalAxis::drawAxisLabel2(JKQTPEnhancedPainter &painter, double left, double top, QSizeF labelMax, JKQTPCADrawMode drawMode) {
void JKQTPHorizontalAxisBase::drawAxisLabel2(JKQTPEnhancedPainter &painter, double left, double top, QSizeF labelMax, JKQTPCADrawMode drawMode) {
double labelOffset=parent->pt2px(painter, axisStyle.labelDistance);
if (drawMode.testFlag(JKQTPCADMTicks)) labelOffset+=parent->pt2px(painter, axisStyle.tickOutsideLength);
if (drawMode.testFlag(JKQTPCADMTickLabels)) {
labelOffset+=parent->pt2px(painter, axisStyle.tickLabelDistance);
labelOffset+=labelMax.width();//+labelMax.height();
labelOffset+=labelMax.height();//+labelMax.height();
}
@ -2314,7 +2324,7 @@ void JKQTPHorizontalAxis::drawAxisLabel2(JKQTPEnhancedPainter &painter, double l
//painter.resetTransform();
}
void JKQTPHorizontalAxis::drawAxes(JKQTPEnhancedPainter& painter) {
void JKQTPHorizontalAxisBase::drawAxes(JKQTPEnhancedPainter& painter, int move1, int move2) {
#ifdef JKQTBP_AUTOTIMER
JKQTPAutoOutputTimer jkaat(QString("JKQTPHorizontalAxis[%1]::drawAxes()").arg(objectName()));
#endif
@ -2338,8 +2348,8 @@ void JKQTPHorizontalAxis::drawAxes(JKQTPEnhancedPainter& painter) {
bottom=getParentOtheraxisOffset()+getParentOtheraxisWidth();//;
}
// move axes outside plot rectangle, if required
top-=parent->pt2px(painter, axisStyle.axisLineOffset);
bottom+=parent->pt2px(painter, axisStyle.axisLineOffset);
top-=parent->pt2px(painter, axisStyle.axisLineOffset)+move2;
bottom+=parent->pt2px(painter, axisStyle.axisLineOffset)+move1;
double ticklabelOffset1PT=axisStyle.tickLabelDistance; // offset of tick labels from axis 1
double minorticklabelOffset1PT=axisStyle.tickLabelDistance; // offset ofminor tick labels from axis 1
@ -2584,6 +2594,53 @@ void JKQTPHorizontalAxis::drawAxes(JKQTPEnhancedPainter& painter) {
JKQTPHorizontalAxis::JKQTPHorizontalAxis(JKQTBasePlotter* parent, JKQTPCoordinateAxisRef otherAxisRef_):
JKQTPHorizontalAxisBase(parent), otherAxisRef(otherAxisRef_)
{
//axisPrefix="xaxis_";
scaleSign=1;
if (parent) {
axisStyle=parent->getCurrentPlotterStyle().xAxisStyle;
} else {
axisStyle=JKQTPGetSystemDefaultBaseStyle().xAxisStyle;
}
}
double JKQTPHorizontalAxis::getParentPlotWidth() const {
return parent->getPlotWidth();
}
double JKQTPHorizontalAxis::getParentPlotOffset() const {
return parent->getInternalPlotBorderLeft();
}
double JKQTPHorizontalAxis::getParentOtheraxisOffset() const {
return getOtherAxis()->x2p(getOtherAxis()->getMax());
}
double JKQTPHorizontalAxis::parentOtherAxisX2P(double x) const
{
return parent->y2p(x);
}
JKQTPCoordinateAxisRef JKQTPHorizontalAxis::getOtherAxisRef() const
{
return otherAxisRef;
}
const JKQTPCoordinateAxis *JKQTPHorizontalAxis::getOtherAxis() const {
return parent->getYAxis(otherAxisRef);
}
double JKQTPHorizontalAxis::getParentOtheraxisWidth() const {
return fabs(getOtherAxis()->x2p(getOtherAxis()->getMax())-getOtherAxis()->x2p(getOtherAxis()->getMin()));
}
bool JKQTPHorizontalAxis::getParentOtheraxisInverted() const
{
return getOtherAxis()->getInverted();
}

View File

@ -36,6 +36,19 @@
// forward declarations
class JKQTBasePlotter;
/*! \brief named references for different oordinate axes in the plot
\ingroup jkqtpplottersupprt
*/
enum JKQTPCoordinateAxes: uint8_t {
JKQTPPrimaryAxis=0,
JKQTPSecondaryAxis=1
};
/*! \brief type for indexing coordinate axes in a plot
\ingroup jkqtpplottersupprt
*/
typedef JKQTPCoordinateAxes JKQTPCoordinateAxisRef;
/*! \brief this virtual class is the base for any type of coordinate axis, to be drawn by JKQTBasePlotter.
\ingroup jkqtpbaseplotter_elements
@ -238,8 +251,13 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPCoordinateAxis: public QObject {
/** \brief returns the size of the right/top axis in pixels */
virtual QSizeF getSize2(JKQTPEnhancedPainter& painter)=0;
/** \brief draw axes */
virtual void drawAxes(JKQTPEnhancedPainter& painter)=0;
/** \brief draw the axes
*
* \param painter the painter to use for drawing
* \param move1 offset in pixels on the major side (horizontal: bottom, vertical: left)
* \param move2 offset in pixels on the secondary side (horizontal: top, vertical: right)
*/
virtual void drawAxes(JKQTPEnhancedPainter& painter, int move1=0, int move2=0)=0;
/** \brief draw grids */
virtual void drawGrids(JKQTPEnhancedPainter& painter)=0;
@ -650,6 +668,8 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPCoordinateAxis: public QObject {
void setTickColor(QColor c);
/** \copydoc JKQTPCoordinateAxisStyle::tickLabelColor */
void setTickLabelColor(QColor c) ;
/** \brief sets all colors (line, ticks, label, ...) of the axis */
void setColor(QColor c) ;
protected:
/** \brief returns the size of the zero axis in pixels, the first part of the return-value is the lhs size and the second part the rhs size */
@ -852,20 +872,32 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPCoordinateAxis: public QObject {
/*! \brief implements a vertical axis, based on JKQTPCoordinateAxis (for most of documentation: see JKQTPCoordinateAxis).
/*! \brief base class for vertical axes, based on JKQTPCoordinateAxis (for most of documentation: see JKQTPCoordinateAxis).
\ingroup jkqtpbaseplotter_elements
The positioning of the different axis elements depends on the psition of the "other" axis (here x-axis),
The positioning of the different axis elements depends on the psition of the "other" axis (i.e. a horizontal/x-axis),
i.e. the corresponding vertical axis:
\image html JKQTPHorizontalAxisPositioning.png
\image html JKQTPVerticalAxisPositioning.png
But this "other>" axis is not defined here, but has to be defined in derived classes by immplementing the corresponding
pure virtual functions:
- getParentPlotWidth()
- getParentPlotOffset()
- getParentOtheraxisWidth()
- getParentOtheraxisInverted()
- getParentOtheraxisOffset()
- parentOtherAxisX2P()
.
\see JKQTPHorizontalAxisBase
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPVerticalAxis: public JKQTPCoordinateAxis {
class JKQTPLOTTER_LIB_EXPORT JKQTPVerticalAxisBase: public JKQTPCoordinateAxis {
Q_OBJECT
protected:
public:
/** \brief class constructor */
JKQTPVerticalAxis(JKQTBasePlotter* parent);
JKQTPVerticalAxisBase(JKQTBasePlotter* parent);
/** \brief returns the size of the left axis in pixels */
virtual QSizeF getSize1(JKQTPEnhancedPainter& painter) override;
@ -874,25 +906,12 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPVerticalAxis: public JKQTPCoordinateAxis {
virtual QSizeF getSize2(JKQTPEnhancedPainter& painter) override;
/** copydoc JKQTPCoordinateAxis::drawAxes() */
virtual void drawAxes(JKQTPEnhancedPainter& painter) override;
virtual void drawAxes(JKQTPEnhancedPainter& painter, int move1=0, int move2=0) override;
/** copydoc JKQTPCoordinateAxis::drawGrids() */
virtual void drawGrids(JKQTPEnhancedPainter& painter) override;
/** copydoc JKQTPCoordinateAxis::getParentPlotWidth() */
virtual double getParentPlotWidth() const override;
/** copydoc JKQTPCoordinateAxis::getParentPlotOffset() */
virtual double getParentPlotOffset() const override;
/** copydoc JKQTPCoordinateAxis::getParentOtheraxisWidth() */
virtual double getParentOtheraxisWidth() const override;
/** copydoc JKQTPCoordinateAxis::getParentOtheraxisInverted() */
virtual bool getParentOtheraxisInverted() const override;
/** copydoc JKQTPCoordinateAxis::getParentOtheraxisOffset() */
virtual double getParentOtheraxisOffset() const override;
/** copydoc JKQTPCoordinateAxis::parentOtherAxisX2P() */
virtual double parentOtherAxisX2P(double x) const override;
protected:
/** copydoc JKQTPCoordinateAxis::getSize0() */
virtual std::pair<QSizeF,QSizeF> getSize0(JKQTPEnhancedPainter& painter) override;
@ -922,6 +941,49 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPVerticalAxis: public JKQTPCoordinateAxis {
void drawAxisLabel1(JKQTPEnhancedPainter &painter, double left, double bottom, QSizeF labelMax, JKQTPCADrawMode drawMode);
/** \brief draw the axis label using \a painter for axis 2 at \c x= \a right and \c y= \a bottom. \a labelMax is the maximum Size of all tick labels */
void drawAxisLabel2(JKQTPEnhancedPainter &painter, double right, double bottom, QSizeF labelMax, JKQTPCADrawMode drawMode);
};
/*! \brief implements a vertical axis for use as primary, secondary, ... axis of a JKQTPBasePlotter,
* based on JKQTPCoordinateAxis (for most of documentation: see JKQTPCoordinateAxis).
\ingroup jkqtpbaseplotter_elements
The positioning of the different axis elements depends on the psition of the "other" axis (here x-axis),
i.e. the corresponding vertical axis:
\image html JKQTPVerticalAxisPositioning.png
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPVerticalAxis: public JKQTPVerticalAxisBase {
Q_OBJECT
protected:
public:
/** \brief class constructor */
JKQTPVerticalAxis(JKQTBasePlotter* parent, JKQTPCoordinateAxisRef otherAxisRef=JKQTPPrimaryAxis);
/** copydoc JKQTPCoordinateAxis::getParentPlotWidth() */
virtual double getParentPlotWidth() const override;
/** copydoc JKQTPCoordinateAxis::getParentPlotOffset() */
virtual double getParentPlotOffset() const override;
/** copydoc JKQTPCoordinateAxis::getParentOtheraxisWidth() */
virtual double getParentOtheraxisWidth() const override;
/** copydoc JKQTPCoordinateAxis::getParentOtheraxisInverted() */
virtual bool getParentOtheraxisInverted() const override;
/** copydoc JKQTPCoordinateAxis::getParentOtheraxisOffset() */
virtual double getParentOtheraxisOffset() const override;
/** copydoc JKQTPCoordinateAxis::parentOtherAxisX2P() */
virtual double parentOtherAxisX2P(double x) const override;
/** \copydoc otherAxisRef */
JKQTPCoordinateAxisRef getOtherAxisRef() const;
/** \brief returns the "other" axis, refernced by otherAxisRef */
const JKQTPCoordinateAxis* getOtherAxis() const;
protected:
/** \brief references the other axis fromm the JKQTPBasePLotter to use as "other" axis */
JKQTPCoordinateAxisRef otherAxisRef;
};
@ -944,7 +1006,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPVerticalAxis: public JKQTPCoordinateAxis {
If it is paired with another axis, the parameters of that axis have to be given explizitly in the constructor or with setters.
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPVerticalIndependentAxis: public JKQTPVerticalAxis {
class JKQTPLOTTER_LIB_EXPORT JKQTPVerticalIndependentAxis: public JKQTPVerticalAxisBase {
Q_OBJECT
protected:
public:
@ -990,20 +1052,33 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPVerticalIndependentAxis: public JKQTPVerticalA
/*! \brief implements a horizontal axis, based on JKQTPCoordinateAxis (for most of documentation: see JKQTPCoordinateAxis).
/*! \brief base class for horizontal axes, based on JKQTPCoordinateAxis (for most of documentation: see JKQTPCoordinateAxis).
\ingroup jkqtpbaseplotter_elements
The positioning of the different axis elements depends on the psition of the "other" axis (here y-axis),
The positioning of the different axis elements depends on the psition of the "other" axis (i.e. a vertical/y-axis),
i.e. the corresponding vertical axis:
\image html JKQTPHorizontalAxisPositioning.png
But this "other>" axis is not defined here, but has to be defined in derived classes by immplementing the corresponding
pure virtual functions:
- getParentPlotWidth()
- getParentPlotOffset()
- getParentOtheraxisWidth()
- getParentOtheraxisInverted()
- getParentOtheraxisOffset()
- parentOtherAxisX2P()
.
\see JKQTPVerticalAxisBase
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPHorizontalAxis: public JKQTPCoordinateAxis {
class JKQTPLOTTER_LIB_EXPORT JKQTPHorizontalAxisBase: public JKQTPCoordinateAxis {
Q_OBJECT
protected:
public:
/** \brief class constructor */
JKQTPHorizontalAxis(JKQTBasePlotter* parent);
JKQTPHorizontalAxisBase(JKQTBasePlotter* parent);
/** \brief returns the size of the bottom axis in pixels */
virtual QSizeF getSize1(JKQTPEnhancedPainter& painter) override;
@ -1012,25 +1087,12 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPHorizontalAxis: public JKQTPCoordinateAxis {
virtual QSizeF getSize2(JKQTPEnhancedPainter& painter) override;
/** copydoc JKQTPCoordinateAxis::drawAxes() */
virtual void drawAxes(JKQTPEnhancedPainter& painter) override;
virtual void drawAxes(JKQTPEnhancedPainter& painter, int move1=0, int move2=0) override;
/** copydoc JKQTPCoordinateAxis::drawGrids() */
virtual void drawGrids(JKQTPEnhancedPainter& painter) override;
/** copydoc JKQTPCoordinateAxis::getParentPlotWidth() */
virtual double getParentPlotWidth() const override;
/** copydoc JKQTPCoordinateAxis::getParentPlotOffset() */
virtual double getParentPlotOffset() const override;
/** copydoc JKQTPCoordinateAxis::getParentOtheraxisWidth() */
virtual double getParentOtheraxisWidth() const override;
/** copydoc JKQTPCoordinateAxis::getParentOtheraxisInverted() */
virtual bool getParentOtheraxisInverted() const override;
/** copydoc JKQTPCoordinateAxis::getParentOtheraxisOffset() */
virtual double getParentOtheraxisOffset() const override;
/** copydoc JKQTPCoordinateAxis::parentOtherAxisX2P() */
virtual double parentOtherAxisX2P(double x) const override;
protected:
/** copydoc JKQTPCoordinateAxis::getSize0() */
virtual std::pair<QSizeF, QSizeF> getSize0(JKQTPEnhancedPainter& painter) override;
@ -1068,6 +1130,45 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPHorizontalAxis: public JKQTPCoordinateAxis {
};
/*! \brief implements a horizontal axis, based on JKQTPCoordinateAxis (for most of documentation: see JKQTPCoordinateAxis).
\ingroup jkqtpbaseplotter_elements
The positioning of the different axis elements depends on the psition of the "other" axis (here y-axis),
i.e. the corresponding vertical axis:
\image html JKQTPHorizontalAxisPositioning.png
*/
class JKQTPLOTTER_LIB_EXPORT JKQTPHorizontalAxis: public JKQTPHorizontalAxisBase {
Q_OBJECT
protected:
public:
/** \brief class constructor */
JKQTPHorizontalAxis(JKQTBasePlotter* parent, JKQTPCoordinateAxisRef otherAxisRef_=JKQTPPrimaryAxis);
/** copydoc JKQTPCoordinateAxis::getParentPlotWidth() */
virtual double getParentPlotWidth() const override;
/** copydoc JKQTPCoordinateAxis::getParentPlotOffset() */
virtual double getParentPlotOffset() const override;
/** copydoc JKQTPCoordinateAxis::getParentOtheraxisWidth() */
virtual double getParentOtheraxisWidth() const override;
/** copydoc JKQTPCoordinateAxis::getParentOtheraxisInverted() */
virtual bool getParentOtheraxisInverted() const override;
/** copydoc JKQTPCoordinateAxis::getParentOtheraxisOffset() */
virtual double getParentOtheraxisOffset() const override;
/** copydoc JKQTPCoordinateAxis::parentOtherAxisX2P() */
virtual double parentOtherAxisX2P(double x) const override;
/** \copydoc otherAxisRef */
JKQTPCoordinateAxisRef getOtherAxisRef() const;
/** \brief returns the "other" axis, refernced by otherAxisRef */
const JKQTPCoordinateAxis* getOtherAxis() const;
protected:
/** \brief references the other axis fromm the JKQTPBasePLotter to use as "other" axis */
JKQTPCoordinateAxisRef otherAxisRef;
};
/*! \brief implements a position-indipendent horizontal axis, based on JKQTPCoordinateAxis (for most of documentation: see JKQTPCoordinateAxis).
\ingroup jkqtpbaseplotter_elements

View File

@ -34,7 +34,7 @@
#define SmallestGreaterZeroCompare_xvsgz() if ((xvsgz>10.0*DBL_MIN)&&((smallestGreaterZero<10.0*DBL_MIN) || (xvsgz<smallestGreaterZero))) smallestGreaterZero=xvsgz;
JKQTPPlotElement::JKQTPPlotElement(JKQTBasePlotter* parent):
QObject(parent)
QObject(parent), xAxisRef(JKQTPPrimaryAxis), yAxisRef(JKQTPPrimaryAxis)
{
title="";
visible=true;
@ -225,18 +225,18 @@ double JKQTPPlotElement::hitTest(const QPointF & posSystem, QPointF* closestSpot
}
double JKQTPPlotElement::transformX(double x) const {
return parent->getXAxis()->x2p(x);
return getXAxis()->x2p(x);
}
double JKQTPPlotElement::transformY(double y) const {
return parent->getYAxis()->x2p(y);
return getYAxis()->x2p(y);
}
QVector<double> JKQTPPlotElement::transformX(const QVector<double>& x) const {
QVector<double> res;
res.resize(x.size());
for (int i=0; i<x.size(); i++) {
res[i]=parent->getXAxis()->x2p(x[i]);
res[i]=getXAxis()->x2p(x[i]);
}
return res;
}
@ -245,18 +245,38 @@ QVector<double> JKQTPPlotElement::transformY(const QVector<double>& y) const {
QVector<double> res;
res.resize(y.size());
for (int i=0; i<y.size(); i++) {
res[i]=parent->getYAxis()->x2p(y[i]);
res[i]=getYAxis()->x2p(y[i]);
}
return res;
}
void JKQTPPlotElement::setXAxis(JKQTPCoordinateAxisRef ref)
{
xAxisRef=ref;
}
void JKQTPPlotElement::setYAxis(JKQTPCoordinateAxisRef ref)
{
yAxisRef=ref;
}
JKQTPCoordinateAxisRef JKQTPPlotElement::getXAxisRef() const
{
return xAxisRef;
}
JKQTPCoordinateAxisRef JKQTPPlotElement::getYAxisRef() const
{
return yAxisRef;
}
double JKQTPPlotElement::backtransformX(double x) const {
return parent->getXAxis()->p2x(x);
return getXAxis()->p2x(x);
}
double JKQTPPlotElement::backtransformY(double y) const {
return parent->getYAxis()->p2x(y);
return getYAxis()->p2x(y);
}

View File

@ -208,16 +208,16 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPPlotElement: public QObject {
/** \brief tool routine that transforms an x-coordinate (plot coordinate --> pixels) for this plot element */
/** \brief tool routine that transforms an x-coordinate (plot coordinate --> pixels) for this plot element, uses the axis referenced in xAxisRef */
double transformX(double x) const;
/** \brief tool routine that transforms a y-coordinate (plot coordinate --> pixels) for this plot element */
/** \brief tool routine that transforms a y-coordinate (plot coordinate --> pixels) for this plot element, uses the axis referenced in yAxisRef */
double transformY(double y) const;
/** \brief tool routine that backtransforms an x-coordinate (pixels --> plot coordinate) for this plot element */
/** \brief tool routine that backtransforms an x-coordinate (pixels --> plot coordinate) for this plot element, uses the axis referenced in xAxisRef */
double backtransformX(double x) const;
/** \brief tool routine that backtransforms a y-coordinate (pixels --> plot coordinate) for this plot element */
/** \brief tool routine that backtransforms a y-coordinate (pixels --> plot coordinate) for this plot element, uses the axis referenced in yAxisRef */
double backtransformY(double y) const;
@ -254,6 +254,31 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPPlotElement: public QObject {
/** \brief transform all y-coordinates in a vector \a x */
QVector<double> transformY(const QVector<double>& x) const;
/** \copydoc xAxisRef */
void setXAxis(JKQTPCoordinateAxisRef ref);
/** \copydoc xAxisRef */
JKQTPCoordinateAxisRef getXAxisRef() const;
/** \copydoc yAxisRef */
void setYAxis(JKQTPCoordinateAxisRef ref);
/** \copydoc yAxisRef */
JKQTPCoordinateAxisRef getYAxisRef() const;
/** \brief returns the actual x-Axis-object from the parent plotter, referenced in xAxisRef */
/** \brief returns the actual x-Axis-object from the parent plotter, referenced in xAxisRef */
inline const JKQTPCoordinateAxis* getXAxis() const {
return parent->getXAxis(xAxisRef);
}
/** \brief returns the actual y-Axis-object from the parent plotter, referenced in yAxisRef */
inline const JKQTPCoordinateAxis* getYAxis() const {
return parent->getYAxis(yAxisRef);
}
/** \brief set the coordinate axes to use for this plot element
*
* \see xAxisRef, yAxisRef, transformX(), transformY()
*/
void setAxes(JKQTPCoordinateAxisRef ref);
Q_PROPERTY(JKQTPCoordinateAxisRef xAxisRef READ getXAxisRef WRITE setXAxis)
Q_PROPERTY(JKQTPCoordinateAxisRef yAxisRef READ getYAxisRef WRITE setYAxis)
protected:
@ -356,6 +381,11 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPPlotElement: public QObject {
bool highlighted;
/** \brief internal storage for the used parent plot style */
int parentPlotStyle;
/** \brief indicates which coordinate axis to use for coordinate transforms in x-direction */
JKQTPCoordinateAxisRef xAxisRef;
/** \brief indicates which coordinate axis to use for coordinate transforms in y-direction */
JKQTPCoordinateAxisRef yAxisRef;
/** \brief dataset with graph-points and associated data fro the function hitTest()

View File

@ -272,10 +272,10 @@ void JKQTPGraphErrorStyleMixin::intPlotXYErrorIndicators(JKQTPEnhancedPainter& p
if (!visX&&!visY) return;
//std::cout<<" JKQTPGraphErrors::intPlotXYErrorIndicators(p, "<<parent<<", "<<xColumn<<", "<<yColumn<<", "<<xErrorColumn<<", "<<yErrorColumn<<", ...)\n";
const double xmin=parentGraph->transformX(parent->getXAxis()->getMin());
const double xmax=parentGraph->transformX(parent->getXAxis()->getMax());
const double ymin=parentGraph->transformY(parent->getYAxis()->getMin());
const double ymax=parentGraph->transformY(parent->getYAxis()->getMax());
const double xmin=parentGraph->transformX(parentGraph->getXAxis()->getMin());
const double xmax=parentGraph->transformX(parentGraph->getXAxis()->getMax());
const double ymin=parentGraph->transformY(parentGraph->getYAxis()->getMin());
const double ymax=parentGraph->transformY(parentGraph->getYAxis()->getMax());
const QMarginsF clipMargins(50,50,50,50);
const QRectF cliprect=QRectF(qMin(xmin,xmax),qMin(ymin,ymax),fabs(xmax-xmin),fabs(ymax-ymin))+clipMargins;

View File

@ -796,7 +796,7 @@ void JKQTPlotter::mouseMoveEvent ( QMouseEvent * event ) {
} else {
zoomRect.translate(mouseDragRectXStartPixel-mouseDragRectXEndPixel, mouseDragRectYStartPixel-mouseDragRectYEndPixel);
}
setXY(plotter->p2x(zoomRect.left()), plotter->p2x(zoomRect.right()), plotter->p2y(zoomRect.bottom()), plotter->p2y(zoomRect.top()));
setXY(plotter->p2x(zoomRect.left()), plotter->p2x(zoomRect.right()), plotter->p2y(zoomRect.bottom()), plotter->p2y(zoomRect.top()), true);
}
} else {
@ -900,7 +900,7 @@ void JKQTPlotter::mouseReleaseEvent ( QMouseEvent * event ){
plotter->correctXYRangeForAspectRatio(xmin,xmax,ymin,ymax);
emit zoomChangedLocally(xmin, xmax, ymin, ymax, this);
plotter->setXY(xmin, xmax, ymin, ymax);
plotter->setXY(xmin, xmax, ymin, ymax, true);
} else if (currentMouseDragAction.mode==jkqtpmdaPanPlotOnRelease) {
QRectF zoomRect= QRectF(QPointF(plotter->x2p(getXAxis()->getMin()),plotter->y2p(getYAxis()->getMax())), QPointF(plotter->x2p(getXAxis()->getMax()),plotter->y2p(getYAxis()->getMin())));
if ( (mouseLastClickX/magnification<plotter->getInternalPlotBorderLeft()) || (mouseLastClickX/magnification>plotter->getPlotWidth()+plotter->getInternalPlotBorderLeft()) ) {
@ -910,7 +910,7 @@ void JKQTPlotter::mouseReleaseEvent ( QMouseEvent * event ){
} else {
zoomRect.translate(mouseDragRectXStartPixel-mouseDragRectXEndPixel, mouseDragRectYStartPixel-mouseDragRectYEndPixel);
}
setXY(plotter->p2x(zoomRect.left()), plotter->p2x(zoomRect.right()), plotter->p2y(zoomRect.bottom()), plotter->p2y(zoomRect.top()));
setXY(plotter->p2x(zoomRect.left()), plotter->p2x(zoomRect.right()), plotter->p2y(zoomRect.bottom()), plotter->p2y(zoomRect.top()), true);
} else if (currentMouseDragAction.mode==jkqtpmdaDrawRectangleForEvent) {
emit userRectangleFinished(x1, y1, x2-x1, y2-y1, event->modifiers());
} else if (currentMouseDragAction.mode==jkqtpmdaDrawCircleForEvent) {
@ -962,7 +962,7 @@ void JKQTPlotter::mouseDoubleClickEvent ( QMouseEvent * event ){
ymin=getYMin();
ymax=getYMax();
}
plotter->setXY(xmin, xmax, ymin, ymax);
plotter->setXY(xmin, xmax, ymin, ymax, true);
update();
} else if (itAction.value()==JKQTPMouseDoubleClickActions::jkqtpdcaClickMovesViewport) {
QRectF zoomRect= QRectF(QPointF(plotter->x2p(getXAxis()->getMin()),plotter->y2p(getYAxis()->getMax())), QPointF(plotter->x2p(getXAxis()->getMax()),plotter->y2p(getYAxis()->getMin())));
@ -973,7 +973,7 @@ void JKQTPlotter::mouseDoubleClickEvent ( QMouseEvent * event ){
} else {
zoomRect.moveCenter(QPointF(event->pos().x(), event->pos().y()));
}
setXY(plotter->p2x(zoomRect.left()), plotter->p2x(zoomRect.right()), plotter->p2y(zoomRect.bottom()), plotter->p2y(zoomRect.top()));
setXY(plotter->p2x(zoomRect.left()), plotter->p2x(zoomRect.right()), plotter->p2y(zoomRect.bottom()), plotter->p2y(zoomRect.top()), true);
}
}
@ -1037,7 +1037,7 @@ void JKQTPlotter::wheelEvent ( QWheelEvent * event ) {
ymin=getYMin();
ymax=getYMax();
}
plotter->setXY(xmin, xmax, ymin, ymax);
plotter->setXY(xmin, xmax, ymin, ymax, true);
} else if (itAction.value()==JKQTPMouseWheelActions::jkqtpmwaPanByWheel) {
//} else if (act==JKQTPMouseWheelActions::jkqtpmwaPanByWheel) {
//qDebug()<<"wheelEvent("<<event->modifiers()<<"):PanByWheel";
@ -1059,7 +1059,7 @@ void JKQTPlotter::wheelEvent ( QWheelEvent * event ) {
} else {
zoomRect.translate(d.x(), d.y());
}
setXY(plotter->p2x(zoomRect.left()), plotter->p2x(zoomRect.right()), plotter->p2y(zoomRect.bottom()), plotter->p2y(zoomRect.top()));
setXY(plotter->p2x(zoomRect.left()), plotter->p2x(zoomRect.right()), plotter->p2y(zoomRect.bottom()), plotter->p2y(zoomRect.top()), true);
}
}

View File

@ -697,13 +697,13 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPlotter: public QWidget {
int getMouseLastClickY() const;
/** \brief returns the coordinate axis object for the x-axis \see JKQTBasePlotter::getXAxis() */
inline JKQTPHorizontalAxis* getXAxis() { return plotter->getXAxis(); }
inline JKQTPHorizontalAxisBase* getXAxis(JKQTPCoordinateAxisRef axis=JKQTPPrimaryAxis) { return plotter->getXAxis(axis); }
/** \brief returns the coordinate axis object for the y-axis \see JKQTBasePlotter::getYAxis() */
inline JKQTPVerticalAxis* getYAxis() { return plotter->getYAxis(); }
inline JKQTPVerticalAxisBase* getYAxis(JKQTPCoordinateAxisRef axis=JKQTPPrimaryAxis) { return plotter->getYAxis(axis); }
/** \brief returns the coordinate axis object for the x-axis as a const pointer \see JKQTBasePlotter::getXAxis() */
inline const JKQTPHorizontalAxis* getXAxis() const { return plotter->getXAxis(); }
inline const JKQTPHorizontalAxisBase* getXAxis(JKQTPCoordinateAxisRef axis=JKQTPPrimaryAxis) const { return plotter->getXAxis(axis); }
/** \brief returns the coordinate axis object for the y-axis as a const pointer \see JKQTBasePlotter::getYAxis() */
inline const JKQTPVerticalAxis* getYAxis() const { return plotter->getYAxis(); }
inline const JKQTPVerticalAxisBase* getYAxis(JKQTPCoordinateAxisRef axis=JKQTPPrimaryAxis) const { return plotter->getYAxis(axis); }
/** \brief returns the \a i -th graph (of type JKQTPPlotElement) in this plotter instance \see JKQTBasePlotter::getGraph() */
inline JKQTPPlotElement* getGraph(size_t i) { return plotter->getGraph(i); }
@ -1185,6 +1185,10 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPlotter: public QWidget {
* \param xmaxx absolute maximum of x-axis
* \param yminn absolute minimum of y-axis
* \param ymaxx absolute maximum of y-axis
* \param affectsSecondaryAxes if \c true, the secondary axes are affectedtoo, by using a relative zooming scheme,
* i.e. if a major axis range shrinks by 50%, also the secondary ranges shrink by 50%
* [default: \c false]
*
*
* \note You cannot expand the ranges outside the absolute ranges set e.g. by setAbsoluteXY()!
* Also the range will be limited to possible values (e.g. to positive values if you use
@ -1195,7 +1199,7 @@ class JKQTPLOTTER_LIB_EXPORT JKQTPlotter: public QWidget {
*
* \see setX(), setX(), zoomToFit(), setAbsoluteXY(), JKQTBasePlotter::setXY()
*/
inline void setXY(double xminn, double xmaxx, double yminn, double ymaxx) { plotter->setXY(xminn, xmaxx, yminn, ymaxx); }
inline void setXY(double xminn, double xmaxx, double yminn, double ymaxx, bool affectsSecondaryAxes=false) { plotter->setXY(xminn, xmaxx, yminn, ymaxx, affectsSecondaryAxes); }
signals:
/** \brief emitted whenever the mouse moves
*

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 KiB

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

BIN
screenshots/second_axis.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Some files were not shown because too many files have changed in this diff Show More