b=Math,d,f=(o)=>0.017*o,g=f(90),h='push',i=(o,p,q,s)=>{return{x:q*b.cos(s)+o,y:q*b.sin(s)+p}},j=(o,p)=>{let q=p.x-o.x,s=p.y-o.y;return{r:b.sqrt(b.pow(q,2)+b.pow(s,2)),p:b.atan2(s,q)}},k=(o,p)=>{let q=j(o,p),s=i(o.x,o.y,q.r,q.p+g);return{A:o,B:p,C:s,D:i(p.x,p.y,q.r,q.p+g),E:i(s.x,s.y,q.r*b.cos(d),q.p+d)}},l=(o,p,q,s,t)=>{let u=90,v=210,w=[];t.lineWidth=1,t.fillStyle='white';let z=(G)=>{let I='lineTo';t.beginPath(),t.moveTo(G.C.x+u,-G.C.y+v),t[I](G.C.x+u,-G.C.y+v),t[I](G.E.x+u,-G.E.y+v),t[I](G.D.x+u,-G.D.y+v),t[I](G.C.x+u,-G.C.y+v),t[I](G.A.x+u,-G.A.y+v),t[I](G.B.x+u,-G.B.y+v),t[I](G.D.x+u,-G.D.y+v),t.fill(),t.stroke()},E=i(0,0,s,0),F=i(E.x,E.y,s,0);d=f(q),t.clearRect(0,0,o.width,o.height),((G)=>{let H=[],I,J;for(let K=0;K<p;K++)if(!w[K]){if(1>K){z(G,K),H[h]([G]);continue}let L=[];for(let M of H[K-1])I=k(M.C,M.E),J=k(M.E,M.D),z(I,K),z(J,K),L[h](I),L[h](J);H[h](L),w[K]=1}})(k(E,F))},m=()=>l(a,8,50,50,c),n='addEventListener';m(),a[n]('mousemove',(o)=>l(a,o.clientY/26,o.clientX/4,50,c)),a[n]('mouseleave',()=>m())
/**
* Pythagoras tree fractal - http://en.wikipedia.org/wiki/Pythagoras_tree_(fractal)
* js1k 2017
*/
(() => {
let Math = window.Math;
let triangleDegInRads;
let d2r = x => 0.017 * x;
let _90degInRads = d2r(90);
let push = 'push';
let Vertex = (argX, argY, r, argPhi) => {
return {
x: r * Math.cos(argPhi) + argX,
y: r * Math.sin(argPhi) + argY
};
};
let BaseLine = (A, B) => {
let x = (B.x - A.x);
let y = (B.y - A.y);
return {
r: Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)),
p: Math.atan2(y, x)
};
};
let Branch = (A, B) => {
let baseLine = BaseLine(A, B);
let C = Vertex(A.x, A.y, baseLine.r, baseLine.p + _90degInRads);
return {
A,
B,
C: C,
D: Vertex(B.x, B.y, baseLine.r, baseLine.p + _90degInRads),
E: Vertex(C.x, C.y, baseLine.r * Math.cos(triangleDegInRads), baseLine.p + triangleDegInRads)
};
};
let PTree = (canvas, order, angle, height, context) => {
let X_MARGIN = 90;
let Y_MARGIN = 210;
let cache = [];
context.lineWidth = 1;
context.fillStyle = 'white';
let drawBranch = (branch, order) => {
let lineTo = 'lineTo';
context.beginPath();
context.moveTo(branch.C.x + X_MARGIN, -branch.C.y + Y_MARGIN);
context[lineTo](branch.C.x + X_MARGIN, -branch.C.y + Y_MARGIN);
context[lineTo](branch.E.x + X_MARGIN, -branch.E.y + Y_MARGIN);
context[lineTo](branch.D.x + X_MARGIN, -branch.D.y + Y_MARGIN);
context[lineTo](branch.C.x + X_MARGIN, -branch.C.y + Y_MARGIN);
context[lineTo](branch.A.x + X_MARGIN, -branch.A.y + Y_MARGIN);
context[lineTo](branch.B.x + X_MARGIN, -branch.B.y + Y_MARGIN);
context[lineTo](branch.D.x + X_MARGIN, -branch.D.y + Y_MARGIN);
context.fill();
context.stroke();
};
let drawTree = branch => {
let branches = [];
let leftB;
let rightB;
for (let branchOrder = 0; branchOrder < order; branchOrder++) {
if (cache[branchOrder]) {
continue;
}
if (branchOrder < 1) {
drawBranch(branch, branchOrder);
branches[push]([branch]);
continue;
}
let branchLeafs = [];
for (let branch of branches[branchOrder - 1]) {
leftB = Branch(branch.C, branch.E);
rightB = Branch(branch.E, branch.D);
drawBranch(leftB, branchOrder);
drawBranch(rightB, branchOrder);
branchLeafs[push](leftB);
branchLeafs[push](rightB);
}
branches[push](branchLeafs);
cache[branchOrder] = 1;
}
};
// init tree
let A = Vertex(0, 0, height, 0);
let B = Vertex(A.x, A.y, height, 0);
triangleDegInRads = d2r(angle);
context.clearRect(0, 0, canvas.width, canvas.height);
drawTree(Branch(A, B));
};
let renderInitial = () => PTree(a, 8, 50, 50, c);
let addEventListener = 'addEventListener';
renderInitial();
a[addEventListener]('mousemove', e => {
PTree(a, e.clientY / 26, e.clientX / 4, 50, c);
});
a[addEventListener]('mouseleave', e => {
renderInitial();
});
})();