I need to get a specific point with specified angle and distance(Radius) from center point of my base UIView. I found this question How to calculate a point with an given center, angle and radius? but this doesn't give me correct point. I'm using below code to find the point,
Basically i need to find the x,y point from 100px distance and 90 degrees(clock wise) from center point of my base view.
int angle = 90 * M_PI / 180;//need to find the point of 90 degrees
int distance = 100;
int line_end_x = 160 + cos(angle)*distance;//160 is my center x
int line_end_y = 274 + sin(angle)*distance;//274 is my center y
myView.center = CGPointMake(line_end_x, line_end_y);
Above code gives me below output,
Red box is "myView" with (20px x 20px)
May be someone can tell me whats wrong i'm doing?
I doubt that you want your angle to be expressed as an int.
Your angle is Pi/2 which is 1.57.
Maybe try float angle = 90 * M_PI / 180;
Related
Maybe it's simple math, but I'm asking a question because it's not easy to find a way to calculate.
I'm drawing a rectangle using canvas and I can rotate it using canvas.rotate.
If have Rect as follows and I rotate it 30 degrees, how can I calculate the Rect value(rect LTRB) after rotation?
Rect rect = Rect.fromLTRB(100,100,200,200);
final degrees = 30;
final radians = degrees * math.pi / 180;
canvas.translate(100,100); // left top pivot
canvas.rotate(radians);
canvas.translate(-100,-100)
// after rotate, rect left,rop, right, bottom value = ?
Let C be the rotation center. Any corner P maps to
(cos Θ (P.X-C.X) - sin Θ (P.Y-C.Y) + C.X, sin Θ (P.X-C.X) + cos Θ (P.Y-C.Y) + C.Y)
Take the minima and maxima for the four corners to get the bounding box.
I am using Cocos3D. I have a camera (which acts as the first-person viewed player in a world with only a spinning "hello, world" and a spinning earth. I have made it possible for the camera to point in any direction, and I have got it to move, but how do I get the camera/player to move forward in the direction he is pointing? (He does not go up or down, i.e. his y position does not change).
I note this is quite an old question - hopefully this answer helps someone!
You need to get the rotation angle of your camera, convert that to radians and use trigonometry to get the new X-Z coordinates. Tell your camera to move to those coordinates and presto, the player has moved forward!
CC3Camera *cam = self.activeCamera;
CC3Rotator *rotator = cam.rotator;
CC3Vector ro = rotatoooor.rotation;
CC3Vector loc = cam.globalLocation;
// If the -90 is left off, you go left/right and not forward
float roA = rotator.rotationAngle-90;
// Bug in rotationAngle? Need this as 315 angle reports as 45
int roI = ro.y;
int diff = roA+90 - roI;
if (diff == 0 && roI == 45)
roA = 315-90;
double theta = roA * M_PI/180; // Convert to radians
/*
x = d cos a
z = d sin a
*/
double sinA = sin(theta);
double cosA = cos(theta);
double newX = distance*cosA + loc.x;
double newZ = distance*sinA + loc.z;
CC3Vector newTo = cc3v(newX, loc.y, newZ); // Pass this to your camera
double = rollingZ = acceleration.x;
double = rollingX = acceleration.y;
if (rollingZ > 0.0) {
self.centerCoordinate.inclination = atan(rollingX / rollingZ) + M_PI / 2.0; //LINE 1
}
else if (rollingZ < 0.0) {
self.centerCoordinate.inclination = atan(rollingX / rollingZ) - M_PI / 2.0; // LINE 2
}
else if (rollingX < 0) {
self.centerCoordinate.inclination = M_PI/2.0; //atan returns a radian
}
else if (rollingX >= 0) {
self.centerCoordinate.inclination = 3 * M_PI/2.0;
Im just trying to fully understand this piece of code. I'm looking to build AR apps on the iphone and this code has the function of calculating the angle of inclination of the device using the accelerometer readings.
My understanding is this:
Assuming a portrait orientation if i roll the device forward the x axis of the accelerometer increases towards a negative number of -1.0 (i.e. the device is laid flat with the screen facing up). If i tilt the device towards me the x axis value increases towards a value of 1.0 (until the device is flat facing the ground).
The y axis changes up and down its axis between -1.0 and 0.0 (0 implies the device is horizontal).
If we take some example readings say x = 0.5 (a -45 degree angle, tilting the device towards me) and y = 0.8. If i plotted this on a cartesian coordinate graph with y (rollingX as the vertical axis) and x (rollingZ as the horizontal) and draw a line between them i understand that i can use the reverse tangent function (atan) to calculate the angle. My confusion comes on line 1. I dont understand why that line adds 90 degrees (in radians) to the calculated angle given by the atan function?
I just cant seem to visualise on a graph whats going on. If someone could shed some light on this - that would be much appreciated.
I suppose that these +90 degrees or -90 degrees (in case of negative rollingZ) are added to bring inclination value to widely used Polar coordinate system with angle between -180 and 180 degrees.
Assuming that you have Z line projecting upward when you look at the screen of the device and Z line looking at you from the screen, the result of calculations above vill give you an angle between screen plane and horizontal plane.
Let us assume that acceleration value is positive when it is goes "inside" the device:
1) Device is in vertical position, we have rollingZ = 1, rollingX = 0. The code returns 90 degrees.
2) Device is tilted towards user. Let rollingZ be 0.7 and rollingX be -0.7. This will give us 45 degree angle.
3) Device is in upside-down position, now we have rollingZ = -1 and rollingX = 0, and it is -90 degrees.
I am trying to draw a linear CGGradient on an angle. Because "CGContextDrawLinearGradientWithAngle()" does not exist, I am trying to use CGContextDrawLinearGradient(CGContextRef, CGGradientRef, CGPoint startPoint, CGPoint endPoint, CGGradientDrawingOptions).
With that in mind, I need to convert an angle (degrees) into a starting point and an ending point. I would like to mimic NSGradient's drawInBezierPath:angle. (As a part of AppKit, NSGradient is sadly not available to iOS developers.) Fortunately, the documentation tells us how to get the starting gradient:
- (CGPoint)startingPointForAngle:(CGFloat)angle rect:(CGRect)rect {
CGPoint point = CGPointZero;
if (angle < 90.0f)
point = CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect));
else if (angle < 180.0f)
point = CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect));
else if (angle < 270.0f)
point = CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect));
else
point = CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect));
return point;
}
Unfortunately, the documentation does not tell us how to get the ending point. (Using either the height or the width of the rect as the distance is only sufficient for certain angles.) Several sites out there tells us how we can find the ending point. Unfortunately, the distance needs to be known before I can compute the ending point. Yet the ending point needs to be computed to get the distance. There is clearly more to it, as NSGradient seems to have it figured out.
- (CGPoint)endingPointForAngle:(CGFloat)angle rect:(CGRect)rect startingPoint:(CGPoint)startingPoint {
//http://www.zahniser.net/~russell/computer/index.php?title=Angle%20and%20Coordinates
//(x + distance * cos(a), y + distance * sin(a))
CGFloat angleInRadians = (CGFloat)M_PI/180.0f * angle;
CGFloat distance = ????????;
CGPoint point = CGPointMake(startingPoint.x + distance * cosf(angleInRadians), startingPoint.y + distance * sinf(angleInRadians));
return point;
}
CGPoint startingGradientPoint = [self startingPointForAngle:self.fillGradientAngle rect:rect];
CGPoint endingGradientPoint = [self endingPointForAngle:self.fillGradientAngle rect:rect startingPoint:startingGradientPoint];
CGContextDrawLinearGradient(graphicsContext, self.fillGradient, startingGradientPoint, endingGradientPoint, 0);
Any ideas.
I'm dealing with the same problem, with a little different way, I use the center point and and angle, and extend the side left and right to find it's points on the edge, my problem was there will be white space if the angel is not pointing any axis, and the drawing option the functions provide a "kCGGradientDrawsBeforeStartLocation or kCGGradientDrawsAfterEndLocation" so it looks like one side will be empty.
But it turns out I can combine the two options with '|', so problem solved, here's my code:
CGGradientRef grRef = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)gradient.colorArray, NULL);
CGFloat degree = angle * M_PI / 180;
CGPoint center = CGPointMake(width/2, height/2);
CGPoint startPoint = CGPointMake(center.x - cos (degree) * width/2, center.y - sin(degree) * height/2);
CGPoint endPoint = CGPointMake(center.x + cos (degree) * width/2, center.y + sin(degree) * height/2);
NSLog(#"start point:%# \n, end point: %#",NSStringFromCGPoint(startPoint),NSStringFromCGPoint(endPoint));
CGContextDrawLinearGradient(gradientContext, grRef, startPoint, endPoint, kCGGradientDrawsBeforeStartLocation|kCGGradientDrawsAfterEndLocation);
I'm not 100% sure how this gradient thing works but from what you've written I'm assuming that you basically just want the length of a line from the starting point until it hits the side of the rectangle.
If this is the case you simply need to do some trigonometry. Lets call the distance x and the angle a.
Between 0 and 45 degrees: width = xcos(a) so x = width/cos(a)
Between 45 and 90 degress: height = xsin(a) so x = height/sin(a)
Between 90 and 135 degrees we have moved to a new corner. Here x = height/cos(a-90).
Between 135 and 180 x = width/sin(a-90)
Between 180 and 225 we have again moved corner. Here x = width/cos(a-180).
Between 225 and 270 x = height/sin(a-180)
Last corner! Between 270 and 315 x = height/sin(a-270)
And finally between 315 and 360 x = width/cos(a-270)
Some of these probably simplify but its easiest to think about the line starting in the bottom left corner pointing right and sweeping round anticlockwise which is what appears to happen in your starting point calculation.
I know there are a load of other questions on this topic, I think I've read most of them, along with Wikipedia and a bunch of other articles but I am missing (I think) some simple arithmetic to complete my coordinate calculations.
I have this code:
typedef struct {
double startX;
double startY;
double x2;
double y2;
double length;
double angle;
double lastAngle;
} LINE;
void lineCalc(LINE *lp) {
double radians = lp->angle * 3.141592653589793/180.0;
lp->x2 = lp->startX + (lp->length * cos(radians));
lp->y2 = lp->startY + (lp->length * sin(radians));
fprintf (stderr, "lineCalc:startX:%2.3f, startY:%2.3f, length:%2.3g, angle:%2.3f, cos(%2.3f):%2.3f, x2:%2.3f, y2:%2.3f\n", lp->startX, lp->startY, lp->length, lp->angle, lp->angle, cos(radians), lp->x2, lp->y2);
}
int main() {
// Initialise to origin of 250, 250. 0, 0 for initial end point. Length 150, first angle 60 (degrees), l.lastAngle currently not used
LINE l = {250, 250, 0, 0, 150, 60, 0};
lineCalc(&l);
//drawLine(&l);
l.startX = x2; l.startY = y2; // make last end point, new start point. Angle stays at 60 degrees
lineCalc(&l);
//drawLine(&l);
l.startX = x2; l.startY = y2;
lineCalc(&l);
//drawLine(&l);
}
Which calculates the end point of a line given its start point, length and angle. All fine and good, but what I want to be able to do is to draw a shape, a triangle would be a start.
At the moment the code will make the calculation, draw the line (in reality it is generating SVG), make the last end point the next origin, recalculate, draw the next line etc...
The crucial bit that I am missing is how to get angle to be relative to the last line drawn. At the moment, the moving of the origin works fine, but the angle stays the same, thus three lines with angles of 60 degrees will just draw a straight line because the angle is relative to the start rather than relative to the last line.
Just in case it is relevant, with SVG horizontal is zero degrees. Thus a line 50 units long, starting at y100, x100 at an angle of 90 degrees will have an end point of y150, x100.
Could someone point out the obvious thing that I a missing to make the angles correct relative to the last line please?
If you take the angle at which the first line is drawn at as theta:
theta + 180 deg OR theta - 180 deg will face you back down the line you just drew.
Then theta + 180 deg + 60 OR theta - 180 deg + 60 will face you at 60 degrees to the first line.
You need to choose whether to + or - the 180 based on the range of degrees that svg uses (does it go -180 to 180 or 0 to 360) and how big your starting theta is. Also you need to choose + or - 60 degrees based on the side of the first line that you want to draw the second line.
Once you've calculated the angle you're drawing the second line at (theta + 180 + 60 for instance) then you need to take that as your next theta to calculate the angle for the third line.