Wrong touch point location in UIView after rotatation - ios

I'm trying to make a custom button using a UIView and when touched on a specific part of the view perform an action, for example when touching the left part of the view log LEFT and when touching the Right part of the view log RIGHT.
I'm using touchesBegan and touchesEnded to detect touch.
Everything works fine when in portrait mode, however, once rotated to landscape mode it doesn't work, the view is displayed in the right place and the touch on the view is detected but it seems the touch point is not in the correct x,y coordinates so I can't detect the LEFT/RIGHT touches correctly.
Couldn't find any previous answers here that helped me.
Tried looking into CGAffineTransform, but still can't fix it.
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"round_directions_button_default.png"]];
self.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin;
topLeft = CGPointMake(self.frame.origin.x, self.frame.origin.y);
topRight = CGPointMake(self.frame.origin.x + 105, self.frame.origin.y);
bottomLeft = CGPointMake(self.frame.origin.x, self.frame.origin.y + 105);
bottomRight = CGPointMake(self.frame.origin.x + 105, self.frame.origin.y + 105);
NSLog(#"topLeft: x = %f, y = %f", topLeft.x, topLeft.y);
NSLog(#"topRight: x = %f, y = %f", topRight.x, topRight.y);
NSLog(#"bottomLeft: x = %f, y = %f", bottomLeft.x, bottomLeft.y);
NSLog(#"bottomRight: x = %f, y = %f", bottomRight.x, bottomRight.y);
NSLog(#"self.center: x = %f, y = %f", self.center.x, self.center.y);
}
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"topLeft: x = %f, y = %f", topLeft.x, topLeft.y);
NSLog(#"topRight: x = %f, y = %f", topRight.x, topRight.y);
NSLog(#"bottomLeft: x = %f, y = %f", bottomLeft.x, bottomLeft.y);
NSLog(#"bottomRight: x = %f, y = %f", bottomRight.x, bottomRight.y);
NSLog(#"self.center: x = %f, y = %f", self.center.x, self.center.y);
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:nil];
NSLog(#"touchesBegan: touchPoint: x = %f, y = %f", touchPoint.x, touchPoint.y);
if ([self isPoint:touchPoint inTriangle:topLeft :self.center :topRight]) {
NSLog(#"touchesBegan: UP");
direction = 1;
self.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"round_directions_button_pressed_up.png"]];
} else if ([self isPoint:touchPoint inTriangle:bottomLeft :self.center :bottomRight]) {
NSLog(#"touchesBegan: DOWN");
direction = 2;
self.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"round_directions_button_pressed_down.png"]];
} else if ([self isPoint:touchPoint inTriangle:topLeft :self.center :bottomLeft]) {
NSLog(#"touchesBegan: LEFT");
direction = 3;
self.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"round_directions_button_pressed_left.png"]];
} else if ([self isPoint:touchPoint inTriangle:topRight :self.center :bottomRight]) {
NSLog(#"touchesBegan: RIGHT");
direction = 4;
self.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"round_directions_button_pressed_right.png"]];
} else {
NSLog(#"touchesBegan: NOTHING");
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
self.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"round_directions_button_default.png"]];
}
- (BOOL) isPoint:(CGPoint)point inTriangle:(CGPoint)v1 :(CGPoint)v2 :(CGPoint)v3 {
BOOL b1, b2, b3;
b1 = ((point.x - v2.x) * (v1.y - v2.y) - (v1.x - v2.x) * (point.y - v2.y)) < 0.0f;
b2 = ((point.x - v3.x) * (v2.y - v3.y) - (v2.x - v3.x) * (point.y - v3.y)) < 0.0f;
b3 = ((point.x - v1.x) * (v3.y - v1.y) - (v3.x - v1.x) * (point.y - v1.y)) < 0.0f;
return ((b1 == b2) && (b2 == b3));
}
in view controller viewDidLoad:
CustomButton *customButton = [[CustomButton alloc] initWithFrame:CGRectMake(1, self.view.bounds.size.height - 106, 105, 105)];
[self.view addSubview:customButton];
Any help will be appreciated.
Thanks

If the size of the button doesn't change with rotation you can set points just once inside initWithFrame and use bounds instead of frame.
topLeft = CGPointMake(0, 0);
topRight = CGPointMake(self.bounds.size.width, 0);
bottomLeft = CGPointMake(0, self.bounds.size.height);
bottomRight = CGPointMake(self.bounds.size.width, self.bounds.size.height);
Then in touchesBegan use [touch locationInView:self]; to get the touch location in the button own coordinate system.
If the size changes, a solution can be to recalculate points on every touch so place the above code inside touchesBegan.
EDIT:
If you want to use local button coordinate you have to calculate the center because self.center contains center point of the view in the superview’s coordinate system.

Related

touchesmoved screen bounds, how can I restrict the movement of the rect out of the screen bounds

I'am trying to restrict the movement of the rect by the screen bounds. The logic is simple, you tap inside the rect (doesn't metter where) and drag it. It follows your finger, and it has to be stoped when the border of the rect reached the bounds of the screen.
- (void)viewDidLoad {
[super viewDidLoad];
rect.backgroundColor = [UIColor redColor];
}
then I try to figure out where the tap is and if its inside the rect I change the color of the rect
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//NSLog(#"%s", __PRETTY_FUNCTION__);
UITouch *touch = touches.anyObject;
if (touch.view == rect) {
rect.backgroundColor = [UIColor greenColor];
isSelectedRect = YES;
CGPoint point = [touch locationInView:self.view];
CGPoint center = rect.center;
delta = CGPointMake(point.x - center.x,
point.y - center.y);
} else {
rect.backgroundColor = [UIColor redColor];
isSelectedRect = NO;
}
}
after that I move this rect
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//NSLog(#"%s", __PRETTY_FUNCTION__);
if (isSelectedRect) {
UITouch *touch = touches.anyObject;
CGPoint point = [touch locationInView:self.view];
rect.center = CGPointMake(point.x - delta.x,
point.y - delta.y);
}
}
Eventualy, I need to write one line of the code which will limit the movement the rect by bounds of the screeen. I and it would be perfect to make it with ternary operator. I would appreciate any help.
Replace your touchesMoved method with the code below. Hope it can help you ;)
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//NSLog(#"%s", __PRETTY_FUNCTION__);
if (isSelectedRect) {
UITouch *touch = touches.anyObject;
CGPoint point = [touch locationInView:self.view];
CGPoint newCenter = CGPointMake(point.x - delta.x,
point.y - delta.y);
CGFloat rectHeight = rect.frame.size.height;
CGFloat rectWidth = rect.frame.size.width;
CGFloat screenWidth = self.view.frame.size.width;
CGFloat screenHeight = self.view.frame.size.height;
if (newCenter.x + rectWidth / 2 > screenWidth) {
newCenter.x = screenWidth - rectWidth / 2;
}
if (newCenter.x - rectWidth / 2 < 0) {
newCenter.x = rectWidth / 2;
}
if (newCenter.y + rectHeight / 2 > screenHeight) {
newCenter.y = screenHeight - rectHeight / 2;
}
if (newCenter.y - rectHeight / 2 >= 0) {
newCenter.y = rectHeight / 2;
}
rect.center = newCenter;
}
}
if (CGRectContainsPoint(boundsRect, point)) {
rect.center = CGPointMake(point.x - delta.x,
point.y - delta.y);
}
Here, boundsRect will be the Rectangle of device.
You have to note that the point which you are moving in touchesMoved function is the center point of the view. In order to restrict them from going outside the viewBounds you must check whether the bounds of the draggable view is exceeding your translation point.
to get the actual bounds
CGPoint center = rect.center;
CGSize size = rect.size
CGRect originalRect = CGRectMake(center.x - size.width/2, center.y - size.height/2, size.width, size.height);
Now check whether the given rect is within the desired rect.
if (CGRectContainsRect(boundsRect, originalRect)) {
// Here change the center of the view
}
I Hope this helps.

