C
C     The following code was excerpted from: angle.f
C
      DOUBLE PRECISION FUNCTION ANGLE(XA,YA,XB,YB,XC,YC)
      IMPLICIT LOGICAL (A-Z)
      DOUBLE PRECISION XA,XB,XC,YA,YB,YC
C
C     Written and copyright by:
C        Barry Joe, Dept. of Computing Science, Univ. of Alberta
C        Edmonton, Alberta, Canada  T6G 2H1
C        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca
C
C     Purpose: Compute the interior angle (in radians) at vertex
C        (XB,YB) of the chain formed by the directed edges from
C        (XA,YA) to (XB,YB) to (XC,YC) - the interior is to the
C        left of the two directed edges.
C
C     Input parameters:
C        XA,YA, XB,YB, XC,YC - vertex coordinates
C
C     Returned function value:
C        ANGLE - angle between 0 and 2*PI (PI/2 in degenerate case)
C
      DOUBLE PRECISION PI,TOL
      COMMON /GCONST/ PI,TOL
      SAVE /GCONST/
C
      DOUBLE PRECISION T,X1,X2,Y1,Y2
      DOUBLE PRECISION SIGNUS
C
      X1 = XA - XB
      Y1 = YA - YB
      X2 = XC - XB
      Y2 = YC - YB
      T = SQRT((X1**2 + Y1**2)*(X2**2 + Y2**2))
      IF (T .EQ. 0.0D0) T = 1.0D0
      T = (X1*X2 + Y1*Y2)/T
C
C     Eliminate the call to sign to avoid using the fortran math library
C     IF (ABS(T) .GT. 1.0D0 - TOL) T = SIGN(1.0D0,T)
C
      SIGNUS = -1.0D0
      IF (T .GT. 0.0D0) SIGNUS = 1.0D0
C
      IF (ABS(T) .GT. 1.0D0 - TOL) T = SIGNUS
      ANGLE = ACOS(T)
      IF (X2*Y1 - Y2*X1 .LT. 0.0D0) ANGLE = 2.0D0*PI - ANGLE
      END
C
C     The following code was excerpted from: areapg.f
C
      DOUBLE PRECISION FUNCTION AREAPG(NVRT,XC,YC)
      IMPLICIT LOGICAL (A-Z)
      INTEGER NVRT
      DOUBLE PRECISION XC(NVRT),YC(NVRT)
C
C     Written and copyright by:
C        Barry Joe, Dept. of Computing Science, Univ. of Alberta
C        Edmonton, Alberta, Canada  T6G 2H1
C        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca
C
C     Purpose: Compute twice the signed area of a simple polygon with
C        vertices given in circular (CCW or CW) order.
C
C     Input parameters:
C	 NVRT - number of vertices on the boundary of polygon (>= 3)
C	 XC(1:NVRT),YC(1:NVRT) - vertex coordinates in CCW or CW order
C
C     Returned function value:
C        AREAPG - twice the signed area of polygon, positive if CCW
C
      INTEGER I
      DOUBLE PRECISION SUM
C
      SUM = XC(1)*(YC(2) - YC(NVRT)) + XC(NVRT)*(YC(1) - YC(NVRT-1))
      DO 10 I = 2,NVRT-1
	 SUM = SUM + XC(I)*(YC(I+1) - YC(I-1))
   10 CONTINUE
      AREAPG = SUM
      END
C
C     The following code was excerpted from: areatr.f
C
      DOUBLE PRECISION FUNCTION AREATR(XA,YA,XB,YB,XC,YC)
      IMPLICIT LOGICAL (A-Z)
      DOUBLE PRECISION XA,XB,XC,YA,YB,YC
C
C     Written and copyright by:
C        Barry Joe, Dept. of Computing Science, Univ. of Alberta
C        Edmonton, Alberta, Canada  T6G 2H1
C        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca
C
C     Purpose: Compute twice the signed area of the triangle with
C         vertices (XA,YA), (XB,YB), and (XC,YC) in CCW or CW order.
C
C     Input parameters:
C        XA,YA, XB,YB, XC,YC - vertex coordinates
C
C     Returned function value:
C        AREATR - twice the signed area of triangle, positive if CCW
C
      AREATR = (XB - XA)*(YC - YA) - (XC - XA)*(YB - YA)
      END
C
C     The following code was excerpted from: diaedg.f
C
      INTEGER FUNCTION DIAEDG(X0,Y0,X1,Y1,X2,Y2,X3,Y3)
      IMPLICIT LOGICAL (A-Z)
      DOUBLE PRECISION X0,X1,X2,X3,Y0,Y1,Y2,Y3
C
C     Written and copyright by:
C        Barry Joe, Dept. of Computing Science, Univ. of Alberta
C        Edmonton, Alberta, Canada  T6G 2H1
C        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca
C
C     Purpose: Determine whether 02 or 13 is the diagonal edge chosen
C        based on the circumcircle criterion, where (X0,Y0), (X1,Y1),
C        (X2,Y2), (X3,Y3) are the vertices of a simple quadrilateral
C        in counterclockwise order.
C
C     Input parameters:
C        X0,Y0, X1,Y1, X2,Y2, X3,Y3 - vertex coordinates
C
C     Returned function value:
C        DIAEDG -  1 if diagonal edge 02 is chosen, i.e. 02 is inside
C                  quadrilateral + vertex 3 is outside circumcircle 012
C                 -1 if diagonal edge 13 is chosen, i.e. 13 is inside
C                  quadrilateral + vertex 0 is outside circumcircle 123
C                  0 if four vertices are cocircular
C
      DOUBLE PRECISION PI,TOL
      COMMON /GCONST/ PI,TOL
      SAVE /GCONST/
C
      DOUBLE PRECISION CA,CB,DX10,DX12,DX30,DX32,DY10,DY12,DY30,DY32
      DOUBLE PRECISION S,TOLA,TOLB
C
      DX10 = X1 - X0
      DY10 = Y1 - Y0
      DX12 = X1 - X2
      DY12 = Y1 - Y2
      DX30 = X3 - X0
      DY30 = Y3 - Y0
      DX32 = X3 - X2
      DY32 = Y3 - Y2
      TOLA = TOL*MAX(ABS(DX10),ABS(DY10),ABS(DX30),ABS(DY30))
      TOLB = TOL*MAX(ABS(DX12),ABS(DY12),ABS(DX32),ABS(DY32))
      CA = DX10*DX30 + DY10*DY30
      CB = DX12*DX32 + DY12*DY32
      IF (CA .GT. TOLA .AND. CB .GT. TOLB) THEN
	 DIAEDG = -1
      ELSE IF (CA .LT. -TOLA .AND. CB .LT. -TOLB) THEN
	 DIAEDG = 1
      ELSE
	 TOLA = MAX(TOLA,TOLB)
	 S = (DX10*DY30 - DX30*DY10)*CB + (DX32*DY12 - DX12*DY32)*CA
	 IF (S .GT. TOLA) THEN
	    DIAEDG = -1
	 ELSE IF (S .LT. -TOLA) THEN
	    DIAEDG = 1
	 ELSE
	    DIAEDG = 0
	 ENDIF
      ENDIF
      END
C
C     The following code was excerpted from: diam2.f
C
      SUBROUTINE DIAM2(NVRT,XC,YC,I1,I2,DIAMSQ)
      IMPLICIT LOGICAL (A-Z)
      INTEGER I1,I2,NVRT
      DOUBLE PRECISION DIAMSQ,XC(NVRT),YC(NVRT)
C
C     Written and copyright by:
C        Barry Joe, Dept. of Computing Science, Univ. of Alberta
C        Edmonton, Alberta, Canada  T6G 2H1
C        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca
C
C     Purpose: Find the diameter of a convex polygon with vertices
C        given in CCW order and with all interior angles < PI.
C
C     Input parameters:
C	 NVRT - number of vertices on the boundary of convex polygon
C	 XC(1:NVRT),YC(1:NVRT) - vertex coordinates in CCW order
C
C     Output parameters:
C        I1,I2 - indices in XC,YC of diameter edge; diameter is from
C              (XC(I1),YC(I1)) to (XC(I2),YC(I2))
C        DIAMSQ - square of diameter
C
C     Abnormal return:
C        IERR is set to 200
C
C     Routines called:
C        AREATR
C
      INTEGER IERR
      DOUBLE PRECISION PI,TOL
      COMMON /GERROR/ IERR
      COMMON /GCONST/ PI,TOL
      SAVE /GERROR/,/GCONST/
