Yuki1112
Yuki1112

Reputation: 365

Banach Fractal Curve Java - Recursive

I have the following Banach Fractal problem: The so-called Banach Curve can be generated using the following fractal rule:

  1. Draw a circle.
  2. Draw 9 smaller circles, each with a radius ⅓ of the original circle. One of the smaller circles should have the same center as that of the original circle. The centers of the remaining 8 smaller circles should be equally spaced along the circumference of the original circle.
  3. Repeat step b with each of the smaller circles.

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:

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: my output stages of Banach Curve: Stages of Banach Curve

Upvotes: 0

Views: 1162

Answers (2)

cdlane
cdlane

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);

enter image description here

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:

enter image description here

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:

enter image description here

Upvotes: 1

Billy Brown
Billy Brown

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);:

Banach Curve for recursion depth of 6.

Upvotes: 2

Related Questions