Calculate coordinates after pinch-to-zoom gesture

I need to find position (left-upper corner) of a content rectangle in screen coordinates after pinch-to-zoom gesture. Here are the way of my thinking:

The gesture has two points: A (start of the gesture) and B (end of the gesture). Let C is a point of the content rectangle, which matches A at the start of the gesture and matches B at the end of the gesture.

Then the left-upper corner P (The y-axis is pointing down) of the content rectangle is just translated by the vector AB (like it does C). So P' is:

ABx = Bx - Ax
ABy = By - Ay
P'x = Px + ABx
P'y = Py + ABy


Problem comes when scale factor of content rectangle changes during the gesture (C is also a center of enlargement). As we are just dragging C, from A to B, we can add vector AB after applying new scale factor k'. So we have:

P'x = (Px - Ax)*k'/k + Ax
P'y = (Py - Ay)*k'/k + Ay


And then we take care of our AB translation, and finally get:

P"x = (Px - Ax)*k'/k + Ax + ABx
P"y = (Py - Ay)*k'/k + Ay + ABy
P"x = (Px - Ax)*k'/k + Bx
P"y = (Py - Ay)*k'/k + By


This is how I get close but wrong result. Please help me to find correct P" coordinates!

Result animation

EDIT:

A is the middle point between two fingers at the start of gesture, and B middle point between two fingers at the end of gesture.

Distance between fingers s is used to calculate scale factor for time delta:

k" = s'/s


Expected result

EDIT 2:

Positions of fingers are hidden by OS' API. Gesture detector provides current focal point (obviously center of enlargement), scale factor given for some portion of time since the last time detector triggered (detector triggered several times during gesture), various spans (for current and previous finger positions) which are used internally to calculate scale factor. Number of fingers may differ (>2) or it can be stylus gesture. So all headache determining scale factor handled by the API.

I also need to clarify the way I draw content on the screen. There are Px, Py and k to set content position on the screen. So I enlarge content rectangle in (0, 0) by k, then translate it by Px and Py:

(0, 0, width, height) // content rectangle
(0, 0, width*k, height*k) // enlarged content rectangle
(Px, Py, width*k + Px, height*k + Py) // final rectangle


k', value used in formulas above, has the same meaning as it has k (but instead it determinates new position), it is calculated with:

k' = k*k"0*...*k"n,


where k"0, ..., k"n scale factors provided by the gesture detector for a some time period during the gesture. K" itself calculated with current span s' and previous span s, which due to documentation is:

Span is the average distance between each of the pointers forming the gesture in progress through the focal point.

And due to the sources k" calculated like:

k" = s'/s


So that's why I do k'/k here:

P" = (P - A)*k'/k + B

• You say the gesture has two points, but when I imagine pinch-to-zoom, I see four points: the two points where I put my fingers at the beginning, and the two points where my fingers end up. Which two points do you mean? Mar 20, 2022 at 14:31
• Points A and B are center between all fingers. Mar 20, 2022 at 14:38
• Yes. After EDIT 2 you seem to have the right equation (the last equation) for the position of a point $P$ after shifting/scaling. After a single trigger, if the original center is $A$ and the final center is $B$ and the scale factor is $k$ then $P' = B + k (P - A)$ which is what you got. Mar 21, 2022 at 10:49

From what I understand, you place two fingers on the screen, one finger at point $$A$$ and the other finger at point $$B$$. And then you drag both fingers, so that now the first finger is at point $$A'$$ and the second finger is at point $$B'$$. Points $$A$$ and $$B$$ determine a rectangle. So does the pair $$A'$$ and $$B'$$. So now you want to map the rectangle specified by the corner points $$A$$ and $$B$$ to the rectangle specified by the corner points $$A'$$ and $$B'$$. The obstacle here is that both rectangles must have equal aspect ratio, defined as

$$\alpha = \dfrac{ | A_y - B_y | }{ | A_x - B_x | }$$

which does not necessarily match the aspect ratio specified by $$A'$$, and $$B'$$ which

$$\alpha' =\dfrac{ | A'_y - B'_y | }{ | A'_x - B'_x | }$$

So what do we do in the case $$\alpha \ne \alpha'$$ ? We override the aspect ratio of the second rectangle to make its aspect ratio equal to $$\alpha$$ as well.

To do that, we can keep the horizontal base of the second rectangle as is, and modify its upper side, thus modifying $$B'_y$$. In other words, we're fixing $$A'_x$$, $$A'_y$$, and calculating a new point $$B''$$, with $$B''_x = B'_x$$ and $$B''_y$$ we calculate from the following equation

$$| A'_y - B''_y | = \alpha | A'_x - B''_x |$$

Now both rectangles have the same aspect ratio. So we can calculate the scale factor $$k$$ as follows

$$k = \dfrac{ |A'_x - B''_x |}{ |A_x - B_x |} = \dfrac{|A'_y - B''_y|}{|A_y - B_y|}$$

What remains is very simple, point $$A$$ is mapped to $$A'$$ and point $$B$$ is mapped to $$B''$$; therefore, point P(x, y) anywhere on the plane is mapped to

$$P' = (x', y') = A' + k (P - A )$$

i.e.

$$x' = A'_x + k (x - A_x)$$

$$y' = A'_y + k (y - A_y)$$

• A is the middle point between two fingers at the start of gesture, and B middle point between two fingers at the end of gesture. I am sorry for misleading Mar 20, 2022 at 15:25
• But this setup is not correct. You don't care about the center between the fingers. What you should care about is the position of the fingers themselves before and after the movement. Mar 20, 2022 at 16:19
• Finger positions just are unknown. Anyway formulas look pretty familiar. And it feels like any point can be used as long as scale factor is correctly calculated for that point. I added further explanations with the EDIT 2. Mar 21, 2022 at 5:54