From efc89b9d9cafc3d9fbe58bdfa3a0bff26a51f8c8 Mon Sep 17 00:00:00 2001 From: Berthold Stoeger Date: Sat, 16 Oct 2021 20:43:19 +0200 Subject: [PATCH] profile: use dynamic distances between labels on chart 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 --- profile-widget/divecartesianaxis.cpp | 10 ++++++++++ profile-widget/divecartesianaxis.h | 3 +++ profile-widget/diveprofileitem.cpp | 18 ++++++++++-------- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/profile-widget/divecartesianaxis.cpp b/profile-widget/divecartesianaxis.cpp index 7df960fdc..82eb03c1c 100644 --- a/profile-widget/divecartesianaxis.cpp +++ b/profile-widget/divecartesianaxis.cpp @@ -99,6 +99,16 @@ double DiveCartesianAxis::height() const return labelHeight + labelSpaceVertical * dpr; } +int DiveCartesianAxis::getMinLabelDistance(const DiveCartesianAxis &timeAxis) const +{ + // For the plot not being to crowded we want at least two + // labels to fit between each pair of displayed labels. + // May need some optimization. + QLineF m = timeAxis.line(); + double interval = labelWidth * 3.0 * (timeAxis.maximum() - timeAxis.minimum()) / (m.x2() - m.x1()); + return int(ceil(interval)); +} + static double sensibleInterval(double inc, int decimals) { // Use full decimal increments diff --git a/profile-widget/divecartesianaxis.h b/profile-widget/divecartesianaxis.h index fd11b835f..b4297c559 100644 --- a/profile-widget/divecartesianaxis.h +++ b/profile-widget/divecartesianaxis.h @@ -45,6 +45,9 @@ public: double width() const; // only for vertical axes double height() const; // only for horizontal axes + // The minimum space between two labels on the plot in seconds + int getMinLabelDistance(const DiveCartesianAxis &timeAxis) const; + private: Position position; bool inverted; // Top-to-bottom or right-to-left axis. diff --git a/profile-widget/diveprofileitem.cpp b/profile-widget/diveprofileitem.cpp index 767ca8fb1..65e3b6001 100644 --- a/profile-widget/diveprofileitem.cpp +++ b/profile-widget/diveprofileitem.cpp @@ -224,6 +224,7 @@ void DiveHeartrateItem::replot(const dive *, int fromIn, int toIn, bool) texts.clear(); // Ignore empty values. a heart rate of 0 would be a bad sign. QPolygonF poly; + int interval = vAxis.getMinLabelDistance(hAxis); for (int i = from; i < to; i++) { auto [sec_double, hr_double] = getPoint(i); int hr = lrint(hr_double); @@ -241,8 +242,8 @@ void DiveHeartrateItem::replot(const dive *, int fromIn, int toIn, bool) hist[2].hr = hr; // don't print a HR // if it's not a local min / max - // if it's been less than 5min and less than a 20 beats change OR - // if it's been less than 2min OR if the change from the + // if it's been less a full label interval and less than a 20 beats change OR + // if it's been less than half a label interval OR if the change from the // last print is less than 10 beats // to test min / max requires three points, so we now look at the // previous one @@ -250,8 +251,8 @@ void DiveHeartrateItem::replot(const dive *, int fromIn, int toIn, bool) hr = hist[1].hr; if ((hist[0].hr < hr && hr < hist[2].hr) || (hist[0].hr > hr && hr > hist[2].hr) || - ((sec < last + 300) && (abs(hr - last_printed_hr) < 20)) || - (sec < last + 120) || + ((sec < last + interval) && (abs(hr - last_printed_hr) < 20)) || + (sec < last + interval / 2) || (abs(hr - last_printed_hr) < 10)) continue; last = sec; @@ -309,6 +310,7 @@ void DiveTemperatureItem::replot(const dive *, int fromIn, int toIn, bool) texts.clear(); // Ignore empty values. things do not look good with '0' as temperature in kelvin... QPolygonF poly; + int interval = vAxis.getMinLabelDistance(hAxis); for (int i = from; i < to; i++) { auto [sec, mkelvin] = getPoint(i); if (mkelvin < 1.0) @@ -318,11 +320,11 @@ void DiveTemperatureItem::replot(const dive *, int fromIn, int toIn, bool) last_valid_temp = sec; /* don't print a temperature - * if it's been less than 5min and less than a 2K change OR - * if it's been less than 2min OR if the change from the + * if it's been less than a full label interval and less than a 2K change OR + * if it's been less than a half label interval OR if the change from the * last print is less than .4K (and therefore less than 1F) */ - if (((sec < last + 300.0) && (fabs(mkelvin - last_printed_temp) < 2000.0)) || - (sec < last + 120.0) || + if (((sec < last + interval) && (fabs(mkelvin - last_printed_temp) < 2000.0)) || + (sec < last + interval / 2) || (fabs(mkelvin - last_printed_temp) < 400.0)) continue; last = sec;