Reputation: 365
I have the following Banach Fractal problem: The so-called Banach Curve can be generated using the following fractal rule:
Note: The circle of radius r centered at point (x, y) is the set of all the points
(x + r · cos(t), y + r · sin(t)) where 0 ≤ t ≤ 2π , and t is given in radians. I can use Math.toRadians()
Guidelines:
?
public static void banachCurve(int n)
and help functions private static void banachCurve(double x, double y, double r, int n)
I thought of adding circles each time since there are supposed to be 9 at the edges and 1 in the center each time, however I can only seem to get the circles on the right or left, and for some reason a RuntimeError.
public static void banachCurve(int n) {
banachCurve (0.5,0.5,1,n);
}
private static void banachCurve(double x, double y, double r, int n) {
if (n == 0) {
return;
}
double d = (r/3);
StdDraw.circle (x,y,d);
// StdDraw.ellipse(x, y, r, r);
banachCurve (x + d, y, d, n - 1); // centre
banachCurve (x + d+ d, y+d, d, n--); // left
banachCurve (x , y + d, d, n--); // right
banachCurve (x+d , y +d+ d, d, n--);
banachCurve (x+d , y +d, d, n--);
}
my output: stages of Banach Curve:
Upvotes: 0
Views: 1162
Reputation: 41872
If you're going to drag Math.cos()
into the picture, a la the currenly accepted answer, why not go the whole hog and use sine and cosine to move around the circle:
private static void banachCurve(double x, double y, double r, int n) {
if (n == 0) {
return;
}
double d = r / 3;
StdDraw.circle (x, y, d);
banachCurve (x, y, d, n - 1); // center
for (double angle = 0; angle < 360; angle += 45) {
double theta = Math.toRadians(angle);
double dx = x + d * Math.cos(theta);
double dy = y + d * Math.sin(theta);
banachCurve (dx, dy, d, n - 1);
}
}
Output for banachCurve(0.5, 0.5, 1, 3);
This approach makes easy work of testing out @tucuxi's suggestion, of six instead of eight surrounding circles. Just increase the increment angle in the for
loop from 45 to 60:
Though I can't say its an improvement over the original design. Though seven surrounding circles, again trivial to test given this code design, catches one's eye:
Upvotes: 1
Reputation: 2342
Every time you call n--
, you are passing n
to the function and then decrementing it by one for the next call. Instead, you need to pass n - 1
to each call, as the call itself will decrement n
further in its own recursive call, eventually stopping at 0
as you correctly have.
For the four cardinal points, using (x + d, y)
, (x, y + d)
, (x - d, y)
and (x, y - d)
works correctly, but for the four diagonal points, you will need to use either the square root (Math.sqrt
) for the Pythagoras method, or the sine and cosine (Math.sin
and Math.cos
) for the trigonometric method. Using (x + d, y + d)
and the like would place them on a square instead.
Assuming that x
and y
mark the centre of your circle, your function will then become:
private static void banachCurve(final double x, final double y, final double r, final int n) {
if (n == 0) {
return;
}
final double d = r / 3;
StdDraw.circle (x, y, d);
banachCurve (x, y, d, n - 1); // centre
banachCurve (x, y + d, d, n - 1); // north
banachCurve (x + d, y, d, n - 1); // east
banachCurve (x, y - d, d, n - 1); // south
banachCurve (x - d, y, d, n - 1); // west
// Get the diagonal radius for a point at 45 degrees on the circle
final double diagD = Math.cos(Math.toRadians(45)) * d;
banachCurve (x + diagD, y + diagD, d, n - 1); // north-east
banachCurve (x + diagD, y - diagD, d, n - 1); // south-east
banachCurve (x - diagD, y - diagD, d, n - 1); // south-west
banachCurve (x - diagD, y + diagD, d, n - 1); // north-west
}
Here is the output for banachCurve(0.5, 0.5, 1, 6);
:
Upvotes: 2