mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Use get_o2() and get_he() instead of accessing permilles directly
This gets rid of problems with air. Signed-off-by: Robert C. Helling <helling@atdotde.de> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
c86d055db7
commit
04b6b6aaf9
5 changed files with 53 additions and 40 deletions
4
dive.c
4
dive.c
|
@ -488,7 +488,7 @@ static int same_rounded_pressure(pressure_t a, pressure_t b)
|
||||||
return abs(a.mbar - b.mbar) <= 500;
|
return abs(a.mbar - b.mbar) <= 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sanitize_gasmix(struct gasmix *mix)
|
void sanitize_gasmix(struct gasmix *mix)
|
||||||
{
|
{
|
||||||
unsigned int o2, he;
|
unsigned int o2, he;
|
||||||
|
|
||||||
|
@ -1218,7 +1218,7 @@ static void merge_weightsystem_info(weightsystem_t *res, weightsystem_t *a, weig
|
||||||
*res = *a;
|
*res = *a;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gasmix_distance(const struct gasmix *a, const struct gasmix *b)
|
int gasmix_distance(const struct gasmix *a, const struct gasmix *b)
|
||||||
{
|
{
|
||||||
int a_o2 = get_o2(a), b_o2 = get_o2(b);
|
int a_o2 = get_o2(a), b_o2 = get_o2(b);
|
||||||
int a_he = get_he(a), b_he = get_he(b);
|
int a_he = get_he(a), b_he = get_he(b);
|
||||||
|
|
3
dive.h
3
dive.h
|
@ -91,6 +91,9 @@ static inline int get_he(const struct gasmix *mix)
|
||||||
return mix->he.permille;
|
return mix->he.permille;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void sanitize_gasmix(struct gasmix *mix);
|
||||||
|
extern int gasmix_distance(const struct gasmix *a, const struct gasmix *b);
|
||||||
|
|
||||||
static inline bool is_air(int o2, int he)
|
static inline bool is_air(int o2, int he)
|
||||||
{
|
{
|
||||||
return (he == 0) && (o2 == 0 || ((o2 >= O2_IN_AIR - 1) && (o2 <= O2_IN_AIR + 1)));
|
return (he == 0) && (o2 == 0 || ((o2 >= O2_IN_AIR - 1) && (o2 <= O2_IN_AIR + 1)));
|
||||||
|
|
54
planner.c
54
planner.c
|
@ -72,23 +72,19 @@ void get_gas_from_events(struct divecomputer *dc, int time, int *o2, int *he)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* simple helper function to compare two permille values with
|
|
||||||
* (rounded) percent granularity */
|
|
||||||
static inline bool match_percent(int a, int b)
|
|
||||||
{
|
|
||||||
return (a + 5) / 10 == (b + 5) / 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
int get_gasidx(struct dive *dive, int o2, int he)
|
int get_gasidx(struct dive *dive, int o2, int he)
|
||||||
{
|
{
|
||||||
int gasidx = -1;
|
int gasidx = -1;
|
||||||
|
struct gasmix mix;
|
||||||
|
|
||||||
|
mix.o2.permille = o2;
|
||||||
|
mix.he.permille = he;
|
||||||
|
|
||||||
/* we treat air as 0/0 because it is special */
|
/* we treat air as 0/0 because it is special */
|
||||||
if (is_air(o2, he))
|
//if (is_air(o2, he))
|
||||||
o2 = 0;
|
// o2 = 0;
|
||||||
while (++gasidx < MAX_CYLINDERS)
|
while (++gasidx < MAX_CYLINDERS)
|
||||||
if (match_percent(dive->cylinder[gasidx].gasmix.o2.permille, o2) &&
|
if (gasmix_distance(&dive->cylinder[gasidx].gasmix, &mix) < 200)
|
||||||
match_percent(dive->cylinder[gasidx].gasmix.he.permille, he))
|
|
||||||
return gasidx;
|
return gasidx;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -138,8 +134,8 @@ double tissue_at_end(struct dive *dive, char **cached_datap)
|
||||||
psample = sample = dc->sample;
|
psample = sample = dc->sample;
|
||||||
lastdepth = t0 = 0;
|
lastdepth = t0 = 0;
|
||||||
/* we always start with gas 0 (unless an event tells us otherwise) */
|
/* we always start with gas 0 (unless an event tells us otherwise) */
|
||||||
o2 = dive->cylinder[0].gasmix.o2.permille;
|
o2 = get_o2(&dive->cylinder[0].gasmix);
|
||||||
he = dive->cylinder[0].gasmix.he.permille;
|
he = get_he(&dive->cylinder[0].gasmix);
|
||||||
for (i = 0; i < dc->samples; i++, sample++) {
|
for (i = 0; i < dc->samples; i++, sample++) {
|
||||||
t1 = sample->time.seconds;
|
t1 = sample->time.seconds;
|
||||||
get_gas_from_events(&dive->dc, t0, &o2, &he);
|
get_gas_from_events(&dive->dc, t0, &o2, &he);
|
||||||
|
@ -189,14 +185,17 @@ static int add_gas(struct dive *dive, int o2, int he)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct gasmix *mix;
|
struct gasmix *mix;
|
||||||
|
struct gasmix mix_in;
|
||||||
cylinder_t *cyl;
|
cylinder_t *cyl;
|
||||||
|
|
||||||
|
mix_in.o2.permille = o2;
|
||||||
|
mix_in.he.permille = he;
|
||||||
for (i = 0; i < MAX_CYLINDERS; i++) {
|
for (i = 0; i < MAX_CYLINDERS; i++) {
|
||||||
cyl = dive->cylinder + i;
|
cyl = dive->cylinder + i;
|
||||||
mix = &cyl->gasmix;
|
mix = &cyl->gasmix;
|
||||||
if (cylinder_nodata(cyl))
|
if (cylinder_nodata(cyl))
|
||||||
break;
|
break;
|
||||||
if (match_percent(o2, mix->o2.permille) && match_percent(he, mix->he.permille))
|
if (gasmix_distance(mix, &mix_in) < 200)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
if (i == MAX_CYLINDERS) {
|
if (i == MAX_CYLINDERS) {
|
||||||
|
@ -206,6 +205,7 @@ static int add_gas(struct dive *dive, int o2, int he)
|
||||||
fill_default_cylinder(cyl);
|
fill_default_cylinder(cyl);
|
||||||
mix->o2.permille = o2;
|
mix->o2.permille = o2;
|
||||||
mix->he.permille = he;
|
mix->he.permille = he;
|
||||||
|
sanitize_gasmix(mix);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,6 +388,7 @@ static struct gaschanges *analyze_gaslist(struct diveplan *diveplan, struct dive
|
||||||
int nr = 0;
|
int nr = 0;
|
||||||
struct gaschanges *gaschanges = NULL;
|
struct gaschanges *gaschanges = NULL;
|
||||||
struct divedatapoint *dp = diveplan->dp;
|
struct divedatapoint *dp = diveplan->dp;
|
||||||
|
struct gasmix mix;
|
||||||
|
|
||||||
while (dp) {
|
while (dp) {
|
||||||
if (dp->time == 0 && dp->depth <= depth) {
|
if (dp->time == 0 && dp->depth <= depth) {
|
||||||
|
@ -403,9 +404,10 @@ static struct gaschanges *analyze_gaslist(struct diveplan *diveplan, struct dive
|
||||||
}
|
}
|
||||||
gaschanges[i].depth = dp->depth;
|
gaschanges[i].depth = dp->depth;
|
||||||
gaschanges[i].gasidx = -1;
|
gaschanges[i].gasidx = -1;
|
||||||
|
mix.o2.permille = dp->o2;
|
||||||
|
mix.he.permille = dp->he;
|
||||||
do {
|
do {
|
||||||
if (dive->cylinder[j].gasmix.o2.permille == dp->o2 &&
|
if (!gasmix_distance(&dive->cylinder[j].gasmix, &mix)) {
|
||||||
dive->cylinder[j].gasmix.he.permille == dp->he) {
|
|
||||||
gaschanges[i].gasidx = j;
|
gaschanges[i].gasidx = j;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -419,8 +421,8 @@ static struct gaschanges *analyze_gaslist(struct diveplan *diveplan, struct dive
|
||||||
#if DEBUG_PLAN & 16
|
#if DEBUG_PLAN & 16
|
||||||
for (nr = 0; nr < *gaschangenr; nr++)
|
for (nr = 0; nr < *gaschangenr; nr++)
|
||||||
printf("gaschange nr %d: @ %5.2lfm gasidx %d (%d/%d)\n", nr, gaschanges[nr].depth / 1000.0,
|
printf("gaschange nr %d: @ %5.2lfm gasidx %d (%d/%d)\n", nr, gaschanges[nr].depth / 1000.0,
|
||||||
gaschanges[nr].gasidx, (dive->cylinder[gaschanges[nr].gasidx].gasmix.o2.permille + 5) / 10,
|
gaschanges[nr].gasidx, (get_o2(&dive->cylinder[gaschanges[nr].gasidx].gasmix) + 5) / 10,
|
||||||
(dive->cylinder[gaschanges[nr].gasidx].gasmix.he.permille + 5) / 10);
|
(get_he(&dive->cylinder[gaschanges[nr].gasidx].gasmix) + 5) / 10);
|
||||||
#endif
|
#endif
|
||||||
return gaschanges;
|
return gaschanges;
|
||||||
}
|
}
|
||||||
|
@ -493,8 +495,8 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive)
|
||||||
snprintf(buffer, sizeof(buffer), translate("gettextFromC", "%s\nSubsurface dive plan\nbased on GFlow = %.0f and GFhigh = %.0f\n\n"),
|
snprintf(buffer, sizeof(buffer), translate("gettextFromC", "%s\nSubsurface dive plan\nbased on GFlow = %.0f and GFhigh = %.0f\n\n"),
|
||||||
disclaimer, plangflow * 100, plangfhigh * 100);
|
disclaimer, plangflow * 100, plangfhigh * 100);
|
||||||
/* we start with gas 0, then check if that was changed */
|
/* we start with gas 0, then check if that was changed */
|
||||||
o2 = dive->cylinder[0].gasmix.o2.permille;
|
o2 = get_o2(&dive->cylinder[0].gasmix);
|
||||||
he = dive->cylinder[0].gasmix.he.permille;
|
he = get_he(&dive->cylinder[0].gasmix);
|
||||||
do {
|
do {
|
||||||
const char *depth_unit;
|
const char *depth_unit;
|
||||||
char gas[64];
|
char gas[64];
|
||||||
|
@ -568,8 +570,8 @@ static void add_plan_to_notes(struct diveplan *diveplan, struct dive *dive)
|
||||||
continue;
|
continue;
|
||||||
len = strlen(buffer);
|
len = strlen(buffer);
|
||||||
volume = get_volume_units(consumption[gasidx], NULL, &unit);
|
volume = get_volume_units(consumption[gasidx], NULL, &unit);
|
||||||
get_gas_string(dive->cylinder[gasidx].gasmix.o2.permille,
|
get_gas_string(get_o2(&dive->cylinder[gasidx].gasmix),
|
||||||
dive->cylinder[gasidx].gasmix.he.permille, gas, sizeof(gas));
|
get_he(&dive->cylinder[gasidx].gasmix), gas, sizeof(gas));
|
||||||
snprintf(buffer + len, sizeof(buffer) - len, translate("gettextFromC", "%.0f%s of %s\n"), volume, unit, gas);
|
snprintf(buffer + len, sizeof(buffer) - len, translate("gettextFromC", "%.0f%s of %s\n"), volume, unit, gas);
|
||||||
}
|
}
|
||||||
dive->notes = strdup(buffer);
|
dive->notes = strdup(buffer);
|
||||||
|
@ -625,8 +627,8 @@ void plan(struct diveplan *diveplan, char **cached_datap, struct dive **divep, b
|
||||||
/* Let's start at the last 'sample', i.e. the last manually entered waypoint. */
|
/* Let's start at the last 'sample', i.e. the last manually entered waypoint. */
|
||||||
sample = &dive->dc.sample[dive->dc.samples - 1];
|
sample = &dive->dc.sample[dive->dc.samples - 1];
|
||||||
/* we start with gas 0, then check if that was changed */
|
/* we start with gas 0, then check if that was changed */
|
||||||
o2 = dive->cylinder[0].gasmix.o2.permille;
|
o2 = get_o2(&dive->cylinder[0].gasmix);
|
||||||
he = dive->cylinder[0].gasmix.he.permille;
|
he = get_he(&dive->cylinder[0].gasmix);
|
||||||
get_gas_from_events(&dive->dc, sample->time.seconds, &o2, &he);
|
get_gas_from_events(&dive->dc, sample->time.seconds, &o2, &he);
|
||||||
po2 = dive->dc.sample[dive->dc.samples - 1].po2;
|
po2 = dive->dc.sample[dive->dc.samples - 1].po2;
|
||||||
if ((current_cylinder = get_gasidx(dive, o2, he)) == -1) {
|
if ((current_cylinder = get_gasidx(dive, o2, he)) == -1) {
|
||||||
|
@ -704,8 +706,8 @@ void plan(struct diveplan *diveplan, char **cached_datap, struct dive **divep, b
|
||||||
stopping = true;
|
stopping = true;
|
||||||
|
|
||||||
current_cylinder = gaschanges[gi].gasidx;
|
current_cylinder = gaschanges[gi].gasidx;
|
||||||
o2 = dive->cylinder[current_cylinder].gasmix.o2.permille;
|
o2 = get_o2(&dive->cylinder[current_cylinder].gasmix);
|
||||||
he = dive->cylinder[current_cylinder].gasmix.he.permille;
|
he = get_he(&dive->cylinder[current_cylinder].gasmix);
|
||||||
#if DEBUG_PLAN & 16
|
#if DEBUG_PLAN & 16
|
||||||
printf("switch to gas %d (%d/%d) @ %5.2lfm\n", gaschanges[gi].gasidx,
|
printf("switch to gas %d (%d/%d) @ %5.2lfm\n", gaschanges[gi].gasidx,
|
||||||
(o2 + 5) / 10, (he + 5) / 10, gaschanges[gi].depth / 1000.0);
|
(o2 + 5) / 10, (he + 5) / 10, gaschanges[gi].depth / 1000.0);
|
||||||
|
|
|
@ -414,8 +414,8 @@ void DivePlannerPointsModel::loadFromDive(dive *d)
|
||||||
CylindersModel::instance()->setDive(stagingDive);
|
CylindersModel::instance()->setDive(stagingDive);
|
||||||
int lasttime = 0;
|
int lasttime = 0;
|
||||||
// we start with the first gas and see if it was changed
|
// we start with the first gas and see if it was changed
|
||||||
int o2 = backupDive.cylinder[0].gasmix.o2.permille;
|
int o2 = get_o2(&backupDive.cylinder[0].gasmix);
|
||||||
int he = backupDive.cylinder[0].gasmix.he.permille;
|
int he = get_he(&backupDive.cylinder[0].gasmix);
|
||||||
for (int i = 0; i < backupDive.dc.samples - 1; i++) {
|
for (int i = 0; i < backupDive.dc.samples - 1; i++) {
|
||||||
const sample &s = backupDive.dc.sample[i];
|
const sample &s = backupDive.dc.sample[i];
|
||||||
if (s.time.seconds == 0)
|
if (s.time.seconds == 0)
|
||||||
|
@ -453,7 +453,7 @@ QStringList &DivePlannerPointsModel::getGasList()
|
||||||
cylinder_t *cyl = &activeDive->cylinder[i];
|
cylinder_t *cyl = &activeDive->cylinder[i];
|
||||||
if (cylinder_nodata(cyl))
|
if (cylinder_nodata(cyl))
|
||||||
break;
|
break;
|
||||||
list.push_back(gasToStr(cyl->gasmix.o2.permille, cyl->gasmix.he.permille));
|
list.push_back(gasToStr(get_o2(&cyl->gasmix), get_he(&cyl->gasmix)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
|
@ -1246,6 +1246,12 @@ bool divePointsLessThan(const divedatapoint &p1, const divedatapoint &p2)
|
||||||
|
|
||||||
bool DivePlannerPointsModel::addGas(int o2, int he)
|
bool DivePlannerPointsModel::addGas(int o2, int he)
|
||||||
{
|
{
|
||||||
|
struct gasmix mix;
|
||||||
|
|
||||||
|
mix.o2.permille = o2;
|
||||||
|
mix.he.permille = he;
|
||||||
|
sanitize_gasmix(&mix);
|
||||||
|
|
||||||
if (is_air(o2, he))
|
if (is_air(o2, he))
|
||||||
o2 = 0;
|
o2 = 0;
|
||||||
|
|
||||||
|
@ -1255,16 +1261,14 @@ bool DivePlannerPointsModel::addGas(int o2, int he)
|
||||||
fill_default_cylinder(cyl);
|
fill_default_cylinder(cyl);
|
||||||
cyl->gasmix.o2.permille = o2;
|
cyl->gasmix.o2.permille = o2;
|
||||||
cyl->gasmix.he.permille = he;
|
cyl->gasmix.he.permille = he;
|
||||||
|
sanitize_gasmix(&cyl->gasmix);
|
||||||
/* The depth to change to that gas is given by the depth where its pO2 is 1.6 bar.
|
/* The depth to change to that gas is given by the depth where its pO2 is 1.6 bar.
|
||||||
* The user should be able to change this depth manually. */
|
* The user should be able to change this depth manually. */
|
||||||
if (!o2)
|
cyl->depth.mm = 1600 * 1000 / get_o2(&mix) * 10 - 10000;
|
||||||
cyl->depth.mm = 1600 * 1000 / O2_IN_AIR * 10 - 10000;
|
|
||||||
else
|
|
||||||
cyl->depth.mm = 1600 * 1000 / o2 * 10 - 10000;
|
|
||||||
CylindersModel::instance()->setDive(stagingDive);
|
CylindersModel::instance()->setDive(stagingDive);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (cyl->gasmix.o2.permille == o2 && cyl->gasmix.he.permille == he)
|
if (!gasmix_distance(&cyl->gasmix, &mix))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
qDebug("too many gases");
|
qDebug("too many gases");
|
||||||
|
@ -1299,8 +1303,8 @@ int DivePlannerPointsModel::addStop(int milimeters, int seconds, int o2, int he,
|
||||||
//Default to the first defined gas, if we got one.
|
//Default to the first defined gas, if we got one.
|
||||||
cylinder_t *cyl = &stagingDive->cylinder[0];
|
cylinder_t *cyl = &stagingDive->cylinder[0];
|
||||||
if (cyl) {
|
if (cyl) {
|
||||||
o2 = cyl->gasmix.o2.permille;
|
o2 = get_o2(&cyl->gasmix);
|
||||||
he = cyl->gasmix.he.permille;
|
he = get_he(&cyl->gasmix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (o2 != -1)
|
if (o2 != -1)
|
||||||
|
@ -1420,7 +1424,7 @@ QVector<QPair<int, int> > DivePlannerPointsModel::collectGases(struct dive *d)
|
||||||
for (int i = 0; i < MAX_CYLINDERS; i++) {
|
for (int i = 0; i < MAX_CYLINDERS; i++) {
|
||||||
cylinder_t *cyl = &d->cylinder[i];
|
cylinder_t *cyl = &d->cylinder[i];
|
||||||
if (!cylinder_nodata(cyl))
|
if (!cylinder_nodata(cyl))
|
||||||
l.push_back(qMakePair(cyl->gasmix.o2.permille, cyl->gasmix.he.permille));
|
l.push_back(qMakePair(get_o2(&cyl->gasmix), get_he(&cyl->gasmix)));
|
||||||
}
|
}
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
@ -1520,7 +1524,7 @@ void DivePlannerPointsModel::createTemporaryPlan()
|
||||||
for (int i = 0; i < MAX_CYLINDERS; i++) {
|
for (int i = 0; i < MAX_CYLINDERS; i++) {
|
||||||
cylinder_t *cyl = &stagingDive->cylinder[i];
|
cylinder_t *cyl = &stagingDive->cylinder[i];
|
||||||
if (cyl->depth.mm) {
|
if (cyl->depth.mm) {
|
||||||
dp = create_dp(0, cyl->depth.mm, cyl->gasmix.o2.permille, cyl->gasmix.he.permille, 0);
|
dp = create_dp(0, cyl->depth.mm, get_o2(&cyl->gasmix), get_he(&cyl->gasmix), 0);
|
||||||
if (diveplan.dp) {
|
if (diveplan.dp) {
|
||||||
dp->next = diveplan.dp->next;
|
dp->next = diveplan.dp->next;
|
||||||
diveplan.dp->next = dp;
|
diveplan.dp->next = dp;
|
||||||
|
|
|
@ -253,6 +253,10 @@ bool CylindersModel::setData(const QModelIndex &index, const QVariant &value, in
|
||||||
case O2:
|
case O2:
|
||||||
if (CHANGED()) {
|
if (CHANGED()) {
|
||||||
cyl->gasmix.o2 = string_to_fraction(vString.toUtf8().data());
|
cyl->gasmix.o2 = string_to_fraction(vString.toUtf8().data());
|
||||||
|
if (!cyl->gasmix.o2.permille) {
|
||||||
|
cyl->gasmix.o2.permille = 210;
|
||||||
|
cyl->gasmix.he.permille = 0;
|
||||||
|
}
|
||||||
cyl->depth.mm = 1600 * 1000 / cyl->gasmix.o2.permille * 10 - 10000;
|
cyl->depth.mm = 1600 * 1000 / cyl->gasmix.o2.permille * 10 - 10000;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue