GRASS GIS 8 Programmer's Manual 8.2.0(2022)-exported
stroke.c
Go to the documentation of this file.
1/****************************************************************************
2*
3* MODULE: Symbol library
4*
5* AUTHOR(S): Radim Blazek
6*
7* PURPOSE: Stroke symbol
8*
9* COPYRIGHT: (C) 2001 by the GRASS Development Team
10*
11* This program is free software under the GNU General Public
12* License (>=v2). Read the file COPYING that comes with GRASS
13* for details.
14*
15*****************************************************************************/
16
17#include <stdlib.h>
18#include <math.h>
19#include <grass/gis.h>
20#include <grass/symbol.h>
21
22#define PI M_PI
23
24
25void add_coor(SYMBCHAIN *chain, double x, double y)
26{
27 G_debug(5, " add_coor %f, %f", x, y);
28 if (chain->scount == chain->salloc) {
29 chain->salloc += 10;
30 chain->sx = (double *)G_realloc(chain->sx, chain->salloc * sizeof(double));
31 chain->sy = (double *)G_realloc(chain->sy, chain->salloc * sizeof(double));
32 }
33 chain->sx[chain->scount] = x;
34 chain->sy[chain->scount] = y;
35 chain->scount++;
36}
37
38/* draw chain
39 * s - scale
40 * ch - chain number
41 * rotation - degrees CCW from East
42 */
43int stroke_chain(SYMBPART *part, int ch, double s, double rotation)
44{
45 int k, l, first;
46 SYMBEL *elem;
47 SYMBCHAIN *chain;
48 double r;
49 double a1, a2, da;
50 double x, y, x0, y0;
51
52 G_debug(5, " stroke_chain(): ch = %d", ch);
53 chain = part->chain[ch];
54
55 G_debug(5, " element count = %d", chain->count);
56 first = 1;
57 for (k = 0; k < chain->count; k++) {
58 elem = chain->elem[k];
59 switch (elem->type) {
60 case S_LINE:
61 G_debug(5, " LINE count = %d", elem->coor.line.count);
62 for (l = 0; l < elem->coor.line.count; l++) {
63 x = s * elem->coor.line.x[l];
64 y = s * elem->coor.line.y[l];
65
66 if (rotation != 0.0)
67 G_rotate_around_point(0, 0, &x, &y, rotation);
68
69 add_coor(chain, x, y);
70 if (first) {
71 x0 = x;
72 y0 = y;
73 first = 0;
74 }
75 }
76 break;
77 case S_ARC:
78 if (s >= 50)
79 da = 1 * PI / 180; /* later calc from size and tolerance */
80 else
81 da = 10 * PI / 180;
82
83 r = elem->coor.arc.r;
84 G_debug(5, " ARC da = %f r = %f", da, r);
85
86 /* convert to positive angles */
87 a1 = PI * elem->coor.arc.a1 / 180;
88 if (a1 < 0)
89 a1 += 2 * PI;
90 a2 = PI * elem->coor.arc.a2 / 180;
91 if (a2 < 0)
92 a2 += 2 * PI;
93
94 if (elem->coor.arc.clock) { /* clockwise */
95 while (1) {
96 x = s * elem->coor.arc.x + s * r * cos(a1);
97 y = s * elem->coor.arc.y + s * r * sin(a1);
98
99 if (rotation != 0.0)
100 G_rotate_around_point(0, 0, &x, &y, rotation);
101
102 add_coor(chain, x, y);
103 if (first) {
104 x0 = x;
105 y0 = y;
106 first = 0;
107 }
108 if (a1 == a2)
109 break;
110 a1 -= da;
111 if (a1 < a2)
112 a1 = a2;
113 }
114
115 }
116 else {
117 while (1) {
118 x = s * elem->coor.arc.x + s * r * cos(a1);
119 y = s * elem->coor.arc.y + s * r * sin(a1);
120
121 if (rotation != 0.0)
122 G_rotate_around_point(0, 0, &x, &y, rotation);
123
124 add_coor(chain, x, y);
125 if (first) {
126 x0 = x;
127 y0 = y;
128 first = 0;
129 }
130 if (a1 == a2)
131 break;
132 a1 += da;
133 if (a1 > a2)
134 a1 = a2;
135 }
136 }
137 break;
138 }
139 }
140 if (part->type == S_POLYGON) {
141 add_coor(chain, x0, y0); /* Close ring */
142 }
143
144 return 0;
145}
146
147/*!
148 * \brief Stroke symbol to form used for Xdriver.
149 *
150 * tolerance currently not supported
151 *
152 * \param Symb pointer to
153 * \param size symbol size
154 * \param rotation symbol rotation, degrees CCW from East
155 * \param tolerance currently not supported
156 *
157 */
158void S_stroke(SYMBOL *Symb, double size, double rotation, int tolerance)
159{
160 int i, j;
161 double s;
162 SYMBPART *part;
163
164 G_debug(3, "S_stroke(): size = %.2f, rotation = %.2f, tolerance = %d",
165 size, rotation, tolerance);
166
167 /* TODO: support for tolerance */
168
169 s = size * Symb->scale;
170
171 for (i = 0; i < Symb->count; i++) {
172 G_debug(4, " part %d", i);
173 part = Symb->part[i];
174 switch (part->type) {
175 case S_POLYGON:
176 for (j = 0; j < part->count; j++) { /* RINGS */
177 stroke_chain(part, j, s, rotation);
178 }
179 break;
180 case S_STRING: /* string has 1 chain */
181 stroke_chain(part, 0, s, rotation);
182 break;
183 }
184 }
185}
int G_debug(int level, const char *msg,...)
Print debugging message.
Definition: debug.c:65
double l
double r
void G_rotate_around_point(double X0, double Y0, double *X1, double *Y1, double angle)
Rotate point (double version)
Definition: rotate.c:35
void add_coor(SYMBCHAIN *chain, double x, double y)
Definition: stroke.c:25
void S_stroke(SYMBOL *Symb, double size, double rotation, int tolerance)
Stroke symbol to form used for Xdriver.
Definition: stroke.c:158
#define PI
Definition: stroke.c:22
int stroke_chain(SYMBPART *part, int ch, double s, double rotation)
Definition: stroke.c:43
#define x