18 #include <grass/gis.h>
20 static double xconv, yconv;
21 static double left, right, top, bottom;
23 static struct Cell_head
window;
24 static int fastline(
double,
double,
double,
double);
25 static int slowline(
double,
double,
double,
double);
26 static int plot_line(
double,
double,
double,
double,
int (*)());
27 static double nearest(
double,
double);
28 static int edge(
double,
double,
double,
double);
29 static int edge_point(
double,
int);
31 #define POINT struct point
36 static int edge_order(
const void *,
const void *);
37 static int row_solid_fill(
int,
double,
double);
38 static int row_dotted_fill(
int,
double,
double);
39 static int dotted_fill_gap = 2;
40 static int ifloor(
double);
41 static int iceil(
double);
42 static int (*row_fill) () = row_solid_fill;
98 int (*Move) (
int,
int),
int (*Cont) (
int,
int))
112 ymax = ifloor(bottom);
115 ymin = iceil(bottom);
139 row_fill = row_dotted_fill;
140 dotted_fill_gap = gap + 1;
143 row_fill = row_solid_fill;
148 #define X(e) (left + xconv * ((e) - window.west))
149 #define Y(n) (top + yconv * (window.north - (n)))
151 #define EAST(x) (window.west + ((x)-left)/xconv)
152 #define NORTH(y) (window.north - ((y)-top)/yconv)
171 *y = ifloor(
Y(north) + 0.5);
230 int G_plot_line(
double east1,
double north1,
double east2,
double north2)
232 return plot_line(east1, north1, east2, north2, fastline);
235 int G_plot_line2(
double east1,
double north1,
double east2,
double north2)
237 return plot_line(east1, north1, east2, north2, slowline);
244 static int fastline(
double x1,
double y1,
double x2,
double y2)
246 move(ifloor(x1 + 0.5), ifloor(y1 + 0.5));
247 cont(ifloor(x2 + 0.5), ifloor(y2 + 0.5));
258 static int slowline(
double x1,
double y1,
double x2,
double y2)
262 int xstart, xstop, ystart, ystop;
267 if (fabs(dx) > fabs(dy)) {
272 xstart = iceil(x2 - 0.5);
273 xstop = ifloor(x1 + 0.5);
276 xstart = iceil(x1 - 0.5);
277 xstop = ifloor(x2 + 0.5);
279 if (xstart <= xstop) {
280 ystart = ifloor(m * xstart + b + 0.5);
281 move(xstart, ystart);
282 while (xstart <= xstop) {
283 cont(xstart++, ystart);
284 ystart = ifloor(m * xstart + b + 0.5);
296 ystart = iceil(y2 - 0.5);
297 ystop = ifloor(y1 + 0.5);
300 ystart = iceil(y1 - 0.5);
301 ystop = ifloor(y2 + 0.5);
303 if (ystart <= ystop) {
304 xstart = ifloor(m * ystart + b + 0.5);
305 move(xstart, ystart);
306 while (ystart <= ystop) {
307 cont(xstart, ystart++);
308 xstart = ifloor(m * ystart + b + 0.5);
316 static int plot_line(
double east1,
double north1,
double east2,
double north2,
317 int (*line) (
double,
double,
double,
double))
319 double x1, x2, y1, y2;
324 if (
window.proj == PROJECTION_LL) {
326 while ((east1 - east2) > 180)
328 else if (east2 > east1)
329 while ((east2 - east1) > 180)
331 while (east1 >
window.east) {
335 while (east1 <
window.west) {
342 line(x1, y1, x2, y2);
345 while (east2 >
window.east) {
349 while (east2 <
window.west) {
355 line(x1, y1, x2, y2);
361 line(x1, y1, x2, y2);
382 static int npalloc = 0;
385 #define TOO_FEW_EDGES 2
387 #define OUT_OF_SYNC -1
389 static double nearest(
double e0,
double e1)
391 while (e0 - e1 > 180)
393 while (e1 - e0 > 180)
418 double shift, E, W = 0L;
431 if (
window.proj == PROJECTION_LL) {
443 if (pole && !edge(x0, y0, x0,
Y(90.0 * pole)))
446 for (i = 0; i <
n; i++) {
447 e1 = nearest(e0, x[i]);
456 if (!edge(x0, y0, x1, y1))
463 if (pole && !edge(x0, y0, x0,
Y(90.0 * pole)))
467 while (E + shift >
window.east)
469 while (E + shift <
window.west)
471 shift1 =
X(x[n - 1] + shift) -
X(x[n - 1]);
477 for (i = 0; i <
n; i++) {
480 if (!edge(x0, y0, x1, y1))
492 qsort(P, np,
sizeof(
POINT), &edge_order);
495 for (i = 1; i < np; i += 2) {
496 if (P[i].y != P[i - 1].y)
498 row_fill(P[i].y, P[i - 1].x + shift1, P[i].x + shift1);
500 if (
window.proj == PROJECTION_LL) {
502 while (W + shift <
window.west)
504 while (W + shift >
window.east)
506 shift2 =
X(x[n - 1] + shift) -
X(x[n - 1]);
507 if (shift2 != shift1) {
508 for (i = 1; i < np; i += 2) {
509 row_fill(P[i].y, P[i - 1].x + shift2, P[i].x + shift2);
542 int G_plot_area(
double *
const *xs,
double *
const *ys,
int *rpnts,
int rings)
548 double shift, E, W = 0L;
550 int *shift1 =
NULL, shift2;
555 shift1 = (
int *)G_calloc(
sizeof(
int), rings);
557 for (j = 0; j < rings; j++) {
567 if (
window.proj == PROJECTION_LL) {
579 if (pole && !edge(x0, y0, x0,
Y(90.0 * pole)))
582 for (i = 0; i <
n; i++) {
583 e1 = nearest(e0, x[i]);
592 if (!edge(x0, y0, x1, y1))
599 if (pole && !edge(x0, y0, x0,
Y(90.0 * pole)))
603 while (E + shift >
window.east)
605 while (E + shift <
window.west)
607 shift1[j] =
X(x[n - 1] + shift) -
X(x[n - 1]);
613 for (i = 0; i <
n; i++) {
616 if (!edge(x0, y0, x1, y1))
629 qsort(P, np,
sizeof(
POINT), &edge_order);
632 for (j = 0; j < rings; j++) {
633 for (i = 1; i < np; i += 2) {
634 if (P[i].y != P[i - 1].y)
636 row_fill(P[i].y, P[i - 1].x + shift1[j], P[i].x + shift1[j]);
638 if (
window.proj == PROJECTION_LL) {
644 while (W + shift <
window.west)
646 while (W + shift >
window.east)
648 shift2 =
X(x[n - 1] + shift) -
X(x[n - 1]);
649 if (shift2 != shift1[j]) {
650 for (i = 1; i < np; i += 2) {
651 row_fill(P[i].y, P[i - 1].x + shift2, P[i].x + shift2);
661 static int edge(
double x0,
double y0,
double x1,
double y1)
670 if (fabs(dy) < 1e-10)
690 x = m * (ystart - y0) + x0;
691 while (ystart <= ystop) {
692 if (!edge_point(x, ystart++))
699 static int edge_point(
double x,
int y)
702 if (y < ymin || y >
ymax)
707 P = (
POINT *) G_realloc(P, npalloc *
sizeof(
POINT));
711 P = (
POINT *) G_malloc(npalloc *
sizeof(
POINT));
723 static int edge_order(
const void *aa,
const void *bb)
725 const struct point *a = aa, *b = bb;
740 static int row_solid_fill(
int y,
double x1,
double x2)
754 static int row_dotted_fill(
int y,
double x1,
double x2)
758 if (y != iceil(y / dotted_fill_gap) * dotted_fill_gap)
761 i1 = iceil(x1 / dotted_fill_gap) * dotted_fill_gap;
764 for (i = i1; i <= i2; i += dotted_fill_gap) {
773 static int ifloor(
double x)
783 static int iceil(
double x)
811 int G_plot_fx(
double (*f) (
double),
double east1,
double east2)
813 double east, north, north1;
817 incr = fabs(1.0 / xconv);
823 while ((east1 -= incr) > east2) {
831 while ((east1 += incr) < east2) {
int G_plot_area(double *const *xs, double *const *ys, int *rpnts, int rings)
plot multiple polygons
int G_plot_where_xy(double east, double north, int *x, int *y)
east,north to x,y
int G_plot_point(double east, double north)
void G_free(void *buf)
Free allocated memory.
int G_get_set_window(struct Cell_head *window)
Get the current working window.
int G_setup_fill(int gap)
set row_fill routine to row_solid_fill or row_dotted_fill
int G_plot_where_en(int x, int y, double *east, double *north)
x,y to east,north
int G_plot_line(double east1, double north1, double east2, double north2)
plot line between latlon coordinates
int G_plot_fx(double(*f)(double), double east1, double east2)
plot f(east1) to f(east2)
int G_plot_line2(double east1, double north1, double east2, double north2)
int G_setup_plot(double t, double b, double l, double r, int(*Move)(int, int), int(*Cont)(int, int))
returns east larger than west
double G_adjust_easting(double east, const struct Cell_head *window)
Returns east larger than west.
int G_plot_polygon(const double *x, const double *y, int n)
plot filled polygon with n vertices