GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
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 
31 static void fastline(double, double, double, double);
32 static void slowline(double, double, double, double);
33 static void plot_line(double, double, double, double, void (*)());
34 static double wrap_east(double, double);
35 static int edge(double, double, double, double);
36 static int edge_point(double, int);
37 
38 static int edge_order(const void *, const void *);
39 static void row_solid_fill(int, double, double);
40 static void row_dotted_fill(int, double, double);
41 static int ifloor(double);
42 static int iceil(double);
43 
44 struct point {
45  double x;
46  int y;
47 };
48 #define POINT struct point
49 
50 static struct state {
51  struct Cell_head window;
52  double xconv, yconv;
53  double left, right, top, bottom;
54  int ymin, ymax;
55  int dotted_fill_gap;
56 
57  POINT *P;
58  int np;
59  int npalloc;
60 
61  void (*row_fill)(int, double, double);
62  int (*move)(int, int);
63  int (*cont)(int, int);
64 } state;
65 
66 static 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  */
94 void G_setup_plot(double t, double b, double l, double r,
95  int (*Move) (int, int), int (*Cont) (int, int))
96 {
97  G_get_set_window(&st->window);
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  */
130 void G_setup_fill(int gap)
131 {
132  if (gap > 0) {
133  st->row_fill = row_dotted_fill;
134  st->dotted_fill_gap = gap + 1;
135  }
136  else
137  st->row_fill = row_solid_fill;
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  */
158 void 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 
176 void 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 */
188 void 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  */
207 void 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  */
222 void 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  */
230 static 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 
242 static 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 
298 static 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 
347 static 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  */
373 int 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)
384  st->row_fill = row_solid_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  */
502 int 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)
513  st->row_fill = row_solid_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 
628 static 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 */
636  d = GRASS_EPSILON;
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 
678 static 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 
702 static 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 
719 static 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 
731 static void row_dotted_fill(int y, double x1, double x2)
732 {
733  int i1, i2, i;
734 
735  if (y != iceil(y / st->dotted_fill_gap) * st->dotted_fill_gap)
736  return;
737 
738  i1 = iceil(x1 / st->dotted_fill_gap) * st->dotted_fill_gap;
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 
748 static int ifloor(double x)
749 {
750  int i;
751 
752  i = (int)x;
753  if (i > x)
754  i--;
755  return i;
756 }
757 
758 static 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  */
779 void 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 }
int G_plot_area(double *const *xs, double *const *ys, int *rpnts, int rings)
Plot multiple polygons.
Definition: plot.c:502
#define G_malloc(n)
Definition: defs/gis.h:112
#define EAST(x)
Definition: plot.c:143
2D/3D raster map header (used also for region)
Definition: gis.h:423
#define GRASS_EPSILON
Definition: gis.h:159
void G_plot_where_en(int x, int y, double *east, double *north)
Converts x,y to east,north.
Definition: plot.c:176
#define OUT_OF_SYNC
Definition: plot.c:71
int edge_order(const void *aa, const void *bb)
Determines points order during sorting.
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:149
void G_plot_fx(double(*f)(double), double east1, double east2)
Plot f(east1) to f(east2)
Definition: plot.c:779
#define NORTH(y)
Definition: plot.c:144
#define NULL
Definition: ccmath.h:32
#define x
#define G_calloc(m, n)
Definition: defs/gis.h:113
#define Y(n)
Definition: plot.c:141
#define W
Definition: ogsf.h:140
double top
Extent coordinates (top) - 3D data.
Definition: gis.h:477
struct state * st
Definition: parser.c:104
double l
Definition: r_raster.c:39
double t
Definition: r_raster.c:39
#define NO_MEMORY
Definition: plot.c:70
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
void G_setup_fill(int gap)
Set row_fill routine to row_solid_fill or row_dotted_fill.
Definition: plot.c:130
double b
Definition: r_raster.c:39
void G_plot_where_xy(double east, double north, int *x, int *y)
Converts east,north to x,y.
Definition: plot.c:158
void G_plot_line(double east1, double north1, double east2, double north2)
Plot line between latlon coordinates (fastline)
Definition: plot.c:207
#define OK
Definition: plot.c:68
double bottom
Extent coordinates (bottom) - 3D data.
Definition: gis.h:479
#define PROJECTION_LL
Projection code - Latitude-Longitude.
Definition: gis.h:116
void G_get_set_window(struct Cell_head *)
Get the current working window (region)
double G_adjust_easting(double, const struct Cell_head *)
Returns east not smaller than west.
#define TOO_FEW_EDGES
Definition: plot.c:69
void G_warning(const char *,...) __attribute__((format(printf
#define G_realloc(p, n)
Definition: defs/gis.h:114
#define X(e)
Definition: plot.c:140
void G_plot_line2(double east1, double north1, double east2, double north2)
Plot line between latlon coordinates (slowline)
Definition: plot.c:222
#define POINT
Definition: plot.c:48
void G_plot_point(double east, double north)
Plot point.
Definition: plot.c:188
struct state state
Definition: parser.c:103
int G_plot_polygon(const double *x, const double *y, int n)
Plot filled polygon with n vertices.
Definition: plot.c:373
double r
Definition: r_raster.c:39