mirror of
https://github.com/subsurface/subsurface.git
synced 2025-02-19 22:16:15 +00:00
Profile: Fix the Initial Gasmix.
Fix the initial gasmix that is shown in the tank bar of the profile. Also add a meaningful gas name for gases with negative values for percentages. @bstoeger: This is a side effect of the `event_loop` functionality introduced as part of #4198. In the case of an `event_loop("gasmix")` this does not take into account the edge case where there is no gaschange event at the very beginning of the dive, and the first gasmix is implicitly used as the starting gasmix. This happens for planned and manually added dives, but also for some dive computers. We are using the same kind of loop in a number of other places in `core/profile.cpp`, `core/dive.cpp`, `core/gaspressures.cpp`, and `profile-widget/tankitem.cpp`, and I am wondering if we should be converting these to use `gasmix_loop` instead to avoid being bit by this special case? Signed-off-by: Michael Keller <github@ike.ch>
This commit is contained in:
parent
38fe08e5e1
commit
db516b6d4e
9 changed files with 171 additions and 140 deletions
206
core/dive.cpp
206
core/dive.cpp
|
@ -354,17 +354,10 @@ static bool has_unknown_used_cylinders(const struct dive &dive, const struct div
|
|||
}
|
||||
|
||||
/* We know about the explicit first cylinder (or first) */
|
||||
idx = dive.explicit_first_cylinder(dc);
|
||||
if (idx >= 0 && used_and_unknown[idx]) {
|
||||
used_and_unknown[idx] = false;
|
||||
num--;
|
||||
}
|
||||
|
||||
/* And we have possible switches to other gases */
|
||||
event_loop loop("gaschange");
|
||||
const struct event *ev;
|
||||
while ((ev = loop.next(*dc)) != nullptr && num > 0) {
|
||||
idx = dive.get_cylinder_index(*ev);
|
||||
gasmix_loop loop(dive, *dc);
|
||||
while (loop.has_next() && num > 0) {
|
||||
idx = loop.next_cylinder_index().first;
|
||||
if (idx >= 0 && used_and_unknown[idx]) {
|
||||
used_and_unknown[idx] = false;
|
||||
num--;
|
||||
|
@ -376,9 +369,6 @@ static bool has_unknown_used_cylinders(const struct dive &dive, const struct div
|
|||
|
||||
void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, int *mean, int *duration)
|
||||
{
|
||||
int32_t lasttime = 0;
|
||||
int lastdepth = 0;
|
||||
int idx = 0;
|
||||
int num_used_cylinders;
|
||||
|
||||
if (dive->cylinders.empty())
|
||||
|
@ -420,35 +410,41 @@ void per_cylinder_mean_depth(const struct dive *dive, struct divecomputer *dc, i
|
|||
}
|
||||
if (dc->samples.empty())
|
||||
fake_dc(dc);
|
||||
event_loop loop("gaschange");
|
||||
const struct event *ev = loop.next(*dc);
|
||||
|
||||
gasmix_loop loop(*dive, *dc);
|
||||
std::vector<int> depthtime(dive->cylinders.size(), 0);
|
||||
int lasttime = 0;
|
||||
int lastdepth = 0;
|
||||
int last_cylinder_index = -1;
|
||||
std::pair<int, int> gaschange_event;
|
||||
for (auto it = dc->samples.begin(); it != dc->samples.end(); ++it) {
|
||||
int32_t time = it->time.seconds;
|
||||
int depth = it->depth.mm;
|
||||
|
||||
/* Make sure to move the event past 'lasttime' */
|
||||
while (ev && lasttime >= ev->time.seconds) {
|
||||
idx = dive->get_cylinder_index(*ev);
|
||||
ev = loop.next(*dc);
|
||||
gaschange_event = loop.cylinder_index_at(lasttime);
|
||||
|
||||
/* Do we need to fake a midway sample? */
|
||||
if (last_cylinder_index >= 0 && last_cylinder_index != gaschange_event.first) {
|
||||
int newdepth = interpolate(lastdepth, depth, gaschange_event.second - lasttime, time - lasttime);
|
||||
if (newdepth > SURFACE_THRESHOLD || lastdepth > SURFACE_THRESHOLD) {
|
||||
duration[gaschange_event.first] += gaschange_event.second - lasttime;
|
||||
depthtime[gaschange_event.first] += (gaschange_event.second - lasttime) * (newdepth + lastdepth) / 2;
|
||||
}
|
||||
|
||||
lasttime = gaschange_event.second;
|
||||
lastdepth = newdepth;
|
||||
}
|
||||
|
||||
/* Do we need to fake a midway sample at an event? */
|
||||
if (ev && it != dc->samples.begin() && time > ev->time.seconds) {
|
||||
int newtime = ev->time.seconds;
|
||||
int newdepth = interpolate(lastdepth, depth, newtime - lasttime, time - lasttime);
|
||||
|
||||
time = newtime;
|
||||
depth = newdepth;
|
||||
--it;
|
||||
}
|
||||
/* We ignore segments at the surface */
|
||||
if (depth > SURFACE_THRESHOLD || lastdepth > SURFACE_THRESHOLD) {
|
||||
duration[idx] += time - lasttime;
|
||||
depthtime[idx] += (time - lasttime) * (depth + lastdepth) / 2;
|
||||
duration[gaschange_event.first] += time - lasttime;
|
||||
depthtime[gaschange_event.first] += (time - lasttime) * (depth + lastdepth) / 2;
|
||||
}
|
||||
|
||||
lastdepth = depth;
|
||||
lasttime = time;
|
||||
last_cylinder_index = gaschange_event.first;
|
||||
}
|
||||
for (size_t i = 0; i < dive->cylinders.size(); i++) {
|
||||
if (duration[i])
|
||||
|
@ -476,27 +472,6 @@ static int same_rounded_pressure(pressure_t a, pressure_t b)
|
|||
return abs(a.mbar - b.mbar) <= 500;
|
||||
}
|
||||
|
||||
/* Some dive computers (Cobalt) don't start the dive with cylinder 0 but explicitly
|
||||
* tell us what the first gas is with a gas change event in the first sample.
|
||||
* Sneakily we'll use a return value of 0 (or FALSE) when there is no explicit
|
||||
* first cylinder - in which case cylinder 0 is indeed the first cylinder.
|
||||
* We likewise return 0 if the event concerns a cylinder that doesn't exist.
|
||||
* If the dive has no cylinders, -1 is returned. */
|
||||
int dive::explicit_first_cylinder(const struct divecomputer *dc) const
|
||||
{
|
||||
int res = 0;
|
||||
if (cylinders.empty())
|
||||
return -1;
|
||||
if (dc) {
|
||||
const struct event *ev = get_first_event(*dc, "gaschange");
|
||||
if (ev && ((!dc->samples.empty() && ev->time.seconds == dc->samples[0].time.seconds) || ev->time.seconds <= 1))
|
||||
res = get_cylinder_index(*ev);
|
||||
else if (dc->divemode == CCR)
|
||||
res = std::max(get_cylinder_idx_by_use(*this, DILUENT), res);
|
||||
}
|
||||
return static_cast<size_t>(res) < cylinders.size() ? res : 0;
|
||||
}
|
||||
|
||||
static double calculate_depth_to_mbarf(int depth, pressure_t surface_pressure, int salinity);
|
||||
|
||||
/* this gets called when the dive mode has changed (so OC vs. CC)
|
||||
|
@ -518,17 +493,9 @@ void update_setpoint_events(const struct dive *dive, struct divecomputer *dc)
|
|||
// by mistake when it's actually CCR is _bad_
|
||||
// So we make sure, this comes from a Predator or Petrel and we only remove
|
||||
// pO2 values we would have computed anyway.
|
||||
event_loop loop("gaschange");
|
||||
const struct event *ev = loop.next(*dc);
|
||||
struct gasmix gasmix = dive->get_gasmix_from_event(*ev);
|
||||
const struct event *next = loop.next(*dc);
|
||||
|
||||
gasmix_loop loop(*dive, *dc);
|
||||
for (auto &sample: dc->samples) {
|
||||
if (next && sample.time.seconds >= next->time.seconds) {
|
||||
ev = next;
|
||||
gasmix = dive->get_gasmix_from_event(*ev);
|
||||
next = loop.next(*dc);
|
||||
}
|
||||
struct gasmix gasmix = loop.at(sample.time.seconds).first;
|
||||
gas_pressures pressures = fill_pressures(lrint(calculate_depth_to_mbarf(sample.depth.mm, dc->surface_pressure, 0)), gasmix ,0, dc->divemode);
|
||||
if (abs(sample.setpoint.mbar - (int)(1000 * pressures.o2)) <= 50)
|
||||
sample.setpoint.mbar = 0;
|
||||
|
@ -1408,11 +1375,12 @@ static void add_initial_gaschange(struct dive &dive, struct divecomputer &dc, in
|
|||
{
|
||||
/* if there is a gaschange event up to 30 sec after the initial event,
|
||||
* refrain from adding the initial event */
|
||||
event_loop loop("gaschange");
|
||||
while(auto ev = loop.next(dc)) {
|
||||
if (ev->time.seconds > offset + 30)
|
||||
gasmix_loop loop(dive, dc);
|
||||
while (loop.has_next()) {
|
||||
int time = loop.next().second;
|
||||
if (time > offset + 30)
|
||||
break;
|
||||
else if (ev->time.seconds > offset)
|
||||
else if (time > offset)
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2586,36 +2554,95 @@ location_t dive::get_gps_location() const
|
|||
}
|
||||
|
||||
gasmix_loop::gasmix_loop(const struct dive &d, const struct divecomputer &dc) :
|
||||
dive(d), dc(dc), last(gasmix_air), loop("gaschange")
|
||||
dive(d), dc(dc), first_run(true), loop("gaschange")
|
||||
{
|
||||
/* if there is no cylinder, return air */
|
||||
if (dive.cylinders.empty())
|
||||
return;
|
||||
|
||||
/* on first invocation, get initial gas mix and first event (if any) */
|
||||
int cyl = dive.explicit_first_cylinder(&dc);
|
||||
last = dive.get_cylinder(cyl)->gasmix;
|
||||
ev = loop.next(dc);
|
||||
}
|
||||
|
||||
gasmix gasmix_loop::next(int time)
|
||||
{
|
||||
/* if there is no cylinder, return air */
|
||||
if (dive.cylinders.empty())
|
||||
return last;
|
||||
/* Some dive computers (Cobalt) don't start the dive with cylinder 0 but explicitly
|
||||
* tell us what the first gas is with a gas change event in the first sample.
|
||||
* Sneakily we'll use a return value of 0 (or FALSE) when there is no explicit
|
||||
* first cylinder - in which case cylinder 0 is indeed the first cylinder.
|
||||
* We likewise return 0 if the event concerns a cylinder that doesn't exist.
|
||||
* If the dive has no cylinders, -1 is returned. */
|
||||
|
||||
while (ev && ev->time.seconds <= time) {
|
||||
last = dive.get_gasmix_from_event(*ev);
|
||||
ev = loop.next(dc);
|
||||
std::pair<int, int> gasmix_loop::next_cylinder_index()
|
||||
{
|
||||
if (dive.cylinders.empty())
|
||||
return std::make_pair(-1, INT_MAX);
|
||||
|
||||
if (first_run) {
|
||||
next_event = loop.next(dc);
|
||||
last_cylinder_index = 0; // default to first cylinder
|
||||
last_time = 0;
|
||||
if (next_event && ((!dc.samples.empty() && next_event->time.seconds == dc.samples[0].time.seconds) || next_event->time.seconds <= 1)) {
|
||||
last_cylinder_index = dive.get_cylinder_index(*next_event);
|
||||
last_time = next_event->time.seconds;
|
||||
next_event = loop.next(dc);
|
||||
} else if (dc.divemode == CCR) {
|
||||
last_cylinder_index = std::max(get_cylinder_idx_by_use(dive, DILUENT), last_cylinder_index);
|
||||
}
|
||||
|
||||
first_run = false;
|
||||
} else {
|
||||
if (next_event) {
|
||||
last_cylinder_index = dive.get_cylinder_index(*next_event);
|
||||
last_time = next_event->time.seconds;
|
||||
next_event = loop.next(dc);
|
||||
} else {
|
||||
last_cylinder_index = -1;
|
||||
last_time = INT_MAX;
|
||||
}
|
||||
}
|
||||
return last;
|
||||
|
||||
return std::make_pair(last_cylinder_index, last_time);
|
||||
}
|
||||
|
||||
std::pair<gasmix, int> gasmix_loop::next()
|
||||
{
|
||||
if (first_run && dive.cylinders.empty()) {
|
||||
first_run = false;
|
||||
|
||||
// return one cylinder of air if we don't have any cylinders
|
||||
return std::make_pair(gasmix_air, 0);
|
||||
}
|
||||
|
||||
next_cylinder_index();
|
||||
|
||||
return std::make_pair(last_cylinder_index < 0 ? gasmix_invalid : dive.get_cylinder(last_cylinder_index)->gasmix, last_time);
|
||||
}
|
||||
|
||||
std::pair<int, int> gasmix_loop::cylinder_index_at(int time)
|
||||
{
|
||||
if (first_run)
|
||||
next_cylinder_index();
|
||||
|
||||
while (has_next() && next_event->time.seconds <= time)
|
||||
next_cylinder_index();
|
||||
|
||||
return std::make_pair(last_cylinder_index, last_time);
|
||||
}
|
||||
|
||||
std::pair<gasmix, int> gasmix_loop::at(int time)
|
||||
{
|
||||
if (dive.cylinders.empty())
|
||||
// return air if we don't have any cylinders
|
||||
return std::make_pair(gasmix_air, 0);
|
||||
|
||||
cylinder_index_at(time);
|
||||
|
||||
return std::make_pair(last_cylinder_index < 0 ? gasmix_invalid : dive.get_cylinder(last_cylinder_index)->gasmix, last_time);
|
||||
}
|
||||
|
||||
bool gasmix_loop::has_next() const
|
||||
{
|
||||
return first_run || (!dive.cylinders.empty() && next_event);
|
||||
}
|
||||
|
||||
/* get the gas at a certain time during the dive */
|
||||
/* If there is a gasswitch at that time, it returns the new gasmix */
|
||||
struct gasmix dive::get_gasmix_at_time(const struct divecomputer &dc, duration_t time) const
|
||||
{
|
||||
return gasmix_loop(*this, dc).next(time.seconds);
|
||||
return gasmix_loop(*this, dc).at(time.seconds).first;
|
||||
}
|
||||
|
||||
/* Does that cylinder have any pressure readings? */
|
||||
|
@ -2710,16 +2737,13 @@ dive::get_maximal_gas_result dive::get_maximal_gas() const
|
|||
|
||||
bool dive::has_gaschange_event(const struct divecomputer *dc, int idx) const
|
||||
{
|
||||
bool first_gas_explicit = false;
|
||||
event_loop loop("gaschange");
|
||||
while (auto event = loop.next(*dc)) {
|
||||
if (!dc->samples.empty() && (event->time.seconds == 0 ||
|
||||
(dc->samples[0].time.seconds == event->time.seconds)))
|
||||
first_gas_explicit = true;
|
||||
if (get_cylinder_index(*event) == idx)
|
||||
gasmix_loop loop(*this, *dc);
|
||||
while (loop.has_next()) {
|
||||
if (loop.next_cylinder_index().first == idx)
|
||||
return true;
|
||||
}
|
||||
return !first_gas_explicit && idx == 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dive::is_cylinder_used(int idx) const
|
||||
|
|
|
@ -103,7 +103,6 @@ struct dive {
|
|||
bool likely_same(const struct dive &b) const;
|
||||
bool is_cylinder_used(int idx) const;
|
||||
bool is_cylinder_prot(int idx) const;
|
||||
int explicit_first_cylinder(const struct divecomputer *dc) const;
|
||||
int get_cylinder_index(const struct event &ev) const;
|
||||
bool has_gaschange_event(const struct divecomputer *dc, int idx) const;
|
||||
struct gasmix get_gasmix_from_event(const struct event &ev) const;
|
||||
|
|
|
@ -431,7 +431,7 @@ static void add_dive_to_deco(struct deco_state *ds, const struct dive &dive, boo
|
|||
|
||||
for (j = t0; j < t1; j++) {
|
||||
int depth = interpolate(psample.depth.mm, sample.depth.mm, j - t0, t1 - t0);
|
||||
auto gasmix = loop.next(j);
|
||||
auto gasmix = loop.at(j).first;
|
||||
add_segment(ds, dive.depth_to_bar(depth), gasmix, 1, sample.setpoint.mbar,
|
||||
loop_d.next(j), dive.sac,
|
||||
in_planner);
|
||||
|
|
20
core/event.h
20
core/event.h
|
@ -68,12 +68,26 @@ public:
|
|||
class gasmix_loop {
|
||||
const struct dive &dive;
|
||||
const struct divecomputer &dc;
|
||||
struct gasmix last;
|
||||
bool first_run;
|
||||
event_loop loop;
|
||||
const struct event *ev;
|
||||
const struct event *next_event;
|
||||
int last_cylinder_index;
|
||||
int last_time;
|
||||
public:
|
||||
gasmix_loop(const struct dive &dive, const struct divecomputer &dc);
|
||||
gasmix next(int time);
|
||||
// Return the next cylinder index / gasmix from the list of gas switches
|
||||
// and the time in seconds when this gas switch happened
|
||||
// (including the potentially imaginary first gas switch to cylinder 0 / air)
|
||||
std::pair<int, int> next_cylinder_index(); // -1 -> end
|
||||
std::pair<gasmix, int> next(); // gasmix_invalid -> end
|
||||
|
||||
// Return the cylinder index / gasmix at a given time during the dive
|
||||
// and the time in seconds when this switch to this gas happened
|
||||
// (including the potentially imaginary first gas switch to cylinder 0 / air)
|
||||
std::pair<int, int> cylinder_index_at(int time); // -1 -> end
|
||||
std::pair<gasmix, int> at(int time); // gasmix_invalid -> end
|
||||
|
||||
bool has_next() const;
|
||||
};
|
||||
|
||||
/* Get divemodes at increasing timestamps. */
|
||||
|
|
|
@ -187,7 +187,9 @@ const char *gastype_name(enum gastype type)
|
|||
|
||||
std::string gasmix::name() const
|
||||
{
|
||||
if (gasmix_is_air(*this))
|
||||
if (get_he(*this) < 0 || get_o2(*this) < 0)
|
||||
return translate("gettextFromC", "invalid gas");
|
||||
else if (gasmix_is_air(*this))
|
||||
return translate("gettextFromC", "air");
|
||||
else if (get_he(*this) == 0 && get_o2(*this) < 1000)
|
||||
return format_string_std(translate("gettextFromC", "EAN%d"), (get_o2(*this) + 5) / 10);
|
||||
|
|
|
@ -349,9 +349,8 @@ void populate_pressure_information(const struct dive *dive, const struct divecom
|
|||
* itself has a gas change event.
|
||||
*/
|
||||
cyl = sensor;
|
||||
event_loop loop_gas("gaschange");
|
||||
const struct event *ev = dive->has_gaschange_event(dc, sensor) ?
|
||||
loop_gas.next(*dc) : nullptr;
|
||||
bool has_gaschange = dive->has_gaschange_event(dc, sensor);
|
||||
gasmix_loop loop_gas(*dive, *dc);
|
||||
divemode_loop loop_mode(*dc);
|
||||
|
||||
for (int i = first; i <= last; i++) {
|
||||
|
@ -359,11 +358,10 @@ void populate_pressure_information(const struct dive *dive, const struct divecom
|
|||
int pressure = get_plot_sensor_pressure(pi, i, sensor);
|
||||
int time = entry.sec;
|
||||
|
||||
while (ev && ev->time.seconds <= time) { // Find 1st gaschange event after
|
||||
cyl = dive->get_cylinder_index(*ev); // the current gas change.
|
||||
if (has_gaschange) {
|
||||
cyl = loop_gas.cylinder_index_at(time).first;
|
||||
if (cyl < 0)
|
||||
cyl = sensor;
|
||||
ev = loop_gas.next(*dc);
|
||||
}
|
||||
|
||||
divemode_t dmode = loop_mode.next(time);
|
||||
|
|
|
@ -617,7 +617,7 @@ static void calculate_sac(const struct dive *dive, const struct divecomputer *dc
|
|||
gasmix_loop loop(*dive, *dc);
|
||||
for (int i = 0; i < pi.nr; i++) {
|
||||
const struct plot_data &entry = pi.entry[i];
|
||||
struct gasmix newmix = loop.next(entry.sec);
|
||||
struct gasmix newmix = loop.at(entry.sec).first;
|
||||
if (!same_gasmix(newmix, gasmix)) {
|
||||
gasmix = newmix;
|
||||
matching_gases(dive, newmix, gases.data());
|
||||
|
@ -677,31 +677,28 @@ static void setup_gas_sensor_pressure(const struct dive *dive, const struct dive
|
|||
std::vector<int> first(num_cyl, 0);
|
||||
std::vector<int> last(num_cyl, INT_MAX);
|
||||
|
||||
int prev = dive->explicit_first_cylinder(dc);
|
||||
prev = prev >= 0 ? prev : 0;
|
||||
seen[prev] = 1;
|
||||
int prev = -1;
|
||||
gasmix_loop loop(*dive, *dc);
|
||||
while (loop.has_next()) {
|
||||
auto [cylinder_index, time] = loop.next_cylinder_index();
|
||||
|
||||
event_loop loop("gaschange");
|
||||
while (auto ev = loop.next(*dc)) {
|
||||
int cyl = ev->gas.index;
|
||||
int sec = ev->time.seconds;
|
||||
|
||||
if (cyl < 0)
|
||||
if (cylinder_index < 0)
|
||||
continue; // unknown cylinder
|
||||
if (cyl >= num_cyl) {
|
||||
report_info("setup_gas_sensor_pressure(): invalid cylinder idx %d", cyl);
|
||||
if (cylinder_index >= num_cyl) {
|
||||
report_info("setup_gas_sensor_pressure(): invalid cylinder idx %d", cylinder_index);
|
||||
continue;
|
||||
}
|
||||
|
||||
last[prev] = sec;
|
||||
prev = cyl;
|
||||
if (prev >= 0) {
|
||||
last[prev] = time;
|
||||
|
||||
last[cyl] = sec;
|
||||
if (!seen[cyl]) {
|
||||
// The end time may be updated by a subsequent cylinder change
|
||||
first[cyl] = sec;
|
||||
seen[cyl] = 1;
|
||||
if (!seen[cylinder_index])
|
||||
first[cylinder_index] = time;
|
||||
}
|
||||
|
||||
seen[cylinder_index] = 1;
|
||||
|
||||
prev = cylinder_index;
|
||||
}
|
||||
last[prev] = INT_MAX;
|
||||
|
||||
|
@ -878,7 +875,7 @@ static void calculate_deco_information(struct deco_state *ds, const struct deco_
|
|||
int time_stepsize = 20, max_ceiling = -1;
|
||||
|
||||
divemode_t current_divemode = loop_d.next(entry.sec);
|
||||
struct gasmix gasmix = loop.next(t1);
|
||||
struct gasmix gasmix = loop.at(t1).first;
|
||||
entry.ambpressure = dive->depth_to_bar(entry.depth);
|
||||
entry.gfline = get_gf(ds, entry.ambpressure, dive) * (100.0 - AMB_PERCENTAGE) + AMB_PERCENTAGE;
|
||||
if (t0 > t1) {
|
||||
|
@ -1113,14 +1110,14 @@ static void calculate_gas_information_new(const struct dive *dive, const struct
|
|||
double fn2, fhe;
|
||||
struct plot_data &entry = pi.entry[i];
|
||||
|
||||
auto gasmix = loop.next(entry.sec);
|
||||
auto gasmix = loop.at(entry.sec).first;
|
||||
amb_pressure = dive->depth_to_bar(entry.depth);
|
||||
divemode_t current_divemode = loop_d.next(entry.sec);
|
||||
entry.pressures = fill_pressures(amb_pressure, gasmix, (current_divemode == OC) ? 0.0 : entry.o2pressure.mbar / 1000.0, current_divemode);
|
||||
fn2 = 1000.0 * entry.pressures.n2 / amb_pressure;
|
||||
fhe = 1000.0 * entry.pressures.he / amb_pressure;
|
||||
if (dc->divemode == PSCR) { // OC pO2 is calulated for PSCR with or without external PO2 monitoring.
|
||||
struct gasmix gasmix2 = loop.next(entry.sec);
|
||||
struct gasmix gasmix2 = loop.at(entry.sec).first;
|
||||
entry.scr_OC_pO2.mbar = (int) dive->depth_to_mbar(entry.depth) * get_o2(gasmix2) / 1000;
|
||||
}
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ void DivePercentageItem::replot(const dive *d, const struct divecomputer *dc, co
|
|||
continue;
|
||||
|
||||
double value = item.percentages[tissue];
|
||||
struct gasmix gasmix = loop.next(sec);
|
||||
struct gasmix gasmix = loop.at(sec).first;
|
||||
int inert = get_n2(gasmix) + get_he(gasmix);
|
||||
color = colorScale(value, inert);
|
||||
if (nextX >= width)
|
||||
|
|
|
@ -80,19 +80,16 @@ void TankItem::setData(const struct dive *d, const struct divecomputer *dc, int
|
|||
return;
|
||||
|
||||
// start with the first gasmix and at the start of the plotted range
|
||||
event_loop loop("gaschange");
|
||||
struct gasmix gasmix = gasmix_invalid;
|
||||
const struct event *ev;
|
||||
while ((ev = loop.next(*dc)) != nullptr && ev->time.seconds <= plotStartTime)
|
||||
gasmix = d->get_gasmix_from_event(*ev);
|
||||
|
||||
// work through all the gas changes and add the rectangle for each gas while it was used
|
||||
int startTime = plotStartTime;
|
||||
while (ev && (int)ev->time.seconds < plotEndTime) {
|
||||
createBar(startTime, ev->time.seconds, gasmix);
|
||||
startTime = ev->time.seconds;
|
||||
gasmix = d->get_gasmix_from_event(*ev);
|
||||
ev = loop.next(*dc);
|
||||
// and work through all the gas changes and add the rectangle for each gas while it was used
|
||||
gasmix_loop loop(*d, *dc);
|
||||
struct gasmix next_gasmix = loop.at(plotStartTime).first;
|
||||
int next_startTime = plotStartTime;
|
||||
while (loop.has_next()) {
|
||||
auto [gasmix, time] = loop.next();
|
||||
createBar(next_startTime, time, next_gasmix);
|
||||
next_startTime = time;
|
||||
next_gasmix = gasmix;
|
||||
}
|
||||
createBar(startTime, plotEndTime, gasmix);
|
||||
|
||||
createBar(next_startTime, plotEndTime, next_gasmix);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue