# Pictures of Julia and Mandelbrot Sets/Landscapes

If, in a three-dimensional coordinate system, we imagine the plane with the Mandelbrot or the Julia set as the *x,y*-plane and plot the distance function in the *z*-direction, we have a surface looking like a landscape, and we can see it from the side. Such a picture has to be drawn from the top and downwards (on the screen), and from the far distance towards the near (in the landscape), so that something will grow and hide what was previously drawn.

The distance function can have singularities, which means that the surface has points in which it grows towards infinity. As these vigorous rises are unaesthetic if they are numerous and dominant, we must modify the distance function (third picture). We can also modify it in order to create a more interesting landscape (second picture).

We can let the light be "natural", like the light from the sun. Then we imagine the rays are parallel (and given by two angles), and we let the colour of a point on the surface be determined by the angle between this direction and the slope of the surface at the point. The intensity (on the earth) is independent of the distance, but the light grows whiter because of the atmosphere, and sometimes the ground looks as if it is enveloped in a veil of mist (second picture). We can also let the light be "artificial", as if it issues from a lantern held by the observer. In this case the colour must grow darker with the distance (third picture).

We look at the landscape in a direction inclining downward from the eye, and the drawing window has this line as normal in its centre. A vertical line (of pixels) in the drawing window corresponds to a line in the base plane with the fractal. And for each of these lines, we start in the point farthest back and go towards the observer colouring pixels in the corresponding vertical line of the window in the following way: If p is a point on the line in the base plane, we calculate the value of the distance function in p. If the line from this point on the surface to the eye intersects the window, we shall colour this pixel. We calculate the slope of the surface in the point, by calculating the distance function in two points very near p in the x- and y-direction. The little triangle spanned by the three values lies on the surface. We take the scalar product of the normal (unit) vector of the triangle and the direction (unit) vector of the light - in case of artificial light this is the direction vector from the eye to the point.

This number (multiplied by the density) can be combined with other factors determining the colour: the height over the ground or the distance to the observer, for instance.

From the scalar product of the normal (unit) vector of the surface and the direction vector to the observer, we can approximately calculate the distance we must go towards the observer in order to colour the adjacent pixel above or below the just coloured pixel (for rise or fall of the landscape in the direction towards the observer, respectively). As this calculation cannot be exact, the steps must possibly be diminished by a factor. We stop the drawing for this line, when we are so near the observer that the bottom pixel of this vertical line of the window is coloured - possibly we do continue the drawing, if something grows up nearer the observer and we want this to be seen. Instead of finishing a vertical line before we go to the next, we can make the drawing looking more fascinating by going to the next vertical line for each step towards the observer, so that the drawing looks like a wave motion from the top and downwards.

The surface is primary constructed from a function proportional to the distance function, but the program should be made so that this function can be worked up. In the first turn the singularities should be made finite by choosing a relative maximum height *hm0*. This number times the width of the section is the maximum height *hm* in the landscape, and we can replace the height *h* by *hm * arctan(h/hm)*, for instance. The (constant) number *hm* should however be made varying, by dividing it by a number proportional to the exponential function of the real iteration number, in order to lower the maximum height near the boundary. Instead of making the singularities finite, we can simply cut them down by replacing *h* by *hm* when *h* > *hm*. We can also regulate *h* by dividing it by , for instance, or we can convert the singularities to craters by replacing *h* by when *h* > *hm*.

Furthermore, the surface can be smoothed out by multiplying *h* by (for instance) the number , where *s* is the slope of the surface and *a* and *b* are parameters determining the effect.

For natural light, we can get the colour growing whiter (mist) or darker with the distance and the height, by mixing the colour with grey or black, respectively, according to this number (in the interval [0, 1]): , where *a, b, c* and *d* are parameters determining the effect.

For artificial light, we can get the colour growing darker with the distance, by mixing with black according to the number , where *s* is the scalar product of the direction vector from the eye and the slope (unit) vector, and *l* and *e* are parameters determining the effect.

## Contents

### The Drawing in More Details[edit]

We must start by choice of a scale which we apply for both the window and the landscape, namely by assigning a distance *gg* to the width *ww* (in pixels) of the window (or the picture). Then the width of a pixel is *hh = gg/ww*, and in the coordinate system in the window having the centre as origo, the line *i* pixels from the left border has abscissa *xs = -gg/2 + i×hh*.

The landscape is seen from a point on the *z*-axis having *z*-coordinate *z0*, along a line *lc* in the direction of the (positive) *y*-axis which intersects this in a point having ordinate *yc*. The fractal motif is displaced such that this point (0, *yc*) in the base plane becomes the centre of the fractal motif: if the real centre of the fractal motif is (*x1*, *y1*), we add (*x1*, *y1*) to the coordinate set in the *x-y*-system when we calculate the height and the slope.

The line (in the *y-z*-plane) from *z0* orthogonal to *lc*, intersects the *y*-axis in a point having *y*-coordinate -*yv* (*yv* positive), this point is the *vanishing point* (seeming infinitely far away from the observer). We let *d* (= *yc+yv*) be the distance from the vanishing point to the base point *yc*. If *m* is the distance *lc* (from the observer to the base point) divided by the distance from the observer to the window, the vertical line in the window having abscissa *xs*, corresponds to the line in the base plane going through the vanishing point (0, -*yv*) and the point (*m×xs*, *yc*). And the point on this line having ordinate *y*, has abscissa *m×xs×(d + y - yc)/d*.

