*------------- Telecommunications & Signal Processing Lab --------------
*                          McGill University
*
*
* Module:
*     SUBROUTINE DECOUP (MINX,MINY, MAXX,MAXY, IX1,IY1, IX2,IY2,
*                        IX1C,IY1C, IX2C,IY2C, INVIS)
*
*
* Purpose:
*     Clip a vector to a rectangle
*
*
* Description:
*     This routine clips a vector, returning the end points of the
*     visible portion of the vector.  If the vector is completely
*     inside the given rectangle, the end points are the original
*     vector end points.  If only part of the vector is visible, the
*     end points are determined as the intersection of the vector with
*     the rectangle.  If no part of the vector is visible, a flag is
*     set.  This routine uses the clipping algorithm due to D. Cohen
*     and I. Sutherland as described in "Principles of Interactive
*     Computer Graphics" by W. M. Newman and R. F. Sproull.
*
*
* Parameters:
* I ->  MINX,MINY - X and Y coordinates or the lower lefthand corner of
*                   the visible rectangle (plotting coordinates)
* I ->  MAXX,MAXY - X and Y coordinates of the upper righthand corner
*                   of the visible rectangle (plotting coordinates)
* I ->  IX1,IY1   - X and Y coordinates of the start of the vector
*                   (plotting coordinates)
* I ->  IX2,IY2   - X and Y coordinates of the end of the vector
*                   (plotting coordinates)
* I <-  IX1C,IY1C - X and Y coordinates of the start of the visible
*                   part of the vector (plotting coordinates).  If no
*                   part of the vector is visible, these are set equal
*                   to the start of the vector, IX1C=IX1 and IY1C=IY1.
* I <-  IX2C,IY2C - X and Y coordinates of the end of the visible part
*                   of the vector (plotting coordinates).  If no part
*                   of the vector is visible, these are set equal to
*                   the end of the vector, IX2C=IX2 and IY2C=IY2.
* I <-  IVISIB    - Variable indicating if any part of the vector is
*                   visible
*                   0 - The entire vector is invisible
*                   1 - Part of the line is visible; the start of the
*                       vector has been changed.
*                   2 - Part of the line is visible; the end of the
*                       vector has been changed.
*                   3 - Part of the line is visible; both the start of
*                       the vector and the end of the vector have been
*                       changed.
*                   4 - The entire vector is visible
*
*
* Author / revision:
*     P. Kabal
*     $Revision: 1.5 $  $Date: 1995/03/08 15:27:44 $
*
*
*-----------------------------------------------------------------------

      SUBROUTINE DECOUP (MINX,MINY, MAXX,MAXY, IX1,IY1, IX2,IY2,
     -                   IX1C,IY1C, IX2C,IY2C, IVISIB)


* IC(i) values:
*    1 - Left                6 - Bottom and Right
*    2 - Right               7 - invalid
*    3 - invalid             8 - Top
*    4 - Bottom              9 - Top and Left
*    5 - Bottom and Left    10 - Top and Right
      INTEGER IL,IR,IB,IBL,IBR,IT,ITL,ITR
      PARAMETER (IL=1,IR=2,IB=4,IBL=5,IBR=6,IT=8,ITL=9,ITR=10)

      INTEGER MINX,MINY,MAXX,MAXY,IX1,IY1,IX2,IY2,IX1C,IY1C,IX2C,IY2C,
     -        IVISIB
      INTEGER I
      INTEGER IX(2),IY(2),IC(2),IV(2)
      INTEGER IANDTB(0:ITR,0:ITR)
      INTEGER IPOSN

      REAL DIFX,DIFY

* For two position codes, this table implements the logical AND of the
* codes (certain input codes are unallowed)
*                  0   L   R  --   B  BL  BR  --   T  TL  TR
      DATA IANDTB/ 0,  0,  0, -1,  0,  0,  0, -1,  0,  0,  0, 
     -             0, IL,  0, -1,  0, IL,  0, -1,  0, IL,  0,
     -             0,  0, IR, -1,  0,  0, IR, -1,  0,  0, IR,
     -            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     -             0,  0,  0, -1, IB, IB, IB, -1,  0,  0,  0,
     -             0, IL,  0, -1, IB,IBL, IB, -1,  0, IL,  0,
     -             0,  0, IR, -1, IB, IB,IBR, -1,  0,  0, IR,
     -            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
     -             0,  0,  0, -1,  0,  0,  0, -1, IT, IT, IT,
     -             0, IL,  0, -1,  0, IL,  0, -1, IT,ITL, IT,
     -             0,  0, IR, -1,  0,  0, IR, -1, IT, IT,ITR/


      IX1C=IX1
      IY1C=IY1
      IX2C=IX2
      IY2C=IY2

* Determine the visibility of the end points
      IC(1)=IPOSN(MINX,MINY,MAXX,MAXY,IX1C,IY1C)
      IC(2)=IPOSN(MINX,MINY,MAXX,MAXY,IX2C,IY2C)

* Quick exit for a completely visible vector
      IF (IC(1).EQ.0 .AND. IC(2).EQ.0) THEN
        IVISIB=4
        GO TO 900

* Check for the condition that the ends of the vector are
* both Left, both Right, both Bottom, or both Top
      ELSE IF (IANDTB(IC(1),IC(2)) .GT. 0) THEN
        IVISIB=0
        GO TO 900

      END IF

* At most only part of the vector is visible
      DIFX=IX2C-IX1C
      DIFY=IY2C-IY1C
      IX(1)=IX1C
      IY(1)=IY1C
      IX(2)=IX2C
      IY(2)=IY2C

      IV(1)=0
      IV(2)=0
      IVISIB=0
      DO 500 I=1,2

 100    IF (IC(I).NE.0) THEN

          IV(I)=I
          IF (IC(I).EQ.IT) THEN

* Crosses top edge (find the intersection with IY=MAXY)
            IX(I)=IX1C + NINT((MAXY-IY1C)*(DIFX/DIFY))
            IY(I)=MAXY

          ELSE IF (IC(I).EQ.IB) THEN

* Crosses bottom edge (find the intersection with IY=MINY)
            IX(I)=IX1C + NINT((MINY-IY1C)*(DIFX/DIFY))
            IY(I)=MINY

          ELSE IF (IC(I).EQ.IL .OR. IC(I).EQ.IBL .OR. IC(I).EQ.ITL) THEN

* Crosses left edge (find the intersection with IX=MINX)
            IY(I)=IY1C + NINT((MINX-IX1C)*(DIFY/DIFX))
            IX(I)=MINX

          ELSE IF (IC(I).EQ.IR .OR. IC(I).EQ.IBR .OR. IC(I).EQ.ITR) THEN

* Crosses right edge (find the intersection with IX=MAXX)
            IY(I)=IY1C + NINT((MAXX-IX1C)*(DIFY/DIFX))
            IX(I)=MAXX

          END IF

* Check if the redefined end point is outside the boundaries
          IC(I)=IPOSN(MINX,MINY,MAXX,MAXY,IX(I),IY(I))
          IF (IANDTB(IC(1),IC(2)) .GT. 0) GO TO 900

        GO TO 100
        END IF
 500  CONTINUE

* Vector (IX(1),IY(1)) to (IX(2),IY(2)) is visible
* Return the updated coordinates
      IVISIB=IV(1)+IV(2)
      IX1C=IX(1)
      IY1C=IY(1)
      IX2C=IX(2)
      IY2C=IY(2)


 900  RETURN

      END
