GRASS 8 Programmer's Manual 8.6.0dev(2026)-5f4f7ad06c
Loading...
Searching...
No Matches
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
11struct vector {
12 double x, y;
13};
14
15/******************************************************************************/
16
17static struct path path;
18
19static int clip_mode = M_NONE;
20static double epsilon = 0.0;
21static struct path ll_path, clip_path, raw_path, eps_path;
22
23static struct vector cur;
24
25static struct rectangle clip;
26
27static 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
34static int shift_count(double dx)
35{
36 return (int)floor(dx / 360);
37}
38
39static double shift_angle(double dx)
40{
41 return shift_count(dx) * 360;
42}
43
44static double coerce(double x)
45{
46 x += 180;
47 x -= shift_angle(x);
48 x -= 180;
49 return x;
50}
51
52static 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
84static 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
100static 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
113static 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 */
150void D_set_clip(double t, double b, double l, double r)
151{
152 clip.left = min(l, r);
153 clip.rite = max(l, r);
154 clip.bot = min(b, t);
155 clip.top = max(b, t);
156
157 window_set = 1;
158}
159
160/*!
161 * \brief set clipping window to map window
162 *
163 * Sets the clipping window to the pixel window that corresponds to the
164 * current database region. This is the default.
165 *
166 * \param ~
167 */
169{
170 double t, b, l, r;
171
172 D_get_src(&t, &b, &l, &r);
173 D_set_clip(t, b, l, r);
174}
175
177{
178 clip_mode = mode;
179}
180
181void D_set_reduction(double e)
182{
183 epsilon = e;
184}
185
186void D_line_width(double d)
187{
188 COM_Line_width(d > 0 ? d : 0);
189}
190
191void D_get_text_box(const char *text, double *t, double *b, double *l,
192 double *r)
193{
194 double T, B, L, R;
195
196 COM_Get_text_box(text, &T, &B, &L, &R);
197
198 *t = D_d_to_u_row(T);
199 *b = D_d_to_u_row(B);
200 *l = D_d_to_u_col(L);
201 *r = D_d_to_u_col(R);
202
203 if (*t < *b) {
204 double tmp = *t;
205 *t = *b;
206 *b = tmp;
207 }
208
209 if (*r < *l) {
210 double tmp = *r;
211 *r = *l;
212 *l = tmp;
213 }
214}
215
216/******************************************************************************/
217
218/* D_pos_abs(easting, northing): move to an absolute position
219 on the display using map coordinates */
220void D_pos_abs(double x, double y)
221{
222 cur.x = x;
223 cur.y = y;
224
225 x = D_u_to_d_col(x);
226 y = D_u_to_d_row(y);
227
228 COM_Pos_abs(x, y);
229}
230
231void D_pos_rel(double x, double y)
232{
233 D_pos_abs(cur.x + x, cur.y + y);
234}
235
236/******************************************************************************/
237
238static void do_path(int no_pole)
239{
240 struct path *p = &path;
241 struct clip planes;
242 int i;
243
244 if (!window_set)
246
247 if (D_is_lat_lon()) {
248 ll_wrap_path(&ll_path, p, no_pole);
249 p = &ll_path;
250 }
251
252 switch (clip_mode) {
253 case M_NONE:
254 break;
255 case M_CULL:
258 p = &clip_path;
259 break;
260 case M_CLIP:
263 p = &clip_path;
264 break;
265 }
266
267 conv_path(&raw_path, p);
268 p = &raw_path;
269
270 if (epsilon > 0) {
271 reduce_path(&eps_path, p, epsilon);
272 p = &eps_path;
273 }
274
275 COM_Begin();
276 for (i = 0; i < p->count; i++) {
277 struct vertex *v = &p->vertices[i];
278 switch (v->mode) {
279 case P_MOVE:
280 COM_Move(v->x, v->y);
281 break;
282 case P_CONT:
283 COM_Cont(v->x, v->y);
284 break;
285 case P_CLOSE:
286 COM_Close();
287 break;
288 }
289 }
290}
291
292void D_begin(void)
293{
295}
296
297void D_end(void)
298{
299}
300
301/* D_move_abs(x,y): move to an absolute position on the display using
302 display pixel coordinates */
303void D_move_abs(double x, double y)
304{
305 path_move(&path, x, y);
306
307 cur.x = x;
308 cur.y = y;
309}
310
311void D_cont_abs(double x, double y)
312{
313 path_cont(&path, x, y);
314
315 cur.x = x;
316 cur.y = y;
317}
318
319void D_close(void)
320{
322}
323
324void D_stroke(void)
325{
326 do_path(0);
327 COM_Stroke();
328}
329
330void D_fill(void)
331{
332 do_path(1);
333 COM_Fill();
334}
335
336void D_dots(void)
337{
338 struct path *p = &path;
339 int i;
340
341 if (!window_set)
343
344 for (i = 0; i < p->count; i++) {
345 struct vertex *v = &p->vertices[i];
346 double x = v->x;
347 double y = v->y;
348
349 if (D_is_lat_lon())
350 x = coerce(x);
351
352 if (clip_mode != M_NONE) {
353 if (x < clip.left || x > clip.rite)
354 continue;
356 continue;
357 }
358
359 x = D_u_to_d_col(x);
360 y = D_u_to_d_row(y);
361
362 COM_Point(x, y);
363 }
364}
365
366/******************************************************************************/
367
368static void poly_abs(const double *x, const double *y, int n)
369{
370 int i;
371
372 if (n < 2)
373 return;
374
375 D_begin();
376 D_move_abs(x[0], y[0]);
377 for (i = 1; i < n; i++)
378 D_cont_abs(x[i], y[i]);
379}
380
381void D_polyline_abs(const double *x, const double *y, int n)
382{
383 poly_abs(x, y, n);
384 D_stroke();
385}
386
387void D_polygon_abs(const double *x, const double *y, int n)
388{
389 poly_abs(x, y, n);
390 D_close();
391 D_fill();
392}
393
394void D_polydots_abs(const double *x, const double *y, int n)
395{
396 poly_abs(x, y, n);
397 D_dots();
398}
399
400void D_line_abs(double x1, double y1, double x2, double y2)
401{
402 D_begin();
403 D_move_abs(x1, y1);
404 D_cont_abs(x2, y2);
405 D_end();
406 D_stroke();
407}
408
409void D_box_abs(double x1, double y1, double x2, double y2)
410{
411 struct vector save = cur;
412
413 D_begin();
414 D_move_abs(x1, y1);
415 D_cont_abs(x2, y1);
416 D_cont_abs(x2, y2);
417 D_cont_abs(x1, y2);
418 D_close();
419 D_end();
420 D_fill();
421
422 cur = save;
423}
424
425/******************************************************************************/
426
427static void poly_rel(const double *x, const double *y, int n)
428{
429 int i;
430
431 if (n < 2)
432 return;
433
434 D_begin();
435 D_move_rel(x[0], y[0]);
436 for (i = 1; i < n; i++)
437 D_cont_rel(x[i], y[i]);
438}
439
440void D_move_rel(double x, double y)
441{
442 D_move_abs(cur.x + x, cur.y + y);
443}
444
445void D_cont_rel(double x, double y)
446{
447 D_cont_abs(cur.x + x, cur.y + y);
448}
449
450void D_polydots_rel(const double *x, const double *y, int n)
451{
452 poly_rel(x, y, n);
453 D_dots();
454}
455
456void D_polyline_rel(const double *x, const double *y, int n)
457{
458 poly_rel(x, y, n);
459 D_stroke();
460}
461
462void D_polygon_rel(const double *x, const double *y, int n)
463{
464 poly_rel(x, y, n);
465 D_close();
466 D_fill();
467}
468
469void D_line_rel(double x1, double y1, double x2, double y2)
470{
471 cur.x += x1;
472 cur.y += y1;
473
474 x1 = cur.x;
475 y1 = cur.y;
476
477 cur.x += x2;
478 cur.y += y2;
479
480 x2 = cur.x;
481 y2 = cur.y;
482
483 D_line_abs(x1, y1, x2, y2);
484}
485
486void D_box_rel(double x2, double y2)
487{
488 D_box_abs(cur.x, cur.y, cur.x + x2, cur.y + y2);
489}
490
491/******************************************************************************/
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:428
double D_u_to_d_row(double)
earth to screen (north)
Definition cnversions.c:500
int D_is_lat_lon(void)
Definition cnversions.c:155
double D_u_to_d_col(double)
earth to screen (east)
Definition cnversions.c:514
double D_d_to_u_row(double)
screen to earth (y)
Definition cnversions.c:414
void D_get_src(double *, double *, double *, double *)
returns frame bounds in source coordinate system
Definition cnversions.c:297
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:394
void D_pos_abs(double x, double y)
Definition draw2.c:220
void D_stroke(void)
Definition draw2.c:324
void D_end(void)
Definition draw2.c:297
void D_set_clip(double t, double b, double l, double r)
set clipping window
Definition draw2.c:150
void D_move_rel(double x, double y)
Definition draw2.c:440
void D_line_abs(double x1, double y1, double x2, double y2)
Definition draw2.c:400
void D_get_text_box(const char *text, double *t, double *b, double *l, double *r)
Definition draw2.c:191
void D_box_rel(double x2, double y2)
Definition draw2.c:486
void D_fill(void)
Definition draw2.c:330
void D_pos_rel(double x, double y)
Definition draw2.c:231
void D_cont_rel(double x, double y)
Definition draw2.c:445
void D_line_width(double d)
Definition draw2.c:186
void D_polydots_rel(const double *x, const double *y, int n)
Definition draw2.c:450
void D_cont_abs(double x, double y)
Definition draw2.c:311
void D_line_rel(double x1, double y1, double x2, double y2)
Definition draw2.c:469
void D_set_reduction(double e)
Definition draw2.c:181
void D_clip_to_map(void)
set clipping window to map window
Definition draw2.c:168
#define min(x, y)
Definition draw2.c:29
void D_polyline_rel(const double *x, const double *y, int n)
Definition draw2.c:456
#define max(x, y)
Definition draw2.c:30
void D_dots(void)
Definition draw2.c:336
void D_polyline_abs(const double *x, const double *y, int n)
Definition draw2.c:381
void D_close(void)
Definition draw2.c:319
void D_move_abs(double x, double y)
Definition draw2.c:303
void D_begin(void)
Definition draw2.c:292
void D_box_abs(double x1, double y1, double x2, double y2)
Definition draw2.c:409
void D_set_clip_mode(int mode)
Definition draw2.c:176
void D_polygon_rel(const double *x, const double *y, int n)
Definition draw2.c:462
void D_polygon_abs(const double *x, const double *y, int n)
Definition draw2.c:387
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 path.h:10
int mode
Definition path.h:12
double x
Definition path.h:11
double y
Definition path.h:11
#define x