home *** CD-ROM | disk | FTP | other *** search
- REM > <Graphics$Dir>.Clip
- REM
- REM Line clipping code demonstration
- REM
- REM The algorithm is based on Cohen-Sutherland's
- REM
- REM First both points are give a 4-bit code
- REM dependent on their position as follows:
- REM
- REM 1001 | 1000 | 1010
- REM ------+------+------
- REM 0001 | 0000 | 0010 (0000 is visible window)
- REM ------+------+------
- REM 0101 | 0100 | 0110
- REM
- REM Invisible lines can now easily be rejected
- REM when the logical AND of their codes is not 0
- REM They need not be clipped if the OR of their
- REM codes is 0 (they are completely visible)
- REM They must be clipped otherwise, but could
- REM be rejected later on after the first clip
- REM
- REM Status line:
- REM
- REM Current operation:
- REM
- REM Line can be rejected (outside screen),
- REM processed (possibly partly within screen),
- REM or drawn (line is within screen)
- REM
- REM Coordinates:
- REM
- REM Current (subdivided) coordinates
- REM
- REM Level of subdivision:
- REM
- REM Number of times a subdivision had to be made,
- REM at maximum this is equal to the number of
- REM bits resolution in the original coordinates
- REM
- REM Line number:
- REM
- REM Line which is currently being processed
- REM
- REM Line colours:
- REM
- REM Blue - original
- REM Red - rejected
- REM Green - processing
- REM White - clipped
- REM Magenta - *visible* screen boundary
- REM clipped lines will always end on this
- REM
- REM Keys:
- REM
- REM Stop the program by depressing <Left Shift>
- REM Speed up displaying by depressing <Shift>
- REM
- REM Sounds:
- REM
- REM A beep is heard whenever underflow is encountered
- REM in the clipping code, the coordinates are corrected
- REM
- REM Slow down general display to half speed:
- REM
- S%=FALSE
- REM
- REM Display clipping process:
- REM
- P%=TRUE
- REM
- REM Wait between lines:
- REM
- W%=TRUE
- REM
- REM Display graphics, otherwise full speed text only:
- REM
- G%=TRUE
- REM
- :
- ON ERROR PRINT REPORT$ : ON : END
- :
- REM Any 16 colour mode works, but the display
- REM looks best in MODE 20 as this has exactly
- REM double the resolution of MODE 13
- MODE 20
- IF MODE<>20 THEN
- MODE 12
- IF MODE<>12 THEN
- MODE 9
- IF MODE<>9 THEN
- REM How low can you go...
- ENDIF
- ENDIF
- ENDIF
- OFF
- :
- N%=1
- REPEAT
- REM Lines which fit on the display window
- X1%=640+(RND(2560)-1280)
- Y1%=512+(RND(2048)-1024)
- X2%=640+(RND(2560)-1280)
- Y2%=512+(RND(2048)-1024)
- PROCDraw(X1%,Y1%,X2%,Y2%)
- N%+=1
- UNTIL INKEY(-4) : REM <Left Shift>
- :
- END
- :
- DEF PROCDraw(X1%,Y1%,X2%,Y2%)
- X1%=X1%<<16 : X1%=X1%>>2
- Y1%=Y1%<<16 : Y1%=Y1%>>2
- X2%=X2%<<16 : X2%=X2%>>2
- Y2%=Y2%<<16 : Y2%=Y2%>>2
- PROCOldCoords(X1%>>16,Y1%>>16,X2%>>16,Y2%>>16)
- PROCPrep(X1%,Y1%,X2%,Y2%,F1%,F2%)
- T1%=F1% OR F2% : REM Combination
- T2%=F1% EOR F2% : REM Difference
- T1%=T1% AND NOT T2% : REM Logical intersection
- IF T1%=0 THEN
- IF (F1% OR F2%)=0 THEN
- PROCLine(X1%>>16,Y1%>>16,X2%>>16,Y2%>>16,2,0)
- ELSE
- IF ((F1% OR F2%) AND %0011)<>0 THEN
- PROCClipToX(X1%,Y1%,X2%,Y2%,F1%,F2%)
- PROCPrep(X1%,Y1%,X2%,Y2%,F1%,F2%)
- T1%=F1% OR F2% : REM Combination
- T2%=F1% EOR F2% : REM Difference
- T1%=T1% AND NOT T2% : REM Logical intersection
- ENDIF
- IF T1%=0 THEN
- IF ((F1% OR F2%) AND %1100)<>0 THEN
- PROCClipToY(X1%,Y1%,X2%,Y2%,F1%,F2%)
- ENDIF
- REM No need to reject now, would have
- REM been done by the X clipping part
- PROCLine(X1%>>16,Y1%>>16,X2%>>16,Y2%>>16,2,0)
- ELSE
- REM Line is outside boundaries
- PROCLine(X1%>>16,Y1%>>16,X2%>>16,Y2%>>16,0,0)
- ENDIF
- ENDIF
- ELSE
- REM Line is outside boundaries
- PROCLine(X1%>>16,Y1%>>16,X2%>>16,Y2%>>16,0,0)
- ENDIF
- ENDPROC
- :
- DEF PROCPrep(RETURN X1%,RETURN Y1%,RETURN X2%,RETURN Y2%,RETURN F1%,RETURN F2%)
- IF X2%<X1% THEN
- X1%=X1% EOR X2%
- X2%=X1% EOR X2%
- X1%=X1% EOR X2%
- Y1%=Y1% EOR Y2%
- Y2%=Y1% EOR Y2%
- Y1%=Y1% EOR Y2%
- ENDIF
- F1%=0
- IF X1%<(0<<16) THEN F1%=F1% OR %0001
- IF X1%>(319<<16) THEN F1%=F1% OR %0010
- IF Y1%<(0<<16) THEN F1%=F1% OR %0100
- IF Y1%>(255<<16) THEN F1%=F1% OR %1000
- F2%=0
- IF X2%<(0<<16) THEN F2%=F2% OR %0001
- IF X2%>(319<<16) THEN F2%=F2% OR %0010
- IF Y2%<(0<<16) THEN F2%=F2% OR %0100
- IF Y2%>(255<<16) THEN F2%=F2% OR %1000
- ENDPROC
- :
- DEF PROCClipToX(RETURN X1%,RETURN Y1%,RETURN X2%,RETURN Y2%,F1%,F2%)
- LOCAL X%,Y%,M%
- Y%=Y2%>>1
- Y%-=Y1%>>1 : REM Subdivide Y
- X%=X2%>>1
- X%-=X1%>>1 : REM Subdivide X
- IF X%<>0 THEN
- REPEAT
- IF (F1% AND %0001) THEN
- REM Clip to line X=0
- IF X1%<(0<<16) THEN X1%+=X% : Y1%+=Y% ELSE X1%-=X% : Y1%-=Y%
- IF (X1%>>16)=0 THEN F1%=F1% AND NOT %0001
- ELSE
- IF (F1% AND %0010) THEN
- REM Clip to line X=319
- IF X1%>(319<<16) THEN X1%-=X% : Y1%-=Y% ELSE X1%+=X% : Y1%+=Y%
- IF (X1%>>16)=319 THEN F1%=F1% AND NOT %0010
- ENDIF
- ENDIF
- IF (F2% AND %0001) THEN
- REM Clip to line X=0
- IF X2%<(0<<16) THEN X2%+=X% : Y2%+=Y% ELSE X2%-=X% : Y2%-=Y%
- IF (X2%>>16)=0 THEN F2%=F2% AND NOT %0001
- ELSE
- IF (F2% AND %0010) THEN
- REM Clip to line X=319
- IF X2%>(319<<16) THEN X2%-=X% : Y2%-=Y% ELSE X2%+=X% : Y2%+=Y%
- IF (X2%>>16)=319 THEN F2%=F2% AND NOT %0010
- ENDIF
- ENDIF
- Y%=Y%>>1
- X%=X%>>1
- IF X%=0 THEN F1%=F1% AND NOT %0011 : F2%=F2% AND NOT %0011
- M%+=1
- PROCLine(X1%>>16,Y1%>>16,X2%>>16,Y2%>>16,1,M%)
- UNTIL ((F1% OR F2%) AND %0011)=0
- ENDIF
- REM Lines that have only a single pixel on the
- REM boundary X=0 line could have round off errors
- REM This is for X1% only as this is moved
- IF X1%<0 THEN X1%=0
- REM Update old coords for neater display of clip
- PROCOldCoords(X1%>>16,Y1%>>16,X2%>>16,Y2%>>16)
- ENDPROC
- :
- DEF PROCClipToY(RETURN X1%,RETURN Y1%,RETURN X2%,RETURN Y2%,F1%,F2%)
- LOCAL X%,Y%,M%
- X%=X2%>>1
- X%-=X1%>>1 : REM Subdivide X
- Y%=Y2%>>1
- Y%-=Y1%>>1 : REM Subdivide Y
- IF Y%<>0 THEN
- IF Y%<0 THEN Y%=0-Y% : X%=0-X%
- REPEAT
- IF (F1% AND %0100) THEN
- REM Clip to line Y=0
- IF Y1%<(0<<16) THEN X1%+=X% : Y1%+=Y% ELSE X1%-=X% : Y1%-=Y%
- IF (Y1%>>16)=0 THEN F1%=F1% AND NOT %0100
- ELSE
- IF (F1% AND %1000) THEN
- REM Clip to line Y=255
- IF Y1%>(255<<16) THEN X1%-=X% : Y1%-=Y% ELSE X1%+=X% : Y1%+=Y%
- IF (Y1%>>16)=255 THEN F1%=F1% AND NOT %1000
- ENDIF
- ENDIF
- IF (F2% AND %0100) THEN
- REM Clip to line Y=0
- IF Y2%<(0<<16) THEN X2%+=X% : Y2%+=Y% ELSE X2%-=X% : Y2%-=Y%
- IF (Y2%>>16)=0 THEN F2%=F2% AND NOT %0100
- ELSE
- IF (F2% AND %1000) THEN
- REM Clip to line Y=255
- IF Y2%>(255<<16) THEN X2%-=X% : Y2%-=Y% ELSE X2%+=X% : Y2%+=Y%
- IF (Y2%>>16)=255 THEN F2%=F2% AND NOT %1000
- ENDIF
- ENDIF
- X%=X%>>1
- Y%=Y%>>1
- IF Y%<=0 THEN F1%=F1% AND NOT %1100 : F2%=F2% AND NOT %1100
- M%+=1
- PROCLine(X1%>>16,Y1%>>16,X2%>>16,Y2%>>16,1,M%)
- UNTIL ((F1% OR F2%) AND %1100)=0
- ENDIF
- REM Lines that have only a single pixel on the
- REM boundary Y=0 line could have round off errors
- REM This is for the lowest Y only as this is moved,
- REM however I don't know at this point which one it is
- IF Y1%<0 THEN Y1%=0
- IF Y2%<0 THEN Y2%=0
- IF X1%<0 THEN X1%=0
- IF X2%<0 THEN X2%=0
- REM Update old coords for neater display of clip
- PROCOldCoords(X1%>>16,Y1%>>16,X2%>>16,Y2%>>16)
- ENDPROC
- :
- DEF PROCLine(X1%,Y1%,X2%,Y2%,C%,M%)
- REM C% = 0 rejected, 1 processing, 2 clipped
- REM M% = variable to print (0..255)
- REM Needs P%, S% and W% as global vars (process, slow, wait)
- CASE C% OF
- WHEN 0
- IF G% THEN
- PROCCLine(X1%,Y1%,X2%,Y2%,1)
- PROCText("Rejecting "+FNCoords(X1%,Y1%,X2%,Y2%))
- IF W% THEN
- IF S% THEN PROCWait(150) ELSE PROCWait(75)
- ENDIF
- ELSE
- PROCText("Rejecting")
- ENDIF
- WHEN 1
- IF P% THEN
- IF G% THEN
- PROCCLine(X1%,Y1%,X2%,Y2%,2)
- PROCText("Processing "+FNCoords(X1%,Y1%,X2%,Y2%)+" "+STR$(M%))
- IF S% THEN PROCWait(50) ELSE PROCWait(25)
- ELSE
- PROCText("Processing")
- ENDIF
- ENDIF
- WHEN 2
- IF G% THEN
- PROCCLine(X1%,Y1%,X2%,Y2%,7)
- PROCText("Drawing "+FNCoords(X1%,Y1%,X2%,Y2%))
- IF W% THEN
- IF S% THEN PROCWait(150) ELSE PROCWait(75)
- ENDIF
- ELSE
- PROCText("Drawing")
- ENDIF
- REM Next is just a test to check if
- REM the line was correctly clipped
- PROCPrep(X1%,Y1%,X2%,Y2%,F1%,F2%)
- IF (F1% OR F2%)<>0 THEN
- REM This error should never happen as it
- REM will result in address exceptions later
- ERROR 18,"Error for "+FNCoords(X1%,Y1%,X2%,Y2%)
- ENDIF
- ENDCASE
- ENDPROC
- :
- DEF PROCCLine(X1%,Y1%,X2%,Y2%,C%)
- REM Needs OX1%,OY1%,OX2%,OY2% as global vars (coords)
- CLS
- OFF
- ORIGIN 320,256
- GCOL 0,5 : REM Magenta
- RECTANGLE 0,0,319<<1,255<<1
- GCOL 0,4 : REM Blue
- LINE OX1%<<1,OY1%<<1,OX2%<<1,OY2%<<1
- GCOL 0,C% : REM Colour
- LINE X1%<<1,Y1%<<1,X2%<<1,Y2%<<1
- ENDPROC
- :
- DEF PROCText(T$)
- REM Needs T% and N% as global vars (text, line)
- PRINTTAB(0,0);T$;STRING$(80-(LEN(T$)+LEN(STR$(N%)))," ");STR$(N%)
- ENDPROC
- :
- DEF FNCoords(X1%,Y1%,X2%,Y2%)
- LOCAL S$
- S$ ="("
- S$+=CHR$(ASC(" ")+(ASC("-")-ASC(" "))*ABS(SGN(X1%<<2)<0))
- S$+=RIGHT$("00000"+STR$(ABS(X1%<<2)),5)
- S$+=","
- S$+=CHR$(ASC(" ")+(ASC("-")-ASC(" "))*ABS(SGN(Y1%<<2)<0))
- S$+=RIGHT$("00000"+STR$(ABS(Y1%<<2)),5)
- S$+=","
- S$+=CHR$(ASC(" ")+(ASC("-")-ASC(" "))*ABS(SGN(X2%<<2)<0))
- S$+=RIGHT$("00000"+STR$(ABS(X2%<<2)),5)
- S$+=","
- S$+=CHR$(ASC(" ")+(ASC("-")-ASC(" "))*ABS(SGN(Y2%<<2)<0))
- S$+=RIGHT$("00000"+STR$(ABS(Y2%<<2)),5)
- S$+=")"
- =S$
- :
- DEF PROCOldCoords(X1%,Y1%,X2%,Y2%)
- REM Set global old coords for first clip and second clip
- OX1%=X1%
- OY1%=Y1%
- OX2%=X2%
- OY2%=Y2%
- ENDPROC
- :
- DEF PROCWait(T%)
- LOCAL D%
- IF NOT INKEY(-1) THEN
- D%=INKEY(T%)
- ENDIF
- ENDPROC
- :
-