mandel.pp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993-98 by Gernot Tenchio
  5. Mandelbrot Example using the Graph unit
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. program mandel;
  13. {
  14. Mandelbrot example using the graph unit.
  15. Note: For linux you need to run this program as root !!
  16. }
  17. {$ifdef Win32}
  18. {$apptype GUI}
  19. {$endif}
  20. uses
  21. {$ifdef Win32}
  22. Windows,
  23. {$endif}
  24. dos,Graph;
  25. {
  26. const
  27. shift:byte=12;
  28. }
  29. var
  30. SearchPoint,ActualPoint,NextPoint : PointType;
  31. LastColor : longint;
  32. Gd,Gm : smallint;
  33. Max_Color,Max_X_Width,
  34. Max_Y_Width,Y_Width : word;
  35. Y1,Y2,X1,X2,Dy,Dx : Real;
  36. Zm : Integer;
  37. SymetricCase : boolean;
  38. LineY : array [0..600] OF BYTE;
  39. LineX : array [0..100,0..600] OF INTEGER;
  40. const
  41. SX : array [0..7] OF SHORTINT=(-1, 0, 1, 1, 1, 0,-1,-1);
  42. SY : array [0..7] OF SHORTINT=(-1,-1,-1, 0, 1, 1, 1, 0);
  43. type
  44. arrayType = array[1..50] of integer;
  45. {------------------------------------------------------------------------------}
  46. function ColorsEqual(c1, c2 : longint) : boolean;
  47. begin
  48. ColorsEqual:=((GetMaxColor=$FF) and ((c1 and $FF)=(c2 and $FF))) or
  49. ((GetMaxColor=$7FFF) and ((c1 and $F8F8F8)=(c2 and $F8F8F8))) or
  50. ((GetMaxColor=$FFFF) and ((c1 and $F8FCF8)=(c2 and $F8FCF8))) or
  51. ((GetMaxColor>$10000) and ((c1 and $FFFFFF)=(c2 and $FFFFFF)));
  52. end;
  53. {------------------------------------------------------------------------------}
  54. function CalcMandel(Point:PointType; z:integer) : Longint ;
  55. var
  56. x,y,xq,yq,Cx,Cy : real ;
  57. begin
  58. Cy:=y2 + dy*Point.y ;
  59. Cx:=x2 + dx*Point.x ;
  60. X:=-Cx ; Y:=-Cy ;
  61. repeat
  62. xq:=x * x;
  63. yq:=y * y ;
  64. y :=x * y;
  65. y :=y + y - cy;
  66. x :=xq - yq - cx ;
  67. z :=z -1;
  68. until (Z=0) or (Xq + Yq > 4 );
  69. if Z=0 Then
  70. CalcMandel:=(blue and $FFFFFF)
  71. else
  72. CalcMandel:={DefaultColors[}(z mod Max_Color) + 1 {]};
  73. end;
  74. {-----------------------------------------------------------------------------}
  75. procedure Partition(var A : arrayType; First, Last : Byte);
  76. var
  77. Right,Left : byte ;
  78. V,Temp : integer;
  79. begin
  80. V := A[(First + Last) SHR 1];
  81. Right := First;
  82. Left := Last;
  83. repeat
  84. while (A[Right] < V) do
  85. inc(Right);
  86. while (A[Left] > V) do
  87. Dec(Left);
  88. if (Right <= Left) then
  89. begin
  90. Temp:=A[Left];
  91. A[Left]:=A[Right];
  92. A[Right]:=Temp;
  93. Right:=Right+1;
  94. Left:=Left-1;
  95. end;
  96. until Right > Left;
  97. if (First < Left) then
  98. Partition(A, First, Left);
  99. if (Right < Last) then
  100. Partition(A, Right, Last)
  101. end;
  102. {-----------------------------------------------------------------------------}
  103. function BlackScan(var NextPoint:PointType) : boolean;
  104. begin
  105. BlackScan:=true;
  106. repeat
  107. if NextPoint.X=Max_X_Width then
  108. begin
  109. if NextPoint.Y < Y_Width then
  110. begin
  111. NextPoint.X:=0 ;
  112. NextPoint.Y:=NextPoint.Y+1;
  113. end
  114. else
  115. begin
  116. BlackScan:=false;
  117. exit;
  118. end ; { IF }
  119. end ; { IF }
  120. NextPoint.X:=NextPoint.X+1;
  121. until GetPixel(NextPoint.X,NextPoint.Y)=0;
  122. end ;
  123. {------------------------------------------------------------------------------}
  124. procedure Fill(Ymin,Ymax,LastColor:integer);
  125. var
  126. P1,P3,P4,P : integer ;
  127. Len,P2 : byte ;
  128. Darray : arraytype;
  129. begin
  130. SetColor(LastColor);
  131. for P1:=Ymin+1 to Ymax-1 do
  132. begin
  133. Len:=LineY[P1] ;
  134. if Len >= 2 then
  135. begin
  136. for P2:=1 to Len do
  137. Darray[P2]:=LineX[P2,P1] ;
  138. if Len > 2 then
  139. Partition(Darray,1,len);
  140. P2:=1;
  141. repeat
  142. P3:= Darray[P2] ; P4:= Darray[P2 + 1];
  143. if P3 <> P4 then
  144. begin
  145. line ( P3 , P1 , P4 , P1) ;
  146. if SymetricCase then
  147. begin
  148. P:=Max_Y_Width-P1;
  149. line ( P3 , P , P4 , P ) ;
  150. end;
  151. end; { IF }
  152. P2:=P2+2;
  153. until P2 >= Len ;
  154. end; { IF }
  155. end; { FOR }
  156. end;
  157. {-----------------------------------------------------------------------------}
  158. Function NewPosition(Last:Byte):Byte;
  159. begin
  160. newposition:=(((last+1) and 254)+6) and 7;
  161. end;
  162. {-----------------------------------------------------------------------------}
  163. procedure CalcBounds;
  164. var
  165. lastOperation,KK,
  166. Position : Byte ;
  167. foundcolor : longint;
  168. Start,Found,NotFound : boolean ;
  169. MerkY,Ymax : Integer ;
  170. label
  171. L;
  172. begin
  173. repeat
  174. FillChar(LineY,SizeOf(LineY),0) ;
  175. ActualPoint:=NextPoint;
  176. LastColor:=CalcMandel(NextPoint,Zm) ;
  177. putpixel (ActualPoint.X,ActualPoint.Y,LastColor);
  178. if SymetricCase then
  179. putpixel (ActualPoint.X,Max_Y_Width-ActualPoint.Y,LastColor) ;
  180. Ymax:=NextPoint.Y ;
  181. MerkY:=NextPoint.Y ;
  182. NotFound:=false ;
  183. Start:=false ;
  184. LastOperation:=4 ;
  185. repeat
  186. Found:=false ;
  187. KK:=0 ;
  188. Position:=NewPosition(LastOperation);
  189. repeat
  190. LastOperation:=(Position+KK) and 7 ;
  191. SearchPoint.X:=ActualPoint.X+Sx[LastOperation];
  192. SearchPoint.Y:=ActualPoint.Y+Sy[LastOperation];
  193. if ((SearchPoint.X < 0) or
  194. (SearchPoint.X > Max_X_Width) or
  195. (SearchPoint.Y < NextPoint.Y) or
  196. (SearchPoint.Y > Y_Width)) then
  197. goto L;
  198. if (SearchPoint.X=NextPoint.X) and (SearchPoint.Y=NextPoint.Y) then
  199. begin
  200. Start:=true ;
  201. Found:=true ;
  202. end
  203. else
  204. begin
  205. FoundColor:=GetPixel(SearchPoint.X,SearchPoint.Y) ;
  206. if FoundColor = 0 then
  207. begin
  208. FoundColor:= CalcMandel (SearchPoint,Zm) ;
  209. Putpixel (SearchPoint.X,SearchPoint.Y,FoundColor) ;
  210. if SymetricCase then
  211. PutPixel (SearchPoint.X,Max_Y_Width-SearchPoint.Y,FoundColor) ;
  212. end ;
  213. if ColorsEqual(FoundColor,LastColor) then
  214. begin
  215. if ActualPoint.Y <> SearchPoint.Y then
  216. begin
  217. if SearchPoint.Y = MerkY then
  218. LineY[ActualPoint.Y]:=LineY[ActualPoint.Y]-1;
  219. MerkY:= ActualPoint.Y ;
  220. LineY[SearchPoint.Y]:=LineY[SearchPoint.Y]+1;
  221. end ;
  222. LineX[LineY[SearchPoint.Y],SearchPoint.Y]:=SearchPoint.X ;
  223. if SearchPoint.Y > Ymax then Ymax:= SearchPoint.Y ;
  224. Found:=true ;
  225. ActualPoint:=SearchPoint ;
  226. end;
  227. L:
  228. KK:=KK+1;
  229. if KK > 8 then
  230. begin
  231. Start:=true ;
  232. NotFound:=true ;
  233. end;
  234. end;
  235. until Found or (KK > 8);
  236. until Start ;
  237. if not NotFound then
  238. Fill(NextPoint.Y,Ymax,LastColor) ;
  239. until not BlackScan(NextPoint);
  240. end ;
  241. {------------------------------------------------------------------------------
  242. MAINROUTINE
  243. ------------------------------------------------------------------------------}
  244. var
  245. error,dummy : smallint;
  246. var i,neededtime,starttime : longint;
  247. hour, minute, second, sec100 : word;
  248. const
  249. count : longint = 1;
  250. gmdefault = m640x480;
  251. begin
  252. gm:=$ffff;
  253. if paramcount>0 then
  254. begin
  255. val(paramstr(1),gm,error);
  256. if error<>0 then
  257. gm:=gmdefault;
  258. {$ifdef go32v2}
  259. if paramcount>1 then
  260. begin
  261. Val(paramstr(2),count,error);
  262. if error<>0 then
  263. count:=1;
  264. end;
  265. if paramcount>2 then
  266. UseLFB:=true;
  267. if paramcount>3 then
  268. UseNoSelector:=true;
  269. {$endif go32v2}
  270. end;
  271. gd:=d8bit;
  272. if gm=-1 then
  273. GetModeRange(gd,dummy,gm);
  274. GetTime(hour, minute, second, sec100);
  275. starttime:=((hour*60+minute)*60+second)*100+sec100;
  276. {$ifdef Win32}
  277. ShowWindow(GetActiveWindow,0);
  278. {$endif}
  279. InitGraph(gd,gm,'');
  280. if GraphResult <> grOk then
  281. begin
  282. Writeln('Graph driver ',gd,' graph mode ',gm,' not supported');
  283. Halt(1);
  284. end;
  285. for i:=1 to count do
  286. begin
  287. Max_X_Width:=GetMaxX;
  288. Max_y_Width:=GetMaxY;
  289. Max_Color:=GetMaxColor-1;
  290. if Max_Color>255 then
  291. Max_Color:=255;
  292. ClearViewPort;
  293. x1:=-0.9;
  294. x2:= 2.2;
  295. y1:= 1.25;
  296. y2:=-1.25;
  297. zm:=90;
  298. dx:=(x1 - x2) / Max_X_Width ;
  299. dy:=(y1 - y2) / Max_Y_Width ;
  300. if abs(y1) = abs(y2) then
  301. begin
  302. SymetricCase:=true;
  303. Y_Width:=Max_Y_Width shr 1
  304. end
  305. else
  306. begin
  307. SymetricCase:=false;
  308. Y_Width:=Max_Y_Width;
  309. end;
  310. NextPoint.X:=0;
  311. NextPoint.Y:=0;
  312. LastColor:=CalcMandel(SearchPoint,zm);
  313. CalcBounds ;
  314. end;
  315. GetTime(hour, minute, second, sec100);
  316. neededtime:=((hour*60+minute)*60+second)*100+sec100-starttime;
  317. {$ifndef fpc_profile}
  318. readln;
  319. {$endif fpc_profile}
  320. CloseGraph;
  321. {$ifndef Win32}
  322. Writeln('Mandel took ',Real(neededtime)/100/count:0:3,' secs to generate mandel graph');
  323. Writeln('With graph driver ',gd,' and graph mode ',gm);
  324. {$endif}
  325. end.
  326. {
  327. $Log$
  328. Revision 1.2 2001-11-11 21:09:49 marco
  329. * Gameunit, Fpctris and samegame fixed for win32 GUI
  330. Revision 1.1 2001/05/03 21:39:33 peter
  331. * moved to own module
  332. Revision 1.3 2001/04/25 22:45:41 peter
  333. * regenerated
  334. Revision 1.2 2000/07/13 11:33:08 michael
  335. + removed logs
  336. }