123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- #include <math.h>
- #include <grass/gis.h>
- #include <grass/dbmi.h>
- #include <grass/vector.h>
- #include <grass/glocale.h>
- #include "local.h"
- static struct state {
- struct Cell_head window;
- double xconv, yconv;
- double left, right, top, bottom;
- int ymin, ymax;
- int dotted_fill_gap;
- int (*dot)(int, int);
- } state;
- static struct state *st = &state;
- #define X(e) (st->left + st->xconv * ((e) - st->window.west))
- #define Y(n) (st->top + st->yconv * (st->window.north - (n)))
- #define EAST(x) (st->window.west + ((x)-st->left)/st->xconv)
- #define NORTH(y) (st->window.north - ((y)-st->top)/st->yconv)
- void dense_line(double x1, double y1, double x2, double y2,
- int (*point) (int, int));
- static int ifloor(double x)
- {
- int i;
- i = (int)x;
- if (i > x)
- i--;
- return i;
- }
- static int iceil(double x)
- {
- int i;
- i = (int)x;
- if (i < x)
- i++;
- return i;
- }
- void setup_plot(double t, double b, double l, double r,
- int (*dot) (int, int))
- {
- G_get_set_window(&st->window);
- st->left = l;
- st->right = r;
- st->top = t;
- st->bottom = b;
- st->xconv = (st->right - st->left) / (st->window.east - st->window.west);
- st->yconv = (st->bottom - st->top) / (st->window.north - st->window.south);
- if (st->top < st->bottom) {
- st->ymin = iceil(st->top);
- st->ymax = ifloor(st->bottom);
- }
- else {
- st->ymin = iceil(st->bottom);
- st->ymax = ifloor(st->top);
- }
- st->dot = dot;
- }
- /* dense line plotting, alternative to G_plot_line2()
- * x1, y1, x2, y2 are col, row numbers */
- void plot_line_dense(double east1, double north1, double east2, double north2)
- {
- double x1, x2, y1, y2;
- y1 = Y(north1);
- y2 = Y(north2);
- if (st->window.proj == PROJECTION_LL) {
- if (east1 > east2)
- while ((east1 - east2) > 180)
- east2 += 360;
- else if (east2 > east1)
- while ((east2 - east1) > 180)
- east1 += 360;
- while (east1 > st->window.east) {
- east1 -= 360.0;
- east2 -= 360.0;
- }
- while (east1 < st->window.west) {
- east1 += 360.0;
- east2 += 360.0;
- }
- x1 = X(east1);
- x2 = X(east2);
- dense_line(x1, y1, x2, y2, st->dot);
- if (east2 > st->window.east || east2 < st->window.west) {
- while (east2 > st->window.east) {
- east1 -= 360.0;
- east2 -= 360.0;
- }
- while (east2 < st->window.west) {
- east1 += 360.0;
- east2 += 360.0;
- }
- x1 = X(east1);
- x2 = X(east2);
- dense_line(x1, y1, x2, y2, st->dot);
- }
- }
- else {
- x1 = X(east1);
- x2 = X(east2);
- dense_line(x1, y1, x2, y2, st->dot);
- }
- }
- /* dense line plotting, alternative to G_bresenham_line()
- * x1, y1, x2, y2 are col, row numbers */
- void dense_line(double x1, double y1, double x2, double y2,
- int (*point) (int, int))
- {
- int ix1, ix2, iy1, iy2, idx, idy;
- int xinc, yinc;
- double dx, dy;
- G_debug(2, "dense line");
- if (x2 < x1) {
- double tmp;
-
- tmp = x1;
- x1 = x2;
- x2 = tmp;
-
- tmp = y1;
- y1 = y2;
- y2 = tmp;
- }
- ix1 = (int)x1;
- ix2 = (int)x2;
- iy1 = (int)y1;
- iy2 = (int)y2;
- idx = ix2 - ix1;
- idy = iy2 - iy1;
- dx = x2 - x1;
- dy = y2 - y1;
-
- xinc = yinc = 1;
-
- if (idx < 0) {
- xinc = -1;
- idx = -idx;
- }
- if (idy < 0) {
- yinc = -1;
- idy = -idy;
- }
- if (dx < 0)
- dx = -dx;
- if (dy < 0)
- dy = -dy;
- if (idx == 0) {
- while (iy1 != iy2) {
- point(ix1, iy1);
- iy1 += yinc;
- }
- }
- else if (idy == 0) {
- while (ix1 != ix2) {
- point(ix1, iy1);
- ix1 += xinc;
- }
- }
- else if (dx >= dy) {
- double m, a, yi;
- int xnext;
- m = (y2 - y1) / (x2 - x1);
- a = y1 - m * x1;
-
- /* find x for y = iy1 or y = iy1 + 1 */
- m = (x2 - x1) / (y2 - y1);
- a = x1 - m * y1;
- yi = iy1;
- if (iy1 < iy2)
- yi += 1;
- xnext = a + m * yi;
-
- while (ix1 != ix2) {
- point(ix1, iy1);
- if (ix1 == xnext) {
- iy1 += yinc;
- point(ix1, iy1);
- if (iy1 != iy2) {
- yi = iy1;
- if (iy1 < iy2)
- yi += 1;
- xnext = a + m * yi;
- }
- else
- xnext = ix2;
- }
- ix1 += xinc;
- }
- if (iy1 != iy2)
- point(ix1, iy1);
- }
- else if (dx < dy) {
- double m, a, xi;
- int ynext;
- if (y2 < y1) {
- double tmp;
-
- tmp = x1;
- x1 = x2;
- x2 = tmp;
-
- tmp = y1;
- y1 = y2;
- y2 = tmp;
- ix1 = (int)x1;
- ix2 = (int)x2;
- iy1 = (int)y1;
- iy2 = (int)y2;
- yinc = 1;
- xinc = 1;
- if (x2 < x1)
- xinc = -1;
- }
- /* find y for x = ix1 or x = ix1 + 1 */
- m = (y2 - y1) / (x2 - x1);
- a = y1 - m * x1;
- xi = ix1;
- if (ix1 < ix2)
- xi += 1;
- ynext = a + m * xi;
- while (iy1 != iy2) {
- point(ix1, iy1);
- if (iy1 == ynext) {
- ix1 += xinc;
- point(ix1, iy1);
- if (ix1 != ix2) {
- xi = ix1;
- if (ix1 < ix2)
- xi += 1;
- ynext = a + m * xi;
- }
- else
- ynext = iy2;
- }
- iy1 += yinc;
- }
- if (ix1 != ix2)
- point(ix1, iy1);
- }
- point(ix2, iy2);
- }
|