/** 3DGPL **************************************************\
 *  ()                                                     *
 *  2D line and polygon clipping.                          *
 *                                                         *
 *  Defines:                                               *
 *   C_line_x_clipping       Clipping a line horizontally; *
 *   C_line_y_clipping       Clipping a line vertically;   *
 *                                                         *
 *   C_polygon_x_clipping    Horizontal polygon cliping.   *
 *                                                         *
 *  (6/1995) By Sergei Savchenko. (savs@cs.mcgill.ca).     *
 *  Copyright (c) 1995 Sergei Savchenko.                   *
 *  THIS SOURCE CODE CAN'T BE USED FOR COMERCIAL PURPOSES  *
 *  WITHOUT AUTHORISATION                                  *
\***********************************************************/

#include "../hardware/hardware.h"           /* hardware specific stuff */
#include "../clipper/clipper.h"             /* 2D macros */

int C_2D_clipping;                          /* type of performed clipping */

/**********************************************************\
 *  Line clipping using binary search technique.          *
 *                                                        *
 *  RETUNRNS: 0, when line is compleately ouside          *
 *  --------- 1, boundaries otherwise.                    *
 *                                                        *
 *  SETS:  C_2D_clipping to 1 when both first or both     *
 *  -----  points were changed, 0 otherwise.              *
\**********************************************************/

int C_line_x_clipping(int **vertex1,int **vertex2,int dimension)
{
 register int i;
 register int whereto;
 register int *l,*r,*m,*t;                  /* left right and midle and tmp */
 static int g_store0[C_MAX_DIMENSIONS];     /* static stores for clipped vxes */
 static int g_store1[C_MAX_DIMENSIONS];
 static int g_store2[C_MAX_DIMENSIONS];
 static int g_store3[C_MAX_DIMENSIONS];
 static int g_store4[C_MAX_DIMENSIONS];
 static int g_store5[C_MAX_DIMENSIONS];
 int **vmn,**vmx;                           /* so that *vmn[0] < *vmx[0] */
 int swap;                                  /* were coordinates swaped? */

 C_2D_clipping=0;                           /* default no clipping yet */

 if((*vertex1)[0]<(*vertex2)[0])
 { swap=0; vmn=vertex1; vmx=vertex2; }      /* so that *vmn[0] < *vmx[0] */
 else
 { swap=1; vmn=vertex2; vmx=vertex1; }

 if(((*vmn)[0]>C_X_CLIPPING_MAX)||((*vmx)[0]<C_X_CLIPPING_MIN)) return(0);
 else
 {
  if((*vmn)[0]<=C_X_CLIPPING_MIN)           /* clipping */
  {
   HW_copy_int(*vmn,l=g_store0,dimension);  /* copying old vertices */
   HW_copy_int(*vmx,m=g_store1,dimension);
   r=g_store2;                              

   whereto=0;
   while(m[0]!=C_X_CLIPPING_MIN)
   {
    if(whereto==1) { t=l; l=m; m=t; }
    else           { t=r; r=m; m=t; }
    for(i=0;i<dimension;i++) m[i]=(l[i]+r[i])>>1;
    whereto=m[0]<C_X_CLIPPING_MIN;
   }
   *vmn=m;                                  /* that is why m[] is static */
   C_2D_clipping=swap^1;
  }

  if((*vmx)[0]>=C_X_CLIPPING_MAX)           /* clipping */
  {
   HW_copy_int(*vmn,l=g_store3,dimension);  /* copying old vertices */
   HW_copy_int(*vmx,m=g_store4,dimension);
   r=g_store5;                              

   whereto=0;
   while(m[0]!=C_X_CLIPPING_MAX)
   {
    if(whereto==1) { t=l; l=m; m=t; }
    else           { t=r; r=m; m=t; }
    for(i=0;i<dimension;i++) m[i]=(l[i]+r[i])>>1;
    whereto=m[0]<C_X_CLIPPING_MAX;
   }
   *vmx=m;                                  /* that is why m[] is static */
   C_2D_clipping|=swap&1;
  }
 }
 return(1);                                 /* partialy or not clipped */
}

/**********************************************************\
 *  Line clipping using binary search technique.          *
 *                                                        *
 *  RETUNRNS: 0, when line is compleately ouside          *
 *  --------- 1, boundaries otherwise.                    *
 *                                                        *
 *  SETS:  C_2D_clipping to 1 when both first or both     *
 *  -----  points were changed, 0 otherwise.              *
\**********************************************************/

