Add support for MOD, EAD, AND and EADD in the mouse over display

- MOD: Maximum Operation Depth based on a configurable limit
- EAD: Equivalent Air Depth considering N2 and (!) O2 narcotic
- END: Equivalent Nitrogen (Narcotic) Depth considering just N2 narcotic
       (ignoring O2)
- EADD: Equivalent Air Density Depth

Please note that some people and even diving organisations have opposite
definitions for EAD and END. Considering A stands for Air, lets choose the
above. And considering N for Nitrogen it also fits in this scheme.

This patch moves N2_IN_AIR from deco.c to dive.h as this is already used
in several places and might be useful for future use also. It also
respecifies N2_IN_AIR to a more correct value of 78,084%, the former one
also included all other gases than oxygen appearing in air. If someone
needs to use the former value it would be more correct to use 1-O2_IN_AIR
instead.

Signed-off-by: Jan Schubert / Jan.Schubert@GMX.li
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Dirk Hohndel 2013-01-13 16:24:58 -08:00
parent 53dbccb87a
commit 23ce727e62
7 changed files with 90 additions and 5 deletions

1
deco.c
View file

@ -78,7 +78,6 @@ const double buehlmann_He_factor_expositon_one_second[] = {
1.00198406028040E-004, 7.83611475491108E-005, 6.13689891868496E-005, 4.81280465299827E-005};
#define WV_PRESSURE 0.0627 /* water vapor pressure */
#define N2_IN_AIR 0.7902
#define DECO_STOPS_MULTIPLIER_MM 3000.0
#define GF_LOW_AT_MAXDEPTH 0

7
dive.h
View file

@ -11,6 +11,13 @@
#include <libxml/tree.h>
#include <openssl/sha.h>
#define O2_IN_AIR 0.20942
#define N2_IN_AIR 0.78084 // has been set to 0.7902 before to ignore other components of air
#define O2_DENSITY 1.429 // Gramm/Liter
#define N2_DENSITY 1.251
#define HE_DENSITY 0.1786
/*
* Some silly typedefs to make our units very explicit.
*

View file

@ -439,6 +439,8 @@ OPTIONCALLBACK(cylinder_toggle, prefs.visible_cols.cylinder)
OPTIONCALLBACK(po2_toggle, prefs.pp_graphs.po2)
OPTIONCALLBACK(pn2_toggle, prefs.pp_graphs.pn2)
OPTIONCALLBACK(phe_toggle, prefs.pp_graphs.phe)
OPTIONCALLBACK(mod_toggle, prefs.mod)
OPTIONCALLBACK(ead_toggle, prefs.ead)
OPTIONCALLBACK(red_ceiling_toggle, prefs.profile_red_ceiling)
OPTIONCALLBACK(calc_ceiling_toggle, prefs.profile_calc_ceiling)
OPTIONCALLBACK(calc_ceiling_3m_toggle, prefs.calc_ceiling_3m_incr)
@ -529,9 +531,9 @@ static void preferences_dialog(GtkWidget *w, gpointer data)
{
int result;
GtkWidget *dialog, *notebook, *font, *frame, *box, *vbox, *button, *xmlfile_button;
GtkWidget *entry_po2, *entry_pn2, *entry_phe, *entry_gflow, *entry_gfhigh;
GtkWidget *entry_po2, *entry_pn2, *entry_phe, *entry_mod, *entry_ead, *entry_gflow, *entry_gfhigh;
const char *current_default, *new_default;
char threshold_text[10], utf8_buf[128];
char threshold_text[10], mod_text[10], utf8_buf[128];
struct preferences oldprefs = prefs;
dialog = gtk_dialog_new_with_buttons(_("Preferences"),
@ -722,6 +724,31 @@ static void preferences_dialog(GtkWidget *w, gpointer data)
box = gtk_hbox_new(FALSE, 6);
gtk_container_add(GTK_CONTAINER(vbox), box);
button = gtk_check_button_new_with_label(_("Show MOD"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), prefs.mod);
gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6);
g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(mod_toggle), &entry_mod);
frame = gtk_frame_new(_("max ppO2"));
gtk_box_pack_start(GTK_BOX(box), frame, FALSE, FALSE, 6);
entry_mod = gtk_entry_new();
gtk_entry_set_max_length(GTK_ENTRY(entry_mod), 4);
snprintf(mod_text, sizeof(mod_text), "%.1f", prefs.mod_ppO2);
gtk_entry_set_text(GTK_ENTRY(entry_mod), mod_text);
gtk_widget_set_sensitive(entry_mod, prefs.mod);
gtk_container_add(GTK_CONTAINER(frame), entry_mod);
box = gtk_hbox_new(FALSE, 6);
gtk_container_add(GTK_CONTAINER(vbox), box);
button = gtk_check_button_new_with_label(_("Show EAD, END, EADD"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), prefs.ead);
gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6);
g_signal_connect(G_OBJECT(button), "toggled", G_CALLBACK(ead_toggle), NULL);
box = gtk_hbox_new(FALSE, 6);
gtk_container_add(GTK_CONTAINER(vbox), box);
button = gtk_check_button_new_with_label(_("Show dc reported ceiling in red"));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), prefs.profile_red_ceiling);
gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 6);
@ -766,7 +793,7 @@ static void preferences_dialog(GtkWidget *w, gpointer data)
gtk_widget_show_all(dialog);
result = gtk_dialog_run(GTK_DIALOG(dialog));
if (result == GTK_RESPONSE_ACCEPT) {
const char *po2_threshold_text, *pn2_threshold_text, *phe_threshold_text, *gflow_text, *gfhigh_text;
const char *po2_threshold_text, *pn2_threshold_text, *phe_threshold_text, *mod_text, *gflow_text, *gfhigh_text;
/* Make sure to flush any modified old dive data with old units */
update_dive(NULL);
@ -778,6 +805,8 @@ static void preferences_dialog(GtkWidget *w, gpointer data)
sscanf(pn2_threshold_text, "%lf", &prefs.pp_graphs.pn2_threshold);
phe_threshold_text = gtk_entry_get_text(GTK_ENTRY(entry_phe));
sscanf(phe_threshold_text, "%lf", &prefs.pp_graphs.phe_threshold);
mod_text = gtk_entry_get_text(GTK_ENTRY(entry_mod));
sscanf(mod_text, "%lf", &prefs.mod_ppO2);
gflow_text = gtk_entry_get_text(GTK_ENTRY(entry_gflow));
sscanf(gflow_text, "%lf", &prefs.gflow);
gfhigh_text = gtk_entry_get_text(GTK_ENTRY(entry_gfhigh));

