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