+/*
+ * Create a plot-info with smoothing and ranged min/max
+ *
+ * This also makes sure that we have extra empty events on both
+ * sides, so that you can do end-points without having to worry
+ * about it.
+ */
+static struct plot_info *create_plot_info(struct dive *dive, int nr_samples, struct sample *dive_sample)
+{
+ int cylinderindex = -1;
+ int lastdepth, lastindex;
+ int i, pi_idx, nr, sec, cyl;
+ size_t alloc_size;
+ 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;
+
+ /* we want to potentially add synthetic plot_info elements for the gas changes */
+ nr = nr_samples + 4 + 2 * count_gas_change_events(dive);
+ alloc_size = plot_info_size(nr);
+ pi = malloc(alloc_size);
+ if (!pi)
+ return pi;
+ memset(pi, 0, alloc_size);
+ pi->nr = nr;
+ pi_idx = 2; /* the two extra events at the start */
+ /* check for gas changes before the samples start */
+ ev = get_next_gaschange(dive->events);
+ while (ev && ev->time.seconds < dive_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_gaschange(ev->next);
+ }
+ if (ev && ev->time.seconds == dive_sample->time.seconds) {
+ /* we already have a sample at the time of the event */
+ ev = get_next_gaschange(ev->next);
+ }
+ sec = 0;
+ lastindex = 0;
+ lastdepth = -1;
+ for (i = 0; i < nr_samples; i++) {
+ int depth;
+ int delay = 0;
+ struct sample *sample = dive_sample+i;
+
+ entry = pi->entry + i + pi_idx;
+ 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 */
+ 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;
+ pi_idx += 2;
+ entry = pi->entry + i + pi_idx;
+ ev = get_next_gaschange(ev->next);
+ }
+ 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;
+ pi_idx++;
+ entry = pi->entry + i + pi_idx;
+ ev = get_next_gaschange(ev->next);
+ delay = 1;
+ }
+ sec = entry->sec = sample->time.seconds + delay;
+ depth = entry->depth = sample->depth.mm;
+ entry->cylinderindex = sample->cylinderindex;
+ SENSOR_PRESSURE(entry) = sample->cylinderpressure.mbar;
+ entry->temperature = sample->temperature.mkelvin;
+
+ if (depth || lastdepth)
+ lastindex = i+pi_idx;
+
+ lastdepth = depth;
+ if (depth > pi->maxdepth)
+ pi->maxdepth = 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_gaschange(ev->next);
+ }
+ nr = nr_samples + pi_idx - 2;
+ check_gas_change_events(dive, pi);
+
+ 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];
+ for (i = 0; i < nr + 1; i++) {
+ entry = pi->entry + i + 1;
+
+ entry->same_cylinder = entry->cylinderindex == cylinderindex;
+ cylinderindex = entry->cylinderindex;
+
+ /* track the segments per cylinder and their pressure/time integral */
+ if (!entry->same_cylinder) {
+ current->end = SENSOR_PRESSURE(entry-1);
+ current->t_end = (entry-1)->sec;
+ current = pr_track_alloc(SENSOR_PRESSURE(entry), entry->sec);
+ track_pr[cylinderindex] = list_add(track_pr[cylinderindex], current);
+ } else { /* same cylinder */
+ if ((!SENSOR_PRESSURE(entry) && SENSOR_PRESSURE(entry-1)) ||
+ (SENSOR_PRESSURE(entry) && !SENSOR_PRESSURE(entry-1))) {
+ /* transmitter changed its working status */
+ current->end = SENSOR_PRESSURE(entry-1);
+ current->t_end = (entry-1)->sec;
+ current = pr_track_alloc(SENSOR_PRESSURE(entry), entry->sec);
+ track_pr[cylinderindex] =
+ list_add(track_pr[cylinderindex], current);
+ }
+ }
+ /* finally, do the discrete integration to get the SAC rate equivalent */
+ current->pressure_time += (entry->sec - (entry-1)->sec) *
+ (1 + entry->depth / 10000.0);
+ missing_pr |= !SENSOR_PRESSURE(entry);
+ }