iOS: Resize and Rotate UIView Concurrently

Using a UIPanGestureRecognizer in my view controller, I'm trying to draw a view (ArrowView) at an angle based upon the touch location. I'm trying to use CGAffineTransformRotate to rotate the view based up the angle between the first touch and the current touch, but this isn't working unless the view has already been drawn by at lease 20 or more pixels. Also, when drawing, the view doesn't always line up under my finger. Is this the correct approach for this situation? If not, does anyone recommend a better way of accomplishing this? If so, what am I doing wrong?
ViewController.m
#implementation ViewController {
ArrowView *_selectedArrowView;
UIColor *_selectedColor;
CGFloat _selectedWeight;
CGPoint _startPoint;
}
- (void)viewDidLoad {
[super viewDidLoad];
_selectedColor = [UIColor yellowColor];
_selectedWeight = 3;
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panHandler:)];
[self.view addGestureRecognizer:pan];
}
- (void) panHandler: (UIPanGestureRecognizer *) sender {
if (sender.state == UIGestureRecognizerStateBegan) {
//Instantiate the arrow
CGPoint touchPoint = [sender locationInView:sender.view];
_startPoint = touchPoint;
_selectedArrowView = [[ArrowView alloc] initWithFrame:CGRectMake(touchPoint.x, touchPoint.y, 0, 25) withColor:_selectedColor withWeight:_selectedWeight];
_selectedArrowView.delegate = self;
[self.view addSubview:_selectedArrowView];
[self.view bringSubviewToFront:_selectedArrowView];
} else if (sender.state == UIGestureRecognizerStateChanged) {
//"Draw" the arrow based upon finger postion
CGPoint touchPoint = [sender locationInView:sender.view];
[_selectedArrowView drawArrow:_startPoint to:touchPoint];
}
}
#end
ArrowView.m
- (void) drawArrow: (CGPoint) startPoint to: (CGPoint) endPoint {
startPoint = [self convertPoint:startPoint fromView:self.superview];
endPoint = [self convertPoint:endPoint fromView:self.superview];
if (_initialAngle == -1000 /*Initially set to an arbitrary value so I know when the draw began*/) {
_initialAngle = atan2(startPoint.y - endPoint.y, startPoint.x - endPoint.x);
[self setPosition:0];
} else {
CGFloat ang = atan2(startPoint.y - endPoint.y, startPoint.x - endPoint.x);
ang -= _initialAngle;
self.transform = CGAffineTransformRotate(self.transform, ang);
CGFloat diff = (endPoint.x - self.bounds.size.width);
NSLog(#"\n\n diff: %f \n\n", diff);
self.bounds = CGRectMake(0, 0, self.bounds.size.width + diff, self.bounds.size.height);
_endPoint = CGPointMake(self.bounds.size.width, self.bounds.size.height);
[self setNeedsDisplay];
}
}
- (void) setPosition: (CGFloat) anchorPointX {
CGPoint layerLoc;
if (anchorPointX == 0) {
layerLoc = CGPointMake(self.layer.bounds.origin.x, self.layer.bounds.origin.y + (self.layer.bounds.size.height / 2));
} else {
layerLoc = CGPointMake(self.layer.bounds.origin.x + self.layer.bounds.size.width, self.layer.bounds.origin.y + (self.layer.bounds.size.height / 2));
}
CGPoint superLoc = [self convertPoint:layerLoc toView:self.superview];
self.layer.anchorPoint = CGPointMake(anchorPointX, 0.5);
self.layer.position = superLoc;
}
- (CGFloat) pToA: (CGPoint) touchPoint {
CGPoint start;
if (_dotButtonIndex == kDotButtonFirst) {
start = CGPointMake(CGRectGetMaxX(self.bounds), CGRectGetMaxY(self.bounds));
} else {
start = CGPointMake(CGRectGetMinX(self.bounds), CGRectGetMinY(self.bounds));
}
return atan2(start.y - touchPoint.y, start.x - touchPoint.x);
}
Link to project on GitHub: Project Link
Figured it out.
I had to make it have an initial width so the angle would work.
_initialAngle = atan2(startPoint.y - endPoint.y, startPoint.x - (endPoint.x + self.frame.size.width));

Pinching/Panning a CCNode in Cocos2d 3.0

I want to zoom in out a CCNode by pinching and panning the screen. The node has a background which is very large but the portionof it shown on the screen. That node also contains other sprites.
What I have done by now is that first I register UIPinchGestureRecognizer
UIPinchGestureRecognizer * pinchRecognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(handlePinchFrom:)];
[[[CCDirector sharedDirector] view] addGestureRecognizer: pinchRecognizer];
-(void)handlePinchFrom:(UIPinchGestureRecognizer *) pinch
{
if(pinch.state == UIGestureRecognizerStateEnded) {
prevScale = 1;
}
else {
CGFloat dscale = [self scale] - prevScale + pinch.scale;
if(dscale > 0)
{
deltaScale = dscale;
}
CGAffineTransform transform = CGAffineTransformScale(pinch.view.transform, deltaScale, deltaScale);
[pinch.view setTransform: transform];
// [_contentNode setScale:deltaScale];
prevScale = pinch.scale;
}
}
The problem is that it scalw whole UIView not the CCNode. I have also tried to by setting the scale of my _contentNode.
**EDIT
I ave also tried this
- (void)handlePinchGesture:(UIPinchGestureRecognizer*)aPinchGestureRecognizer
{
if (pinch.state == UIGestureRecognizerStateBegan || pinch.state == UIGestureRecognizerStateChanged) {
CGPoint midpoint = [pinch locationInView:[CCDirector sharedDirector].view];
CGSize winSize = [CCDirector sharedDirector].viewSize;
float x = midpoint.x/winSize.width;
float y = midpoint.y/winSize.height;
_contentNode.anchorPoint = CGPointMake(x, y);
float scale = [pinch scale];
_contentNode.scale *= scale;
pinch.scale = 1;
}
}
But it zoom from the bottom left of the screen.
I had the same problem. I use CCScrollView, that contains CCNode that larger than device screen. I want scroll and zoom it, but node shouldnt scroll out of screen, and scale smaller than screen. So, i create my subclass of CCScrollView, where i handle pinch. It has some strange glitches, but it works fine at all.
When pinch began i set anchor point of my node to pinch center on node space. Then i need change position of my node proportional to shift of anchor point, so moving anchor point doesn't change nodes location on view:
- (void)handlePinch:(UIPinchGestureRecognizer*)recognizer
{
if (recognizer.state == UIGestureRecognizerStateEnded) {
_previousScale = self.contentNode.scale;
}
else if (recognizer.state == UIGestureRecognizerStateBegan) {
float X = [recognizer locationInNode:self.contentNode].x / self.contentNode.contentSize.width;
float Y = [recognizer locationInNode:self.contentNode].y / self.contentNode.contentSize.height;
float positionX = self.contentNode.position.x + self.contentNode.boundingBox.size.width * (X - self.contentNode.anchorPoint.x);
float positionY = self.contentNode.position.y + self.contentNode.boundingBox.size.height * (Y - self.contentNode.anchorPoint.y);
self.contentNode.anchorPoint = ccp(X, Y);
self.contentNode.position = ccp(positionX, positionY);
}
else {
CGFloat scale = _previousScale * recognizer.scale;
if (scale >= maxScale) {
self.contentNode.scale = maxScale;
}
else if (scale <= [self minScale]) {
self.contentNode.scale = [self minScale];
}
else {
self.contentNode.scale = scale;
}
}
}
Also i need change CCScrollView min and max scroll, so my node never scroll out of view. Default anchor point is (0,1), so i need shift min and max scroll proportional to the new anchor point.
- (float) maxScrollX
{
if (!self.contentNode) return 0;
float maxScroll = self.contentNode.boundingBox.size.width - self.contentSizeInPoints.width;
if (maxScroll < 0) maxScroll = 0;
return maxScroll - self.contentNode.boundingBox.size.width * self.contentNode.anchorPoint.x;
}
- (float) maxScrollY
{
if (!self.contentNode) return 0;
float maxScroll = self.contentNode.boundingBox.size.height - self.contentSizeInPoints.height;
if (maxScroll < 0) maxScroll = 0;
return maxScroll - self.contentNode.boundingBox.size.height * (1 - self.contentNode.anchorPoint.y);
}
- (float) minScrollX
{
float minScroll = [super minScrollX];
return minScroll - self.contentNode.boundingBox.size.width * self.contentNode.anchorPoint.x;
}
- (float) minScrollY
{
float minScroll = [super minScrollY];
return minScroll - self.contentNode.boundingBox.size.height * (1 - self.contentNode.anchorPoint.y);
}
UIGestureRecognizerStateEnded doesn't have locationInNode: method, so i added it by category. It just return touch location on node space:
#import "UIGestureRecognizer+locationInNode.h"
#implementation UIGestureRecognizer (locationInNode)
- (CGPoint) locationInNode:(CCNode*) node
{
CCDirector* dir = [CCDirector sharedDirector];
CGPoint touchLocation = [self locationInView: [self view]];
touchLocation = [dir convertToGL: touchLocation];
return [node convertToNodeSpace:touchLocation];
}
- (CGPoint) locationInWorld
{
CCDirector* dir = [CCDirector sharedDirector];
CGPoint touchLocation = [self locationInView: [self view]];
return [dir convertToGL: touchLocation];
}
#end

