home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1989 / 04 / extra / graf.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1989-01-25  |  9.2 KB  |  385 lines

  1. {************************************************}
  2. {*                   GRAF.PAS                   *}
  3. {*         Grafiksystem mit Treibern für        *}
  4. {*             verschiedene Geräte              *}
  5. {*          (C) 1989 S.Szkaradnik & TOOLBOX     *}
  6. {************************************************}
  7. PROGRAM GraphicPackage ;
  8. TYPE
  9.   Pattern = ARRAY[0..7] OF BYTE;
  10.   Tools   = ( None, Pen ) ;
  11.   Devices = ( Monitor, Plotter, Printer ) ;
  12.   Func    = ( OpenF, PointF, PlotF, DotF,
  13.               ClearF, CloseF ) ;
  14.   ErrMode = ( ClipMode, WrapMode, FenceMode ) ;
  15.   Parameters = RECORD
  16.                  Command : Func ;
  17.                  X, Y : INTEGER ;
  18.                  Result : BOOLEAN ;
  19.                END ;
  20.   PolyPoint = RECORD
  21.                 N : BYTE ;
  22.                 Co : ARRAY[BYTE] OF
  23.                      RECORD
  24.                        X, Y : INTEGER;
  25.                      END ;
  26.               END ;
  27.  
  28. CONST
  29.   Pat : Pattern = ( 128,64,32,16,8,4,2,1 ) ;
  30.  
  31. VAR
  32.   Tool : Tools ;
  33.   Device : Devices ;
  34.   Position : RECORD
  35.                X, Y : INTEGER ;
  36.              END ;
  37.   Xmin, Xmax : INTEGER ;
  38.   Ymin, Ymax : INTEGER ;
  39.   Parameter : Parameters ;
  40.   ErrorMode : ErrMode ;
  41.   BitMap : FILE ;
  42.  
  43. FUNCTION Min ( A, B : INTEGER ) : INTEGER ;
  44. BEGIN
  45.   IF A < B THEN Min := A ELSE Min := B
  46. END ;
  47.  
  48. FUNCTION Max ( A, B : INTEGER ) : INTEGER ;
  49. BEGIN
  50.   IF A > B THEN Max := A ELSE Max := B
  51. END ;
  52.  
  53. PROCEDURE Clip ( VAR X, Y : INTEGER ) ;
  54. BEGIN
  55.   X := Max ( Min ( X, Xmax ), Xmin ) ;
  56.   Y := Max ( Min ( Y, Ymax ), Ymin ) ;
  57. END ;
  58.  
  59. PROCEDURE Fence ;
  60. BEGIN
  61.   WriteLn ( 'Error: Out of range' ) ; Halt
  62. END ;
  63.  
  64. PROCEDURE Wrap ( VAR X, Y : INTEGER ) ;
  65. BEGIN
  66.   IF Y > Ymax THEN
  67.     Y := ( Y - Ymin ) MOD ( Ymax - Ymin ) + Ymin
  68.   ELSE IF Y < Ymin THEN
  69.     Y := - (Ymin - Y) MOD (Ymax - Ymin) + Ymax;
  70.   IF X > Xmax THEN
  71.     X := (X - Xmin) MOD (Xmax - Xmin) + Xmin
  72.   ELSE IF X < Xmin THEN
  73.     X := - (Xmin - X) MOD (Xmax - Xmin) + Xmax;
  74. END ;
  75.  
  76. PROCEDURE Control ( VAR X, Y : INTEGER ) ;
  77. BEGIN
  78.   IF ( X < Xmin ) OR ( X > Xmax )
  79.      OR ( Y < Ymin ) OR ( Y > Ymax )
  80.     THEN
  81.       CASE ErrorMode OF
  82.         ClipMode  : Clip( X, Y ) ;
  83.         WrapMode  : Wrap( X, Y ) ;
  84.         FenceMode : Fence ;
  85.       END ;
  86. END ;
  87. (* GRAPH.P wird in der Turbo 3.0 Version auf *)
  88. (* IBM-Kompatiblen benötigt, um Pixel zu     *)
  89. (* testen. Also:                             *)
  90. (* $I GRAPH.P *)
  91. (*$I MONITOR.TP3 *)
  92. (* Plotter und Printer kommen in Folge 2 *)
  93. (* $I PRINTER.PAS*)
  94. (* $I PLOTTER.PAS*)
  95.  
  96. PROCEDURE CallDevice ( Dev : Devices ) ;
  97. BEGIN
  98.   CASE Dev OF
  99.     Monitor : MonitorDriver ( Parameter ) ;
  100.     (* Plotter und Printer kommen in Folge 2 *)
  101.     Plotter : (* PlotterDriver ( Parameter )*) ;
  102.     Printer : (* PrinterDriver ( Parameter )*) ;
  103.   END
  104. END ;
  105.  
  106. FUNCTION OpenDevice (Output : Devices): BOOLEAN;
  107. BEGIN
  108.   Parameter.Command := OpenF ;
  109.   CallDevice ( Output ) ;
  110.   OpenDevice := Parameter.Result
  111. END ;
  112.  
  113. FUNCTION Point ( X, Y : INTEGER ) : BOOLEAN ;
  114. BEGIN
  115.   Parameter.Command := PointF ;
  116.   Parameter.X := X ; Parameter.Y := Y ;
  117.   CallDevice ( Device ) ;
  118.   Point := Parameter.Result
  119. END ;
  120.  
  121. PROCEDURE Plot ( X, Y : INTEGER ) ;
  122. BEGIN
  123.   Parameter.Command := PlotF ;
  124.   Parameter.X := X ; Parameter.Y := Y ;
  125.   CallDevice ( Device ) ;
  126. END ;
  127.  
  128. PROCEDURE Dot ( X, Y : INTEGER ) ;
  129. BEGIN
  130.   Parameter.Command := DotF ;
  131.   Parameter.X := X ; Parameter.Y := Y ;
  132.   CallDevice ( Device ) ;
  133. END ;
  134.  
  135. PROCEDURE Clear ;
  136. BEGIN
  137.   Parameter.Command := ClearF ;
  138.   CallDevice ( Device ) ;
  139. END ;
  140.  
  141. PROCEDURE Draw ( X, Y : INTEGER ) ;
  142. VAR
  143.   Dx, Dy, Sx, Sy, Xtemp, Ytemp, I, Eps : INTEGER;
  144.   Flag : BOOLEAN ;
  145.  
  146. FUNCTION Sgn ( Val : INTEGER ) : INTEGER ;
  147. BEGIN
  148.   IF Val > 0
  149.     THEN Sgn := 1
  150.     ELSE IF Val < 0
  151.            THEN Sgn := -1
  152.            ELSE Sgn := 0
  153. END ;
  154.  
  155. PROCEDURE Swap ( VAR A, B : INTEGER ) ;
  156. VAR Temp : INTEGER ;
  157. BEGIN
  158.   Temp := A ; A := B ; B := Temp
  159. END ;
  160.  
  161. BEGIN
  162.   Ytemp := Position.Y ; Xtemp := Position.X ;
  163.   Dy := Abs ( Y - Ytemp ) ;
  164.   Dx := Abs ( X - Xtemp ) ;
  165.   Sy := Sgn ( Y - Ytemp ) ;
  166.   Sx := Sgn ( X - Xtemp ) ;
  167.   IF Dx + Dy = 0
  168.     THEN Dot ( Xtemp, Ytemp )
  169.     ELSE
  170.       BEGIN
  171.         Flag := Dy > Dx ;
  172.         IF Flag
  173.           THEN Swap ( Dx, Dy ) ;
  174.         Eps := Dy SHL 1 - Dx ;
  175.         FOR I := 1 TO Dx DO
  176.           BEGIN
  177.             Dot ( Xtemp, Ytemp ) ;
  178.             WHILE Eps >= 0 DO
  179.               BEGIN
  180.                 IF Flag
  181.                   THEN Xtemp := Xtemp + Sx
  182.                   ELSE Ytemp := Ytemp + Sy ;
  183.                 Eps := Eps - Dx SHL 1
  184.               END ;
  185.             IF Flag
  186.               THEN Ytemp := Ytemp + Sy
  187.               ELSE Xtemp := Xtemp + Sx ;
  188.             Eps := Eps + Dy SHL 1
  189.           END
  190.       END ;
  191.   Position.X := X ; Position.Y := Y ;
  192. END ;
  193.  
  194. PROCEDURE Line ( VAR Points : PolyPoint ) ;
  195. VAR
  196.   I : BYTE ;
  197. BEGIN
  198.   WITH Points DO
  199.     IF N > 0 THEN
  200.       BEGIN
  201.         Plot ( Co [0].X, Co [0].Y ) ;
  202.         FOR I := 1 TO N DO
  203.           Draw ( Co [I].X, Co [I].Y ) ;
  204.       END ;
  205. END ;
  206.  
  207. (*$I STACK.ALL*)
  208.  
  209. PROCEDURE Fill ( X, Y : INTEGER ) ;
  210. VAR
  211.   EndOfStack, Return, Xleft, Xright,
  212.   SaveX, Xc, Yc                      : INTEGER ;
  213.   Pflag : BYTE ;
  214.  
  215. PROCEDURE Scan ;
  216. BEGIN
  217.   Return := PopStack ;
  218.   WHILE Xc <= Xright DO
  219.     BEGIN
  220.       Pflag := 0 ;
  221.       WHILE NOT Point ( Xc, Yc )
  222.             AND ( Xc <= Xright ) DO
  223.         BEGIN Pflag := 1 ; Xc := Succ ( Xc ) END ;
  224.       IF Pflag = 1 THEN
  225.         BEGIN
  226.           IF (Xc = Xright) AND NOT Point (Xc, Yc)
  227.             THEN BEGIN
  228.               PushStack ( Yc ) ;
  229.               PushStack ( Xc )
  230.             END
  231.             ELSE BEGIN
  232.                PushStack ( Yc ) ;
  233.                PushStack ( Pred ( Xc ))
  234.              END ;
  235.         END ;
  236.       Xc := Succ ( Xc ) ;
  237.       WHILE Point ( Xc, Yc )
  238.             AND ( Xc < Xright ) DO
  239.               Xc := Succ ( Xc ) ;
  240.     END ;
  241.   PushStack ( Return )
  242. END ;
  243.  
  244. BEGIN
  245.   EndOfStack := GrafStackPtr ;
  246.   PushStack ( Y ) ; PushStack ( X ) ;
  247.   WHILE GrafStackPtr <> EndOfStack DO
  248.     BEGIN
  249.       Xc := PopStack ; Yc := PopStack ;
  250.       Dot ( Xc, Yc ) ;
  251.       SaveX := Xc ;
  252.       Xc := Succ ( SaveX ) ;
  253.       WHILE NOT Point ( Xc, Yc ) DO
  254.         BEGIN
  255.           Dot ( Xc, Yc ) ;
  256.           Xc := Succ ( Xc )
  257.         END ;
  258.       Xright := Pred ( Xc ) ;
  259.       Xc := Pred ( SaveX ) ;
  260.       WHILE NOT Point ( Xc, Yc ) DO
  261.         BEGIN
  262.           Dot ( Xc, Yc ) ;
  263.           Xc := Pred ( Xc )
  264.         END ;
  265.       Xleft := Succ ( Xc ) ;
  266.       Xc := Xleft ; Yc := Yc - 1 ; Scan ;
  267.       Xc := Xleft ; Yc := Yc + 2 ; Scan ;
  268.     END ;
  269. END ;
  270.  
  271. PROCEDURE Area ( VAR Points : PolyPoint ) ;
  272. VAR
  273.   EndOfStack, Return,
  274.   Yscan, MinY, MaxY : INTEGER ;
  275.   I : BYTE ;
  276.  
  277. PROCEDURE RangeY ( VAR MaxY, MinY : INTEGER ) ;
  278. VAR
  279.   I : BYTE ;
  280. BEGIN
  281.   MaxY := Ymin ; MinY := Ymax ;
  282.   WITH Points DO
  283.     FOR I := 0 TO N DO
  284.       BEGIN
  285.         MaxY := Max ( MaxY, Co [I].Y ) ;
  286.         MinY := Min ( MinY, Co [I].Y ) ;
  287.       END ;
  288.   MaxY := Min ( MaxY, Ymax ) ;
  289.   MinY := Max ( MinY, Ymin ) ;
  290. END ;
  291.  
  292. PROCEDURE CloseContour  ;
  293. BEGIN
  294.   WITH Points DO
  295.     IF ( Co [0].X <> Co [N].X )
  296.         OR ( Co [0].Y <> Co [N].Y ) THEN
  297.       BEGIN
  298.         N := Succ ( N ) ;
  299.         Co [N].X := Co [0].X ;
  300.         Co [N].Y := Co [0].Y ;
  301.       END ;
  302. END ;
  303.  
  304. FUNCTION Xcross ( Xstart, Ystart,
  305.                   Xend, Yend, Yscan : INTEGER )
  306.                                         : INTEGER;
  307. BEGIN
  308.   Xcross := Round((Yscan - Ystart)/(Yend - Ystart)
  309.             * ( Xend - Xstart ) + Xstart ) ;
  310. END ;
  311.  
  312. PROCEDURE DrawScan ( Yscan : INTEGER ) ;
  313. BEGIN
  314.   Return := PopStack ;
  315.   WHILE GrafStackPtr < EndOfStack  DO
  316.     BEGIN
  317.       Plot ( PopStack, Yscan ) ;
  318.       Draw ( PopStack, Yscan ) ;
  319.     END ;
  320.   PushStack ( Return ) ;
  321. END ;
  322.  
  323. PROCEDURE SortStack ( Xins : INTEGER ) ;
  324. VAR
  325.   Xtst, N, I : INTEGER ;
  326. BEGIN
  327.   Return := PopStack ;
  328.   N := 0 ; Xtst := PickStack ;
  329.   WHILE ( GrafStackPtr < EndOfStack )
  330.         AND ( Xtst < Xins ) DO
  331.     BEGIN
  332.       PushHeap ( PopStack ) ;
  333.       N := Succ ( N ) ;
  334.       Xtst := PickStack ;
  335.     END ;
  336.   PushStack ( Xins ) ; I := 1 ;
  337.   WHILE I <= N DO BEGIN
  338.     PushStack ( PopHeap ) ;
  339.     I := Succ ( I ) ;
  340.   END ;
  341.   PushStack ( Return ) ;
  342. END ;
  343.  
  344. BEGIN
  345.   CloseContour ; Line ( Points ) ;
  346.   RangeY ( MaxY, MinY ) ;
  347.   FOR Yscan := MinY TO MaxY DO
  348.     WITH Points DO BEGIN
  349.       I := 0 ; EndOfStack := GrafStackPtr ;
  350.       WHILE I < N DO BEGIN
  351.         IF ( Co [I].Y <> Co [I+1].Y )
  352.            AND ( Yscan >= Min ( Co [I].Y,
  353.                                 Co [I+1].Y ))
  354.            AND ( Yscan < Max ( Co [I].Y,
  355.                  Co [I+1].Y )) THEN
  356.              SortStack(Xcross(Co[I].X,Co[I].Y,
  357.                               Co[I+1].X,
  358.                        Co [I+1].Y, Yscan )) ;
  359.             I := Succ ( I ) ;
  360.           END ;
  361.         DrawScan ( Yscan ) ;
  362.       END ;
  363. END ;
  364.  
  365. PROCEDURE CloseDevice ( Output : Devices ) ;
  366. BEGIN
  367.   Parameter.Command := CloseF ;
  368.   CallDevice ( Output ) ;
  369. END ;
  370.  
  371. (*$I FUNGR.PAS*)
  372.  
  373. BEGIN
  374.   IF OpenDevice ( Monitor ) THEN
  375.     BEGIN
  376.       Tool := Pen ;
  377.       ErrorMode := ClipMode ;
  378.       Clear ;
  379.       FnGraph ( -3.0, 3.0, -2.0, 2.0, 0.0, 1.0) ;
  380.       ReadLn ;
  381.       CloseDevice ( Monitor ) ;
  382.     END ;
  383. END.
  384.  
  385.