I use CGPathAddArc to create a circle, if the radius is 5 pixel, will the whole circle end up with 10 pixels width or 11 pixels?
It's also confusing if it does end up with 10 pixels. In that case, what does it mean that center of a radius?
The CGPathAddArc defined here:
void CGPathAddArc (
CGMutablePathRef path,
const CGAffineTransform *m,
CGFloat x,
CGFloat y,
CGFloat radius,
CGFloat startAngle,
CGFloat endAngle,
bool clockwise
);
It does end up with 10 pixels as the diameter, which includes the center point.
As the Apple reference doc says:
When you call this function, you provide the center point, radius, and
two angles in radians. Quartz uses this information to determine the
end points of the arc
The end points are determined 'including' the center point, so that the entire diameter is 10.
Related
I am trying to create anticlockwise UIBezierPath with start of arc is negative y axis (just for visualization).
let arcPathForLayer = UIBezierPath(arcCenter: upperCenterPoint, radius: radius, startAngle: arcPathStartAngle, endAngle: (arcPathEndAngle), clockwise: false)
Normally for clockwise UIBezierPath, start and end angle is 0.0pi and 2.0pi respectively -for if the path is to start form positive x axis.
But for this case where UIBezierPath is anti clockwise and start of arc is negative y axis -the start angle and end angle is little confusing to calculate.
So I will post the answer for the same.
Here is the visualization for solution:
So the start angle is 0.5pi and end is -1.5pi, now for drawing the stroke for 25% --> the value of end angle = 0pi, for 50% --> end angle = -0.5pi, and on same note for 100% --> end angle = -1.5pi
here is the formula to calculate the same:
endAngle = (0.5 - (2 * percentageForProgress)) * .pi
I need to define a rotated rectangle from its 4 corners. The rotated rectangle is defined by a center point, a size couple (width, height), and an angle.
How is it decided which size is the height, and which one is the width?
The width is not the length of the most horizontal edge, is it? E.g. if the angle is bigger than 90°, does it swap?
height should be the largest side, width is the other one, and angle is the rotation angle (in degrees) in a clockwise direction.
Otherwise, you can get an equivalent rectangle with height and width swapped, rotated by 90 degrees.
You can use minAreaRect to find a RotatedRect:
vector<Point> pts = {pt1, pt2, pt3, pt4}
RotatedRect box = minAreaRect(pts);
// Be sure that largest side is the height
if (box.size.width > box.size.height)
{
swap(box.size.width, box.size.height);
box.angle += 90.f;
}
Ok, with Miki's help, and with some tests, I got it clearer...
It seems that the rotated rectangle is an upright rectangle (width and height are clearly defined, then)... that is rotated!
In image coords, y is directed to the bottom, the angle is given clockwise. In usual math coords (y to the top), the angle is given counter-clockwise. Then, it fits with c++ <math.h> included atan2(y,x) function for example (except that it returns radians).
Then, to summarize, if we consider one given edge of the rectangle (two corners), its length can be considered as the width if we retrieve the angle with atan2 on its y difference and x difference. Something like:
Point pt1, pt2, pt3, pt4;
RotatedRect rect;
rect.center = (pt1 + pt2 + pt3 + pt4)/4;
// assuming the points are already sorted
rect.size.width = distance(pt1, pt2); // sqrt(...)
rect.size.height = distance(pt2, pt3);
rect.angle = atan2(pt2.y-pt1.y, pt2.x-pt1.x);
and this can be improved with width being the mean value of dist(pt1,pt2) and dist(pt3,pt4) for example. The same for height.
angle can also be calculated as being the mean value of atan for (pt1, pt2) and atan for (pt3, pt4).
I have 5 subviews(White) added to the superview(Gray), when I rotate the superview I want to know the angle(like 1 and 2) of each of the subview with the red circle.(the center of the subviews and the red circle are ON the same circle)
Start Position:
Rotated Position:
From your comment you appear to want to determine the coordinates of the centres of your five circles for a given rotation. The centres will all lie on a circle. So your question boils down to what are the coordinates of a point on a circle of radius r for an angle θ. The parametric equations for a circle give you that:
x = r cos θ
y = r sin θ
The angle, θ, in these equations is measured in radians from the positive x-axis in an anti-clockwise direction. If your angle are in degrees you will find the M_PI constant for π useful as:
360 degrees = 2 π radians
The rest is simple math, take your angle of rotation to give you the angle for A (remembering to adjust for 0 being the x-axis and measuring anti-clockwise if needed), the other centres are multiples of 72 degrees (0.4 π radians) from this.
HTH
I'm not sure I completely understand your question, but if you just need to take a known point and rotate it a certain number of degrees, check out the docs for CGAffineTransform.
For example:
CGAffineTransform rotation = CGAffineTransformMakeRotation (angle);
CGPoint rotatedPoint = CGPointApplyAffineTransform (startingPoint, rotation);
This rotation matrix is around (0, 0) and the angle is in radians, so you will need to subtract the center of your superview's bounds to get an offset relative to the center, do the rotation, and add back in the center. Or you can build an affine transform made up of that translation, rotation, and inverse translation, and then apply that to your starting point as above.
Given that you already seem to know the main rotation angle, this will give you the angles in the range -180 .. +180 and positions of each of the white discs:
GCFloat toRads = M_PI / 180.0;
CGFloat angleA = self.rotationInDegrees;
if (angleA > 180) angleA -= 360;
CGFloat xA = self.radius * sinf(angleA * toRads);
CGFloat yA = self.radius * cosf(angleA * toRads);
CGFloat angleB = angleA + 72;
if (angleB > 180) angleB -= 360;
CGFloat xB = self.radius * sinf(angleB * toRads);
CGFloat yB = self.radius * cosf(angleB * toRads);
etc...
(This assumes your zero degrees is from the vertical. If it's from the horizontal swap cos and sin over).
Just what it says in the title, is there any way to do this kind of thing:
Is there any way to do this? If so, how would I correspond the SKAction rotateToAngle to the side facing the circle?
Thanks!
The tangent of a circle at any given point is perpendicular to a radius drawn to that point. Consider the two nodes as being in a polar coordinate system, with the origin at the center of the circle. You can convert the square's cartesian coordinates (at its center) to polar and find the angle of the proper radius:
void cartopol(CGFloat x, CGFloat y, CGFloat *radius, CGFloat *theta)
{
*radius = sqrt(x*x, y*y);
*theta = atan2(y, x);
}
(This could instead return a CGPoint if you prefer that to using out parameters, as I'll do below for the complementary function; the arithmetic is the important point.)
theta will be in radians; add or subtract π/4 to rotate it by 90˚.
To move the square around the circle, pick the angle and radius you want and convert from polar to cartesian:
CGPoint poltocar(CGFloat radius, CGFloat theta)
{
return (CGPoint){radius * cos(theta), radius * sin(theta)};
}
Very easy: add the rectangle sprite (it should not have a physics body of its own, though you could try to see if it works with a static body) as child node to the circle sprite with the physics body. Change the rectangle sprite's position to be offset from the center of its parent node, ie {100, 0} to put the circle node 100 points away from the center.
As the circle sprite & body rotate, the rectangle sprite will move and rotate along with it.
This is so much an iOS question as it is my current inability to do coordinate geometry. Given a CGPoint to act as a point that the line will pass through and an angle in radians. How do I draw a line that extends across to the bounds of the screen (infinite line)?
I am using Quartz2d to do this and the API for creating a line is limited to two points as input. So how do I convert a point and angle to two points on the bounds of the iOS device?
This begins with simple trigonometry. You need to calculate the x and y coordinate of the 2nd point. With an origin of 0,0 and treating a line that goes straight to the right as 0 degrees, and going counterclockwise (anti-clockwise for some of you), you do:
double angle = ... // angle in radians
double newX = cos(angle);
double newY = sin(angle);
This assumes a radius of 1. Multiply each times a desired radius. Pick a number that will be bigger than the screen such as 480 for an iPhone or 1024 for an iPad (assuming you want points and not pixels).
Then add the original point to get the final point.
Assuming you have CGPoint start, double angle, and a length, your final point is:
double endX = cos(angle) * length + start.x;
double endY = sin(angle) * length + start.y;
CGPoint end = CGPointMake(endX, endY);
It's OK if the end point is off the screen.