Polygon.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #include <stdlib.h>
  2. #include <math.h>
  3. #include <grass/gis.h>
  4. #include "path.h"
  5. #include "pngdriver.h"
  6. static int cmp_double(const void *aa, const void *bb)
  7. {
  8. const double *a = aa;
  9. const double *b = bb;
  10. return
  11. *a > *b ? 1 :
  12. *a < *b ? -1 :
  13. 0;
  14. }
  15. static void fill(double x0, double x1, double y)
  16. {
  17. int yi = (int) floor(y);
  18. int xi0 = (int) floor(x0 + 0.5);
  19. int xi1 = (int) floor(x1 + 0.5);
  20. unsigned int *p;
  21. int x;
  22. if (yi >= png.clip_bot || yi < png.clip_top)
  23. return;
  24. if (xi0 > png.clip_rite)
  25. return;
  26. if (xi1 < png.clip_left)
  27. return;
  28. if (xi0 < png.clip_left)
  29. xi0 = png.clip_left;
  30. if (xi1 > png.clip_rite)
  31. xi1 = png.clip_rite;
  32. p = &png.grid[yi * png.width + xi0];
  33. for (x = xi0; x < xi1; x++)
  34. *p++ = png.current_color;
  35. }
  36. static void line(const struct vertex *p, int n, double y)
  37. {
  38. static double *xs;
  39. static int max_x;
  40. int num_x = 0;
  41. int i;
  42. for (i = 1; i < n; i++) {
  43. const struct vertex *p0 = &p[i - 1];
  44. const struct vertex *p1 = &p[i];
  45. const struct vertex *tmp;
  46. double x;
  47. if (p0->y == p1->y)
  48. continue;
  49. if (p0->y > p1->y)
  50. tmp = p0, p0 = p1, p1 = tmp;
  51. if (p0->y > y)
  52. continue;
  53. if (p1->y <= y)
  54. continue;
  55. x = p1->x * (y - p0->y) + p0->x * (p1->y - y);
  56. x /= p1->y - p0->y;
  57. if (num_x >= max_x) {
  58. max_x += 20;
  59. xs = G_realloc(xs, max_x * sizeof(double));
  60. }
  61. xs[num_x++] = x;
  62. }
  63. qsort(xs, num_x, sizeof(double), cmp_double);
  64. for (i = 0; i + 1 < num_x; i += 2)
  65. fill(xs[i], xs[i + 1], y);
  66. }
  67. static void poly(const struct vertex *p, int n)
  68. {
  69. double y0, y1, y;
  70. int i;
  71. if (n < 3)
  72. return;
  73. y0 = y1 = p[0].y;
  74. for (i = 1; i < n; i++) {
  75. if (y0 > p[i].y)
  76. y0 = p[i].y;
  77. if (y1 < p[i].y)
  78. y1 = p[i].y;
  79. }
  80. if (y0 > png.clip_bot || y1 < png.clip_top)
  81. return;
  82. if (y0 < png.clip_top)
  83. y0 = png.clip_top;
  84. if (y1 > png.clip_bot)
  85. y1 = png.clip_bot;
  86. for (y = floor(y0 + 0.5) + 0.5; y < y1; y++)
  87. line(p, n, y);
  88. }
  89. void png_polygon(struct path *p)
  90. {
  91. if (p->vertices[p->count - 1].mode != P_CLOSE)
  92. path_close(p);
  93. poly(p->vertices, p->count);
  94. png.modified = 1;
  95. }