Intersection of CGRect and CGPath

Is there an effective way to detect the intersection of CGPath and CGRect?

I thought about iterating over every point inside CGRect something like this:

for (CGPoint point in rect) { if (CGPathContainsPoint(path, nil, point, NO)) { intersects = YES; break; } 

But I wanted to know if there is a better way.

My application has many CGrects and one CGPath that can change its shape. I just need to check which lines intersect the track, as shown in the image below. enter image description here

+6
source share
2 answers
  • Draw a path in a raster (white on alpha)
  • then check the Rectangle portion of the bitmap. check if there is a white color in this area, which will mean overlap

- to make it more effective, draw only part of the bitmap that is in the rectangle.


I havent tried this and it will not offer real-time performance, but that sounds fine to me.

+2
source

The only completely accurate way I found for this is to scroll through each point, something like this (I have not tested this exact code):

 for (NSValue *rectValue in rects) { CGRect rect = rectValue.CGRectValue; // Set the initial point values to the top left of the current rect CGFloat x = CGRectGetMinX(rect); CGFloat y = CGRectGetMinY(rect); BOOL intersects = NO; BOOL morePoints = YES; // Loop until there are no more points to check in this rect while (morePoints) { CGPoint point = CGPointMake(x, y); if (CGPathContainsPoint(path, nil, point, NO)) { intersects = YES; break; } // Adjust the x and y values to check all points if (x < CGRectGetMaxX(rect)) { x++; } else if (y < CGRectGetMaxY(rect)) { x = CGRectGetMinX(rect); y++; } else { morePoints = NO; } } if (intersects) { // The path intersects the current rect } else { // The path does not intersect the current rect } } 

But this is the most inefficient way.

You can optimize this solution through an asynchronous loop:

 [rects enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(NSValue * _Nonnull rectValue, NSUInteger idx, BOOL * _Nonnull stop) { CGRect rect = rectValue.CGRectValue; ... }]; 

I only needed to know if the path crossed the edge of the rectangle, so I did something similar to this:

 for (NSValue *rectValue in rects) { CGRect rect = rectValue.CGRectValue; // Set the initial point values to the top left of the current rect CGFloat x = CGRectGetMinX(rect); CGFloat y = CGRectGetMinY(rect); BOOL intersects = NO; // top edge for (; x < CGRectGetMaxX(rect); x++) { CGPoint point = CGPointMake(x, y); if (CGPathContainsPoint(path, nil, point, NO)) { intersects = YES; break; } } if (intersects) { // The path intersects the current rect on the top edge } // right edge for (; y < CGRectGetMaxY(rect); y++) { CGPoint point = CGPointMake(x, y); if (CGPathContainsPoint(path, nil, point, NO)) { intersects = YES; break; } } if (intersects) { // The path intersects the current rect on the right edge } // bottom edge x = CGRectGetMinX(rect); for (; x < CGRectGetMaxX(rect); x++) { CGPoint point = CGPointMake(x, y); if (CGPathContainsPoint(path, nil, point, NO)) { intersects = YES; break; } } if (intersects) { // The path intersects the current rect on the bottom edge } // left edge x = CGRectGetMinX(rect); y = CGRectGetMinY(rect); for (; y < CGRectGetMaxY(rect); y++) { CGPoint point = CGPointMake(x, y); if (CGPathContainsPoint(path, nil, point, NO)) { intersects = YES; break; } } if (intersects) { // The path intersects the current rect on the left edge } } 
+2
source

All Articles