C
      INTEGER J,JP1,K,KP1,M
      DOUBLE PRECISION AREATR
      DOUBLE PRECISION AREA1,AREA2,C1MTOL,C1PTOL,DIST
C
C     Find first vertex which is farthest from edge connecting
C     vertices with indices NVRT, 1.
C
      C1MTOL = 1.0D0 - TOL
      C1PTOL = 1.0D0 + TOL
      J = NVRT
      JP1 = 1
      K = 2
      AREA1 = AREATR(XC(J),YC(J),XC(JP1),YC(JP1),XC(K),YC(K))
   10 CONTINUE
         AREA2 = AREATR(XC(J),YC(J),XC(JP1),YC(JP1),XC(K+1),YC(K+1))
         IF (AREA2 .GT. AREA1*C1PTOL) THEN
   	    AREA1 = AREA2
   	    K = K + 1
   	    GO TO 10
         ENDIF
      M = K
      DIAMSQ = 0.0D0
C
C     Find diameter = maximum distance of antipodal pairs.
C
      AREA1 = AREATR(XC(J),YC(J),XC(JP1),YC(JP1),XC(K),YC(K))
   20 CONTINUE
	 KP1 = K + 1
	 IF (KP1 .GT. NVRT) KP1 = 1
         AREA2 = AREATR(XC(J),YC(J),XC(JP1),YC(JP1),XC(KP1),YC(KP1))
	 IF (AREA2 .GT. AREA1*C1PTOL) THEN
	    K = K + 1
	    AREA1 = AREA2
	 ELSE IF (AREA2 .LT. AREA1*C1MTOL) THEN
	    J = JP1
	    JP1 = J + 1
	    AREA1 = AREATR(XC(J),YC(J),XC(JP1),YC(JP1),XC(K),YC(K))
	 ELSE
	    K = K + 1
	    J = JP1
	    JP1 = J + 1
	    AREA1 = AREATR(XC(J),YC(J),XC(JP1),YC(JP1),XC(K),YC(K))
	 ENDIF
	 IF (J .GT. M .OR. K .GT. NVRT) THEN
	    IERR = 200
	    RETURN
	 ENDIF
	 DIST = (XC(J) - XC(K))**2 + (YC(J) - YC(K))**2
	 IF (DIST .GT. DIAMSQ) THEN
	    DIAMSQ = DIST
	    I1 = J
	    I2 = K
	 ENDIF
      IF (J .NE. M .OR. K .NE. NVRT) GO TO 20
      END
C
C     The following code was excerpted from: lrline.f
C
      INTEGER FUNCTION LRLINE(XU,YU,XV1,YV1,XV2,YV2,DV)
      IMPLICIT LOGICAL (A-Z)
      DOUBLE PRECISION DV,XU,XV1,XV2,YU,YV1,YV2
C
C     Written and copyright by:
C        Barry Joe, Dept. of Computing Science, Univ. of Alberta
C        Edmonton, Alberta, Canada  T6G 2H1
C        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca
C
C     Purpose: Determine whether a point is to the left of, right of,
C        or on a directed line parallel to a line through given points.
C
C     Input parameters:
C        XU,YU, XV1,YV1, XV2,YV2 - vertex coordinates; the directed
C              line is parallel to and at signed distance DV to the
C              left of the directed line from (XV1,YV1) to (XV2,YV2);
C              (XU,YU) is the vertex for which the position
C              relative to the directed line is to be determined
C        DV - signed distance (positive for left)
C
C     Returned function value:
C        LRLINE - +1, 0, or -1 depending on whether (XU,YU) is
C              to the right of, on, or left of the directed line
C              (0 if line degenerates to a point)
C
      DOUBLE PRECISION PI,TOL
      COMMON /GCONST/ PI,TOL
      SAVE /GCONST/
C
      DOUBLE PRECISION DX,DXU,DY,DYU,T,TOLABS
      DOUBLE PRECISION SIGNUS