3
main.c
View file

@ -27,6 +27,9 @@ struct preferences default_prefs = {
.pn2_threshold = 4.0,
.phe_threshold = 13.0,
},
.mod = FALSE,
.mod_ppO2 = 1.6,
.ead = FALSE,
.profile_red_ceiling = FALSE,
.profile_calc_ceiling = FALSE,
.calc_ceiling_3m_incr = FALSE,

3
pref.h
View file

@ -25,6 +25,9 @@ struct preferences {
struct units units;
visible_cols_t visible_cols;
partial_pressure_graphs_t pp_graphs;
gboolean mod;
double mod_ppO2;
gboolean ead;
gboolean profile_red_ceiling;
gboolean profile_calc_ceiling;
gboolean calc_ceiling_3m_incr;

10
prefs.c
View file

@ -85,6 +85,9 @@ void save_preferences(void)
SAVE_DOUBLE("pn2threshold", pp_graphs.pn2_threshold);
SAVE_DOUBLE("phethreshold", pp_graphs.phe_threshold);
SAVE_BOOL("mod", mod);
SAVE_DOUBLE("modppO2", mod_ppO2);
SAVE_BOOL("ead", ead);
SAVE_BOOL("redceiling", profile_red_ceiling);
SAVE_BOOL("calcceiling", profile_calc_ceiling);
SAVE_BOOL("calcceiling3m", calc_ceiling_3m_incr);
@ -149,6 +152,13 @@ void load_preferences(void)
sscanf(conf_value, "%lf", &prefs.pp_graphs.phe_threshold);
free((void *)conf_value);
}
GET_BOOL("mod", mod);
conf_value = subsurface_get_conf("modppO2");
if (conf_value) {
sscanf(conf_value, "%lf", &prefs.mod_ppO2);
free((void *)conf_value);
}
GET_BOOL("ead", ead);
GET_BOOL("redceiling", profile_red_ceiling);
GET_BOOL("calcceiling", profile_calc_ceiling);
GET_BOOL("calcceiling3m", calc_ceiling_3m_incr);

