profile: replace orientation by inverted flag

There were two somewhat redundant flags for the axes: the position
(left, right, bottom) and the orientation (up-down, left-right, etc).

Replace the latter by an inverted flag: if true, the axis is
up-down or right-left, i.e. the opposite of what one would expect
for a normal graph.

Set the flag in the constructor and remove the setOrientation()
function.

Sadly, the code is a bit complex, because screen coordinates are
top-to-bottom. Who thought that would be a good idea?

Note: this also fixes the placement of the ticks of the time
axis.

Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This commit is contained in:
Berthold Stoeger 2021-10-03 22:29:18 +02:00 committed by Dirk Hohndel
parent 3a79f3e78a
commit 2f9c0c04b5
3 changed files with 44 additions and 85 deletions

View file

@ -18,15 +18,15 @@ void DiveCartesianAxis::setBounds(double minimum, double maximum)
dataMax = max = maximum;
}
DiveCartesianAxis::DiveCartesianAxis(Position position, int integralDigits, int fractionalDigits, color_index_t gridColor,
DiveCartesianAxis::DiveCartesianAxis(Position position, bool inverted, int integralDigits, int fractionalDigits, color_index_t gridColor,
QColor textColor, bool textVisible, bool linesVisible,
double dpr, double labelScale, bool printMode, bool isGrayscale, ProfileScene &scene) :
printMode(printMode),
position(position),
inverted(inverted),
fractionalDigits(fractionalDigits),
textColor(textColor),
scene(scene),
orientation(LeftToRight),
min(0),
max(0),
textVisibility(textVisible),
@ -73,12 +73,6 @@ DiveCartesianAxis::~DiveCartesianAxis()
{
}
void DiveCartesianAxis::setOrientation(Orientation o)
{
orientation = o;
changed = true;
}
void DiveCartesianAxis::setTransform(double a, double b)
{
transform.a = a;
@ -182,23 +176,21 @@ void DiveCartesianAxis::updateTicks(int animSpeed)
if (numTicks == 0)
return;
double internalToScreen = size / (max - min);
stepValue = position == Position::Bottom ?
intervalDisplay / transform.a : // special case for time axis.
numTicks > 1 ? (max - min) / (numTicks - 1) : 0;
double stepScreen = stepValue * size / (max - min);
double stepScreen = stepValue * internalToScreen;
// The ticks of the time axis don't necessarily start at the beginning.
double offsetScreen = position == Position::Bottom ?
(firstValue - min) * internalToScreen : 0.0;
// Move the remaining grid lines / labels to their correct positions
// regarding the possible new values for the axis
double firstPosScreen;
if (orientation == TopToBottom) {
firstPosScreen = m.y1();
} else if (orientation == BottomToTop) {
firstPosScreen = m.y2();
} else if (orientation == LeftToRight) {
firstPosScreen = m.x1();
} else /* if (orientation == RightToLeft) */ {
firstPosScreen = m.x2();
}
// regarding the possible new values for the axis.
double firstPosScreen = position == Position::Bottom ?
(inverted ? m.x2() - offsetScreen : m.x1() + offsetScreen) :
(inverted ? m.y1() + offsetScreen : m.y2() - offsetScreen);
if (textVisibility)
updateLabels(numTicks, firstPosScreen, firstValue, stepScreen, stepValue, animSpeed);
@ -210,10 +202,9 @@ void DiveCartesianAxis::updateTicks(int animSpeed)
void DiveCartesianAxis::updateLabels(int numTicks, double firstPosScreen, double firstValue, double stepScreen, double stepValue, int animSpeed)
{
for (int i = 0, count = labels.size(); i < count; i++, firstValue += stepValue) {
double childPos = (orientation == TopToBottom || orientation == LeftToRight) ?
double childPos = ((position == Position::Bottom) != inverted) ?
firstPosScreen + i * stepScreen :
firstPosScreen - i * stepScreen;
labels[i]->set(textForValue(firstValue), textColor);
switch (position) {
default:
@ -231,12 +222,9 @@ void DiveCartesianAxis::updateLabels(int numTicks, double firstPosScreen, double
// Add the rest of the needed labels.
for (int i = labels.size(); i < numTicks; i++, firstValue += stepValue) {
double childPos;
if (orientation == TopToBottom || orientation == LeftToRight) {
childPos = firstPosScreen + i * stepScreen;
} else {
childPos = firstPosScreen - i * stepScreen;
}
double childPos = ((position == Position::Bottom) != inverted) ?
firstPosScreen + i * stepScreen :
firstPosScreen - i * stepScreen;
int alignFlags = position == Position::Bottom ? Qt::AlignTop | Qt::AlignHCenter :
position == Position::Left ? Qt::AlignVCenter | Qt::AlignLeft:
Qt::AlignVCenter | Qt::AlignRight;
@ -265,9 +253,9 @@ void DiveCartesianAxis::updateLabels(int numTicks, double firstPosScreen, double
void DiveCartesianAxis::updateLines(int numTicks, double firstPosScreen, double stepScreen, int animSpeed)
{
for (int i = 0, count = lines.size(); i < count; i++) {
double childPos = (orientation == TopToBottom || orientation == LeftToRight) ?
firstPosScreen + i * stepScreen :
firstPosScreen - i * stepScreen;
double childPos = ((position == Position::Bottom) != inverted) ?
firstPosScreen + i * stepScreen :
firstPosScreen - i * stepScreen;
if (position == Position::Bottom) {
// Fix size in case the scene changed
@ -284,12 +272,9 @@ void DiveCartesianAxis::updateLines(int numTicks, double firstPosScreen, double
// Add the rest of the needed grid lines.
for (int i = lines.size(); i < numTicks; i++) {
double childPos;
if (orientation == TopToBottom || orientation == LeftToRight) {
childPos = firstPosScreen + i * stepScreen;
} else {
childPos = firstPosScreen - i * stepScreen;
}
double childPos = ((position == Position::Bottom) != inverted) ?
firstPosScreen + i * stepScreen :
firstPosScreen - i * stepScreen;
DiveLineItem *line = new DiveLineItem(this);
line->setPen(gridPen);
line->setZValue(0);
@ -349,18 +334,16 @@ QString DiveCartesianAxis::textForValue(double value) const
qreal DiveCartesianAxis::valueAt(const QPointF &p) const
{
double fraction;
QLineF m = line();
QPointF relativePosition = p;
relativePosition -= pos(); // normalize p based on the axis' offset on screen
if (orientation == LeftToRight || orientation == RightToLeft)
fraction = (relativePosition.x() - m.x1()) / (m.x2() - m.x1());
else
fraction = (relativePosition.y() - m.y1()) / (m.y2() - m.y1());
double fraction = position == Position::Bottom ?
(relativePosition.x() - m.x1()) / (m.x2() - m.x1()) :
(relativePosition.y() - m.y1()) / (m.y2() - m.y1());
if (orientation == RightToLeft || orientation == BottomToTop)
fraction = 1 - fraction;
if ((position == Position::Bottom) == inverted)
fraction = 1.0 - fraction;
return fraction * (max - min) + min;
}
@ -375,20 +358,18 @@ qreal DiveCartesianAxis::posAtValue(qreal value) const
double percent = IS_FP_SAME(min, max) ? 0.0 : (value - min) / size;
double realSize = orientation == LeftToRight || orientation == RightToLeft ?
m.x2() - m.x1() :
m.y2() - m.y1();
double realSize = position == Position::Bottom ?
m.x2() - m.x1() :
m.y2() - m.y1();
// Inverted axis, just invert the percentage.
if (orientation == RightToLeft || orientation == BottomToTop)
percent = 1 - percent;
if ((position == Position::Bottom) == inverted)
percent = 1.0 - percent;
double retValue = realSize * percent;
double adjusted =
orientation == LeftToRight ? retValue + m.x1() + p.x() :
orientation == RightToLeft ? retValue + m.x1() + p.x() :
orientation == TopToBottom ? retValue + m.y1() + p.y() :
/* entation == BottomToTop */ retValue + m.y1() + p.y();
double adjusted = position == Position::Bottom ?
retValue + m.x1() + p.x() :
retValue + m.y1() + p.y();
return adjusted;
}

View file

@ -23,23 +23,16 @@ class DiveCartesianAxis : public QObject, public QGraphicsLineItem {
private:
bool printMode;
public:
enum Orientation {
TopToBottom,
BottomToTop,
LeftToRight,
RightToLeft
};
enum class Position {
Left, Right, Bottom
};
DiveCartesianAxis(Position position, int integralDigits, int fractionalDigits, color_index_t gridColor,
DiveCartesianAxis(Position position, bool inverted, int integralDigits, int fractionalDigits, color_index_t gridColor,
QColor textColor, bool textVisible, bool linesVisible,
double dpr, double labelScale, bool printMode, bool isGrayscale, ProfileScene &scene);
~DiveCartesianAxis();
void setBounds(double min, double max);
void setTransform(double a, double b = 0.0);
void setOrientation(Orientation orientation);
double minimum() const;
double maximum() const;
std::pair<double, double> screenMinMax() const;
@ -54,13 +47,13 @@ public:
private:
Position position;
bool inverted; // Top-to-bottom or right-to-left axis.
int fractionalDigits;
QRectF rect; // Rectangle to fill with grid lines
QPen gridPen;
QColor textColor;
ProfileScene &scene;
QString textForValue(double value) const;
Orientation orientation;
QList<DiveTextItem *> labels;
QList<DiveLineItem *> lines;
double dataMin, dataMax;

View file

@ -47,19 +47,19 @@ ProfileScene::ProfileScene(double dpr, bool printMode, bool isGrayscale) :
maxtime(-1),
maxdepth(-1),
dataModel(new DivePlotDataModel(this)),
profileYAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Left, 3, 0, TIME_GRID, Qt::red, true, true,
profileYAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Left, true, 3, 0, TIME_GRID, Qt::red, true, true,
dpr, 1.0, printMode, isGrayscale, *this)),
gasYAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Right, 1, 2, TIME_GRID, Qt::black, true, true,
gasYAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Right, false, 1, 2, TIME_GRID, Qt::black, true, true,
dpr, 0.7, printMode, isGrayscale, *this)),
temperatureAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Right, 3, 0, TIME_GRID, Qt::black, false, false,
temperatureAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Right, false, 3, 0, TIME_GRID, Qt::black, false, false,
dpr, 1.0, printMode, isGrayscale, *this)),
timeAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Bottom, 2, 2, TIME_GRID, Qt::blue, true, true,
timeAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Bottom, false, 2, 2, TIME_GRID, Qt::blue, true, true,
dpr, 1.0, printMode, isGrayscale, *this)),
cylinderPressureAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Right, 4, 0, TIME_GRID, Qt::black, false, false,
cylinderPressureAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Right, false, 4, 0, TIME_GRID, Qt::black, false, false,
dpr, 1.0, printMode, isGrayscale, *this)),
heartBeatAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Left, 3, 0, HR_AXIS, Qt::black, true, true,
heartBeatAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Left, false, 3, 0, HR_AXIS, Qt::black, true, true,
dpr, 0.7, printMode, isGrayscale, *this)),
percentageAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Right, 2, 0, TIME_GRID, Qt::black, false, false,
percentageAxis(new DiveCartesianAxis(DiveCartesianAxis::Position::Right, false, 2, 0, TIME_GRID, Qt::black, false, false,
dpr, 0.7, printMode, isGrayscale, *this)),
diveProfileItem(createItem<DiveProfileItem>(*profileYAxis, DivePlotDataModel::DEPTH, 0, dpr)),
temperatureItem(createItem<DiveTemperatureItem>(*temperatureAxis, DivePlotDataModel::TEMPERATURE, 1, dpr)),
@ -87,21 +87,6 @@ ProfileScene::ProfileScene(double dpr, bool printMode, bool isGrayscale) :
setSceneRect(0, 0, 100, 100);
setItemIndexMethod(QGraphicsScene::NoIndex);
// Initialize axes. Perhaps part of this should be moved down to the axes code?
profileYAxis->setOrientation(DiveCartesianAxis::TopToBottom);
gasYAxis->setOrientation(DiveCartesianAxis::BottomToTop);
#ifndef SUBSURFACE_MOBILE
heartBeatAxis->setOrientation(DiveCartesianAxis::BottomToTop);
percentageAxis->setOrientation(DiveCartesianAxis::BottomToTop);
#endif
temperatureAxis->setOrientation(DiveCartesianAxis::BottomToTop);
cylinderPressureAxis->setOrientation(DiveCartesianAxis::BottomToTop);
gasYAxis->setZValue(timeAxis->zValue() + 1);
tankItem->setZValue(100);