Using CGAffineTransformMakeRotation to rotate a point - objective-c

If I want to rotate one CGPoint about another, I'm currently doing this (which works fine):
CGFloat rx = cos(DEGREES_TO_RADIANS(-angle)) * (positionToRotate.x-rotationPoint.x) - sin(DEGREES_TO_RADIANS(-angle)) * (positionToRotate.y-rotationPoint.y) + rotationPoint.x;
CGFloat ry = sin(DEGREES_TO_RADIANS(-angle)) * (positionToRotate.x-rotationPoint.x) + cos(DEGREES_TO_RADIANS(-angle)) * (positionToRotate.y-rotationPoint.y) + rotationPoint.y;
It strikes me that I should be able to do this with a CGAffineTransform, but I'm a bit stuck as to how it would work:
CGAffineTransform affine CGAffineTransformMakeRotation(M_PI/4);
CGPointApplyAffineTransform(positionToRotate, affine);
That does nothing as I'm (hopefully) missing something obvious :)
So how do you rotate a CGPoint about another without doing the matrix math myself?
Cheers,
Ian

CGPointApplyAffineTransform returns the transformed point. It doesn't mutate the CGPoint you pass in.
CGPoint transformedPoint = CGPointApplyAffineTransform(positionToRotate, affine);

Related

Velocity Verlet Algorithm: Cannot seem to determine correct velocity for stable Orbit?

