nmandel.pp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  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. {$ifdef profile}
  20. { profile needs only to be inserted in _USES
  21. for version < 0.99.9 PM }
  22. profile,
  23. {$endif profile}
  24. heaptrc,
  25. dpmiexcp,
  26. {$endif go32v2}
  27. Graph;
  28. {$ifdef FPC}
  29. {$ifdef go32v2}
  30. {$ifndef ver0_99_8}
  31. {$define has_colors_equal}
  32. {$endif ver0_99_8}
  33. {$endif go32v2}
  34. {$endif FPC}
  35. const
  36. shift:byte=12;
  37. var
  38. SearchPoint,ActualPoint,NextPoint : PointType;
  39. LastColor : longint;
  40. Gd,Gm,
  41. Max_Color,Max_X_Width,
  42. Max_Y_Width,Y_Width : integer;
  43. Y1,Y2,X1,X2,Dy,Dx : Real;
  44. Zm : Integer;
  45. Flag : boolean;
  46. LineY : array [0..600] OF BYTE;
  47. LineX : array [0..100,0..600] OF INTEGER;
  48. const
  49. SX : array [0..7] OF SHORTINT=(-1, 0, 1, 1, 1, 0,-1,-1);
  50. SY : array [0..7] OF SHORTINT=(-1,-1,-1, 0, 1, 1, 1, 0);
  51. type
  52. arrayType = array[1..50] of integer;
  53. {------------------------------------------------------------------------------}
  54. {$ifndef has_colors_equal}
  55. function ColorsEqual(c1, c2 : longint) : boolean;
  56. begin
  57. ColorsEqual:=((GetMaxColor=$FF) and ((c1 and $FF)=(c2 and $FF))) or
  58. ((GetMaxColor=$7FFF) and ((c1 and $F8F8F8)=(c2 and $F8F8F8))) or
  59. ((GetMaxColor=$FFFF) and ((c1 and $F8FCF8)=(c2 and $F8FCF8))) or
  60. ((GetMaxColor>$10000) and ((c1 and $FFFFFF)=(c2 and $FFFFFF)));
  61. end;
  62. {$endif not has_colors_equal}
  63. {------------------------------------------------------------------------------}
  64. function CalcMandel(Point:PointType; z:integer) : Longint ;
  65. var
  66. x,y,xq,yq,Cx,Cy : real ;
  67. begin
  68. Cy:=y2 + dy*Point.y ;
  69. Cx:=x2 + dx*Point.x ;
  70. X:=-Cx ; Y:=-Cy ;
  71. repeat
  72. xq:=x * x;
  73. yq:=y * y ;
  74. y :=x * y;
  75. y :=y + y - cy;
  76. x :=xq - yq - cx ;
  77. z :=z -1;
  78. until (Z=0) or (Xq + Yq > 4 );
  79. if Z=0 Then
  80. CalcMandel:=(blue and $FFFFFF)
  81. else if getMaxColor>255 then
  82. CalcMandel:=(stdcolors[(z mod 254) + 1] and $FFFFFF)
  83. else
  84. CalcMandel:=(z mod Max_Color) + 1 ;
  85. end;
  86. {-----------------------------------------------------------------------------}
  87. procedure Partition(var A : arrayType; First, Last : Byte);
  88. var
  89. Right,Left : byte ;
  90. V,Temp : integer;
  91. begin
  92. V := A[(First + Last) SHR 1];
  93. Right := First;
  94. Left := Last;
  95. repeat
  96. while (A[Right] < V) do
  97. inc(Right);
  98. while (A[Left] > V) do
  99. Dec(Left);
  100. if (Right <= Left) then
  101. begin
  102. Temp:=A[Left];
  103. A[Left]:=A[Right];
  104. A[Right]:=Temp;
  105. Right:=Right+1;
  106. Left:=Left-1;
  107. end;
  108. until Right > Left;
  109. if (First < Left) then
  110. Partition(A, First, Left);
  111. if (Right < Last) then
  112. Partition(A, Right, Last)
  113. end;
  114. {-----------------------------------------------------------------------------}
  115. function BlackScan(var NextPoint:PointType) : boolean;
  116. begin
  117. BlackScan:=true;
  118. repeat
  119. if NextPoint.X=Max_X_Width then
  120. begin
  121. if NextPoint.Y < Y_Width then
  122. begin
  123. NextPoint.X:=0 ;
  124. NextPoint.Y:=NextPoint.Y+1;
  125. end
  126. else
  127. begin
  128. BlackScan:=false;
  129. exit;
  130. end ; { IF }
  131. end ; { IF }
  132. NextPoint.X:=NextPoint.X+1;
  133. until GetPixel(NextPoint.X,NextPoint.Y)=0;
  134. end ;
  135. {------------------------------------------------------------------------------}
  136. procedure Fill(Ymin,Ymax,LastColor:integer);
  137. var
  138. P1,P3,P4,P : integer ;
  139. Len,P2 : byte ;
  140. Darray : arraytype;
  141. begin
  142. SetColor(LastColor);
  143. for P1:=Ymin+1 to Ymax-1 do
  144. begin
  145. Len:=LineY[P1] ;
  146. if Len >= 2 then
  147. begin
  148. for P2:=1 to Len do
  149. Darray[P2]:=LineX[P2,P1] ;
  150. if Len > 2 then
  151. Partition(Darray,1,len);
  152. P2:=1;
  153. repeat
  154. P3:= Darray[P2] ; P4:= Darray[P2 + 1];
  155. if P3 <> P4 then
  156. begin
  157. line ( P3 , P1 , P4 , P1) ;
  158. if Flag then
  159. begin
  160. P:=Max_Y_Width-P1;
  161. line ( P3 , P , P4 , P ) ;
  162. end;
  163. end; { IF }
  164. P2:=P2+2;
  165. until P2 >= Len ;
  166. end; { IF }
  167. end; { FOR }
  168. end;
  169. {-----------------------------------------------------------------------------}
  170. Function NewPosition(Last:Byte):Byte;
  171. begin
  172. newposition:=(((last+1) and 254)+6) and 7;
  173. end;
  174. {-----------------------------------------------------------------------------}
  175. procedure CalcBounds;
  176. var
  177. lastOperation,KK,
  178. Position : Byte ;
  179. foundcolor : longint;
  180. Start,Found,NotFound : boolean ;
  181. MerkY,Ymax : Integer ;
  182. label
  183. L;
  184. begin
  185. repeat
  186. FillChar(LineY,SizeOf(LineY),0) ;
  187. ActualPoint:=NextPoint;
  188. LastColor:=CalcMandel(NextPoint,Zm) ;
  189. putpixel (ActualPoint.X,ActualPoint.Y,LastColor);
  190. if Flag then
  191. putpixel (ActualPoint.X,Max_Y_Width-ActualPoint.Y,LastColor) ;
  192. Ymax:=NextPoint.Y ;
  193. MerkY:=NextPoint.Y ;
  194. NotFound:=false ;
  195. Start:=false ;
  196. LastOperation:=4 ;
  197. repeat
  198. Found:=false ;
  199. KK:=0 ;
  200. Position:=NewPosition(LastOperation);
  201. repeat
  202. LastOperation:=(Position+KK) and 7 ;
  203. SearchPoint.X:=ActualPoint.X+Sx[LastOperation];
  204. SearchPoint.Y:=ActualPoint.Y+Sy[LastOperation];
  205. if ((SearchPoint.X < 0) or
  206. (SearchPoint.X > Max_X_Width) or
  207. (SearchPoint.Y < NextPoint.Y) or
  208. (SearchPoint.Y > Y_Width)) then
  209. goto L;
  210. if (SearchPoint.X=NextPoint.X) and (SearchPoint.Y=NextPoint.Y) then
  211. begin
  212. Start:=true ;
  213. Found:=true ;
  214. end
  215. else
  216. begin
  217. FoundColor:=GetPixel(SearchPoint.X,SearchPoint.Y) ;
  218. if FoundColor = 0 then
  219. begin
  220. FoundColor:= CalcMandel (SearchPoint,Zm) ;
  221. Putpixel (SearchPoint.X,SearchPoint.Y,FoundColor) ;
  222. if Flag then
  223. PutPixel (SearchPoint.X,Max_Y_Width-SearchPoint.Y,FoundColor) ;
  224. end ;
  225. if ColorsEqual(FoundColor,LastColor) then
  226. begin
  227. if ActualPoint.Y <> SearchPoint.Y then
  228. begin
  229. if SearchPoint.Y = MerkY then
  230. LineY[ActualPoint.Y]:=LineY[ActualPoint.Y]-1;
  231. MerkY:= ActualPoint.Y ;
  232. LineY[SearchPoint.Y]:=LineY[SearchPoint.Y]+1;
  233. end ;
  234. LineX[LineY[SearchPoint.Y],SearchPoint.Y]:=SearchPoint.X ;
  235. if SearchPoint.Y > Ymax then Ymax:= SearchPoint.Y ;
  236. Found:=true ;
  237. ActualPoint:=SearchPoint ;
  238. end;
  239. L:
  240. KK:=KK+1;
  241. if KK > 8 then
  242. begin
  243. Start:=true ;
  244. NotFound:=true ;
  245. end;
  246. end;
  247. until Found or (KK > 8);
  248. until Start ;
  249. if not NotFound then
  250. Fill(NextPoint.Y,Ymax,LastColor) ;
  251. until not BlackScan(NextPoint);
  252. end ;
  253. {------------------------------------------------------------------------------
  254. MAINROUTINE
  255. ------------------------------------------------------------------------------}
  256. {$ifndef Linux}
  257. var
  258. error : word;
  259. st : string;
  260. {$endif not Linux}
  261. begin
  262. {$ifdef go32v2}
  263. {$ifdef debug}
  264. {$warning If the compilation fails, you need to recompile}
  265. {$warning the graph unit with -dDEBUG option }
  266. Write('Use linear ? ');
  267. readln(st);
  268. if st='y' then UseLinear:=true;
  269. {$endif debug}
  270. {$endif go32v2}
  271. {$ifdef Linux}
  272. gm:=0;
  273. gd:=0;
  274. {$else}
  275. if paramcount>0 then
  276. begin
  277. val(paramstr(1),gm,error);
  278. if error<>0 then
  279. gm:=$103;
  280. end
  281. else
  282. gm:=$103;
  283. gd:=$ff;
  284. {$ifDEF TURBO}
  285. gd:=detect;
  286. {$endif}
  287. {$endif}
  288. InitGraph(gd,gm,'D:\bp\bgi');
  289. if GraphResult <> grOk then Halt(1);
  290. Max_X_Width:=GetMaxX;
  291. Max_y_Width:=GetMaxY;
  292. Max_Color:=GetMaxColor-1;
  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. {$ifndef NOFLAG}
  304. flag:=true;
  305. {$endif NOFLAG}
  306. Y_Width:=Max_Y_Width shr 1
  307. end
  308. else
  309. begin
  310. flag:=false;
  311. Y_Width:=Max_Y_Width;
  312. end;
  313. NextPoint.X:=0;
  314. NextPoint.Y:=0;
  315. LastColor:=CalcMandel(SearchPoint,zm);
  316. CalcBounds ;
  317. {$ifndef fpc_profile}
  318. readln;
  319. {$endif fpc_profile}
  320. CloseGraph;
  321. end.
  322. {
  323. $Log$
  324. Revision 1.3 1998-11-20 10:16:00 pierre
  325. * Found out the LinerFrameBuffer problem
  326. Was an alignment problem in VesaInfoBlock (see graph.pp file)
  327. Compile with -dDEBUG and answer 'y' to 'Use Linear ?' to test
  328. Revision 1.2 1998/11/18 11:45:06 pierre
  329. * LinearFrameBuffer test added
  330. Revision 1.1 1998/11/17 18:17:53 pierre
  331. + mandel changed for new graph unit (probably not very linux compatible !)
  332. Revision 1.3 1998/09/11 10:55:25 peter
  333. + header+log
  334. }