Class 8 - Recursive Pictures. Recursively-defined curves The Hilbert curve. Recursive drawings. Many shapes are “self-similar” - their overall structure is repeated in sub-pictures. Peano curve:. Recursive drawings (cont.). “Koch snowflake”:. Recursive drawings (cont.).
Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.
“Koch snowflake”:
HC(1):
HC(2):
HC(3):
n-1
n-1
n-1
n-1
n-1
Hilbert curves have “open” side on left:
Form H.C. of order n by combining four copies of H.C. of order n-1,
plus three connecting
lines (of length sl):
This leads to the basic recursive pattern for defining HC(order, sl):
int diam = size of HC of order n-1;
hcsub1 = HC(order-1, sl);
hcul = rotate hcsub1 by -90 degrees;
hcur = translate hcsub1 to (diam+sl, 0);
hclr = translate hcsub1 to (diam+sl, diam+sl);
hcll = rotate hcsub1 by 90 degrees,
then translate to (0, diam+sl);
hc = append(hcul, append(hcur, append(hclr, hcll)));
return hc, with three lines added;
We have already seen how to translate a LineList:
static LineList translate (LineList L, int x, int y) {
if (L.empty())
return L;
else {
Line ln = L.hd();
Line transLine = new Line(ln.x0()+x, ln.y0()+y,
ln.x1()+x, ln.y1()+y);
return LL.cons(transLine,
translate(L.tl(), x, y));
}
}
Rotation is more complicated. Consider rotating one point around the origin by angle :
(x’,y’)
1. Calculate m and
m = x2+y2
= tan-1(y/x)
2. = +
3. (x’,y’) = point of length
m, at angle
(x,y)
We’ll rotate shapes (i.e. LineList’s) about the
origin by rotating each line:
static LineList rotateShapeAboutOrigin
(LineList L, double theta) {
if (L.empty())
return LL.nil;
else
return LL.cons(rotateLine(L.hd(), theta),
rotateShapeAboutOrigin(L.tl(), theta));
}
Rotating individual lines around the origin is a matter of rotating both endpoints, as we have indicated. Some added complexity comes from two factors:
static Line rotateLine (Line ln, double theta) {
int x0 = ln.x0(),
y0 = -ln.y0(), // turn coordinates rightside-up
x1 = ln.x1(),
y1 = -ln.y1(); // turn coordinates rightside-up
double currangle0 = Math.atan((double)y0/x0);
double newangle0 = currangle0+theta;
if (x0<0) newangle0 = newangle0 + Math.PI;
double mag0 = Math.sqrt(x0*x0+y0*y0);
int newx0 = (int)Math.round(mag0*Math.cos(newangle0));
int newy0 = -(int)Math.round(mag0*Math.sin(newangle0));
double currangle1 = Math.atan((double)y1/x1);
double newangle1 = currangle1+theta;
if (x1<0) newangle1 = newangle1 + Math.PI;
double mag1 = Math.sqrt(x1*x1+y1*y1);
int newx1 = (int)Math.round(mag1*Math.cos(newangle1));
int newy1 = -(int)Math.round(mag1*Math.sin(newangle1));
return new Line(newx0,newy0,newx1,newy1);
}
One remaining technicality: when we say “rotate a shape”, we usually mean, “rotate it around its center”. However, so far we know only how to rotate a shape around the origin. The rotateShape method takes a shape and an angle and a point (x,y) which is taken to be the center of the shape.
It does so by translating the shape, then rotating,
then translating back:
static LineList rotateShape (LineList L, double theta,
int x, int y) {
LineList transL = translate(L, -x, -y);
LineList rotateL =
rotateShapeAboutOrigin(transL, theta);
return translate(rotateL, x, y);
}
Recall again the abstract version of HC(order, sl):
int diam = size of HC of order n-1;
hcsub1 = HC(order-1, sl);
hcul = rotate hcsub1 by -90 degrees;
hcur = translate hcsub1 to (diam+sl, 0);
hclr = translate hcsub1 to (diam+sl, diam+sl);
hcll = rotate hcsub1 by 90 degrees,
then translate to (0, diam+sl);
hc = append(hcul, append(hcur, append(hclr, hcll)));
return hc, with three lines added;
We can now say that the rotation steps should
rotate the shape around the center of the Hilbert
curve of order n-1. That center is at (diam/2,
diam/2).
How do we calculate diam? A review of the
Hilbert curve of various orders show that
HC(n-1) has diameter ( 2n-1-1)*sl.
This leads to our solution:
static LineList HC (int order, int sl) {
if (order == 1)
return LL.cons(new Line(0,0,sl,0),
LL.cons(new Line(sl,0,sl,sl),
LL.cons(new Line(sl,sl,0,sl), LL.nil)));
else {
int diam = sl*(int)(Math.pow(2,order-1)-1);
// diameter of HC(order-1)
int radius = diam/2;
LineList hcsub1 = HC(order-1, sl);
LineList hcul = rotateShape(hcsub1, -Math.PI/2,
radius, radius);
LineList hcur = translate(hcsub1, diam+sl, 0);
LineList hclr = translate(hcsub1, diam+sl, diam+sl);
LineList hcll = translate(
rotateShape(hcsub1,Math.PI/2,
radius, radius),
0, diam+sl);
LineList hc = append(hcul,
append(hcur, append(hclr, hcll)));
hc = LL.cons(new Line(diam,0,diam+sl,0),
LL.cons(new Line(diam+sl,diam,diam+sl,diam+sl),
LL.cons(new Line(diam+sl,2*diam+sl,
diam,2*diam+sl),
hc)));
return hc;
}
}