1

I'm working on a fractal graphic. I need to be able to zoom in on a specific point.

Here's what I've got so far. If you keep the mouse in the same position for the whole zoom, it works. But if you zoom part of the way then move the mouse to a new position and try to zoom some more from there, it starts jumping all over.

scale_change = zoom * ((button == SCROLL_DOWN) ? ZOOM_INC : -ZOOM_INC);
zoom += scale_change;
center->x -= (mouse->x - (IMG_SIZE / 2)) * scale_change;
center->y -= (mouse->y - (IMG_SIZE / 2)) * scale_change;

I assume some part of it is over-simplistic? There's some variable I'm not accounting for? It does work if you don't move the mouse, though.

motaylormo
  • 49
  • 1
  • 6
  • 1
    You're confusing your co-ordinate systems. Remember that when you are already in a zoomed view, then the mouse position also references zoomed co-ordinates. You first need to find which actual point in the fractal the mouse is currently hovering over. You then need to determine what the new center point will be _after_ zooming in on that point. – paddy Feb 22 '19 at 04:07
  • With that in mind, I tried: `x -= IMG_SIZE / 2; y -= IMG_SIZE / 2; center->x -= (x * new_zoom) - (x * old_zoom); center->y -= (y * new_zoom) - (y * old_zoom);` which **also** works only as long as you don't move your mouse. – motaylormo Feb 23 '19 at 00:21
  • Possible duplicate of [Zooming graphics based on current mouse position](https://stackoverflow.com/questions/37262282/zooming-graphics-based-on-current-mouse-position) – Spektre Mar 12 '19 at 10:54

1 Answers1

1

The best approach is probably to use a transform matrix to both scale the image and find out what point in the scaled image your mouse is over so you can transform based on that point.

I know you're working in C, but I created an example in js, because it allows me to demonstrate working code easier. Click on the image and use Z and X to zoom in and out. https://jsfiddle.net/7ekqg8cb/

Most of the code is implementing matrix multiplication, matrix inversion and matrix point transformation. The important part is:

var scaledMouse = transformPoint(mouse);

matrixMultiplication([1, 0, scaledMouse.x,
                      0, 1, scaledMouse.y,
                      0, 0, 1]);
var scale = 1.2;
if (direction) {
    matrixMultiplication([scale, 0, 0,
                          0, scale, 0,
                          0, 0, 1]);
}
else {
    matrixMultiplication([1/scale, 0, 0,
                          0, 1/scale, 0,
                          0, 0, 1]);
}

matrixMultiplication([1, 0, -scaledMouse.x,
                      0, 1, -scaledMouse.y,
                      0, 0, 1]);

transformPoint uses the inverse of the transform matrix to find out where the mouse is relative to the transformed image. Then the transform matrix is translated, scaled and translated back, to scale the transform matrix around that point.

aptriangle
  • 1,395
  • 1
  • 9
  • 11