Passing only one argument with CGAffineTransformMakeTranslation (x,y) - iphone

I have multiple animations on a button, and I'm using CGAffineTransformMakeTranslation to do this.
Is it possible to use only one argument with it, only "x" or only "y"?
I've tried everything but couldn't make it work:
button.transform = CGAffineTransformMakeTranslation(nil, 10);
button.transform = CGAffineTransformMakeTranslation(NULL, 10);
etc, etc...
Or make it the "x" the current location. If I use 0 it will bring the button to the original location.
Is it possible to do this?
Thanks!!

Pass 0. A translation of 0 along an axis produces no change, because 0 is the identity of addition (which is what translation is).
button.transform = CGAffineTransformMakeTranslation(0, someYValue);

Translation in x direction only:
CGAffineTransformMakeTranslation(x, 0.0);
Translation in y direction only:
CGAffineTransformMakeTranslation(0.0, y);

CGAffineTransformTranslate retains the previous transform.
You can therefore call CGAffineTransformTranslate(myview.transform,0,y) or whatever suits you.
CGAffineTransform CGAffineTransformTranslate (
CGAffineTransform t,
CGFloat tx,
CGFloat ty
);

Related

CGAffineTransformMakeTranslation Movement

I am using CGAffineTransformMakeTranslation with UIPanGestureRecognizer to pan a UIView.
Does CGAffineTransformMakeTranslation take delta x and delta y or the absolute value of the new position? Here's what I have:
- (void)swipeDetected:(UIPanGestureRecognizer *)recognizer
{
CGPoint newTranslation = [recognizer translationInView:self.view];
self.navController.view.transform = CGAffineTransformMakeTranslation(newTranslation.x, 0);
.....
}
This works from left to right but not from right to left. I'm pretty sure "translation" means delta x and delta y and not absolute value.
Any suggestions?
Thanks
Setting the transform is an immediate operation as it is just matrix multiplication of the view's location.
If you need to revert back from your current position, you can save the transform to an ivar, and use an inverse transform, ie:
_currentTransform = CGAffineTransformMakeTranslation(newTranslation.x, 0);
and later:
CGAffineTransform inverse = CGAffineTransformInvert(_currentTransform);
If you want to remove all transforms you can do self.transform = CGAffineTransformIdentity
Hope this helps!

CGPoint rotation changes distance from origin

I want to rotate a CGPoint(red rect) around another CGPoint(blue rect) but it changes distance from the origin(blue rect)...when i give 270 in angle it creates the point right above the origin but when i give 90 as angle value it comes down the origin BUT CHANGES THE DISTANCE ALSO almost three times more....I want to keep the distance same and want to rotate CGPoint around another. Please guide any approach for rotation of cgpoints...
distance = 100;
angle = 270*M_PI/180;
rotatedPoint.x = initialPoint.x+distance*cos(angle);
rotatedPoint.y = initialPoint.y+distance*sin(angle);
//rotatedPoint.x = initialPoint.x+tan(angle);
[test setCenter:rotatedPoint];
[test setBackgroundColor:[UIColor redColor]];
Thanks
CGAffineTransform is a handy tool when it comes to rotation, translation, and scaling. To make sure a point is rotated properly, you must translate it to the origin, rotate it, and then translate it back.
To complete your transformation, something like the following should do the trick:
CGPoint pointToRotate = CGPointMake(30, 30);
float angleInRadians = DEGREES_TO_RADIANS(90);
CGPoint distanceFromOrigin = CGPointMake(0 - pointToRotate.x, 0 - pointToRotate.y);
CGAffineTransform translateToOrigin = CGAffineTransformMakeTranslation(distanceFromOrigin.x, distanceFromOrigin.y);
CGAffineTransform rotationTransform = CGAffineTransformMakeRotation(angleInRadians);
CGAffineTransform translateBackFromOrigin = CGAffineTransformInvert(translateToOrigin);
CGAffineTransform totalTransform = CGAffineTransformConcat(translateToOrigin, rotationTransform);
totalTransform = CGAffineTransformConcat(totalTransform, translateBackFromOrigin);
pointToRotate = CGPointApplyAffineTransform(pointToRotate, totalTransform);
And here is the documentation on CGAffineTransform, if you'd like to review it further: http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/CGAffineTransform/Reference/reference.html
Please let me know if you need anything else if this doesn't solve your problem!