Now we choose a vertical line in the window (lying *i* pixels from the left and thus having abscissa *xs = -gg/2 + i×hh)*, and we will colour this line by going along the corresponding line in the base plane from the distant towards the near. Assume that we on this line have reached the point having ordinate *y*. This point has abscissa *m×xs×(d + y - yc)/d*, and we shall calculate the height *z* and the slope *s* of the surface at the point having abscissa *x1 + m×xs×(d + y - yc)/d* and ordinate *y1 + y - yc*. In the *y-z*-plane we have the line segment *lz* from the observer (0, *z0*) to (*y*, *z*). The pixel in the window to be coloured (lying *i* pixels from the left), lies *j* pixels from the top, where *j* is the integral part of the number *wh/2 - wj×tan(acz)*, here *wh* is the height of the window (in pixels), *wj* is the distance from the observer to the window also measured in pixels, and *acz* is the angle from *lc* to *lz*.

After this pixel have been coloured, we must estimate the ordinate *dy* of step we shall go forward (in the direction of the negative *y*-axis) in order to colour the next (adjacent) pixel (above or below). In the *y-z*-plane we have the line segment *ly* from the observer (0, *z0*) to (*y*, 0). We let *ay* be the angle from the (negative) *z*-axis to *ly* and let *ayz* be the angle from *ly* to *lz*. If we set

- ,

*dy* is given by

- ,

that is, the new *y* is *y - dy*.

As this is only an estimation (found by differential calculus), we must arrange the program so that we can multiply the steps *dy* by a factor *r* < 1.

The drawing of the vertical line in the window is finished when the last pixel is drawn (number *wh* from the top) *and* when the new *y* is smaller than a certain *y* value depending on the situation of the lower border of the window, on the visual angle and on whether the landscape is turned upwards or downwards (when the surface is below the base plane and the visual angle is small, this *y* value can lie rather far behind the lower border of the window).

### Gaps Between the Iteration Bands[edit]

There is a circumstance which can make it necessary to move forward in smaller steps, namely the tendency for gaps to develop between iteration bands, especially if a largish power appears in the formula. At the moving towards the boundary, the value of the distance function becomes smaller and smaller, but at the curves where the iteration number is increased by 1, there is a tendency towards that the calculated distance is a little smaller than it should be. The reason is, that the iteration number used in the calculation of the distance estimation must be very large, and this presupposes that the bail out radius is very small (- or very large for iteration towards infinity), but *if* the bail out radius is as small as it ought to be, the colouring between the iteration bands becomes unclean, because the calculation of the slope is uncertain - in the same way as a fractal picture always becomes unclean when we zoom in sufficiently many times: the precision of the computer is no more enough.

### Interpolation[edit]

We can solve the problem with gaps between the iteration bands by applying interpolation: if (in the downward drawing, that is, the drawing of the visual side of the surface) the next pixel drawn is not the pixel next below, we can fill the gap by applying interpolation of the colour values. With this technique we can always produce a picture which is without perceptible faults. Furthermore, the technique means that if we let the reducing factor *r* be larger than 1, we can draw a picture which is good enough for choice of motif and colouring very fast (faster than usual fractal pictures, because the fine fractal pattern is lesser discernible).

### Drawing Pixel for Pixel[edit]

The above drawing method is rather effective because we estimate beforehand the situation of the next pixel to be drawn. However, every time something grows up and hide the previous drawn, pixels are drawn again. Furthermore, the irregular way of drawing means that a well working program can be rather complicated (interpolation and calculation of the place in the landscape where to start at the top and stop at the bottom). It is possible to make a simpler program where the picture is drawn regularly from pixel to pixel, implying that each pixel is coloured only one time, but then several calculations are necessary for each pixel. For a given pixel on the screen we go in steps along the line from the observer through this pixel, and we stop when the calculations show that we are below the surface. In principle we could let the steps have one and the same size, but then this size had to be very small and the number of calculations would consequently be very large. Fortunately we have a tool by which we can adjust the steps so that they at first are rather large and then become smaller in the right rate, namely the distance estimation by which the landscape is constructed. But this method presupposes (or rather, works best) when the landscape is turned downwards, that is, formed below instead of above the base plane, because we then can start the stepwise approximation at the point where the line from the observer intersects the base plane and because we can let (the horizontal extent of) all the steps be ruled by the distance estimation.

From the point where the line from the observer intersects the base plane, we go successively forward in steps whose projection on the base plane is half of the estimated distance, for instance. At each step we calculate the height of the step point (on the line) and the height of the surface (below or above this point), and continue as long as the first is smaller than the later. When this is no more the case, we are below the surface, and then we must go backwards and possibly again forwards. Also these steps must be ruled by the distance estimation, because they must be smaller near the boundary. We can let step be *e×d×dist*, where *dist* is the distance estimation and *e* = ±1 for the step point above/below the surface, and where *d* is a factor which is at first fixed to a given small number (e.g. 0.5) and which is divided by 2 every time *e* alters sign. We perform the stepwise approximation until the difference between the two heights is smaller than a given smal number, *or* until the maximum iteration number or the boundary is reached, or the number of performed operations is larger than a given large number in order to ensure that the procedure stops. If the found point on the surface corresponds to the complex number *z* (in the base plane), we calculate the height of the surface at two points very near *z* in the *x*- and *y*-direction, in order to find the slope of the surface.

### Shade effect[edit]

We can (as the pictures below show) get the landscape to look more realistic by drawing shades (in the case of natural light or light not coming from the observer): a point on the surface is in shade, and thus made darker, if the line from the point in the direction of the light source has a point below the surface. The method is most profitable in the case of a turned downwards landscape, but even in this case it can be necessary to perform calculations for points outside the visible part of the landscape (unless the light source is above the visible part of the landscape):