View file

@ -46,6 +46,7 @@ struct plot_data {
int cns;
int smoothed;
double po2, pn2, phe;
double mod, ead, end, eadd;
velocity_t velocity;
struct plot_data *min[3];
struct plot_data *max[3];
@ -1835,11 +1836,32 @@ static void calculate_deco_information(struct dive *dive, struct divecomputer *d
entry->phe = (amb_pressure - po2) * ratio;
entry->pn2 = amb_pressure - po2 - entry->phe;
entry->po2 = po2;
entry->ead = (entry->depth + 10000) *
(entry->po2+(amb_pressure-entry->po2)*(1-ratio))/amb_pressure - 10000;
entry->end = (entry->depth + 10000) *
(amb_pressure-entry->po2)*(1-ratio)/amb_pressure/N2_IN_AIR - 10000;
entry->eadd = (entry->depth + 10000) *
(entry->po2/amb_pressure * O2_DENSITY + entry->pn2/amb_pressure * N2_DENSITY +
entry->phe/amb_pressure * HE_DENSITY) /
(O2_IN_AIR * O2_DENSITY + N2_IN_AIR * N2_DENSITY) -10000;
} else {
entry->po2 = fo2 / 1000.0 * amb_pressure;
entry->phe = fhe / 1000.0 * amb_pressure;
entry->pn2 = (1000 - fo2 - fhe) / 1000.0 * amb_pressure;
entry->ead = (entry->depth + 10000) * (1000 - fhe) / 1000.0 - 10000;
entry->end = (entry->depth + 10000) * (1000 - fo2 - fhe) / 1000.0 / N2_IN_AIR - 10000;
entry->eadd = (entry->depth + 10000) * (fo2 * O2_DENSITY + (1-fo2-fhe) * N2_DENSITY + fhe * HE_DENSITY) / (O2_IN_AIR * O2_DENSITY + N2_IN_AIR * N2_DENSITY) -10000;
}
entry->mod = (prefs.mod_ppO2/fo2*1000 - 1) * 10000;
if(entry->mod <0)
entry->mod=0;
if(entry->ead <0)
entry->ead=0;
if(entry->end <0)
entry->end=0;
if(entry->eadd <0)
entry->eadd=0;
if (entry->po2 > pi->maxpp && prefs.pp_graphs.po2)
pi->maxpp = entry->po2;
if (entry->phe > pi->maxpp && prefs.pp_graphs.phe)
@ -2070,7 +2092,7 @@ void plot(struct graphics_context *gc, struct dive *dive, scale_mode_t scale)
static void plot_string(struct plot_data *entry, char *buf, size_t bufsize,
int depth, int pressure, int temp, gboolean has_ndl)
{
int pressurevalue;
int pressurevalue, mod, ead, end, eadd;
const char *depth_unit, *pressure_unit, *temp_unit;
char *buf2 = malloc(bufsize);
double depthvalue, tempvalue;
@ -2136,6 +2158,18 @@ static void plot_string(struct plot_data *entry, char *buf, size_t bufsize,
memcpy(buf2, buf, bufsize);
snprintf(buf, bufsize, "%s\npHe:%.2f", buf2, entry->phe);
}
if (prefs.mod) {
mod = (int)get_depth_units(entry->mod, NULL, &depth_unit);
memcpy(buf2, buf, bufsize);
snprintf(buf, bufsize, "%s\nMOD:%d%s", buf2, mod, depth_unit);
}
if (prefs.ead) {
ead = (int)get_depth_units(entry->ead, NULL, &depth_unit);
end = (int)get_depth_units(entry->end, NULL, &depth_unit);
eadd = (int)get_depth_units(entry->eadd, NULL, &depth_unit);
memcpy(buf2, buf, bufsize);
snprintf(buf, bufsize, "%s\nEAD:%d%s\nEND:%d%s\nEADD:%d%s", buf2, ead, depth_unit, end, depth_unit, eadd, depth_unit);
}
free(buf2);
}