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,
34 void (*)(
double,
double,
double,
double));
35 static double wrap_east(
double,
double);
36 static int edge(
double,
double,
double,
double);
37 static int edge_point(
double,
int);
39 static int edge_order(
const void *,
const void *);
40 static void row_solid_fill(
int,
double,
double);
41 static void row_dotted_fill(
int,
double,
double);
42 static int ifloor(
double);
43 static int iceil(
double);
50 #define POINT struct point
63 void (*row_fill)(int, double, double);
64 int (*move)(int, int);
65 int (*cont)(int, int);
71 #define TOO_FEW_EDGES 2
73 #define OUT_OF_SYNC -1
98 int (*Cont)(
int,
int))
107 st->xconv = (
st->right -
st->left) / (
st->window.east -
st->window.west);
108 st->yconv = (
st->bottom -
st->top) / (
st->window.north -
st->window.south);
110 if (
st->top <
st->bottom) {
111 st->ymin = iceil(
st->top);
112 st->ymax = ifloor(
st->bottom);
115 st->ymin = iceil(
st->bottom);
116 st->ymax = ifloor(
st->top);
136 st->row_fill = row_dotted_fill;
137 st->dotted_fill_gap = gap + 1;
140 st->row_fill = row_solid_fill;
143 #define X(e) (st->left + st->xconv * ((e) - st->window.west))
144 #define Y(n) (st->top + st->yconv * (st->window.north - (n)))
146 #define EAST(x) (st->window.west + ((x) - st->left) / st->xconv)
147 #define NORTH(y) (st->window.north - ((y) - st->top) / st->yconv)
163 *y = ifloor(
Y(north) + 0.5);
209 void G_plot_line(
double east1,
double north1,
double east2,
double north2)
211 plot_line(east1, north1, east2, north2, fastline);
224 void G_plot_line2(
double east1,
double north1,
double east2,
double north2)
226 plot_line(east1, north1, east2, north2, slowline);
232 static void fastline(
double x1,
double y1,
double x2,
double y2)
234 st->move(ifloor(x1 + 0.5), ifloor(y1 + 0.5));
235 st->cont(ifloor(x2 + 0.5), ifloor(y2 + 0.5));
244 static void slowline(
double x1,
double y1,
double x2,
double y2)
248 int xstart, xstop, ystart, ystop;
253 if (fabs(dx) > fabs(dy)) {
258 xstart = iceil(x2 - 0.5);
259 xstop = ifloor(x1 + 0.5);
262 xstart = iceil(x1 - 0.5);
263 xstop = ifloor(x2 + 0.5);
265 if (xstart <= xstop) {
266 ystart = ifloor(m * xstart +
b + 0.5);
267 st->move(xstart, ystart);
268 while (xstart <= xstop) {
269 st->cont(xstart++, ystart);
270 ystart = ifloor(m * xstart +
b + 0.5);
282 ystart = iceil(y2 - 0.5);
283 ystop = ifloor(y1 + 0.5);
286 ystart = iceil(y1 - 0.5);
287 ystop = ifloor(y2 + 0.5);
289 if (ystart <= ystop) {
290 xstart = ifloor(m * ystart +
b + 0.5);
291 st->move(xstart, ystart);
292 while (ystart <= ystop) {
293 st->cont(xstart, ystart++);
294 xstart = ifloor(m * ystart +
b + 0.5);
300 static void plot_line(
double east1,
double north1,
double east2,
double north2,
301 void (*line)(
double,
double,
double,
double))
303 double x1, x2, y1, y2;
310 while ((east1 - east2) > 180)
312 else if (east2 > east1)
313 while ((east2 - east1) > 180)
315 while (east1 >
st->window.east) {
319 while (east1 < st->window.west) {
326 line(x1, y1, x2, y2);
328 if (east2 >
st->window.east || east2 < st->window.west) {
329 while (east2 >
st->window.east) {
333 while (east2 < st->window.west) {
339 line(x1, y1, x2, y2);
345 line(x1, y1, x2, y2);
349 static double wrap_east(
double e0,
double e1)
351 while (e0 - e1 > 180)
353 while (e1 - e0 > 180)
380 double shift, E,
W = 0L;
385 st->row_fill = row_solid_fill;
408 if (pole && !edge(x0, y0, x0,
Y(90.0 * pole)))
411 for (i = 0; i < n; i++) {
412 e1 = wrap_east(e0,
x[i]);
421 if (!edge(x0, y0, x1, y1))
428 if (pole && !edge(x0, y0, x0,
Y(90.0 * pole)))
432 while (E + shift >
st->window.east)
434 while (E + shift < st->window.west)
436 shift1 =
X(
x[n - 1] + shift) -
X(
x[n - 1]);
442 for (i = 0; i < n; i++) {
445 if (!edge(x0, y0, x1, y1))
454 G_warning(
"Weird internal error: perimeter has odd number of points");
462 for (i = 1; i <
st->np; i += 2) {
463 if (
st->P[i].y !=
st->P[i - 1].y) {
464 G_warning(
"Weird internal error: edge leaves row");
467 st->row_fill(
st->P[i].y,
st->P[i - 1].x + shift1,
st->P[i].x + shift1);
471 while (
W + shift < st->window.west)
473 while (
W + shift >
st->window.east)
475 shift2 =
X(
x[n - 1] + shift) -
X(
x[n - 1]);
476 if (shift2 != shift1) {
477 for (i = 1; i <
st->np; i += 2) {
478 st->row_fill(
st->P[i].y,
st->P[i - 1].x + shift2,
479 st->P[i].x + shift2);
504 int G_plot_area(
double *
const *xs,
double *
const *ys,
int *rpnts,
int rings)
510 double shift, E,
W = 0L;
512 int *shift1 =
NULL, shift2;
515 st->row_fill = row_solid_fill;
520 shift1 = (
int *)
G_calloc(
sizeof(
int), rings);
522 for (j = 0; j < rings; j++) {
544 if (pole && !edge(x0, y0, x0,
Y(90.0 * pole)))
547 for (i = 0; i < n; i++) {
548 e1 = wrap_east(e0,
x[i]);
557 if (!edge(x0, y0, x1, y1))
564 if (pole && !edge(x0, y0, x0,
Y(90.0 * pole)))
568 while (E + shift >
st->window.east)
570 while (E + shift < st->window.west)
572 shift1[j] =
X(
x[n - 1] + shift) -
X(
x[n - 1]);
578 for (i = 0; i < n; i++) {
581 if (!edge(x0, y0, x1, y1))
591 G_warning(
"Weird internal error: perimeter has odd number of points");
599 for (j = 0; j < rings; j++) {
600 for (i = 1; i <
st->np; i += 2) {
601 if (
st->P[i].y !=
st->P[i - 1].y) {
602 G_warning(
"Weird internal error: edge leaves row");
605 st->row_fill(
st->P[i].y,
st->P[i - 1].x + shift1[j],
606 st->P[i].x + shift1[j]);
614 while (
W + shift < st->window.west)
616 while (
W + shift >
st->window.east)
618 shift2 =
X(
x[n - 1] + shift) -
X(
x[n - 1]);
619 if (shift2 != shift1[j]) {
620 for (i = 1; i <
st->np; i += 2) {
621 st->row_fill(
st->P[i].y,
st->P[i - 1].x + shift2,
622 st->P[i].x + shift2);
631 static int edge(
double x0,
double y0,
double x1,
double y1)
641 if (fabs(y0) > fabs(y1))
651 if (fabs(y0 - y1) < d)
670 m = (x0 - x1) / (y0 - y1);
671 x = m * (ystart - y0) + x0;
672 while (ystart <= ystop) {
673 if (!edge_point(
x, ystart++))
681 static int edge_point(
double x,
int y)
684 if (y < st->ymin || y >
st->ymax)
686 if (
st->np >=
st->npalloc) {
687 if (
st->npalloc > 0) {
701 st->P[
st->np++].y = y;
705 static int edge_order(
const void *aa,
const void *bb)
707 const struct point *a = aa, *
b = bb;
722 static void row_solid_fill(
int y,
double x1,
double x2)
734 static void row_dotted_fill(
int y,
double x1,
double x2)
738 if (y != iceil(y /
st->dotted_fill_gap) *
st->dotted_fill_gap)
741 i1 = iceil(x1 /
st->dotted_fill_gap) *
st->dotted_fill_gap;
744 for (i = i1; i <= i2; i +=
st->dotted_fill_gap) {
751 static int ifloor(
double x)
761 static int iceil(
double x)
782 void G_plot_fx(
double (*f)(
double),
double east1,
double east2)
784 double east, north, north1;
787 incr = fabs(1.0 /
st->xconv);
793 while ((east1 -= incr) > east2) {
801 while ((east1 += incr) < east2) {
void G_free(void *)
Free allocated memory.
void G_warning(const char *,...) __attribute__((format(printf
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 PROJECTION_LL
Projection code - Latitude-Longitude.
int edge_order(const void *aa, const void *bb)
Determines points order during sorting.
int G_plot_area(double *const *xs, double *const *ys, int *rpnts, int rings)
Plot multiple polygons.
void G_plot_line2(double east1, double north1, double east2, double north2)
Plot line between latlon coordinates (slowline)
int G_plot_polygon(const double *x, const double *y, int n)
Plot filled polygon with n vertices.
void G_plot_where_en(int x, int y, double *east, double *north)
Converts x,y to east,north.
void G_plot_where_xy(double east, double north, int *x, int *y)
Converts east,north to x,y.
void G_setup_fill(int gap)
Set row_fill routine to row_solid_fill or row_dotted_fill.
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_plot_fx(double(*f)(double), double east1, double east2)
Plot f(east1) to f(east2)
void G_plot_line(double east1, double north1, double east2, double north2)
Plot line between latlon coordinates (fastline)
void G_plot_point(double east, double north)
Plot point.
2D/3D raster map header (used also for region)
double bottom
Extent coordinates (bottom) - 3D data.
double top
Extent coordinates (top) - 3D data.