]> git.tdb.fi Git - ext/subsurface.git/blobdiff - profile.c
Libdivecomputer integration, part n+1
[ext/subsurface.git] / profile.c
index 12e648be92abef21933c2ee6efd9e0e595c60ce7..1912690ce2b2021fbe25957eff294a086c5c2999 100644 (file)
--- a/profile.c
+++ b/profile.c
@@ -32,8 +32,8 @@ struct plot_info {
                int sec;
                int val;
                int smoothed;
-               int min[3];
-               int max[3];
+               struct plot_data *min[3];
+               struct plot_data *max[3];
                int avg[3];
        } entry[];
 };
@@ -129,10 +129,10 @@ static void plot_text(struct graphics_context *gc, const text_render_options_t *
        cairo_show_text(cr, buffer);
 }
 
-static void render_depth_sample(struct graphics_context *gc, struct sample *sample, const text_render_options_t *tro)
+static void render_depth_sample(struct graphics_context *gc, struct plot_data *entry, const text_render_options_t *tro)
 {
-       int sec = sample->time.seconds;
-       depth_t depth = sample->depth;
+       int sec = entry->sec;
+       depth_t depth = { entry->val };
        const char *fmt;
        double d;
 
@@ -149,76 +149,28 @@ static void render_depth_sample(struct graphics_context *gc, struct sample *samp
        plot_text(gc, tro, sec, depth.mm, fmt, d);
 }
 
-/*
- * Find the next minimum/maximum point.
- *
- * We exit early if we hit "enough" of a depth reversal,
- * which is roughly 10 feet.
- */
-static struct sample *next_minmax(struct sample *sample, struct sample *end, int minmax)
-{
-       const int enough = 3000;
-       struct sample *result;
-       int depthlimit;
-
-       if (sample >= end)
-               return 0;
-
-       depthlimit = sample->depth.mm;
-       result = NULL;
-
-       for (;;) {
-               int depth;
-
-               sample++;
-               if (sample >= end)
-                       return NULL;
-               depth = sample->depth.mm;
-
-               if (minmax) {
-                       if (depth <= depthlimit) {
-                               if (depthlimit - depth > enough)
-                                       break;
-                               continue;
-                       }
-               } else {
-                       if (depth >= depthlimit) {
-                               if (depth - depthlimit > enough)
-                                       break;
-                               continue;
-                       }
-               }
-
-               result = sample;
-               depthlimit = depth;
-       }
-       return result;
-}
-
-static void plot_text_samples(struct graphics_context *gc, struct sample *a, struct sample *b)
+static void plot_text_samples(struct graphics_context *gc, struct plot_info *pi)
 {
        static const text_render_options_t deep = {14, 1.0, 0.2, 0.2, CENTER, TOP};
        static const text_render_options_t shallow = {14, 1.0, 0.2, 0.2, CENTER, BOTTOM};
+       int i;
 
-       for (;;) {
-               if (b <= a)
-                       break;
-               a = next_minmax(a, b, 1);
-               if (!a)
-                       break;
-               render_depth_sample(gc, a, &deep);
-               a = next_minmax(a, b, 0);
-               if (!a)
-                       break;
-               if (a->depth.mm < 2500)
+       for (i = 0; i < pi->nr; i++) {
+               struct plot_data *entry = pi->entry + i;
+
+               if (entry->val < 2000)
                        continue;
-               render_depth_sample(gc, a, &shallow);
+
+               if (entry == entry->max[2])
+                       render_depth_sample(gc, entry, &deep);
+
+               if (entry == entry->min[2])
+                       render_depth_sample(gc, entry, &shallow);
        }
 }
 
-static void plot_depth_text(struct dive *dive, struct graphics_context *gc)
+static void plot_depth_text(struct dive *dive, struct graphics_context *gc, struct plot_info *pi)
 {
-       struct sample *sample, *end;
        int maxtime, maxdepth;
 
        /* Get plot scaling limits */
@@ -228,10 +180,7 @@ static void plot_depth_text(struct dive *dive, struct graphics_context *gc)
        gc->scalex = maxtime;
        gc->scaley = maxdepth;
 
-       sample = dive->sample;
-       end = dive->sample + dive->samples;
-
-       plot_text_samples(gc, sample, end);
+       plot_text_samples(gc, pi);
 }
 
 static void plot_smoothed_profile(struct graphics_context *gc, struct plot_info *pi)
@@ -255,13 +204,13 @@ static void plot_minmax_profile_minute(struct graphics_context *gc, struct plot_
        struct plot_data *entry = pi->entry;
 
        cairo_set_source_rgba(gc->cr, 1, 0.2, 1, a);
-       move_to(gc, entry->sec, entry->min[index]);
+       move_to(gc, entry->sec, entry->min[index]->val);
        for (i = 1; i < pi->nr; i++) {
                entry++;
-               line_to(gc, entry->sec, entry->min[index]);
+               line_to(gc, entry->sec, entry->min[index]->val);
        }
        for (i = 1; i < pi->nr; i++) {
-               line_to(gc, entry->sec, entry->max[index]);
+               line_to(gc, entry->sec, entry->max[index]->val);
                entry--;
        }
        cairo_close_path(gc->cr);
@@ -442,7 +391,7 @@ static void plot_info(struct dive *dive, struct graphics_context *gc)
 {
        text_render_options_t tro = {10, 0.2, 1.0, 0.2, LEFT, TOP};
        const double liters_per_cuft = 28.317;
-       const char *unit;
+       const char *unit, *desc;
        double airuse;
 
        airuse = calculate_airuse(dive);
@@ -465,6 +414,15 @@ static void plot_info(struct dive *dive, struct graphics_context *gc)
                double sac = airuse / pressure * 60 / dive->duration.seconds;
                plot_text(gc, &tro, 0.8, 0.85, "SAC: %4.2f %s/min", sac, unit);
        }
+       desc = dive->cylinder[0].type.description;
+       if (desc || dive->cylinder[0].gasmix.o2.permille) {
+               int o2 = dive->cylinder[0].gasmix.o2.permille / 10;
+               if (!desc)
+                       desc = "";
+               if (!o2)
+                       o2 = 21;
+               plot_text(gc, &tro, 0.8, 0.9, "%s (%d%%)", desc, o2);
+       }
 }
 
 static void plot_cylinder_pressure_text(struct dive *dive, struct graphics_context *gc)
@@ -504,8 +462,9 @@ static void analyze_plot_info_minmax_minute(struct plot_data *entry, struct plot
 {
        struct plot_data *p = entry;
        int time = entry->sec;
-       int seconds = 60*(index+1);
-       int min, max, avg, nr;
+       int seconds = 90*(index+1);
+       struct plot_data *min, *max;
+       int avg, nr;
 
        /* Go back 'seconds' in time */
        while (p > first) {
@@ -515,7 +474,8 @@ static void analyze_plot_info_minmax_minute(struct plot_data *entry, struct plot
        }
 
        /* Then go forward until we hit an entry past the time */
-       min = max = avg = p->val;
+       min = max = p;
+       avg = p->val;
        nr = 1;
        while (++p < last) {
                int val = p->val;
@@ -523,10 +483,10 @@ static void analyze_plot_info_minmax_minute(struct plot_data *entry, struct plot
                        break;
                avg += val;
                nr ++;
-               if (val < min)
-                       min = val;
-               if (val > max)
-                       max = val;
+               if (val < min->val)
+                       min = p;
+               if (val > max->val)
+                       max = p;
        }
        entry->min[index] = min;
        entry->max[index] = max;
@@ -623,7 +583,7 @@ static void plot(struct graphics_context *gc, int w, int h, struct dive *dive)
        plot_depth_profile(dive, gc, pi);
 
        /* Text on top of all graphs.. */
-       plot_depth_text(dive, gc);
+       plot_depth_text(dive, gc, pi);
        plot_cylinder_pressure_text(dive, gc);
 
        /* And info box in the lower right corner.. */
@@ -667,7 +627,7 @@ GtkWidget *dive_profile_widget(void)
        GtkWidget *da;
 
        da = gtk_drawing_area_new();
-       gtk_widget_set_size_request(da, 450, 350);
+       gtk_widget_set_size_request(da, 350, 250);
        g_signal_connect(da, "expose_event", G_CALLBACK(expose_event), NULL);
 
        return da;