mandel.pp 9.3 KB

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