I've been working on a C Mandelbrot set program for the past few days and I managed to make it work fine, however, my end goal is to be able to smoothly zoom in the set with my mouse and that's something I haven't yet been able to do yet so I might need a bit of help !
Here's part of my code (well, the full mandelbrot function) :
//removed to free space
Here's a picture of the output : (Sorry, it's not very pretty, colors were not my priority but I'll be sure to work on them as soon as I figure out the zoom !)
What I want to be able to do :
(already have a function that gets mouse's position and button being pressed)
Thanks a lot for your help !
The visible area is a rectangle defined by (Re.min, Im.min)
and (Re.max, Im.max)
. When you click on a particular point, you can map the mouse position to a point (mouseRe, mouseIm)
by using the same mapping as you use when rendering:
double mouseRe = (double)mouse_x / (WIN_L / (e->Re.max - e->Re.min)) + e->Re.min;
double mouseIm = (double)mouse_y / (WIN_H / (e->Im.max - e->Im.min)) + e->Im.min;
To zoom in, imagine drawing a line from the (mouseRe, mouseIm)
zooming centerpoint to each of the corners of the visible area, forming a lopsided X. Based on the zoom amount, find 4 new points a certain fraction of the distance along these lines, these points will give you your new rectangle. For example, if you are zooming in by a factor of 3, find a point 1/3rd of the way from the centerpoint to the corners. This will produce a new rectangle with sides 1/3rd the size of the original and an area 1/9th the size.
To do this you can define a simple interpolation function:
double interpolate(double start, double end, double interpolation)
{
return start + ((end - start) * interpolation);
}
Then use the function to find your new points:
void applyZoom(t_fractal* e, double mouseRe, double mouseIm, double zoomFactor)
{
double interpolation = 1.0 / zoomFactor;
e->Re.min = interpolate(mouseRe, e->Re.min, interpolation);
e->Im.min = interpolate(mouseIm, e->Im.min, interpolation);
e->Re.max = interpolate(mouseRe, e->Re.max, interpolation);
e->Im.max = interpolate(mouseIm, e->Im.max, interpolation);
}
Based on my description, you might think you need to find 8 values (4 points for the 4 legs of the X with 2 dimension each) but in practise there are only 4 unique values because each of the sides is axis aligned.
For a smooth zoom, call it with a zoom factor of a little over 1.0 e.g. 1.01. To zoom out, pass the inverse e.g. 1.0 / 1.01.
Alternatively, if you want the center of the view to jump to a certain position when you click the mouse, calculate mouseRe
and mouseIm
as above and then offset the corners of the view rectangle by the difference between these values and the center of the view rectangle. You could store these values at the time the mouse button was first pressed down, and use them to zoom in as long as it is held.