Lsystems.pas 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. Unit Lsystems;
  2. InterFace
  3. Uses Graph;
  4. const
  5. MaxStack = 100;
  6. MaxBuf = 10000;
  7. type
  8. PLsys = ^TLsys;
  9. PS = ^String;
  10. TLsys = record
  11. Axiom : string;
  12. Comment : string;
  13. Turns : integer;
  14. RulesTable : array [0..255] of PS;
  15. end;
  16. Tpos = record
  17. x, y, a : real;
  18. end;
  19. Function CreateLsys(aAxiom, aComment : string; aTurns : integer):PLsys;
  20. Procedure AddRule(var aFrac : PLsys; aCh : char; aRule:string);
  21. Procedure DestroyLsys(var aFrac : PLsys);
  22. Function Calculate(var aFrac:PLsys; aStage : integer):string;
  23. Function Advance(var aFrac:PLsys; PrevName : string):string;
  24. Procedure DrawLsys(fName : string; var aFrac : PLsys);
  25. Implementation
  26. Function CreateLsys;
  27. var RET:PLsys;i:byte;
  28. begin
  29. New(RET);
  30. RET^.Axiom := aAxiom;
  31. RET^.Comment := aComment;
  32. RET^.Turns := aTurns;
  33. for i:=0 to 255 do RET^.RulesTable[i]:=nil;
  34. CreateLsys := RET;
  35. end;{CreateLsys}
  36. {--------------------------------------------}
  37. Procedure AddRule;
  38. begin
  39. if aFrac = nil then begin writeln('AddRule Error: Fractal undefined'); halt(255);end;
  40. if aFrac^.RulesTable[Ord(aCh)] <> nil then Dispose(aFrac^.RulesTable[Ord(aCh)]);
  41. New(aFrac^.RulesTable[Ord(aCh)]);
  42. aFrac^.RulesTable[Ord(aCh)]^ := aRule;
  43. end;{AddRule}
  44. {--------------------------------------------}
  45. Function Calculate;
  46. var
  47. A : FILE;
  48. CH : char;
  49. N1 : string;
  50. I : integer;
  51. begin
  52. n1:='1.!!!';
  53. if odd(aStage) then Calculate := '2.!!!'
  54. else Calculate := '1.!!!';
  55. Assign(A,'1.!!!');
  56. Rewrite(A,1);
  57. BlockWrite(A,Ptr(Seg(aFrac^.Axiom),Ofs(aFrac^.Axiom)+1)^,Length(aFrac^.Axiom));
  58. Close(A);
  59. For i := 1 to aStage do
  60. begin
  61. N1:=Advance(aFrac,N1);
  62. end;
  63. end;{Calculate}
  64. {--------------------------------------------}
  65. Function Advance;
  66. type PFILE=^FILE;
  67. var
  68. A,B : PFILE;
  69. Out : string;
  70. CH : char;
  71. I : integer;
  72. begin
  73. New(A);NEW(B);
  74. if PrevName = '1.!!!' then out:='2.!!!'
  75. else out:='1.!!!';
  76. Advance := out;
  77. Assign(A^,PrevName);
  78. Assign(B^,Out);
  79. Reset(A^,1);
  80. Rewrite(B^,1);
  81. repeat
  82. BlockRead(A^,CH,1);
  83. if aFrac^.RulesTable[Ord(ch)] <> nil then BlockWrite(B^,Ptr(Seg(aFrac^.RulesTable[Ord(ch)]^),
  84. Ofs(aFrac^.RulesTable[Ord(ch)]^)+1)^,Length(aFrac^.RulesTable[Ord(ch)]^))
  85. else BlockWrite(B^,Ch,1);
  86. until EOF(A^);
  87. Close(A^);
  88. Close(B^);
  89. Erase(A^);
  90. Dispose(A);Dispose(B);
  91. end;{Advance}
  92. {--------------------------------------------}
  93. Procedure DestroyLsys;
  94. var i:byte;
  95. begin
  96. for i:=0 to 255 do if aFrac^.RulesTable[i] <> nil then
  97. Dispose(aFrac^.RulesTable[i]);
  98. Dispose(aFrac);
  99. end;{DestroyLsys}
  100. {-------------------------------------------}
  101. Procedure DrawLsys;
  102. type TBuf = array [1..MaxBuf] of char;
  103. Var
  104. Step : real;
  105. StackPos : integer;
  106. Stack : array [1..MaxStack] of Tpos;
  107. Buffer : ^TBuf;
  108. BufPos,NumRead:1..MaxBuf;
  109. C : Tpos;
  110. Ip : FILE;
  111. dx, dy,cx,cy : real;
  112. da : real;
  113. MaxX,MinX,MaxY,MinY : real;
  114. begin
  115. Step := 100.0;
  116. da := 2*PI/aFrac^.Turns;
  117. New(Buffer);
  118. Assign(ip,fName);
  119. Reset(ip,1);
  120. BlockRead(ip,Buffer^,MaxBuf,NumRead);
  121. BufPos:=1;
  122. StackPos:=1;
  123. dx:=step;dy:=0;C.x:=0;c.y:=0;c.a:=0;
  124. MaxX:=0;MaxY:=0;MinX:=0;MinY:=0;
  125. repeat
  126. case Buffer^[BufPos] of
  127. 'F': begin
  128. c.x := c.x + dx;
  129. c.y := c.y + dy;
  130. If C.X > MaxX then MaxX := c.x;
  131. If C.X < MinX then MinX := c.x;
  132. If C.Y > MaxY then MaxY := c.y;
  133. If C.Y < MinY then MinY := c.y;
  134. end;
  135. '+': begin
  136. c.a := c.a - da;
  137. if c.a > 2*PI then c.a:=c.a-2*Pi;
  138. if c.a < 0 then c.a:=c.a+2*Pi;
  139. dx := cos(c.a)*Step;
  140. dy := sin(c.a)*Step;
  141. end;
  142. '-': begin
  143. c.a := c.a + da;
  144. if c.a > 2*PI then c.a:=c.a-2*Pi;
  145. if c.a < 0 then c.a:=c.a+2*Pi;
  146. dx := cos(c.a)*Step;
  147. dy := sin(c.a)*Step;
  148. end;
  149. '[': begin
  150. If StackPos > MaxStack then
  151. begin
  152. CloseGraph;
  153. WriteLN('Stack overflow');
  154. Halt(210);
  155. end;
  156. Stack[StackPos] := C;
  157. Inc(StackPos);
  158. end;
  159. ']': begin
  160. If StackPos = 1 then
  161. begin
  162. CloseGraph;
  163. WriteLN('Stack error');
  164. Halt(200);
  165. end;
  166. Dec(StackPos);
  167. C:=Stack[StackPos];
  168. dx := cos(c.a)*Step;
  169. dy := sin(c.a)*Step;
  170. end;
  171. end;
  172. Inc(BufPos);
  173. if BufPos = NumRead+1 then
  174. begin
  175. BlockRead(ip,Buffer^,MaxBuf,NumRead);
  176. BufPos:=1;
  177. end;
  178. if NumRead = 0 then break;
  179. until false;
  180. if (MaxY=MinY) and (MaxX=MaxY) then
  181. begin
  182. Exit;
  183. end;
  184. if (MaxX-MinX)/(MaxY-MinY) > 4/3 then
  185. Step := 61300/(MaxX-MinX)
  186. else
  187. step := 46000/(MaxY-MinY);
  188. cx := (MaxX+MinX)*step/200;
  189. cy := (MaxY+MinY)*step/200;
  190. Seek(ip,0);
  191. BlockRead(ip,Buffer^,MaxBuf,NumRead);
  192. BufPos:=1;
  193. StackPos:=1;
  194. dx:=step;dy:=0;C.x:=0;c.y:=0;c.a:=0;
  195. OutTextXY(10,5,aFrac^.Comment);
  196. repeat
  197. case Buffer^[BufPos] of
  198. 'F': begin
  199. moveto(round(320-cx+c.x),round(240+cy-c.y));
  200. c.x := c.x + dx;c.y := c.y + dy;
  201. LineTo(round(320-cx+c.x),round(240+cy-c.y))
  202. end;
  203. '+': begin
  204. c.a := c.a - da;
  205. if c.a > 2*PI then c.a:=c.a-2*Pi;
  206. if c.a < 0 then c.a:=c.a+2*Pi;
  207. dx := cos(c.a)*Step;
  208. dy := sin(c.a)*Step;
  209. end;
  210. '-': begin
  211. c.a := c.a + da;
  212. if c.a > 2*PI then c.a:=c.a-2*Pi;
  213. if c.a < 0 then c.a:=c.a+2*Pi;
  214. dx := cos(c.a)*Step;
  215. dy := sin(c.a)*Step;
  216. end;
  217. '[': begin
  218. If StackPos > MaxStack then
  219. begin
  220. WriteLN('Stack overflow');
  221. Halt(210);
  222. end;
  223. Stack[StackPos] := C;
  224. Inc(StackPos);
  225. end;
  226. ']': begin
  227. If StackPos = 1 then
  228. begin
  229. WriteLN('Stack error');
  230. Halt(200);
  231. end;
  232. Dec(StackPos);
  233. C:=Stack[StackPos];
  234. dx := cos(c.a)*Step;
  235. dy := sin(c.a)*Step;
  236. end;
  237. end;
  238. Inc(BufPos);
  239. if BufPos = NumRead+1 then
  240. begin
  241. BlockRead(ip,Buffer^,MaxBuf,NumRead);
  242. BufPos:=1;
  243. end;
  244. if NumRead = 0 then break;
  245. until false;
  246. close(ip);
  247. Dispose(Buffer);
  248. end; {DrawLsys}
  249. {--------------------------------------------}
  250. END.