C SUBROUTINE VECTOR: BY DR. J.A.FIELD C DEPT. OF ELECTRICAL ENGINEERING C C C THIS SUBROUTINE WILL PLOT POINTS, STRAIGHT LINES, C OR CURVES. IT PREVENTS LINES BEING DRAWN OUTSIDE C THE SCREEN LIMITS, AND AS AN OPTION IT WILL TRIM C LINES TO FIT WITHIN A GIVEN WINDOW. C C C THE CALLING SEQUENCE IS: C C C CALL VECTOR(MODE,ARRAY,BEGIN,END,IVECT,FIRST,LAST,INT,ISPACE,LTPEN) C C WHERE: ARRAY IS REAL C LTPEN IS LOGICAL C ALL OTHERS ARE INTEGER C C C C C C C THE DISPLAY FILE IS GENERATED STARTING AT IVECT(FIRST) C AND AFTER GENERATION , THE PROGRAM SETS 'LAST' SUCH C THAT 'IVECT(LAST)' IS THE LAST ELEMENT IN THE DISPLAY C FILE. 'INT' SPECIFIES THE DISPLAY INTENSITY (0 - 7), C 'ISPACE' SPECIFIES POINT SPACING ON THE SCREEN (1,2,4,8) C RASTER UNIT. IF 'LTPEN=.TRUE.' THEN LIGHT PEN INTERRUPTS C ARE IGNORED. C C C C WHEN (MODE=1) OR (MODE=2), 'ARRAY' IS A (4 BY N) C ARRAY SPECIFYING A SET AT LINES (X1,Y1, X2,Y2), C AND ALL LINES BETWEEN. C C 'ARRAY(1,BEGIN)' AND 'ARRAY(1,END)' WILL BE PLOTTED C FOR (MODE=2) ONLY THAT PART OF A LINE INSIDE A C WINDOW IS PLOTTED. C C C C C WHEN (MODE=3) OR (MODE=4) 'ARRAY' IS A (2 BY N) C ARRAY SPECIFYING THE (X,Y) PAIRS OF A CURVE. THE C CURVE BEGINS AT 'ARRAY(1,BEGIN)' AND ENDS AT C ARRAY(1,END). FOR MODE=4, ONLY THAT PART OF THE C CURVE INSIDE THE WINDOW IS PLOTTED. C C C C C C C C C C C C C C C C WHEN (MODE=5) OR (MODE=6) , 'ARRAY' IS A (2 BY N) C ARRAY SPECIFYING (X,Y) POINTS TO BE PLOTTED. C THE FIRST POINT IS AT 'ARRAY(1,BEGIN),ARRAY(2,BEGIN) C AND THE LAST IS AT 'ARRAY(1,END),ARRAY(2,END). C FOR MODE =6, ONLY THOSE POINTS INSIDE THE WINDOW C ARE PLOTTED. C C C C C C C WINDOW: C C TO SPECIFY A WINDOW REQUIRES THE STATEMENT; C C COMMON/FRAME/A,B,C,D C C IN THE MAIN PROGRAM. THE WINDOW KEEPS- C A.LE.X.LE.B C C.LE.Y.LE.D C C NOTE: THESE LIMITS ARE INDEPENDENT OF 'XMAX' ETC., C THAT SPECIFY THE SCREEN SIZE. THERE IS NO NEED C FOR THE WINDOW TO BE COMPLETELY ON THE SCREEN. C C C C C C C C SUBROUTINE VECTOR (MODE,PICT,FIRST,LAST,IVECT,II,JJ,INT,ISPACE 1,LTPEN) LOGICAL LTPEN,SWITCH,POINT INTEGER FIRST,OLDX,OLDY,PREV DIMENSION PICT (2,10),IVECT(100) COMMON /LIMITS/XMIN,XMAX,YMIN,YMAX COMMON /FRAME/ A,B,C,D COMMON/LINEND/XBEGIN,YBEGIN,XFINAL,YFINAL L = 1 SWITCH = .FALSE. IF (MODE.LT.1) STOP 123456 IF (MODE.GT.6) STOP 123456 GO TO (101,102,103,104,105,106), MODE 101 SWITCH = .TRUE. 102 IFIRST = FIRST*2-1 ILAST = LAST*2 INCRE = 2 GO TO 11 105 SWITCH = .TRUE. 106 L = 0 ILAST = LAST GO TO 200 103 SWITCH = .TRUE. 104 ILAST = LAST - 1 200 IFIRST = FIRST INCRE = 1 11 OLDX = -1 PREV = -1 J = II JOG = 4168 IF (LTPEN) JOG = JOG+2048 ISP = ISPACE/2 IF (ISP.LT.0) ISP = 0 IF (ISP.GT.3) ISP = 3 INTX = INT IF (INT.LT.0) INTX = 7 IF (INT.GT.7) INTX = 7 JOG = JOG + ISP*16 + INT ISCALE = 2**ISP XLOW = AMIN1 (XMIN,XMAX) XHIGH = AMAX1(XMIN,XMAX) YLOW = AMIN1(YMIN,YMAX) YHIGH = AMAX1(YMIN,YMAX) IF (SWITCH) GO TO 20 XLOW = AMAX1(XLOW,AMIN1(AMIN1(A,B),XHIGH)) XHIGH = AMIN1(XHIGH,AMAX1(AMAX1(A,B),XLOW)) YLOW = AMAX1(YLOW,AMIN1(AMIN1(C,D),YHIGH)) YHIGH = AMIN1(YHIGH,AMAX1(AMAX1(C,D),YLOW)) 20 IF (XLOW.EQ.XHIGH.OR.YLOW.EQ.YHIGH) GO TO 65 XDIFF = 1023./(XMAX-XMIN) YDIFF = 1023./(YMAX-YMIN) DO 9 I = IFIRST,ILAST,INCRE C C GET END POINTS OF LINE C XBEGIN = PICT (1,I) YBEGIN = PICT (2,I) K = I+L XFINAL = PICT (1,K) YFINAL = PICT (2,K) C C TRIM LINE SO THAT IT WILL FIT ON THE SCREEN C SWITCH = ABS(XFINAL-XBEGIN).GT.ABS(YFINAL-YBEGIN) IF (SWITCH) GO TO 50 60 IF (XBEGIN.GT.XFINAL) CALL SWAP IF (XBEGIN.GT.XHIGH.OR.XFINAL.LT.XLOW) GO TO 9 IF (XBEGIN.LT.XLOW) CALL TRIM(XBEGIN,YBEGIN,XLOW,XFINAL,YFINAL) IF (XFINAL.GT.XHIGH) CALL TRIM(XFINAL,YFINAL,XHIGH,XBEGIN 1,YBEGIN) IF (SWITCH) GO TO 70 50 IF (YBEGIN.GT.YFINAL) CALL SWAP IF (YBEGIN.GT.YHIGH.OR.YFINAL.LT.YLOW) GO TO 9 IF (YBEGIN.LT.YLOW) CALL TRIM(YBEGIN,XBEGIN,YLOW,YFINAL 2,XBEGIN) IF (YFINAL.GT.YHIGH) CALL TRIM(YFINAL,XFINAL,YHIGH,YBEGIN 3,XBEGIN) IF (SWITCH) GO TO 60 C C CONVERT END POINTS TO SCREEN COORDINATES C 70 IXX1 = (XBEGIN - XMIN)*XDIFF + 0.5 IYY1 = (YBEGIN - YMIN)*YDIFF + 0.5 IXX2 = (XFINAL - XMIN)*XDIFF + 0.5 IYY2 = (YFINAL - YMIN)*YDIFF + 0.5 C C CHECK IF BEAM REPOSITIONING REQUIRED C IF (IXX1.NE.OLDX) GO TO 1111 IF (IYY1.EQ.OLDY) GO TO 2 1111 IF (IXX2.NE.OLDX) GO TO 1 IF (IYY2.NE.OLDY) GO TO 1 IXX2 = IXX1 IYY2 = IYY1 IXX1 = OLDX IYY1 = OLDY GO TO 2 C C BEAM REPOSITIONING IS REQUIRED. THREE POSSIBLE CASES EXIST. C C PREV = -1 , INITIAL POINT C PREV = 0 , LAST ITEM WAS A VECTOR C PREV - +1 , LAST ITEM WAS A POINT C 1 POINT = .FALSE. 17 IF (PREV) 1001,1002,1003 C C ADJUST PREVIOUS POINT WORD C 1003 IVECT(J) = IVECT(J) - 24576 GO TO 1004 C C INSERT ESCAPE BIT IN PREVIOUS VECTOR, AND ADD PARAMETER WORD C 1002 IVECT(J) = IVECT(J) + 65536 + 65536 1001 J = J+1 IVECT(J) = 8192 + JOG C C ADD POINT WORDS C 1004 J = J+1 IVECT(J) = IYY1 + 73728 J = J+1 IVECT(J) = IXX1 + 33792 C C INDICATE THAT POINT OPERATION HAS OCCURRED C PREV = 1 IF (POINT) GO TO 9 C C REMEMBER WHERE END OF LINE NOW IS C 2 OLDX = IXX2 OLDY = IYY2 C C START GENERATION OF THE REQUIRED VECTOR C IWORD = 65536 C C GET SIGN OF DELTA X C IXINC = IXX2 - IXX1 IF (IXINC.GE.0) GO TO 3 IWORD = IWORD + 128 IXINC = -IXINC C C GET SIGN OF DELTA Y C 3 IYINC = IYY2 - IYY1 IF (IYINC.GE.0) GO TO 4 IWORD = IWORD + 32768 IYINC = -IYINC C C IF SCALE NOT UNITY THEN MUST ADJUST FOR SCALE FACTOR C 4 IF (ISCALE.EQ.1) GO TO 5 IX = IXINC/ISCALE IY = IYINC/ISCALE IXJUST = IXINC - IX*ISCALE IYJUST = IYINC - IY*ISCALE IXINC = IX IYINC = IY C C CALCULATE NUMBER OF LINE SEGMENTS REQUIRED C 5 IF (IXINC + IYINC.EQ.0) GO TO 6 ISEGMT = (MAX0(IYINC,IXINC)-1)/127 + 1 IROUND = ISEGMT/2 IX = 0 IY = 0 C C GENERATE VECTOR ELEMENTS DO 100 M = 1,ISEGMT IXVEC = (IXINC*M+IROUND)/ISEGMT - IX IYVEC = (IYINC*M+IROUND)/ISEGMT - IY IX = IX + IXVEC IY = IY + IYVEC J = J+1 100 IVECT (J) = IWORD + IYVEC*256 + IXVEC C C INDICATE VECTOR GENERATION HAS OCCURRED C PREV = 0 C C CHECK IF MUST ADJUST FOR NON-UNITY SCALE FACTOR C 6 IF (ISCALE.EQ.1) GO TO 9 POINT = .TRUE. IXX1 = OLDX IYY1 = OLDY IF (IXJUST+IYJUST.GT.0) GO TO 17 C 9 CONTINUE C C CHECK IF ENDED ON A POINT OR VECTOR, OR NEVER GOT STARTED C 65 IF (PREV) 13,14,12 C C IT'S A VECTOR C 14 IVECT(J) = IVECT(J) + 65536 + 65536 GO TO 13 12 IVECT(J) = IVECT(J) - 32768 13 J = J+1 IVECT(J) = 57344 JJ = J+1 RETURN END C C C C C C C C C C C C C SUBROUTINE TRIM(XOUT,YOUT,XBOUND,XOK,YOK) C C IN ORDER TO RETAIN AS MUCH ACCURACY AS POSSIBLE WHEN ONE OF C THE END POINTS IS CLOSE TO THE MACHINE BOUND, WE WILL ALWAYS C CALCULATE THE Y INTERCEPT BY SUBTRACTION FROM THE POINT C NEAREST THE XBOUND C BASE = (YOUT-YOK)/(XOUT-XOK) DELTA1 = XBOUND-XOUT DELTA2 = XBOUND - XOK IF (ABS(DELTA1).GT.ABS(DELTA2)) GO TO 1 YOUT = YOUT + DELTA1*BASE GO TO 2 1 YOUT = YOK + DELTA2*BASE 2 XOUT = XBOUND RETURN END C C C C C C C C C C SUBROUTINE SWAP COMMON/LINEND/ XFIRST,YFIRST,XLAST,YLAST TEMP = XFIRST XFIRST = XLAST XLAST = TEMP TEMP = YFIRST YFIRST = YLAST YLAST = TEMP RETURN END