MusicIsLife
MusicIsLife

Reputation: 51

Normalized Iteration Count does not work. What am I doing wrong?

As you can see from the title, I'm busy programming a little programm for visualizing fractals in Java. Anybody who deals with fractals will come to the point where he/she searches for a solution to get these stupid "bands" away, when you just colour a pixel by the number of iterations it took to escape. So I searched for a more advanced colouring algorithm, finding the "normalized iteration count". The formula I'm using is:

float loc = (float) 1 - Math.log(Math.log(c.abs())) / Math.log(2);

Everybody on the Internet is so happy about this algorithm, everybody uses it, everbody gets great results. Except me. I thought, this algorithm should provide a float between 0 and 1. But that doesn't happen. I did some calculations and came to the conclusion, that this algorithm only works for c.abs() >= Math.E && c.abs() <= Math.exp(2) (that is Math.E * Math.E). In numbers this means, my input into this equation has to be between about 2.718 and 7.389.

But a complex number c is considerd to tend towards infinity when its magnitude gets greater than 2. But for any Input smaller than Math.E, I get a value greater than one. And for any number greater than Math.exp(2), it gets negative. That is the case if a complex number escapes really fast.

So please tell me: what am I doing wrong. I'm desperate.

Thanks.

EDIT:

I was wrong: the code I posted is correct, I just 1. used it the wrong way and so it didn't provide the right output. 2. had to set the bailout value of the mandelbrot/julia algorithm to 10, otherwise I would've got stupid bands again.

Problem solved!

Upvotes: 4

Views: 1308

Answers (2)

sh1
sh1

Reputation: 4751

As you've already discovered, you need to increase the bailout radius before smoothing will look right.

Two is the minimum length that a coordinate can have such that when you square it and add the initial value, it cannot result in a smaller length. If the previous length was 2.0, and you squared it, you'd have a length of 4.0 (pointing in whichever direction), and the most that any value of c could reduce that by is 2.0 (by pointing in precisely the opposite direction). If c were larger than that then it would start to escape right away.

Now, to estimate the fractional part of the number of iterations we look at the final |z|. If z had simply been squared and c not added to it, then it would have a length between 2.0 and 4.0 (the new value must be larger than 2.0 to bail out, and the old value must have been less than 2.0 to have not bailed out earlier).

Without c, taking |z|'s proportional position between 2 and 4 gives us a fractional part of the number of iterations. If |z| is close to 4 then the previous length must have been close to 2, so it was already close to bailing out in the previous iteration and the smoothed result should be close to the previous iteration count to represent that. If it's close to 2, then the previous iteration was further from bailing out, and so the smoothed result should be closer to the new iteration count.

Unfortunately c messes that up. The larger c is, the larger the potential error is in that simple relationship. Even if the old length was nearly at 2.0, it might have landed such that c's influence made it look like it must have been smaller.

Increasing the bailout mitigates the effect of adding c. If the bailout is 64 then the resulting length will be between 64 and 4096, and c's maximum offset of 2 has a proportionally smaller very impact on the result.

Upvotes: 2

karatedog
karatedog

Reputation: 2618

You have left out the iteration value, try this:

float loc = <iteration_value> + (float) 1 - Math.log(Math.log(c.abs())) / Math.log(2);

The iteration_value is the number of iterations which yielded c in the formula.

Upvotes: 0

Related Questions