mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-30 22:20:21 +00:00
For CCR dives, show plot for diluent and O2 cylinder pressures
Also fixes a bug in the diluent pressure interpolation Signed-off-by: Robert C. Helling <helling@atdotde.de> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
992e58eaf2
commit
d5d7fdc9af
6 changed files with 67 additions and 24 deletions
2
TODO.CCR
2
TODO.CCR
|
@ -1,5 +1,5 @@
|
|||
TODO for CCR support
|
||||
|
||||
- tank pressure plot (see test40.xml)
|
||||
- make tank pressure plot work for bailout dives
|
||||
- bailout handling in SAC rate calculation
|
||||
- UI to modify the tank type for CCR (i.e., set the diluent and oxygen cylinders)
|
||||
|
|
|
@ -99,6 +99,8 @@ static void dump_pr_track(pr_track_t **track_pr)
|
|||
*/
|
||||
static void fill_missing_segment_pressures(pr_track_t *list, enum interpolation_strategy strategy)
|
||||
{
|
||||
double magic;
|
||||
|
||||
while (list) {
|
||||
int start = list->start, end;
|
||||
pr_track_t *tmp = list;
|
||||
|
@ -144,10 +146,12 @@ static void fill_missing_segment_pressures(pr_track_t *list, enum interpolation_
|
|||
}
|
||||
break;
|
||||
case TIME:
|
||||
if (list->t_end && (tmp->t_start - tmp->t_end))
|
||||
list->end = start - (start - end) * (list->t_end - tmp->t_end) / (tmp->t_start - tmp->t_end);
|
||||
else
|
||||
if (list->t_end && (tmp->t_start - tmp->t_end)) {
|
||||
magic = (list->t_start - tmp->t_end) / (tmp->t_start - tmp->t_end);
|
||||
list->end = rint(start - (start - end) * magic);
|
||||
} else {
|
||||
list->end = start;
|
||||
}
|
||||
break;
|
||||
case CONSTANT:
|
||||
list->end = start;
|
||||
|
@ -219,7 +223,7 @@ static struct pr_interpolate_struct get_pr_interpolate_data(pr_track_t *segment,
|
|||
return interpolate;
|
||||
}
|
||||
|
||||
static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi, pr_track_t **track_pr, int o2_flag)
|
||||
static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi, pr_track_t **track_pr, bool o2_flag)
|
||||
{
|
||||
int cyl, i;
|
||||
struct plot_data *entry;
|
||||
|
@ -291,16 +295,22 @@ static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi,
|
|||
*save_pressure = cur_pr[cyl]; // Just use our current pressure
|
||||
continue; // and skip to next point.
|
||||
}
|
||||
|
||||
// If there is a valid segment but no tank pressure ..
|
||||
interpolate = get_pr_interpolate_data(segment, pi, i, pressure); // Set up an interpolation structure
|
||||
if(dive->cylinder[cyl].cylinder_use == OC_GAS) {
|
||||
|
||||
/* if this segment has pressure_time, then calculate a new interpolated pressure */
|
||||
if (interpolate.pressure_time) {
|
||||
/* Overall pressure change over total pressure-time for this segment*/
|
||||
magic = (interpolate.end - interpolate.start) / (double)interpolate.pressure_time;
|
||||
/* if this segment has pressure_time, then calculate a new interpolated pressure */
|
||||
if (interpolate.pressure_time) {
|
||||
/* Overall pressure change over total pressure-time for this segment*/
|
||||
magic = (interpolate.end - interpolate.start) / (double)interpolate.pressure_time;
|
||||
|
||||
/* Use that overall pressure change to update the current pressure */
|
||||
cur_pr[cyl] = rint(interpolate.start + magic * interpolate.acc_pressure_time);
|
||||
/* Use that overall pressure change to update the current pressure */
|
||||
cur_pr[cyl] = rint(interpolate.start + magic * interpolate.acc_pressure_time);
|
||||
}
|
||||
} else {
|
||||
magic = (interpolate.end - interpolate.start) / (segment->t_end - segment->t_start);
|
||||
cur_pr[cyl] = rint(segment->start + magic * (entry->sec - segment->t_start));
|
||||
}
|
||||
*save_interpolated = cur_pr[cyl]; // and store the interpolated data in plot_info
|
||||
}
|
||||
|
@ -341,7 +351,7 @@ static void debug_print_pressures(struct plot_info *pi)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* This function goes through the list of tank pressures, either SENSOR_PRESSURE(entry) or DILUENT_PRESSURE(entry),
|
||||
/* This function goes through the list of tank pressures, either SENSOR_PRESSURE(entry) or O2CYLINDER_PRESSURE(entry),
|
||||
* of structure plot_info for the dive profile where each item in the list corresponds to one point (node) of the
|
||||
* profile. It finds values for which there are no tank pressures (pressure==0). For each missing item (node) of
|
||||
* tank pressure it creates a pr_track_alloc structure that represents a segment on the dive profile and that
|
||||
|
|
26
profile.c
26
profile.c
|
@ -612,34 +612,40 @@ struct plot_data *populate_plot_entries(struct dive *dive, struct divecomputer *
|
|||
|
||||
#undef INSERT_ENTRY
|
||||
|
||||
static void populate_cylinder_pressure_data(int idx, int start, int end, struct plot_info *pi)
|
||||
static void populate_cylinder_pressure_data(int idx, int start, int end, struct plot_info *pi, bool o2flag)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* First: check that none of the entries has sensor pressure for this cylinder index */
|
||||
for (i = 0; i < pi->nr; i++) {
|
||||
struct plot_data *entry = pi->entry + i;
|
||||
if (entry->cylinderindex != idx)
|
||||
if (entry->cylinderindex != idx && !o2flag)
|
||||
continue;
|
||||
if (SENSOR_PRESSURE(entry))
|
||||
if (CYLINDER_PRESSURE(o2flag, entry))
|
||||
return;
|
||||
}
|
||||
|
||||
/* Then: populate the first entry with the beginning cylinder pressure */
|
||||
for (i = 0; i < pi->nr; i++) {
|
||||
struct plot_data *entry = pi->entry + i;
|
||||
if (entry->cylinderindex != idx)
|
||||
if (entry->cylinderindex != idx && !o2flag)
|
||||
continue;
|
||||
SENSOR_PRESSURE(entry) = start;
|
||||
if (o2flag)
|
||||
O2CYLINDER_PRESSURE(entry) = start;
|
||||
else
|
||||
SENSOR_PRESSURE(entry) = start;
|
||||
break;
|
||||
}
|
||||
|
||||
/* .. and the last entry with the ending cylinder pressure */
|
||||
for (i = pi->nr; --i >= 0; /* nothing */) {
|
||||
struct plot_data *entry = pi->entry + i;
|
||||
if (entry->cylinderindex != idx)
|
||||
if (entry->cylinderindex != idx && !o2flag)
|
||||
continue;
|
||||
SENSOR_PRESSURE(entry) = end;
|
||||
if (o2flag)
|
||||
O2CYLINDER_PRESSURE(entry) = end;
|
||||
else
|
||||
SENSOR_PRESSURE(entry) = end;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -688,7 +694,7 @@ static void setup_gas_sensor_pressure(struct dive *dive, struct divecomputer *dc
|
|||
if (!start || !end)
|
||||
continue;
|
||||
|
||||
populate_cylinder_pressure_data(i, start, end, pi);
|
||||
populate_cylinder_pressure_data(i, start, end, pi, dive->cylinder[i].cylinder_use == OXYGEN);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1013,9 +1019,9 @@ void create_plot_info_new(struct dive *dive, struct divecomputer *dc, struct plo
|
|||
|
||||
check_gas_change_events(dive, dc, pi); /* Populate the gas index from the gas change events */
|
||||
setup_gas_sensor_pressure(dive, dc, pi); /* Try to populate our gas pressure knowledge */
|
||||
populate_pressure_information(dive, dc, pi, false); /* .. calculate missing pressure entries for all gasses except diluent */
|
||||
populate_pressure_information(dive, dc, pi, false); /* .. calculate missing pressure entries for all gasses except o2 */
|
||||
if (dc->dctype == CCR) /* For CCR dives.. */
|
||||
populate_pressure_information(dive, dc, pi, true); /* .. calculate missing diluent gas pressure entries */
|
||||
populate_pressure_information(dive, dc, pi, true); /* .. calculate missing o2 gas pressure entries */
|
||||
|
||||
fill_o2_values(dc, pi, dive); /* .. and insert the O2 sensor data having 0 values. */
|
||||
calculate_sac(dive, pi); /* Calculate sac */
|
||||
|
|
|
@ -92,9 +92,11 @@ int get_maxdepth(struct plot_info *pi);
|
|||
#define INTERPOLATED_PR 1
|
||||
#define SENSOR_PRESSURE(_entry) (_entry)->pressure[SENSOR_PR]
|
||||
#define O2CYLINDER_PRESSURE(_entry) (_entry)->o2cylinderpressure[SENSOR_PR]
|
||||
#define CYLINDER_PRESSURE(_o2, _entry) (_o2 ? O2CYLINDER_PRESSURE(_entry) : SENSOR_PRESSURE(_entry))
|
||||
#define INTERPOLATED_PRESSURE(_entry) (_entry)->pressure[INTERPOLATED_PR]
|
||||
#define INTERPOLATED_O2CYLINDER_PRESSURE(_entry) (_entry)->o2cylinderpressure[INTERPOLATED_PR]
|
||||
#define GET_PRESSURE(_entry) (SENSOR_PRESSURE(_entry) ? SENSOR_PRESSURE(_entry) : INTERPOLATED_PRESSURE(_entry))
|
||||
#define GET_O2CYLINDER_PRESSURE(_entry) (O2CYLINDER_PRESSURE(_entry) ? O2CYLINDER_PRESSURE(_entry) : INTERPOLATED_O2CYLINDER_PRESSURE(_entry))
|
||||
#define SAC_WINDOW 45 /* sliding window in seconds for current SAC calculation */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
QString gasToStr(struct gasmix gas)
|
||||
{
|
||||
uint o2 = (get_o2(&gas) + 5) / 10, he = (get_he(&gas) + 5) / 10;
|
||||
QString result = gasmix_is_air(&gas) ? QObject::tr("AIR") : he == 0 ? QString("EAN%1").arg(o2, 2, 10, QChar('0')) : QString("%1/%2").arg(o2).arg(he);
|
||||
QString result = gasmix_is_air(&gas) ? QObject::tr("AIR") : he == 0 ? (o2 == 100 ? QObject::tr("OXYGEN") : QString("EAN%1").arg(o2, 2, 10, QChar('0'))) : QString("%1/%2").arg(o2).arg(he);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -574,12 +574,18 @@ void DiveGasPressureItem::modelDataChanged(const QModelIndex &topLeft, const QMo
|
|||
if (!shouldCalculateStuff(topLeft, bottomRight))
|
||||
return;
|
||||
int last_index = -1;
|
||||
QPolygonF boundingPoly; // This is the "Whole Item", but a pressure can be divided in N Polygons.
|
||||
int o2mbar;
|
||||
QPolygonF boundingPoly, o2Poly; // This is the "Whole Item", but a pressure can be divided in N Polygons.
|
||||
polygons.clear();
|
||||
if (displayed_dive.dc.dctype == CCR)
|
||||
polygons.append(o2Poly);
|
||||
|
||||
for (int i = 0, count = dataModel->rowCount(); i < count; i++) {
|
||||
o2mbar = 0;
|
||||
plot_data *entry = dataModel->data().entry + i;
|
||||
int mbar = GET_PRESSURE(entry);
|
||||
if (displayed_dive.dc.dctype == CCR)
|
||||
o2mbar = GET_O2CYLINDER_PRESSURE(entry);
|
||||
|
||||
if (entry->cylinderindex != last_index) {
|
||||
polygons.append(QPolygonF()); // this is the polygon that will be actually drawned on screen.
|
||||
|
@ -588,6 +594,11 @@ void DiveGasPressureItem::modelDataChanged(const QModelIndex &topLeft, const QMo
|
|||
if (!mbar) {
|
||||
continue;
|
||||
}
|
||||
if (o2mbar) {
|
||||
QPointF o2point(hAxis->posAtValue(entry->sec), vAxis->posAtValue(o2mbar));
|
||||
boundingPoly.push_back(o2point);
|
||||
polygons.first().push_back(o2point);
|
||||
}
|
||||
|
||||
QPointF point(hAxis->posAtValue(entry->sec), vAxis->posAtValue(mbar));
|
||||
boundingPoly.push_back(point); // The BoundingRect
|
||||
|
@ -603,9 +614,23 @@ void DiveGasPressureItem::modelDataChanged(const QModelIndex &topLeft, const QMo
|
|||
struct plot_data *entry;
|
||||
|
||||
cyl = -1;
|
||||
o2mbar = 0;
|
||||
for (int i = 0, count = dataModel->rowCount(); i < count; i++) {
|
||||
entry = dataModel->data().entry + i;
|
||||
mbar = GET_PRESSURE(entry);
|
||||
if (displayed_dive.dc.dctype == CCR)
|
||||
o2mbar = GET_O2CYLINDER_PRESSURE(entry);
|
||||
|
||||
if (o2mbar) {
|
||||
if (!seen_cyl[displayed_dive.oxygen_cylinder_index]) {
|
||||
plotPressureValue(o2mbar, entry->sec, Qt::AlignRight | Qt::AlignBottom);
|
||||
plotGasValue(o2mbar, entry->sec, Qt::AlignRight | Qt::AlignBottom, displayed_dive.cylinder[displayed_dive.oxygen_cylinder_index].gasmix);
|
||||
seen_cyl[displayed_dive.oxygen_cylinder_index] = true;
|
||||
}
|
||||
last_pressure[displayed_dive.oxygen_cylinder_index] = o2mbar;
|
||||
last_time[displayed_dive.oxygen_cylinder_index] = entry->sec;
|
||||
}
|
||||
|
||||
|
||||
if (!mbar)
|
||||
continue;
|
||||
|
|
Loading…
Reference in a new issue