Cgaffinetransformmakerotation with Negative M_Pi

CGAffineTransformMakeRotation with negative M_PI

As I stated in my first comment and as Segii already wrote: the animation will take the shortest distance between where it's value is at now and where it is trying to go. The best solution imho is to use CABasicAnimation for forcing a counterclockwise rotation:

let anim = CABasicAnimation(keyPath: "transform.rotation")
anim.fromValue = M_PI
anim.toValue = 0
anim.additive = true
anim.duration = 2.0

myView.layer.addAnimation(anim, forKey: "rotate")
myView.transform = CGAffineTransformMakeRotation(CGFloat(-M_PI))

This will rotate it by 180 counter clockwise in one go.

The angle you specify in the last line + the fromValue is the starting angle -> 0. And then the rotation will go the distance (toValue - fromValue) = 0 - M_PI = - M_PI -> counter clockwise 180 degree rotation.

CGAffineTransformRotate and M_PI inconsistencies (Objective-C, iOS)

The problem is you can't really control the rotation direction when using animateWithDuration. It will always take the shortest route. When rotating 180 degrees the behavior is undetermined because in theory there are 2 possibilities for the shortest route. This also explains why you can't rotate more than 180 degrees. If you want to have more control over the animation or do more complex animations use a CAKeyframeAnimation.

About CGAffineTransformMakeRotation rotation direction?

This is an error in documentation.

Here they describe matrix and provide equations which they use to do the transform:

Sample Image

If you do the math, you'll see that for positive angles, it gives rotation counterclockwise when Y axis direction is upwards as in OS X and clockwise when Y axis directed downwards as in iOS

For example you may try to transform point (5,0) with 90 degrees, you will get (0,5), which means clockwise for iOS and counterclockwise for OS X.

The same piece of documentation still have the (false) part you quoted:

In iOS, a positive value specifies counterclockwise
rotation and a negative value specifies clockwise rotation. In OS X, a
positive value specifies clockwise rotation and a negative value
specifies counterclockwise rotation.

Which is clearly wrong, because the equations (which are the part of the same document and are pretty standard rotation equations) say the opposite.

CGAffineTransformMakeRotation on AnnotationViews

As a matter of fact, for a reason I ignore, it was enough to assign the angle in the animation for the annotation view to appropriately rotate: this is the upadated code including a chunk for reversing the annotation if pointing towards the left:
BOOL oldVerticalInverted=NO;
#define degreesToRadians(x) (M_PI * x / 180.0)
#define radiandsToDegrees(x) (x * 180.0 / M_PI)

-(void)adjustAnnotationFor:(CLLocationCoordinate2D)start ToCoordinates:(CLLocationCoordinate2D)end completion:(void (^)(void))completion{
__block float newAngle=[Line angleFromCoordinate:start toCoordinate:end];
__block float angle2Rotate=self.angle;
__block BusAnnotation* blockSelf=self;
__block BOOL blockOldInverted=oldVerticalInverted;
NSLog(@"setto angle a %f cos=%f", self.angle, cos(self.angle));
if (view!=nil){
dispatch_async(dispatch_get_main_queue(), ^{
[UIView animateWithDuration:1 animations:^{
blockSelf.angle=newAngle;
BOOL verticallyInverted=cos(blockSelf.angle)<0;
int invertVertical=blockOldInverted==verticallyInverted?1:-1;
blockOldInverted=verticallyInverted;
CGAffineTransform affineInvert=CGAffineTransformMakeScale(1, invertVertical);
view.transform=CGAffineTransformConcat(CGAffineTransformIdentity, affineInvert);

}
completion :^(BOOL finished){
if (completion) completion();
}];
});
}
}

The only remaining issue is how to reverse a text I have burnt inside the annotationView and that would be reversed when pointing towards the left: that is how I make this latter part:

-(UIImage *)burnText:(NSString *)text ofBackColor:(UIColor*)color intoImage:(UIImage *)img inRect:(CGRect)aRect font:(UIFont*) font{

UIGraphicsBeginImageContextWithOptions(img.size,NO,0.0);

CGRect aRectangle = CGRectMake(0,0, img.size.width, img.size.height);
[img drawInRect:aRectangle];
NSMutableParagraphStyle *textStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
textStyle.lineBreakMode = NSLineBreakByTruncatingTail;
textStyle.alignment=NSTextAlignmentCenter;

NSDictionary *dictionary = @{ NSFontAttributeName: font,
NSParagraphStyleAttributeName: textStyle,
NSForegroundColorAttributeName: [UIColor blackColor],
NSBackgroundColorAttributeName: color};
[text drawInRect:aRect withAttributes:dictionary];
UIImage *theImage=UIGraphicsGetImageFromCurrentImageContext(); // extract the image
UIGraphicsEndImageContext(); // clean up the context.
theImage.accessibilityValue=text;
return theImage;
}

Rotate UIImageView with same center point using CGAffineTransformMakeRotation

Turns out the weird rotation issue was related to the new iOS 6 autolayout feature. Once I took some time to understand how the align constraints worked I was able to achieve the results I wanted.

If you run into weird rotation issues and are using iOS 6 with autolayout enabled chances are your constraints need adjusting.

The key is to vertically and horizontally center the image under rotation in it's parent view.

iOS: How to rotate UIImageView around center point?

From my above comment: You can simply reset the transformation with

hourHand.transform = CGAffineTransformMakeRotation(0);
// or:
hourHand.transform = CGAffineTransformIdentity;

and there is no need to remember rotationBackHour. (Setting the transform does not accumulate.)

Note also that you can simplify your code to

hourHand.transform = CGAffineTransformMakeRotation((hourHandLocation + 1)*M_PI/6.0);
hourCorrectAnswer = [NSString stringWithFormat:@"%d", hourHandLocation + 1];

make the many if-blocks obsolete.

The "appears sometimes in random positions" problem is caused by Autolayout or by the Autosizing options. Either switch them off or fix them such that the size and relative position of the hours/minute view to the clock does not change.

how To detect that cgaffinetransformrotate method is rotating the clockwise or anticlockwise?

YourView.transform = CGAffineTransformMakeRotation( positive value ); 
will rotate the view clockwise, and
YourView.transform = CGAffineTransformMakeRotation( Negative value ); 
will rotate the view Anti clockwise,

CGAffineTransform rotation goes the wrong way

Your confusion is quite understandable.

In truth, a positive angle represents a rotation from the positive X axis toward the positive Y axis. A negative angle represents a rotation from the positive X axis toward the negative Y axis.

The “native” Core Graphics coordinate system is modeled after the standard Cartesian coordinate system, in which the Y axis increases upward on the page. In this system, a positive angle represents a counter-clockwise rotation:

normal coordinate system

So if you create your own CGContext (for example, by using CGBitmapContextCreate or CGPDFContextCreate), rotations will work as you expect.

However, computer systems have historically used a coordinate system in which the Y axis increases downward on the page. In a flipped coordinate system like this, a positive angle represents a clockwise rotation:

flipped coordinate system

Notice that in both coordinate systems, a positive angle rotates from the positive X axis toward the positive Y axis.

It turns out that UIKit flips the coordinate system of the graphics contexts that it creates for you. This includes the graphics context it sets up before sending you drawRect: and the graphics context it sets up in UIGraphicsBeginImageContext. (The Quartz 2D Programming Guide explains this.) You can check this by looking at the current transform matrix (using CGContextGetCTM). You will find that it has a -1 in its d element, meaning that the Y axis is flipped.

A UIView also uses a flipped coordinate system for laying out its subviews, which affects the meaning of the UIView transform property.



Related Topics



Leave a reply



Submit