A CGAffineTransform with rotation and translation, what different? - ios

There are:
1.
CGAffineTransform layerTransform = CGAffineTransformMakeRotation(M_PI_2);
layerTransform = CGAffineTransformTranslate(layerTransform, 1080, 0);
2.
CGAffineTransform layerTransform = CGAffineTransformMakeTranslation(1080, 0);
layerTransform = CGAffineTransformRotate(layerTransform, M_PI_2);
What's the different between them ?
Rotate before or after translate, is there any different?

CGAffineTransformTranslate is basically create a new affine transform by translating (moving) existing affine transform with specified method. We have to use CGAffineTransform CGAffineTransformTranslate ( CGAffineTransform t, CGFloat tx, CGFloat ty ) method for it. Here tx and ty has the values by which new affine transform have to move in X and Y direction respectively.
CGAffineTransformRotate is basically create a new affine transform by rotating existing transform with specified method. We have to use CGAffineTransform CGAffineTransformRotate ( CGAffineTransform t, CGFloat angle ) method for it. Here angle has the rotation angle for new affine transform.
I hope, you can get that first one is used to get a shift from one position to another one, and second one is used to get a roation.

The thing you need to know is that translation means move the location.
Rotation is self explanatory.
The order does matter depending on the origin point and the effect you want to achieve.
I'm Core Graphics this is lower left on a OS X and upper left on iOS.
In Core Animation objects can be transformed more easily by their center points.
CG works with rects though.
The most common hurtful thing is trying to rotate something about its center in CG.
If you just rotate transform the thing will appear to rotate around its origin like the hand of a clock.
So if you move the origin then rotate, you you can compensate for this.
The math is not easy unless you know trig and radians.
The trick is that you need to apply both transformations before drawing again or the thing will jump about.

Related

Transform Image to four projected points in iOS

I have four points and I would like to draw an UIImageView with corners in those four points.
The four points represent an arbitrary rectangle (might be a trapez or a parallelogram).
I guess I somehow need to make a transform from those four points, but I'm not quite sure how.
Any suggestions?
Other solutions?
Look at https://math.stackexchange.com/questions/169176/2d-transformation-matrix-to-make-a-trapezoid-out-of-a-rectangle to determine your transformation matrix.
Note that you cannot use a 2D matrix so you have to use a CATransform3D.
CATransform3D transform = CATransform3DIdentity;
// update transform elements, .m11, .m12, .m13, etc.
imageView.layer.transform = transform;

CoreGraphics: Use coordinates from 0 to 1?

Is it possible to use a normalized coordinate system (from 0.0 to 1.0) instead of using pixel coordinates when drawing stuff with CoreGraphics? It would certainly make a lot of things easier...
Yes, use a CGAffineTransform. I do this in an app. keep all coordinates normalized to -1.0 to 1.0, create a transform based on the size of the view I am drawing into.
Example:
CGAffineTransform translateTransform = CGAffineTransformMakeTranslation(offset.x, offset.y);
One can transform each point or create a path and transform the entire path:
CGMutablePathRef transformedPath = CGPathCreateMutable();
CGPathAddPath(transformedPath, &transform, path);
As #yurish points out one can also use CGContextScaleCTM, CGContextTranslateCTM, etc. instead of scaling the points/path if that works better for you.
Core graphics does not use pixel coordinates. It uses abstract points that are converted to pixels using current transformation matrix (CTM). You can use the normalized coordinate system if you adjust CTM appropriately (CGContextScaleCTM etc) .

Apply a perspective transform without rotating

