      SUBROUTINE CURVE(X,Y,NE,DELTA)
C
C     NAME: CURVE
C
C    LANGUAGE:  FORTRAN
C
C    OPERATING SYSTEM:  UNIVERSAL
C
C    ORDER NUMBER:  5428-SE
C
C    PART NUMBER:  000-026366  NOVEMBER 1985
C
C    PRODUCT:  UNIVERSAL VERSAPLOT COLOR RANDOM 2.0
C
C    VERSATEC, INC., SANTA CLARA, CALIFORNIA 95051
C    A XEROX COMPANY
C
C    Copyright (C) 1985 by Xerox Corporation.  All rights reserved.
C
C    "NOTICE. THIS PROGRAM IS THE EXCLUSIVE PROPERTY OF VERSATEC,
C    INC. AND IS ISSUED IN STRICT CONFIDENCE UNDER A PREARRANGED
C    LICENSE AGREEMENT AND IS NOT TO BE DISCLOSED IN ANY MANNER TO
C    PERSONS OUTSIDE THE LICENSED ORGANIZATION AND SHALL NOT BE
C    REPRODUCED OR DISSEMINATED, IN WHOLE OR PART, TO ANYONE OUTSIDE
C    THE LICENSED ORGANIZATION WITHOUT THE PRIOR WRITTEN APPROVAL OF
C    VERSATEC, INC. UNLESS OTHERWISE PROVIDED FOR BY SUCH LICENSE
C    AGREEMENT.  THIS WORK IS PROTECTED AS AN UNPUBLISHED WORK UNDER
C    THE COPYRIGHT ACT OF 1976."
C
C     CURVE - PERFORMS CURVE APPROXIMATION WITH SOLID OR DASHED LINES
C
C     SUBROUTINE CURVE IS USED TO GENERATE A SMOOTH CONTINUOUS CURVED
C     LINE THROUGH A SERIES OF USER-DEFINED COORDINATE DATA POINTS.
C     COORD. DATA PTS. MAY BE SCALED OR UNSCALED, AND THE GENERATED
C     LINE MAY OPTIONALLY BE DASHED OR SOLID.  THE ALGORITHM EMPLOYED
C     IS INVARIANT UNDER AXIS ROTATION AND USED LOCAL PROCEEDURES FOR
C     INCREMENTALLY APPROXIMATING A SMOOTH CURVE.
C
C     ENTRY: CALL CURVE(X,Y,NE,DELTA)
C
C            X,Y  - AN ARRAY OF COORDINATE POINTS TO BE JOINED
C                   BY A SMOOTH CURVE.
C
C             NE  - (ABSOLUTE) IS THE NUMBER OF COORDINATE POINTS
C                   IN X AND Y.
C
C                 -NE - INDICATES THAT SCALE FACTORS ARE LOCATED AS
C                      THE LAST TWO ELEMENTS OF EACH DATA ARRAY
C                      (I.E. NE+1 AND NE+2).
C
C                 +NE - INDICATES THAT THE COORD. POINTS ARE ALREADY
C                      SCALED FOR PLOTTING (NO SCALE FACTORS).
C
C           DELTA  - (ABSOLUTE) IS THE SEGMENT LENGTH FOR THE
C                   INCREMENTAL APPROXIMATION OF THE CURVE.
C
C                 +DELTA - INDICATES THAT THE CURVE IS TO BE
C                          GENERATED WITH A SOLID LINE.
C
C                 -DELTA - INDICATES THE CURVE IS TO BE GENERATED
C                         WITH DASHED LINES (OF 'DELTA' LENGTH).
C
C     NOTES: AT THE MINIMUM THREE POINTS ARE REQUIRED FOR CURVE
C            APPROXIMATION.  IF NE IS SPECIFIED AS +-2 THE TWO DATA
C            POINTS WILL BE JOINED WITH A STRAIGHT LINE.  IF NE IS
C            SPECIFIED AS 0 OR +-1, OR DELTA IS DEFINED AS ZERO NO
C            PLOTTING TAKES PLACE AND EXECUTION RETURNS DIRECTLY TO
C            THE CALLING PROGRAM.
C
C     EXIT: RETURN
C
C     CALLS:   PLOT
C
C     CALLED BY:  USER
C
C     COMMON USED:
C
C     /MSGCOM/
C            I INTARG()- ARRAY FOR PASSING INTEGER OUTPUT ARGUMENTS
C            R RELARG()- ARRAY FOR PASSING REAL OUTPUT ARGUMENTS
C
C
C     LOCAL:
C            R  A,B,C,D- TEMPORARY WORKING VARIABLES
C              E,F,G,H
C            R  C1     - COSINE OF THE SLOPE (TANGENT) AT X1,Y1
C            R  C2     - COSINE OF THE SLOPE (TANGENT) AT X2,Y2
C            R  DELT   - ABSOLUTE DELTA
C            R  DLTSQ  - DELTA SQUARED
C            R  DLTX1  - DELTA DIST. BETWEEN THE POINTSX(K-1),Y(K-1)
C            R  DLTY1  - AND X(K), Y(K)
C            R  DLTX2  - DELTA DISTANCES BETWEEN THE POINTS X(K), Y(K)
C            R  DLTY2  - AND X(K+1), Y(K+1)
C            I  IPEN   - PEN UP (3) OR DOWN (2) INDICATOR
C            I  K      - COORDINATE DATA ARRAY INDEX FOR X AND Y
C            I  MPEN   - PEN SWITCH TO SELECT SOLID (4) OR DASHED (5)
C                      LINES
C            I  NET    - ABSOLUTE NE
C            R  S1     - SINE OF THE SLOPE (TANGENT) AT X1, Y1
C            R  S2     - SINE OF THE SLOPE (TANGENT) AT X2, Y2
C            R  T,T1,T2- TEMPORARY WORKING VARIABLES
C              T3,U,V
C            R  X1,Y1  - WORKING VARIABLES FOR THE PREVIOUS DATA POINT
C                      X(K-1), Y(K-1)
C            R  X2,Y2  - WORKING VARIABLES FOR THE CURRENT DATA POINT
C                      X(K), Y(K)
C            R  XFAC   - X AND Y SCALING FACTORS
C            R  YFAC
C            R  XOFF   - X AND Y SCALING OFFSETS
C                          E.G. XX=(X(K)-XOFF)/XFAC
C                               YY=(Y(K)-YOFF)/YFAC
C
C
C     THE CURVE APPROXIMATION ALGORITHM EMPLOYED BY SUBROUTINE CURVE
C     IS BASED ON A DISSERTATION PRESENTED BY DR. J. McCONALOGUE
C     (IMPERIAL COLLEGE, LONDON) IN THE COMPUTER JOURNAL, NOVEMBER
C     1970.  FOR DETAILED INFORMATION REGARDING THE OPERATION OF THE
C     BASIC ALGORITHM THE USER IS REFERRED TO THIS PUBLICATION.
C
C     McCONALOGUE, D. J. (1970).  A QUASI-INTRINSIC SCHEME FOR PASSING
C     A SMOOTH CURVE THROUGH A DISCRETE SET OF POINTS, THE COMPUTER
C     JOURNAL, VOL. 13, NO. 4, pp. 392-6.
C
C
C...  COMMON /MSGCOM/ - MESSAGE OUTPUT VARIABLES
C
      COMMON /MSGCOM/ INTARG(8), RELARG(12)
C
C
      DIMENSION X(1),Y(1)
C
C-D   DEBUG MESSAGE
C      RELARG(1)=X(1)
C      RELARG(2)=Y(1)
C      INTARG(1)=NE
C      RELARG(3)=DELTA
C      CALL MSGLG1(9)
C-D
C
C
C...  SET DEFAULT SCALE FACTORS.
      XOFF = 0.
      YOFF = 0.
      XFAC = 1.
      YFAC = 1.
      NET = NE
C
C...  DETERMINE WHETHER THE USER IS PROVIDING HIS OWN SCALE FACTORS.
      IF (NET)  10,900,20
C
C...  PICK UP THE SCALE FACTORS DEFINED BY THE USER.
   10 NET = -NET
      XOFF = X(NET+1)
      YOFF = Y(NET+1)
      XFAC = X(NET+2)
      YFAC = Y(NET+2)
C
C...  CHECK FOR SOLID(+ DELTA) OR DASHED(- DELTA) LINES
C     IF SOLID MPEN=4, IF DASHED MPEN=5.  MPEN IS USED TO SWITCH
C     BETWEEN PEN UP, PEN DOWN OR ALWAYS SELECT PEN DOWN.
C      IPEN = 5 - IPEN           -DASHED LINES-
C        3 = 5-2 OR 2=5-3
C      IPEN = 4 - IPEN           - SOLID LINES-
C        2 = 4-2
   20 MPEN = 4
      DELT = DELTA
      IF (DELT)  30,900,50
C
C...  DASHED LINE
   30 DELT = -DELT
      MPEN = 5
C
C...  INITIALIZE FOR COORDINATE PROCESSING.  K(COORDINATE INDEX) IS
C     INITIALIZED TO THE FIRST POINT, IPEN IS SET FOR A PEN UP MOVE
C     POINT, AND DLTSQ IS SET EQUAL TO DELTA SQUARED.
   50 K = 1
      IPEN = 3
      DLTSQ = DELTA*DELTA
C
C*******************************************************************
C*      BEGIN MAIN LOOP.  (X1,Y1) IS JOINED TO (X2,Y2) BY ARC WITH *
C*      DIRECTION COSINES (C1,S1) AND (C2,S2) AT END POINTS.  FINAL*
C*      VALUES FOR PREVIOUS ARC ARE TAKEN AS INITIAL VALUES FOR    *
C*      NEW ARC.                                                   *
C*******************************************************************
C
C...  COMPUTE THE SCALED COORDINATES FOR THE END POINTS OF THE NEXT
C     ARC.  IF (K=NE) THEN COMPUTE THE LAST DATA POINT.  IF (1<K<NE)
C     THEN COMPUTE AN INTERIM DATA POINT.
  110 X2 = (X(K)-XOFF)/XFAC
      Y2 = (Y(K)-YOFF)/YFAC
      IF (K.EQ.NET) GO TO 130
      IF (K.GT.1)  GO TO 140
C
C...  COMPUTE C2 AND S2 AS THE SINE AND COSINE OF THE SLOPE AT POINT
C     X(K), Y(K)  ON THE CURVE.  SPECIAL CASES ARE ASSUMED FOR THE
C     1ST AND LAST DATA POINT OF THE CURVE WHERE A COORDINATE BRACKET
C     CANNOT BE DIRECTLY DETERMINED.
C
C...   FIRST DATA POINT (K=1)
  120 IF (NET-2) 122,124,126
  122 X1 = (X(1)-XOFF)/XFAC
      Y1 = (Y(1)-YOFF)/YFAC
      CALL PLOT (X1,Y1,+3)
      GO TO 900
  124 DLTX1 = (X(2)-X(1))/XFAC
      DLTY1 = (Y(2)-Y(1))/YFAC
      DLTX2 = DLTX1
      DLTY2 = DLTY1
C
C...  T1 IS EQUAL TO T2
      T1 = DLTX1*DLTX1 + DLTY1*DLTY1
      T3 = T1 + T1
      T2 = T3 + T1
      T1 = -T1
      GO TO 150
  126 DLTX1 = (X(2)-X(1))/XFAC
      DLTY1 = (Y(2)-Y(1))/YFAC
      DLTX2 = (X(3)-X(2))/XFAC
      DLTY2 = (Y(3)-Y(2))/YFAC
      T1 = DLTX1*DLTX1 + DLTY1*DLTY1
      T2 = DLTX2*DLTX2 + DLTY2*DLTY2
      T3 = 2.*SQRT(T1*T2)
      T1 = -T1
      T2 = T3 + T2
      GO TO 150
  130 IF (NET.GT.2)GO TO 135
C
C...  LAST DATA POINT  (K.EQ.2)
      DLTX1 = (X(2)-X(1))/XFAC
      DLTY1 = (Y(2)-Y(1))/YFAC
      DLTX2 = DLTX1
      DLTY2 = DLTY1
C
C...  T1 IS EQUAL TO T2
      T1 = DLTX1*DLTX1 + DLTY1*DLTY1
      T3 = T1 + T1
      T2 = -T1
      T1 = T3 + T1
      GO TO 150
C
C...  LAST DATA POINT (K.GT.2)
  135 DLTX1 = X1 - (X(K-2)-XOFF)/XFAC
      DLTY1 = Y1 - (Y(K-2)-YOFF)/YFAC
      DLTX2 = X2 - X1
      DLTY2 = Y2 - Y1
      T1 = DLTX1*DLTX1 + DLTY1*DLTY1
      T2 = DLTX2*DLTX2 + DLTY2*DLTY2
      T3 = 2.*SQRT(T1*T2)
      T2 = -T2
      T1 = T3 + T1
      GO TO 150
C
C...   INTERIM DATA POINT (1<K<NET)
  140 DLTX1 = X2 - X1
      DLTY1 = Y2 - Y1
      DLTX2 = (X(K+1)-X(K))/XFAC
      DLTY2 = (Y(K+1)-Y(K))/YFAC
      T1 = DLTX1*DLTX1 + DLTY1*DLTY1
      T2 = DLTX2*DLTX2 + DLTY2*DLTY2
C
C...  COMPUTE G AS THE DISTANCE SQUARED BETWEEN THE PREVIOUS POINT
C     (X1,Y1) AND THE CURRENT POINT (X2,Y2).
  150 E = DLTX1*T2 + DLTX2*T1
      F = DLTY1*T2 + DLTY2*T1
      G = SQRT(E*E+F*F)
      IF (G.NE.0.)  G = 1./G
      C2 = G*E
      S2 = G*F
      IF (K.EQ.1)  GO TO 180
C
      U = X2 - X1
      V = Y2 - Y1
      G = U*U + V*V
C
C...  COMPUTE A AS THE COSINE OF THE ANGLE BETWEEN THE TANGENTS AT
C     THE END POINTS OF THE ARC.
      A = C1*C2 + S1*S2
C
C...  CHECK IF (X2,Y2) IS MORE THAN 'DELTA' AWAY FROM (X1,Y1)
C     IF MORE THAN DELTA DISTANCE APART EXECUTION BRANCHES TO THE
C     CALULATION OF COEFFICIENTS OF CUBICS FOR X AND Y.
      IF (G.GE.DLTSQ)  GO TO 200
C
C...  IF (X1,Y1) AND (X2,Y2) ARE LESS THAN DELTA DISTANCE APART CHECK
C     TO SEE IF THEY ARE THE SAME PT.  IF THE SAME, SKIP TO THE NEXT
C     POINT IN THE DATA ARRAY.
      IF (G.GT.0.)  GO TO 170
C
C...  IF THE PTS. ARE LESS THAN DELTA DISTANCE APART BUT NOT THE SAME
C     PT., CHECK FOR TANGENTIAL DISCONTINUITY.  IF THE TANGENTS AT THE
C     TWO PTS. HAVE EFFECTIVELY THE SAME SLOPE (i.e. ANGLE BETWEEN THE
C     TWO TANGENTS IS ZERO; COS(0)=1.), SKIP TO THE NEXT PT.  IF THE
C     TANGENTS AT THE TWO POINTS HAVE DIFFERENT SLOPES, WILL CONNECT A
C     STRAIGHT LINE BETWEEN THE TWO POINTS.
      IF (A.LE.0.99996)  GO TO 180
C
C...  BRANCH EXECUTION FOR COINCIDENT DATA POINTS AND TANGENTIALLY
C     CONTINUOUS DATA POINTS TO SIMPLY SKIP TO THE NEXT DATA POINT.
C     THE ARRAY INDEX K IS INCREMENTED AND IF WITHIN LIMITS EXECUTION
C     LOOPS TO PROCESS THE NEXT COORDINATE POINT IN THE LINE.
  170 K = K + 1
      IF (K.LE.NET)  GO TO 110
C
C...  PLOT COORDINATE POINT JUST CALCULATED
C
C...  MOVES FROM THE CURRENT LOCATION WITH THE PEN EITHER UP OR DOWN.
C     H IS SET TO THE DELTA DIST. BETWEEN INCREMENTS, IPEN IS SET TO
C     2 (PEN DOWN) FOR THE NEXT MOVE.  THEN SETUP FOR PROCESSING THE
C     NEXT COORDINATE POINT IN LINE.
  180 CALL PLOT (X2,Y2,IPEN)
      H = DELT
      IPEN = 2
      GO TO 320
