clipping.c

Go to the documentation of this file.
00001 /*----------------------------------------------------------------------------------------*/
00002 /* FILE      : clipping.c                                                                 */
00003 /* COPYRIGHT : INRIA 2006                                                                 */
00004 /* AUTHORS   : Jean-Baptiste Silvy, Jean-Philipe Chancelier                               */
00005 /* DESC.     : Management of clipping when drawing                                        */
00006 /*----------------------------------------------------------------------------------------*/
00007 
00008 #include "clipping.h"
00009 #include "math_graphics.h"
00010 #include "GetProperty.h"
00011 #include "Xcall1.h"
00012 #include "SetProperty.h"
00013 
00014 /*-------------------------------------------------------------------------------------*/
00015 SClipRegion getClipRegion( struct BCG * scilabXGC )
00016 {
00017   SClipRegion clipping ;
00018 
00019   clipping.leftX   = scilabXGC->CurClipRegion[0];
00020   clipping.rightX  = scilabXGC->CurClipRegion[0] + scilabXGC->CurClipRegion[2];
00021   clipping.bottomY = scilabXGC->CurClipRegion[1] ;
00022   clipping.topY    = scilabXGC->CurClipRegion[1] + scilabXGC->CurClipRegion[3] ;
00023 
00024   return clipping ;
00025 }
00026 /*-------------------------------------------------------------------------------------*/
00027 
00028 /*-------------------------------------------------------------------------------------*/
00029 /* Functions taken from periX11.c used here to work on every plateform                 */
00030 /*-------------------------------------------------------------------------------------*/
00031 
00032 /*-------------------------------------------------------------------------------------*/
00033 
00034 int sciClipPoint(integer x, integer y, SClipRegion * clipping )
00035 {
00036   integer ret_val = 0;
00037 
00038   if (x < clipping->leftX) ret_val |= (char)0x01;
00039   else if (x > clipping->rightX) ret_val |= (char)0x02;
00040   if (y < clipping->bottomY) ret_val |= (char)0x04;
00041   else if (y > clipping->topY ) ret_val |= (char)0x08;
00042   return ret_val;
00043 }
00044 
00045 /*-------------------------------------------------------------------------------------*/
00046 
00047 void sciClipLine( integer       x1      ,
00048                   integer       yy1     ,
00049                   integer       x2      ,
00050                   integer       y2      ,
00051                   integer     * x1n     ,
00052                   integer     * yy1n    ,
00053                   integer     * x2n     ,
00054                   integer     * y2n     ,
00055                   integer     * flag    ,
00056                   SClipRegion * clipping  )
00057 {
00058   integer  x_intr[2], y_intr[2]; /* used to store intersection points 
00059                                   * at most two points 
00060                                   */
00061   integer x, y, dx, dy, count, pos1, pos2; 
00062 
00063   *x1n=x1  ;
00064   *yy1n=yy1;
00065   *x2n=x2  ;
00066   *y2n=y2  ;
00067   *flag=4  ;
00068 
00069   pos1 = sciClipPoint(x1, yy1, clipping ) ;
00070   pos2 = sciClipPoint(x2, y2 , clipping ) ;
00071   if (pos1 || pos2) {
00072     if (pos1 & pos2) { *flag=0;return;}   
00073     /* segment is totally out. */
00074 
00075     /* Here part of the segment MAy be inside. test the intersection
00076      * of this segment with the 4 boundaries for hopefully 2 intersections
00077      * in. If non found segment is totaly out.
00078      */
00079     count = 0;
00080     dx = x2 - x1;
00081     dy = y2 - yy1;
00082 
00083     /* Find intersections with the x parallel bbox lines: */
00084     if (dy != 0) {
00085       x = (integer) ((int) (clipping->bottomY - y2)  * ((double) dx / (double) dy) + x2);
00086       /* Test for clipping.bottomY boundary. */
00087       if (x >= clipping->leftX && x <= clipping->rightX ) {
00088         x_intr[count] = x;
00089         y_intr[count++] = clipping->bottomY ;
00090       }
00091       x = (integer)((clipping->topY - y2) * ((double) dx / (double) dy) + x2); 
00092       /* Test for clipping.topY boundary. */
00093       if ( x >= clipping->leftX && x <= clipping->rightX ) {
00094         x_intr[count] = x;
00095         y_intr[count++] = clipping->topY;
00096       }
00097     }
00098     if ( count < 2 )
00099       {
00100         /* Find intersections with the y parallel bbox lines: */
00101         if (dx != 0) {
00102           y = (integer)((clipping->leftX - x2) * ((double) dy / (double) dx) + y2);   
00103           /* Test for clipping.leftX boundary. */
00104           if (y >= clipping->bottomY && y <= clipping->topY) {
00105             x_intr[count] = clipping->leftX;
00106             y_intr[count++] = y;
00107           }
00108           if ( count < 2 ) 
00109             {
00110               y = (integer)((clipping->rightX - x2) * ((double) dy / (double) dx) + y2);  
00111               /* Test for clipping.rightX boundary. */
00112               if (y >= clipping->bottomY && y <= clipping->topY) {
00113                 x_intr[count] = clipping->rightX;
00114                 y_intr[count++] = y;
00115               }
00116             }
00117         }
00118       }
00119 
00120     if (count == 2) {
00121       if (pos1 && pos2) {          /* Both were out - update both */
00122         *x1n = x_intr[0];
00123         *yy1n = y_intr[0];
00124         *x2n = x_intr[1];
00125         *y2n = y_intr[1];
00126         *flag=3;return;
00127       }
00128       else if (pos1) {       /* Only x1/yy1 was out - update only it */
00129         if (dx * (x2 - x_intr[0]) + dy * (y2 - y_intr[0]) >= 0) {
00130           *x1n = x_intr[0];
00131           *yy1n = y_intr[0];
00132           *flag=1;return;
00133         }
00134         else {
00135           *x1n = x_intr[1];
00136           *yy1n = y_intr[1];
00137           *flag=1;return;
00138         }
00139       }
00140       else {             /* Only x2/y2 was out - update only it */
00141         if (dx * (x_intr[0] - x1) + dy * (y_intr[0] - yy1) >= 0) {
00142           *x2n = x_intr[0];
00143           *y2n = y_intr[0];
00144           *flag=2;return;
00145         }
00146         else {
00147           *x2n = x_intr[1];
00148           *y2n = y_intr[1];
00149           *flag=2;return;
00150         }
00151       }
00152     }
00153     else 
00154       {
00155         /* count != 0 */
00156         *flag=0;
00157         return;
00158       }
00159   }
00160 }
00161 
00162 /*-------------------------------------------------------------------------------------*/
00163 
00164 void sciDrawInsideSegments( integer       iib, 
00165                             integer       iif, 
00166                             integer     * vx , 
00167                             integer     * vy ,
00168                             SClipRegion * clipping )
00169 {
00170   integer x1n,y1n,x11n,y11n,x2n,y2n,flag2=0,flag1=0;
00171   integer npts;
00172   integer * vxNew ; /* the drawn vector */
00173   integer * vyNew ;
00174   int close = 0 ;
00175   /* backup of the first and last bounds of the bounds of the drawn vector
00176      which may be changed */
00177   int prevBounds[4] ;
00178 
00179   npts = ( iib > 0) ? iif-iib+2  : iif-iib+1;  
00180   
00181   if ( iib > 0) 
00182   {
00183     sciClipLine( vx[iib-1], vy[iib-1],
00184                  vx[iib]  , vy[iib]  ,
00185                  &x1n     , &y1n     ,
00186                  &x2n     , &y2n     ,
00187                  &flag1   , clipping ) ;
00188   }
00189   sciClipLine( vx[iif-1], vy[iif-1],
00190                vx[iif]  , vy[iif]  ,
00191                &x11n    , &y11n    ,
00192                &x2n     , &y2n     ,
00193                &flag2   , clipping    ) ;
00194   vxNew = &vx[Max(0,iib-1)] ;
00195   vyNew = &vy[Max(0,iib-1)] ;
00196 
00197   prevBounds[0] = vxNew[0]      ;
00198   prevBounds[1] = vyNew[0]      ;
00199   prevBounds[2] = vxNew[npts-1] ;
00200   prevBounds[3] = vyNew[npts-1] ;
00201 
00202   if ( iib > 0 && (flag1==1||flag1==3) )
00203   {
00204     vxNew[0] = x1n ;
00205     vyNew[0] = y1n ;
00206   }
00207   if ( flag2==2 || flag2==3 )
00208   {
00209     vxNew[npts-1] = x2n ;
00210     vyNew[npts-1] = y2n ;
00211   }
00212 
00213   
00214   C2F (dr) ("xuclines", "xv", &npts, vxNew, vyNew, &close, PI0, PI0, PD0, PD0, PD0, PD0,6L,2L);
00215 
00216   /* restore the possibly changed bounds */
00217   vxNew[0]      = prevBounds[0] ;
00218   vyNew[0]      = prevBounds[1] ;
00219   vxNew[npts-1] = prevBounds[2] ;
00220   vyNew[npts-1] = prevBounds[3] ;
00221 
00222 }
00223 
00224 /*-------------------------------------------------------------------------------------*/
00225 
00226 /* draw the segement defined by (vx[index-1],vy[index-1]) (vx[index],vy[index]) */
00227 void sciDrawOutsideSegment( integer ind, 
00228                             integer *vx,
00229                             integer *vy, 
00230                             SClipRegion * clipping )
00231 {
00233   integer segX[2],segY[2],flag;
00234   sciClipLine( vx[ind-1], vy[ind-1]  ,
00235                vx[ind]  , vy[ind]    ,
00236                &segX[0]   , &segY[0],
00237                &segX[1]   , &segY[1]  ,
00238                &flag      , clipping  ) ;
00239   if ( flag == 3 )
00240   {
00241     int nbPoints = 2 ;
00242     int close    = 0 ;
00243     C2F (dr) ("xuclines", "xv", &nbPoints, segX, segY, &close, PI0, PI0, PD0, PD0, PD0, PD0,6L,2L);
00244   }
00245 }
00246 
00247 /*-------------------------------------------------------------------------------------*/
00248 
00249 /* 
00250  *  returns the first (vx[.],vy[.]) point inside 
00251  *  xleft,xright,ybot,ytop bbox. begining at index ideb
00252  *  or zero if the whole polyline is out 
00253  */
00254 
00255 integer sciFirstInClipRegion( integer       n   ,
00256                               integer       ideb,
00257                               integer     * vx  ,
00258                               integer     * vy  ,
00259                               SClipRegion * clipping )
00260 {
00261   integer i;
00262   for (i=ideb  ; i < n ; i++)
00263   {
00264     if (    vx[i] >= clipping->leftX 
00265          && vx[i] <= clipping->rightX 
00266          && vy[i] >= clipping->bottomY 
00267          && vy[i] <= clipping->topY    )
00268     {
00269       return(i);
00270     }
00271   }
00272   return(-1);
00273 }
00274 
00275 /*-------------------------------------------------------------------------------------*/
00276 
00277 /* 
00278  *  returns the first (vx[.],vy[.]) point outside
00279  *  xleft,xright,ybot,ytop bbox.
00280  *  or zero if the whole polyline is out 
00281  */
00282 integer sciFirstOutClipRegion( integer       n   ,
00283                                integer       ideb,
00284                                integer     * vx  ,
00285                                integer     * vy  ,
00286                                SClipRegion * clipping )
00287 {
00288   integer i;
00289   for ( i=ideb  ; i < n ; i++ )
00290   {
00291     if (    vx[i] < clipping->leftX 
00292          || vx[i] > clipping->rightX  
00293          || vy[i] < clipping->bottomY
00294          || vy[i] > clipping->topY   ) 
00295     {
00296       return(i);
00297     }
00298   }
00299   return(-1);
00300 }
00301 
00302 /*-------------------------------------------------------------------------------------*/
00303 
00304 /* check every segment of the polyline and draw only the part which is in the */
00305 /* clip region */
00306 void C2F(clipPolyLine)( integer       n     , 
00307                         integer     * vx    , 
00308                         integer     * vy    , 
00309                         integer       closed,
00310                         SClipRegion * clipping )
00311 { 
00312   integer iib,iif,ideb=0,vxl[2],vyl[2];
00313   
00314   while (1) 
00315   { 
00316     integer j;
00317     iib = sciFirstInClipRegion( n, ideb, vx, vy, clipping ) ;
00318     if (iib == -1)
00319     { 
00320       for (j=ideb+1; j < n; j++)
00321       {
00322         sciDrawOutsideSegment( j, vx, vy, clipping ) ;
00323       }
00324       break;
00325     }
00326     else
00327     { 
00328       if ( iib - ideb > 1) 
00329       {
00330         /* un partie du polygine est totalement out de ideb a iib -1 */
00331         /* mais peu couper la zone */
00332         for ( j = ideb + 1 ; j < iib; j++ )
00333         {
00334           sciDrawOutsideSegment(j,vx,vy, clipping ) ;
00335         }
00336       }
00337     }
00338     iif = sciFirstOutClipRegion( n, iib, vx, vy, clipping ) ;
00339     if ( iif == -1 ) 
00340     {
00341       /* special case the polyligne is totaly inside */
00342       if (iib == 0) 
00343       {
00344         C2F (dr) ("xuclines", "xv", &n, vx, vy, &closed, PI0, PI0, PD0, PD0, PD0, PD0,6L,2L) ;
00345         return ;
00346       }
00347       else
00348       { 
00349         sciDrawInsideSegments( iib, n-1, vx, vy, clipping ) ;
00350       }
00351       break;
00352     }
00353 
00354     sciDrawInsideSegments( iib, iif, vx, vy, clipping ) ;
00355     ideb=iif;
00356   }
00357   if ( closed )
00358   {
00359     /* The polyligne is closed we consider the closing segment */
00360     integer x1n,y1n,x2n,y2n,flag1=0;
00361     vxl[0]=vx[n-1];vxl[1]=vx[0];vyl[0]=vy[n-1];vyl[1]=vy[0];
00362     sciClipLine( vxl[0], vyl[0],
00363                  vxl[1], vyl[1],
00364                  &x1n  , &y1n  ,
00365                  &x2n  , &y2n  ,
00366                  &flag1, clipping ) ;
00367     
00368     if ( flag1==0 ) { return ; }
00369 
00370     if ( flag1==1 || flag1==3 )
00371     {
00372       vxl[0] = x1n ;
00373       vyl[0] = y1n ;
00374     }
00375     if ( flag1==2 || flag1==3 )
00376     {
00377       vxl[1] = x2n ;
00378       vyl[1] = y2n ;
00379     }
00380     
00381     {
00382       int nbPoints = 2 ;
00383       int close = 0 ;
00384       C2F (dr) ("xuclines", "xv", &nbPoints, vxl, vyl, &close, PI0, PI0, PD0, PD0, PD0, PD0,6L,2L);
00385     }
00386     
00387     
00388   }
00389 }
00390 
00391 /*-------------------------------------------------------------------------------------*/
00392 /*
00393  * get the real clipping (the set one the axe or the window borders) 
00394  * in pixels of a graphic object
00395  */
00396 void getPixelClipping( sciPointObj * pObj, SClipRegion * clipping )
00397 {
00398   double * clipRegion = sciGetClipping( pObj ) ;
00399   clipping->leftX = XDouble2Pixel( clipRegion[0] ) ;
00400   clipping->rightX = XDouble2Pixel( clipRegion[0] + clipRegion[2] ) ;
00401   clipping->bottomY = YDouble2Pixel( clipRegion[1] ) ;
00402   clipping->topY = YDouble2Pixel( clipRegion[1] - clipRegion[3] ) ;
00403   
00404 }
00405 /*-------------------------------------------------------------------------------------*/
00406 void sciClip (sciPointObj *pobj)
00407 {
00408   int x,y,w,h; 
00409   int value;
00410   double *clip_region = NULL;
00411 
00412   sciPointObj * psubwin = sciGetParentSubwin(pobj);
00413   sciSubWindow * ppsubwin = pSUBWIN_FEATURE(psubwin);
00414 
00415   value = sciGetIsClipping(pobj);     /* clipping state */
00416 
00417   if(value == -1) return;
00418   if(ppsubwin->is3d == TRUE) return; /* no clipping in 3d */
00419 
00420   clip_region = sciGetClipping(pobj); /* clipping region */
00421 
00422 
00423   if(sciGetIsClipRegionValuated(pobj) == 0)
00424     value = 0; /* we use the 'clipgrf' value instead */
00425 
00426   if (value == 0){
00427     double clip[4];
00428     double tmpx, tmpy, tmpw, tmph;
00429 
00430     tmpw = fabs(ppsubwin->FRect[2] - ppsubwin->FRect[0]);
00431     tmph = fabs(ppsubwin->FRect[3] - ppsubwin->FRect[1]);
00432 
00433     tmpx = ppsubwin->FRect[0]; /* xmin */
00434     tmpy = ppsubwin->FRect[3]; /* ymax */
00435 
00436     clip[0] = tmpx;
00437     clip[1] = tmpy;
00438     clip[2] = tmpw;
00439     clip[3] = tmph;
00440 
00441     sciSetClipping(pobj,clip);
00442 
00443     frame_clip_on();
00444   }
00445   else if (value > 0)
00446   { 
00447     double tmpw, tmph;
00448     double tmpx, tmpy;
00449 
00450     tmpw = clip_region[2];
00451     tmph = clip_region[3];
00452 
00453     tmpx = clip_region[0];
00454     tmpy = clip_region[1];
00455 
00456     if(ppsubwin->axes.reverse[0] == TRUE)
00457       tmpx = tmpx + tmpw;
00458 
00459     if(ppsubwin->axes.reverse[1] == TRUE)
00460       tmpy = tmpy - tmph;
00461 
00462     x = XDouble2Pixel( tmpx);
00463     y = YDouble2Pixel( tmpy);
00464     w = WDouble2Pixel( tmpx, tmpw);
00465     h = HDouble2Pixel( tmpy, tmph);
00466     C2F(dr)("xset","clipping",&x, &y, &w, &h,PI0,PI0,PD0,PD0,PD0,PD0,4L,8L);
00467   }
00468 }
00469 /*-------------------------------------------------------------------------------------*/
00470 void sciUnClip ( sciPointObj * pobj )
00471 {
00472   int value = sciGetIsClipping(pobj);     /* clipping state */
00473 
00474   if ( value > -1 )
00475   {
00476     C2F(dr)("xset","clipoff",PI0,PI0,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,4L,7L) ;
00477   }
00478 }
00479 /*-------------------------------------------------------------------------------------*/
00480 void frame_clip_on( void )
00481 {
00482   C2F(dr)("xset","clipping",&Cscale.WIRect1[0],&Cscale.WIRect1[1],&Cscale.WIRect1[2],
00483     &Cscale.WIRect1[3],PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
00484 }
00485 /*-------------------------------------------------------------------------------------*/
00486 void frame_clip_off( void )
00487 {
00488   C2F(dr)("xset","clipoff",PI0,PI0,PI0,PI0, PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
00489 }
00490 /*-------------------------------------------------------------------------------------*/

Generated on Sun Mar 4 15:03:50 2007 for Scilab [trunk] by  doxygen 1.5.1