C
      DX = XV2 - XV1
      DY = YV2 - YV1
      DXU = XU - XV1
      DYU = YU - YV1
      TOLABS = TOL*MAX(ABS(DX),ABS(DY),ABS(DXU),ABS(DYU),ABS(DV))
      T = DY*DXU - DX*DYU
      IF (DV .NE. 0.0D0) T = T + DV*SQRT(DX**2 + DY**2)
C
C     Eliminate the call to sign to avoid using the fortran math library
C     LRLINE = INT(SIGN(1.0D0,T))
C
      SIGNUS = -1.0D0
      IF (T .GT. 0.0D0) SIGNUS = 1.0D0
C
      LRLINE = INT(SIGNUS)
      IF (ABS(T) .LE. TOLABS) LRLINE = 0
      END
C
C     The following code was excerpted from: shrnk2.f
C
      SUBROUTINE SHRNK2(NVRT,XC,YC,SDIST,NSHR,XS,YS,IEDGE)
      IMPLICIT LOGICAL (A-Z)
      INTEGER NSHR,NVRT
      INTEGER IEDGE(0:NVRT)
      DOUBLE PRECISION SDIST(0:NVRT-1)
      DOUBLE PRECISION XC(0:NVRT),YC(0:NVRT),XS(0:NVRT),YS(0:NVRT)
C
C     Purpose: Shrink a convex polygon, with vertices given in CCW
C        order and with all interior angles < PI, by distance SDIST(I)
C        for Ith edge, I = 0,...,NVRT-1.
C
C     Input parameters:
C	 NVRT - number of vertices on the boundary of convex polygon
C	 XC(0:NVRT),YC(0:NVRT) - vertex coordinates in CCW order;
C              (XC(0),YC(0)) = (XC(NVRT),YC(NVRT))
C        SDIST(0:NVRT-1) - nonnegative shrink distances for edges
C
C     Output parameters:
C        NSHR - number of vertices on boundary of shrunken polygon;
C              0 if shrunken polygon is empty else 3 <= NSHR <= NVRT
C        XS(0:NSHR),YS(0:NSHR) - coordinates of shrunken polygon in CCW
C              order if NSHR > 0; (XS(0),YS(0)) = (XS(NSHR),YS(NSHR))
C        IEDGE(0:NVRT) - indices of edges of shrunken polygon in
C              range from 0 to NVRT-1
C
C     Abnormal return:
C        IERR is set to 202
C
C     Routines called:
C        LRLINE, XLINE
C
      INTEGER IERR
      DOUBLE PRECISION PI,TOL
      COMMON /GERROR/ IERR
      COMMON /GCONST/ PI,TOL
      SAVE /GERROR/,/GCONST/
C
      INTEGER LRLINE
      INTEGER I,J,K,LR
      DOUBLE PRECISION ALPHA,PI2,THETA
      LOGICAL FIRST,PARALL
C
      PI2 = 2.0D0*PI
      ALPHA = ATAN2(YC(1)-YC(0),XC(1)-XC(0))
      CALL XLINE(XC(0),YC(0),XC(1),YC(1),XC(1),YC(1),XC(2),YC(2),
     $   SDIST(0),SDIST(1),XS(1),YS(1),PARALL)
      IF (PARALL) THEN
	 IERR = 202
	 GO TO 90
      ENDIF
      IEDGE(0) = 0
      IEDGE(1) = 1
      I = 2
      J = 0
      NSHR = 1
      FIRST = .TRUE.
C
C     First while loop processes edges subtending angle <= PI
C     with respect to first edge.
C
   10 CONTINUE
      THETA = ATAN2(YC(I+1)-YC(I),XC(I+1)-XC(I)) - ALPHA
      IF (THETA .LT. 0.0D0) THETA = THETA + PI2
      IF (THETA .GT. PI + TOL) GO TO 40
   20    CONTINUE
	    LR = LRLINE(XS(NSHR),YS(NSHR),XC(I),YC(I),XC(I+1),YC(I+1),
     $         SDIST(I))
	    IF (LR .LT. 0) GO TO 30
	    NSHR = NSHR - 1
	    IF (NSHR .GE. 1) GO TO 20
   30    CONTINUE
	 IF (NSHR .LT. 1 .AND. ABS(THETA - PI) .LE. TOL) GO TO 90
	 K = IEDGE(NSHR)
	 NSHR = NSHR + 1
	 CALL XLINE(XC(K),YC(K),XC(K+1),YC(K+1),XC(I),YC(I),XC(I+1),
     $      YC(I+1),SDIST(K),SDIST(I),XS(NSHR),YS(NSHR),PARALL)
	 IF (PARALL) THEN
	    IERR = 202
	    GO TO 90
	 ENDIF
	 IEDGE(NSHR) = I
	 I = I + 1
      GO TO 10
