GRASS Programmer's Manual  6.4.2(2012)
display/draw.c
Go to the documentation of this file.
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 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines