Domanda

Part of the application I'm writing requires that I handle multi-touch interaction to handle things like panning and zooming. After messing around with ways to implement it, it got me thinking... is there a way to implement panning and zooming with a constant amount of memory, regardless of how many touches there are on the screen?

How will zoom and pan function?

Input is in the form of one changed touch. Every time a touch is moved, the zoom and pan must be corrected. The information provided with this event is the newPosition and the oldPosition of the touch that moved.

...additionally, a touch can be added or removed. In that event, there is just a position.

For panning, the screen will pan just as much as the average change in position of all the touches. So, if one touch moves by (15,5), and there are 5 touches (4 of which stayed put), then the screen will pan by (3,1)

For zooming, the screen will zoom proportional to the change in average distance of each touch from the center (the average position of all the touches).

What have I tried?

So far, I've decided that I need to keep track of the numberOfTouches, the center, or average position of all the touches, and the averageDistance from the center.

Panning is easy. Whenever a touch moves by changeInPosition, pan by changeInPosition/numberOfTouches. Easy.

I haven't figured out zooming. I think I need to keep track of the center, so I know what point to zoom in on. I also think I need to keep track of the averageDistance, so I know how much to zoom. But... I can't figure out how to maintain averageDistance. It's easiy to keep track of if the center doesn't move, but how do I find the new averageDistance if the center does move?

So, the question is, given that one input, that one changed point, that one new touch, or that one removed touch... is there a way, without storing that touch in an array (AKA: with constant memory), to implement zoom and pan?

Am I on the right track? Can it be done with constant memory? Or must all the touches be tracked?

È stato utile?

Soluzione

Just to give you a counter example.

Let's assume such a method exists with constant memory; and you got a series of 100 touches, all of them at (10,10) with center at (15,15) therefore the average distance from the center is 5. You now execute a pan such that the new center is (10,10). Actually, if you had the whole history of touches, the new average distance from the new center would be now 0, but because you don't have the touch history you have no way how to update the average distance, it could be anything. Maybe the previous 100 touches where equally distributed on your space, or all in one half, or as in the example I chose, all at the same location.

So I would say there is no constant memory approach. What you can do is maintain a history window of the last N touches and recalculate the average distance for them each time. You can keep the zoom amount at the first touch in history (N) and apply the rest of the touches' zoom. On each new touch, update the initial zoom amount to the next touch (N-1), and discard the oldest touch (N) before inserting the new touch(1).

Altri suggerimenti

Not sure if Pythagoras would agree with me, but maybe this will spark a decent answer:

center.x = 0
center.y = 0
for each touch position 'p':
   center.x = center.x + p.x
   center.y = center.y + p.y
averageDistance = sqrt((center.x * center.x) + (center.y * center.y))
averageDistance = averageDistance / (2 * (NumberOfTouches - 1))
center.x = center.x / numberOfTouches
center.y = center.y / numberOfTouches

BTW, if you allow center to move while zooming this will cause a pan-and-zoom.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top