summaryrefslogtreecommitdiffstats
path: root/profile.c
diff options
context:
space:
mode:
authorGravatar Linus Torvalds <torvalds@linux-foundation.org>2013-01-06 16:09:48 -0800
committerGravatar Dirk Hohndel <dirk@hohndel.org>2013-01-06 22:16:43 -0800
commit98ed131bdaee6074a2f65d0643e7137e7e5692df (patch)
tree800f74235fbec3942bf11f1e311d728aa07498de /profile.c
parentbe9be189f7350cfb92899680907735719566631e (diff)
downloadsubsurface-98ed131bdaee6074a2f65d0643e7137e7e5692df.tar.gz
Split up and re-organize the plot entry calculations
This splits up the (very complex) function that calculates all the plot info data, so that the gas pressure logic is in several helper functions, and the deco and partial pressure calculations are in a function of their own. That makes the code almost readable. This also changes the cylinder pressure calculations so that if you have manually set the beginning and end pressures, those are the ones we will show (by making them fake "sensor pressures"). We used to shopw some random pressure that was related to the manually entered ones only distantly (through various rounding phases and the SAC-rate calculations). That does make the rounding errors more obvious in the graph, but we can fix that separately. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'profile.c')
-rw-r--r--profile.c229
1 files changed, 155 insertions, 74 deletions
diff --git a/profile.c b/profile.c
index 6e8102b70..7540ff764 100644
--- a/profile.c
+++ b/profile.c
@@ -1618,75 +1618,153 @@ static struct plot_data *populate_plot_entries(struct dive *dive, struct divecom
return plot_data;
}
-/*
- * 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, struct divecomputer *dc, struct graphics_context *gc)
+static void populate_cylinder_pressure_data(int idx, int start, int end, struct plot_info *pi)
{
- int cylinderindex = -1;
- 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;
- double amb_pressure;
- double surface_pressure = (dive->surface_pressure.mbar ? dive->surface_pressure.mbar : 1013) / 1000.0;
+ int i;
- /* The plot-info is embedded in the graphics context */
- pi = &gc->pi;
+ /* 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)
+ continue;
+ if (SENSOR_PRESSURE(entry))
+ return;
+ }
- /* reset deco information to start the calculation */
- init_decompression(dive);
+ /* 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)
+ continue;
+ SENSOR_PRESSURE(entry) = start;
+ break;
+ }
- /* Create the new plot data */
- if (last_pi_entry)
- free((void *)last_pi_entry);
- last_pi_entry = populate_plot_entries(dive, dc, pi);
+ /* .. and the last entry with the ending cylinder pressure */
+ for (i = pi->nr; --i >= 0; ) {
+ struct plot_data *entry = pi->entry+i;
+ if (entry->cylinderindex != idx)
+ continue;
+ SENSOR_PRESSURE(entry) = end;
+ break;
+ }
+}
- /* Populate the gas index from the gas change events */
- check_gas_change_events(dive, dc, pi);
+static void populate_secondary_sensor_data(struct divecomputer *dc, struct plot_info *pi)
+{
+ /* We should try to see if it has interesting pressure data here */
+}
- nr = pi->nr-2;
+static void setup_gas_sensor_pressure(struct dive *dive, struct divecomputer *dc, struct plot_info *pi)
+{
+ int i;
+ struct divecomputer *secondary;
- 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++) {
- int fo2, fhe;
+ /* First, populate the pressures with the manual cylinder data.. */
+ for (i = 0; i < MAX_CYLINDERS; i++) {
+ cylinder_t *cyl = dive->cylinder+i;
+ int start = cyl->start.mbar ? : cyl->sample_start.mbar;
+ int end = cyl->end.mbar ? : cyl->sample_end.mbar;
+
+ if (!start || !end)
+ continue;
+
+ populate_cylinder_pressure_data(i, start, end, pi);
+ }
+
+ /*
+ * Here, we should try to walk through all the dive computers,
+ * and try to see if they have sensor data different from the
+ * primary dive computer (dc).
+ */
+ secondary = &dive->dc;
+ do {
+ if (secondary == dc)
+ continue;
+ populate_secondary_sensor_data(dc, pi);
+ } while ((secondary = secondary->next) != NULL);
+}
+
+static void populate_pressure_information(struct dive *dive, struct divecomputer *dc, struct plot_info *pi)
+{
+ int i, cylinderindex;
+ pr_track_t *track_pr[MAX_CYLINDERS] = {NULL, };
+ pr_track_t *current;
+ gboolean missing_pr = FALSE;
+
+ /* Set up the pressure tracking data structures */
+ for (i = 0; i < MAX_CYLINDERS; i++) {
+ cylinder_t *cyl = dive->cylinder + i;
+ int mbar = cyl->start.mbar ? : cyl->sample_start.mbar;
+ track_pr[i] = pr_track_alloc(mbar, 0);
+ }
+
+ cylinderindex = pi->entry[0].cylinderindex;
+ current = track_pr[cylinderindex];
+ for (i = 1; i < pi->nr; i++) {
+ struct plot_data *entry = pi->entry + i;
- entry = pi->entry + i + 1;
+ entry = pi->entry + i;
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))) {
+ if (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->end = SENSOR_PRESSURE(entry);
+ current->t_end = entry->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) *
+ depth_to_mbar((entry->depth + (entry-1)->depth) / 2, dive) / 1000.0;
+ if (SENSOR_PRESSURE(entry)) {
+ current->end = SENSOR_PRESSURE(entry);
+ current->t_end = entry->sec;
+ }
+ missing_pr |= !SENSOR_PRESSURE(entry);
+ }
+
+ /* initialize the end pressures */
+ for (i = 0; i < MAX_CYLINDERS; i++) {
+ cylinder_t *cyl = dive->cylinder + i;
+ int pr = cyl->end.mbar ? : cyl->sample_end.mbar;
+ if (pr && track_pr[i]) {
+ pr_track_t *pr_track = list_last(track_pr[i]);
+ pr_track->end = pr;
+ }
+ }
+
+ if (missing_pr) {
+ fill_missing_tank_pressures(pi, track_pr);
+ }
+ for (i = 0; i < MAX_CYLINDERS; i++)
+ list_free(track_pr[i]);
+}
+
+static void calculate_deco_information(struct dive *dive, struct divecomputer *dc, struct plot_info *pi)
+{
+ int i;
+ double amb_pressure;
+ double surface_pressure = (dive->surface_pressure.mbar ? dive->surface_pressure.mbar : 1013) / 1000.0;
+
+ for (i = 1; i < pi->nr; i++) {
+ int fo2, fhe;
+ struct plot_data *entry = pi->entry + i;
+ int cylinderindex = entry->cylinderindex;
+
amb_pressure = depth_to_mbar(entry->depth, dive) / 1000.0;
- fo2 = dive->cylinder[cylinderindex].gasmix.o2.permille;
+ fo2 = dive->cylinder[cylinderindex].gasmix.o2.permille ? : AIR_PERMILLE;
fhe = dive->cylinder[cylinderindex].gasmix.he.permille;
- if (!fo2)
- fo2 = AIR_PERMILLE;
if (entry->po2) {
/* we have an O2 partial pressure in the sample - so this
* is likely a CC dive... use that instead of the value
@@ -1707,10 +1785,7 @@ static struct plot_info *create_plot_info(struct dive *dive, struct divecomputer
pi->maxpp = entry->phe;
if (entry->pn2 > pi->maxpp)
pi->maxpp = entry->pn2;
- /* finally, do the discrete integration to get the SAC rate equivalent */
- current->pressure_time += (entry->sec - (entry-1)->sec) *
- depth_to_mbar((entry->depth + (entry-1)->depth) / 2, dive) / 1000.0;
- missing_pr |= !SENSOR_PRESSURE(entry);
+
/* and now let's try to do some deco calculations */
if (i > 0) {
int j;
@@ -1727,41 +1802,47 @@ static struct plot_info *create_plot_info(struct dive *dive, struct divecomputer
entry->ceiling = deco_allowed_depth(tissue_tolerance, surface_pressure, dive, !prefs.calc_ceiling_3m_incr);
}
}
+
#if DECO_CALC_DEBUG & 1
dump_tissues();
#endif
+}
- if (entry)
- current->t_end = entry->sec;
+/*
+ * 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, struct divecomputer *dc, struct graphics_context *gc)
+{
+ struct plot_info *pi;
- for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) { /* initialize the end pressures */
- int pr = dive->cylinder[cyl].end.mbar;
- if (pr && track_pr[cyl]) {
- pr_track = list_last(track_pr[cyl]);
- pr_track->end = pr;
- }
- }
- /* 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)
- pi->entry[1].po2 = pi->entry[2].po2 / amb_pressure;
- if (pi->entry[1].phe < 0.01)
- pi->entry[1].phe = pi->entry[2].phe / amb_pressure;
- pi->entry[1].pn2 = 1.01325 - pi->entry[1].po2 - pi->entry[1].phe;
- amb_pressure = depth_to_mbar(pi->entry[1].depth, dive) / 1000.0;
- if (pi->entry[0].po2 < 0.01)
- pi->entry[0].po2 = pi->entry[1].po2 / amb_pressure;
- if (pi->entry[0].phe < 0.01)
- 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 plot-info is embedded in the graphics context */
+ pi = &gc->pi;
+ /* reset deco information to start the calculation */
+ init_decompression(dive);
+
+ /* Create the new plot data */
+ if (last_pi_entry)
+ free((void *)last_pi_entry);
+ last_pi_entry = populate_plot_entries(dive, dc, pi);
+
+ /* Populate the gas index from the gas change events */
+ check_gas_change_events(dive, dc, pi);
+
+ /* Try to populate our gas pressure knowledge */
+ setup_gas_sensor_pressure(dive, dc, pi);
+
+ /* .. calculate missing pressure entries */
+ populate_pressure_information(dive, dc, pi);
+
+ /* Then, calculate partial pressures and deco information */
+ calculate_deco_information(dive, dc, pi);
pi->meandepth = dive->meandepth.mm;
- if (missing_pr) {
- fill_missing_tank_pressures(pi, track_pr);
- }
- for (cyl = 0; cyl < MAX_CYLINDERS; cyl++)
- list_free(track_pr[cyl]);
if (0) /* awesome for debugging - not useful otherwise */
dump_pi(pi);
return analyze_plot_info(pi);