diff --git a/profile.c b/profile.c index ee001d728..d39133c21 100644 --- a/profile.c +++ b/profile.c @@ -705,31 +705,111 @@ static void populate_cylinder_pressure_data(int idx, int start, int end, struct } } +/* + * Calculate the sac rate between the two plot entries 'first' and 'last'. + * + * Everything in between has a cylinder pressure, and it's all the same + * cylinder. + */ +static int sac_between(struct dive *dive, struct plot_data *first, struct plot_data *last) +{ + int airuse; + double pressuretime; + pressure_t a, b; + cylinder_t *cyl; + int duration; + + if (first == last) + return 0; + + /* Calculate air use - trivial */ + a.mbar = GET_PRESSURE(first); + b.mbar = GET_PRESSURE(last); + cyl = dive->cylinder + first->cylinderindex; + airuse = gas_volume(cyl, a) - gas_volume(cyl, b); + if (airuse <= 0) + return 0; + + /* Calculate depthpressure integrated over time */ + pressuretime = 0.0; + do { + int depth = (first[0].depth + first[1].depth) / 2; + int time = first[1].sec - first[0].sec; + double atm = depth_to_atm(depth, dive); + + pressuretime += atm * time; + } while (++first < last); + + /* Turn "atmseconds" into "atmminutes" */ + pressuretime /= 60; + + /* SAC = mliter per minute */ + return rint(airuse / pressuretime); +} + +/* + * Try to do the momentary sac rate for this entry, averaging over one + * minute. + */ +static void fill_sac(struct dive *dive, struct plot_info *pi, int idx) +{ + struct plot_data *entry = pi->entry + idx; + struct plot_data *first, *last; + int time; + + if (entry->sac) + return; + + if (!GET_PRESSURE(entry)) + return; + + /* + * Try to go back 30 seconds to get 'first'. + * Stop if the sensor changed, or if we went back too far. + */ + first = entry; + time = entry->sec - 30; + while (idx > 0) { + struct plot_data *prev = first-1; + if (prev->cylinderindex != first->cylinderindex) + break; + if (prev->depth < SURFACE_THRESHOLD && first->depth < SURFACE_THRESHOLD) + break; + if (prev->sec < time) + break; + if (!GET_PRESSURE(prev)) + break; + idx--; + first = prev; + } + + /* Now find an entry a minute after the first one */ + last = first; + time = first->sec + 60; + while (++idx < pi->nr) { + struct plot_data *next = last+1; + if (next->cylinderindex != last->cylinderindex) + break; + if (next->depth < SURFACE_THRESHOLD && last->depth < SURFACE_THRESHOLD) + break; + if (next->sec > time) + break; + if (!GET_PRESSURE(next)) + break; + last = next; + } + + /* Ok, now calculate the SAC between 'first' and 'last' */ + entry->sac = sac_between(dive, first, last); +} + static void calculate_sac(struct dive *dive, struct plot_info *pi) { int i = 0, last = 0; struct plot_data *last_entry = NULL; - for (i = 0; i < pi->nr; i++) { - struct plot_data *entry = pi->entry + i; - if (entry->sac) - continue; - if (!last_entry || last_entry->cylinderindex != entry->cylinderindex) { - last = i; - last_entry = entry; - entry->sac = get_local_sac(entry, pi->entry + i + 1, dive); - } else { - int j; - entry->sac = 0; - for (j = last; j < i; j++) - entry->sac += get_local_sac(pi->entry + j, pi->entry + j + 1, dive); - entry->sac /= (i - last); - if (entry->sec - last_entry->sec >= SAC_WINDOW) { - last++; - last_entry = pi->entry + last; - } - } - } + for (i = 0; i < pi->nr; i++) + fill_sac(dive, pi, i); } static void populate_secondary_sensor_data(struct divecomputer *dc, struct plot_info *pi) diff --git a/qt-ui/profile/diveprofileitem.cpp b/qt-ui/profile/diveprofileitem.cpp index 986a0eac0..cff2b1f43 100644 --- a/qt-ui/profile/diveprofileitem.cpp +++ b/qt-ui/profile/diveprofileitem.cpp @@ -780,7 +780,8 @@ void DiveGasPressureItem::paint(QPainter *painter, const QStyleOptionGraphicsIte Q_FOREACH (const QPolygonF &poly, polygons) { entry = dataModel->data().entry; for (int i = 1, count = poly.count(); i < count; i++, entry++) { - pen.setBrush(getSacColor(entry->sac, displayed_dive.sac)); + if (entry->sac) + pen.setBrush(getSacColor(entry->sac, displayed_dive.sac)); painter->setPen(pen); painter->drawLine(poly[i - 1], poly[i]); }