Placing Buttons on a Circle - iphone

I'm having a heck of a time calculating points on a circle in Objective-C. Even after reading TONS of other code samples my circle is still way off center. (And that's taking into consideration "center" vs "origin" and adjusting for the size of the UIView, in this case a UIButton.)
Here's the code I'm using. The circle is formed correctly, it's just off center. I'm not sure if this is a radians vs degrees problem or something else. This is a helper function in a ViewController that programmatically creates the UIButtons and adds them to the view:
- (CGPoint)pointOnCircle:(int)thisPoint withTotalPointCount:(int)totalPoints {
CGPoint centerPoint = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2);
float radius = 100.0;
float angle = ( 2 * M_PI / (float)totalPoints ) * (float)thisPoint;
CGPoint newPoint;
newPoint.x = (centerPoint.x / 2) + (radius * cosf(angle));
newPoint.y = (centerPoint.y / 2) + (radius * sinf(angle));
return newPoint;
}
Thanks for the help!

The center of your buttons (i.e. points on the circle) is
newPoint.x = (centerPoint.x) + (radius * cosf(angle)); // <= removed / 2
newPoint.y = (centerPoint.y) + (radius * sinf(angle)); // <= removed / 2
Please note that if you place buttons (i.e. rectangles) on these points you have to make sure that their center lies at this point (i.e. subtract buttonWidth/2 from newPoint.x and buttonHeight/2 from newPoint.y to get the top left corner).

Not sure why you divide by 2 a second time newPoint coordinates...
What about this:
newPoint.x = centerPoint.x + (radius * cosf(angle));
newPoint.y = centerPoint.y + (radius * sinf(angle));
return newPoint;  

Related

Rotate UIView without deformation

I'm rotating a UIView based on the accelerometer data, and it works fine except that the UIView is deformed. I'm not sure how to fix the issue. Here's the code in my didAccelerate method:
float kFilteringFactor = 0.175;
CGFloat x = acceleration.x * kFilteringFactor + acceleration.x * (1.0 - kFilteringFactor);
CGFloat y = acceleration.y * kFilteringFactor + acceleration.y * (1.0 - kFilteringFactor);
float radians = M_PI - atan2(y, x);
[_horizonView setTransform:CGAffineTransformMakeRotation(radians)];
Am I performing the rotation incorrectly? I've changed the origin point in Xcode, but that appears to have no effect.
what kind of deformation occures? I think the the rotation is fine.

Apply gradient to a non-square shape drawn with AddArc

I've got a couple of closed shapes that I'm drawing in an iPhone app using CGContextAddArc, and I'd like to apply a gradient to it but can't find any good examples. Everything I've found that clips bounds to a drawn shape reference CGRect somewhere, but I need to clip the gradient bounds to a non-CGRect shape. Any ideas/help?
I'm using xcode 4.2.1 with storyboard and iOS5, though these shapes are being drawn within a view programmatically.
The code I'm using to draw my non-square shapes:
CGContextRef context = UIGraphicsGetCurrentContext();
//set context-based constants
double widthMiddle = self.frame.size.width/2;
double heightMiddle = self.frame.size.height/2;
double avgDimension = (widthMiddle + heightMiddle) / 2;
float arcRadius = avgDimension * .9;
float innerRadius = avgDimension * .4;
double startAngle = 2 * (sectionNumber - 1) * (M_PI / 3);
double endAngle = (2 * (sectionNumber * (M_PI / 3))) - [sectionSpacing doubleValue];
double interfaceAngle = [sectionSpacing doubleValue] * (innerRadius / arcRadius);
double ratingRadius = innerRadius + ((arcRadius-innerRadius) * percentGood);
double percentInterfaceAngle = interfaceAngle * (1-percentGood);
//NSLog(#"InterfaceAngle and percentInterfaceAngle are: %f/%f", interfaceAngle, percentInterfaceAngle);
//draw grey background shape
CGContextBeginPath(context);
CGContextSetLineWidth(context, [lineWeight doubleValue]);
//CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextSetRGBStrokeColor(context, .65, .65, .65, 1);
CGContextSetAllowsAntialiasing(context, 1);
//outer arc
CGContextAddArc(context, //context
widthMiddle, //X-value for center point of arc
heightMiddle, //Y-value for center point of arc
arcRadius, //Radius of the arc
startAngle, //start angle in radians
endAngle, //end angle in radians (2pi = full circle)
0); //Clockwise? 1 = true
//inner arc
CGContextAddArc(context, //context
widthMiddle, //X-value for center point of arc
heightMiddle, //Y-value for center point of arc
innerRadius, //Radius of the arc
endAngle - interfaceAngle, //start angle in radians
startAngle + interfaceAngle, //end angle in radians (2pi = full circle)
1); //Clockwise? 1 = true
CGContextClosePath(context);
//CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextSetRGBFillColor(context, .65, .65, .65, 1);
//CGContextSetAlpha(context, .6);
CGContextDrawPath(context, kCGPathFillStroke );
You are looking for the CGContextClip function, or maybe the CGContextEOClip function.
CGContextClip sets the context's clipping path to the intersection of its current clipping path and its current path, and then clears the current path. CGContextEOClip does the same, but with a different way of handling "holes" in the path. The different only matters if you have a path that intersects itself, or contains multiple closed subpaths.

iPhone - Drawing something at a given point using angle from center of view

I have a view with a point on its center.
I have an angle in degrees (or radian, that's not the problem).
I have a circle which center is the center of the view, and the radius is R.
I'd like to draw :
something (let's say an image) on the point that is placed on the
circle, at an angle of R from the vertical position.
an arc from the vertical position above the center that intersect
the circle, to that point
How may I do that ?
I think it you could calculate the image position with:
CGPoint center = self.view.center;
float x = radius * cos(angle);
float y = radius * sin(angle);
CGPoint newPoint = CGPointMake(center.x + x, center.y + y);
Let me know if it worked.
As for drawing an arc you would have two points, one is newPoint that is calculated above (on circle depending the angle) and point above the center intersecting the circle which is calculated easily:
CGPoint pointAboveCenter = CGPointMake(center.x, center.y + radius);

CGAffineTransformMakeRotation stretches my image, what am I doing wrong?

I have an image which shows which way is north on a map. This image is updated by CoreLocation if a new heading is found. It is also placed at the correct position, I use the following code:
locateMeView.transform = CGAffineTransformMakeRotation(([CoreLocationController sharedInstance].heading - 45) * M_PI / 180);
CGRect frame = locateMeView.frame;
CGPoint pos = [MapClass vectorForLocation:[CoreLocationController sharedInstance].location mapCenter:curLocation zoom:curZoom];
frame.origin.x = (int)(self.view.bounds.size.width/2 + pos.x - frame.size.width / 2);
frame.origin.y = (int)(self.view.bounds.size.height/2 + pos.y - frame.size.height / 2);
frame.size.width = 24;
frame.size.height = 24;
locateMeView.frame = frame;
CoreLocationController is a class which stores the updates of the normal CoreLocation. The MapClass transforms lat/lng coordinates to x/y coordinates on my map. The position of the image is correct, but the rotation is causing strange effects. For 0 en M_PI the image is correct but between these the image is stretched as if it is also rotated around the z-axis and at M_PI/2 and 3 * M_PI/2, it disappears altogether. Can someone explain what is happening and what I am doing wrong?
I found out what was wrong (more or less anyway). When using the transform property you are not allowed (for whatever reason) to change the position by changing the frame, you have to use the center property. So the code in the end was:
CGPoint pos = [MapClass vectorForLocation:[CoreLocationController sharedInstance].location mapCenter:curLocation zoom:curZoom];
locateMeView.transform = CGAffineTransformMakeRotation(([CoreLocationController sharedInstance].heading - 45) * M_PI / 180);
locateMeView.center = CGPointMake(int)(self.view.bounds.size.width/2 + pos.x), (int)(self.view.bounds.size.height/2 + pos.y));
Hope that someone with the same problem will find my answer.
Another solution:
Set transform to identity
Change the frame
Set transform
In your situation it should be:
locateMeView.transform = CGAffineTransformIdentity;
CGRect frame = locateMeView.frame;
CGPoint pos = [MapClass vectorForLocation:[CoreLocationController sharedInstance].location mapCenter:curLocation zoom:curZoom];
frame.origin.x = (int)(self.view.bounds.size.width/2 + pos.x - frame.size.width / 2);
frame.origin.y = (int)(self.view.bounds.size.height/2 + pos.y - frame.size.height / 2);
frame.size.width = 24;
frame.size.height = 24;
locateMeView.frame = frame;
locateMeView.transform = CGAffineTransformMakeRotation(([CoreLocationController sharedInstance].heading - 45) * M_PI / 180);
Try setting the transform after the resizing? Order can matter with transforms.

How do I properly move an image using UIAccelerometer?

i have implementing moving image using UIAccelerometer.I have used below code.
code:
float gravX = (acceleration. x * kFilteringFactor) + (gravX * (1 - kFilteringFactor));
float gravY = (acceleration. y * kFilteringFactor) + (gravY * (1 - kFilteringFactor));
float moveX = acceleration. x - gravX;
float moveY = acceleration. y - gravY;
CGPoint MoveCenter = [moveImage center];
float Movex = moveX * 30 + MoveCenter. x;
float Movey = moveY * 30 + MoveCenter. y;
moveImage.center = CGPointMake(Movex, Movey);
In this code there is one problem.If i move device on top side then image is moving on left side,if device is move left side then image is moving top side.can you give me advice.
Maybe is a problem of the coordinates. I'm not sure this is the problem but in Quartz the (0,0) is on bottom left while on UIKit is on top left.
Try to change the coordinates with frame.origin.x and frame.origin.y instead of using CGPoint.