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);
208 void G_plot_line(
double east1,
double north1,
double east2,
double north2)
210 plot_line(east1, north1, east2, north2, fastline);
223 void G_plot_line2(
double east1,
double north1,
double east2,
double north2)
225 plot_line(east1, north1, east2, north2, slowline);
231 static void fastline(
double x1,
double y1,
double x2,
double y2)
233 st->move(ifloor(x1 + 0.5), ifloor(y1 + 0.5));
234 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)
378 double shift, E,
W = 0L;
383 st->row_fill = row_solid_fill;
406 if (pole && !edge(x0, y0, x0,
Y(90.0 * pole)))
409 for (i = 0; i < n; i++) {
410 e1 = wrap_east(e0,
x[i]);
419 if (!edge(x0, y0, x1, y1))
426 if (pole && !edge(x0, y0, x0,
Y(90.0 * pole)))
430 while (E + shift >
st->window.east)
432 while (E + shift < st->window.west)
434 shift1 =
X(
x[n - 1] + shift) -
X(
x[n - 1]);
440 for (i = 0; i < n; i++) {
443 if (!edge(x0, y0, x1, y1))
452 G_warning(
"Weird internal error: perimeter has odd number of points");
460 for (i = 1; i <
st->np; i += 2) {
461 if (
st->P[i].y !=
st->P[i - 1].y) {
462 G_warning(
"Weird internal error: edge leaves row");
465 st->row_fill(
st->P[i].y,
st->P[i - 1].x + shift1,
st->P[i].x + shift1);
469 while (
W + shift < st->window.west)
471 while (
W + shift >
st->window.east)
473 shift2 =
X(
x[n - 1] + shift) -
X(
x[n - 1]);
474 if (shift2 != shift1) {
475 for (i = 1; i <
st->np; i += 2) {
476 st->row_fill(
st->P[i].y,
st->P[i - 1].x + shift2,
477 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],
604 st->P[i].x + shift1[j]);
612 while (
W + shift < st->window.west)
614 while (
W + shift >
st->window.east)
616 shift2 =
X(
x[n - 1] + shift) -
X(
x[n - 1]);
617 if (shift2 != shift1[j]) {
618 for (i = 1; i <
st->np; i += 2) {
619 st->row_fill(
st->P[i].y,
st->P[i - 1].x + shift2,
620 st->P[i].x + shift2);
629 static int edge(
double x0,
double y0,
double x1,
double y1)
639 if (fabs(y0) > fabs(y1))
649 if (fabs(y0 - y1) < d)
668 m = (x0 - x1) / (y0 - y1);
669 x = m * (ystart - y0) + x0;
670 while (ystart <= ystop) {
671 if (!edge_point(
x, ystart++))
679 static int edge_point(
double x,
int y)
682 if (y < st->ymin || y >
st->ymax)
684 if (
st->np >=
st->npalloc) {
685 if (
st->npalloc > 0) {
699 st->P[
st->np++].y = y;
703 static int edge_order(
const void *aa,
const void *bb)
705 const struct point *a = aa, *
b = bb;
720 static void row_solid_fill(
int y,
double x1,
double x2)
732 static void row_dotted_fill(
int y,
double x1,
double x2)
736 if (y != iceil(y /
st->dotted_fill_gap) *
st->dotted_fill_gap)
739 i1 = iceil(x1 /
st->dotted_fill_gap) *
st->dotted_fill_gap;
742 for (i = i1; i <= i2; i +=
st->dotted_fill_gap) {
749 static int ifloor(
double x)
759 static int iceil(
double x)
780 void G_plot_fx(
double (*f)(
double),
double east1,
double east2)
782 double east, north, north1;
785 incr = fabs(1.0 /
st->xconv);
791 while ((east1 -= incr) > east2) {
799 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.