ROV13_6.MWS

Chapter 13. Fractal Curves and Dimension

> restart:

13.1 Sierpinski's Curves

Example 1 . A simple program for plotting with recursion.

> tree := proc(L::algebraic,lev::integer,x0::algebraic, y0::algebraic) local i; global s,p; options remember; s:=s+1; p[s]:=plot([[x0-L,y0+L],[x0,y0],[x0+L,y0+L]]); if lev > 1 then tree(L/2,lev-1,x0-L,y0+L);tree(L/2,lev-1,x0+L,y0+L) fi; RETURN(plots[display]([seq(p[i], i=1..2^lev-1)],scaling=constrained)) end:

> s:=0: tree(100, 3, 0, 0);

>

Replace the angle by a more complicated object

> # p[s]:=plot([x0+L*sqrt(2)*sin(2*t)*cos(t), y0+L*sqrt(2)*sin(2*t)*sin(t), t=-Pi/2..Pi/2], color=green, style=point):

> cactus := proc(L::algebraic,lev::integer,x0::algebraic, y0::algebraic) local i; global s,p; options remember; s:=s+1; p[s]:=plot([x0+L*sqrt(2)*sin(2*t)*cos(t), y0+L*sqrt(2)*sin(2*t)*sin(t), t=-Pi/2..Pi/2], color=green, style=point,symbol=diamond): if lev > 1 then cactus(L/2,lev-1,x0-L,y0+L); cactus(L/2,lev-1,x0+L,y0+L) fi; RETURN(plots[display]([seq(p[i], i=1..2^lev-1)],scaling=constrained)) end:

> s:=0: cactus(100, 3, 0, 0);

Problem 1 .

> serp1:= proc(L::algebraic, lev::integer,x0::algebraic,y0::algebraic) global p,s; options remember; if s=0 then p[0]:=plots[polygonplot]([[x0,y0],[x0+2*L ,y0],[x0,y0+2*L]], style=line) fi; s:=s+1; p[s]:=plots[polygonplot]([[x0,y0+L], [x0+L,y0+L],[x0+L,y0]], color=green); if lev>1 then serp1(L/2,lev-1,x0,y0);serp1(L/2,lev-1,x0+L,y0); serp1(L/2,lev-1,x0,y0+L) fi; RETURN(plots[display]([seq(p[i],i=0..(3^lev-1)/2)],scaling=constrained)) end:

> s:=0: serp1(100, 4, 0, 0);

>

Problem 2 .

> serp2 := proc(a::algebraic,lev::integer,x0::algebraic,y0::algebraic) local i,j; global s,p; options remember; if s=0 then p[0]:=plots[polygonplot]([[x0,y0], [x0,y0+a], [x0+a,y0+a], [x0+a,y0]], style=line) fi; s:=s+1; p[s]:=plots[polygonplot]([[x0+a/3, y0+a/3], [x0+a/3, y0+2*a/3], [x0+2*a/3, y0+2*a/3], [x0+2*a/3, y0+a/3]],color=green); if lev > 1 then for i from 0 to 2 do for j from 0 to 2 do if abs(i-1)+abs(j-1) > 0 then serp2(a/3,lev-1, x0+i*a/3, y0+j*a/3) fi od od fi; RETURN(plots[display]([seq(p[i], i=0..(8^lev-1)/7)], axes=none,scaling=constrained)) end:

> s:=0: serp2(100, 3, 0, 0);

>

13.2 Peano Curves

Problem 1 .

(a)

> restart:

> peano1 := proc(L::algebraic, lev::integer) local A,s,p,i; global Q; Q:=plots[polygonplot]([[L,L/2],[L/2,L],[L,3*L/2], [3*L/2,L]]); s:=1; while s <= lev do A:=L/2^(s-1); p[4]:=plot([[A/2,0], [A/2,A/4]]); p[5]:=plot([[0, A/2], [A/4, A/2]]); p[6]:=plot([[A/2,A/4],[A/4,A/2]], color=white,scaling=constrained); p[0]:=plots[display]([p[6],plottools[scale](Q,1/2,1/2), p[4], p[5]]); for i from 1 to 3 do p[i]:=plottools[rotate](p[0], i*Pi/2) od; Q:=plottools[translate](plots[display]([seq(p[i], i=0..3)]),L,L); s:=s+1 od; RETURN(Q) end:

