mandel.pp 9.9 KB

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