I have been trying to perform a perspective transform on a UIView. I have been working from this example.
However, that example applies a rotation on the view as well as a perspective change. Is there a way to change the perspective of the view with no rotation? Something that might look like this:
I have been trying to remove the rotation, but when I do the perspective transform does not get applied. I can't find any examples out there that deal with just changing the perspective. Thanks in advance.
Just adding to David's answer: To get an output as in your image you have to rotate the view around the x-axis (the horizontal axis) so that the upper edge of the view rectangle appears "further away" from the viewer than the lower edge, e.g.
CATransform3D rotationAndPerspectiveTransform = CATransform3DIdentity;
rotationAndPerspectiveTransform.m34 = 1.0 / -200;
rotationAndPerspectiveTransform = CATransform3DRotate(rotationAndPerspectiveTransform, 45.0f * M_PI / 180.0f, 1.0f, 0.0f, 0.0f);
layer.transform = rotationAndPerspectiveTransform;
Perspective won't be visible without any rotation relative to your view point. The perspective does still get applied even when you don't rotate but it won't be very visible.
One other transform that shows perspective is translating along Z which makes the view look like it is being scaled.

Rotate AVAssetWriter's output 180 deg about the x-axis

I'm creating a Quicktime movie file using AVAssetWriter. Currently the output video is "upside down". In theory I can correct this by rotating the video 180 degrees about the horizontal axis (essentially "flipping" the video). What's the best way to do this?
Currently I'm trying to assign a CGAffineTransform to myAVAssetWriterInput.transform. Perhaps CGAffineTransformMake(a, b, c, d, tx, ty) will allow me to specify the correct affine transformation matrix?
Neither the Apple docs nor wikipedia gives a clear explanation on how an affine transformation matrix works. And there might be a better way all together.
myAVAssetWriterInput.transform = CGAffineTransformMakeRotation(M_PI);
if you want to rotate the video 180 degrees around z-axis, or
myAVAssetWriterInput.transform = CGAffineTransformMakeScale(1, -1);
if you want to reflect in x-axis
[AVAssetTrack preferredTransform] will return the right CGAffineTransform.
You can assign this CGAffineTransform to writeInput.

How to distort a Sprite into a trapezoid?

I am trying to transform a Sprite into a trapezoid, I don't really care about the interpolation even though I know without it my image will lose detail. All I really want to do is Transform my rectangular Sprite into a trapezoid like this:
/ \
/ \
/__________\
Has anyone done this with CGAffineTransforms or with cocos2d?
The transformation you're proposing is not affine. Affine transformations have to be undoable. So they can typically:
Scale
Rotate
Shear (make lopsided, like square -> parallelogram)
Translate
But they cannot "squeeze". Notice that the left and right sides of your trapezoid, if extended, would intersect at a particular spot. They're not parallel anymore. So you couldn't "undo" the transformation, because if there was anything to transform at that spot, you couldn't decide where they would transform to. In other words, if a transformation doesn't preserve parallelism, it pinches space, can't be undone, and isn't affine.
I don't know that much about transformations in Core Animation, so I hope that mathy stuff helps you find an alternative.
But I do know how you could do it in OpenGL, but it would require you to start over on how you draw your application:
If I'm envisioning the result you want correctly, you want to build your rectangle in 3D, use an affine transformation to rotate it away a little bit, and use a (non-affine) projection transformation to flatten it into a 2D image.
If you're not looking for a 3D effect, but you really just want to pinch in the corners, then you can specify a GL_RECT with the points of your trapezoid and map your sprite onto it as a texture.
The easiest thing might be to pre-squeeze your image in a photo editor, save it as a .png with transparency, and draw a rectangle with that image.
You need to apply a CATransform3D to the layer of the UIView.
To find out the right one, it is easier to use AGGeometryKit.
#import <AGGeometryKit/AGGeometryKit.h>
UIView *view = ...; // create a view
view.layer.anchorPoint = CGPointZero;
AGKQuad quad = view.layer.quadrilateral;
quad.tl.x += 20; // shift top left x-value with 20 pixels
quad.tr.x -= 20; // shift top right x-value with 20 pixels
view.layer.quadrilateral = quad; // the quad is converted to CATransform3D and applied

Resources