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 wrap_east(
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 wrap_east(
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 = wrap_east(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))
489 G_warning(
"Weird internal error: perimeter has odd number of points");
494 qsort(P, np,
sizeof(
POINT), &edge_order);
497 for (i = 1; i < np; i += 2) {
498 if (P[i].y != P[i - 1].y) {
499 G_warning(
"Weird internal error: edge leaves row");
502 row_fill(P[i].y, P[i - 1].x + shift1, P[i].x + shift1);
504 if (
window.proj == PROJECTION_LL) {
506 while (W + shift <
window.west)
508 while (W + shift >
window.east)
510 shift2 =
X(x[n - 1] + shift) -
X(x[n - 1]);
511 if (shift2 != shift1) {
512 for (i = 1; i < np; i += 2) {
513 row_fill(P[i].y, P[i - 1].x + shift2, P[i].x + shift2);
546 int G_plot_area(
double *
const *xs,
double *
const *ys,
int *rpnts,
int rings)
552 double shift, E, W = 0L;
554 int *shift1 =
NULL, shift2;
559 shift1 = (
int *)G_calloc(
sizeof(
int), rings);
561 for (j = 0; j < rings; j++) {
571 if (
window.proj == PROJECTION_LL) {
583 if (pole && !edge(x0, y0, x0,
Y(90.0 * pole)))
586 for (i = 0; i <
n; i++) {
587 e1 = wrap_east(e0, x[i]);
596 if (!edge(x0, y0, x1, y1))
603 if (pole && !edge(x0, y0, x0,
Y(90.0 * pole)))
607 while (E + shift >
window.east)
609 while (E + shift <
window.west)
611 shift1[j] =
X(x[n - 1] + shift) -
X(x[n - 1]);
617 for (i = 0; i <
n; i++) {
620 if (!edge(x0, y0, x1, y1))
630 G_warning(
"Weird internal error: perimeter has odd number of points");
635 qsort(P, np,
sizeof(
POINT), &edge_order);
638 for (j = 0; j < rings; j++) {
639 for (i = 1; i < np; i += 2) {
640 if (P[i].y != P[i - 1].y) {
641 G_warning(
"Weird internal error: edge leaves row");
644 row_fill(P[i].y, P[i - 1].x + shift1[j], P[i].x + shift1[j]);
646 if (
window.proj == PROJECTION_LL) {
652 while (W + shift <
window.west)
654 while (W + shift >
window.east)
656 shift2 =
X(x[n - 1] + shift) -
X(x[n - 1]);
657 if (shift2 != shift1[j]) {
658 for (i = 1; i < np; i += 2) {
659 row_fill(P[i].y, P[i - 1].x + shift2, P[i].x + shift2);
669 static int edge(
double x0,
double y0,
double x1,
double y1)
679 if (fabs(y0) > fabs(y1))
689 if (fabs(y0 - y1) < d)
707 m = (x0 - x1) / (y0 - y1);
708 x = m * (ystart - y0) + x0;
709 while (ystart <= ystop) {
710 if (!edge_point(x, ystart++))
717 static int edge_point(
double x,
int y)
720 if (y < ymin || y >
ymax)
725 P = (
POINT *) G_realloc(P, npalloc *
sizeof(
POINT));
729 P = (
POINT *) G_malloc(npalloc *
sizeof(
POINT));
741 static int edge_order(
const void *aa,
const void *bb)
743 const struct point *a = aa, *b = bb;
758 static int row_solid_fill(
int y,
double x1,
double x2)
772 static int row_dotted_fill(
int y,
double x1,
double x2)
776 if (y != iceil(y / dotted_fill_gap) * dotted_fill_gap)
779 i1 = iceil(x1 / dotted_fill_gap) * dotted_fill_gap;
782 for (i = i1; i <= i2; i += dotted_fill_gap) {
791 static int ifloor(
double x)
801 static int iceil(
double x)
829 int G_plot_fx(
double (*f) (
double),
double east1,
double east2)
831 double east, north, north1;
835 incr = fabs(1.0 / xconv);
841 while ((east1 -= incr) > east2) {
849 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)
G_warning("category support for [%s] in mapset [%s] %s", name, mapset, type)
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