addvec := (p,q) -> [ p[1]+q[1], p[2]+q[2]]:
Now, we write the main guts, which turns a segment into 9 segments, arranged appropriately. Notice that 4 of the segments are perpendicular to the original, so we need to compute perp, which is the vector perpendicular to the given one, and 1/3 as long. the vector pq3 is the vector parallel to the input segment, but 1/3 the length.
Note that decoration only returns the 8 points making up the boxlike
structure in the middle, NOT the endpoints p & q.
decoration:=proc(p,q) local a,b,c,d,e,f, pq3, perp, perpneg; pq3 := [ (q[1]-p[1])/3, (q[2]-p[2])/3 ]; perp:= [ pq3[2], -pq3[1] ]; perpneg:= [ -pq3[2], pq3[1] ]; a := addvec(p, pq3); b := addvec(a, perp); c := addvec(b, pq3); d := addvec(a, pq3); e := addvec(a, perpneg); f := addvec(e, pq3); RETURN( a, b, c, d, a, e, f, d ); end:The procedure decoration takes a curve (actually a list of points), and calls decorate on each segment, inserting the result between each pair of points.
decorate := proc ( incurve ) local i, outcurve; outcurve := [incurve[1]]; for i from 2 to nops(incurve) do outcurve := [ op(outcurve), decoration(incurve[i-1], incurve[i]), incurve[i] ]; od; RETURN(outcurve); end:
Now we are ready to make the curve. First, we write the initiator, the unit segment.
l0 := [[0,0], [1,0]]:
We use l1 for the first stage of the Peano curve.
l1 := decorate(l0): plot(l1, axes=none, scaling=constrained);
l2:=decorate(l1): plot(l2, axes=none, scaling=constrained);
After two steps, we already see it beginning to fill out the square,
although lets do a few more, just to see how it goes.
l3:=decorate(l2): l4:= decorate(l3): plot(l4,axes=none);
plot(decorate(decorate(decorate([[0,0],[1,1]]))));
It is a little difficult to SEE the way the curve winds its way through the
square, so lets change decoration a little bit, so that the
decorations dont quite meet up. Then we should be able to follow its path
through the square.
decoration:=proc(p,q) local a,b,c,d,e,f, pq3, perp, perpneg, pq30, a2, d2; pq3 := [ (q[1]-p[1])/3, (q[2]-p[2])/3 ]; pq30 := [ (q[1]-p[1])/20, (q[2]-p[2])/20 ]; perp:= [ .9*pq3[2], -.9*pq3[1] ]; perpneg:= [ - .9*pq3[2], .9*pq3[1] ]; a := addvec(p, pq3); b := addvec(a, perp); c := addvec(b, pq3); d := addvec(a, pq3); a2 := addvec(a,pq30); e := addvec(a2, perpneg); f := addvec(e, pq3); d2:= addvec(f,perp); RETURN( a, b, c, d, a2, e, f, d2 ); end:
Now we can follow the way the curve winds through the square. Of course,
it no longer will fill out the whole square, but you can see the trend of
the original.
plot(decorate(decorate(decorate([[0,0],[1,0]]))));
This square is skewed because I was not careful enough about the way I avoided self-intersections (some of the segments are longer than others, etc.) Oh well. Fix it if you feel like it....