Like many that post about this topic, I too am busy trying to write myself an accurate simulator for the movement of objects in a 2D gravitation field.
I decided early on that I would settle on Velocity Verlet Integration, as I want my objects to maintain stable orbits and conserve energy even if the timestep is rather large. So, what might the problem be?
Well, so far, everything seems to behave correctly, except for one component. When I try to calculate the correct velocity for a stable orbit at a certain distance, the resulting velocity sends them into odd elliptical orbits that quickly increase in magnitude each time.
So, to begin, here are the following methods that determine an objects next position, velocity, and acceleration in scene: (Objective C)
Acceleration:
-(CGVector)determineAccelerationFor:(SKObject *)object
{ // Ok, let's find Acceleration!
CGVector forceVector = (CGVector){0,0}; // Blank vector that we will add forces to
for (SKObject *i in self.sceneObjects)
{
if (![i isEqual:object]) // Just make sure we're not counting ourselves here
{
CGPoint distance = [self getDistanceBetween:i.position And:object.position];
float hypotenuse = sqrtf(powf(distance.x, 2)+ powf(distance.y, 2));
float force = ((self.gravity * object.mass * i.mass)/powf(hypotenuse, 3));
float xMagnitude = (force * distance.x);
float yMagnitude = (force * distance.y);
forceVector.dx += xMagnitude;
forceVector.dy += yMagnitude;
}
}
CGVector acceleration = (CGVector){forceVector.dx/object.mass, forceVector.dy/object.mass};
return acceleration;
}
Cool, so basically, I just take an object, add all the other forces that each other object imposes on it together then divide the X & Y factor by the mass of the current object to get the acceleration!
Next up is Velocity. Here I use the following equation:
The method for it is pretty straightforward too:
-(CGVector)determineVelocityWithCurrentVelocity:(CGVector)v OldAcceleration:(CGVector)ao NewAcceleration:(CGVector)a
{
float xVelocity = (v.dx + ((ao.dx + a.dx)/2) * self.timeStep);
float yVelocity = (v.dy + ((ao.dy + a.dy)/2) * self.timeStep);
CGVector velocity = (CGVector){xVelocity,yVelocity};
return velocity;
}
And finally, position! The equation for this is:
And it is determined with the following method!
-(CGPoint)determinePositionWithCurrentPosition:(CGPoint)x CurrentVelocity:(CGVector)v OldAcceleration:(CGVector)ao
{
float xPosition = (x.x + v.dx * self.timeStep + ((ao.dx * powf(self.timeStep, 2))/2));
float yPosition = (x.y + v.dy * self.timeStep + ((ao.dy * powf(self.timeStep, 2))/2));
CGPoint position = (CGPoint){xPosition,yPosition};
return position;
}
This is all called from the below method!!
-(void)refreshPhysics:(SKObject *)object
{
CGPoint position = [self determinePositionWithCurrentPosition:object.position CurrentVelocity:object.velocity OldAcceleration:object.acceleration]; // Determine new Position
SKAction *moveTo = [SKAction moveTo:position duration:0.0];
[object runAction:moveTo]; // Move to new position
CGVector acceleration = [self determineAccelerationFor:object]; // Determine acceleration off new position
CGVector velocity = [self determineVelocityWithCurrentVelocity:object.velocity OldAcceleration:object.acceleration NewAcceleration:acceleration];
NSLog(#"%# Old Velocity: %f, %f",object.name,object.velocity.dx,object.velocity.dy);
NSLog(#"%# New Velocity: %f, %f\n\n",object.name,velocity.dx,velocity.dy);
[object setAcceleration:acceleration];
[object setVelocity:velocity];
}
Okay, so those methods above dictate how objects are moved in scene. Now onto the initial issue, the ever present problem of achieving a stable orbit!
In order to determine what velocity an object should have to maintain an orbit, I use the following equation:
And I implement that as follows:
-(void)setObject:(SKObject *)object ToOrbit:(SKObject *)parent
{
float defaultSeparation = 200;
// Move Object to Position at right of parent
CGPoint defaultOrbitPosition = (CGPoint){parent.position.x + (parent.size.width/2)+ defaultSeparation,parent.position.y};
[object setPosition:defaultOrbitPosition];
// Determine Orbital Velocity
float velocity = sqrtf((self.gravity * parent.mass)/(parent.size.width/2+defaultSeparation));
CGVector vector = (CGVector){0,velocity};
[object setVelocity:vector];
}
And for some reason, despite this, I get abysmal results. Here is some of the output:
Information:
Gravity(constant) = 1000 (For test purposes)
Mass(Parent) = 5000 units
Mass(Satellite) = 1 units
Separation = 224 pixels
It determines that in order for the Satellite to Orbit the Parent, a velocity of:
149.403580 pixels/timeStep
is required. And that checks out on my calculator.
So this has left me a little confused as to what could be going wrong. I log all the output concerning new velocities and positions, and it does use the velocity I set it to, but that just doesn't seem to make a difference. If anyone could possible help spot what's going wrong here I would be immensely grateful.
If anyone believes I have left something out, tell me and I will edit this right away. Thanks!

iBeacon Trilateration - Vector Math

I'm having a bit of trouble with Trilateration using iBeacon's. I found a formula using vector math in this thread, and I implemented it in my project. However it seems to be giving me odd numbers.
It seems like it works most of the time, however I've noticed that sometimes it will give me extremely similar answers when using distances that are vastly different, which seems odd to me.
CGPoint pointA = [[curBlufiPoints objectAtIndex:0] CGPointValue];
CGPoint pointB = [[curBlufiPoints objectAtIndex:1] CGPointValue];
CGPoint pointC = [[curBlufiPoints objectAtIndex:2] CGPointValue];
/*Point A = (40, 612)
Point B = (379, 788)
Point C = (0, 352)*/
float distanceA = [[distances objectAtIndex:0] floatValue];
float distanceB = [[distances objectAtIndex:1] floatValue];
float distanceC = [[distances objectAtIndex:2] floatValue];
/*distanceA = 13.535637
distanceB = 46.931522
distanceC = 51.585461
----OR----
distanceA = 349.9057;
distanceB = 352.84134;
distanceC = 353.37515;*/
CGPoint P2MinusP1 = CGPointMake(pointB.x - pointA.x, pointB.y - pointA.y);
CGPoint P3MinusP1 = CGPointMake(pointC.x - pointA.x, pointC.y - pointA.y);
CGFloat magP2MinusP1 = sqrt(pow((P2MinusP1.x), 2) + pow((P2MinusP1.y), 2));
CGPoint eX = CGPointMake(P2MinusP1.x / magP2MinusP1, P2MinusP1.y / magP2MinusP1);
CGFloat i = eX.x * P3MinusP1.x + eX.y * P3MinusP1.y;
CGPoint eXTimesI = CGPointMake(eX.x * i, eX.y * i);
CGPoint P3MinusP1MinusITimesEX = CGPointMake(P3MinusP1.x - eXTimesI.x, P3MinusP1.y - eXTimesI.y);
CGFloat magP3MinusP1MinusITimesEX = sqrt(pow(P3MinusP1MinusITimesEX.x, 2) + pow(P3MinusP1MinusITimesEX.y, 2));
CGPoint eY = CGPointMake(P3MinusP1MinusITimesEX.x / magP3MinusP1MinusITimesEX, P3MinusP1MinusITimesEX.y / magP3MinusP1MinusITimesEX);
CGFloat j = eY.x * P3MinusP1.x + eY.y * P3MinusP1.y;
CGFloat x = (pow(distanceA, 2) - pow(distanceB, 2) + pow(magP2MinusP1, 2)) / (2 * magP2MinusP1);
CGFloat y = (pow(distanceA, 2) - pow(distanceC, 2) + pow(i, 2) + pow(j, 2)) / (2 * j) - (i * x) / j;
CGPoint finalPoint = CGPointMake(pointA.x + x * eX.x + y * eY.x, pointA.y + x * eX.y + y * eY.y);
NSLog(#"%f %f %f %f", finalPoint.x, finalPoint.y);
//finalPoint.x = ~343
//finalPoint.y = ~437
As you can see from the values I've commented in the code above, when I am using the same points, but different distances I end up with the same result. It doesn't make sense to me how they can both have around the same answer. If the point (343, 437), (the answer I get for both sets of input) is 13.5 units away from point (40, 612), how can the same point also be 349.9 units away?
I'm not sure where my math has gone wrong but I think that something about calculating x and y is where the problems comes in. I've discovered that the lines "pow(distanceA, 2) - pow(distanceB, 2)" and "pow(distanceA, 2) - pow(distanceC, 2)" give me approximately the same answer for both sets of numbers, which is why x and y end up being the same regardless of which set of numbers I use.
I don't think that this should be the case, any help would be greatly appreciated, thank you!
I tried your code with a sample (and bad looking code test).
The testing code is here.
To debug, I used the "3D" new feature of XCode 6, to see the points and circle that were out of the screen bounds, because I didn't want to do translation (recentering the plane, etc.)
The main issue (with your first sample test (#[#(13.535637), #(46.931522), #(51.585461)];) is that the circles aren't overlapping. There is NO intersection. So you can't guess the position.
If you draw a circle with center pointA, and radius distanceA, and do it for point B and C, you'll need to find the intersection to geolocalize, which is clearly illustrated on the wiki-related article on the linked question.
I added a "check" method to see if they overlap correctly, with a "allowed mistake", because we're doing some maths with float and there could be a few rounding issue.
The check method consist on recalculating the distance between the finalPoint (coordinate found) and each point. The question is now if they differs (a lot?) from the original ones.
Screenshot with first set of distances
Screenshot with second set of distances

UIKit Dynamics: Calculating pushDirection Needed for UIPushBehavior

I'd like to use UIPushBehavior to give a physically realistic animation of a view across the screen. But to do this, I need to be be able to calculated the magnitude of the push needed in the CGVector in the pushDirection property of UIPushBehavior.
Basically, I know the size of the view, the amount of time, and the distance I'd like it to travel. Is there a way to use the UIKit Newton definition and a UIDynamicItemBehavior with resistance to calculate exactly the magnitude need to move a view a specific distance in a specific amount of time?
If you're using a pan gesture, you can do this:
if ( gestureRecognizer.state == UIGestureRecognizerStateEnded )
{
CGPoint velocity = [gestureRecognizer velocityInView:gestureRecognizer.view.superview];
CGFloat magnitude = sqrtf((velocity.x * velocity.x) + (velocity.y * velocity.y));
myPushBehavior = [[UIPushBehavior alloc] initWithItems:#[gestureRecognizer.view]
mode:UIPushBehaviorModeInstantaneous];
myPushBehavior.pushDirection = CGVectorMake((velocity.x / 10) , (velocity.y / 10));
myPushBehavior.magnitude = magnitude;
}
Courtesy of Tony Dahbura's tutorial.

Drawing an Arrow with NSBezierPath between two Points

So I'm trying to generate a NSBezierPath that looks like an arrow between two points, which can lie anywhere on the view, so the startPoint can be larger or smaller than the endpoint.
The arrow is updated while a user drags the mouse like in a drawing app.
I already figured out, that I probably have to use transformations and some math to do trigonometric and have come up with this implementation:
+(NSBezierPath *)arrowWithStart:(NSPoint)startPoint andEnd:(NSPoint)endPoint{
NSBezierPath* path = [NSBezierPath bezierPath];
CGFloat width = endPoint.x - startPoint.x;
CGFloat height = endPoint.y - startPoint.y;
CGFloat angle = atan2(width, height);
NSAffineTransform *tr = [NSAffineTransform transform];
[tr translateXBy:startPoint.x yBy:startPoint.y];
[tr scaleXBy:width yBy:height];
[tr rotateByDegrees:angle];
[path moveToPoint:CGPointZero];
[path lineToPoint:CGPointMake(0.75, 0.7)];
[path lineToPoint:CGPointMake(0.8, 0.65)];
[path lineToPoint:CGPointMake(1, 1)];
[path lineToPoint:CGPointMake(0.65, 0.8)];
[path lineToPoint:CGPointMake(0.7, 0.75)];
[path closePath];
[path transformUsingAffineTransform:tr];
return path;
}
This Code generates pretty nice arrows, when the points are some kind of diagonal,
like
(0,0)
(-2,-2)
to each other, but when the points are getting nearer to a horizontal or vertical line, like
(2,3)
(5,3)
the result becomes a straight line without an arrowhead.
So I think I'm doing something wrong in the transformation Matrix.
If somebody knows where I'm making a mistake it would be great.
What you need is an affine transformation that transforms the point (0, 0) to startPoint and (1, 1) to endPoint. This transformation can be computed directly:
CGFloat tx = startPoint.x;
CGFloat ty = startPoint.y;
CGFloat a = ((endPoint.x - startPoint.x) + (endPoint.y - startPoint.y))/2.;
CGFloat b = (-(endPoint.x - startPoint.x) + (endPoint.y - startPoint.y))/2.;
NSAffineTransformStruct transformStruct = { a, b, -b, a, tx, ty };
NSAffineTransform *tr = [NSAffineTransform transform];
[tr setTransformStruct:transformStruct];
Explanation:
NSAffineTransformStruct transformStruct = { a, b, -b, a, tx, ty };
describes a general combination of translation, scaling and rotation, i.e. an affine transformation without shearing. The requirements (0, 0) -> startPoint, (1, 1) -> endPoint give the equations
startPoint.x = 0 * a + 0 * (-b) + tx
startPoint.y = 0 * b + 0 * a + ty
endPoint.x = 1 * a + 1 * (-b) + tx
endPoint.y = 1 * b + 1 * a + tx
and solving these equations for a, b, tx, ty gives above solution. (See Transform Mathematics in the "Cocoa Drawing Guide" for more information.)
The problem with your original code is that
atan2 takes y as first argument, so atan2(height, width) would compute the angle.
For horizontal or vertical lines, width or height and therefore one scaling factor is zero, this causes the straight lines without arrowhead.

How to recognize if CGPoint is included in shape?

I'm a beginner in quartz.
I'm wonderring a way that recognize if CGPoint is included in shape.
Please give me a help of Expert.
Follow is concept diagram.
In above three case,
Result I want is YES, Because three RED CGPoint is included in shape.
It is possible like follow way?
CGPoint RedPoint1 = {200,100};
CGPoint RedPoint2 = {200,200};
CGPoint RedPoint3 = {350,300};
BOOL includeRect;
includeRect = CGRectContainsPoint(RectCase, RedPoint1);
BOOL includeCircle;
includeCircle = CG ? ContainsPoint(CircleCase, RedPoint2)
BOOL includeBoldLine;
includeBoldLine = CG ? ContainsPoint(BoldLineCase, RedPoint3);
The ease of this all depends on how your shapes are defined.
If you have these as CGPathRefs or NSBezierPaths there is a containsPoint: method you could use.
If these are CGRects that have a transform applied to them, you can use the CGAffineTransformPoint methods to move the point into the same coordinate space and then use CGRectContainsPoint