New, hopefully better, implementation of PART drawing
authoralex <alex@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Wed, 13 Mar 2002 02:58:44 +0000 (02:58 +0000)
committeralex <alex@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Wed, 13 Mar 2002 02:58:44 +0000 (02:58 +0000)
git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@95 a5681a0c-68f1-0310-ab6d-d61299d08faa

src/rrd_gfx.c
src/rrd_gfx.h
src/rrd_graph.c

index 724a074..1a45439 100644 (file)
@@ -15,6 +15,7 @@
 #include <png.h>
 #include <ft2build.h>
 #include FT_FREETYPE_H
+#include <math.h>
 
 #include "rrd_gfx.h"
 
@@ -107,6 +108,52 @@ gfx_node_t   *gfx_new_area   (gfx_canvas_t *canvas,
 
   return node;
 }
+/* create an arc section (2*M_PI is full circle) */
+gfx_node_t   *gfx_arc_sect   (gfx_canvas_t *canvas, 
+                             double centerx, double centery,
+                             double radiusx, double radiusy,
+                             double start, double end,
+                             gfx_color_t color) {
+
+  gfx_node_t *node;
+  ArtVpath *vec;
+  int counter;
+  double position;
+
+/* 20 is too low, 100 is overkill */
+#define AMOUNT_OF_VECTORS 50
+
+  node = gfx_new_node(canvas,GFX_AREA);
+  if (node == NULL) return NULL;
+  vec = art_new(ArtVpath, AMOUNT_OF_VECTORS+4);
+  if (vec == NULL) return NULL;
+
+  vec[0].code = ART_MOVETO;
+  vec[0].x = centerx;
+  vec[0].y = centery;
+
+  for (counter=0;counter<=AMOUNT_OF_VECTORS;) {
+    position=start + counter*(end-start)/AMOUNT_OF_VECTORS;
+
+    counter++;
+    vec[counter].code = ART_LINETO;
+    vec[counter].x = centerx + sin(position)*radiusx;
+    vec[counter].y = centery - cos(position)*radiusy;
+  }
+
+  vec[AMOUNT_OF_VECTORS+2].code = ART_LINETO;
+  vec[AMOUNT_OF_VECTORS+2].x = centerx;
+  vec[AMOUNT_OF_VECTORS+2].y = centery;
+
+  vec[AMOUNT_OF_VECTORS+3].code = ART_END;
+  
+  node->points = AMOUNT_OF_VECTORS+4;
+  node->points_max = AMOUNT_OF_VECTORS+4;
+  node->color = color;
+  node->path  = vec;
+
+  return node;
+}
 
 /* add a point to a line or to an area */
 int           gfx_add_point  (gfx_node_t *node, 
index 808b7c4..8362ff1 100644 (file)
@@ -54,6 +54,13 @@ gfx_node_t   *gfx_new_area   (gfx_canvas_t *canvas,
                              double x2, double y2,
                              gfx_color_t  color);
 
+/* create an arc section (2*M_PI is full circle) */
+gfx_node_t   *gfx_arc_sect   (gfx_canvas_t *canvas, 
+                             double centerx, double centery,
+                             double radiusx, double radiusy,
+                             double start, double end,
+                             gfx_color_t color);
+
 /* add a point to a line or to an area */
 int           gfx_add_point  (gfx_node_t *node, double x, double y);
 
index abbfcdb..c7ba63e 100644 (file)
@@ -938,6 +938,7 @@ data_proc( image_desc_t *im ){
            case GF_DEF:               
            case GF_CDEF:
            case GF_VDEF:
+           case GF_PART:
                break;
            }
        }
