Detecting Special touch on the iphone - cocoa-touch

I was asking myself if there are examples online which covers how you can for instance detect shapes in touch gestures.
for example a rectangle or a circle (or more complex a heart .. )
or determine the speed of swiping (over time ( like i'm swiping my iphone against 50mph ))

For very simple gestures (horizontal vs. vertical swipe), calculate the difference in x and y between two touches.
dy = abs(y2 - y1)
dx = abs(x2 - x1)
f = dy/dx
An f close to zero is a horizontal swipe. An f close to 1 is a diagonal swipe. And a very large f is a vertical swipe (keep in mind that dx could be zero, so the above won't yield valid results for all x and y).
If you're interested in speed, pythagoras can help. The length of the distance travelled between two touches is:
l = sqrt(dx*dx + dy*dy)
If the touches happened at times t1 and t2, the speed is:
tdiff = abs(t2 - t1)
s = l/tdiff
It's up to you to determine which value of s you interpret as fast or slow.
You can extend this approach for more complex figures, e.g. your square shape could be a horizontal/vertical/horizontal/vertical swipe with start/end points where the previous swipe stopped.
For more complex figures, it's probably better to work with an idealized shape. One could consider a polygon shape as the ideal, and check if a range of touches
don't have too high a distance to their closest point on the pologyon's outline, and
all touches follow the same direction along the polygon's outline.
You can refine things further from there.

There does exist other methods for detecting non-simple touches on a touchscreen. Check out the $1 unistroke gesture recognizer at the University of Washington. http://depts.washington.edu/aimgroup/proj/dollar/
It basically works like this:
Resample the recorded path into a fixed number of points that are evenly spaced along the path
Rotating the path so that the first point is directly to the right of the path’s center of mass
Scaling the path (non-uniformly) to a fixed height and width
For each reference path, calculating the average distance for the corresponding points in the input path. The path with the lowest average point distance is the match.
What’s great is that the output of steps 1-3 is a reference path that can be added to the array of known gestures. This makes it extremely easy to give your application gesture support and create your own set of custom gestures, as you see fit.
This has been ported to iOS by Adam Preble, repo on github:
http://github.com/preble/GLGestureRecognizer

Related

How could I make an "iPod Wheel" type control on iPhone?

I want to create a sort of "iPod Wheel" control in a Swift project that I'm doing. I've got everything drawn out, but not it's time to actually make this thing work.
What would be the best way to recognize "spinning" so to speak, or to describe that more clearly, when the user is actively pressing the wheel and spinning his/her thumb around the wheel in a clockwise or counter-clockwise direction.
I will no doubt want to use touchesBegan/touchesMoved/touchesEnded. What's the best way to figure out spinning though?
I'm thinking
a) determine in touchesMoved if the users touch is within circle, by determining the radius from the center point. Center point and radius are easily obtainable. Using these however, how can I determine the outer edge of the circle/wheel... to know whether the user is within the actually circle (their touch could still be in the view, but outside the actual wheel portion)
b) Determine the current angle and how it has changed the previous angle. By that I mean... I would use the center point of the circle as one point, and the users current touch as the second point. This gives me my vector. I would also have a baseline angle. Likely center point to 12 c'clock. I would compare the two vectors (I already have a VectorMath class for this from something else I'm doing) and see my angle is 0. If the users touch were at 3 oclock, and I compared it to our baseline angle... I would see the angle is 90 degrees. I would continually calculate the angle, and perhaps every 5 degrees of change... would warrant a change in the controls output (depending on desired sensitivity).
Does this seem like the best way to do this? I think this would be an ideal way, but am still not sure on how to calculate the circles outer edge, and determine if a users touch is within it.
You are on the right track. I think approach b) will work.
Remember the starting position of the finger at the touchesBegan
event.
Imagine a line from the finger position to the middle of the button
circle.
For the touchesMoved event, again, imagine a virtual line from the
new position to the center of the circle.
Using the formula from
http://mathworld.wolfram.com/Line-LineAngle.html (or some code) you can determine
the angle between the two lines. If it's a negative angle the user
is turning the wheel counter-clockwise, otherwise it's clockwise.
To determine if the touch event was inside the ring, calculate the distance from the center of the circle to the point of touch. It should be between the minimum and the maximum distance (inner circle and outer circle radius). Calculating the distance between to two points is explained at https://www.mathsisfun.com/algebra/distance-2-points.html
I think you're almost there, although I'd do something slightly different on your point b.
If you think about it, when you start "spinning" on your iPod, you don't need to start from a precise position, you start spinning from "where you started", therefore I wouldn't set my "baseline angle" at π/2, I'd set my baseline (or 0°) angle at the point the user taps for the first time, and starting from then, I'd count the offset angles, clockwise and counterclockwise.
I don't think there would be much difference, except maybe from some calculations you'll do on the angles, on the two approaches, practically speaking; it just makes more sense imho to start counting from the first input rater than setting a baseline to π/2 and counting the first angle.
I am answering in parts.
// Get a position based on the angle
float xPosition = center.x + (radiusX * sinf(angleInRadians)) - (CGRectGetWidth([cell frame]) / 2);
float yPosition = center.y + (radiusY * cosf(angleInRadians)) - (CGRectGetHeight([cell frame]) / 2);
float scale = 0.75f + 0.25f * (cosf(angleInRadians) + 1.0);
next
[cell setTransform:CGAffineTransformScale(CGAffineTransformMakeTranslation(xPosition, yPosition), scale, scale)];
// Tweak alpha using the same system as applied for scale, this
// time with 0.3 the minimum and a semicircle range of 0.5
[cell setAlpha:(0.3f + 0.5f * (cosf(angleInRadians) + 1.0))];
and
- (void)spin:(SpinGestureRecognizer *)recognizer
{
CGFloat angleInRadians = -[recognizer rotation];
CGFloat degrees = 180.0 * angleInRadians / M_PI; // Radians to degrees
[self setCurrentAngle:[self currentAngle] + degrees];
[self setAngle:[self currentAngle]];
}
again check the wheelview.m of photowheel in github.

