GRASS Programmer's Manual
6.4.2(2012)
|
00001 00002 /**************************************************************************** 00003 * 00004 * MODULE: display 00005 * AUTHOR(S): CERL (original contributors) 00006 * Bernhard Reiter <bernhard intevation.de>, 00007 * Markus Neteler <neteler itc.it>, 00008 * Glynn Clements <glynn gclements.plus.com>, 00009 * Hamish Bowman <hamish_nospam yahoo.com> 00010 * PURPOSE: 00011 * COPYRIGHT: (C) 1999-2007 by the GRASS Development Team 00012 * 00013 * This program is free software under the GNU General Public 00014 * License (>=v2). Read the file COPYING that comes with GRASS 00015 * for details. 00016 * 00017 *****************************************************************************/ 00018 00019 /******************************************************************* 00020 * Line drawing in the current window. 00021 * 00022 * Clip window: 00023 * D_set_clip_window (top, bottom ,left, right) 00024 * establish clipping region for subseqent line drawing. 00025 * D_set_clip_window_to_map_window () 00026 * set clipping to pixels corresponding to the current map region 00027 * (default) 00028 * D_set_clip_window_to_screen_window () 00029 * set clipping to full extent of the window (ie disables clipping on screen) 00030 * 00031 * Moves. 00032 * D_move_abs(x,y) move to x,y. 00033 * D_move_rel(x,y) move to +x,+y. 00034 * Set current position. Position is not clipped. 00035 * 00036 * Draw line 00037 * D_cont_abs(x,y) draw to x,y. 00038 * D_cont_rel(x,y) draw to +x,+y. 00039 * Line draw from current position. New postion is not clipped. 00040 * The lines drawn are clipped however. 00041 * Return values indicate the nature of the clipping: 00042 * 0 no clipping 00043 * 1 part of the line is drawn 00044 * -1 none of the line is drawn 00045 * 00046 * 00047 */ 00048 #include <grass/raster.h> 00049 #include <grass/gis.h> 00050 #include <grass/display.h> 00051 00052 static int clip(void); 00053 static int line_eq(int, int, int, int, int, int); 00054 00055 static int curx, cury; 00056 static int left, right, top, bottom; /* window edges */ 00057 static int x1, y1, x2, y2; 00058 00059 static int window_set = 0; 00060 00061 #define swap(x,y) {int t; t=x; x=y; y=t;} 00062 #define limit(a,x,b) x<a?a:(x>b?b:x) 00063 00064 00078 int D_set_clip_window(int Top, int Bottom, int Left, int Right) 00079 { 00080 /* make sure top is above bottom, left is left of right */ 00081 if (Top > Bottom) 00082 swap(Top, Bottom); 00083 if (Left > Right) 00084 swap(Left, Right); 00085 00086 /* make sure edges are within the true window edges */ 00087 D_get_screen_window(&top, &bottom, &left, &right); 00088 Top = limit(top, Top, bottom); 00089 Bottom = limit(top, Bottom, bottom); 00090 Left = limit(left, Left, right); 00091 Right = limit(left, Right, right); 00092 00093 /* set the window */ 00094 top = Top; 00095 bottom = Bottom; 00096 left = Left; 00097 right = Right; 00098 00099 window_set = 1; 00100 00101 R_move_abs(left, top); 00102 00103 return 0; 00104 } 00105 00106 00117 int D_set_clip_window_to_map_window(void) 00118 { 00119 D_set_clip_window((int)D_get_d_north(), 00120 (int)D_get_d_south(), 00121 (int)D_get_d_west(), (int)D_get_d_east() 00122 ); 00123 00124 return 0; 00125 } 00126 00127 00138 int D_set_clip_window_to_screen_window(void) 00139 { 00140 D_get_screen_window(&top, &bottom, &left, &right); 00141 D_set_clip_window(top, bottom, left, right); 00142 00143 return 0; 00144 } 00145 00146 00162 int D_cont_abs(int x, int y) 00163 { 00164 int clipped; 00165 00166 x1 = curx; 00167 y1 = cury; 00168 x2 = x; 00169 y2 = y; 00170 curx = x; 00171 cury = y; 00172 00173 if (!window_set) 00174 D_set_clip_window_to_map_window(); 00175 00176 clipped = clip(); 00177 if (clipped >= 0) { 00178 R_move_abs(x1, y1); 00179 R_cont_abs(x2, y2); 00180 } 00181 00182 return clipped; 00183 } 00184 00185 00198 int D_cont_rel(int x, int y) 00199 { 00200 return D_cont_abs(curx + x, cury + y); 00201 } 00202 00203 00215 int D_move_abs(int x, int y) 00216 { 00217 curx = x; 00218 cury = y; 00219 return 0; 00220 } 00221 00222 00235 int D_move_rel(int x, int y) 00236 { 00237 curx += x; 00238 cury += y; 00239 return 0; 00240 } 00241 00242 /********************************************************************* 00243 * this code is the window clipping for D_cont_abs() 00244 *********************************************************************/ 00245 00246 #define Y(x) line_eq(x,x0,y0,dx,dy,xround) 00247 00248 #define X(y) line_eq(y,y0,x0,dy,dx,yround) 00249 00250 00251 static int clip(void) 00252 { 00253 register int x0, y0; 00254 register int dx, dy; 00255 int xround; 00256 int yround; 00257 int clipped; 00258 00259 /* 00260 * quick check for line above,below,left,or right of window 00261 */ 00262 if (x1 < left && x2 < left) 00263 return -1; 00264 if (x1 > right && x2 > right) 00265 return -1; 00266 00267 if (y1 < top && y2 < top) 00268 return -1; 00269 if (y1 > bottom && y2 > bottom) 00270 return -1; 00271 00272 /* 00273 * setup line equations variables 00274 */ 00275 x0 = x1; 00276 y0 = y1; 00277 00278 dx = x2 - x1; 00279 dy = y2 - y1; 00280 00281 if ((xround = dx / 2) < 0) 00282 xround = -xround; 00283 if ((yround = dy / 2) < 0) 00284 yround = -yround; 00285 00286 /* 00287 * clipping 00288 * 00289 * if x of endpoint 1 doesn't fall within the window 00290 * move x to the nearest edge 00291 * recalculate the y 00292 * if the new y doesn't fall within the window then 00293 * the line doesn't cross into the window 00294 * 00295 * if y of endpoint 1 doesn't fall within the window 00296 * move y to the nearest edge 00297 * recalculate the x 00298 * if the new x doesn't fall within the window then 00299 * the line doesn't cross into the window 00300 * 00301 * repeat for the second endpoint 00302 * 00303 */ 00304 00305 clipped = 0; 00306 if (x1 < left || x1 > right) { 00307 if (dx == 0) 00308 return -1; 00309 00310 x1 = x1 < left ? left : right; 00311 y1 = Y(x1); 00312 00313 if (y1 < top || y1 > bottom) { 00314 if (dy == 0) 00315 return -1; 00316 00317 y1 = y1 < top ? top : bottom; 00318 x1 = X(y1); 00319 00320 if (x1 < left || x1 > right) 00321 return -1; 00322 } 00323 clipped = 1; 00324 } 00325 if (y1 < top || y1 > bottom) { 00326 if (dy == 0) 00327 return -1; 00328 y1 = y1 < top ? top : bottom; 00329 x1 = X(y1); 00330 00331 if (x1 < left || x1 > right) { 00332 if (dx == 0) 00333 return -1; 00334 00335 x1 = x1 < left ? left : right; 00336 y1 = Y(x1); 00337 00338 if (y1 < top || y1 > bottom) 00339 return -1; 00340 } 00341 clipped = 1; 00342 } 00343 00344 if (x2 < left || x2 > right) { 00345 if (dx == 0) 00346 return -1; 00347 00348 x2 = x2 < left ? left : right; 00349 y2 = Y(x2); 00350 00351 if (y2 < top || y2 > bottom) { 00352 if (dy == 0) 00353 return -1; 00354 00355 y2 = y2 < top ? top : bottom; 00356 x2 = X(y2); 00357 00358 if (x2 < left || x2 > right) 00359 return -1; 00360 } 00361 clipped = 1; 00362 } 00363 if (y2 < top || y2 > bottom) { 00364 if (dy == 0) 00365 return -1; 00366 00367 y2 = y2 < top ? top : bottom; 00368 x2 = X(y2); 00369 00370 if (x2 < left || x2 > right) { 00371 if (dx == 0) 00372 return -1; 00373 00374 x2 = x2 < left ? left : right; 00375 y2 = Y(x2); 00376 00377 if (y2 < top || y2 > bottom) 00378 return -1; 00379 } 00380 clipped = 1; 00381 } 00382 00383 return clipped; 00384 } 00385 00386 static int line_eq(int x, int x0, int y0, int dx, int dy, int round) 00387 { 00388 register int t; 00389 00390 if ((t = dy * (x - x0)) < 0) 00391 t -= round; 00392 else 00393 t += round;; 00394 00395 return (y0 + t / dx); 00396 }