The old profile code didn't show the 0m label, because that
was cut off. This was lost when redoing the axis code.
Reimplement this. The code is very ugly: it recognizes the
depth axis by the fact that is the only "inverted" axis.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The old get_maxdepth() function in profile.c was accounting for
two things:
- the partial pressure graphs
- rounding to sane value
Both are now taken care of by the profile itself. This leads to
excessive max-depths. Remove the code from profile.c.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This is a shouldn't happen situation, because we always
fake a profile. Let's handle it gracefully anyway.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When hovering over the chart after the chart was cleared,
there were artifacts owing to the stale profile data.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
free_plot_info_data() frees the sample and pressure arrays
and accordingly sets the corresponding pointers to NULL.
However, it doesn't clear the element-count and thus leaves
the structure in an inconsistent state.
Clear the whole structure with memset(). I am not a fan of
doing so, but there are existing memset() calls in the
same source file, so let's keep it like that for consistency.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
All data access is now directly via the plot_info structure
owned by the ProfileScene itself.
Also removes DivePercentageItem::hColumn, which was an
artifact from the DivePlotDataModel.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There were two plot_infos of the same dive: one owned by
ProfileScene and one owned by DivePlotDataModel. The latter
was (or at least should have been) a copy of the former.
Simply always access the plot-info which is owned by
ProfileScene anyway. That seems much less brittle. Why
risk some desyncing?
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The profile was using a Qt-model to access its data. This means
routing everything through Qt's QVariants and lead to verbose
code such as
double prev_y = dataModel.index(i-1, vDataColumn).data().toReal();
Instead of storing a data-column and do access via a template,
simply store accessor functions. The code from above now reads as
double prev_y = accessor(data[i-1]);
This should also be distinctly faster for the ns-optimizers among
us.
Only one case was somewhat nasty to convert: The accessors for
the 16 tissues are now generated via a recursive template. Thanks
to C++17's constexpr if, such a template is pleasantly easy
to follow, though.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The intention was to use QObject slots for animations.
However, these animations never materialized. Should we
ever want to animate them, we might use the animation
object that is already used for cartesian axes.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This indicated the data of the horizontal axis. It was (obviously)
always the time axis. Remove.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There is only one user of this - let's remove complex
interdependencies.
Note: there seem to be two independent plot_infos: in the
ProfileScene and in the DivePlotDataModel. To avoid behavioral
change, this keeps using the DivePlotDataModel's version.
In any case, this has to be unified.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There was logic to disable animation when switching from "no dive"
to "show dive". However, that has bit-rotted away: the plotted
dive was set before plotting the dive and therefore the check
for "change from empty" did not work. Introduce an explicit
empty flag instead.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The old animation was weird: it would reuse the labels
based on the index, not on the value. Thus, with the
new scaling code, sometimes there was no animation at all,
if the value, but not the position changed.
Consider the values instead and let labels appear/disappear.
This makes things slightly more complex.
While changing this code, create our own animation-class.
Thus, we can avoid having the dive axes being QObjects.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This function was just needlessly complicated. For one, it
considered the position of the line, but that is never changed
since redoing the positioning code. Moreover, it does in
lots of lines what is a very idiomatic operation: a
one-dimensional affine transformation. Let's shorten the
actual calculation to two lines.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This label is put to the right of the corresponding curve,
so it should arguably be centered vertically. At least to
me this looks more natural.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The time axis might need some space and the average depth item
puts a formatted depth at to right of the profile. Consider
these when calculating the right border.
Since I found no way to turn of the average depth, this creates
a permanent border, which might or might not be a good thing.
Contains some refactoring of the label-size functions provided
by DiveTextItem.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The usual increments (leading 1, 2, 4 or 5) don't look
natural for the time axis. Therefore special case the
time axis and to increments in 1, 2, 3, 4, 5, 6 or 12
parts of a minute or second.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This function was used to check wether a screen-point
is located on the profile. Bizzarely, this was done by
transforming into local coordinates and checking
min/max value. Simply check the screen coordinates
directly. Moreover, make the function return whether
the point is inside the region, not outside the region,
to make logic more straight forward.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Hide thumbnails, which are out of the shown range. This became
necessary when converting to absolute scaling.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
When changing from relative to absolute scaling of the char
elements, positioning of the picture thumbnails was broken.
To emulate the old behavior, add a function to DiveCartesianAxis,
that allows positioning with respect to the axis on the screen.
To simplify tuning of the poctuire positions, name a few
constants explicitly.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The picture thumbnails were recreated on every profile render,
even when zooming / scrolling. In that case, we should only change
the positions.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This is a potentially expensive operation (e.g. interpolation of
pressure values), so don't recalculate the plot data for every
redraw.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Positional bool parameters to control the rendering of the plot
have been a pain. We are down to one parameter (instant),
but more will be readded, so let's use the opportunity to
control rendering with a flags parameter.
Sadly, C++ has no reasonable way of defining flags that I know
of. Either the identifiers leak (enum), or can't be trivially
ORed (enum class) or are weakly typed (int). Let's just use an
integer for now.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
These were the minimum and maximum of a 9-min window.
The profile now uses an adaptive peak-search, so this is not
used anymore.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The old code used the maximum / minimum values of nine-minute
intervals to indicate maximum / minimum depths. This does not
work well when zooming, since the labels will get sparse.
Instead implement a primitive peak finding algorithm, that
searches for the deepest peak in the whole plot and then
repeats the procedure for the right and left sides, leaving
out a certain distance to the origninal peak. This is repeated
until there are no more peaks found.
Only peaks of a certain prominence are considered, which
conveniently gives us the valleys.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Use variable intervals for printing temperature and heart
beat labels. Obviously, so that the labels don't become
sparse on zooming, but also to make them not too crowded
on mobile / small screens.
This doesn't work for depth labels, because these labels
use data provided from the profile.c core that doesn't
know about the size of the chart.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
There was a bunch of conditionally compiled code on mobile
that had special hiding/unhiding rules.
Try to unify that with the desktop code by introducing a
"simplified" flag. This certainly breaks and will have to
be finetuned. In particular, I can't test CCR dives, which
are treated specially on mobile.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Avoid "overshooting" of the profile items by linearly clipping
the first and last segment to the boundaries of the time-axis.
Sadly, quite a lot of code, because every profile item is
slightly different.
In particular the pressure-segment handling was rewritten.
It now stores the begin and end of each segment to draw
the appropriate text items.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Due to bit-rot the gas pressure and gas type were displayed on top
of each other. I don't understand the meaning of the old code
[log10(log10(axisRange))] (!). Therefore let's just add the height
of the label to separate the labels.
Probably needs some fine-tuning.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This was a rather trivial change: simply pass in the first
and the last second to the plot function.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
That variable was only used in a single function and
always reset at the beginning of the function. No point
in being a member variable.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Only plot the zoomed range. Currently this passes the sample
before and after the range, so it generally "overshoots" by
one sample in each direction. The plan is to do clipping
on the first and last polygon segment later on.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
We were using the QGraphicsScene machinery to zoom into the
plot. This not only zoomed into the dive, but into the whole
thing. In general, one couldn't see the axes anymore.
Instead, adjust the range of the time-axis according to the
zoom-level and position.
Of course, the code isn't adapted to that and the result
is comical. The chart features will have to be fixed
one-by-one. Oh joy.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Currently, the zoomLevel is reset for every plotDive() call,
because the zooming is done via the QGraphicsScene. However,
this does not work well (e.g. axes are likewise zoomed) and
in the future a change of the zoom level will cause a replot.
Thus, remove the zoom-reset in plotDive() and do it explicitly
when switching dives.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This is a constant, no point in keeping it as a member variable.
Contains removal of a pointless #ifdef (guarding against mobile,
but code not compiled on mobile), a typo-fix in a comment and
replacement of Qt's idiosyncratic qreal by double.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
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>
There were virtual functions to calculate the label colors
based on the value of the label. However, these functions
only returned constant values. Therefore, just set these
in the constructors.
Thuse, a few virtual functions and derived classes can be
removed.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
This was only used in the constructor to create the pen for
the grid lines. Not need to keep it around.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The visibility of axis text / lines is never changed, so set
in axis constructor.
Moreover, instead of rendering the lines/text and then setting
them invisible, do not render them if invisible.
The whole thing appears superfluous, since the proper way to
not show lines/text is to just not call updateTicks on the
axis. But in the future we might want to have axes with text
but no lines, so keep for now.
Since this means breaking out the text / line rendering
into their own function, we might rename some variables to
make them (at least somewhat) more clear.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Rounding the axes dimensions to "nice" number may have been a
good idea, but for the time-axis it feels weird.
Therefore revert the time axis to the previous behavior:
range is set according to the data. To differentiate between
time an other axes, use the position: the time axis is the
only axis at the bottom. Yes, that's ugly but pragmatic.
Since we have that flag also use it for the special casing
of the text-display. Spares us one virtual function dispatch.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The integers were simply rounded to integers, which might give
ugly intervals (e.g. multiples of 3). Use the code of the
statistics tab, with one modification: take care not to
use intervals below the given precision. The statistics work
differently: there, the precision is adjusted according to
the interval size, not the other way around.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
The ticks were recalculated twice per plotDive() call:
1) When updating the position of the axes in updateChangeLine()
2) After setting the bounds in plotDive() via setBounds()
Remove the first instance. updateChangeLine() is called in
only one place [from plotDive()] and therefore, the recalculation
is always redundant. Moreover, rename the function to setPosition(),
since it doesn't do any animation at all.
Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>