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