SUBROUTINE GSFILL(X,Y,N,TX,TY) DIMENSION X(N),Y(N), TX(N),TY(N) C C DIGLIB POLYGON FILL SUPPORT C DERIVED FROM "HATCH" ALGORITHM BY KELLY BOOTH C COMMON /GCDCHR/ DEVID, XLENCM, YLENCM, XRES, YRES, 1 NDCLRS, IDVBTS, NFLINE, XCLIPD, YCLIPD COMMON /GCDPRM/ XS, YS, XT, YT, RCOS, RSIN, VXL, VXH, VYL, VYH LOGICAL*1 LINILT, LPOSND COMMON /GCLTYP/ ILNTYP, DLEFT, DIST(4,3), LINILT, LPOSND C DIMENSION XINS(40) INTEGER GSIVIS LOGICAL*1 LEFT DATA FACT /16.0/ C C ***** C DEFINE ARITHMETIC STATEMENT FUNCTION TO MAPPING VERTICES YMAP(YYY) = 2.0*AINT(YSCALE*YYY+0.5)+1.0 C ***** C IF (N .LT. 3) RETURN C C C CONVERT TO ABSOLUTE COORD. C DO 10 I=1,N CALL GSRST(X(I),Y(I),TX(I),TY(I)) 10 CONTINUE CALL MINMAX(TY,N,YMIN,YMAX) CALL MINMAX(TX,N,XMIN,XMAX) C C IF CLIPPING NEEDED OR IF NO HARDWARE POLYGON FILL, USE SOFTWARE C IF ((GSIVIS(XMIN,YMIN) .NE. 0) .OR. 1 (GSIVIS(XMAX,YMAX) .NE. 0) .OR. 2 (IAND(IDVBTS,256) .EQ. 0)) GO TO 200 C C IF CAN HANDLE CONCAVE POLYGONS, JUST CALL DRIVER C IF ((IAND(IDVBTS,512) .EQ. 0) .OR. 1 (N .EQ. 3)) GO TO 150 C C IF HERE, DRIVER CAN HANDLE CONVEX NON-INTERSECTING POLYGONS ONLY, C SO MAKE SURE THIS POLYGON IS CONVEX AND NON-SELF-INTERSECTING. C DX1 = X(1)-X(N) DY1 = Y(1)-Y(N) DY = DY1 !OLD NON-ZERO DELTA-Y NCHNGS = 0 !NUMBER OF TIMES DELTA-Y CHANGES SIGN L = 1 COSTH = 0.0 110 CONTINUE C C CONVEXITY TEST C DX2 = X(L+1)-X(L) DY2 = Y(L+1)-Y(L) A = DX1*DY2-DX2*DY1 IF (A*COSTH .LT. 0.0) GO TO 200 IF (COSTH .EQ. 0.0) COSTH = A C C SELF INTERSECTION CHECK - RELYS ON "CONVEXITY" CHECK C IF (DY .NE. 0.0) GO TO 120 DY = DY2 GO TO 130 120 CONTINUE IF (DY2*DY .GE. 0.0) GO TO 130 DY = DY2 NCHNGS = NCHNGS + 1 IF (NCHNGS .GE. 3) GO TO 200 130 CONTINUE DX1 = DX2 DY1 = DY2 L = L + 1 IF (L .LT. N) GO TO 110 150 CONTINUE CALL GSDRVR(1024+N,TX,TY) RETURN C C ********** C SOFTWARE FILL C ********** C 200 CONTINUE C C FILLING A POLYGON IS VERY SIMPLE IF AND ONLY IF THE VERTICES OF C THE POLYGON NEVER LIE ON A SCAN LINE. WE CAN FORCE THIS TO HAPPEN C BY THE FOLLOWING TRICK: MAKE ALL VERTICES LIE JUST BARELY ABOVE C THE SCAN LINE THEY SHOULD LIE ON. THIS IS DONE BY MAPPING THE C VERTICES TO A GRID THAT IS "FACT" TIMES THE DEVICE RESOLUTION, C AND THEN DOUBLING THE GRID DENSITY, AND OFFSETTING THE VERTICES C BY 1. BECAUSE WE DO THIS, WE MUST OUTLINE THE POLYGON. C C ******* C C FILL WITH SOLID LINES C LINOLD = ILNTYP ILNTYP = 1 C LEFT = .TRUE. YSCALE = YS*YRES*FACT DLINES = 2.0*FACT CALL MINMAX(Y,N,YMIN,YMAX) YMIN = AINT(YMAP(YMIN)/DLINES)*DLINES+DLINES YMAX = AINT(YMAP(YMAX)/DLINES)*DLINES YSCAN = YMIN 210 CONTINUE INISEC = 0 IFIRST = 0 C C DO EACH SIDE OF THE POLYGON. PUT ANY X INTERSECTIONS C WITH THE SCAN LINE Y=YSCAN IN XINS C YBEGIN = YMAP(Y(N)) XBEGIN = X(N) DO 400 L = 1, N YEND = YMAP(Y(L)) DY = YSCAN-YBEGIN IF (DY*(YSCAN-YEND) .GT. 0.0) GO TO 390 C C INSERT AN INTERSECTION C INISEC = INISEC + 1 XINS(INISEC) = DY*(X(L)-XBEGIN)/(YEND-YBEGIN)+XBEGIN C 390 CONTINUE YBEGIN = YEND XBEGIN = X(L) 400 CONTINUE C C FILL IF THERE WERE ANY INTERSECTIONS C IF (INISEC .EQ. 0) GOTO 500 C C FIRST WE MUST SORT ON X INTERSECTION. C USE BUBBLE SORT BECAUSE USUALLY ONLY 2. C WHEN "LEFT" IS TRUE, ASCENDING SORT, FALSE IS DESCENDING SORT. C DO 450 I = 1, INISEC-1 XKEY = XINS(I) DO 430 J = I+1, INISEC IF (.NOT. LEFT) GOTO 420 IF (XKEY .GE. XINS(J)) GO TO 430 410 CONTINUE TEMP = XKEY XKEY = XINS(J) XINS(J) = TEMP GO TO 430 420 IF (XKEY .GT. XINS(J)) GOTO 410 430 CONTINUE XINS(I) = XKEY 450 CONTINUE C C DRAW FILL LINES NOW C YY = YSCAN/(2.0*YSCALE) DO 460 I = 1, INISEC, 2 CALL GSMOVE(XINS(I),YY) CALL GSDRAW(XINS(I+1),YY) 460 CONTINUE 500 CONTINUE YSCAN = YSCAN + DLINES*NFLINE LEFT = .NOT. LEFT IF (YSCAN .LE. YMAX) GO TO 210 C C FINALLY, OUTLINE THE POLYGON C CALL GSMOVE(X(N),Y(N)) DO 510 L=1,N CALL GSDRAW(X(L),Y(L)) 510 CONTINUE C C RESTORE LINE TYPE C ILNTYP = LINOLD RETURN END