mandel.pp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  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. Graph;
  22. {$ifdef go32v2}
  23. {$ifndef ver0_99_8}
  24. {$define has_colors_equal}
  25. {$endif ver0_99_8}
  26. {$endif go32v2}
  27. const
  28. shift:byte=12;
  29. var
  30. SearchPoint,ActualPoint,NextPoint : PointType;
  31. LastColor : longint;
  32. Gd,Gm,
  33. Max_Color,Max_X_Width,
  34. Max_Y_Width,Y_Width : integer;
  35. Y1,Y2,X1,X2,Dy,Dx : Real;
  36. Zm : Integer;
  37. Flag : 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. {$ifndef has_colors_equal}
  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. {$endif not has_colors_equal}
  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 if getMaxColor>255 then
  74. CalcMandel:=(stdcolors[(z mod 254) + 1] and $FFFFFF)
  75. else
  76. CalcMandel:=(z mod Max_Color) + 1 ;
  77. end;
  78. {-----------------------------------------------------------------------------}
  79. procedure Partition(var A : arrayType; First, Last : Byte);
  80. var
  81. Right,Left : byte ;
  82. V,Temp : integer;
  83. begin
  84. V := A[(First + Last) SHR 1];
  85. Right := First;
  86. Left := Last;
  87. repeat
  88. while (A[Right] < V) do
  89. inc(Right);
  90. while (A[Left] > V) do
  91. Dec(Left);
  92. if (Right <= Left) then
  93. begin
  94. Temp:=A[Left];
  95. A[Left]:=A[Right];
  96. A[Right]:=Temp;
  97. Right:=Right+1;
  98. Left:=Left-1;
  99. end;
  100. until Right > Left;
  101. if (First < Left) then
  102. Partition(A, First, Left);
  103. if (Right < Last) then
  104. Partition(A, Right, Last)
  105. end;
  106. {-----------------------------------------------------------------------------}
  107. function BlackScan(var NextPoint:PointType) : boolean;
  108. begin
  109. BlackScan:=true;
  110. repeat
  111. if NextPoint.X=Max_X_Width then
  112. begin
  113. if NextPoint.Y < Y_Width then
  114. begin
  115. NextPoint.X:=0 ;
  116. NextPoint.Y:=NextPoint.Y+1;
  117. end
  118. else
  119. begin
  120. BlackScan:=false;
  121. exit;
  122. end ; { IF }
  123. end ; { IF }
  124. NextPoint.X:=NextPoint.X+1;
  125. until GetPixel(NextPoint.X,NextPoint.Y)=0;
  126. end ;
  127. {------------------------------------------------------------------------------}
  128. procedure Fill(Ymin,Ymax,LastColor:integer);
  129. var
  130. P1,P3,P4,P : integer ;
  131. Len,P2 : byte ;
  132. Darray : arraytype;
  133. begin
  134. SetColor(LastColor);
  135. for P1:=Ymin+1 to Ymax-1 do
  136. begin
  137. Len:=LineY[P1] ;
  138. if Len >= 2 then
  139. begin
  140. for P2:=1 to Len do
  141. Darray[P2]:=LineX[P2,P1] ;
  142. if Len > 2 then
  143. Partition(Darray,1,len);
  144. P2:=1;
  145. repeat
  146. P3:= Darray[P2] ; P4:= Darray[P2 + 1];
  147. if P3 <> P4 then
  148. begin
  149. line ( P3 , P1 , P4 , P1) ;
  150. if Flag then
  151. begin
  152. P:=Max_Y_Width-P1;
  153. line ( P3 , P , P4 , P ) ;
  154. end;
  155. end; { IF }
  156. P2:=P2+2;
  157. until P2 >= Len ;
  158. end; { IF }
  159. end; { FOR }
  160. end;
  161. {-----------------------------------------------------------------------------}
  162. Function NewPosition(Last:Byte):Byte;
  163. begin
  164. newposition:=(((last+1) and 254)+6) and 7;
  165. end;
  166. {-----------------------------------------------------------------------------}
  167. procedure CalcBounds;
  168. var
  169. lastOperation,KK,
  170. Position : Byte ;
  171. foundcolor : longint;
  172. Start,Found,NotFound : boolean ;
  173. MerkY,Ymax : Integer ;
  174. label
  175. L;
  176. begin
  177. repeat
  178. FillChar(LineY,SizeOf(LineY),0) ;
  179. ActualPoint:=NextPoint;
  180. LastColor:=CalcMandel(NextPoint,Zm) ;
  181. putpixel (ActualPoint.X,ActualPoint.Y,LastColor);
  182. if Flag then
  183. putpixel (ActualPoint.X,Max_Y_Width-ActualPoint.Y,LastColor) ;
  184. Ymax:=NextPoint.Y ;
  185. MerkY:=NextPoint.Y ;
  186. NotFound:=false ;
  187. Start:=false ;
  188. LastOperation:=4 ;
  189. repeat
  190. Found:=false ;
  191. KK:=0 ;
  192. Position:=NewPosition(LastOperation);
  193. repeat
  194. LastOperation:=(Position+KK) and 7 ;
  195. SearchPoint.X:=ActualPoint.X+Sx[LastOperation];
  196. SearchPoint.Y:=ActualPoint.Y+Sy[LastOperation];
  197. if ((SearchPoint.X < 0) or
  198. (SearchPoint.X > Max_X_Width) or
  199. (SearchPoint.Y < NextPoint.Y) or
  200. (SearchPoint.Y > Y_Width)) then
  201. goto L;
  202. if (SearchPoint.X=NextPoint.X) and (SearchPoint.Y=NextPoint.Y) then
  203. begin
  204. Start:=true ;
  205. Found:=true ;
  206. end
  207. else
  208. begin
  209. FoundColor:=GetPixel(SearchPoint.X,SearchPoint.Y) ;
  210. if FoundColor = 0 then
  211. begin
  212. FoundColor:= CalcMandel (SearchPoint,Zm) ;
  213. Putpixel (SearchPoint.X,SearchPoint.Y,FoundColor) ;
  214. if Flag then
  215. PutPixel (SearchPoint.X,Max_Y_Width-SearchPoint.Y,FoundColor) ;
  216. end ;
  217. if ColorsEqual(FoundColor,LastColor) then
  218. begin
  219. if ActualPoint.Y <> SearchPoint.Y then
  220. begin
  221. if SearchPoint.Y = MerkY then
  222. LineY[ActualPoint.Y]:=LineY[ActualPoint.Y]-1;
  223. MerkY:= ActualPoint.Y ;
  224. LineY[SearchPoint.Y]:=LineY[SearchPoint.Y]+1;
  225. end ;
  226. LineX[LineY[SearchPoint.Y],SearchPoint.Y]:=SearchPoint.X ;
  227. if SearchPoint.Y > Ymax then Ymax:= SearchPoint.Y ;
  228. Found:=true ;
  229. ActualPoint:=SearchPoint ;
  230. end;
  231. L:
  232. KK:=KK+1;
  233. if KK > 8 then
  234. begin
  235. Start:=true ;
  236. NotFound:=true ;
  237. end;
  238. end;
  239. until Found or (KK > 8);
  240. until Start ;
  241. if not NotFound then
  242. Fill(NextPoint.Y,Ymax,LastColor) ;
  243. until not BlackScan(NextPoint);
  244. end ;
  245. {------------------------------------------------------------------------------
  246. MAINROUTINE
  247. ------------------------------------------------------------------------------}
  248. {$ifndef Linux}
  249. var
  250. error : word;
  251. {$endif not Linux}
  252. begin
  253. {$ifdef go32v2}
  254. {$ifdef debug}
  255. {$warning If the compilation fails, you need to recompile}
  256. {$warning the graph unit with -dDEBUG option }
  257. Write('Use linear ? ');
  258. readln(st);
  259. if st='y' then UseLinear:=true;
  260. {$endif debug}
  261. {$endif go32v2}
  262. {$ifdef Linux}
  263. gm:=0;
  264. gd:=0;
  265. {$else}
  266. if paramcount>0 then
  267. begin
  268. val(paramstr(1),gm,error);
  269. if error<>0 then
  270. gm:=$103;
  271. end
  272. else
  273. gm:=$103;
  274. gd:=$ff;
  275. {$ifDEF TURBO}
  276. gd:=detect;
  277. {$endif}
  278. {$endif}
  279. InitGraph(gd,gm,'');
  280. if GraphResult <> grOk then Halt(1);
  281. Max_X_Width:=GetMaxX;
  282. Max_y_Width:=GetMaxY;
  283. Max_Color:=GetMaxColor-1;
  284. ClearViewPort;
  285. x1:=-0.9;
  286. x2:= 2.2;
  287. y1:= 1.25;
  288. y2:=-1.25;
  289. zm:=90;
  290. dx:=(x1 - x2) / Max_X_Width ;
  291. dy:=(y1 - y2) / Max_Y_Width ;
  292. if abs(y1) = abs(y2) then
  293. begin
  294. {$ifndef NOFLAG}
  295. flag:=true;
  296. {$endif NOFLAG}
  297. Y_Width:=Max_Y_Width shr 1
  298. end
  299. else
  300. begin
  301. flag:=false;
  302. Y_Width:=Max_Y_Width;
  303. end;
  304. NextPoint.X:=0;
  305. NextPoint.Y:=0;
  306. LastColor:=CalcMandel(SearchPoint,zm);
  307. CalcBounds ;
  308. {$ifndef fpc_profile}
  309. readln;
  310. {$endif fpc_profile}
  311. CloseGraph;
  312. end.
  313. {
  314. $Log$
  315. Revision 1.4 1998-12-20 22:22:10 peter
  316. * updates
  317. }