GRASS GIS 8 Programmer's Manual 8.4.1(2025)-45ca3179ab
Loading...
Searching...
No Matches
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
13 * GRASS 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
24void add_coor(SYMBCHAIN *chain, double x, double y)
25{
26 G_debug(5, " add_coor %f, %f", x, y);
27 if (chain->scount == chain->salloc) {
28 chain->salloc += 10;
29 chain->sx =
30 (double *)G_realloc(chain->sx, chain->salloc * sizeof(double));
31 chain->sy =
32 (double *)G_realloc(chain->sy, chain->salloc * sizeof(double));
33 }
34 chain->sx[chain->scount] = x;
35 chain->sy[chain->scount] = y;
36 chain->scount++;
37}
38
39/* draw chain
40 * s - scale
41 * ch - chain number
42 * rotation - degrees CCW from East
43 */
44int stroke_chain(SYMBPART *part, int ch, double s, double rotation)
45{
46 int k, l, first;
47 SYMBEL *elem;
48 SYMBCHAIN *chain;
49 double r;
50 double a1, a2, da;
51 double x, y, x0, y0;
52
53 G_debug(5, " stroke_chain(): ch = %d", ch);
54 chain = part->chain[ch];
55
56 G_debug(5, " element count = %d", chain->count);
57 first = 1;
58 for (k = 0; k < chain->count; k++) {
59 elem = chain->elem[k];
60 switch (elem->type) {
61 case S_LINE:
62 G_debug(5, " LINE count = %d", elem->coor.line.count);
63 for (l = 0; l < elem->coor.line.count; l++) {
64 x = s * elem->coor.line.x[l];
65 y = s * elem->coor.line.y[l];
66
67 if (rotation != 0.0)
68 G_rotate_around_point(0, 0, &x, &y, rotation);
69
70 add_coor(chain, x, y);
71 if (first) {
72 x0 = x;
73 y0 = y;
74 first = 0;
75 }
76 }
77 break;
78 case S_ARC:
79 if (s >= 50)
80 da = 1 * PI / 180; /* later calc from size and tolerance */
81 else
82 da = 10 * PI / 180;
83
84 r = elem->coor.arc.r;
85 G_debug(5, " ARC da = %f r = %f", da, r);
86
87 /* convert to positive angles */
88 a1 = PI * elem->coor.arc.a1 / 180;
89 if (a1 < 0)
90 a1 += 2 * PI;
91 a2 = PI * elem->coor.arc.a2 / 180;
92 if (a2 < 0)
93 a2 += 2 * PI;
94
95 if (elem->coor.arc.clock) { /* clockwise */
96 while (1) {
97 x = s * elem->coor.arc.x + s * r * cos(a1);
98 y = s * elem->coor.arc.y + s * r * sin(a1);
99
100 if (rotation != 0.0)
101 G_rotate_around_point(0, 0, &x, &y, rotation);
102
103 add_coor(chain, x, y);
104 if (first) {
105 x0 = x;
106 y0 = y;
107 first = 0;
108 }
109 if (a1 == a2)
110 break;
111 a1 -= da;
112 if (a1 < a2)
113 a1 = a2;
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", size,
165 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:66
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:33
void add_coor(SYMBCHAIN *chain, double x, double y)
Definition stroke.c:24
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:44
#define x