Reputation: 784
I'm trying to solve task 9.3 from book "Think Recursively by Eric S. Roberts (1986)". Let consider that we have simple triangle:
.
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/ \
/_______________________\
Putting a smaller flea on each of two segments that forms the back of the large flea gives the next stage:
.
/ \
/ \
/ \
_________/ \_________
\ / \ /
\ / \ /
\ / \ /
\ / \ /
/ \
/ \
/ \
/_______________________\
Each of these two new fleas plays host to two smaller fleas, which give us the following menagerie:
.
/ \
/ \
. / \ .
___/_\___/ \___/_\___
\ / \ /
: / \ :
/_\ / \ /_\
\ / \ /
/ \
/ \
/ \
/_______________________\
The problem is that I can not figure out the recursion pattern here. I even do not know how should I start to think about this task to find a solution.
For drawing I use 3 functions:
My class for drawing at Canvas:
var X_CENTER = 400;
var Y_CENTER = 400;
function DrawLib() {
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var inverted_y = 800;
var _dx = 0, _dy = 800;
this.setPoint = function (x, y) {
inverted_y = 800;
inverted_y -= y;
_dx = x;
_dy = inverted_y;
ctx.moveTo(x, inverted_y);
};
this.vector = function(dx, dy) {
_dx += dx;
_dy -= dy;
ctx.lineTo(_dx, _dy);
};
this.polarVec = function(lengthPx, angle) {
var radians = angle * Math.PI / 180;
this.vector(lengthPx * Math.cos(radians), lengthPx * Math.sin(radians));
}
this.stroke = function () {
ctx.stroke();
}
}
var drawLib = new DrawLib();
My solution (perfectly works only for order 0 and 1):
function fractLine(order, l, theta) {
if (order == 0) return drawLib.polarVec(l, theta);
fractLine(order - 1, 2 * l/3,theta);
fractLine(order - 1, l/3,theta - 120);
fractLine(order - 1, l/3,theta + 120);
fractLine(order - 1, 2* l/3,theta);
}
function triangleWithFleas(order, l) {
//left side of triangle
drawLib.setPoint(X_CENTER - l/2, Y_CENTER - Math.sqrt(3)* l/4);
//start drawing
drawLib.vector(l,0);
fractLine(order, l, 120);
fractLine(order, l, 240);
drawLib.stroke();
}
triangleWithFleas(1, 400);
Upvotes: 1
Views: 54
Reputation: 784
According to @jxh comment, I needed a function that draws a triangle at a particular orientation from a particular starting point. Then, it should recursively calls itself twice, adjusting the orientation and starting point for each call.
I've updated my code. triangle
draws the triangle, showFlake
recursively draws the flea triangles after calling triangle
.
Now it works perfectly.
var X_CENTER = 400;
var Y_CENTER = 400;
function DrawLib() {
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var inverted_y = 800;
var _dx = 0, _dy = 800;
this.setPoint = function (x, y) {
inverted_y = 800;
inverted_y -= y;
_dx = x;
_dy = inverted_y;
ctx.moveTo(x, inverted_y);
};
this.vector = function(dx, dy) {
_dx += dx;
_dy -= dy;
ctx.lineTo(_dx, _dy);
return {
x: _dx,
y: 800 - _dy // coord inversion
};
};
this.polarVec = function(lengthPx, angle, color) {
var radians = angle * Math.PI / 180;
return this.vector(lengthPx * Math.cos(radians), lengthPx * Math.sin(radians));
}
this.stroke = function () {
ctx.stroke();
}
}
var drawLib = new DrawLib();
function triangle(x, y, l, theta) {
drawLib.setPoint(x, y);
drawLib.polarVec(l, theta);
var firstAngle = theta + 120;
var secondAngle = theta + 240;
var firstTrianleStartPoint = drawLib.polarVec(2 * l / 3, firstAngle);
drawLib.polarVec( l / 3, firstAngle);
var secondTrianleStartPoint = drawLib.polarVec(2 * l / 3, secondAngle);
drawLib.polarVec(l / 3, secondAngle);
return {
x1: firstTrianleStartPoint.x,
y1: firstTrianleStartPoint.y,
x2: secondTrianleStartPoint.x,
y2: secondTrianleStartPoint.y,
}
}
function showFlake(order, x, y, l, theta) {
if(order === 0) return;
var coords = triangle(x, y, l, theta);
showFlake(order - 1, coords.x1, coords.y1, l / 3, theta + -60);
showFlake(order - 1, coords.x2, coords.y2, l / 3, theta + 60);
}
var len = 600
var x = X_CENTER - len / 2;
var y = Y_CENTER - Math.sqrt(3) * len / 4;
showFlake(5, x, y, len, 0);
drawLib.stroke();
Upvotes: 1