C
C     Second while loop processes remaining edges.
C
   40 CONTINUE
	 IF (FIRST) THEN
	    FIRST = .FALSE.
	    GO TO 50
	 ENDIF
	 LR = LRLINE(XS(J),YS(J),XC(I),YC(I),XC(I+1),YC(I+1),SDIST(I))
	 IF (LR .LE. 0) GO TO 70
   50       CONTINUE
	       IF (NSHR .LE. J) GO TO 90
	       LR = LRLINE(XS(NSHR),YS(NSHR),XC(I),YC(I),XC(I+1),
     $            YC(I+1),SDIST(I))
	       IF (LR .GE. 0) THEN
		  NSHR = NSHR - 1
		  GO TO 50
	       ENDIF
	    K = IEDGE(NSHR)
	    NSHR = NSHR + 1
	    CALL XLINE(XC(K),YC(K),XC(K+1),YC(K+1),XC(I),YC(I),XC(I+1),
     $         YC(I+1),SDIST(K),SDIST(I),XS(NSHR),YS(NSHR),PARALL)
	    IF (PARALL) THEN
	       IERR = 202
	       GO TO 90
	    ENDIF
	    IEDGE(NSHR) = I
   60       CONTINUE
	    LR = LRLINE(XS(J+1),YS(J+1),XC(I),YC(I),XC(I+1),YC(I+1),
     $         SDIST(I))
	    IF (LR .GE. 0) THEN
	       J = J + 1
	       GO TO 60
	    ENDIF
	    K = IEDGE(J)
	    CALL XLINE(XC(K),YC(K),XC(K+1),YC(K+1),XC(I),YC(I),XC(I+1),
     $         YC(I+1),SDIST(K),SDIST(I),XS(J),YS(J),PARALL)
	    IF (PARALL) THEN
	       IERR = 202
	       GO TO 90
	    ENDIF
	    XS(NSHR+1) = XS(J)
	    YS(NSHR+1) = YS(J)
	    IEDGE(NSHR+1) = IEDGE(J)
   70    CONTINUE
	 I = I + 1
      IF (I .LT. NVRT) GO TO 40
C
      IF (J .GT. 0) THEN
	 DO 80 I = 0,NSHR+1-J
	    XS(I) = XS(I+J)
	    YS(I) = YS(I+J)
	    IEDGE(I) = IEDGE(I+J)
   80    CONTINUE
      ENDIF
      NSHR = NSHR + 1 - J
      RETURN
C
   90 CONTINUE
      NSHR = 0
      RETURN
      END
C
C     The following code was excerpted from: width2.f
C
      SUBROUTINE WIDTH2(NVRT,XC,YC,I1,I2,WIDSQ)
      IMPLICIT LOGICAL (A-Z)
      INTEGER I1,I2,NVRT
      DOUBLE PRECISION WIDSQ,XC(NVRT),YC(NVRT)
C
C     Written and copyright by:
C        Barry Joe, Dept. of Computing Science, Univ. of Alberta
C        Edmonton, Alberta, Canada  T6G 2H1
C        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca
C
C     Purpose: Find the width (minimum breadth) of a convex polygon with
C        vertices given in CCW order and with all interior angles < PI.
C
C     Input parameters:
C	 NVRT - number of vertices on the boundary of convex polygon
C	 XC(1:NVRT),YC(1:NVRT) - vertex coordinates in CCW order
C
C     Output parameters:
C        I1,I2 - indices in XC,YC such that width is from vertex
C              (XC(I1),YC(I1)) to line joining (XC(I2),YC(I2)) and
C              (XC(I2+1),YC(I2+1)), where index NVRT+1 is same as 1
C        WIDSQ - square of width
C
C     Abnormal return:
C        IERR is set to 201
C
C     Routines called:
C        AREATR
C
      INTEGER IERR
      DOUBLE PRECISION PI,TOL
      COMMON /GERROR/ IERR
      COMMON /GCONST/ PI,TOL
      SAVE /GERROR/,/GCONST/
