GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-a2d9ad8523
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 *a > *b ? 1 : *a < *b ? -1 : 0;
28 }
29 
30 static void fill(double x0, double x1, double y)
31 {
32  int yi = (int)floor(y);
33  int xi0 = (int)floor(x0 + 0.5);
34  int xi1 = (int)floor(x1 + 0.5);
35  unsigned int *p;
36  int x;
37 
38  if (yi >= png.clip_bot || yi < png.clip_top)
39  return;
40 
41  if (xi0 > png.clip_rite)
42  return;
43 
44  if (xi1 < png.clip_left)
45  return;
46 
47  if (xi0 < png.clip_left)
48  xi0 = png.clip_left;
49 
50  if (xi1 > png.clip_rite)
51  xi1 = png.clip_rite;
52 
53  p = &png.grid[yi * png.width + xi0];
54 
55  for (x = xi0; x < xi1; x++)
56  *p++ = png.current_color;
57 }
58 
59 static void line(const struct vertex *p, int n, double y)
60 {
61  static double *xs;
62  static int max_x;
63  int num_x = 0;
64  int i;
65 
66  for (i = 1; i < n; i++) {
67  const struct vertex *p0 = &p[i - 1];
68  const struct vertex *p1 = &p[i];
69  const struct vertex *tmp;
70  double x;
71 
72  if (p0->y == p1->y)
73  continue;
74 
75  if (p0->y > p1->y)
76  tmp = p0, p0 = p1, p1 = tmp;
77 
78  if (p0->y > y)
79  continue;
80 
81  if (p1->y <= y)
82  continue;
83 
84  x = p1->x * (y - p0->y) + p0->x * (p1->y - y);
85  x /= p1->y - p0->y;
86 
87  if (num_x >= max_x) {
88  max_x += 20;
89  xs = G_realloc(xs, max_x * sizeof(double));
90  }
91 
92  xs[num_x++] = x;
93  }
94 
95  qsort(xs, num_x, sizeof(double), cmp_double);
96 
97  for (i = 0; i + 1 < num_x; i += 2)
98  fill(xs[i], xs[i + 1], y);
99 }
100 
101 static void poly(const struct vertex *p, int n)
102 {
103  double y0, y1, y;
104  int i;
105 
106  if (n < 3)
107  return;
108 
109  y0 = y1 = p[0].y;
110 
111  for (i = 1; i < n; i++) {
112  if (y0 > p[i].y)
113  y0 = p[i].y;
114 
115  if (y1 < p[i].y)
116  y1 = p[i].y;
117  }
118 
119  if (y0 > png.clip_bot || y1 < png.clip_top)
120  return;
121 
122  if (y0 < png.clip_top)
123  y0 = png.clip_top;
124 
125  if (y1 > png.clip_bot)
126  y1 = png.clip_bot;
127 
128  for (y = floor(y0 + 0.5) + 0.5; y < y1; y++)
129  line(p, n, y);
130 }
131 
132 /*!
133  \brief Draw polygon
134  */
135 void png_polygon(struct path *p)
136 {
137  if (p->vertices[p->count - 1].mode != P_CLOSE)
138  path_close(p);
139 
140  poly(p->vertices, p->count);
141 
142  png.modified = 1;
143 }
#define G_realloc(p, n)
Definition: defs/gis.h:96
void path_close(struct path *p)
Definition: driver/path.c:83
@ P_CLOSE
Definition: path.h:7
struct png_state png
void png_polygon(struct path *p)
Draw polygon.
GRASS png display driver - header file.
double b
Definition: r_raster.c:39
Definition: path.h:15
int count
Definition: path.h:17
struct vertex * vertices
Definition: path.h:16
double clip_left
Definition: pngdriver.h:41
double clip_bot
Definition: pngdriver.h:41
double clip_top
Definition: pngdriver.h:41
int current_color
Definition: pngdriver.h:33
unsigned int * grid
Definition: pngdriver.h:43
int width
Definition: pngdriver.h:42
double clip_rite
Definition: pngdriver.h:41
int modified
Definition: pngdriver.h:46
Definition: path.h:10
int mode
Definition: path.h:12
double y
Definition: path.h:11
#define x