scaling & Rotation of shape (rectangle)

Please i want scaling & Rotation of shape (rectangle) from one point.
Take as an example of MS Paint.
What will be the approach for that ?
Will it be possible ?
Thanks in Advance.
Use CGAffineTransform for that.
Rotation:
myView.layer.transform = CGAffineTransformRotate(theView.transform, degreesToRadians(45));
Scaling:
myView.layer.transform = CGAffineTransformScale(theView.transform, 2.0, 2.0);
By default it scale/rotate from center.
For any point you need to set the anchor point. See example:-
myView.layer.anchorPoint = CGPointMake(0, 0);

iPhone skew a CALayer

I'm a beginner and I am doing some exercises to familiarize myself with CALayer ...
I just want to know how to "incline" (or skew) a CALayer 45° angle ?
Thank you.
CALayers have a property, affineTransform that takes a CAAffineTransform. That documentation explicitly notes that:
Scaling, rotation, and translation are
the most commonly used manipulations
supported by affine transforms, but
skewing is also possible.
(emphasis mine, obviously)
There's no built in helper to construct a skew transform, but you could do something like (untested):
CGAffineTransform CGAffineTransformMakeSkew(CGFloat skewAmount)
{
CGAffineTransform skewTransform = CGAffineTransformIdentity;
skewTransform.b = skewAmount;
return skewTransform;
}
Then, for a skew such that things that were verticals stand at 45 degrees to the horizontal you'd use:
layer.affineTransform = CGAffineTransformMakeSkew(1.0f);
CALayers can be transformed using matrix operations. The skew transformation is represented by the following matrix
So if you want to do a skew transformation along the x axis you can use the following sample.
CALayer* layer = [CALayer layer];
layer.frame = CGRectMake(50,50,50,50);
layer.backgroundColor = [UIColor blueColor].CGColor;
[self.window.layer addSublayer:layer];
float theta = -45.0f;
CGAffineTransform t = CGAffineTransformIdentity;
t.b = tan(theta*M_PI/180.0f);
layer.transform = CATransform3DMakeAffineTransform(t);
The following sample will result in a layer that looks like the following
You could do this but you would have to mess with the layer's transform property, which is a struct CATransform3D. You're going to have to do some vector math to do this, as you . See the compute_transform_matrix(...) function from this answer for more details.
You'll want to do something like this:
CGRect r = layer.bounds;
layer.transform = compute_transform_matrix(r.origin.x, r.origin.y, r.size.width, r.size.height,
r.size.height, r.origin.y, r.size.width + r.size.height, r.origin.y,
r.origin.x, r.origin.y + r.size.height, r.size.width, r.origin.y );
Check my math on this. It should be right.
There are a lot of resources on how transforms work and it takes a bit of time to really understand them (at least for me!), here is some straight-to-the-point code that makes sure to indicate to which axis the transform is applied.
/*!
* Positive `skewX` creates a shift to the left.
* Negative `skewX` creates a shift to the right.
*
* `skewX` is NOT pixel based. Test values of 0.0f - 1.0f.
*/
CGAffineTransform CGAffineTransformMakeSkewX(CGFloat skewX)
{
return CGAffineTransformMakeSkew(skewX, 0.0f);
}
/*!
* Positive `skewY` creates a shift to the bottom.
* Negative `skewY` creates a shift to the top.
*
* `skewY` is NOT pixel based. Test values of 0.0f - 1.0f.
*/
CGAffineTransform CGAffineTransformMakeSkewY(CGFloat skewY)
{
return CGAffineTransformMakeSkew(0.0f, skewY);
}
/*!
* Positive `skewX` creates a shift to the left.
* Negative `skewX` creates a shift to the right.
*
* Positive `skewY` creates a shift to the bottom.
* Negative `skewY` creates a shift to the top.
*
* The skew values are NOT pixel based. Test values of 0.0f - 1.0f.
*/
CGAffineTransform CGAffineTransformMakeSkew(CGFloat skewX, CGFloat skewY)
{
return CGAffineTransformMake(1.0f, skewY, skewX, 1.0f, 0.0f, 0.0f);
}