@@ -1920,14 +1921,17 @@ graph_paint(image_desc_t *im, char ***calcpr)
   }
 
   if (piechart) {
+       /* allocate enough space for the piechart itself (PieSize), 20%
+       ** more for the background and an additional 50 pixels spacing.
+       */
     if (im->xsize < im->ysize)
        PieSize = im->xsize;
     else
        PieSize = im->ysize;
-    im->xgif += PieSize + 50;
+    im->xgif += PieSize*1.2 + 50;
 
-    PieCenterX = im->xorigin + im->xsize + 50 + PieSize/2;
-    PieCenterY = im->yorigin - PieSize/2;
+    PieCenterX = im->xorigin + im->xsize + 50 + PieSize*0.6;
+    PieCenterY = im->yorigin - PieSize*0.5;
   }
   
   /* determine where to place the legends onto the graphics.
@@ -1957,12 +1961,21 @@ graph_paint(image_desc_t *im, char ***calcpr)
   gfx_add_point(node,im->xorigin, im->yorigin - im->ysize);
 
   if (piechart) {
+#if 1
+    node=gfx_arc_sect (canvas,
+       PieCenterX,PieCenterY,
+       PieSize*0.6, PieSize*0.6,       /* 20% more as background */
+       0,M_PI*2,
+       im->graph_col[GRC_CANVAS]);
+#else
     node=gfx_new_area ( canvas,
-               im->xorigin + im->xsize + 50,           im->yorigin,
-               im->xorigin + im->xsize + 50 + PieSize, im->yorigin,
-               im->xorigin + im->xsize + 50 + PieSize, im->yorigin - PieSize,
-               im->graph_col[GRC_CANVAS]);
-    gfx_add_point(node,im->xorigin+im->xsize+50, im->yorigin - PieSize);
+       PieCenterX-0.6*PieSize, PieCenterY-0.6*PieSize,
+       PieCenterX+0.6*PieSize, PieCenterY-0.6*PieSize,
+       PieCenterX+0.6*PieSize, PieCenterY+0.6*PieSize,
+       im->graph_col[GRC_CANVAS]);
+    gfx_add_point(node,
+       PieCenterX-0.6*PieSize, PieCenterY+0.6*PieSize);
+#endif
   }
 
   if (im->minval > 0.0)
@@ -2092,48 +2105,20 @@ graph_paint(image_desc_t *im, char ***calcpr)
       } 
       lastgdes = &(im->gdes[i]);                         
       break;
-    case GF_PART: {
-      int x,y , counter;
-      double d1,d2,d3,d4;
-
-      /* This probably is not the most efficient algorithm...
-      ** If you know how to help, please do!
-      **
-      ** If you change this routine be aware that I optimized
-      ** the following algorithm:
-      **
-      ** Full circle == 100
-      **    relative X-position is sin(2*pi * position/100)
-      **    relative Y-position is cos(2*pi * position/100)
-      **
-      ** Position is incremented from start to end in a number
-      ** of steps.  This number of steps corresponds with the
-      ** size of the pie canvas, each step being 1/PieSize.
-      */
-
+    case GF_PART:
       if(isnan(im->gdes[i].yrule)) /* fetch variable */
        im->gdes[i].yrule = im->gdes[im->gdes[i].vidx].vf.val;
      
-      if (finite(im->gdes[i].yrule)) {
-       d1 = 2 * M_PI / 100;
-       d2 = im->gdes[i].yrule / PieSize;
-       d3 = PieSize/2;
-
-       for (counter=0;counter<=PieSize;counter++) {
-         d4 = d1 * (PieStart + d2 * counter);
-         x=sin(d4) * d3;
-         y=cos(d4) * d3;
-
-         gfx_new_line(canvas,
-           PieCenterX,PieCenterY ,
-           PieCenterX+x,PieCenterY-y,
-           1.0,
-           im->gdes[i].col);
-        }
-        PieStart += im->gdes[i].yrule;
+      if (finite(im->gdes[i].yrule)) { /* even the fetched var can be NaN */
+       node=gfx_arc_sect(canvas,
+               PieCenterX, PieCenterY,
+               PieSize/2,PieSize/2,
+               M_PI*2.0*PieStart/100.0,
+               M_PI*2.0*(PieStart+im->gdes[i].yrule)/100.0,
+               im->gdes[i].col);
+       PieStart += im->gdes[i].yrule;
       }
       break;
-      } /* GF_PART */
     } /* switch */
   }
   grid_paint(im,canvas);