aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--profile.c260
1 files changed, 99 insertions, 161 deletions
diff --git a/profile.c b/profile.c
index 44373e7a2..6e8102b70 100644
--- a/profile.c
+++ b/profile.c
@@ -1461,19 +1461,6 @@ static void check_gas_change_events(struct dive *dive, struct divecomputer *dc,
set_cylinder_index(pi, i, cylinderindex, ~0u);
}
-/* for computers that track gas changes through events */
-static int count_gas_change_events(struct divecomputer *dc)
-{
- int count = 0;
- struct event *ev = get_next_event(dc->events, "gaschange");
-
- while (ev) {
- count++;
- ev = get_next_event(ev->next, "gaschange");
- }
- return count;
-}
-
static void calculate_max_limits(struct dive *dive, struct divecomputer *dc, struct graphics_context *gc)
{
struct plot_info *pi;
@@ -1539,6 +1526,98 @@ static void calculate_max_limits(struct dive *dive, struct divecomputer *dc, str
pi->maxtemp = maxtemp;
}
+/* Average between 'a' and 'b', when we are 'part'way into the 'whole' distance from a to b */
+static int average_depth(int a, int b, int part, int whole)
+{
+ double x;
+
+ x = (a * (whole - part) + b * part) / whole;
+ return rint(x);
+}
+
+static struct plot_data *populate_plot_entries(struct dive *dive, struct divecomputer *dc, struct plot_info *pi)
+{
+ int idx, maxtime, nr, i;
+ int lastdepth, lasttime;
+ struct plot_data *plot_data;
+
+ maxtime = get_maxtime(pi);
+ if (dive->end > 0)
+ maxtime = dive->end;
+
+ /*
+ * We want to have a plot_info event at least every 10s (so "maxtime/10"),
+ * but samples could be more dense than that (so add in dc->samples), and
+ * additionally we want two surface events around the whole thing (thus the
+ * additional 4).
+ */
+ nr = dc->samples + 4 + maxtime / 10;
+ plot_data = calloc(nr, sizeof(struct plot_data));
+ pi->entry = plot_data;
+ if (!plot_data)
+ return NULL;
+ pi->nr = nr;
+ idx = 2; /* the two extra events at the start */
+
+ lastdepth = 0;
+ lasttime = 0;
+ for (i = 0; i < dc->samples; i++) {
+ struct plot_data *entry = plot_data + idx;
+ struct sample *sample = dc->sample+i;
+ int time = sample->time.seconds;
+ int depth = sample->depth.mm;
+ int offset, delta;
+
+ /* Add intermediate plot entries if required */
+ delta = time - lasttime;
+ for (offset = 10; offset < delta; offset += 10) {
+ if (lasttime + offset > maxtime)
+ break;
+
+ /* Use the data from the previous plot entry */
+ *entry = entry[-1];
+
+ /* .. but update depth and time, obviously */
+ entry->sec = lasttime + offset;
+ entry->depth = average_depth(lastdepth, depth, offset, delta);
+
+ /* And clear out the sensor pressure, since we'll interpolate */
+ SENSOR_PRESSURE(entry) = 0;
+
+ idx++; entry++;
+ }
+
+ if (time > maxtime)
+ break;
+
+ entry->sec = time;
+ entry->depth = depth;
+
+ entry->stopdepth = sample->stopdepth.mm;
+ entry->stoptime = sample->stoptime.seconds;
+ entry->ndl = sample->ndl.seconds;
+ pi->has_ndl |= sample->ndl.seconds;
+ entry->in_deco = sample->in_deco;
+ entry->cns = sample->cns;
+ entry->po2 = sample->po2 / 1000.0;
+ /* FIXME! sensor index -> cylinder index translation! */
+ entry->cylinderindex = sample->sensor;
+ SENSOR_PRESSURE(entry) = sample->cylinderpressure.mbar;
+ entry->temperature = sample->temperature.mkelvin;
+
+ lasttime = time;
+ lastdepth = depth;
+ idx++;
+ }
+
+ /* Add two final surface events */
+ plot_data[idx++].sec = lasttime+10;
+ plot_data[idx++].sec = lasttime+20;
+ pi->nr = idx;
+
+ return plot_data;
+}
+
/*
* Create a plot-info with smoothing and ranged min/max
*
@@ -1549,16 +1628,13 @@ static void calculate_max_limits(struct dive *dive, struct divecomputer *dc, str
static struct plot_info *create_plot_info(struct dive *dive, struct divecomputer *dc, struct graphics_context *gc)
{
int cylinderindex = -1;
- int lastdepth, lastindex;
- int i, pi_idx, nr, sec, cyl, stoptime, ndl, stopdepth, cns;
- gboolean in_deco;
+ int i, nr, cyl;
struct plot_info *pi;
pr_track_t *track_pr[MAX_CYLINDERS] = {NULL, };
pr_track_t *pr_track, *current;
gboolean missing_pr = FALSE;
struct plot_data *entry = NULL;
- struct event *ev;
- double amb_pressure, po2;
+ double amb_pressure;
double surface_pressure = (dive->surface_pressure.mbar ? dive->surface_pressure.mbar : 1013) / 1000.0;
/* The plot-info is embedded in the graphics context */
@@ -1567,129 +1643,16 @@ static struct plot_info *create_plot_info(struct dive *dive, struct divecomputer
/* reset deco information to start the calculation */
init_decompression(dive);
- /* we want to potentially add synthetic plot_info elements for the gas changes */
- nr = dc->samples + 4 + 2 * count_gas_change_events(dc);
+ /* Create the new plot data */
if (last_pi_entry)
free((void *)last_pi_entry);
- last_pi_entry = pi->entry = calloc(nr, sizeof(struct plot_data));
- if (!pi->entry)
- return NULL;
- pi->nr = nr;
- pi_idx = 2; /* the two extra events at the start */
- /* check for gas changes before the samples start */
- ev = get_next_event(dc->events, "gaschange");
- while (ev && ev->time.seconds < dc->sample->time.seconds) {
- entry = pi->entry + pi_idx;
- entry->sec = ev->time.seconds;
- entry->depth = 0; /* is that always correct ? */
- pi_idx++;
- ev = get_next_event(ev->next, "gaschange");
- }
- if (ev && ev->time.seconds == dc->sample->time.seconds) {
- /* we already have a sample at the time of the event */
- ev = get_next_event(ev->next, "gaschange");
- }
- sec = 0;
- lastindex = 0;
- lastdepth = -1;
- for (i = 0; i < dc->samples; i++) {
- int depth;
- int delay = 0;
- struct sample *sample = dc->sample+i;
-
- if ((dive->start > -1 && sample->time.seconds < dive->start) ||
- (dive->end > -1 && sample->time.seconds > dive->end)) {
- pi_idx--;
- continue;
- }
- entry = pi->entry + i + pi_idx;
- in_deco = sample->in_deco;
- ndl = sample->ndl.seconds;
- pi->has_ndl |= ndl;
- stopdepth = sample->stopdepth.mm;
- stoptime = sample->stoptime.seconds;
- po2 = sample->po2 / 1000.0;
- cns = sample->cns;
- while (ev && ev->time.seconds < sample->time.seconds) {
- /* insert two fake plot info structures for the end of
- * the old tank and the start of the new tank */
- if (ev->time.seconds == sample->time.seconds - 1) {
- entry->sec = ev->time.seconds - 1;
- (entry+1)->sec = ev->time.seconds;
- } else {
- entry->sec = ev->time.seconds;
- (entry+1)->sec = ev->time.seconds + 1;
- }
- /* we need a fake depth - let's interpolate */
- if (i) {
- entry->depth = sample->depth.mm -
- (sample->depth.mm - (sample-1)->depth.mm) / 2;
- } else
- entry->depth = sample->depth.mm;
- (entry + 1)->depth = entry->depth;
- entry->stopdepth = stopdepth;
- entry->stoptime = stoptime;
- entry->ndl = ndl;
- entry->cns = cns;
- entry->po2 = po2;
- entry->in_deco = in_deco;
- (entry + 1)->stopdepth = stopdepth;
- (entry + 1)->stoptime = stoptime;
- (entry + 1)->ndl = ndl;
- (entry + 1)->in_deco = in_deco;
- (entry + 1)->cns = cns;
- (entry + 1)->po2 = po2;
- pi_idx += 2;
- entry = pi->entry + i + pi_idx;
- ev = get_next_event(ev->next, "gaschange");
- }
- if (ev && ev->time.seconds == sample->time.seconds) {
- /* we already have a sample at the time of the event
- * just add a new one for the old tank and delay the
- * real even by one second (to keep time monotonous) */
- entry->sec = ev->time.seconds;
- entry->depth = sample->depth.mm;
- entry->stopdepth = stopdepth;
- entry->stoptime = stoptime;
- entry->ndl = ndl;
- entry->in_deco = in_deco;
- entry->cns = cns;
- entry->po2 = po2;
- pi_idx++;
- entry = pi->entry + i + pi_idx;
- ev = get_next_event(ev->next, "gaschange");
- delay = 1;
- }
- sec = entry->sec = sample->time.seconds + delay;
- depth = entry->depth = sample->depth.mm;
- entry->stopdepth = stopdepth;
- entry->stoptime = stoptime;
- entry->ndl = ndl;
- entry->in_deco = in_deco;
- entry->cns = cns;
- entry->po2 = po2;
- /* FIXME! sensor index -> cylinder index translation! */
- entry->cylinderindex = sample->sensor;
- SENSOR_PRESSURE(entry) = sample->cylinderpressure.mbar;
- entry->temperature = sample->temperature.mkelvin;
-
- if (depth || lastdepth)
- lastindex = i + pi_idx;
+ last_pi_entry = populate_plot_entries(dive, dc, pi);
- lastdepth = depth;
- }
- entry = pi->entry + i + pi_idx;
- /* are there still unprocessed gas changes? that would be very strange */
- while (ev) {
- entry->sec = ev->time.seconds;
- entry->depth = 0; /* why are there gas changes after the dive is over? */
- pi_idx++;
- entry = pi->entry + i + pi_idx;
- ev = get_next_event(ev->next, "gaschange");
- }
- nr = dc->samples + pi_idx - 2;
+ /* Populate the gas index from the gas change events */
check_gas_change_events(dive, dc, pi);
+ nr = pi->nr-2;
+
for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) /* initialize the start pressures */
track_pr[cyl] = pr_track_alloc(dive->cylinder[cyl].start.mbar, -1);
current = track_pr[pi->entry[2].cylinderindex];
@@ -1778,24 +1741,6 @@ static struct plot_info *create_plot_info(struct dive *dive, struct divecomputer
pr_track->end = pr;
}
}
- /* Fill in the last two entries with empty values but valid times
- * without creating a false cylinder change event */
- i = nr + 2;
- pi->entry[i].sec = sec + 20;
- pi->entry[i].same_cylinder = 1;
- pi->entry[i].cylinderindex = pi->entry[i-1].cylinderindex;
- INTERPOLATED_PRESSURE(pi->entry + i) = GET_PRESSURE(pi->entry + i - 1);
- amb_pressure = depth_to_mbar(pi->entry[i - 1].depth, dive) / 1000.0;
- pi->entry[i].po2 = pi->entry[i-1].po2 / amb_pressure;
- pi->entry[i].phe = pi->entry[i-1].phe / amb_pressure;
- pi->entry[i].pn2 = 1.01325 - pi->entry[i].po2 - pi->entry[i].phe;
- pi->entry[i+1].sec = sec + 40;
- pi->entry[i+1].same_cylinder = 1;
- pi->entry[i+1].cylinderindex = pi->entry[i-1].cylinderindex;
- INTERPOLATED_PRESSURE(pi->entry + i + 1) = GET_PRESSURE(pi->entry + i - 1);
- pi->entry[i+1].po2 = pi->entry[i].po2;
- pi->entry[i+1].phe = pi->entry[i].phe;
- pi->entry[i+1].pn2 = pi->entry[i].pn2;
/* make sure the first two pi entries have a sane po2 / phe / pn2 */
amb_pressure = depth_to_mbar(pi->entry[2].depth, dive) / 1000.0;
if (pi->entry[1].po2 < 0.01)
@@ -1810,13 +1755,6 @@ static struct plot_info *create_plot_info(struct dive *dive, struct divecomputer
pi->entry[0].phe = pi->entry[1].phe / amb_pressure;
pi->entry[0].pn2 = 1.01325 - pi->entry[0].po2 - pi->entry[0].phe;
- /* the number of actual entries - some computers have lots of
- * depth 0 samples at the end of a dive, we want to make sure
- * we have exactly one of them at the end */
- pi->nr = lastindex+1;
- while (pi->nr <= i+2 && pi->entry[pi->nr-1].depth > 0)
- pi->nr++;
-
pi->meandepth = dive->meandepth.mm;
if (missing_pr) {