grass  7.8.6
About: GRASS (Geographic Resources Analysis Support System) is a raster- and vector-based GIS, image processing system, graphics production system and spatial modeling system.
  Fossies Dox: grass-7.8.6.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

plot.c
Go to the documentation of this file.
1/*!
2 * \file lib/gis/plot.c
3 *
4 * \brief GIS Library - Plotting functions.
5 *
6 * Plot lines and filled polygons. Input space is current
7 * window. Output space and output functions are user
8 * defined. Converts input east,north lines and polygons to output x,y
9 * and calls user supplied line drawing routines to do the plotting.
10 *
11 * Handles global wrap-around for lat-lon locations.
12 *
13 * Does not perform window clipping.
14 * Clipping must be done by the line draw routines supplied by the user.
15 *
16 * Note:
17 * Hopefully, cartographic style projection plotting will be added later.
18 *
19 * (C) 2001-2008, 2013 by the GRASS Development Team
20 *
21 * This program is free software under the GNU General Public License
22 * (>=v2). Read the file COPYING that comes with GRASS for details.
23 *
24 * \author Original author CERL
25 */
26
27#include <stdlib.h>
28#include <math.h>
29#include <grass/gis.h>
30
31static void fastline(double, double, double, double);
32static void slowline(double, double, double, double);
33static void plot_line(double, double, double, double, void (*)());
34static double wrap_east(double, double);
35static int edge(double, double, double, double);
36static int edge_point(double, int);
37
38static int edge_order(const void *, const void *);
39static void row_solid_fill(int, double, double);
40static void row_dotted_fill(int, double, double);
41static int ifloor(double);
42static int iceil(double);
43
44struct point {
45 double x;
46 int y;
47};
48#define POINT struct point
49
50static struct state {
51 struct Cell_head window;
52 double xconv, yconv;
53 double left, right, top, bottom;
54 int ymin, ymax;
56
58 int np;
60
61 void (*row_fill)(int, double, double);
62 int (*move)(int, int);
63 int (*cont)(int, int);
65
66static struct state *st = &state;
67
68#define OK 0
69#define TOO_FEW_EDGES 2
70#define NO_MEMORY 1
71#define OUT_OF_SYNC -1
72
73/*!
74 * \brief Initialize plotting routines
75 *
76 * Initializes the plotting capability. This routine must be called
77 * once before calling the G_plot_*() routines described below. The
78 * parameters <i>t, b, l, r</i> are the top, bottom, left, and right
79 * of the output x,y coordinate space. They are not integers, but
80 * doubles to allow for subpixel registration of the input and output
81 * coordinate spaces. The input coordinate space is assumed to be the
82 * current GRASS region, and the routines supports both planimetric
83 * and latitude-longitude coordinate systems.
84
85 * <b>Move</b> and <b>Cont</b> are subroutines that will draw lines in x,y
86 * space. They will be called as follows:
87 * - Move(x, y) move to x,y (no draw)
88 * - Cont(x, y) draw from previous position to x,y. Cont(~) is responsible for clipping
89 *
90 * \param t,b,l,r top, bottom, left, right
91 * \param move Move function
92 * \param Cont Cont function
93 */
94void G_setup_plot(double t, double b, double l, double r,
95 int (*Move) (int, int), int (*Cont) (int, int))
96{
98
99 st->left = l;
100 st->right = r;
101 st->top = t;
102 st->bottom = b;
103
104 st->xconv = (st->right - st->left) / (st->window.east - st->window.west);
105 st->yconv = (st->bottom - st->top) / (st->window.north - st->window.south);
106
107 if (st->top < st->bottom) {
108 st->ymin = iceil(st->top);
109 st->ymax = ifloor(st->bottom);
110 }
111 else {
112 st->ymin = iceil(st->bottom);
113 st->ymax = ifloor(st->top);
114 }
115
116 st->move = Move;
117 st->cont = Cont;
118}
119
120/*!
121 * \brief Set row_fill routine to row_solid_fill or row_dotted_fill
122 *
123 * After calling this function, G_plot_polygon() and G_plot_area()
124 * fill shapes with solid or dotted lines. If gap is greater than
125 * zero, this value will be used for row_dotted_fill. Otherwise,
126 * row_solid_fill is used.
127 *
128 * \param gap
129 */
130void G_setup_fill(int gap)
131{
132 if (gap > 0) {
134 st->dotted_fill_gap = gap + 1;
135 }
136 else
138}
139
140#define X(e) (st->left + st->xconv * ((e) - st->window.west))
141#define Y(n) (st->top + st->yconv * (st->window.north - (n)))
142
143#define EAST(x) (st->window.west + ((x)-st->left)/st->xconv)
144#define NORTH(y) (st->window.north - ((y)-st->top)/st->yconv)
145
146
147/*!
148 * \brief Converts east,north to x,y
149 *
150 * The map coordinates <i>east,north</i> are converted
151 * to pixel coordinates <i>x,y</i>.
152 *
153 * \param east easting
154 * \param north nothing
155 * \param x x coordinate
156 * \param y y coordinate
157 */
158void G_plot_where_xy(double east, double north, int *x, int *y)
159{
160 *x = ifloor(X(G_adjust_easting(east, &st->window)) + 0.5);
161 *y = ifloor(Y(north) + 0.5);
162}
163
164/*!
165 * \brief Converts x,y to east,north
166 *
167 * The pixel coordinates <i>x,y</i> are converted to map
168 * coordinates <i>east,north</i>.
169 *
170 * \param x x coordinate
171 * \param y y coordinate
172 * \param east easting
173 * \param north northing
174 */
175
176void G_plot_where_en(int x, int y, double *east, double *north)
177{
178 *east = G_adjust_easting(EAST(x), &st->window);
179 *north = NORTH(y);
180}
181
182/*!
183 \brief Plot point
184
185 \param east easting
186 \param north northing
187*/
188void G_plot_point(double east, double north)
189{
190 int x, y;
191
192 G_plot_where_xy(east, north, &x, &y);
193 st->move(x, y);
194 st->cont(x, y);
195}
196
197/*!
198 * \brief Plot line between latlon coordinates (fastline)
199 *
200 * A line from <i>east1,north1</i> to <i>east2,north2</i> is plotted
201 * in output x,y coordinates (e.g. pixels for graphics.) This routine
202 * handles global wrap-around for latitude-longitude databases.
203 *
204 * \param east1, north1 first point (start line node)
205 * \param east2, north2 second point (end line node)
206 */
207void G_plot_line(double east1, double north1, double east2, double north2)
208{
209 plot_line(east1, north1, east2, north2, fastline);
210}
211
212/*!
213 * \brief Plot line between latlon coordinates (slowline)
214 *
215 * A line from <i>east1,north1</i> to <i>east2,north2</i> is plotted
216 * in output x,y coordinates (e.g. pixels for graphics.) This routine
217 * handles global wrap-around for latitude-longitude databases.
218 *
219 * \param east1, north1 first point (start line node)
220 * \param east2, north2 second point (end line node)
221 */
222void G_plot_line2(double east1, double north1, double east2, double north2)
223{
224 plot_line(east1, north1, east2, north2, slowline);
225}
226
227/* fastline converts double rows/cols to ints then plots
228 * this is ok for graphics, but not the best for vector to raster
229 */
230static void fastline(double x1, double y1, double x2, double y2)
231{
232 st->move(ifloor(x1 + 0.5), ifloor(y1 + 0.5));
233 st->cont(ifloor(x2 + 0.5), ifloor(y2 + 0.5));
234}
235
236/* NOTE (shapiro):
237 * I think the adding of 0.5 in slowline is not correct
238 * the output window (left, right, top, bottom) should already
239 * be adjusted for this: left=-0.5; right = window.cols-0.5;
240 */
241
242static void slowline(double x1, double y1, double x2, double y2)
243{
244 double dx, dy;
245 double m, b;
246 int xstart, xstop, ystart, ystop;
247
248 dx = x2 - x1;
249 dy = y2 - y1;
250
251 if (fabs(dx) > fabs(dy)) {
252 m = dy / dx;
253 b = y1 - m * x1;
254
255 if (x1 > x2) {
256 xstart = iceil(x2 - 0.5);
257 xstop = ifloor(x1 + 0.5);
258 }
259 else {
260 xstart = iceil(x1 - 0.5);
261 xstop = ifloor(x2 + 0.5);
262 }
263 if (xstart <= xstop) {
264 ystart = ifloor(m * xstart + b + 0.5);
265 st->move(xstart, ystart);
266 while (xstart <= xstop) {
267 st->cont(xstart++, ystart);
268 ystart = ifloor(m * xstart + b + 0.5);
269 }
270 }
271 }
272 else {
273 if (dx == dy) /* they both might be 0 */
274 m = 1.;
275 else
276 m = dx / dy;
277 b = x1 - m * y1;
278
279 if (y1 > y2) {
280 ystart = iceil(y2 - 0.5);
281 ystop = ifloor(y1 + 0.5);
282 }
283 else {
284 ystart = iceil(y1 - 0.5);
285 ystop = ifloor(y2 + 0.5);
286 }
287 if (ystart <= ystop) {
288 xstart = ifloor(m * ystart + b + 0.5);
289 st->move(xstart, ystart);
290 while (ystart <= ystop) {
291 st->cont(xstart, ystart++);
292 xstart = ifloor(m * ystart + b + 0.5);
293 }
294 }
295 }
296}
297
298static void plot_line(double east1, double north1, double east2, double north2,
299 void (*line)(double, double, double, double))
300{
301 double x1, x2, y1, y2;
302
303 y1 = Y(north1);
304 y2 = Y(north2);
305
306 if (st->window.proj == PROJECTION_LL) {
307 if (east1 > east2)
308 while ((east1 - east2) > 180)
309 east2 += 360;
310 else if (east2 > east1)
311 while ((east2 - east1) > 180)
312 east1 += 360;
313 while (east1 > st->window.east) {
314 east1 -= 360.0;
315 east2 -= 360.0;
316 }
317 while (east1 < st->window.west) {
318 east1 += 360.0;
319 east2 += 360.0;
320 }
321 x1 = X(east1);
322 x2 = X(east2);
323
324 line(x1, y1, x2, y2);
325
326 if (east2 > st->window.east || east2 < st->window.west) {
327 while (east2 > st->window.east) {
328 east1 -= 360.0;
329 east2 -= 360.0;
330 }
331 while (east2 < st->window.west) {
332 east1 += 360.0;
333 east2 += 360.0;
334 }
335 x1 = X(east1);
336 x2 = X(east2);
337 line(x1, y1, x2, y2);
338 }
339 }
340 else {
341 x1 = X(east1);
342 x2 = X(east2);
343 line(x1, y1, x2, y2);
344 }
345}
346
347static double wrap_east(double e0, double e1)
348{
349 while (e0 - e1 > 180)
350 e1 += 360.0;
351 while (e1 - e0 > 180)
352 e1 -= 360.0;
353
354 return e1;
355}
356
357
358/*!
359 * \brief Plot filled polygon with n vertices
360 *
361 * The polygon, described by the <i>n</i> vertices
362 * <i>east,north</i>, is plotted in the output x,y space as a filled polygon.
363 *
364 * \param x coordinates of vertices
365 * \param y coordinates of vertices
366 * \param n number of vertices
367 *
368 * \return 0 on success
369 * \return 2 n < 3
370 * \return -1 weird internal error
371 * \return 1 no memory
372 */
373int G_plot_polygon(const double *x, const double *y, int n)
374{
375 int i;
376 int pole;
377 double x0, x1;
378 double y0, y1;
379 double shift, E, W = 0L;
380 double e0, e1;
381 int shift1, shift2;
382
383 if (!st->row_fill)
385
386 if (n < 3)
387 return TOO_FEW_EDGES;
388
389 /* traverse the perimeter */
390
391 st->np = 0;
392 shift1 = 0;
393
394 /* global wrap-around for lat-lon, part1 */
395 if (st->window.proj == PROJECTION_LL) {
396 /*
397 pole = G_pole_in_polygon(x,y,n);
398 */
399 pole = 0;
400
401 e0 = x[n - 1];
402 E = W = e0;
403
404 x0 = X(e0);
405 y0 = Y(y[n - 1]);
406
407 if (pole && !edge(x0, y0, x0, Y(90.0 * pole)))
408 return NO_MEMORY;
409
410 for (i = 0; i < n; i++) {
411 e1 = wrap_east(e0, x[i]);
412 if (e1 > E)
413 E = e1;
414 if (e1 < W)
415 W = e1;
416
417 x1 = X(e1);
418 y1 = Y(y[i]);
419
420 if (!edge(x0, y0, x1, y1))
421 return NO_MEMORY;
422
423 x0 = x1;
424 y0 = y1;
425 e0 = e1;
426 }
427 if (pole && !edge(x0, y0, x0, Y(90.0 * pole)))
428 return NO_MEMORY;
429
430 shift = 0; /* shift into window */
431 while (E + shift > st->window.east)
432 shift -= 360.0;
433 while (E + shift < st->window.west)
434 shift += 360.0;
435 shift1 = X(x[n - 1] + shift) - X(x[n - 1]);
436 }
437 else {
438 x0 = X(x[n - 1]);
439 y0 = Y(y[n - 1]);
440
441 for (i = 0; i < n; i++) {
442 x1 = X(x[i]);
443 y1 = Y(y[i]);
444 if (!edge(x0, y0, x1, y1))
445 return NO_MEMORY;
446 x0 = x1;
447 y0 = y1;
448 }
449 }
450
451 /* check if perimeter has odd number of points */
452 if (st->np & 1) {
453 G_warning("Weird internal error: perimeter has odd number of points");
454 return OUT_OF_SYNC;
455 }
456
457 /* sort the edge points by col(x) and then by row(y) */
458 qsort(st->P, st->np, sizeof(POINT), edge_order);
459
460 /* plot */
461 for (i = 1; i < st->np; i += 2) {
462 if (st->P[i].y != st->P[i - 1].y) {
463 G_warning("Weird internal error: edge leaves row");
464 return OUT_OF_SYNC;
465 }
466 st->row_fill(st->P[i].y, st->P[i - 1].x + shift1, st->P[i].x + shift1);
467 }
468 if (st->window.proj == PROJECTION_LL) { /* now do wrap-around, part 2 */
469 shift = 0;
470 while (W + shift < st->window.west)
471 shift += 360.0;
472 while (W + shift > st->window.east)
473 shift -= 360.0;
474 shift2 = X(x[n - 1] + shift) - X(x[n - 1]);
475 if (shift2 != shift1) {
476 for (i = 1; i < st->np; i += 2) {
477 st->row_fill(st->P[i].y, st->P[i - 1].x + shift2, st->P[i].x + shift2);
478 }
479 }
480 }
481 return OK;
482}
483
484/*!
485 * \brief Plot multiple polygons
486 *
487 * Like G_plot_polygon(), except it takes a set of polygons, each with
488 * npts[<i>i</i>] vertices, where the number of polygons is specified
489 * with the <i>rings</i> argument. It is especially useful for
490 * plotting vector areas with interior islands.
491 *
492 * \param xs pointer to pointer for X's
493 * \param ys pointer to pointer for Y's
494 * \param rpnts array of ints w/ num points per ring
495 * \param rings number of rings
496 *
497 * \return 0 on success
498 * \return 2 n < 3
499 * \return -1 weird internal error
500 * \return 1 no memory
501 */
502int G_plot_area(double *const *xs, double *const *ys, int *rpnts, int rings)
503{
504 int i, j, n;
505 int pole;
506 double x0, x1, *x;
507 double y0, y1, *y;
508 double shift, E, W = 0L;
509 double e0, e1;
510 int *shift1 = NULL, shift2;
511
512 if (!st->row_fill)
514
515 /* traverse the perimeter */
516
517 st->np = 0;
518 shift1 = (int *)G_calloc(sizeof(int), rings);
519
520 for (j = 0; j < rings; j++) {
521 n = rpnts[j];
522
523 if (n < 3)
524 return TOO_FEW_EDGES;
525
526 x = xs[j];
527 y = ys[j];
528
529 /* global wrap-around for lat-lon, part1 */
530 if (st->window.proj == PROJECTION_LL) {
531 /*
532 pole = G_pole_in_polygon(x,y,n);
533 */
534 pole = 0;
535
536 e0 = x[n - 1];
537 E = W = e0;
538
539 x0 = X(e0);
540 y0 = Y(y[n - 1]);
541
542 if (pole && !edge(x0, y0, x0, Y(90.0 * pole)))
543 return NO_MEMORY;
544
545 for (i = 0; i < n; i++) {
546 e1 = wrap_east(e0, x[i]);
547 if (e1 > E)
548 E = e1;
549 if (e1 < W)
550 W = e1;
551
552 x1 = X(e1);
553 y1 = Y(y[i]);
554
555 if (!edge(x0, y0, x1, y1))
556 return NO_MEMORY;
557
558 x0 = x1;
559 y0 = y1;
560 e0 = e1;
561 }
562 if (pole && !edge(x0, y0, x0, Y(90.0 * pole)))
563 return NO_MEMORY;
564
565 shift = 0; /* shift into window */
566 while (E + shift > st->window.east)
567 shift -= 360.0;
568 while (E + shift < st->window.west)
569 shift += 360.0;
570 shift1[j] = X(x[n - 1] + shift) - X(x[n - 1]);
571 }
572 else {
573 x0 = X(x[n - 1]);
574 y0 = Y(y[n - 1]);
575
576 for (i = 0; i < n; i++) {
577 x1 = X(x[i]);
578 y1 = Y(y[i]);
579 if (!edge(x0, y0, x1, y1))
580 return NO_MEMORY;
581 x0 = x1;
582 y0 = y1;
583 }
584 }
585 } /* for() */
586
587 /* check if perimeter has odd number of points */
588 if (st->np & 1) {
589 G_warning("Weird internal error: perimeter has odd number of points");
590 return OUT_OF_SYNC;
591 }
592
593 /* sort the edge points by col(x) and then by row(y) */
594 qsort(st->P, st->np, sizeof(POINT), &edge_order);
595
596 /* plot */
597 for (j = 0; j < rings; j++) {
598 for (i = 1; i < st->np; i += 2) {
599 if (st->P[i].y != st->P[i - 1].y) {
600 G_warning("Weird internal error: edge leaves row");
601 return OUT_OF_SYNC;
602 }
603 st->row_fill(st->P[i].y, st->P[i - 1].x + shift1[j], st->P[i].x + shift1[j]);
604 }
605 if (st->window.proj == PROJECTION_LL) { /* now do wrap-around, part 2 */
606 n = rpnts[j];
607 x = xs[j];
608 y = ys[j];
609
610 shift = 0;
611 while (W + shift < st->window.west)
612 shift += 360.0;
613 while (W + shift > st->window.east)
614 shift -= 360.0;
615 shift2 = X(x[n - 1] + shift) - X(x[n - 1]);
616 if (shift2 != shift1[j]) {
617 for (i = 1; i < st->np; i += 2) {
618 st->row_fill(st->P[i].y, st->P[i - 1].x + shift2, st->P[i].x + shift2);
619 }
620 }
621 }
622 }
623 G_free(shift1);
624 return OK;
625
626}
627
628static int edge(double x0, double y0, double x1, double y1)
629{
630 double m, d;
631 double x;
632 int ystart, ystop;
633 int exp;
634
635 /* tolerance to avoid FPE */
637 if (y0 != y1) {
638 if (fabs(y0) > fabs(y1))
639 d = fabs(y0);
640 else
641 d = fabs(y1);
642
643 d = frexp(d, &exp);
644 exp -= 53;
645 d = ldexp(d, exp);
646 }
647
648 if (fabs(y0 - y1) < d)
649 return 1;
650
651 if (y0 < y1) {
652 ystart = iceil(y0);
653 ystop = ifloor(y1);
654 if (ystop == y1)
655 ystop--; /* if line stops at row center, don't include point */
656 }
657 else {
658 ystart = iceil(y1);
659 ystop = ifloor(y0);
660 if (ystop == y0)
661 ystop--; /* if line stops at row center, don't include point */
662 }
663
664 if (ystart > ystop)
665 return 1; /* does not cross center line of row */
666
667 m = (x0 - x1) / (y0 - y1);
668 x = m * (ystart - y0) + x0;
669 while (ystart <= ystop) {
670 if (!edge_point(x, ystart++))
671 return 0;
672 x += m;
673 }
674
675 return 1;
676}
677
678static int edge_point(double x, int y)
679{
680
681 if (y < st->ymin || y > st->ymax)
682 return 1;
683 if (st->np >= st->npalloc) {
684 if (st->npalloc > 0) {
685 st->npalloc *= 2;
686 st->P = (POINT *) G_realloc(st->P, st->npalloc * sizeof(POINT));
687 }
688 else {
689 st->npalloc = 32;
690 st->P = (POINT *) G_malloc(st->npalloc * sizeof(POINT));
691 }
692 if (st->P == NULL) {
693 st->npalloc = 0;
694 return 0;
695 }
696 }
697 st->P[st->np].x = x;
698 st->P[st->np++].y = y;
699 return 1;
700}
701
702static int edge_order(const void *aa, const void *bb)
703{
704 const struct point *a = aa, *b = bb;
705
706 if (a->y < b->y)
707 return (-1);
708 if (a->y > b->y)
709 return (1);
710
711 if (a->x < b->x)
712 return (-1);
713 if (a->x > b->x)
714 return (1);
715
716 return (0);
717}
718
719static void row_solid_fill(int y, double x1, double x2)
720{
721 int i1, i2;
722
723 i1 = iceil(x1);
724 i2 = ifloor(x2);
725 if (i1 <= i2) {
726 st->move(i1, y);
727 st->cont(i2, y);
728 }
729}
730
731static void row_dotted_fill(int y, double x1, double x2)
732{
733 int i1, i2, i;
734
736 return;
737
739 i2 = ifloor(x2);
740 if (i1 <= i2) {
741 for (i = i1; i <= i2; i += st->dotted_fill_gap) {
742 st->move(i, y);
743 st->cont(i, y);
744 }
745 }
746}
747
748static int ifloor(double x)
749{
750 int i;
751
752 i = (int)x;
753 if (i > x)
754 i--;
755 return i;
756}
757
758static int iceil(double x)
759{
760 int i;
761
762 i = (int)x;
763 if (i < x)
764 i++;
765 return i;
766}
767
768/*!
769 * \brief Plot f(east1) to f(east2)
770 *
771 * The function <i>f(east)</i> is plotted from <i>east1</i> to
772 * <i>east2</i>. The function <i>f(east)</i> must return the map
773 * northing coordinate associated with east.
774 *
775 * \param f plotting function
776 * \param east1 easting (first point)
777 * \param east2 easting (second point)
778 */
779void G_plot_fx(double (*f) (double), double east1, double east2)
780{
781 double east, north, north1;
782 double incr;
783
784
785 incr = fabs(1.0 / st->xconv);
786
787 east = east1;
788 north = f(east1);
789
790 if (east1 > east2) {
791 while ((east1 -= incr) > east2) {
792 north1 = f(east1);
793 G_plot_line(east, north, east1, north1);
794 north = north1;
795 east = east1;
796 }
797 }
798 else {
799 while ((east1 += incr) < east2) {
800 north1 = f(east1);
801 G_plot_line(east, north, east1, north1);
802 north = north1;
803 east = east1;
804 }
805 }
806
807 G_plot_line(east, north, east2, f(east2));
808}
#define NULL
Definition: ccmath.h:32
static struct @14 window
void G_free(void *buf)
Free allocated memory.
Definition: alloc.c:149
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition: error.c:204
void G_get_set_window(struct Cell_head *window)
Get the current working window (region)
Definition: set_window.c:35
double G_adjust_easting(double east, const struct Cell_head *window)
Returns east not smaller than west.
Definition: window_map.c:58
#define GRASS_EPSILON
Definition: gis.h:149
#define PROJECTION_LL
Projection code - Latitude-Longitude.
Definition: gis.h:116
static void line(double m[2][3], double x0, double y0, double x1, double y1)
Definition: icon.c:20
static uint16 x0
Definition: lrand48.c:35
static uint16 x1
Definition: lrand48.c:35
static uint16 x2
Definition: lrand48.c:35
#define W
Definition: ogsf.h:140
int G_plot_area(double *const *xs, double *const *ys, int *rpnts, int rings)
Plot multiple polygons.
Definition: plot.c:502
void G_plot_line2(double east1, double north1, double east2, double north2)
Plot line between latlon coordinates (slowline)
Definition: plot.c:222
static int edge_order(const void *, const void *)
Definition: plot.c:702
static double wrap_east(double, double)
Definition: plot.c:347
int G_plot_polygon(const double *x, const double *y, int n)
Plot filled polygon with n vertices.
Definition: plot.c:373
#define OUT_OF_SYNC
Definition: plot.c:71
void G_plot_where_en(int x, int y, double *east, double *north)
Converts x,y to east,north.
Definition: plot.c:176
static void slowline(double, double, double, double)
Definition: plot.c:242
#define X(e)
Definition: plot.c:140
static int iceil(double)
Definition: plot.c:758
#define POINT
Definition: plot.c:48
void G_plot_where_xy(double east, double north, int *x, int *y)
Converts east,north to x,y.
Definition: plot.c:158
static struct state state
void G_setup_fill(int gap)
Set row_fill routine to row_solid_fill or row_dotted_fill.
Definition: plot.c:130
static void plot_line(double, double, double, double, void(*)())
void G_setup_plot(double t, double b, double l, double r, int(*Move)(int, int), int(*Cont)(int, int))
Initialize plotting routines.
Definition: plot.c:94
static int edge_point(double, int)
Definition: plot.c:678
#define NORTH(y)
Definition: plot.c:144
void G_plot_fx(double(*f)(double), double east1, double east2)
Plot f(east1) to f(east2)
Definition: plot.c:779
void G_plot_line(double east1, double north1, double east2, double north2)
Plot line between latlon coordinates (fastline)
Definition: plot.c:207
static int edge(double, double, double, double)
Definition: plot.c:628
static void row_solid_fill(int, double, double)
Definition: plot.c:719
#define Y(n)
Definition: plot.c:141
#define NO_MEMORY
Definition: plot.c:70
static void fastline(double, double, double, double)
Definition: plot.c:230
#define OK
Definition: plot.c:68
void G_plot_point(double east, double north)
Plot point.
Definition: plot.c:188
static struct state * st
Definition: plot.c:66
#define EAST(x)
Definition: plot.c:143
#define TOO_FEW_EDGES
Definition: plot.c:69
static void row_dotted_fill(int, double, double)
Definition: plot.c:731
static int ifloor(double)
Definition: plot.c:748
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
2D/3D raster map header (used also for region)
Definition: gis.h:414
double north
Extent coordinates (north)
Definition: gis.h:459
double east
Extent coordinates (east)
Definition: gis.h:463
int proj
Projection code.
Definition: gis.h:445
double south
Extent coordinates (south)
Definition: gis.h:461
double west
Extent coordinates (west)
Definition: gis.h:465
Definition: plot.c:44
int y
Definition: plot.c:46
double x
Definition: plot.c:45
Definition: area.c:16
int npalloc
Definition: plot.c:59
int ymin
Definition: plot.c:54
int(* move)(int, int)
Definition: plot.c:62
int dotted_fill_gap
Definition: plot.c:55
struct point * P
Definition: plot.c:57
int np
Definition: plot.c:58
void(* row_fill)(int, double, double)
Definition: plot.c:61
double xconv
Definition: plot.c:52
int ymax
Definition: plot.c:54
double L
Definition: rhumbline.c:42
double right
Definition: plot.c:53
double E
Definition: area_ellipse.c:19
int(* cont)(int, int)
Definition: plot.c:63
double bottom
Definition: plot.c:53
double top
Definition: plot.c:53
double yconv
Definition: plot.c:52
double north
Definition: area.c:26
double left
Definition: plot.c:53
struct Cell_head window
Definition: area.c:17
static float d[4][4]
Definition: trans.c:49
static unsigned int a
Definition: unfl.c:8
#define x