Smoother curves (using Bezier algo).
authorJean-Philippe Orsini <jeanfi@gmail.com>
Wed, 10 Sep 2014 07:55:10 +0000 (09:55 +0200)
committerJean-Philippe Orsini <jeanfi@gmail.com>
Wed, 10 Sep 2014 07:55:10 +0000 (09:55 +0200)
NEWS
NEWS.html
src/graph.c

diff --git a/NEWS b/NEWS
index faba488..9b6c2e6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,7 @@ v1.1.2
   sensors.
 * Added free memory support.
 * Added alarm support of sensors expressed as percent.
+* Smoother curves (using Bezier algo).
 
 v1.1.1
 ------
index 7996419..52f5a87 100644 (file)
--- a/NEWS.html
+++ b/NEWS.html
@@ -442,6 +442,11 @@ Added free memory support.
 Added alarm support of sensors expressed as percent.\r
 </p>\r
 </li>\r
+<li>\r
+<p>\r
+Smoother curves (using Bezier algo).\r
+</p>\r
+</li>\r
 </ul></div>\r
 </div>\r
 </div>\r
@@ -2794,7 +2799,7 @@ Fixed BR1: crash when no temperature sensor is available
 <div id="footnotes"><hr /></div>\r
 <div id="footer">\r
 <div id="footer-text">\r
-Last updated 2014-09-09 08:33:08 CEST\r
+Last updated 2014-09-10 09:49:54 CEST\r
 </div>\r
 </div>\r
 </body>\r
index 578ad73..a69b65a 100644 (file)
@@ -55,7 +55,8 @@ static time_t get_graph_begin_time_s(struct config *cfg)
        return ct - cfg->graph_monitoring_duration * 60;
 }
 
-static int compute_y(double value, double min, double max, int height, int off)
+static double
+compute_y(double value, double min, double max, int height, int off)
 {
        double t = value - min;
        return height - ((double)height * (t / (max - min))) + off;
@@ -169,6 +170,108 @@ static void draw_background_lines(cairo_t *cr,
        cairo_set_dash(cr, 0, 0, 0);
 }
 
+/* contains the time_t of the measures which have been draw ie not the
+ * bezier control points for each sensor. */
+static GHashTable *times;
+
+static void draw_sensor_smooth_curve(struct psensor *s,
+                                    cairo_t *cr,
+                                    double min,
+                                    double max,
+                                    int bt,
+                                    int et,
+                                    int g_width,
+                                    int g_height,
+                                    int g_xoff,
+                                    int g_yoff)
+{
+       int i, dt, vdt, j, k, found;
+       double x[4], y[4], v;
+       time_t t, t0, *stimes;
+
+       if (!times)
+               times = g_hash_table_new_full(g_str_hash,
+                                             g_str_equal,
+                                             free,
+                                             free);
+
+       stimes = g_hash_table_lookup(times, s->id);
+
+       cairo_set_source_rgb(cr,
+                            s->color->red,
+                            s->color->green,
+                            s->color->blue);
+
+       i = 0;
+       if (stimes) {
+               while (i < s->values_max_length) {
+                       t = s->measures[i].time.tv_sec;
+                       v = s->measures[i].value;
+
+                       found = 0;
+                       if (v != UNKNOWN_DBL_VALUE && t) {
+                               k = 0;
+                               while (stimes[k]) {
+                                       if (t == stimes[k]) {
+                                               found = 1;
+                                               break;
+                                       }
+                                       k++;
+                               }
+                       }
+
+                       if (found)
+                               break;
+
+                       i++;
+               }
+       }
+
+       stimes = malloc((s->values_max_length + 1) * sizeof(time_t));
+       memset(stimes, 0, (s->values_max_length + 1) * sizeof(time_t));
+       g_hash_table_insert(times, strdup(s->id), stimes);
+
+       if (i == s->values_max_length)
+               i = 0;
+
+       k = 0;
+       dt = et - bt;
+       while (i < s->values_max_length) {
+               j = 0;
+               t = 0;
+               while (i < s->values_max_length && j < 4) {
+                       t = s->measures[i].time.tv_sec;
+                       v = s->measures[i].value;
+
+                       if (v == UNKNOWN_DBL_VALUE || !t) {
+                               i++;
+                               continue;
+                       }
+
+                       vdt = t - bt;
+
+                       x[0 + j] = ((double)vdt * g_width) / dt + g_xoff;
+                       y[0 + j] = compute_y(v, min, max, g_height, g_yoff);
+
+
+                       if (j == 0)
+                               t0 = t;
+
+                       i++;
+                       j++;
+               }
+
+               if (j == 4) {
+                       cairo_move_to(cr, x[0], y[0]);
+                       cairo_curve_to(cr, x[1], y[1], x[2], y[3], x[3], y[3]);
+                       stimes[k++] = t0;
+                       i--;
+               }
+       }
+
+       cairo_stroke(cr);
+}
+
 static void draw_sensor_curve(struct psensor *s,
                              cairo_t *cr,
                              double min,
@@ -180,8 +283,8 @@ static void draw_sensor_curve(struct psensor *s,
                              int g_xoff,
                              int g_yoff)
 {
-       int first, i, x, y, t, dt, vdt;
-       double v;
+       int first, i, t, dt, vdt;
+       double v, x, y;
 
        cairo_set_source_rgb(cr,
                             s->color->red,
@@ -201,7 +304,7 @@ static void draw_sensor_curve(struct psensor *s,
                if (vdt < 0)
                        continue;
 
-               x = vdt * g_width / dt + g_xoff;
+               x = ((double)vdt * g_width) / dt + g_xoff;
 
                y = compute_y(v, min, max, g_height, g_yoff);
 
@@ -373,11 +476,18 @@ graph_update(struct psensor **sensors,
                                max = maxt;
                        }
 
-                       draw_sensor_curve(s, cr,
-                                         min, max,
-                                         bt, et,
-                                         g_width, g_height,
-                                         g_xoff, g_yoff);
+                       if (1)
+                               draw_sensor_smooth_curve(s, cr,
+                                                        min, max,
+                                                        bt, et,
+                                                        g_width, g_height,
+                                                        g_xoff, g_yoff);
+                       else
+                               draw_sensor_curve(s, cr,
+                                                 min, max,
+                                                 bt, et,
+                                                 g_width, g_height,
+                                                 g_xoff, g_yoff);
 
                        sensor_cur++;
                }