mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
profile: unify formating of axis labels
Instead of a host of virtual functions, let the base class (DiveCartesianAxis) do the formatting of the axis labels. To do so, it needs to know how to convert the internal representation (e.g. mm) into the displayed value (e.g. feet). Moreover, this transformation has to be adapted when changing the locale-setting, therefore do it for every plot() call. The transformation itself cannot be a simple linear translation, because we have non-absolute display units, namely °C and °F. Thankfully affine transformations are enough though. Only one custom formatter remains: the time axis. It might be a good idea to remove the virtual function and do this via a flag. This is all done not so much for code simplification, but because for a general layout of the axis labels, the axis has to understand the values of the labels and not only handle them as opaque texts. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
parent
0e9eee0a7f
commit
177df72d33
3 changed files with 63 additions and 18 deletions
|
@ -51,7 +51,7 @@ ProfileScene::ProfileScene(double dpr, bool printMode, bool isGrayscale) :
|
|||
gasYAxis(new PartialGasPressureAxis(*dataModel, DiveCartesianAxis::Position::Right, 1, 2, TIME_GRID, dpr, 0.7, printMode, isGrayscale, *this)),
|
||||
temperatureAxis(new TemperatureAxis(DiveCartesianAxis::Position::Right, 3, 0, TIME_GRID, dpr, 1.0, printMode, isGrayscale, *this)),
|
||||
timeAxis(new TimeAxis(DiveCartesianAxis::Position::Bottom, 2, 2, TIME_GRID, dpr, 1.0, printMode, isGrayscale, *this)),
|
||||
cylinderPressureAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Right, 2, 2, TIME_GRID, dpr, 1.0, printMode, isGrayscale, *this)),
|
||||
cylinderPressureAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Right, 4, 0, TIME_GRID, dpr, 1.0, printMode, isGrayscale, *this)),
|
||||
heartBeatAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Left, 3, 0, HR_AXIS, dpr, 0.7, printMode, isGrayscale, *this)),
|
||||
percentageAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Right, 2, 0, TIME_GRID, dpr, 0.7, printMode, isGrayscale, *this)),
|
||||
diveProfileItem(createItem<DiveProfileItem>(*profileYAxis, DivePlotDataModel::DEPTH, 0, dpr)),
|
||||
|
@ -115,6 +115,11 @@ ProfileScene::ProfileScene(double dpr, bool printMode, bool isGrayscale) :
|
|||
gasYAxis->setZValue(timeAxis->zValue() + 1);
|
||||
tankItem->setZValue(100);
|
||||
|
||||
// These axes are not locale-dependent. Set their scale factor once here.
|
||||
timeAxis->setTransform(60.0);
|
||||
heartBeatAxis->setTransform(1.0);
|
||||
gasYAxis->setTransform(1.0); // Non-metric countries likewise use bar (disguised as "percentage") for partial pressure.
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
DiveCalculatedTissue *tissueItem = createItem<DiveCalculatedTissue>(*profileYAxis, DivePlotDataModel::TISSUE_1 + i, i + 1, dpr);
|
||||
allTissues.append(tissueItem);
|
||||
|
@ -199,6 +204,19 @@ void ProfileScene::resize(QSizeF size)
|
|||
setSceneRect(QRectF(QPointF(), size));
|
||||
}
|
||||
|
||||
// Helper templates to determine slope and intersect of a linear function.
|
||||
// The function arguments are supposed to be integral types.
|
||||
template<typename Func>
|
||||
static auto intercept(Func f)
|
||||
{
|
||||
return f(0);
|
||||
}
|
||||
template<typename Func>
|
||||
static auto slope(Func f)
|
||||
{
|
||||
return f(1) - f(0);
|
||||
}
|
||||
|
||||
// Helper structure for laying out secondary plots.
|
||||
struct VerticalAxisLayout {
|
||||
DiveCartesianAxis *axis;
|
||||
|
@ -286,6 +304,16 @@ void ProfileScene::updateAxes(bool instant, bool diveHasHeartBeat)
|
|||
|
||||
// The cylinders are displayed in the 24-80% region of the profile
|
||||
cylinderPressureAxis->animateChangeLine(QRectF(leftBorder, topBorder + 0.24 * height, width, 0.56 * height), animSpeed);
|
||||
|
||||
// Set scale factors depending on locale.
|
||||
// The conversion calls, such as mm_to_feet(), will be optimized away.
|
||||
profileYAxis->setTransform(prefs.units.length == units::METERS ? 0.001 : slope(mm_to_feet));
|
||||
cylinderPressureAxis->setTransform(prefs.units.pressure == units::BAR ? 0.001 : slope(mbar_to_PSI));
|
||||
// Temperature is special: this is not a linear transformation, but requires a shift of origin.
|
||||
if (prefs.units.temperature == units::CELSIUS)
|
||||
temperatureAxis->setTransform(slope(mkelvin_to_C), intercept(mkelvin_to_C));
|
||||
else
|
||||
temperatureAxis->setTransform(slope(mkelvin_to_F), intercept(mkelvin_to_F));
|
||||
}
|
||||
|
||||
bool ProfileScene::isPointOutOfBoundaries(const QPointF &point) const
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue