0

I am trying to rotate the rectangle around the circle. So far after putting together some code I found in various places (mainly here: https://stackoverflow.com/a/4657476/861181) , I am able to rotate rectangle around it's center axis.

How can I make it rotate around the circle?

Here is what I have: OverlaySelectionView.h

#import <QuartzCore/QuartzCore.h>

@interface OverlaySelectionView : UIView {
@private
    UIView* dragArea;
    CGRect dragAreaBounds;

    UIView* vectorArea;
    UITouch *currentTouch;
    CGPoint touchLocationpoint;
    CGPoint PrevioustouchLocationpoint;

}
@property    CGRect vectorBounds;
@end

OverlaySelectionView.m

#import "OverlaySelectionView.h"

@interface OverlaySelectionView()
@property (nonatomic, retain) UIView* vectorArea;
@end

@implementation OverlaySelectionView

@synthesize vectorArea, vectorBounds;
@synthesize delegate;

- (void) initialize {

    self.userInteractionEnabled = YES;
    self.multipleTouchEnabled = NO;
    self.backgroundColor = [UIColor clearColor];
    self.opaque = NO;
    self.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;

    UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(rotateVector:)];

    panRecognizer.maximumNumberOfTouches = 1;
    [self addGestureRecognizer:panRecognizer];

}

- (id) initWithCoder: (NSCoder*) coder {
    self = [super initWithCoder: coder];
    if (self != nil) {
        [self initialize];
    }
    return self;
}

- (id) initWithFrame: (CGRect) frame {
    self = [super initWithFrame: frame];
    if (self != nil) {
        [self initialize];
    }
    return self;
}

- (void)drawRect:(CGRect)rect {

    if (vectorBounds.origin.x){

    UIView* area = [[UIView alloc] initWithFrame: vectorBounds];
    area.backgroundColor = [UIColor grayColor];
    area.opaque = YES;

    area.userInteractionEnabled = NO;
    vectorArea = area;
    [self addSubview: vectorArea];
    }

}


- (void)rotateVector: (UIPanGestureRecognizer *)panRecognizer{


    if (touchLocationpoint.x){

            PrevioustouchLocationpoint  = touchLocationpoint;
    }

    if ([panRecognizer numberOfTouches] >= 1){
        touchLocationpoint = [panRecognizer locationOfTouch:0 inView:self];
    }

    CGPoint origin;
    origin.x=240;
    origin.y=160;
    CGPoint previousDifference = [self vectorFromPoint:origin toPoint:PrevioustouchLocationpoint];
    CGAffineTransform newTransform =CGAffineTransformScale(vectorArea.transform, 1, 1);
    CGFloat previousRotation = atan2(previousDifference.y, previousDifference.x);
    CGPoint currentDifference = [self vectorFromPoint:origin toPoint:touchLocationpoint];
    CGFloat currentRotation = atan2(currentDifference.y, currentDifference.x);
    CGFloat newAngle = currentRotation- previousRotation;

    newTransform = CGAffineTransformRotate(newTransform, newAngle);
    [self animateView:vectorArea toPosition:newTransform];

}


-(CGPoint)vectorFromPoint:(CGPoint)firstPoint toPoint:(CGPoint)secondPoint
{
    CGPoint result;
    CGFloat x = secondPoint.x-firstPoint.x;
    CGFloat y = secondPoint.y-firstPoint.y;
    result = CGPointMake(x, y);
    return result;
}


-(void)animateView:(UIView *)theView toPosition:(CGAffineTransform) newTransform
{
    [UIView setAnimationsEnabled:YES];
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:0.0750];
    vectorArea.transform = newTransform;
    [UIView commitAnimations];

}



@end

here is attempt to clarify. I am creating the rectangle from a coordinates on a map. Here is the function that creates that rectangle in the main view. Essentially it is the middle of the screen:

overlay is the view created with the above code.

- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{

    if (!circle){
    circle = [MKCircle circleWithCenterCoordinate: userLocation.coordinate radius:100];

        [mainMapView addOverlay:circle];
        CGPoint centerPoint = [mapView convertCoordinate:userLocation.coordinate toPointToView:self.view];

        CGPoint upPoint = CGPointMake(centerPoint.x, centerPoint.y - 100);

        overlay = [[OverlaySelectionView alloc] initWithFrame: self.view.frame];

        overlay.vectorBounds = CGRectMake(upPoint.x, upPoint.y, 30, 100);

        [self.view addSubview: overlay];


    }


}

Here is the sketch of what I am trying to achieve:

enter image description here

Community
  • 1
  • 1
Stpn
  • 6,202
  • 7
  • 47
  • 94
  • 1
    it does not help if you present more code. Express in words what you want to do. Describe it e.g with a clock where something is rotated. – AlexWien Feb 08 '13 at 01:55
  • oh ok.. I will draw a sketch in minute. – Stpn Feb 08 '13 at 01:57
  • This question is very basic (which is fine), but you might want to read some basic math for computer graphics. This handout looks pretty clear and concise: http://techhouse.brown.edu/~dmorris/cs148_summer_2005/handouts/h03_essential_math.pdf. – Codie CodeMonkey Feb 08 '13 at 08:57

1 Answers1

-1

Introduction
A rotation is always done around (0,0).
What you already know:
To rotate around the center of the rectangle you translate the rect to origin, rotate and translate back.

Now for your question:
to rotate around a center point of a circle, simply move the center of the rectangle such that the circle is at (0,0) then rotate, and move back.

start positioning the rectangle at 12 o clock, with the center line at 12.

1) as explained you always rotate around 0,0, so move the center of the circle to 0,0

  CGAffineTransform trans1 =  CGAffineTransformTranslation(-circ.x, -circ.y);

2) rotate by angle

CGAffineTransform transRot =  CGAffineTransformRotation(angle); // or -angle try out.

3) Move back

CGAffineTransform transBack = CGAffineTransformTranslation(circ.x, circ.y);

Concat these 3 rotation matrices to one combibed matrix, and apply it to the rectangle.

CGAffineTransformation tCombo = CGAffineTransformConcat(trans1, transRot);
tCombo = CGTransformationConcat(tCombo, transback);

Apply

rectangle.transform = tCombo;

You probably should also read the chapter about Transformation matrices in Quartz docu.

This code is written with a text editor only, so expect slighly different function names.

AlexWien
  • 28,470
  • 6
  • 53
  • 83
  • sorry I did not make it clear - when I said I want to rotate around the circle - I meant around the circumference of the circle – Stpn Feb 08 '13 at 01:24
  • this is still not clear expressed. where is the center of the rotation? try to explain much preciser – AlexWien Feb 08 '13 at 01:31
  • Added the sketch with what I am trying to achieve: – Stpn Feb 08 '13 at 02:10
  • my initial answer was correct, i understood what you meant, i gave details now. – AlexWien Feb 08 '13 at 02:31
  • I tried using in your suggestion but it does not really solve it - I don't have circ.x so I used touch location for that, but no luck – Stpn Feb 08 '13 at 02:55
  • circ.x is the center of your blue circle you draw. first try it without touch, simply draw a rectangle rotated, aroud center of the screen lie in your sketch. Once this works, try thebfinals code – AlexWien Feb 08 '13 at 03:02