Can i move the origin when doing a rotation transform in Quartz 2D for the iPhone?

Sorry if this is obvious or covered elsewhere, but i've been googling all day and haven't found a solution that actually worked.
My problem is as follows: I am currently drawing an image in a full screen UIView, for examples sake we'll say the image is in the bottom right corner of the UIView. I'd like to do a rotation transform(CGAffineTransformMakeRotation) at the center of that image, however, by default the rotation command rotates around the center of the UIView it self. As a result, my image moves around the screen when i rotate instead of it staying in place and rotating around its own center.
From what i've gathered, i need to translate my context so that the origin(center of the UIView) is at the center of my image, Rotate, and then restore the context by translating back to the original spot.
The following is the closest thing i've gotten to work, but the problem is that while the image is rotating, it moves downward while it's rotating. I think this is caused by animation tweening the 1st step translate and 3rd step translate instead of just realizing that the beginning and end point on the translates would be the same...
// Before this i'd make a call to a function that draws a path to a passed in context
CGAffineTransform inverseTranslation = CGAffineTransformMakeTranslation( transX, transY );
CGAffineTransform translation = CGAffineTransformMakeTranslation( -transX, -transY );
CGAffineTransform rot = CGAffineTransformMakeRotation( 3.14 );
CGAffineTransform final = CGAffineTransformConcat( CGAffineTransformConcat( inverseTranslation, rot ), translation );
// Then i apply the transformation animation like normal using self.transform = final etc etc
I've also tried stuff like CGContextTranslateCTM and CGContextSaveGState/UIGraphicsPushContext, but these seem to have little effect.
I've been fighting with this for days and my current solution seems close, but i have no clue how to get rid of that translating tweening. Does anyone have a solution for this or a better way to go about this?
[update]
For the time being i'm drawing my image centered at the UIview's center and then setting the UIView.center property to the origin i'd like to rotate and then doing the rotate command. Seems like a bit of a hack, but until i can get the real translates working it's my only choice.
Thanks!
duncanwilcox' answer is the right one, but he left out the part where you change the anchor of the view's layer to the point you want to rotate around.
CGSize sz = theview.bounds.size;
// Anchorpoint coords are between 0.0 and 1.0
theview.layer.anchorPoint = CGPointMake(rotPoint.x/sz.width, rotPoint.y/sz.height);
[UIView beginAnimations:#"rotate" context:nil];
theview.transform = CGAffineTransformMakeRotation( 45. / 180. * M_PI );
[UIView commitAnimations];
This is documented here: http://developer.apple.com/documentation/Cocoa/Conceptual/CoreAnimation_guide/Articles/Layers.html
This is also an option: a simple change of basis ;-)
CGAffineTransform transform = CGAffineTransformMakeTranslation(x, y);
transform = CGAffineTransformRotate(transform, angle);
transform = CGAffineTransformTranslate(transform,-x,-y);
where (x,y) is the rotation center you like
Rotation happens around the anchorPoint of the view's layer. The default for the anchorPoint is the center (0.5, 0.5), so the rotation alone without the translations should suffice.
Did a quick test and this works for me:
[UIView beginAnimations:#"rotate" context:nil];
self.transform = CGAffineTransformMakeRotation( 45. / 180. * 3.14 );
[UIView commitAnimations];
If you don't want an animation to occur, but just set the new rotation, you can use this:
CGFloat newRotation = 3.14f
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.0]; // no tweening
CGAffineTransform transform = CGAffineTransformMakeRotation(newRotation);
self.transform = transform;
[UIView commitAnimations];
The rotation should indeed take place around the center of the UIView. Setting the animationDuration to zero garantees no tweening should happen.
Be sure though you don't do this 60 times a second. It's very tempting to create game like animations with these tools. These kind of animations aren't exactly meant for a frame to frame based, "lots of sprites flying everywhere" game.
For that - and I've been down that road - the only way to go, is OpenGL.