diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-06 16:09:48 -0800 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2013-01-06 22:16:43 -0800 |
commit | 98ed131bdaee6074a2f65d0643e7137e7e5692df (patch) | |
tree | 800f74235fbec3942bf11f1e311d728aa07498de /profile.c | |
parent | be9be189f7350cfb92899680907735719566631e (diff) | |
download | subsurface-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.c | 229 |
1 files changed, 155 insertions, 74 deletions
@@ -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); |