prograMing: L-system
- To: mathgroup at smc.vnet.net
- Subject: [mg9733] prograMing: L-system
- From: Xah Lee <xah at best.com>
- Date: Tue, 25 Nov 1997 00:06:34 -0500
- Sender: owner-wri-mathgroup at wolfram.com
Half of my earlier message [Re: Fractal Plane Filling Curves] got truncated.= I don't have the original I send out, so here's a rewrite. I've seen 4 programs on L-system written in Mathematica: One from Stan Wagon's book _Mma in Action_. One from Harvey Wynn (Written 10/96, Converted to 3.0 on 5/7/97) One from J.-P. Kuska,jpk at mpe.fta-berlin.de (Date: /03/06/96, posted here.) and one from Robert Dickau <http://forum.swarthmore.edu/advanced/robertd/index.html> But still I think we lack a general comprehensive package on L-system. (Roman Meader probably has done L-system in Mathematica too, and I know that some= issues of the Mathematica Journal contains them too.) Codes attached below also generats L-system-like graphics. It is not based= on string replacement with turtle graphics interpretation, but based on a= rule or rules that specify the position relationship of line segment(s)= with respect to its parent line. I'm wondering how this approach compares to the L-system for generating many= recursive graphics. Surely the interface is less user-friendly because the= coordinates are harder to work with than string directions. It's probably= slower too because the graphics are calculated directly in every= generation, instead of translating strings to graphics at the final stage= as in L-system. I think there are advantages too. For one thing, certain= graphics are more easily specified with the direct graphics approach. Recently I have been thinking of writing a program that can generate ALL= recursive graphics. I run into problems: 1. What is the definition of recursive graphics? 2. What kind of interface will work out? =46or instance, it doesn't looks trivial to me to specify some of Escher's= work (circle/square limits ...) in terms of L-systems, assuming it can be= done. I also have other questions: 3. When is an L-system a space-filling curve? Is there a simple rule? Thanks in advance for any help or suggestions. The following is an example of recursive graphics using position= relationship rule: (*-----------------cut here------------------------------*) (*LineTransform*) Clear[LineTransform]; LineTransform::"usage"= "LineTransform[graphics1,replacementList] is an L-system like graphical function. graphics1 is a list of Line or an Graphics object. replacementList is a List of Line or graphic directives and primitives. Each Line in graphics1 is replaced by the relation Line[{{0,0},{1,0}}]->replacementList. LineTransform[graphics1,replacementList,Line[{p1,p2}]] will use the relation Line[{p1,p2}]->replacementList. Example: LineTransform[Line[{{0,0},{1,0},{1,-1}}],{Line[{{0,0},{1/2,1/2},{1,0}}]}]"; LineTransform[initialImage_, replacement_]:=( N at initialImage/.line1:Line[{_,_,__}]:> Map[Line,Partition[First at line1,2,1]])/.Line[{p1_,p2_}]:> Block[{v,alpha,scale},v=(p2-p1);alpha=ArcTan@@v;scale=N at Sqrt[v.v= ]; N at replacement/.{ line2_Line:> Map[{{Cos[alpha],-Sin[alpha]},{Sin[alpha],Cos[alpha]}}.#*scale= + p1&,line2,{2}], Point[pt_]:> Point[({{Cos[alpha],-Sin[alpha]},{Sin[alpha],Cos[alpha]}}.pt* scale+p1)]}]; LineTransform[initialImage_,replacement_, Line[{p3_,p4_}]]:=( N at initialImage/.line1:Line[{_,_,__}]:> Map[Line,Partition[First at line1,2,1]])/.Line[{p1_,p2_}]:> Block[{v,v2,alpha,scale},v=N@(p2-p1);v2=N@(p4-p3); alpha=N@(ArcTan@@v-ArcTan@@v2);scale=N@(Sqrt[v.v]/Sqrt[v2.v2]); N at replacement/.{ line2_Line:> Map[{{Cos[alpha],-Sin[alpha]},{Sin[alpha],Cos[alpha]}}.(#-p3)* scale+p1&,line2,{2}], Point[pt_]:> Point[({{Cos[alpha],-Sin[alpha]},{Sin[alpha],Cos[alpha]}}.( pt-p3)*scale+p1)]}]; (* One Example*) Clear[initialImage,replaceRule,gp,gp1,gp2,gp3,x,y,n,s]; x=N at {1,0}; y=N at {Cos[60*Degree],Sin[60*Degree]}; n=4; replaceRule=N at {Line[{0x,x}],Line[{y,x}],Line[{y,x+y}],Line[{2x,x+y}]}; initialImage=Line[{0x,2x}]; gp=Nest[LineTransform[#,replaceRule,Line[{0x,2x}]]&,initialImage,n]; (*The following puts the list gp in the right order corresponding to a path.= *) gp=Fold[MapIndexed[If[EvenQ at Last@#2,Reverse at #1,#1]&,#1,{#2}]&, gp/.Line[li_]->li,Range at n]; (*This line trims the line, so a path can be clearly seen in the graphics.*) s=.7; gp2=If[s===1,gp,#]&@ Map[{(First at #-Last@#)*s+Last at #,(Last at #-First@#)*s+First at #}&, Flatten[gp,n-1]]; (*add color*) gp3=Transpose[{Table[Hue[.7,i,.8],{i,0,1,1./(Length at #-1)}],#}]&@( Line/@(Partition[#,2,1]&@(Partition[#,2]&@Flatten at gp2))); Show[Graphics[{gp3}],AspectRatio->Automatic,Background->GrayLevel[0]]; (*LineTransform code explained: With two arguments: LineTransform[initialImage_, replacement_]. First we= make sure that all line segments stand alone in the form of Line[{p1,p2}].= This is done by (N at initialImage/.line1:Line[{_,_,__}]:>Map[Line,Partition[F= irst at line1,2,1]]). The general plan is this: replace each line in initialImage by the specified= motif. We rotate, scale, and translate the motif to each line's position to= do this. alpha is the angle to rotate, and p1 is the translation needed. With three arguments: LineTransform[initialImage_,replacement_,Line[{p3_,p4_= }]]. Here we need to do an extra set of translations and rotations to put= the motif in the right position, then move it onto each line in original= image. This extra motion is combined into just one motion in the code.*) (*-----------------cut here------------------------------*) Xah, xah at best.com http://www.best.com/~xah/Wallpaper_dir/c0_WallPaper.html Mountain View, CA, USA "Yes. DyLan is the best language around, and Java sucks."