|
@@ -0,0 +1,280 @@
|
|
|
+#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);
|
|
|
+}
|