GRASS GIS 8 Programmer's Manual 8.2.1RC1(2022)-exported
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
22static 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
33static 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
62static 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
104static 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*/
138void 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
double b
void path_close(struct path *p)
Definition: path.c:84
@ P_CLOSE
Definition: path.h:8
struct png_state png
void png_polygon(struct path *p)
Draw polygon.
GRASS png display driver - header file.
Definition: path.h:16
int count
Definition: path.h:18
struct vertex * vertices
Definition: path.h:17
double clip_left
Definition: pngdriver.h:42
double clip_bot
Definition: pngdriver.h:42
double clip_top
Definition: pngdriver.h:42
int current_color
Definition: pngdriver.h:34
unsigned int * grid
Definition: pngdriver.h:44
int width
Definition: pngdriver.h:43
double clip_rite
Definition: pngdriver.h:42
int modified
Definition: pngdriver.h:47
Definition: path.h:11
int mode
Definition: path.h:13
double y
Definition: path.h:12
#define x