Enter two numbers and press "Go". Some examples:
(0,0): a circle!
(-0.4, 0.59): Pretty colours
(0.34, 0.4): More pretty colours
(-1.31, 0): Has a problem in the centre
(0,0.7): Spiral thing
(-0.75,0.05): compare this with (-0.75, 0)
The Julia sets are generated by inverse iteration. We start with one point, z, and then find "all" pre-images of z under the operation z->z2+c. So if we start with z, the next 2 points are sqrt(z-c) and -sqrt(z-c). The number of points doubles with each iteration - this is kept under control by discarding any point which maps to a pixel which has already been drawn.
The most obvious disadvantage of this approach is rendering accuracy: if z-c is small, then taking the square root increases the distance between pixels. This results in "gaps" around 0, and to a lesser extent, gaps around the pre-images of 0. Probably the worst victim of this is the Julia set with c=-2, which should be a line segment without any holes in it.
The only real advantage is speed (or it would be if I didn't put a delay in there). It's also fun to see the set get drawn from the outside in.
One irritating aspect of Java is the lack of operator overloading. In C++, I can write a calculation like this:
( -b+sqrt(b*b-4*a*c) )/(2*a)
(assuming a, b and c are already instances of a complex number class). But in Java, the same thing ends up looking like this:
(b.negative().add(b.multiply(b).subtract(new Complex(4).multiply(a).multiply(c))).sqrt()).divide(new Complex(2).multiply(a))
Bletch. I'm not entirely sure what the designers of Java were thinking. Perhaps they were really, really disgusted by the way C++ overloads the bit shift operators to do I/O.