UIScrollView zoomed with subviews gets different position after back from background

All,
I have a viewController with a ScrollView. On this scrollView, I have a UIImage as subview.
UIImage *image = [UIImage imageNamed:#"greyblue_numbered_15x15_900x900.png"];
self.boardImage = [[UIImageView alloc] initWithImage:image];
self.boardImage.frame = (CGRect){.origin=CGPointMake(0.0f, 0.0f), .size=image.size};
[self.boardScrollView addSubview:self.boardImage];
self.boardScrollView.contentSize = image.size;
When I zoom, use home button and then call app again, everything is fine.
Now, I place an other subview on it by dragging the object to the scrollView:
- (void)myTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint touchPointScreen = [[touches anyObject] locationInView:self.view];
CGPoint touchPointImage = [[touches anyObject] locationInView:self.boardImage];
if (touchPointScreen.x > self.boardScrollView.frame.origin.x &&
touchPointScreen.x < self.boardScrollView.frame.origin.x + self.boardScrollView.frame.size.width &&
touchPointScreen.y > self.boardScrollView.frame.origin.y &&
touchPointScreen.y < self.boardScrollView.frame.origin.y + self.boardScrollView.frame.size.height)
{
self.tmpDragObject.frame = CGRectMake(x,y,60,60);
[self.boardImage addSubview:self.tmpDragObject];
}
self.tmpDragObject = nil;
}
When I zoom, the subviews are also zoomed.
- (void)scrollViewDoubleTapped:(UITapGestureRecognizer*)recognizer {
CGPoint pointInView = [recognizer locationInView:self.boardScrollView];
CGFloat newZoomScale = self.boardScrollView.zoomScale * 1.5f;
newZoomScale = MIN(newZoomScale, self.boardScrollView.maximumZoomScale);
if (newZoomScale != 1.0f) {
CGSize scrollViewSize = self.boardScrollView.bounds.size;
CGFloat w = scrollViewSize.width / newZoomScale;
CGFloat h = scrollViewSize.height / newZoomScale;
CGFloat x = pointInView.x - (w / 2.0f);
CGFloat y = pointInView.y - (h / 2.0f);
CGRect rectToZoomTo = CGRectMake(x, y, w, h);
[self.boardScrollView zoomToRect:rectToZoomTo animated:YES];
}
ISSUE: When I use the home button and then call the app again, the app repositions the subviews of the ScrollView. So all subviews are replaced downwards, about the size of the tmpDragObject or the size of the navigation bar.
Why is this happening? And how can I fix this?
Apparently, I had to set the automaticallyAdjustsScrollViewInsets on my view controller to NO.

How to discover if 2 CGPath roteted rects intersect?

I am building 2 rects when view controller is loaded, using CGPath. The rects can be moved with PanGestureRecognizer. The question is how can I know when 2 rects had met? In order to not let them intersect?
MainViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
for (int i=0; i< 2; i++) {
//create rects of CGPath
CGRectCustomView* randomColorRect =
[[CGRectCustomView alloc]initWithFrame:
CGRectMake(<random place on screen>)];
//random angle
randomColorRect.transform =
CGAffineTransformMakeRotation
(DegreesToRadians([Shared randomIntBetween:0 and:360]));
[self.view addSubview:randomColorRect];
}
}
- (BOOL)areRectsCollide {
???How to find this???
}
CGRectCustomView.m:
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 8.0);
CGContextStrokePath(context); // do actual stroking
CGContextSetRGBFillColor(context, <green color>, 1);
CGContextFillRect(context, CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.frame.size.height));
path = CGContextCopyPath(context);
}
In Apple guide here, there is a function that determines if a path contains point
- (BOOL)containsPoint:(CGPoint)point onPath:(UIBezierPath *)path inFillArea:(BOOL)inFil,
but I have a rectangle which is endless number of points. So what should I do? Breaking my head...
Found it!
I used algorithm described here.
Just one thing: I move the rects around on the screen. So in order for them not to stack after the first collision, I save the last uncollisioned point and if collision accusers, I restore last location.
- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
BOOL rectsColide = NO;
for (RandomColorRect* buttonRectInStoredRects in arreyOfPaths) {
if (buttonRectInStoredRects.tag != recognizer.view.tag) {
if ([self view:buttonRectInStoredRects intersectsWith:recognizer.view]) {
rectsColide = YES;
}
}
}
CGPoint translation = [recognizer translationInView:self.view];
if (!rectsColide) {
lastPoint = recognizer.view.center;
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
recognizer.view.center.y + translation.y);
}else{
recognizer.view.center = CGPointMake(lastPoint.x ,lastPoint.y);
}
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
}
- (void)projectionOfPolygon:(CGPoint *)poly count:(int)count onto:(CGPoint)perp min:(CGFloat *)minp max:(CGFloat *)maxp
{
CGFloat minproj = MAXFLOAT;
CGFloat maxproj = -MAXFLOAT;
for (int j = 0; j < count; j++) {
CGFloat proj = poly[j].x * perp.x + poly[j].y * perp.y;
if (proj > maxproj)
maxproj = proj;
if (proj < minproj)
minproj = proj;
}
*minp = minproj;
*maxp = maxproj;
}
-(BOOL)convexPolygon:(CGPoint *)poly1 count:(int)count1 intersectsWith:(CGPoint *)poly2 count:(int)count2
{
for (int i = 0; i < count1; i++) {
// Perpendicular vector for one edge of poly1:
CGPoint p1 = poly1[i];
CGPoint p2 = poly1[(i+1) % count1];
CGPoint perp = CGPointMake(- (p2.y - p1.y), p2.x - p1.x);
// Projection intervals of poly1, poly2 onto perpendicular vector:
CGFloat minp1, maxp1, minp2, maxp2;
[self projectionOfPolygon:poly1 count:count1 onto:perp min:&minp1 max:&maxp1];
[self projectionOfPolygon:poly2 count:count1 onto:perp min:&minp2 max:&maxp2];
// If projections do not overlap then we have a "separating axis"
// which means that the polygons do not intersect:
if (maxp1 < minp2 || maxp2 < minp1)
return NO;
}
// And now the other way around with edges from poly2:
for (int i = 0; i < count2; i++) {
CGPoint p1 = poly2[i];
CGPoint p2 = poly2[(i+1) % count2];
CGPoint perp = CGPointMake(- (p2.y - p1.y), p2.x - p1.x);
CGFloat minp1, maxp1, minp2, maxp2;
[self projectionOfPolygon:poly1 count:count1 onto:perp min:&minp1 max:&maxp1];
[self projectionOfPolygon:poly2 count:count1 onto:perp min:&minp2 max:&maxp2];
if (maxp1 < minp2 || maxp2 < minp1)
return NO;
}
// No separating axis found, then the polygons must intersect:
return YES;
}
- (BOOL)view:(UIView *)view1 intersectsWith:(UIView *)view2
{
CGPoint poly1[4];
CGRect bounds1 = view1.bounds;
poly1[0] = [view1 convertPoint:bounds1.origin toView:nil];
poly1[1] = [view1 convertPoint:CGPointMake(bounds1.origin.x + bounds1.size.width, bounds1.origin.y) toView:nil];
poly1[2] = [view1 convertPoint:CGPointMake(bounds1.origin.x + bounds1.size.width, bounds1.origin.y + bounds1.size.height) toView:nil];
poly1[3] = [view1 convertPoint:CGPointMake(bounds1.origin.x, bounds1.origin.y + bounds1.size.height) toView:nil];
CGPoint poly2[4];
CGRect bounds2 = view2.bounds;
poly2[0] = [view2 convertPoint:bounds2.origin toView:nil];
poly2[1] = [view2 convertPoint:CGPointMake(bounds2.origin.x + bounds2.size.width, bounds2.origin.y) toView:nil];
poly2[2] = [view2 convertPoint:CGPointMake(bounds2.origin.x + bounds2.size.width, bounds2.origin.y + bounds2.size.height) toView:nil];
poly2[3] = [view2 convertPoint:CGPointMake(bounds2.origin.x, bounds2.origin.y + bounds2.size.height) toView:nil];
return [self convexPolygon:poly1 count:4 intersectsWith:poly2 count:4];
}
If I understand your question, so in order to check if 2 CGRects meet you better use:
/* Return the intersection of `r1' and `r2'. This may return a null rect. */
CG_EXTERN CGRect CGRectIntersection(CGRect r1, CGRect r2)
For example:
CGRect rect1 = CGRectMake(0, 0, 10, 10);
CGRect rect2 = CGRectMake(5, 5, 10, 10);
CGRect rect3 = CGRectMake(20, 20, 10, 10);
CGRect r1 = CGRectIntersection(rect1, rect2); // Returns a CGRect with (0,0,5,5)
CGRect r2 = CGRectIntersection(rect1, rect3); // Returns a CGRect with (Inf,Inf,0,0)
if (CGSizeEqualToSize(r2.size,CGSizeZero)) {
// rect1 rect3 Intersects at CGSizeZero == Do not Intersect
}

Resources