C
C...  CALCULATE THE CUBIC COEFFICIENTS WHICH WILL BE INCREMENTED
C     DURING THE CURVE APPROXIMATION.
  200 A = 7. - A
      E = C1 + C2
      F = S1 + S2
      B = U*E + V*F
      T = SQRT(B*B+2.*A*G)
      C = (T+B)/G
      T = 3.*(T-B)/A
      G = C/12.
      A = G*(C*U-3.*E)
      B = G*(C*V-3.*F)
      U = G*(C2-C1) + A
      V = G*(S2-S1) + B
      C = -C/9.
      A = A*C
      B = B*C
      G = H
C
C...   X AND Y COORDINATES OF ARC ARE GIVEN AS CUBICS IN A PARAMETER
C      GOING FROM ZERO TO T AND HELD IN G.  THE INCREMENT IS DELTA.
C      G IS SET INITIALLY TO SPACE THE FIRST POINT OF THE NEW ARC
C      AT DISTANCE DELTA FROM THE LAST POINT OF THE PREVIOUS ARC.
C
C...  MAKE THE INCREMENTAL CURVE APPROXIMATIONS FROM THE PREVIOUS
C     POINT (X1,Y1) TO THE CURRENT POINT (X2,Y2).  THE ALGORITHM
C     GENERATES A SERIES OF TANGENTIAL SEGMENTS BETWEEN X(K-1), Y(K-1)
C     AND X(K), Y(K) BASED ON A PARABOLIC CURVE DEFINED BY X(K-1),
C     Y(K-1), X(K), Y(K) AND X(K+1), Y(K+1).
C
C     COMPUTE THE NEXT X(E) AND Y(F) COORDINATE
C     DEFINING A SINGL INCREMENTAL SEGMENT OF THE CURVE APPROXIMATION.
C     CALL PLOT TO MOVE THE PEN TO THIS POSITION WITH THE PEN EITHER
C     UP OR DOWN DEPENDING ON THE LINE MODE.
C
  220 E = G*(G*(A*G+U)+C1) + X1
      F = G*(G*(B*G+V)+S1) + Y1
      CALL PLOT (E,F,IPEN)
C
C...  IF THE USER INDICATED SOLID CURVE LINE GENERATION (+DELTA) MPEN
C     IS EQUAL TO 4 AND MPEN-2 WILL NOT CHANGE THE VALUE OF IPEN FOR
C     PEN DOWN MOVES.  IF THE USER INDICATED DASHED LINE GENERATION
C     (-DELTA) MPEN IS EQUAL TO 5 AND MPEN-2 OR MPEN-3 WILL
C     ALTERNATELY FLIP THE STATUS OF IPEN BETWEEN PEN UP, PEN DOWN.
      IPEN = MPEN - IPEN
C
C...  VARIABLE G ACCUMULATES THE ARC LENGTH (AND INTERPOLATION
C     COEFFICIENT) FOR EACH INCREMENTAL MOVE.
      G = G + DELT
C
C...  COMPUTE H, AS THE ARC DISTANCE MOVED (G) MINUS THE TOTAL ARC
C     LENGTH TO BE GENERATED (T).  H POSITIVE INDICATES THAT THE MOVE
C     FROM (X1,Y1) TO (X2,Y2) IS COMPLETE, ELSE THE PROGRAM LOOPS TO
C     STATEMENT 220 TO GENERATE ANOTHER INCREMENT.
      H = G - T
      IF (H.LE.0.)  GO TO 220
C
C...  THE ARC GENERATION FROM (X1,Y1) TO (X2,Y2) IS COMPLETE.  (X2,Y2)
C     IS NOW REDEFINED AS THE PREVIOUS POINT (i.e. X1, Y1), AND THE
C     COORDINATE ARRAY INDEX K IS INCREMENTED TO THE NEXT DATA PT. IN
C     THE ARRAY.
  320 X1 = X2
      Y1 = Y2
      C1 = C2
      S1 = S2
      K = K + 1
C
C...  IF THE ARRAY INDEX K IS WITHIN RANGE PROCESS THE CURVE
C     APPROXIMATION TO THE NEXT POINT.
      IF (K.LE.NET)  GO TO 110
C
C...  CALL PLOT TO COMPLETE THE FINAL PEN MOVEMENT TO THE LAST POINT
C     (IF IT ISN'T EXACTLY THERE ALREADY).
      CALL PLOT (X2,Y2,IPEN)
C
C...  RETURN EXECUTION TO THE CALLING PROGRAM.
  900 RETURN
      END
