1

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...

Luda
  • 7,282
  • 12
  • 79
  • 139
  • A rectangle has an "endless number of points"? These must be really strange rectangles... – bummzack Sep 29 '13 at 07:32
  • @bummzack Any line/area consists of endless number of points. At least in my perception of geometry. But I may be wrong :) – Luda Sep 29 '13 at 07:41
  • Doh! You're right of course. – bummzack Sep 29 '13 at 07:53
  • Apple doesn't provide any methods to check rotated rectangle intersections. This [answer](http://stackoverflow.com/questions/15710853/objective-c-check-if-subviews-of-rotated-uiviews-intersect) should help you implement rotated rect. collision detection. – bummzack Sep 29 '13 at 08:08
  • @bummzack, my genius friend just said that rect has infinite number of points only in math, not in computers. A rect is limited to the pixels on the screen. actually i don't even have to check all points in rect, only in its perimeter. Googling pixels on CGPath. Feeling exited. – Luda Sep 29 '13 at 08:23

2 Answers2

0

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];
}
Community
  • 1
  • 1
Luda
  • 7,282
  • 12
  • 79
  • 139
0

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
 }
Issa
  • 139
  • 4
  • 13
  • Dear Tarek :) It is not 2 rects, but 2 views with a rect shape and rotated. But thank you :-* – Luda Sep 30 '13 at 06:24