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