X-Git-Url: http://git.tdb.fi/?p=ext%2Fsubsurface.git;a=blobdiff_plain;f=profile.c;h=0039867efc29355737294cb1ac02a0cb85743ce6;hp=c7d945f14060d5f1e48052c89c01b1fe27ba1154;hb=HEAD;hpb=b65f8230daca1bca34496f6281ecc0dbe70b0724 diff --git a/profile.c b/profile.c index c7d945f..0039867 100644 --- a/profile.c +++ b/profile.c @@ -1,5 +1,5 @@ /* profile.c */ -/* creates all the necessary data for drawing the dive profile +/* creates all the necessary data for drawing the dive profile * uses cairo to draw it */ #include @@ -14,6 +14,7 @@ #include "color.h" int selected_dive = 0; +char zoomed_plot = 0; typedef enum { STABLE, SLOW, MODERATE, FAST, CRAZY } velocity_t; @@ -168,9 +169,10 @@ static void dump_pi (struct plot_info *pi) pi->maxpressure, pi->mintemp, pi->maxtemp); for (i = 0; i < pi->nr; i++) printf(" entry[%d]:{same_cylinder:%d cylinderindex:%d sec:%d pressure:{%d,%d}\n" - " temperature:%d depth:%d smoothed:%d}\n", + " time:%d:%02d temperature:%d depth:%d smoothed:%d}\n", i, pi->entry[i].same_cylinder, pi->entry[i].cylinderindex, pi->entry[i].sec, pi->entry[i].pressure[0], pi->entry[i].pressure[1], + pi->entry[i].sec / 60, pi->entry[i].sec % 60, pi->entry[i].temperature, pi->entry[i].depth, pi->entry[i].smoothed); printf(" }\n"); } @@ -179,22 +181,40 @@ static void dump_pi (struct plot_info *pi) * When showing dive profiles, we scale things to the * current dive. However, we don't scale past less than * 30 minutes or 90 ft, just so that small dives show - * up as such. - * we also need to add 180 seconds at the end so the min/max + * up as such unless zoom is enabled. + * We also need to add 180 seconds at the end so the min/max * plots correctly */ static int get_maxtime(struct plot_info *pi) { int seconds = pi->maxtime; - /* min 30 minutes, rounded up to 5 minutes, with at least 2.5 minutes to spare */ - return MAX(30*60, ROUND_UP(seconds+150, 60*5)); + if (zoomed_plot) { + /* Rounded up to one minute, with at least 2.5 minutes to + * spare. + * For dive times shorter than 10 minutes, we use seconds/4 to + * calculate the space dynamically. + * This is seamless since 600/4 = 150. + */ + if ( seconds < 600 ) + return ROUND_UP(seconds+seconds/4, 60); + else + return ROUND_UP(seconds+150, 60); + } else { + /* min 30 minutes, rounded up to 5 minutes, with at least 2.5 minutes to spare */ + return MAX(30*60, ROUND_UP(seconds+150, 60*5)); + } } static int get_maxdepth(struct plot_info *pi) { unsigned mm = pi->maxdepth; - /* Minimum 30m, rounded up to 10m, with at least 3m to spare */ - return MAX(30000, ROUND_UP(mm+3000, 10000)); + if (zoomed_plot) { + /* Rounded up to 10m, with at least 3m to spare */ + return ROUND_UP(mm+3000, 10000); + } else { + /* Minimum 30m, rounded up to 10m, with at least 3m to spare */ + return MAX(30000, ROUND_UP(mm+3000, 10000)); + } } typedef struct { @@ -442,20 +462,21 @@ static void plot_depth_profile(struct graphics_context *gc, struct plot_info *pi int sec, depth; struct plot_data *entry; int maxtime, maxdepth, marker; - int increments[4] = { 5*60, 10*60, 15*60, 30*60 }; + int increments[8] = { 10, 20, 30, 60, 5*60, 10*60, 15*60, 30*60 }; /* Get plot scaling limits */ maxtime = get_maxtime(pi); maxdepth = get_maxdepth(pi); - /* Time markers: at most every 5 min, but no more than 12 markers - * and for convenience we do 5, 10, 15 or 30 min intervals. + /* Time markers: at most every 10 seconds, but no more than 12 markers. + * We start out with 10 seconds and increment up to 30 minutes, + * depending on the dive time. * This allows for 6h dives - enough (I hope) for even the craziest * divers - but just in case, for those 8h depth-record-breaking dives, * we double the interval if this still doesn't get us to 12 or fewer * time markers */ i = 0; - while (maxtime / increments[i] > 12 && i < 4) + while (maxtime / increments[i] > 12 && i < 8) i++; incr = increments[i]; while (maxtime / incr > 12) @@ -472,11 +493,17 @@ static void plot_depth_profile(struct graphics_context *gc, struct plot_info *pi } cairo_stroke(cr); - /* now the text on every second time marker */ + /* now the text on the time markers */ text_render_options_t tro = {10, TIME_TEXT, CENTER, TOP}; - for (i = incr; i < maxtime; i += 2 * incr) - plot_text(gc, &tro, i, 1, "%d", i/60); - + if (maxtime < 600) { + /* Be a bit more verbose with shorter dives */ + for (i = incr; i < maxtime; i += incr) + plot_text(gc, &tro, i, 1, "%02d:%02d", i/60, i%60); + } else { + /* Only render the time on every second marker for normal dives */ + for (i = incr; i < maxtime; i += 2 * incr) + plot_text(gc, &tro, i, 1, "%d", i/60); + } /* Depth markers: every 30 ft or 10 m*/ gc->leftx = 0; gc->rightx = 1.0; gc->topy = 0; gc->bottomy = maxdepth; @@ -528,15 +555,8 @@ static void plot_depth_profile(struct graphics_context *gc, struct plot_info *pi for (i = 0; i < pi->nr; i++, entry++) line_to(gc, entry->sec, entry->depth); cairo_close_path(gc->cr); -/* - if (gc->printer) { - set_source_rgba(gc, DEPTH_FILL_PRINTER); - cairo_fill_preserve(cr); - set_source_rgba(gc, DEPTH_STROKE_PRINTER); - cairo_stroke(cr); - return; - } -*/ cairo_fill(gc->cr); + + cairo_fill(gc->cr); /* Now do it again for the velocity colors */ entry = pi->entry; @@ -879,7 +899,7 @@ static velocity_t velocity(int speed) else if (speed < -25) /* -5ft/min */ v = SLOW; else if (speed < 25) /* very hard to find data, but it appears that the recommendations - for descent are usually about 2x ascent rate; still, we want + for descent are usually about 2x ascent rate; still, we want stable to mean stable */ v = STABLE; else if (speed < 152) /* between 5 and 30ft/min is considered slow */ @@ -935,7 +955,7 @@ static struct plot_info *analyze_plot_info(struct plot_info *pi) int past = -2; while (i+past > 0 && entry[0].sec - entry[past].sec < 15) past--; - entry->velocity = velocity((entry[0].depth - entry[past].depth) / + entry->velocity = velocity((entry[0].depth - entry[past].depth) / (entry[0].sec - entry[past].sec)); } } else @@ -947,7 +967,7 @@ static struct plot_info *analyze_plot_info(struct plot_info *pi) struct plot_data *entry = pi->entry +i; analyze_plot_info_minmax(entry, pi->entry, pi->entry+nr); } - + return pi; } @@ -1020,8 +1040,7 @@ static void dump_pr_track(pr_track_t **track_pr) } } -static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi, - pr_track_t **track_pr) +static void fill_missing_tank_pressures(struct plot_info *pi, pr_track_t **track_pr) { pr_track_t *list = NULL; pr_track_t *nlist = NULL; @@ -1055,16 +1074,18 @@ static void fill_missing_tank_pressures(struct dive *dive, struct plot_info *pi, /* there may be multiple segments - so * let's assemble the length */ nlist = list; - pt = list->pressure_time; - while (!nlist->end) { - nlist = nlist->next; - if (!nlist) { - /* oops - we have no end pressure, - * so this means this is a tank without - * gas consumption information */ - break; + if (list) { + pt = list->pressure_time; + while (!nlist->end) { + nlist = nlist->next; + if (!nlist) { + /* oops - we have no end pressure, + * so this means this is a tank without + * gas consumption information */ + break; + } + pt += nlist->pressure_time; } - pt += nlist->pressure_time; } if (!nlist) { /* just continue without calculating @@ -1344,7 +1365,7 @@ static struct plot_info *create_plot_info(struct dive *dive, int nr_samples, str pi->meandepth = dive->meandepth.mm; if (missing_pr) { - fill_missing_tank_pressures(dive, pi, track_pr); + fill_missing_tank_pressures(pi, track_pr); } for (cyl = 0; cyl < MAX_CYLINDERS; cyl++) list_free(track_pr[cyl]); @@ -1361,12 +1382,17 @@ void plot(struct graphics_context *gc, cairo_rectangle_int_t *drawing_area, stru int nr = dive->samples; if (!nr) { + /* The dive has no samples, so create a few fake ones. This assumes an + ascent/descent rate of 9 m/min, which is just below the limit for FAST. */ int duration = dive->duration.seconds; int maxdepth = dive->maxdepth.mm; + int asc_desc_time = dive->maxdepth.mm*60/9000; + if (asc_desc_time * 2 >= duration) + asc_desc_time = duration / 2; sample = fake; - fake[1].time.seconds = duration * 0.05; + fake[1].time.seconds = asc_desc_time; fake[1].depth.mm = maxdepth; - fake[2].time.seconds = duration * 0.95; + fake[2].time.seconds = duration - asc_desc_time; fake[2].depth.mm = maxdepth; fake[3].time.seconds = duration * 1.00; nr = 4; @@ -1389,13 +1415,13 @@ void plot(struct graphics_context *gc, cairo_rectangle_int_t *drawing_area, stru gc->maxx = (drawing_area->width - 2*drawing_area->x); gc->maxy = (drawing_area->height - 2*drawing_area->y); - /* Temperature profile */ - plot_temperature_profile(gc, pi); - /* Depth profile */ plot_depth_profile(gc, pi); plot_events(gc, pi, dive); + /* Temperature profile */ + plot_temperature_profile(gc, pi); + /* Cylinder pressure plot */ plot_cylinder_pressure(gc, pi, dive);