Finding the co-ordinate on an arc for the next position of an orbitting camera

The best example I can give is located at:
http://www.mathopenref.com/arclength.html
In that Java applet, imagine C is the object to be rotated around and A is the camera. I wish to move the camera to point B, but I do not know how to work out B's co-ordinates. How do you do it? In my case, I know the positions of C and A, and the angle theta to rotate.
I know you can use:
x = Xcentre + radius * sin(theta)
y = Ycentre + radius * cos(theta)
but this fails to take into account the camera current position.
I can't help but feel there's some simple solution I'm missing.
Solved by using the equations listed and just reversing the calculation to derive theta. Then applied a check to ensure 360 degree rotations can be done (else only 180 degrees can).

Change angle of 3 sprites and make it look smooth/realistic

I have 3 sprites that all have the same angle, so I'm just going to say arm sprite.
Arm sprite's angle, at the moment, is equal to one point1 (60,60 but this does not matter)
to another point2, the point where the player thumb pressed.
During the ccTime function I update everything, the angles and stuff. So whenever the user touches a spot on the screen, the angle is immediately changed and the arm's angle is equal to the vector from point1 to point2.
I don't want the angle change to take .016 seconds to complete (ccTime gets called every 1/60'th of a second). What I want is for the angle to increment/decrement faster/slower depending on how far away the new vector is from the current vector. Basically I want the arm to raise/lower at a certain speed, maybe accelerate a bit, depending on the vector.
I've tried many times to make it work, but I'm not getting anywhere. Please help me, rotation can go from 90 degrees straight up to almost 180 degrees straight down (the angles in cocos2d are changed, however, so I had to add 90 here and there).
If you need anymore information, just leave a comment and I'll give you the info asap.
You should set the new angle as a destinationAngle then on your update loop:
//Instead of checking for equality, you might want to check the angle is close enough, e.g. if they are withing 1 degree of each other e.g.(if (abs(destinationAngle - angle) < 1)
if (angle != destinationAngle)
{
//move towards destination
angle += ((destinationAngle - angle) / 10.0f);
}

Objective C Game Geometry question

I'm creating simple game and reached the point where I feel helpless. I was good in geometry but it was long time back in school, now trying to refresh my mind.
Let's say i have iPad screen. Object's xy position at one given point of time and xy position at another point of time stored in 2 variables .
Question:
how to find the third position of the object at the end of the screen being given previous 2 position, considering the object moves in the same direction (line) from point 1 to point 2.
Thanks in advance.
Let us have that v1 and v2 are the vectors representing the two points. Let t0 be the time between the two points. Let t be the current time.
Then our location vector v3 is given by v3 = v1 + (v2 - v1)t/t0
If the object is moving in the same direction and you have an horizontal line, the next position given x and y would be
x+1, y
If the object is moving in the same direction in a vertical line it would be
x, y+1
If the object is moving in a diagonal up-right
x+1,y+1
diagonal down-right
x+1, y+1
diagonal down-left
x-1, y-1
diagonal up-left
x-1, y+1
So something general would be :
newPosition = (x+1,y) //if you wish to move forward to the right, try to handle all
cases
All the cases above work if the object is moving forward, if it is moving backwards just change the + by - . Basically think of the object as moving in a cartesian coordinate system, where x is horizontal and y is vertical.
I think you can get the idea out of this three cases ;)

Calculating collision for a moving circle, without overlapping the boundaries

Let's say I have circle bouncing around inside a rectangular area. At some point this circle will collide with one of the surfaces of the rectangle and reflect back. The usual way I'd do this would be to let the circle overlap that boundary and then reflect the velocity vector. The fact that the circle actually overlaps the boundary isn't usually a problem, nor really noticeable at low velocity. At high velocity it becomes quite clear that the circle is doing something it shouldn't.
What I'd like to do is to programmatically take reflection into account and place the circle at it's proper position before displaying it on the screen. This means that I have to calculate the point where it hits the boundary between it's current position and it's future position -- rather than calculating it's new position and then checking if it has hit the boundary.
This is a little bit more complicated than the usual circle/rectangle collision problem. I have a vague idea of how I should do it -- basically create a bounding rectangle between the current position and the new position, which brings up a slew of problems of it's own (Since the rectangle is rotated according to the direction of the circle's velocity). However, I'm thinking that this is a common problem, and that a common solution already exists.
Is there a common solution to this kind of problem? Perhaps some basic theories which I should look into?
Since you just have a circle and a rectangle, it's actually pretty simple. A circle of radius r bouncing around inside a rectangle of dimensions w, h can be treated the same as a point p at the circle's center, inside a rectangle (w-r), (h-r).
Now position update becomes simple. Given your point at position x, y and a per-frame velocity of dx, dy, the updated position is x+dx, y+dy - except when you cross a boundary. If, say, you end up with x+dx > W (letting W = w-r), then you do the following:
crossover = (x+dx) - W // this is how far "past" the edge your ball went
x = W - crossover // so you bring it back the same amount on the correct side
dx = -dx // and flip the velocity to the opposite direction
And similarly for y. You'll have to set up a similar (reflected) check for the opposite boundaries in each dimension.
At each step, you can calculate the projected/expected position of the circle for the next frame.
If this lies outside the rectangle, then you can then use the distance from the old circle position to the rectangle's edge and the amount "past" the rectangle's edge that the next position lies at (the interpenetration) to linearly interpolate and determine the precise time when the circle "hits" the rectangle edge.
For example, if the circle is 10 pixels away from the rectangle's edge, then is predicted to move to 5 pixels beyond it, you know that for 2/3rds of the timestep (10/15ths) it moves on its orginal path, then is reflected and continues on its new path for the remaining 1/3rd of the timestep (5/15ths). By calculating these two parts of the motion and "adding" the translations together, you can find the correct new position.
(Of course, it gets more complicated if you hit near a corner, as there may be several collisions during the timestep, off different edges. And if you have more than one circle moving, things get a lot more complex. But that's where you can start for the case you've asked about)
Reflection across a rectangular boundary is incredibly simple. Just take the amount that the object passed the boundary and subtract it from the boundary position. If the position without reflecting would be (-0.8,-0.2) for example and the upper left corner is at (0,0), the reflected position would be (0.8,0.2).