I am trying to implement rotation in chaos games. I have the following implementation for determining the next point:
function w(x, attractor) {
let compression_ratio = attractor.compression_ratio;
if ('rotation' in attractor) {
let unrotated_new_x =
compression_ratio * x[0] +
(1.0 - compression_ratio) * attractor['point'][0];
let unrotated_new_y =
compression_ratio * x[1] +
(1.0 - compression_ratio) * attractor['point'][1];
let dx = attractor['point'][0] - unrotated_new_x;
let dy = attractor['point'][1] - unrotated_new_y;
let d = Math.sqrt(dx**2 + dy**2);
let theta_1 = Math.atan2(dy, dx);
let theta_2 = attractor['rotation'] * Math.PI / 180.0;
let theta = theta_1 + theta_2;
let new_dx = d * Math.cos(theta);
let new_dy = d * Math.sin(theta);
return [attractor['point'][0] + new_dx, attractor['point'][1] + new_dy];
} else {
return [compression_ratio * x[0] +
(1.0 - compression_ratio) * attractor['point'][0],
compression_ratio * x[1] +
(1.0 - compression_ratio) * attractor['point'][1]];
}
}
If I use these attractors (without rotation):
function get_sierpinski_triangle_attractors() {
v_1 = [-1.0, 0.0];
v_2 = [1.0, 0.0];
v_3 = [0.0, Math.sqrt(3.0)];
vs = [v_1, v_2, v_3];
let attractors =
[{"point": vs[0], "compression_ratio": 0.5,
"probability": 1.0 / 3.0, "color": "red"},
{"point": vs[1], "compression_ratio": 0.5,
"probability": 1.0 / 3.0, "color": "yellow"},
{"point": vs[2], "compression_ratio": 0.5,
"probability": 1.0 / 3.0, "color": "blue"}];
return attractors;
}
it works and I get this:
However, if I set a rotation on the blue vertex:
let attractors =
[{"point": vs[0], "compression_ratio": 0.5,
"probability": 1.0 / 3.0, "color": "red"},
{"point": vs[1], "compression_ratio": 0.5,
"probability": 1.0 / 3.0, "color": "yellow"},
{"point": vs[2], "compression_ratio": 0.5,
"probability": 1.0 / 3.0, "color": "blue", "rotation": 90}];
I get this:
but I'm expecting something similar to this (except flipped vertically):
Note that this is from "Chaos Rules!" by Robert L. Devaney of Boston University.
Moreover, if I set the rotation to 0
:
let attractors =
[{"point": vs[0], "compression_ratio": 0.5,
"probability": 1.0 / 3.0, "color": "red"},
{"point": vs[1], "compression_ratio": 0.5,
"probability": 1.0 / 3.0, "color": "yellow"},
{"point": vs[2], "compression_ratio": 0.5,
"probability": 1.0 / 3.0, "color": "blue", "rotation": 0}];
I expect to get the usual Sierpinski triangle. However, I get this:
What am I doing wrong here?
Note that my entire code base is available here.