pie.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. #include <math.h>
  2. #include <grass/gis.h>
  3. #include <grass/vector.h>
  4. #include <grass/dbmi.h>
  5. #include <grass/display.h>
  6. #include <grass/symbol.h>
  7. #include "global.h"
  8. #define PI M_PI
  9. static int init = 0;
  10. static double sa = 0.0;
  11. static double ca = 1.0;
  12. /* rotates x and y about the origin (xo,yo) by angle radians */
  13. static void rotate(double *x, double *y, double xo, double yo, int do3d)
  14. {
  15. double tmpx, tmpy;
  16. if (!do3d)
  17. return;
  18. /* first translate */
  19. tmpx = *x - xo;
  20. tmpy = *y - yo;
  21. /* now rotate */
  22. *x = tmpx * ca - tmpy * sa;
  23. *y = tmpx * sa + tmpy * ca;
  24. /* now translate back */
  25. *x += xo;
  26. *y += yo;
  27. return;
  28. }
  29. int
  30. pie(double cx, double cy, int size, double *val, int ncols, COLOR * ocolor,
  31. COLOR * colors, int do3d)
  32. {
  33. int i, j, n;
  34. double a, end_ang, ang, tot_sum, sum, step, r, rminor;
  35. double x, y;
  36. struct line_pnts *Points;
  37. G_debug(4, "pie(): cx = %f cy = %f", cx, cy);
  38. Points = Vect_new_line_struct();
  39. if (!init) {
  40. sa = sin(-6 / 180.0 * PI);
  41. ca = cos(-6 / 180.0 * PI);
  42. init = 1;
  43. }
  44. /* Calc sum */
  45. tot_sum = 0;
  46. for (i = 0; i < ncols; i++)
  47. tot_sum += val[i];
  48. if (tot_sum == 0) {
  49. Vect_destroy_line_struct(Points);
  50. return 0; /* nothing to draw */
  51. }
  52. step = PI / 180;
  53. r = (D_d_to_u_col(2) - D_d_to_u_col(1)) * size / 2; /* do it better */
  54. rminor = r;
  55. if (do3d) {
  56. int first, np;
  57. rminor = r * 2.0 / 3.0;
  58. /* Draw lower polygon for each value */
  59. sum = 0;
  60. ang = 0;
  61. for (i = 0; i < ncols; i++) {
  62. if (val[i] == 0)
  63. continue;
  64. sum += val[i];
  65. end_ang = 2 * PI * sum / tot_sum;
  66. if (end_ang <= PI) {
  67. ang = end_ang;
  68. continue;
  69. }
  70. Vect_reset_line(Points);
  71. n = (int)ceil((end_ang - ang) / step);
  72. /* upper -> lower */
  73. a = ang;
  74. if (ang < PI)
  75. a = PI;
  76. x = cx + r * cos(a);
  77. y = cy + rminor * sin(a);
  78. rotate(&x, &y, cx, cy, do3d);
  79. Vect_append_point(Points, x, y, 0);
  80. /* lower */
  81. first = ang < PI ? 1 : 0;
  82. for (j = 0, a = ang; j <= n; j++, a += step) {
  83. if (j == n)
  84. a = end_ang;
  85. if (a > PI) {
  86. if (first) {
  87. x = cx + r * cos(PI);
  88. y = cy + rminor * sin(PI) - r / 5;
  89. rotate(&x, &y, cx, cy, do3d);
  90. Vect_append_point(Points, x, y, 0);
  91. first = 0;
  92. }
  93. x = cx + r * cos(a);
  94. y = cy + rminor * sin(a) - r / 5;
  95. rotate(&x, &y, cx, cy, do3d);
  96. Vect_append_point(Points, x, y, 0);
  97. }
  98. }
  99. np = Points->n_points + 1;
  100. /* upper */
  101. first = end_ang > PI ? 1 : 0;
  102. for (j = 0, a = end_ang; j <= n; j++, a -= step) {
  103. if (j == n)
  104. a = ang;
  105. if (a > PI) {
  106. x = cx + r * cos(a);
  107. y = cy + rminor * sin(a);
  108. rotate(&x, &y, cx, cy, do3d);
  109. Vect_append_point(Points, x, y, 0);
  110. }
  111. else if (first) {
  112. x = cx + r * cos(PI);
  113. y = cy + rminor * sin(PI);
  114. rotate(&x, &y, cx, cy, do3d);
  115. Vect_append_point(Points, x, y, 0);
  116. first = 0;
  117. }
  118. }
  119. ang = end_ang;
  120. if (Points->n_points == 0)
  121. continue;
  122. if (!colors[i].none) {
  123. D_RGB_color(colors[i].r, colors[i].g, colors[i].b);
  124. D_polygon_abs(Points->x, Points->y, Points->n_points);
  125. }
  126. D_RGB_color(ocolor->r, ocolor->g, ocolor->b);
  127. Points->n_points = np;
  128. D_polyline_abs(Points->x, Points->y, Points->n_points);
  129. }
  130. }
  131. /* Draw polygon for each value */
  132. sum = 0;
  133. ang = 0;
  134. for (i = 0; i < ncols; i++) {
  135. if (val[i] == 0)
  136. continue;
  137. sum += val[i];
  138. end_ang = 2 * PI * sum / tot_sum;
  139. Vect_reset_line(Points);
  140. if (val[i] != tot_sum) { /* all in one slice, don't draw line to center */
  141. x = cx;
  142. y = cy;
  143. rotate(&x, &y, cx, cy, do3d);
  144. Vect_append_point(Points, x, y, 0);
  145. }
  146. n = (int)ceil((end_ang - ang) / step);
  147. for (j = 0, a = ang; j <= n; j++, a += step) {
  148. if (a > end_ang)
  149. a = end_ang;
  150. x = cx + r * cos(a);
  151. y = cy + rminor * sin(a);
  152. rotate(&x, &y, cx, cy, do3d);
  153. Vect_append_point(Points, x, y, 0);
  154. }
  155. ang = end_ang;
  156. if (val[i] != tot_sum) { /* all in one slice, don't draw line to center */
  157. x = cx;
  158. y = cy;
  159. rotate(&x, &y, cx, cy, do3d);
  160. Vect_append_point(Points, x, y, 0);
  161. }
  162. if (!colors[i].none) {
  163. D_RGB_color(colors[i].r, colors[i].g, colors[i].b);
  164. D_polygon_abs(Points->x, Points->y, Points->n_points);
  165. }
  166. D_RGB_color(ocolor->r, ocolor->g, ocolor->b);
  167. D_polyline_abs(Points->x, Points->y, Points->n_points);
  168. }
  169. Vect_destroy_line_struct(Points);
  170. return 0;
  171. }