GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-81301443e3
draw2.c
Go to the documentation of this file.
1 #include <math.h>
2 #include <string.h>
3 
4 #include <grass/gis.h>
5 #include <grass/display.h>
6 #include <grass/glocale.h>
7 #include "driver.h"
8 #include "path.h"
9 #include "clip.h"
10 
11 struct vector {
12  double x, y;
13 };
14 
15 /******************************************************************************/
16 
17 static struct path path;
18 
19 static int clip_mode = M_NONE;
20 static double epsilon = 0.0;
21 static struct path ll_path, clip_path, raw_path, eps_path;
22 
23 static struct vector cur;
24 
25 static struct rectangle clip;
26 
27 static int window_set;
28 
29 #define min(x, y) ((x) < (y) ? (x) : (y))
30 #define max(x, y) ((x) > (y) ? (x) : (y))
31 
32 /******************************************************************************/
33 
34 static int shift_count(double dx)
35 {
36  return (int)floor(dx / 360);
37 }
38 
39 static double shift_angle(double dx)
40 {
41  return shift_count(dx) * 360;
42 }
43 
44 static double coerce(double x)
45 {
46  x += 180;
47  x -= shift_angle(x);
48  x -= 180;
49  return x;
50 }
51 
52 static int euclidify(struct path *p, int no_pole)
53 {
54  double ux0 = clip.left;
55  double ux1 = clip.rite;
56  double x0, x1;
57  int lo, hi, count;
58  int i;
59 
60  x0 = x1 = p->vertices[0].x;
61 
62  for (i = 1; i < p->count; i++) {
63  if (fabs(p->vertices[i].y) < 89.9)
64  p->vertices[i].x = p->vertices[i - 1].x +
65  coerce(p->vertices[i].x - p->vertices[i - 1].x);
66 
67  x0 = min(x0, p->vertices[i].x);
68  x1 = max(x1, p->vertices[i].x);
69  }
70 
71  if (no_pole && fabs(p->vertices[p->count - 1].x - p->vertices[0].x) > 180)
72  return 0;
73 
74  lo = -shift_count(ux1 - x0);
75  hi = shift_count(x1 - ux0);
76  count = hi - lo + 1;
77 
78  for (i = 0; i < p->count; i++)
79  p->vertices[i].x -= lo * 360;
80 
81  return count;
82 }
83 
84 static void ll_wrap_path(struct path *dst, const struct path *src, int no_pole)
85 {
86  int count, i, j;
87 
88  path_copy(dst, src);
89 
90  count = euclidify(dst, no_pole);
91 
92  for (i = 0; i < count; i++) {
93  for (j = 0; j < src->count; j++) {
94  struct vertex *v = &dst->vertices[j];
95  path_append(dst, v->x - i * 360, v->y, v->mode);
96  }
97  }
98 }
99 
100 static void conv_path(struct path *dst, const struct path *src)
101 {
102  int i;
103 
104  path_copy(dst, src);
105 
106  for (i = 0; i < dst->count; i++) {
107  struct vertex *v = &dst->vertices[i];
108  v->x = D_u_to_d_col(v->x);
109  v->y = D_u_to_d_row(v->y);
110  }
111 }
112 
113 static void reduce_path(struct path *dst, const struct path *src, double eps)
114 {
115  struct vertex *v = &src->vertices[0];
116  int i;
117 
118  path_reset(dst);
119  path_append(dst, v->x, v->y, v->mode);
120 
121  for (i = 1; i < src->count - 1; i++) {
122  struct vertex *v0 = &dst->vertices[dst->count - 1];
123  struct vertex *v1 = &src->vertices[i];
124  struct vertex *v2 = &src->vertices[i + 1];
125 
126  if (fabs(v1->x - v0->x) < eps && fabs(v1->y - v0->y) < eps &&
127  fabs(v1->x - v2->x) < eps && fabs(v1->y - v2->y) < eps &&
128  v0->mode != P_MOVE && v1->mode != P_MOVE && (!v2->mode) != P_MOVE)
129  continue;
130 
131  path_append(dst, v1->x, v1->y, v1->mode);
132  }
133  v = &src->vertices[src->count - 1];
134  path_append(dst, v->x, v->y, v->mode);
135 }
136 
137 /******************************************************************************/
138 
139 /*!
140  * \brief set clipping window
141  *
142  * Sets the clipping window to the pixel window that corresponds
143  * to the current database region. This is the default.
144  *
145  * \param t top
146  * \param b bottom
147  * \param l left
148  * \param r right
149  */
150 
151 void D_set_clip(double t, double b, double l, double r)
152 {
153  clip.left = min(l, r);
154  clip.rite = max(l, r);
155  clip.bot = min(b, t);
156  clip.top = max(b, t);
157 
158  window_set = 1;
159 }
160 
161 /*!
162  * \brief set clipping window to map window
163  *
164  * Sets the clipping window to the pixel window that corresponds to the
165  * current database region. This is the default.
166  *
167  * \param ~
168  */
169 
170 void D_clip_to_map(void)
171 {
172  double t, b, l, r;
173 
174  D_get_src(&t, &b, &l, &r);
175  D_set_clip(t, b, l, r);
176 }
177 
179 {
180  clip_mode = mode;
181 }
182 
183 void D_set_reduction(double e)
184 {
185  epsilon = e;
186 }
187 
188 void D_line_width(double d)
189 {
190  COM_Line_width(d > 0 ? d : 0);
191 }
192 
193 void D_get_text_box(const char *text, double *t, double *b, double *l,
194  double *r)
195 {
196  double T, B, L, R;
197 
198  COM_Get_text_box(text, &T, &B, &L, &R);
199 
200  *t = D_d_to_u_row(T);
201  *b = D_d_to_u_row(B);
202  *l = D_d_to_u_col(L);
203  *r = D_d_to_u_col(R);
204 
205  if (*t < *b) {
206  double tmp = *t;
207  *t = *b;
208  *b = tmp;
209  }
210 
211  if (*r < *l) {
212  double tmp = *r;
213  *r = *l;
214  *l = tmp;
215  }
216 }
217 
218 /******************************************************************************/
219 
220 /* D_pos_abs(easting, northing): move to an absolute position
221  on the display using map coordinates */
222 void D_pos_abs(double x, double y)
223 {
224  cur.x = x;
225  cur.y = y;
226 
227  x = D_u_to_d_col(x);
228  y = D_u_to_d_row(y);
229 
230  COM_Pos_abs(x, y);
231 }
232 
233 void D_pos_rel(double x, double y)
234 {
235  D_pos_abs(cur.x + x, cur.y + y);
236 }
237 
238 /******************************************************************************/
239 
240 static void do_path(int no_pole)
241 {
242  struct path *p = &path;
243  struct clip planes;
244  int i;
245 
246  if (!window_set)
247  D_clip_to_map();
248 
249  if (D_is_lat_lon()) {
250  ll_wrap_path(&ll_path, p, no_pole);
251  p = &ll_path;
252  }
253 
254  switch (clip_mode) {
255  case M_NONE:
256  break;
257  case M_CULL:
258  D__set_clip_planes(&planes, &clip);
259  D__cull_path(&clip_path, p, &planes);
260  p = &clip_path;
261  break;
262  case M_CLIP:
263  D__set_clip_planes(&planes, &clip);
264  D__clip_path(&clip_path, p, &planes);
265  p = &clip_path;
266  break;
267  }
268 
269  conv_path(&raw_path, p);
270  p = &raw_path;
271 
272  if (epsilon > 0) {
273  reduce_path(&eps_path, p, epsilon);
274  p = &eps_path;
275  }
276 
277  COM_Begin();
278  for (i = 0; i < p->count; i++) {
279  struct vertex *v = &p->vertices[i];
280  switch (v->mode) {
281  case P_MOVE:
282  COM_Move(v->x, v->y);
283  break;
284  case P_CONT:
285  COM_Cont(v->x, v->y);
286  break;
287  case P_CLOSE:
288  COM_Close();
289  break;
290  }
291  }
292 }
293 
294 void D_begin(void)
295 {
296  path_begin(&path);
297 }
298 
299 void D_end(void)
300 {
301 }
302 
303 /* D_move_abs(x,y): move to an absolute position on the display using
304  display pixel coordinates */
305 void D_move_abs(double x, double y)
306 {
307  path_move(&path, x, y);
308 
309  cur.x = x;
310  cur.y = y;
311 }
312 
313 void D_cont_abs(double x, double y)
314 {
315  path_cont(&path, x, y);
316 
317  cur.x = x;
318  cur.y = y;
319 }
320 
321 void D_close(void)
322 {
323  path_close(&path);
324 }
325 
326 void D_stroke(void)
327 {
328  do_path(0);
329  COM_Stroke();
330 }
331 
332 void D_fill(void)
333 {
334  do_path(1);
335  COM_Fill();
336 }
337 
338 void D_dots(void)
339 {
340  struct path *p = &path;
341  int i;
342 
343  if (!window_set)
344  D_clip_to_map();
345 
346  for (i = 0; i < p->count; i++) {
347  struct vertex *v = &p->vertices[i];
348  double x = v->x;
349  double y = v->y;
350 
351  if (D_is_lat_lon())
352  x = coerce(x);
353 
354  if (clip_mode != M_NONE) {
355  if (x < clip.left || x > clip.rite)
356  continue;
357  if (y < clip.bot || y > clip.top)
358  continue;
359  }
360 
361  x = D_u_to_d_col(x);
362  y = D_u_to_d_row(y);
363 
364  COM_Point(x, y);
365  }
366 }
367 
368 /******************************************************************************/
369 
370 static void poly_abs(const double *x, const double *y, int n)
371 {
372  int i;
373 
374  if (n < 2)
375  return;
376 
377  D_begin();
378  D_move_abs(x[0], y[0]);
379  for (i = 1; i < n; i++)
380  D_cont_abs(x[i], y[i]);
381 }
382 
383 void D_polyline_abs(const double *x, const double *y, int n)
384 {
385  poly_abs(x, y, n);
386  D_stroke();
387 }
388 
389 void D_polygon_abs(const double *x, const double *y, int n)
390 {
391  poly_abs(x, y, n);
392  D_close();
393  D_fill();
394 }
395 
396 void D_polydots_abs(const double *x, const double *y, int n)
397 {
398  poly_abs(x, y, n);
399  D_dots();
400 }
401 
402 void D_line_abs(double x1, double y1, double x2, double y2)
403 {
404  D_begin();
405  D_move_abs(x1, y1);
406  D_cont_abs(x2, y2);
407  D_end();
408  D_stroke();
409 }
410 
411 void D_box_abs(double x1, double y1, double x2, double y2)
412 {
413  struct vector save = cur;
414 
415  D_begin();
416  D_move_abs(x1, y1);
417  D_cont_abs(x2, y1);
418  D_cont_abs(x2, y2);
419  D_cont_abs(x1, y2);
420  D_close();
421  D_end();
422  D_fill();
423 
424  cur = save;
425 }
426 
427 /******************************************************************************/
428 
429 static void poly_rel(const double *x, const double *y, int n)
430 {
431  int i;
432 
433  if (n < 2)
434  return;
435 
436  D_begin();
437  D_move_rel(x[0], y[0]);
438  for (i = 1; i < n; i++)
439  D_cont_rel(x[i], y[i]);
440 }
441 
442 void D_move_rel(double x, double y)
443 {
444  D_move_abs(cur.x + x, cur.y + y);
445 }
446 
447 void D_cont_rel(double x, double y)
448 {
449  D_cont_abs(cur.x + x, cur.y + y);
450 }
451 
452 void D_polydots_rel(const double *x, const double *y, int n)
453 {
454  poly_rel(x, y, n);
455  D_dots();
456 }
457 
458 void D_polyline_rel(const double *x, const double *y, int n)
459 {
460  poly_rel(x, y, n);
461  D_stroke();
462 }
463 
464 void D_polygon_rel(const double *x, const double *y, int n)
465 {
466  poly_rel(x, y, n);
467  D_close();
468  D_fill();
469 }
470 
471 void D_line_rel(double x1, double y1, double x2, double y2)
472 {
473  cur.x += x1;
474  cur.y += y1;
475 
476  x1 = cur.x;
477  y1 = cur.y;
478 
479  cur.x += x2;
480  cur.y += y2;
481 
482  x2 = cur.x;
483  y2 = cur.y;
484 
485  D_line_abs(x1, y1, x2, y2);
486 }
487 
488 void D_box_rel(double x2, double y2)
489 {
490  D_box_abs(cur.x, cur.y, cur.x + x2, cur.y + y2);
491 }
492 
493 /******************************************************************************/
void D__cull_path(struct path *dst, const struct path *src, const struct clip *clip)
Definition: clip.c:128
void D__clip_path(struct path *dst, const struct path *src, const struct clip *clip)
Definition: clip.c:145
void D__set_clip_planes(struct clip *clip, const struct rectangle *rect)
Definition: clip.c:109
double D_d_to_u_col(double)
screen to earth (x)
Definition: cnversions.c:441
double D_u_to_d_row(double)
earth to screen (north)
Definition: cnversions.c:518
int D_is_lat_lon(void)
Definition: cnversions.c:164
double D_u_to_d_col(double)
earth to screen (east)
Definition: cnversions.c:533
double D_d_to_u_row(double)
screen to earth (y)
Definition: cnversions.c:426
void D_get_src(double *, double *, double *, double *)
returns frame bounds in source coordinate system
Definition: cnversions.c:306
clip_mode
Definition: display.h:19
@ M_CULL
Definition: display.h:21
@ M_CLIP
Definition: display.h:22
@ M_NONE
Definition: display.h:20
void D_polydots_abs(const double *x, const double *y, int n)
Definition: draw2.c:396
void D_pos_abs(double x, double y)
Definition: draw2.c:222
void D_stroke(void)
Definition: draw2.c:326
void D_end(void)
Definition: draw2.c:299
void D_set_clip(double t, double b, double l, double r)
set clipping window
Definition: draw2.c:151
void D_move_rel(double x, double y)
Definition: draw2.c:442
void D_line_abs(double x1, double y1, double x2, double y2)
Definition: draw2.c:402
void D_get_text_box(const char *text, double *t, double *b, double *l, double *r)
Definition: draw2.c:193
void D_box_rel(double x2, double y2)
Definition: draw2.c:488
void D_fill(void)
Definition: draw2.c:332
void D_pos_rel(double x, double y)
Definition: draw2.c:233
void D_cont_rel(double x, double y)
Definition: draw2.c:447
void D_line_width(double d)
Definition: draw2.c:188
void D_polydots_rel(const double *x, const double *y, int n)
Definition: draw2.c:452
void D_cont_abs(double x, double y)
Definition: draw2.c:313
void D_line_rel(double x1, double y1, double x2, double y2)
Definition: draw2.c:471
void D_set_reduction(double e)
Definition: draw2.c:183
void D_clip_to_map(void)
set clipping window to map window
Definition: draw2.c:170
#define min(x, y)
Definition: draw2.c:29
void D_polyline_rel(const double *x, const double *y, int n)
Definition: draw2.c:458
#define max(x, y)
Definition: draw2.c:30
void D_dots(void)
Definition: draw2.c:338
void D_polyline_abs(const double *x, const double *y, int n)
Definition: draw2.c:383
void D_close(void)
Definition: draw2.c:321
void D_move_abs(double x, double y)
Definition: draw2.c:305
void D_begin(void)
Definition: draw2.c:294
void D_box_abs(double x1, double y1, double x2, double y2)
Definition: draw2.c:411
void D_set_clip_mode(int mode)
Definition: draw2.c:178
void D_polygon_rel(const double *x, const double *y, int n)
Definition: draw2.c:464
void D_polygon_abs(const double *x, const double *y, int n)
Definition: draw2.c:389
void COM_Close(void)
Definition: driver/draw.c:28
void COM_Cont(double x, double y)
Definition: driver/draw.c:22
void COM_Fill(void)
Definition: driver/draw.c:40
void COM_Stroke(void)
Definition: driver/draw.c:34
void COM_Move(double x, double y)
Definition: driver/draw.c:16
void COM_Begin(void)
Definition: driver/draw.c:10
void COM_Point(double x, double y)
Definition: driver/draw.c:46
void path_close(struct path *p)
Definition: driver/path.c:83
void path_copy(struct path *dst, const struct path *src)
Definition: driver/path.c:51
void path_reset(struct path *p)
Definition: driver/path.c:31
void path_begin(struct path *p)
Definition: driver/path.c:66
void path_cont(struct path *p, double x, double y)
Definition: driver/path.c:78
void path_append(struct path *p, double x, double y, int mode)
Definition: driver/path.c:37
void path_move(struct path *p, double x, double y)
Definition: driver/path.c:72
void COM_Pos_abs(double, double)
Definition: driver/move.c:4
void COM_Get_text_box(const char *, double *, double *, double *, double *)
Definition: get_t_box.c:4
void COM_Line_width(double)
int count
@ P_CONT
Definition: path.h:6
@ P_MOVE
Definition: path.h:5
@ P_CLOSE
Definition: path.h:7
double b
Definition: r_raster.c:39
double l
Definition: r_raster.c:39
double t
Definition: r_raster.c:39
double r
Definition: r_raster.c:39
Definition: clip.h:10
struct plane left rite bot top
Definition: clip.h:11
Definition: path.h:15
int count
Definition: path.h:17
struct vertex * vertices
Definition: path.h:16
Definition: clip.h:14
Definition: path.h:10
int mode
Definition: path.h:12
double x
Definition: path.h:11
double y
Definition: path.h:11
#define x