clip.c

Go to the documentation of this file.
00001 /* Gxsm - Gnome X Scanning Microscopy
00002  * universal STM/AFM/SARLS/SPALEED/... controlling and
00003  * data analysis software
00004  * 
00005  * Copyright (C) 1999,2000,2001,2002,2003 Percy Zahl
00006  *
00007  * Authors: Percy Zahl <zahl@users.sf.net>
00008  * additional features: Andreas Klust <klust@users.sf.net>
00009  * WWW Home: http://gxsm.sf.net
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00024  */
00025 
00026 /* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 8 c-style: "K&R" -*- */
00027 
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <math.h>
00031 
00032 #include "clip.h"
00033 
00034 #define TRUE -1
00035 #define FALSE 0
00036 
00037 typedef enum {
00038         LEFT, RIGHT, BOTTOM, TOP
00039 } edge;
00040 typedef long outcode;
00041 
00042 
00043 /* Local variables for cohen_sutherland_line_clip: */
00044 struct LOC_cohen_sutherland_line_clip {
00045         double xmin, xmax, ymin, ymax;
00046 } ;
00047 
00048 void CompOutCode (double x, double y, outcode *code, struct LOC_cohen_sutherland_line_clip *LINK)
00049 {
00050         /*Compute outcode for the point (x,y) */
00051         *code = 0;
00052         if (y > LINK->ymax)
00053                 *code = 1L << ((long)TOP);
00054         else if (y < LINK->ymin)
00055                 *code = 1L << ((long)BOTTOM);
00056         if (x > LINK->xmax)
00057                 *code |= 1L << ((long)RIGHT);
00058         else if (x < LINK->xmin)
00059                 *code |= 1L << ((long)LEFT);
00060 }
00061 
00062 ClipResult cohen_sutherland_line_clip_i (int *x0_, int *y0_, int *x1_, int *y1_, 
00063                                int xmin_, int xmax_, int ymin_, int ymax_)
00064 {
00065         ClipResult ret;
00066         double x0,y0,x1,y1;
00067         x0 = *x0_;
00068         y0 = *y0_;
00069         x1 = *x1_;
00070         y1 = *y1_;
00071         ret = cohen_sutherland_line_clip_d (&x0, &y0, &x1, &y1, 
00072                                           (double)xmin_, (double)xmax_,
00073                                           (double)ymin_, (double)ymax_);
00074         *x0_ = (int)x0;
00075         *y0_ = (int)y0;
00076         *x1_ = (int)x1;
00077         *y1_ = (int)y1;
00078         return ret;
00079 }
00080 
00100 ClipResult cohen_sutherland_line_clip_d (double *x0, double *y0, double *x1, double *y1, 
00101                                       double xmin_, double xmax_, double ymin_, double ymax_)
00102 {
00103         /* Cohen-Sutherland clipping algorithm for line P0=(x1,y0) to P1=(x1,y1)
00104            and clip rectangle with diagonal from (xmin,ymin) to (xmax,ymax).*/
00105         struct LOC_cohen_sutherland_line_clip V;
00106         int accept = FALSE, done = FALSE;
00107         ClipResult clip = NotClipped;
00108         outcode outcode0, outcode1, outcodeOut;
00109         /*Outcodes for P0,P1, and whichever point lies outside the clip rectangle*/
00110         double x=0., y=0.;
00111         
00112         V.xmin = xmin_;
00113         V.xmax = xmax_;
00114         V.ymin = ymin_;
00115         V.ymax = ymax_;
00116         CompOutCode(*x0, *y0, &outcode0, &V);
00117         CompOutCode(*x1, *y1, &outcode1, &V);
00118         do {
00119                 if (outcode0 == 0 && outcode1 == 0) {   /*Trivial accept and exit*/
00120                         accept = TRUE;
00121                         done = TRUE;
00122                 } else if ((outcode0 & outcode1) != 0)
00123                         done = TRUE;
00124                 /*Logical intersection is true, so trivial reject and exit.*/
00125                 else {
00126                         clip = WasClipped;      
00127                         /*Failed both tests, so calculate the line segment to clip;
00128                           from an outside point to an intersection with clip edge.*/
00129                         /*At least one endpoint is outside the clip rectangle; pick it.*/
00130                         if (outcode0 != 0)
00131                                 outcodeOut = outcode0;
00132                         else
00133                                 outcodeOut = outcode1;
00134                         /*Now find intersection point;
00135                           use formulas y=y0+slope*(x-x0),x=x0+(1/slope)*(y-y0).*/
00136                         
00137                         if (((1L << ((long)TOP)) & outcodeOut) != 0) {
00138                                 /*Divide line at top of clip rectangle*/
00139                                 x = *x0 + (*x1 - *x0) * (V.ymax - *y0) / (*y1 - *y0);
00140                                 y = V.ymax;
00141                         } else if (((1L << ((long)BOTTOM)) & outcodeOut) != 0) {
00142                                 /*Divide line at bottom of clip rectangle*/
00143                                 x = *x0 + (*x1 - *x0) * (V.ymin - *y0) / (*y1 - *y0);
00144                                 y = V.ymin;
00145                         } else if (((1L << ((long)RIGHT)) & outcodeOut) != 0) {
00146                                 /*Divide line at right edge of clip rectangle*/
00147                                 y = *y0 + (*y1 - *y0) * (V.xmax - *x0) / (*x1 - *x0);
00148                                 x = V.xmax;
00149                         } else if (((1L << ((long)LEFT)) & outcodeOut) != 0) {
00150                                 /*Divide line at left edge of clip rectangle*/
00151                                 y = *y0 + (*y1 - *y0) * (V.xmin - *x0) / (*x1 - *x0);
00152                                 x = V.xmin;
00153                         }
00154                         /*Now we move outside point to intersection point to clip,
00155                           and get ready for next pass.*/
00156                         if (outcodeOut == outcode0) {
00157                                 *x0 = x;
00158                                 *y0 = y;
00159                                 CompOutCode(*x0, *y0, &outcode0, &V);
00160                         } else {
00161                                 *x1 = x;
00162                                 *y1 = y;
00163                                 CompOutCode(*x1, *y1, &outcode1, &V);
00164                         }
00165                 }
00166         } while (!done);
00167         return clip;
00168 }

Generated on Sat Apr 1 09:03:52 2006 for GXSM by  doxygen 1.4.6