GRASS GIS 7 Programmer's Manual  7.9.dev(2021)-e5379bbd7
pngdriver/polygon.c
Go to the documentation of this file.
1 /*!
2  \file lib/pngdriver/polygon.c
3 
4  \brief GRASS png display driver - draw polygon
5 
6  (C) 2003-2014 by Per Henrik Johansen and the GRASS Development Team
7 
8  This program is free software under the GNU General Public License
9  (>=v2). Read the file COPYING that comes with GRASS for details.
10 
11  \author Per Henrik Johansen (original contributor)
12  \author Glynn Clements
13 */
14 
15 #include <stdlib.h>
16 #include <math.h>
17 #include <grass/gis.h>
18 
19 #include "path.h"
20 #include "pngdriver.h"
21 
22 static int cmp_double(const void *aa, const void *bb)
23 {
24  const double *a = aa;
25  const double *b = bb;
26 
27  return
28  *a > *b ? 1 :
29  *a < *b ? -1 :
30  0;
31 }
32 
33 static void fill(double x0, double x1, double y)
34 {
35  int yi = (int) floor(y);
36  int xi0 = (int) floor(x0 + 0.5);
37  int xi1 = (int) floor(x1 + 0.5);
38  unsigned int *p;
39  int x;
40 
41  if (yi >= png.clip_bot || yi < png.clip_top)
42  return;
43 
44  if (xi0 > png.clip_rite)
45  return;
46 
47  if (xi1 < png.clip_left)
48  return;
49 
50  if (xi0 < png.clip_left)
51  xi0 = png.clip_left;
52 
53  if (xi1 > png.clip_rite)
54  xi1 = png.clip_rite;
55 
56  p = &png.grid[yi * png.width + xi0];
57 
58  for (x = xi0; x < xi1; x++)
59  *p++ = png.current_color;
60 }
61 
62 static void line(const struct vertex *p, int n, double y)
63 {
64  static double *xs;
65  static int max_x;
66  int num_x = 0;
67  int i;
68 
69  for (i = 1; i < n; i++) {
70  const struct vertex *p0 = &p[i - 1];
71  const struct vertex *p1 = &p[i];
72  const struct vertex *tmp;
73  double x;
74 
75  if (p0->y == p1->y)
76  continue;
77 
78  if (p0->y > p1->y)
79  tmp = p0, p0 = p1, p1 = tmp;
80 
81  if (p0->y > y)
82  continue;
83 
84  if (p1->y <= y)
85  continue;
86 
87  x = p1->x * (y - p0->y) + p0->x * (p1->y - y);
88  x /= p1->y - p0->y;
89 
90  if (num_x >= max_x) {
91  max_x += 20;
92  xs = G_realloc(xs, max_x * sizeof(double));
93  }
94 
95  xs[num_x++] = x;
96  }
97 
98  qsort(xs, num_x, sizeof(double), cmp_double);
99 
100  for (i = 0; i + 1 < num_x; i += 2)
101  fill(xs[i], xs[i + 1], y);
102 }
103 
104 static void poly(const struct vertex *p, int n)
105 {
106  double y0, y1, y;
107  int i;
108 
109  if (n < 3)
110  return;
111 
112  y0 = y1 = p[0].y;
113 
114  for (i = 1; i < n; i++) {
115  if (y0 > p[i].y)
116  y0 = p[i].y;
117 
118  if (y1 < p[i].y)
119  y1 = p[i].y;
120  }
121 
122  if (y0 > png.clip_bot || y1 < png.clip_top)
123  return;
124 
125  if (y0 < png.clip_top)
126  y0 = png.clip_top;
127 
128  if (y1 > png.clip_bot)
129  y1 = png.clip_bot;
130 
131  for (y = floor(y0 + 0.5) + 0.5; y < y1; y++)
132  line(p, n, y);
133 }
134 
135 /*!
136  \brief Draw polygon
137 */
138 void png_polygon(struct path *p)
139 {
140  if (p->vertices[p->count - 1].mode != P_CLOSE)
141  path_close(p);
142 
143  poly(p->vertices, p->count);
144 
145  png.modified = 1;
146 }
147 
int width
Definition: pngdriver.h:43
double clip_left
Definition: pngdriver.h:42
Definition: path.h:11
int current_color
Definition: pngdriver.h:34
GRASS png display driver - header file.
void path_close(struct path *p)
Definition: driver/path.c:84
double y
Definition: path.h:12
double clip_top
Definition: pngdriver.h:42
int count
Definition: path.h:18
double clip_rite
Definition: pngdriver.h:42
double clip_bot
Definition: pngdriver.h:42
#define x
struct png_state png
int modified
Definition: pngdriver.h:47
struct vertex * vertices
Definition: path.h:17
double b
Definition: r_raster.c:39
unsigned int * grid
Definition: pngdriver.h:44
void png_polygon(struct path *p)
Draw polygon.
Definition: path.h:16
#define G_realloc(p, n)
Definition: defs/gis.h:114
Definition: path.h:8
int mode
Definition: path.h:13
double x
Definition: path.h:12