C
      INTEGER A,B,C,J,JP1,K,KP1,M
      DOUBLE PRECISION AREATR
      DOUBLE PRECISION AREA1,AREA2,C1MTOL,C1PTOL,DIST,DX,DY
C
C     Find first vertex which is farthest from edge connecting
C     vertices with indices NVRT, 1.
C
      C1MTOL = 1.0D0 - TOL
      C1PTOL = 1.0D0 + TOL
      J = NVRT
      JP1 = 1
      K = 2
      AREA1 = AREATR(XC(J),YC(J),XC(JP1),YC(JP1),XC(K),YC(K))
   10 CONTINUE
         AREA2 = AREATR(XC(J),YC(J),XC(JP1),YC(JP1),XC(K+1),YC(K+1))
         IF (AREA2 .GT. AREA1*C1PTOL) THEN
   	    AREA1 = AREA2
   	    K = K + 1
   	    GO TO 10
         ENDIF
      M = K
      WIDSQ = 0.0D0
C
C     Find width = min distance of antipodal edge-vertex pairs.
C
      AREA1 = AREATR(XC(J),YC(J),XC(JP1),YC(JP1),XC(K),YC(K))
   20 CONTINUE
	 KP1 = K + 1
	 IF (KP1 .GT. NVRT) KP1 = 1
         AREA2 = AREATR(XC(J),YC(J),XC(JP1),YC(JP1),XC(KP1),YC(KP1))
	 IF (AREA2 .GT. AREA1*C1PTOL) THEN
	    A = J
	    B = K
	    K = K + 1
	    C = K
	    IF (C .GT. NVRT) C = 1
	    AREA1 = AREA2
	 ELSE IF (AREA2 .LT. AREA1*C1MTOL) THEN
	    A = K
	    B = J
	    C = JP1
	    J = JP1
	    JP1 = J + 1
	    AREA1 = AREATR(XC(J),YC(J),XC(JP1),YC(JP1),XC(K),YC(K))
	 ELSE
	    A = K
	    B = J
	    C = JP1
	    K = K + 1
	    J = JP1
	    JP1 = J + 1
	    AREA1 = AREATR(XC(J),YC(J),XC(JP1),YC(JP1),XC(K),YC(K))
	 ENDIF
         IF (J .GT. M .OR. K .GT. NVRT) THEN
	    IERR = 201
	    RETURN
	 ENDIF
	 DX = XC(C) - XC(B)
	 DY = YC(C) - YC(B)
	 DIST = ((YC(A) - YC(B))*DX - (XC(A) - XC(B))*DY)**2/
     $      (DX**2 + DY**2)
	 IF (DIST .LT. WIDSQ .OR. WIDSQ .LE. 0.0D0) THEN
	    WIDSQ = DIST
	    I1 = A
	    I2 = B
	 ENDIF
      IF (J .NE. M .OR. K .NE. NVRT) GO TO 20
      END
C
C     The following code was excerpted from: xedge.f
C
      SUBROUTINE XEDGE(MODE,XV1,YV1,XV2,YV2,XW1,YW1,XW2,YW2,XU,YU,
     $   INTSCT)
      IMPLICIT LOGICAL (A-Z)
      INTEGER MODE
      DOUBLE PRECISION XU,XV1,XV2,XW1,XW2,YU,YV1,YV2,YW1,YW2
      LOGICAL INTSCT
C
C     Written and copyright by:
C        Barry Joe, Dept. of Computing Science, Univ. of Alberta
C        Edmonton, Alberta, Canada  T6G 2H1
C        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca
C
C     Purpose: Determine whether two edges or a ray and an edge
C        intersect and return the intersection point if they do.
C
C     Input parameters:
C        MODE - 0 for two edges, 1 (or nonzero) for a ray and an edge
C        XV1,YV1, XV2,YV2, XW1,YW1, XW2,YW2 - vertex coordinates;
C              an edge (ray) is from (XV1,YV1) to (thru) (XV2,YV2);
C              an edge joins vertices (XW1,YW1) and (XW2,YW2)
C
C     Output parameters:
C        XU,YU - coordinates of the point of intersection iff INTSCT
C              is .TRUE.
C        INTSCT - .TRUE. if the edges/ray are nondegenerate, not
C              parallel, and intersect, .FALSE. otherwise
C
      DOUBLE PRECISION PI,TOL
      COMMON /GCONST/ PI,TOL
      SAVE /GCONST/
