]> git.itanic.dy.fi Git - mandelbrot/blobdiff - mandelbrot.c
Fix broken aspect ratio calculation
[mandelbrot] / mandelbrot.c
index 926b6af0a827be7f7b3ed99db094c35bf2d0a27f..9ca242101ae1bad4a2f98aa5e89387dee82f36f0 100644 (file)
@@ -6,10 +6,12 @@
 
 struct context {
        struct SDL_Surface *screen;
-       double origo_x, origo_y;
-       int motion_x, motion_y;
-       double zoom;
+       long double origo_x, origo_y;
+       int motion_x, motion_y;         /* mouse motion */
+       int mx, my;                     /* mouse position */
+       long double zoom;
        int scroll_enabled;
+       int zooms;
 };
 
 static void putpixel(struct SDL_Surface *screen, const int x, const int y,
@@ -26,9 +28,9 @@ static void putpixel(struct SDL_Surface *screen, const int x, const int y,
 
 #define MAX_ITERATION 1000
 
-int get_mandelbrot_iterations(double x0, double y0)
+int get_mandelbrot_iterations(long double x0, long double y0)
 {
-       double x = 0, y = 0, xtemp;
+       long double x = 0, y = 0, xtemp;
        int iteration = 0;
 
        while ((x * x + y * y < 2 * 2) && iteration < MAX_ITERATION) {
@@ -43,18 +45,16 @@ int get_mandelbrot_iterations(double x0, double y0)
        return iteration;
 }
 
-int draw_mandelbrot(struct SDL_Surface *screen, double x1, double x2,
-               double y1, double y2)
+int draw_mandelbrot(struct SDL_Surface *screen, long double x1, long double x2,
+               long double y1, long double y2)
 {
-       double x0, y0, xlen, ylen, xstep, ystep;
+       long double x0, y0, xlen, ylen, xstep, ystep;
        int iteration, xs, ys;
 
-       printf("Drawing area (%f, %f)(%f, %f)\n", x1, y1, x2, y2);
-
        xlen = x2 - x1;
        ylen = y2 - y1;
-       xstep = xlen / (double)screen->w;
-       ystep = ylen / (double)screen->h;
+       xstep = xlen / (long double)screen->w;
+       ystep = ylen / (long double)screen->h;
 
        y0 = y1;
 #pragma omp parallel for private(xs, ys, x0, y0)
@@ -78,6 +78,8 @@ int draw_mandelbrot(struct SDL_Surface *screen, double x1, double x2,
        return 0;
 }
 
+#define ZOOM_FACTOR    1.5
+
 static int read_events(struct context *ctx)
 {
        SDL_Event event;
@@ -112,10 +114,10 @@ static int read_events(struct context *ctx)
                        break;
                case SDL_MOUSEBUTTONDOWN:
                        if (event.button.button == 4) {
-                               ctx->zoom *= 1.5;
-                               exit++;
+                               ctx->zooms++;
+                               delayed_exit++;
                        } else if (event.button.button == 5) {
-                               ctx->zoom /= 1.5;
+                               ctx->zooms--;
                                delayed_exit++;
                        } else {
                                ctx->scroll_enabled = 1;
@@ -123,9 +125,11 @@ static int read_events(struct context *ctx)
                        break;
                case SDL_MOUSEBUTTONUP:
                        ctx->scroll_enabled = 0;
-                       exit++;
+                       delayed_exit++;
                        break;
                case SDL_MOUSEMOTION:
+                       ctx->mx = event.motion.x;
+                       ctx->my = event.motion.y;
                        if (!ctx->scroll_enabled)
                                break;
 
@@ -154,19 +158,48 @@ quit:
 
 static void loop(struct context *ctx)
 {
-       double aspect_ratio;
+       long double aspect_ratio;
+       long double x1, x2, y1, y2;
+       int last_zoom;
 
        do {
-               aspect_ratio = ctx->screen->w / ctx->screen->h;
+               aspect_ratio = ctx->screen->w / (long double)ctx->screen->h;
                ctx->origo_x += ctx->motion_x / ctx->zoom / ctx->screen->w;
                ctx->origo_y += ctx->motion_y / ctx->zoom / ctx->screen->h;
                ctx->motion_x = ctx->motion_y = 0;
 
-               draw_mandelbrot(ctx->screen,
-                               ctx->origo_x - aspect_ratio / ctx->zoom,
-                               ctx->origo_x + aspect_ratio / ctx->zoom,
-                               ctx->origo_y - 1 / ctx->zoom,
-                               ctx->origo_y + 1 / ctx->zoom);
+               if (ctx->zooms != last_zoom) {
+                       int dx, dy;
+
+                       dx = ctx->mx - ctx->screen->w / 2;
+                       dy = ctx->my - ctx->screen->h / 2;
+
+                       if (ctx->zooms > last_zoom) {
+                               ctx->zoom *= ZOOM_FACTOR;
+                               ctx->origo_x += dx / ctx->zoom /
+                                       (long double) ctx->screen->w;
+                               ctx->origo_y += dy / ctx->zoom /
+                                       (long double) ctx->screen->h;
+                       } else {
+                               ctx->origo_x -= dx / ctx->zoom /
+                                       (long double) ctx->screen->w;
+                               ctx->origo_y -= dy / ctx->zoom /
+                                       (long double) ctx->screen->h;
+                               ctx->zoom /= ZOOM_FACTOR;
+                       }
+
+                       last_zoom = ctx->zooms;
+               }
+
+               x1 = ctx->origo_x - aspect_ratio / ctx->zoom;
+               x2 = ctx->origo_x + aspect_ratio / ctx->zoom;
+               y1 = ctx->origo_y - 1 / ctx->zoom;
+               y2 = ctx->origo_y + 1 / ctx->zoom;
+
+               printf("Drawing area (%LF, %LF)(%LF, %LF), zoom %d\n",
+                       x1, y1, x2, y2, ctx->zooms);
+
+               draw_mandelbrot(ctx->screen, x1, x2, y1, y2);
        } while (!read_events(ctx));
 }