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