int C_line_y_clipping(int **vertex1,int **vertex2,int dimension)
{
 register int i;
 register int whereto;
 register int *l,*r,*m,*t;                  /* left right and midle and tmp */
 static int g_store0[C_MAX_DIMENSIONS];     /* static stores for clipped vxes */
 static int g_store1[C_MAX_DIMENSIONS];
 static int g_store2[C_MAX_DIMENSIONS];
 static int g_store3[C_MAX_DIMENSIONS];
 static int g_store4[C_MAX_DIMENSIONS];
 static int g_store5[C_MAX_DIMENSIONS];
 int **vmn,**vmx;                           /* so that *vmn[1] < *vmx[1] */
 int swap;                                  /* were coordinates swaped? */

 C_2D_clipping=0;                           /* default no clipping yet */

 if((*vertex1)[1]<(*vertex2)[1])
 { swap=0; vmn=vertex1; vmx=vertex2; }      /* so that *vmn[1] < *vmx[1] */
 else
 { swap=1; vmn=vertex2; vmx=vertex1; }

 if(((*vmn)[1]>C_Y_CLIPPING_MAX)||((*vmx)[1]<C_Y_CLIPPING_MIN)) return(0);
 else
 {
  if((*vmn)[1]<=C_Y_CLIPPING_MIN)           /* clipping */
  {
   HW_copy_int(*vmn,l=g_store0,dimension);  /* copying old vertices */
   HW_copy_int(*vmx,m=g_store1,dimension);
   r=g_store2;                             

   whereto=0;
   while(m[1]!=C_Y_CLIPPING_MIN)
   {
    if(whereto==1) { t=l; l=m; m=t; }
    else           { t=r; r=m; m=t; }
    for(i=0;i<dimension;i++) m[i]=(l[i]+r[i])>>1;
    whereto=m[1]<C_Y_CLIPPING_MIN;
   }
   *vmn=m;                                  /* that is why m[] is static */
   C_2D_clipping=swap^1;
  }

  if((*vmx)[1]>=C_Y_CLIPPING_MAX)           /* clipping */
  {
   HW_copy_int(*vmn,l=g_store3,dimension);  /* copying old vertices */
   HW_copy_int(*vmx,m=g_store4,dimension);
   r=g_store5;                             

   whereto=0;
   while(m[1]!=C_Y_CLIPPING_MAX)
   {
    if(whereto==1) { t=l; l=m; m=t; }
    else           { t=r; r=m; m=t; }
    for(i=0;i<dimension;i++) m[i]=(l[i]+r[i])>>1;
    whereto=m[1]<C_Y_CLIPPING_MAX;
   }
   *vmx=m;                                  /* that is why m[] is static */
   C_2D_clipping|=swap&1;
  }
 }
 return(1);                                 /* partialy or not clipped */
}

/**********************************************************\
 *  Creating a x-clipped polygon.                         *
 *                                                        *
 *  RETURNS: number of elements in the clipped element.   *
 *  -------  (0 when compleately behind view plane)       *
 *                                                        *
 *          |    |        1-2-3-4-5-6-1  -> 2'-3'-5'-6'   *
 *          |5'  |6'                                      *
 *       5*-*----*-*6      If first dot in the line is    *
 *       /  |    |   \     being clipped both points are  *
 *     4*   |    |    *1   copyed If no clipping or second*
 *       \  |    |   /     dot is clipped then only second*
 *       3*-*----*-*2      dot is copyed. If both points  *
 *          |3'  |2'       are clipped well, neither is   *
 *                         copyed.                        *
\**********************************************************/

int C_polygon_x_clipping(register int *from,register int *to,
                         int dimension,int length
                        )
{
 register int i;
 int *v1,*v2,new_lng=0;
 int *first_vrtx=to;                        /* begining of the source */

 for(i=0;i<length;i++)                      /* for all edges */
 {
  v1=from; from+=dimension; v2=from;        /* taking two vertices */

  if(C_line_x_clipping(&v1,&v2,dimension))  /* clipping */
  {
   if(C_2D_clipping)                        /* depends which one was clipped */
   {
    HW_copy_int(v1,to,dimension); to+=dimension;
    HW_copy_int(v2,to,dimension); to+=dimension;  
    new_lng+=2;                             /* first point clipped */
   }
   else
   {
    HW_copy_int(v2,to,dimension); to+=dimension; 
    new_lng++;                              /* second point clipped */
   }
  }
 }
 HW_copy_int(first_vrtx,to,dimension);      /* looping the polygon vertices */

 return(new_lng);
}

/**********************************************************/
