mandel.pp 9.4 KB

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