C
      DOUBLE PRECISION DENOM,DXV,DXW,DYV,DYW,T,TOLABS
C
      INTSCT = .FALSE.
      DXV = XV2 - XV1
      DYV = YV2 - YV1
      DXW = XW2 - XW1
      DYW = YW2 - YW1
      TOLABS = TOL*MAX(ABS(DXV),ABS(DYV),ABS(DXW),ABS(DYW))
      DENOM = DYV*DXW - DXV*DYW
      IF (ABS(DENOM) .LE. TOLABS) RETURN
      T = (DYV*(XV1 - XW1) - DXV*(YV1 - YW1))/DENOM
      IF (T .LT. -TOL .OR. T .GT. 1.0D0 + TOL) RETURN
      XU = XW1 + T*DXW
      YU = YW1 + T*DYW
      IF (ABS(DXV) .GE. ABS(DYV)) THEN
	 T = (XU - XV1)/DXV
      ELSE
	 T = (YU - YV1)/DYV
      ENDIF
      IF (MODE .EQ. 0) THEN
         IF (T .GE. -TOL .AND. T .LE. 1.0D0 + TOL) INTSCT = .TRUE.
      ELSE
         IF (T .GE. -TOL) INTSCT = .TRUE.
      ENDIF
      END
C
C     The following code was excerpted from: xline.f
C
      SUBROUTINE XLINE(XV1,YV1,XV2,YV2,XW1,YW1,XW2,YW2,DV,DW,
     $   XU,YU,PARALL)
      IMPLICIT LOGICAL (A-Z)
      DOUBLE PRECISION DV,DW,XU,XV1,XV2,XW1,XW2,YU,YV1,YV2,YW1,YW2
      LOGICAL PARALL
C
C     Written and copyright by:
C        Barry Joe, Dept. of Computing Science, Univ. of Alberta
C        Edmonton, Alberta, Canada  T6G 2H1
C        Phone: (403) 492-5757      Email: barry@cs.ualberta.ca
C
C     Purpose: Determine the intersection point of two lines parallel
C        to lines through given points.
C
C     Input parameters:
C        XV1,YV1, XV2,YV2, XW1,YW1, XW2,YW2 - vertex coordinates;
C              first line is parallel to and at signed distance DV to
C              left of directed line from (XV1,YV1) to (XV2,YV2);
C              second line is parallel to and at signed distance DW to
C              left of directed line from (XW1,YW1) to (XW2,YW2)
C        DV,DW - signed distances (positive for left)
C
C     Output parameters:
C        XU,YU - coordinates of the point of intersection iff PARALL
C              is .FALSE.
C        PARALL - .TRUE. if the lines are parallel or two points for a
C              line are identical, .FALSE. otherwise
C
      DOUBLE PRECISION PI,TOL
      COMMON /GCONST/ PI,TOL
      SAVE /GCONST/
C
      DOUBLE PRECISION A11,A12,A21,A22,B1,B2,DET,TOLABS
C
      PARALL = .TRUE.
      A11 = YV2 - YV1
      A12 = XV1 - XV2
      A21 = YW2 - YW1
      A22 = XW1 - XW2
      TOLABS = TOL*MAX(ABS(A11),ABS(A12),ABS(A21),ABS(A22))
      DET = A11*A22 - A21*A12
      IF (ABS(DET) .LE. TOLABS) RETURN
      B1 = XV1*A11 + YV1*A12
      IF (DV .NE. 0.0D0) B1 = B1 - DV*SQRT(A11**2 + A12**2)
      B2 = XW1*A21 + YW1*A22
      IF (DW .NE. 0.0D0) B2 = B2 - DW*SQRT(A21**2 + A22**2)
      XU = (B1*A22 - B2*A12)/DET
      YU = (B2*A11 - B1*A21)/DET
      PARALL = .FALSE.
      END