> peano1(10, 4);

>

(b) We plot the triangular Peano curve by the program peano2(L,lev) .

> peano2 := proc(L, k::algebraic, lev::integer) local f,s,p; global Q; p[0]:=plot([[-L*k/2,0], [-L*k/2,L/2], [L*k/2,L/2], [L*k/2,0]], thickness=1); p[1]:=plots[polygonplot]([[-L,0],[0,L],[L,0]], linestyle=2); Q:=plots[display]([p[0],p[1]]); f:=plottools[transform]((x,y) -> [-x,y]); s:=2; while s < lev+2 do if (s mod 2=0) then p[0]:=plot([[L*(1-(2-k)/2^(s/2)),L/2^(s/2)],[L*(1-(3-k)/2^(s/2+1)),L*(3-k)/2^(s/2+1)]],thickness=1); p[1]:=plot([[L*(1-(2-k)/2^(s/2)),L/2^(s/2)],[L*(1-(2-k)/2^(s/2)),0]],thickness=1,color=white); Q:=plots[display]([p[1],Q,p[0]]) fi; p[2]:=plottools[scale](plottools[rotate](plottools[translate](Q,0,-L),3*Pi/4),1/sqrt(2),1/sqrt(2)); Q:=plots[display]([p[2],f(p[2])],scaling=constrained); s:=s+1 od; RETURN(Q) end: # 0<k<1 defines smoothness of curve.

> peano2(10, 0.7, 6);

(c) Recursion can be used for plotting the image known as the Hilbert's curve.

> peano3 := proc(a,b,c,dab::array,dac::array, lev::integer) local d,e,f,g,h,i,j,k,m,p; global Q; options remember; d[1]:=(a[1]+c[1]-dac[1])/2; d[2]:=(a[2]+c[2]-dac[2])/2; f[1]:=d[1]+dac[1]; f[2]:=d[2]+dac[2]; i[1]:=f[1]+b[1]-a[1]; i[2]:=f[2]+b[2]-a[2]; e[1]:=(a[1]+b[1]-dab[1])/2; e[2]:=(a[2]+b[2]-dab[2])/2; g[1]:=f[1]+e[1]-a[1]; g[2]:=f[2]+e[2]-a[2]; h[1]:=g[1]+dab[1]; h[2]:=g[2]+dab[2]; j[1]:=c[1]+h[1]-f[1]; j[2]:=c[2]+h[2]-f[2]; k[1]:=i[1]-dac[1]; k[2]:=i[2]-dac[2]; m[1]:=e[1]+dab[1]; m[2]:=e[2]+dab[2]; p[1]:=plot([[a[1],a[2]],[f[1],f[2]],[i[1],i[2]],[b[1],b[2]]]); p[2]:=plot([[a[1],a[2]],[b[1],b[2]]],color=white); Q:=plots[display]([p[2],p[1],Q],scaling=constrained); if lev > 0 then peano3(a,d,e,dac,dab,lev-1); peano3(f,g,c,dab,dac,lev-1); peano3(h,i,j,dab,dac,lev-1); dab[1]:=-dab[1]; dab[2]:=-dab[2]; peano3(b,k,m,dac,dab,lev-1); dab[1]:=-dab[1]; dab[2]:=-dab[2] fi; RETURN(Q) end:

> a:=[1,1]: b:=[4,1]: c:=[1,4]: m:=3: N:=2^(m+1)-1: dac:=evalm((c-a)/N): dab:=evalm((b-a)/N): Q:=plot([[a[1], a[2]], [b[1], b[2]]], color=white, thickness=2):

> peano3(a, b, c, dab, dac, m);

Triangle:

> with(plottools): a:=[0,0]: b:=[0,3]: c:=[-3,0]: Q:=plot([[a[1],a[2]],[b[1],b[2]]], color=white):

> m:=3: N:=2^(m+1)-1: dac:=evalm((c-a)/N): dab:=evalm((b-a)/N):

> q[1]:=peano3(a,b,c,dab,dac,m): q[2]:=scale(rotate(translate(q[1],0,-3),Pi/2),4/3,4/3): q[3]:=translate(scale(rotate(q[1], Pi+arcsin(4/5)),5/3,5/3),0,3): plots[display]([q[1], q[2], q[3]],axes=none);

>

13.3 Koch Curves

> restart:

> triad1 := proc(L::algebraic, lev::integer, x0::algebraic,y0::algebraic) global p,s; options remember; s:=s+1; p[s]:=plots[polygonplot]([[x0,y0], [x0,y0+L], [x0+L,y0+L], [x0+L,y0]], color=green); if lev>1 then triad1(L/3, lev-1, x0+L/3, y0-L/3); triad1(L/3,lev-1,x0-L/3,y0+L/3);triad1(L/3, lev-1, x0+L/3, y0+L); triad1(L/3, lev-1, x0+L, y0+L/3) fi; RETURN(plots[display]([seq(p[i], i=1..(4^lev-1)/3)])) end:

> s:=0: triad1(100, 3, 0, 0);

>

> triad2 := proc(a,b, lev::integer) local s,c,d,e,f; global p,Q; options remember; s:=.33; c[1]:=a[1]+(b[1]-a[1])*s; c[2]:=a[2]+(b[2]-a[2])*s; f[1]:=a[1]+(b[1]-a[1])*(1-s); f[2]:=a[2]+(b[2]-a[2])*(1-s); d[1]:=c[1]-(f[2]-c[2]); d[2]:=c[2]+(f[1]-c[1]);e[1]:=d[1]+f[1]-c[1]; e[2]:=d[2]+f[2]-c[2];p[1]:=plot([[c[1],c[2]],[d[1],d[2]],[e[1],e[2]],[f[1],f[2]]]); p[2]:=plot([[c[1],c[2]],[f[1],f[2]]], color=white); Q:=plots[display]([p[2],Q,p[1]], scaling=constrained);if lev>1 then triad2(c,d,lev-1); triad2(d,e,lev-1); triad2(e,f,lev-1) fi; RETURN(Q) end: # 0<s<0.5

> a:=[1,1]: b:=[4,1]: Q:=plot([[a[1],a[2]], [b[1],b[2]]]):

> triad2(a, b, 4);

> with(plottools): setoptions(scaling=constrained, axes=none):

> f:= transform((x,y)->[-x,y]): q||1:=translate(Q,-a[1],-a[2]): q||2:=rotate(f(q||1), Pi/2): q||3:=translate(rotate(q||1, -Pi/2), b[1]-a[1], 0): q||4:=translate(rotate(q||1, Pi), b[1]-a[1], a[1]-b[1]): plots[display]([seq(q||i, i=1..4)],axes=framed);

>

> triad3 := proc(a,b,lev::integer) local s,k,c,d,f,p; global Q; options remember; s:=0.4; k:=2;c[1]:=a[1]+(b[1]-a[1])*s; c[2]:=a[2]+(b[2]-a[2])*s; f[1]:=a[1]+(b[1]-a[1])*(1-s); f[2]:=a[2]+(b[2]-a[2])*(1-s); d[1]:=(a[1]+b[1])/2-k*(f[2]-c[2]); d[2]:=(a[2]+b[2])/2+k*(f[1]-c[1]); p[1]:=plot([[c[1],c[2]],[d[1],d[2]],[f[1],f[2]]]); p[2]:=plot([[c[1],c[2]],[f[1],f[2]]], color=white); Q:=plots[display]([p[2],Q,p[1]], scaling=constrained); if lev>1 then triad3(a,c,lev-1); triad3(c,d,lev-1); triad3(d,f,lev-1); triad3(f,b,lev-1) fi; RETURN(Q) end:

> a:=[1,1]: b:=[4,1]: Q:=plot([[a[1],a[2]],[b[1],b[2]]]):

> setoptions(scaling=constrained, axes=none):

> f:=transform((x,y)->[-x,y]): q||1:=translate(Q,-a[1],-a[2]): q||2:=rotate(f(q||1), 2*Pi/3): q||3:=translate(rotate(q||1,-2*Pi/3), b[1]-a[1],0): plots[display]([seq(q||i, i=1..3)], axes=none);

>

Exercise . Modify programs 13.3.1 and 13.3.2 for getting Koch curves which are inside the triangle and the square.

For obtaining Koch similar curves replace the equilateral triangle in the original

Koch curve by an isosceles triangle or try to find your own "generators".

13.4 Dragon Curve (or Polygon)

> restart: with(plottools): setoptions(scaling=constrained,axes=none):

>

