lunadiviner
lunadiviner

Reputation: 509

CGRectIntersectsRect working inconsistently

I have code that generates a random CGRect, checks to see if it intersects any other rects in a previous array, and if it doesn't it adds the new rect to the array. This works perfectly fine, however I also want to ensure that the random CGRect also doesn't overlap an image in the center of the screen. I created a rect that outlines the image with plenty of extra space on the sides, but while the random CGRects still don't intersect each other, they will sometimes intersect the center image rect.

CGRect aRandomFrame = CGRectMake((aRandomX - 50), (aRandomY - 50), 100, 100);
CGRect imageRect = CGRectMake((self.fixation.center.x - 50), (self.fixation.center.y - 50), 100, 100);

if (CGRectContainsRect(BOUNDARY, aRandomFrame)) {
    BOOL isValidFrame = YES;
    for (NSValue *aFrameValue in [self points]) {
        CGRect aFrame = [aFrameValue CGRectValue];
        if (CGRectIntersectsRect(aFrame, aRandomFrame) || CGRectIntersectsRect(imageRect, aRandomFrame)) {
            isValidFrame = NO;
            break;
        }
    }

    if (isValidFrame) {
        [[self points] addObject:[NSValue valueWithCGRect:aRandomFrame]];
    }
}

As a sidenote, BOUNDARY is a larger rect to make sure that none of the random rects are too far from the center.

Upvotes: 0

Views: 200

Answers (1)

danh
danh

Reputation: 62686

To convince a reader that CGRectIntersectsRect isn't working, you'd need to present some NSLog evidence showing it failing.

The code looks okay, so the suspicion falls things we can't see in the OP:

  1. The computation of aRandomX and aRandomY. I presume that looks something like this:

    CGFloat aRandomX = arc4random_uniform(someView.bounds.size.width);
    CGFloat aRandomY = arc4random_uniform(someView.bounds.size.height);
    

someView is important here: it is a UIView containing the image view and the coordinate system of all of these rects, possibly self.view if we're within a view controller

  1. The value of BOUNDARY, but I bet that's a simple constant rectangle with a zero or small origin and a size equal or a little smaller than someView

  2. The probable and most sinister culprit is the coordinate system of the imageRect. If the rectangle and boundary are in the coordinate system of someView then so must be the center property of self.fixation. In other words self.fixation must be a direct subview of someView.

No matter how it relates to someView in the view hierarchy, you can insure that imageRect is correct by using a slightly more sophisticated approach:

CGRect imageRect = [self.fixation convertRect:self.fixation.bounds toView:someView];
// remember someView might be self.view in a view controller
// what to do here depends on how your view hierarchy relates to the rects

As a side note, your loop is a little wasteful, since it makes the imageRect check every time when checking the computed rect against the saved ones. You can fix that like this:

if (CGRectContainsRect(BOUNDARY, aRandomFrame)) {
    if (!CGRectIntersectsRect(imageRect, aRandomFrame)) {
        BOOL isDisjoint = YES;
        for (NSValue *frameValue in self.points) {
            CGRect aFrame = [frameValue CGRectValue];
            if (CGRectIntersectsRect(aFrame, aRandomFrame)) {
                isDisjoint = NO;
                break;
            }
        }
        if (isDisjoint) {
            [self.points addObject:[NSValue valueWithCGRect:aRandomFrame]];
        }
    }
}

Another benefit of this is for debugging: break inside that second conditional and check to see if aRandomFrame intersects imageRect. If it does, NSLog the rectangles and post them here. You will have made a huge discovery that CGRectContainsRect has a bug, but it doesn't, I am certain.

Instead, if you'll see that the rectangles don't intersect at that point, and if anything is wrong, it will be with the imageRect. Good luck!

Upvotes: 1

Related Questions