Rotate rectangle around center

core-animation, core-graphics, ios, iphone

Solution

You need to set the `imageLayer.zPosition` of each of the triangle sides to the distance from the center of the triangle (which is an equilateral triangle in your case).

If `sideHeight = self.bounds.size.height / 2.0f;` Then `distanceFromCenter = ((sideHeight / 2.0f) / sqrt(3));`

Also, when setting the rotation on the sides, you need to move them into their required positions (in your code they are hardcoded).

Updated Code

- (void)awakeFromNib
{
    transformed = [CALayer layer];
    transformed.anchorPoint = CGPointMake(0.5f, 0.5f);

    transformed.frame = self.bounds;
    [self.layer addSublayer:transformed];

    CGFloat sideHeight = self.bounds.size.height / 2.0f;
    CGFloat distanceFromCenter = ((sideHeight / 2.0f) / sqrt(3));

    CGFloat sideC = sideHeight / 2.0f;
    CGFloat sideA = sideC / 2.0f;
    CGFloat sideB = (sqrt(3) * sideA);

    CALayer *imageLayer = [CALayer layer];
    imageLayer.frame = CGRectMake(10.0f, (self.bounds.size.height / 2.0f) - (sideHeight / 2.0f), self.bounds.size.width / 2.0f, sideHeight);
    imageLayer.transform = CATransform3DConcat(CATransform3DMakeRotation(-DEGREES_TO_RADIANS(60.0f), 1.0f, 0.0f, 0.0f),
                                               CATransform3DMakeTranslation(0, -sideA, -sideB));
    imageLayer.contents = (id)[[UIImage imageNamed:@"IMG_0051.png"] CGImage];
    imageLayer.borderColor = [UIColor yellowColor].CGColor;
    imageLayer.borderWidth = 2.0f;
    imageLayer.zPosition = distanceFromCenter;
    [transformed addSublayer:imageLayer];

    imageLayer = [CALayer layer];
    imageLayer.frame = CGRectMake(10.0f, (self.bounds.size.height / 2.0f) - (sideHeight / 2.0f), self.bounds.size.width / 2.0f, sideHeight);
    imageLayer.transform = CATransform3DConcat(CATransform3DMakeRotation(DEGREES_TO_RADIANS(60.0f), 1.0f, 0.0f, 0.0f),
                                               CATransform3DMakeTranslation(0, sideA, -sideB));
    imageLayer.contents = (id)[[UIImage imageNamed:@"IMG_0089.png"] CGImage];
    imageLayer.borderColor = [UIColor greenColor].CGColor;
    imageLayer.zPosition = distanceFromCenter;
    imageLayer.borderWidth = 2.0f;

    transformed.borderColor = [UIColor whiteColor].CGColor;
    transformed.borderWidth = 2.0f;
    [transformed addSublayer:imageLayer];

    UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height / 2.0f, self.bounds.size.width, 2)];
    [line setBackgroundColor:[UIColor redColor]];
    [self addSubview:line];

    line = [[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height * (1.0f / 4.0f), self.bounds.size.width, 2)];
    [line setBackgroundColor:[UIColor blueColor]];
    [self addSubview:line];

    line = [[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height * (3.0f / 4.0f), self.bounds.size.width, 2)];
    [line setBackgroundColor:[UIColor blueColor]];
    [self addSubview:line];
}

Problem

I am playing with Brad Larsen's adaption of the trackball app. I have two views at a 60 degree angle to each other and was wondering how I get the rotation to be in the center of this (non-closed) rectangle? In the images below I would have liked the rotation to take place all within the blue lines. Code (modified to only rotate around x axis): ``` #import "MyView.h" //===================================================== // Defines //===================================================== #define DEGREES_TO_RADIANS(degrees) \ (degrees * (M_PI / 180.0f)) //===================================================== // Public Interface //===================================================== @implementation MyView - (void)awakeFromNib { transformed = [CALayer layer]; transformed.anchorPoint = CGPointMake(0.5f, 0.5f); transformed.frame = self.bounds; [self.layer addSublayer:transformed]; CALayer *imageLayer = [CALayer layer]; imageLayer.frame = CGRectMake(10.0f, 4.0f, self.bounds.size.width / 2.0f, self.bounds.size.height / 2.0f); imageLayer.transform = CATransform3DMakeRotation(DEGREES_TO_RADIANS(60.0f), 1.0f, 0.0f, 0.0f); imageLayer.contents = (id)[[UIImage imageNamed:@"IMG_0051.png"] CGImage]; imageLayer.borderColor = [UIColor yellowColor].CGColor; imageLayer.borderWidth = 2.0f; [transformed addSublayer:imageLayer]; imageLayer = [CALayer layer]; imageLayer.frame = CGRectMake(10.0f, 120.0f, self.bounds.size.width / 2.0f, self.bounds.size.height / 2.0f); imageLayer.transform = CATransform3DMakeRotation(DEGREES_TO_RADIANS(-60.0f), 1.0f, 0.0f, 0.0f); imageLayer.contents = (id)[[UIImage imageNamed:@"IMG_0089.png"] CGImage]; imageLayer.borderColor = [UIColor greenColor].CGColor; imageLayer.borderWidth = 2.0f; transformed.borderColor = [UIColor whiteColor].CGColor; transformed.borderWidth = 2.0f; [transformed addSublayer:imageLayer]; UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height / 2.0f, self.bounds.size.width, 2)]; [line setBackgroundColor:[UIColor redColor]]; [self addSubview:line]; line = [[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height * (1.0f / 4.0f), self.bounds.size.width, 2)]; [line setBackgroundColor:[UIColor blueColor]]; [self addSubview:line]; line = [[UIView alloc] initWithFrame:CGRectMake(0, self.bounds.size.height * (3.0f / 4.0f), self.bounds.size.width, 2)]; [line setBackgroundColor:[UIColor blueColor]]; [self addSubview:line]; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { previousLocation = [[touches anyObject] locationInView:self]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { CGPoint location = [[touches anyObject] locationInView:self]; //location = CGPointMake(previousLocation.x, location.y); CATransform3D currentTransform = transformed.sublayerTransform; //CGFloat displacementInX = location.x - previousLocation.x; CGFloat displacementInX = previousLocation.x - location.x; CGFloat displacementInY = previousLocation.y - location.y; CGFloat totalRotation = sqrt((displacementInX * displacementInX) + (displacementInY * displacementInY)); CGFloat angle = DEGREES_TO_RADIANS(totalRotation); CGFloat x = ((displacementInX / totalRotation) * currentTransform.m12 + (displacementInY/totalRotation) * currentTransform.m11); CATransform3D rotationalTransform = CATransform3DRotate(currentTransform, angle, x, 0, 0); previousLocation = location; transformed.sublayerTransform = rotationalTransform; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { } - (void)dealloc { [super dealloc]; } @end ```

Original source