> dragon1 := proc(m::integer, k::algebraic) local b,i; global c,p; p[1]:=plot([[0,0],[1-k,0],[1,k],[1,1]]); c[1]:=circle([1,0],0.04); for i from 1 to m-1 do b:=[2^(i/2)*cos(i*Pi/4),2^(i/2)*sin(i*Pi/4)]; c[i+1]:=circle(b,0.05); p[i+1]:=plots[display]([plot([[b[1],b[2]-k],[b[1],b[2]],[b[1]-k,b[2]]], color=white), p[i],plot([[b[1],b[2]-k],[b[1]-k,b[2]]]),translate(rotate(translate(p[i],-b[1],-b[2]),-Pi/2),b[1],b[2])]) od; RETURN(plots[display]([p[m], seq(c[i], i=1..m)],axes=framed,scaling=constrained)) end:

> dragon1(10, 1/4);

> plots[display]([p[7], rotate(p[7],Pi/2), rotate(p[7], -Pi/2), rotate(p[7],Pi)],scaling=constrained,axes=framed);

>

> dragon2 := proc(k::algebraic, N::integer) local t,i,q1,q2,q3,q4,delta; global p; q2:=[k,0]; q3:=[1-k,0]; delta:=evalm(q3-q2); p[0]:=plot([[q2[1],q2[2]], [q3[1],q3[2]]]); for i from 1 to N do if (i mod 2=0) then t[i]:=t[i/2] else t[i]:=(i mod 4)-2 fi; q4:=evalm(q3+k/(1-2*k)*delta); delta:=evalm(t[i]*[delta[2],-delta[1]]); q1:=evalm(q3); q2:=evalm(q4+k/(1-2*k)*delta); q3:=evalm(q2+delta); p[i]:=plot([[q1[1],q1[2]], [q2[1],q2[2]], [q3[1],q3[2]]]) od; RETURN(plots[display]([seq(p[i], i=0..N)])) end:

> dragon2(0.2, 128);

>

13.5 Menger Curve

Plot the figure based on the cube of zero rank hexahedron([x0,y0,z0], a0) .

> restart: with(plots): with(plottools): x0:=1: y0:=2: z0:=3: a0:=.8:

```Warning, existing definition for changecoords has been overwritten
```

> display(cutout(hexahedron([x0, y0, z0], a0), 1/3));

Elements of and can be obtained as follows:

> N2:={\$3..421} minus {seq(21*i+2, i=1..20)}: nops(N2); N3:={\$3..8842} minus ({seq(421*j+2, j=0..20)} union {seq(seq(421*j+21*i+3, i=1..20), j=0..20)}): nops(N3);

>

> menger1 := proc(L::algebraic, lev::integer, x0,y0,z0) local i,j,k,f; global p,s; options remember; s:=s+1;f:=0.4; p[s]:=cutout(hexahedron([x0,y0,z0],L),f); if s=2 then p[1]:=p[2] fi; if lev > 1 then for i from -1 to 1 do for j from -1 to 1 do for k from -1 to 1 do if (k=0 and abs(i)+abs(j)>1) or (k<>0 and abs(i)+abs(j)>0) then menger1(L/3,lev-1, x0+2*i*L/3, y0+2*j*L/3, z0+2*k*L/3) fi od od od fi; RETURN(plots[display]([seq(p[i], i=1..(20^lev-1)/19)],orientation=[43,60],scaling=constrained)) end:

> s:=0: menger1(100, 2, 0, 0, 0);

>

> menger2 := proc(L::algebraic, lev::integer, x0, y0, z0) local i,j,k; global p,s; options remember; if s=0 then p[0]:=hexahedron([x0,y0,z0],L,style=line) fi; for i from -1 to 1 do for j from -1 to 1 do for k from -1 to 1 do if abs(i)+abs(j)+abs(k)=1 then s:=s+1; p[s]:=hexahedron([x0+2*i*L/3, y0+2*j*L/3, z0+2*k*L/3], L/3) fi od od od; if lev > 1 then for i from -1 to 1 do for j from -1 to 1 do for k from -1 to 1 do if abs(i)+abs(j)+abs(k)>1 then menger2(L/3,lev-1,x0+2*i*L/3, y0+2*j*L/3, z0+2*k*L/3) fi od od od fi; RETURN(plots[display]([seq(p[i], i=0..6*(20^lev-1)/19)],scaling=constrained)) end:

> s:=0: menger2(100, 3, 0, 0, 0);

>