1 #include <math.h>
2 #include <grass/gis.h>
3 #include <grass/dbmi.h>
4 #include <grass/vector.h>
5 #include <grass/glocale.h>
6 #include "local.h"
7 
8 static struct state {
9     struct Cell_head window;
10     double xconv, yconv;
11     double left, right, top, bottom;
12     int ymin, ymax;
13     int dotted_fill_gap;
14 
15     int (*dot)(int, int);
16 } state;
17 
18 static struct state *st = &state;
19 
20 #define X(e) (st->left + st->xconv * ((e) - st->window.west))
21 #define Y(n) (st->top + st->yconv * (st->window.north - (n)))
22 
23 #define EAST(x) (st->window.west + ((x)-st->left)/st->xconv)
24 #define NORTH(y) (st->window.north - ((y)-st->top)/st->yconv)
25 
26 void dense_line(double x1, double y1, double x2, double y2,
27                 int (*point) (int, int));
28 
ifloor(double x)29 static int ifloor(double x)
30 {
31     int i;
32 
33     i = (int)x;
34     if (i > x)
35 	i--;
36     return i;
37 }
38 
iceil(double x)39 static int iceil(double x)
40 {
41     int i;
42 
43     i = (int)x;
44     if (i < x)
45 	i++;
46     return i;
47 }
48 
49 
setup_plot(double t,double b,double l,double r,int (* dot)(int,int))50 void setup_plot(double t, double b, double l, double r,
51 		  int (*dot) (int, int))
52 {
53     G_get_set_window(&st->window);
54 
55     st->left = l;
56     st->right = r;
57     st->top = t;
58     st->bottom = b;
59 
60     st->xconv = (st->right - st->left) / (st->window.east - st->window.west);
61     st->yconv = (st->bottom - st->top) / (st->window.north - st->window.south);
62 
63     if (st->top < st->bottom) {
64 	st->ymin = iceil(st->top);
65 	st->ymax = ifloor(st->bottom);
66     }
67     else {
68 	st->ymin = iceil(st->bottom);
69 	st->ymax = ifloor(st->top);
70     }
71 
72     st->dot = dot;
73 }
74 
75 
76 /* dense line plotting, alternative to G_plot_line2()
77  * x1, y1, x2, y2 are col, row numbers */
plot_line_dense(double east1,double north1,double east2,double north2)78 void plot_line_dense(double east1, double north1, double east2, double north2)
79 {
80     double x1, x2, y1, y2;
81 
82     y1 = Y(north1);
83     y2 = Y(north2);
84 
85     if (st->window.proj == PROJECTION_LL) {
86 	if (east1 > east2)
87 	    while ((east1 - east2) > 180)
88 		east2 += 360;
89 	else if (east2 > east1)
90 	    while ((east2 - east1) > 180)
91 		east1 += 360;
92 	while (east1 > st->window.east) {
93 	    east1 -= 360.0;
94 	    east2 -= 360.0;
95 	}
96 	while (east1 < st->window.west) {
97 	    east1 += 360.0;
98 	    east2 += 360.0;
99 	}
100 	x1 = X(east1);
101 	x2 = X(east2);
102 
103 	dense_line(x1, y1, x2, y2, st->dot);
104 
105 	if (east2 > st->window.east || east2 < st->window.west) {
106 	    while (east2 > st->window.east) {
107 		east1 -= 360.0;
108 		east2 -= 360.0;
109 	    }
110 	    while (east2 < st->window.west) {
111 		east1 += 360.0;
112 		east2 += 360.0;
113 	    }
114 	    x1 = X(east1);
115 	    x2 = X(east2);
116 	    dense_line(x1, y1, x2, y2, st->dot);
117 	}
118     }
119     else {
120 	x1 = X(east1);
121 	x2 = X(east2);
122 	dense_line(x1, y1, x2, y2, st->dot);
123     }
124 }
125 
126 /* dense line plotting, alternative to G_bresenham_line()
127  * x1, y1, x2, y2 are col, row numbers */
dense_line(double x1,double y1,double x2,double y2,int (* point)(int,int))128 void dense_line(double x1, double y1, double x2, double y2,
129                 int (*point) (int, int))
130 {
131     int ix1, ix2, iy1, iy2, idx, idy;
132     int xinc, yinc;
133     double dx, dy;
134 
135     G_debug(2, "dense line");
136 
137     if (x2 < x1) {
138 	double tmp;
139 
140 	tmp = x1;
141 	x1 = x2;
142 	x2 = tmp;
143 
144 	tmp = y1;
145 	y1 = y2;
146 	y2 = tmp;
147     }
148 
149     ix1 = (int)x1;
150     ix2 = (int)x2;
151     iy1 = (int)y1;
152     iy2 = (int)y2;
153 
154     idx = ix2 - ix1;
155     idy = iy2 - iy1;
156 
157     dx = x2 - x1;
158     dy = y2 - y1;
159 
160     xinc = yinc = 1;
161 
162     if (idx < 0) {
163 	xinc = -1;
164 	idx = -idx;
165     }
166 
167     if (idy < 0) {
168 	yinc = -1;
169 	idy = -idy;
170     }
171     if (dx < 0)
172 	dx = -dx;
173     if (dy < 0)
174 	dy = -dy;
175 
176     if (idx == 0) {
177 	while (iy1 != iy2) {
178 	    point(ix1, iy1);
179 	    iy1 += yinc;
180 	}
181     }
182     else if (idy == 0) {
183 	while (ix1 != ix2) {
184 	    point(ix1, iy1);
185 	    ix1 += xinc;
186 	}
187     }
188     else if (dx >= dy) {
189 	double m, a, yi;
190 	int xnext;
191 
192 	m = (y2 - y1) / (x2 - x1);
193 	a = y1 - m * x1;
194 
195 	/* find x for y = iy1 or y = iy1 + 1 */
196 	m = (x2 - x1) / (y2 - y1);
197 	a = x1 - m * y1;
198 	yi = iy1;
199 	if (iy1 < iy2)
200 	    yi += 1;
201 	xnext = a + m * yi;
202 
203 
204 	while (ix1 != ix2) {
205 	    point(ix1, iy1);
206 
207 	    if (ix1 == xnext) {
208 		iy1 += yinc;
209 		point(ix1, iy1);
210 		if (iy1 != iy2) {
211 		    yi = iy1;
212 		    if (iy1 < iy2)
213 			yi += 1;
214 		    xnext = a + m * yi;
215 		}
216 		else
217 		    xnext = ix2;
218 	    }
219 
220 	    ix1 += xinc;
221 	}
222 	if (iy1 != iy2)
223 	    point(ix1, iy1);
224     }
225     else if (dx < dy) {
226 	double m, a, xi;
227 	int ynext;
228 
229 	if (y2 < y1) {
230 	    double tmp;
231 
232 	    tmp = x1;
233 	    x1 = x2;
234 	    x2 = tmp;
235 
236 	    tmp = y1;
237 	    y1 = y2;
238 	    y2 = tmp;
239 
240 	    ix1 = (int)x1;
241 	    ix2 = (int)x2;
242 	    iy1 = (int)y1;
243 	    iy2 = (int)y2;
244 
245 	    yinc = 1;
246 	    xinc = 1;
247 	    if (x2 < x1)
248 		xinc = -1;
249 	}
250 
251 	/* find y for x = ix1 or x = ix1 + 1 */
252 	m = (y2 - y1) / (x2 - x1);
253 	a = y1 - m * x1;
254 	xi = ix1;
255 	if (ix1 < ix2)
256 	    xi += 1;
257 	ynext = a + m * xi;
258 
259 	while (iy1 != iy2) {
260 	    point(ix1, iy1);
261 
262 	    if (iy1 == ynext) {
263 		ix1 += xinc;
264 		point(ix1, iy1);
265 		if (ix1 != ix2) {
266 		    xi = ix1;
267 		    if (ix1 < ix2)
268 			xi += 1;
269 		    ynext = a + m * xi;
270 		}
271 		else
272 		    ynext = iy2;
273 	    }
274 	    iy1 += yinc;
275 	}
276 	if (ix1 != ix2)
277 	    point(ix1, iy1);
278     }
279     point(ix2, iy2);
280 }
281