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);
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);
48 #define POINT struct point 61 void (*row_fill)(int, double, double);
62 int (*move)(int, int);
63 int (*cont)(int, int);
69 #define TOO_FEW_EDGES 2 71 #define OUT_OF_SYNC -1 95 int (*Move) (
int,
int),
int (*Cont) (
int,
int))
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);
107 if (st->top < st->bottom) {
108 st->ymin = iceil(st->top);
109 st->ymax = ifloor(st->bottom);
112 st->ymin = iceil(st->bottom);
113 st->ymax = ifloor(st->top);
133 st->row_fill = row_dotted_fill;
134 st->dotted_fill_gap = gap + 1;
137 st->row_fill = row_solid_fill;
140 #define X(e) (st->left + st->xconv * ((e) - st->window.west)) 141 #define Y(n) (st->top + st->yconv * (st->window.north - (n))) 143 #define EAST(x) (st->window.west + ((x)-st->left)/st->xconv) 144 #define NORTH(y) (st->window.north - ((y)-st->top)/st->yconv) 161 *y = ifloor(
Y(north) + 0.5);
207 void G_plot_line(
double east1,
double north1,
double east2,
double north2)
209 plot_line(east1, north1, east2, north2, fastline);
222 void G_plot_line2(
double east1,
double north1,
double east2,
double north2)
224 plot_line(east1, north1, east2, north2, slowline);
230 static void fastline(
double x1,
double y1,
double x2,
double y2)
232 st->move(ifloor(x1 + 0.5), ifloor(y1 + 0.5));
233 st->cont(ifloor(x2 + 0.5), ifloor(y2 + 0.5));
242 static void slowline(
double x1,
double y1,
double x2,
double y2)
246 int xstart, xstop, ystart, ystop;
251 if (fabs(dx) > fabs(dy)) {
256 xstart = iceil(x2 - 0.5);
257 xstop = ifloor(x1 + 0.5);
260 xstart = iceil(x1 - 0.5);
261 xstop = ifloor(x2 + 0.5);
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);
280 ystart = iceil(y2 - 0.5);
281 ystop = ifloor(y1 + 0.5);
284 ystart = iceil(y1 - 0.5);
285 ystop = ifloor(y2 + 0.5);
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);
298 static void plot_line(
double east1,
double north1,
double east2,
double north2,
299 void (*line)(
double,
double,
double,
double))
301 double x1, x2, y1, y2;
308 while ((east1 - east2) > 180)
310 else if (east2 > east1)
311 while ((east2 - east1) > 180)
313 while (east1 > st->window.east) {
317 while (east1 < st->window.west) {
324 line(x1, y1, x2, y2);
326 if (east2 > st->window.east || east2 < st->window.west) {
327 while (east2 > st->window.east) {
331 while (east2 < st->window.west) {
337 line(x1, y1, x2, y2);
343 line(x1, y1, x2, y2);
347 static double wrap_east(
double e0,
double e1)
349 while (e0 - e1 > 180)
351 while (e1 - e0 > 180)
379 double shift, E,
W = 0L;
384 st->row_fill = row_solid_fill;
407 if (pole && !edge(x0, y0, x0,
Y(90.0 * pole)))
410 for (i = 0; i < n; i++) {
411 e1 = wrap_east(e0, x[i]);
420 if (!edge(x0, y0, x1, y1))
427 if (pole && !edge(x0, y0, x0,
Y(90.0 * pole)))
431 while (E + shift > st->window.east)
433 while (E + shift < st->window.west)
435 shift1 =
X(x[n - 1] + shift) -
X(x[n - 1]);
441 for (i = 0; i < n; i++) {
444 if (!edge(x0, y0, x1, y1))
453 G_warning(
"Weird internal error: perimeter has odd number of points");
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");
466 st->row_fill(st->P[i].y, st->P[i - 1].x + shift1, st->P[i].x + shift1);
470 while (W + shift < st->window.west)
472 while (W + shift > st->window.east)
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);
502 int G_plot_area(
double *
const *xs,
double *
const *ys,
int *rpnts,
int rings)
508 double shift, E,
W = 0L;
510 int *shift1 =
NULL, shift2;
513 st->row_fill = row_solid_fill;
518 shift1 = (
int *)
G_calloc(
sizeof(
int), rings);
520 for (j = 0; j < rings; j++) {
542 if (pole && !edge(x0, y0, x0,
Y(90.0 * pole)))
545 for (i = 0; i < n; i++) {
546 e1 = wrap_east(e0, x[i]);
555 if (!edge(x0, y0, x1, y1))
562 if (pole && !edge(x0, y0, x0,
Y(90.0 * pole)))
566 while (E + shift > st->window.east)
568 while (E + shift < st->window.west)
570 shift1[j] =
X(x[n - 1] + shift) -
X(x[n - 1]);
576 for (i = 0; i < n; i++) {
579 if (!edge(x0, y0, x1, y1))
589 G_warning(
"Weird internal error: perimeter has odd number of points");
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");
603 st->row_fill(st->P[i].y, st->P[i - 1].x + shift1[j], st->P[i].x + shift1[j]);
611 while (W + shift < st->window.west)
613 while (W + shift > st->window.east)
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);
628 static int edge(
double x0,
double y0,
double x1,
double y1)
638 if (fabs(y0) > fabs(y1))
648 if (fabs(y0 - y1) < d)
667 m = (x0 - x1) / (y0 - y1);
668 x = m * (ystart - y0) + x0;
669 while (ystart <= ystop) {
670 if (!edge_point(x, ystart++))
678 static int edge_point(
double x,
int y)
681 if (y < st->ymin || y > st->ymax)
683 if (st->np >= st->npalloc) {
684 if (st->npalloc > 0) {
698 st->P[st->np++].y = y;
702 static int edge_order(
const void *aa,
const void *bb)
704 const struct point *a = aa, *b = bb;
719 static void row_solid_fill(
int y,
double x1,
double x2)
731 static void row_dotted_fill(
int y,
double x1,
double x2)
735 if (y != iceil(y / st->dotted_fill_gap) * st->dotted_fill_gap)
738 i1 = iceil(x1 / st->dotted_fill_gap) * st->dotted_fill_gap;
741 for (i = i1; i <= i2; i += st->dotted_fill_gap) {
748 static int ifloor(
double x)
758 static int iceil(
double x)
779 void G_plot_fx(
double (*f) (
double),
double east1,
double east2)
781 double east, north, north1;
785 incr = fabs(1.0 / st->xconv);
791 while ((east1 -= incr) > east2) {
799 while ((east1 += incr) < east2) {
int G_plot_area(double *const *xs, double *const *ys, int *rpnts, int rings)
Plot multiple polygons.
2D/3D raster map header (used also for region)
void G_plot_where_en(int x, int y, double *east, double *north)
Converts x,y to east,north.
int edge_order(const void *aa, const void *bb)
Determines points order during sorting.
void G_free(void *)
Free allocated memory.
void G_plot_fx(double(*f)(double), double east1, double east2)
Plot f(east1) to f(east2)
double top
Extent coordinates (top) - 3D data.
void G_setup_plot(double t, double b, double l, double r, int(*Move)(int, int), int(*Cont)(int, int))
Initialize plotting routines.
void G_setup_fill(int gap)
Set row_fill routine to row_solid_fill or row_dotted_fill.
void G_plot_where_xy(double east, double north, int *x, int *y)
Converts east,north to x,y.
void G_plot_line(double east1, double north1, double east2, double north2)
Plot line between latlon coordinates (fastline)
double bottom
Extent coordinates (bottom) - 3D data.
#define PROJECTION_LL
Projection code - Latitude-Longitude.
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.
void G_warning(const char *,...) __attribute__((format(printf
void G_plot_line2(double east1, double north1, double east2, double north2)
Plot line between latlon coordinates (slowline)
void G_plot_point(double east, double north)
Plot point.
int G_plot_polygon(const double *x, const double *y, int n)
Plot filled polygon with n vertices.