mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-29 18:24:20 +02:00
370 lines
9.9 KiB
ObjectPascal
370 lines
9.9 KiB
ObjectPascal
{
|
|
$Id$
|
|
This file is part of the Free Pascal run time library.
|
|
Copyright (c) 1993-98 by Gernot Tenchio
|
|
|
|
Mandelbrot Example using the Graph unit
|
|
|
|
See the file COPYING.FPC, included in this distribution,
|
|
for details about the copyright.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
**********************************************************************}
|
|
program mandel;
|
|
{$goto on}
|
|
{
|
|
Mandelbrot example using the graph unit.
|
|
|
|
Note: For linux you need to run this program as root !!
|
|
}
|
|
|
|
{$ifdef Win32}
|
|
{$apptype GUI}
|
|
{$endif}
|
|
|
|
uses
|
|
{$ifdef Win32}
|
|
Windows,
|
|
{$endif}
|
|
dos,Graph;
|
|
|
|
{
|
|
const
|
|
shift:byte=12;
|
|
}
|
|
|
|
var
|
|
SearchPoint,ActualPoint,NextPoint : PointType;
|
|
LastColor : longint;
|
|
Gd,Gm : smallint;
|
|
Max_Color,Max_X_Width,
|
|
Max_Y_Width,Y_Width : word;
|
|
Y1,Y2,X1,X2,Dy,Dx : Real;
|
|
Zm : Integer;
|
|
SymetricCase : boolean;
|
|
LineY : array [0..600] OF BYTE;
|
|
LineX : array [0..100,0..600] OF INTEGER;
|
|
const
|
|
SX : array [0..7] OF SHORTINT=(-1, 0, 1, 1, 1, 0,-1,-1);
|
|
SY : array [0..7] OF SHORTINT=(-1,-1,-1, 0, 1, 1, 1, 0);
|
|
type
|
|
arrayType = array[1..50] of integer;
|
|
|
|
{------------------------------------------------------------------------------}
|
|
function ColorsEqual(c1, c2 : longint) : boolean;
|
|
begin
|
|
ColorsEqual:=((GetMaxColor=$FF) and ((c1 and $FF)=(c2 and $FF))) or
|
|
((GetMaxColor=$7FFF) and ((c1 and $F8F8F8)=(c2 and $F8F8F8))) or
|
|
((GetMaxColor=$FFFF) and ((c1 and $F8FCF8)=(c2 and $F8FCF8))) or
|
|
((GetMaxColor>$10000) and ((c1 and $FFFFFF)=(c2 and $FFFFFF)));
|
|
end;
|
|
|
|
{------------------------------------------------------------------------------}
|
|
function CalcMandel(Point:PointType; z:integer) : Longint ;
|
|
var
|
|
x,y,xq,yq,Cx,Cy : real ;
|
|
begin
|
|
Cy:=y2 + dy*Point.y ;
|
|
Cx:=x2 + dx*Point.x ;
|
|
X:=-Cx ; Y:=-Cy ;
|
|
repeat
|
|
xq:=x * x;
|
|
yq:=y * y ;
|
|
y :=x * y;
|
|
y :=y + y - cy;
|
|
x :=xq - yq - cx ;
|
|
z :=z -1;
|
|
until (Z=0) or (Xq + Yq > 4 );
|
|
if Z=0 Then
|
|
CalcMandel:=(blue and $FFFFFF)
|
|
else
|
|
CalcMandel:={DefaultColors[}(z mod Max_Color) + 1 {]};
|
|
end;
|
|
|
|
{-----------------------------------------------------------------------------}
|
|
procedure Partition(var A : arrayType; First, Last : Byte);
|
|
var
|
|
Right,Left : byte ;
|
|
V,Temp : integer;
|
|
begin
|
|
V := A[(First + Last) SHR 1];
|
|
Right := First;
|
|
Left := Last;
|
|
repeat
|
|
while (A[Right] < V) do
|
|
inc(Right);
|
|
while (A[Left] > V) do
|
|
Dec(Left);
|
|
if (Right <= Left) then
|
|
begin
|
|
Temp:=A[Left];
|
|
A[Left]:=A[Right];
|
|
A[Right]:=Temp;
|
|
Right:=Right+1;
|
|
Left:=Left-1;
|
|
end;
|
|
until Right > Left;
|
|
if (First < Left) then
|
|
Partition(A, First, Left);
|
|
if (Right < Last) then
|
|
Partition(A, Right, Last)
|
|
end;
|
|
|
|
{-----------------------------------------------------------------------------}
|
|
function BlackScan(var NextPoint:PointType) : boolean;
|
|
begin
|
|
BlackScan:=true;
|
|
repeat
|
|
if NextPoint.X=Max_X_Width then
|
|
begin
|
|
if NextPoint.Y < Y_Width then
|
|
begin
|
|
NextPoint.X:=0 ;
|
|
NextPoint.Y:=NextPoint.Y+1;
|
|
end
|
|
else
|
|
begin
|
|
BlackScan:=false;
|
|
exit;
|
|
end ; { IF }
|
|
end ; { IF }
|
|
NextPoint.X:=NextPoint.X+1;
|
|
until GetPixel(NextPoint.X,NextPoint.Y)=0;
|
|
end ;
|
|
|
|
{------------------------------------------------------------------------------}
|
|
procedure Fill(Ymin,Ymax,LastColor:integer);
|
|
var
|
|
P1,P3,P4,P : integer ;
|
|
Len,P2 : byte ;
|
|
Darray : arraytype;
|
|
begin
|
|
SetColor(LastColor);
|
|
for P1:=Ymin+1 to Ymax-1 do
|
|
begin
|
|
Len:=LineY[P1] ;
|
|
if Len >= 2 then
|
|
begin
|
|
for P2:=1 to Len do
|
|
Darray[P2]:=LineX[P2,P1] ;
|
|
if Len > 2 then
|
|
Partition(Darray,1,len);
|
|
P2:=1;
|
|
repeat
|
|
P3:= Darray[P2] ; P4:= Darray[P2 + 1];
|
|
if P3 <> P4 then
|
|
begin
|
|
line ( P3 , P1 , P4 , P1) ;
|
|
if SymetricCase then
|
|
begin
|
|
P:=Max_Y_Width-P1;
|
|
line ( P3 , P , P4 , P ) ;
|
|
end;
|
|
end; { IF }
|
|
P2:=P2+2;
|
|
until P2 >= Len ;
|
|
end; { IF }
|
|
end; { FOR }
|
|
end;
|
|
|
|
{-----------------------------------------------------------------------------}
|
|
Function NewPosition(Last:Byte):Byte;
|
|
begin
|
|
newposition:=(((last+1) and 254)+6) and 7;
|
|
end;
|
|
|
|
{-----------------------------------------------------------------------------}
|
|
procedure CalcBounds;
|
|
var
|
|
lastOperation,KK,
|
|
Position : Byte ;
|
|
foundcolor : longint;
|
|
Start,Found,NotFound : boolean ;
|
|
MerkY,Ymax : Integer ;
|
|
label
|
|
L;
|
|
begin
|
|
repeat
|
|
FillChar(LineY,SizeOf(LineY),0) ;
|
|
ActualPoint:=NextPoint;
|
|
LastColor:=CalcMandel(NextPoint,Zm) ;
|
|
putpixel (ActualPoint.X,ActualPoint.Y,LastColor);
|
|
if SymetricCase then
|
|
putpixel (ActualPoint.X,Max_Y_Width-ActualPoint.Y,LastColor) ;
|
|
Ymax:=NextPoint.Y ;
|
|
MerkY:=NextPoint.Y ;
|
|
NotFound:=false ;
|
|
Start:=false ;
|
|
LastOperation:=4 ;
|
|
repeat
|
|
Found:=false ;
|
|
KK:=0 ;
|
|
Position:=NewPosition(LastOperation);
|
|
repeat
|
|
LastOperation:=(Position+KK) and 7 ;
|
|
SearchPoint.X:=ActualPoint.X+Sx[LastOperation];
|
|
SearchPoint.Y:=ActualPoint.Y+Sy[LastOperation];
|
|
if ((SearchPoint.X < 0) or
|
|
(SearchPoint.X > Max_X_Width) or
|
|
(SearchPoint.Y < NextPoint.Y) or
|
|
(SearchPoint.Y > Y_Width)) then
|
|
goto L;
|
|
if (SearchPoint.X=NextPoint.X) and (SearchPoint.Y=NextPoint.Y) then
|
|
begin
|
|
Start:=true ;
|
|
Found:=true ;
|
|
end
|
|
else
|
|
begin
|
|
FoundColor:=GetPixel(SearchPoint.X,SearchPoint.Y) ;
|
|
if FoundColor = 0 then
|
|
begin
|
|
FoundColor:= CalcMandel (SearchPoint,Zm) ;
|
|
Putpixel (SearchPoint.X,SearchPoint.Y,FoundColor) ;
|
|
if SymetricCase then
|
|
PutPixel (SearchPoint.X,Max_Y_Width-SearchPoint.Y,FoundColor) ;
|
|
end ;
|
|
if ColorsEqual(FoundColor,LastColor) then
|
|
begin
|
|
if ActualPoint.Y <> SearchPoint.Y then
|
|
begin
|
|
if SearchPoint.Y = MerkY then
|
|
LineY[ActualPoint.Y]:=LineY[ActualPoint.Y]-1;
|
|
MerkY:= ActualPoint.Y ;
|
|
LineY[SearchPoint.Y]:=LineY[SearchPoint.Y]+1;
|
|
end ;
|
|
LineX[LineY[SearchPoint.Y],SearchPoint.Y]:=SearchPoint.X ;
|
|
if SearchPoint.Y > Ymax then Ymax:= SearchPoint.Y ;
|
|
Found:=true ;
|
|
ActualPoint:=SearchPoint ;
|
|
end;
|
|
L:
|
|
KK:=KK+1;
|
|
if KK > 8 then
|
|
begin
|
|
Start:=true ;
|
|
NotFound:=true ;
|
|
end;
|
|
end;
|
|
until Found or (KK > 8);
|
|
until Start ;
|
|
if not NotFound then
|
|
Fill(NextPoint.Y,Ymax,LastColor) ;
|
|
until not BlackScan(NextPoint);
|
|
end ;
|
|
|
|
|
|
{------------------------------------------------------------------------------
|
|
MAINROUTINE
|
|
------------------------------------------------------------------------------}
|
|
var
|
|
error,dummy : smallint;
|
|
|
|
var i,neededtime,starttime : longint;
|
|
hour, minute, second, sec100 : word;
|
|
|
|
const
|
|
count : longint = 1;
|
|
gmdefault = m640x480;
|
|
|
|
begin
|
|
gm:=-1;
|
|
if paramcount>0 then
|
|
begin
|
|
val(paramstr(1),gm,error);
|
|
if error<>0 then
|
|
gm:=gmdefault;
|
|
{$ifdef go32v2}
|
|
if paramcount>1 then
|
|
begin
|
|
Val(paramstr(2),count,error);
|
|
if error<>0 then
|
|
count:=1;
|
|
end;
|
|
if paramcount>2 then
|
|
UseLFB:=true;
|
|
if paramcount>3 then
|
|
UseNoSelector:=true;
|
|
{$endif go32v2}
|
|
end;
|
|
gd:=d8bit;
|
|
if gm=-1 then
|
|
GetModeRange(gd,dummy,gm);
|
|
GetTime(hour, minute, second, sec100);
|
|
starttime:=((hour*60+minute)*60+second)*100+sec100;
|
|
{$ifdef Win32}
|
|
ShowWindow(GetActiveWindow,0);
|
|
{$endif}
|
|
InitGraph(gd,gm,'');
|
|
if GraphResult <> grOk then
|
|
begin
|
|
Writeln('Graph driver ',gd,' graph mode ',gm,' not supported');
|
|
Halt(1);
|
|
end;
|
|
for i:=1 to count do
|
|
begin
|
|
Max_X_Width:=GetMaxX;
|
|
Max_y_Width:=GetMaxY;
|
|
Max_Color:=GetMaxColor-1;
|
|
if Max_Color>255 then
|
|
Max_Color:=255;
|
|
ClearViewPort;
|
|
|
|
x1:=-0.9;
|
|
x2:= 2.2;
|
|
y1:= 1.25;
|
|
y2:=-1.25;
|
|
zm:=90;
|
|
dx:=(x1 - x2) / Max_X_Width ;
|
|
dy:=(y1 - y2) / Max_Y_Width ;
|
|
if abs(y1) = abs(y2) then
|
|
begin
|
|
SymetricCase:=true;
|
|
Y_Width:=Max_Y_Width shr 1
|
|
end
|
|
else
|
|
begin
|
|
SymetricCase:=false;
|
|
Y_Width:=Max_Y_Width;
|
|
end;
|
|
NextPoint.X:=0;
|
|
NextPoint.Y:=0;
|
|
LastColor:=CalcMandel(SearchPoint,zm);
|
|
CalcBounds ;
|
|
end;
|
|
GetTime(hour, minute, second, sec100);
|
|
neededtime:=((hour*60+minute)*60+second)*100+sec100-starttime;
|
|
{$ifndef fpc_profile}
|
|
readln;
|
|
{$endif fpc_profile}
|
|
CloseGraph;
|
|
{$ifndef Win32}
|
|
Writeln('Mandel took ',Real(neededtime)/100/count:0:3,' secs to generate mandel graph');
|
|
Writeln('With graph driver ',gd,' and graph mode ',gm);
|
|
{$endif}
|
|
end.
|
|
{
|
|
$Log$
|
|
Revision 1.4 2002-02-25 21:32:13 carl
|
|
+ $goto on added for makefiles
|
|
|
|
Revision 1.3 2002/02/22 21:40:45 carl
|
|
* range check error fix
|
|
|
|
Revision 1.2 2001/11/11 21:09:49 marco
|
|
* Gameunit, Fpctris and samegame fixed for win32 GUI
|
|
|
|
Revision 1.1 2001/05/03 21:39:33 peter
|
|
* moved to own module
|
|
|
|
Revision 1.3 2001/04/25 22:45:41 peter
|
|
* regenerated
|
|
|
|
Revision 1.2 2000/07/13 11:33:08 michael
|
|
+ removed logs
|
|
|
|
}
|