determine angle between two points on a circle with respect to center - iphone

I have a Ring(width 25px) as UIView. When User selects any where on the ring, I want to Calculate the Angle between the the Points Selected on a fixed point on the circle considering the Center of Circle.
I have found few examples but they are not taking center into consideration.
What is the Optimum way to do this ?

You'll have to handle the code yourself (I'm a Java developer), but the simplest way to get the angle between two points on a circle (measured against its center) is to recall the geometry of the situation. The triangle formed by any two points on the circumference of a circle and the circle's center is necessarily isosceles.
An isosceles triangle, recall, has (at least) two sides of the same length -- the radial segments to your two points. Bisecting the angle results in a radial segment which is perpendicular to and bisects the line connecting the two points. This forms a pair of right triangles, with the radius as the hypotenuse, and half the distance between the two points as the 'opposite' side.
Moving the factor of two to the denominator and recognizing what twice the radius is, simply calculate the distance between the two points (on the circumference), and divide it by the diameter. The value you get is the sine of the half-angle (you desire the whole angle). Take the arcsine, and you'll have half your angle:
θ/2 = sin-1(d/D)
With d as the distance between the two points, and D as the diameter of the circle. Since the diameter is given, and the distance between the two points is simple to calculate, getting to this point should be easy, and then you just need to double the value calculated to get the whole angle between the two points.

This might help you, I have used same thing in one of my projects.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
beginPoint = [[[event allTouches] anyObject] locationInView:self];
currentAngle = 0.0f;
centerPoint = self.center;
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
endPoint = [[[event allTouches] anyObject] locationInView:self];
float fromAngle = atan2(beginPoint.y - self.center.y, beginPoint.x - self.center.x);
float toAngle = atan2(endPoint.y - self.center.y, endPoint.x - self.center.x);
float newAngle = [self wrapd:currentAngle + (toAngle - fromAngle) min:0 max:2 * 3.14];
currentAngle = newAngle;
CGAffineTransform cgaRotate = CGAffineTransformMakeRotation(newAngle);
[self setTransform:cgaRotate];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
endPoint = [[[event allTouches] anyObject] locationInView:self];
float fromAngle = atan2(beginPoint.y - self.center.y, beginPoint.x - self.center.x);
float toAngle = atan2(endPoint.y - self.center.y, endPoint.x - self.center.x);
float newAngle = [self wrapd:currentAngle + (toAngle - fromAngle) min:0 max:2 * 3.14];
currentAngle = newAngle;
}
- (double) wrapd:(double)_val min:(double)_min max:(double)_max {
if(_val < _min) return _max - (_min - _val);
if(_val > _max) return _val - _max; /*_min - (_max - _val)*/;
return _val;
}

As we know
((center.x + radius*cos(theta)) ,(center.y + radius*sin(theta))) ~ (X,Y)
where (X,Y) belongs to the any circumference point
so you can calculate the Angle i.e. theta for any Circumference point as:
X= center.x + radius*cos(theta)
cos(theta) = (X - center.x)/radius .......... eqn-1
similarly
Y= center.y + radius*sin(theta)
sin(theta) = (Y - center.y)/radius .......... eqn-2
By dividing eqn-2 by eqn-1 we have
tan(theta) = (Y - center.y)/(X - center.x) -----------------Final Equation

Related

Figure out angle with right triangle in objective-c

I'm trying to calculate the angle of the click i am making in relationship to the middle of the screen. But maybe i am confused on how atanf is suppsoed to work.
CGPoint pt = [self convertTouchToNodeSpace:[touches anyObject]];
float adj = pt.x - 512;
float opposite = pt.y - 384;
float combined = opposite / adj;
float tan = atanf(combined);
but when i try to NSLog Tan, i just get some giant number like 0.1253649
thoughts?
The right way to convert vector to angle is through atan2 function:
float angle = atan2f (pt.y - 384, pt.x - 512) * 180 / PI;
PS: Are you using cocos2d engine? It has ccpToAngle(...) function.

How do I keep track of the total number of complete rotations of an image in an iOS app?

I am working on an app that has a rotating image (the user tapps and drags and the image rotates in a circle tracking their finger). What I am trying to keep track of is how many times the user makes a complete circle. An additional "hitch" is that I also need to know if the user is circling clockwise vs counter clockwise.
Here is the Code that is rotating the image... Please feel free to request additional information.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchPoint = [touch locationInView:self.view];
long double rotationNumber = atan2(touchPoint.y - originY, touchPoint.x - originX);
totalRotationCount ++;
schedulingWheel.transform = CGAffineTransformMakeRotation(rotationNumber);
offset = (rotationNumber * 100)/14;
dateRibbon.center = CGPointMake(offset, 24);
}
Thanks for the help!
My solution isn't elegant and there might be a cleaner solution I'm missing but this is what I did recently. The trick is to keep track of the angle from the last time touchesMoved: is called. Then, add the delta of your current angle and the stored angel value to your total.
The problem is the "boundaries" that atan2 creates needed ugly code to overcome. Say your lastAngle is 359 and you cross the origin so your next angle is 1. The difference will not be 2 but -358, so whenever you cross that boundary your total will be reset to 0.
Here is what I did:
CGFloat angle = atan2f(center.y - point.y, point.x - center.x);
//Translate to Unit circle
if (angle > 0) {
angle = (M_PI - angle) + M_PI;
} else {
angle = fabsf(angle);
}
CGFloat delta = angle - lastAngle;
//Adjust for boundaries
if (fabsf(delta) > (2*M_PI)-fabsf(delta)) {
BOOL greaterThanZero = (delta > 0);
delta = (2*M_PI)-fabsf(delta);
if (greaterThanZero) {
delta = -1 * delta;
}
}
totalAngle += delta;
lastAngle = angle;
The big/ugly conditional under "Adjust for boundaries" basically just looks to see if there is a shorter angle to get to the new point (So, 2 instead of -258) & assumes that if there is it probably means you crossed that origin and adjusts the delta accordingly.
I translated the Atan2 results so that it represents a full unit circle from 0 to 2π. Bonus side affect, it then accounts for clockwise/counter clockwise movement better than the standard -π to π of Atan2.
To find out what is the total number of the rotations simply sum all the rotation angles in either directions. For clockwise the value of the rotation angle will be positive and for the counter clockwise it will be negative. Then divide it by a pi (~3.14) to get your total number of rotations.
long double rotationNumber = atan2(touchPoint.y - originY, touchPoint.x - originX);
long double totalRotationsAngle += rotationNumber;
Then whenever you want to get the number of full rotations:
double numberOfRotations = floor(totalRotationsAngle/M_PI);

Calculate angle for rotation in Pie Chart

I want to rotate the image around its center point.The problem i am facing is i need to get the angle to calculate in touch moved event (i dont want to use multi touch).I am current using the below code
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
NSArray *allTouches = [touches allObjects];
gestureStartPoint = gestureMovedPoint;//i am getting the gestureStartPoint on touch began event
gestureMovedPoint = [[allTouches objectAtIndex:0] locationInView:[self superview]];
NSLog(#"gestureMovedPoint = %#",NSStringFromCGPoint(gestureMovedPoint));
}
CGFloat previousAngle = [self angleBetweenPoints:gestureStartPoint second11:gestureMovedPoint]; // atan2(gestureMovedPoint.y - gestureStartPoint.y, gestureMovedPoint.x - gestureStartPoint.x) * 180 / M_PI;
CGFloat currentAngle =atan2(self.transform.b, self.transform.a);//atan2(gestureMovedPoint.y - gestureStartPoint.y,gestureMovedPoint.x - gestureStartPoint.x) * 180 / M_PI;
CGFloat angleToRotate = currentAngle - previousAngle;
float xpoint = (((atan2((gestureMovedPoint.x - gestureStartPoint.x) , (gestureMovedPoint.y - gestureStartPoint.y)))*180)/M_PI);
CGAffineTransform transform = CGAffineTransformMakeRotation(angleToRotate-100);
self.transform = transform;
Kindly help me find the solution as i am stuck here and need to complete this application very soon as there is a dead line.
Thanks in advance
Glad I remember triginometry
-(void)degreesToRotateObjectWithPosition:(CGPoint)objPos andTouchPoint:(CGPoint)touchPoint{
float dX = touchPoint.x-objPos.x; // distance along X
float dY = touchPoint.y-objPos.y; // distance along Y
float radians = atan2(dY, dX); // tan = opp / adj
//Now we have to convert radians to degrees:
float degrees = radians*M_PI/360;
return degrees;
}
Once you have your nice method, just do this in the touch event method. (I forgot what it's called...)
CGAffineTransform current = view.transform;
[view setTransform:CGAffineTransformRotate(current, [self degreesTorotateObjectWithPosition:view.frame.origin andTouchPoint:[touch locationInView:parentView]]
//Note: parentView = The view that your object to rotate is sitting in.
This is pretty much all the code that you'll need.The math is right, but I'm not sure about the setTransform stuff. I'm at school writing this in a browser. You should be able to figure it out from here.
Good luck,
Aurum Aquila
Have to think at this. But I will prefer rotating the view with two touches. It will be much simpler.
I did struggle a bit with how to get a touch driven rotation, even more so because I want 100% understanding of the code I am using. So I ended up, after many failed attempts, with this:
- (CGFloat) pointToAngleFromCenter: (CGPoint) point {
// transform point to a self.center'ed origin based coordinate system
point.x = point.x - self.center.x ;
// ditto for y, but compensate for y going downwards to y going upwards
point.y = self.center.y - point.y ;
return ::atan2(point.y, point.x) ;
}
If anyone has a better name for this method, I'm all ears.
What it does is that it takes a point in parent view coordinates, remaps it relative to the center of the view (which is in parent view coordinate), and computes the angle between this remapped point and the axis [0X]. To do so, it normalizes y to the normal mathematical coordinates (y goes up when its value increases, not down), hence self.center.y - point.y and not the opposite.
Finally, in touchesMoved:
- (void) touchesMoved: (NSSet *) touches withEvent: (UIEvent *) event {
UITouch * touch = [touches anyObject] ;
CGFloat currA = [self pointToAngleFromCenter:[touch locationInView:self.superview]] ;
CGFloat prevA = [self pointToAngleFromCenter:[touch previousLocationInView:self.superview]] ;
// the current value of the rotation angle
CGFloat tranA = ::atan2(self.transform.b, self.transform.a) ;
// the angle difference between last touch and the current touch
CGFloat diffA = currA - prevA ;
// the new angle resulting from applying the difference
CGFloat angle = tranA - diffA ;
CGAffineTransform t = ::CGAffineTransformMakeRotation(angle) ;
self.transform = t ;
[self setNeedsDisplay] ;
}

Rotate Arrow UIImage in a circle in objC

I'm working on the iPad app, In which I have to rotate a arrow in a circle by touch. But I'm facing problems in it. The problem is in the angle calculation to which the image must be rotate.
You can check it here .
I have to rotate the big red arrow image around the circle. Can anybody help me, How to get the angle of the touched point. Currently I'm using the following code, I found it at somewhere in the net. But it didn't rotate the arrow to the touched place.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *oneTouch = [touches anyObject];
CGPoint currentPoint = [oneTouch locationInView:imgCompass];
double current_angle = [self wheelAngleFromPoint:currentPoint];
imgNeedle.transform = CGAffineTransformMakeRotation( current_angle );
}
- (double) wheelAngleFromPoint:(CGPoint)location
{
double retAngle;
// subtract center of wheel
location.x -= (self.imgNeedle.bounds.size.width ) / 2.0;
location.y = (self.imgNeedle.bounds.size.height ) / 2.0 - location.y;
// normalize vector
double vector_length = sqrt(location.x*location.x + location.y*location.y);
location.x = location.x/vector_length;
location.y = location.y/vector_length;
retAngle = acos(location.y);
float offset = 0.28;
//if (location.x)
// offset = 0.28;
retAngle += offset;
if (location.x<0)
{
retAngle = -retAngle;
}
return retAngle;
}
Can anyone help me in correct angle calculation.
Thanks
Here's the problem:
location.x -= (self.imgNeedle.bounds.size.width ) / 2.0;
location.y = (self.imgNeedle.bounds.size.height ) / 2.0 - location.y;
The values in location.x and location.y after the calculation should represent a vector from the centre of the imgNeedle (or wheel?) to the touch point. try this instead:
location.x = location.x - self.imgNeedle.center.x;
location.y = self.imgNeedle.center.y - location.y;
Note that since you are setting the imgNeedle.transform property, the frame will be invalid, but the center will be ok :) - the imgNeedle will rotate about the center of the image.
Notice that I explicitly stated location.x - self.imgNeedle.center.x to help you understand what's going on - you need to calculate the difference between the two points (a vector between them). You should understand that in mathematics, (0, 0) being the origin, the x-axis is positive to the right and the y-axis is positive upwards. However, on your device's screen, the co-ordinate system you are using (view co-ordinates) (0, 0) is at the top left with the x-axis going positive to the right but the y-axis going positive downwards (this isn't always true, because you can map your screen co-ordinates a number of ways). That is why the location.y subtraction is the other way around from the location.x subtraction - to account for the screen being "flipped" vertically (in terms of mathematically calculating the angle). It's also good to know that in mathematics, a positive rotation represents a rotation in the anti-clockwise direction, and a flip on one axis can hide this and make it appear that a positive angle means a clockwise rotation (like a double negative making a positive), so when you're playing with rotations and vectors, you should take all of this into account. However, for your purposes, it's quite simple, so instead of trying to wrap your head around all the maths you may just prefer to play with the code using trial and error, you might need to flip one of the directions (change the order of subtraction) or even change the direction of rotation (do 2*M_PI - retAngle for example).

Opengl Iphone SDK: How to tell if you're touching an object on screen?

First is my touchesBegan function and then the struct that stores the values for my object. I have an array of these objects and I'm trying to figure out when I touch the screen if I'm touching an object on the screen.
I don't know if I need to do this by iterating through all my objects and figure out if I'm touching an object that way or maybe there is an easier more efficient way.
How is this usually handled?
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[super touchesEnded:touches withEvent:event];
UITouch* touch = ([touches count] == 1 ? [touches anyObject] : nil);
CGRect bounds = [self bounds];
CGPoint location = [touch locationInView:self];
location.y = bounds.size.height - location.y;
float xTouched = location.x/20 - 8 + ((int)location.x % 20)/20;
float yTouched = location.y/20 - 12 + ((int)location.y % 20)/20;
}
typedef struct object_tag // Create A Structure Called Object
{
int tex; // Integer Used To Select Our Texture
float x; // X Position
float y; // Y Position
float z; // Z Position
float yi; // Y Increase Speed (Fall Speed)
float spinz; // Z Axis Spin
float spinzi; // Z Axis Spin Speed
float flap; // Flapping Triangles :)
float fi; // Flap Direction (Increase Value)
} object;
There are several ways to do this.
You can perform extra draw of the scene with all objects drawn solid using unique color, then read color of the selected pixel using glReadPixels and associate it with object.
Use something like unproject to get in-scene ray, and then find ray-triangle intersection. Unproject function as well as ray-triangle intersection function can be found in glm library which is perfectly suits open gl development.