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