Determine if the CGRect line crosses

What is the most efficient way to determine if a line crosses a rectangle?

I am looking for something similar to this:

CGPoint startLine = CGPointMake(5.0f,5.0f); CGPoint endLine = CGPointMake(25.0f,25.0f); CGRect intersectingRect = CGRectMake(10.0f,10.0f,50.0f,50.0f); if (CGRectContainsLine(intersectingRect,startLine,endLine)) { //true //line intersects rectangle } 
+4
source share
3 answers

Nothing is built in there, but this should do it:

 BOOL RectContainsLine(CGRect r, CGPoint lineStart, CGPoint lineEnd) { BOOL (^LineIntersectsLine)(CGPoint, CGPoint, CGPoint, CGPoint) = ^BOOL(CGPoint line1Start, CGPoint line1End, CGPoint line2Start, CGPoint line2End) { CGFloat q = //Distance between the lines' starting rows times line2 horizontal length (line1Start.y - line2Start.y) * (line2End.x - line2Start.x) //Distance between the lines' starting columns times line2 vertical length - (line1Start.x - line2Start.x) * (line2End.y - line2Start.y); CGFloat d = //Line 1 horizontal length times line 2 vertical length (line1End.x - line1Start.x) * (line2End.y - line2Start.y) //Line 1 vertical length times line 2 horizontal length - (line1End.y - line1Start.y) * (line2End.x - line2Start.x); if( d == 0 ) return NO; CGFloat r = q / d; q = //Distance between the lines' starting rows times line 1 horizontal length (line1Start.y - line2Start.y) * (line1End.x - line1Start.x) //Distance between the lines' starting columns times line 1 vertical length - (line1Start.x - line2Start.x) * (line1End.y - line1Start.y); CGFloat s = q / d; if( r < 0 || r > 1 || s < 0 || s > 1 ) return NO; return YES; }; /*Test whether the line intersects any of: *- the bottom edge of the rectangle *- the right edge of the rectangle *- the top edge of the rectangle *- the left edge of the rectangle *- the interior of the rectangle (both points inside) */ return (LineIntersectsLine(lineStart, lineEnd, CGPointMake(r.origin.x, r.origin.y), CGPointMake(r.origin.x + r.size.width, r.origin.y)) || LineIntersectsLine(lineStart, lineEnd, CGPointMake(r.origin.x + r.size.width, r.origin.y), CGPointMake(r.origin.x + r.size.width, r.origin.y + r.size.height)) || LineIntersectsLine(lineStart, lineEnd, CGPointMake(r.origin.x + r.size.width, r.origin.y + r.size.height), CGPointMake(r.origin.x, r.origin.y + r.size.height)) || LineIntersectsLine(lineStart, lineEnd, CGPointMake(r.origin.x, r.origin.y + r.size.height), CGPointMake(r.origin.x, r.origin.y)) || (CGRectContainsPoint(r, lineStart) && CGRectContainsPoint(r, lineEnd))); } 

Trivially ported from this question: How do I know if a line crosses a rectangle

+6
source

For anyone using objective-c:

 - (BOOL)rectContainsLine:(CGRect)rect startPoint:(CGPoint)lineStart endPoint:(CGPoint)lineEnd { BOOL (^LineIntersectsLine)(CGPoint, CGPoint, CGPoint, CGPoint) = ^BOOL(CGPoint line1Start, CGPoint line1End, CGPoint line2Start, CGPoint line2End) { CGFloat q = //Distance between the lines' starting rows times line2 horizontal length (line1Start.y - line2Start.y) * (line2End.x - line2Start.x) //Distance between the lines' starting columns times line2 vertical length - (line1Start.x - line2Start.x) * (line2End.y - line2Start.y); CGFloat d = //Line 1 horizontal length times line 2 vertical length (line1End.x - line1Start.x) * (line2End.y - line2Start.y) //Line 1 vertical length times line 2 horizontal length - (line1End.y - line1Start.y) * (line2End.x - line2Start.x); if( d == 0 ) return NO; CGFloat r = q / d; q = //Distance between the lines' starting rows times line 1 horizontal length (line1Start.y - line2Start.y) * (line1End.x - line1Start.x) //Distance between the lines' starting columns times line 1 vertical length - (line1Start.x - line2Start.x) * (line1End.y - line1Start.y); CGFloat s = q / d; if( r < 0 || r > 1 || s < 0 || s > 1 ) return NO; return YES; }; /*Test whether the line intersects any of: *- the bottom edge of the rectangle *- the right edge of the rectangle *- the top edge of the rectangle *- the left edge of the rectangle *- the interior of the rectangle (both points inside) */ return (LineIntersectsLine(lineStart, lineEnd, CGPointMake(rect.origin.x, rect.origin.y), CGPointMake(rect.origin.x + rect.size.width, rect.origin.y)) || LineIntersectsLine(lineStart, lineEnd, CGPointMake(rect.origin.x + rect.size.width, rect.origin.y), CGPointMake(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height)) || LineIntersectsLine(lineStart, lineEnd, CGPointMake(rect.origin.x + rect.size.width, rect.origin.y + rect.size.height), CGPointMake(rect.origin.x, rect.origin.y + rect.size.height)) || LineIntersectsLine(lineStart, lineEnd, CGPointMake(rect.origin.x, rect.origin.y + rect.size.height), CGPointMake(rect.origin.x, rect.origin.y)) || (CGRectContainsPoint(rect, lineStart) && CGRectContainsPoint(rect, lineEnd))); } 
+1
source

Quick version:

 extension CGRect { private func lineIntersectsLine(_ line1Start: CGPoint, _ line1End: CGPoint, _ line2Start: CGPoint, _ line2End: CGPoint) -> Bool { // Distance between the lines' starting rows times line2 horizontal length var q = (line1Start.y - line2Start.y) * (line2End.x - line2Start.x) //Distance between the lines' starting columns times line2 vertical length - (line1Start.x - line2Start.x) * (line2End.y - line2Start.y) let d = //Line 1 horizontal length times line 2 vertical length (line1End.x - line1Start.x) * (line2End.y - line2Start.y) //Line 1 vertical length times line 2 horizontal length - (line1End.y - line1Start.y) * (line2End.x - line2Start.x) if d == 0 { return false } let r = q / d q = //Distance between the lines' starting rows times line 1 horizontal length (line1Start.y - line2Start.y) * (line1End.x - line1Start.x) //Distance between the lines' starting columns times line 1 vertical length - (line1Start.x - line2Start.x) * (line1End.y - line1Start.y); let s = q / d if r < 0 || r > 1 || s < 0 || s > 1 { return false } return true } func instersectsLine(start lineStart: CGPoint, end lineEnd: CGPoint) -> Bool { /*Test whether the line intersects any of: *- the bottom edge of the rectangle *- the right edge of the rectangle *- the top edge of the rectangle *- the left edge of the rectangle *- the interior of the rectangle (both points inside) */ return (lineIntersectsLine(lineStart, lineEnd, CGPoint(x:self.origin.x, y: self.origin.y), CGPoint(x: self.origin.x + self.size.width, y: self.origin.y)) || lineIntersectsLine(lineStart, lineEnd, CGPoint(x: self.origin.x + self.size.width, y: self.origin.y), CGPoint(x: self.origin.x + self.size.width, y: self.origin.y + self.size.height)) || lineIntersectsLine(lineStart, lineEnd, CGPoint(x: self.origin.x + self.size.width, y: self.origin.y + self.size.height), CGPoint(x: self.origin.x, y: self.origin.y + self.size.height)) || lineIntersectsLine(lineStart, lineEnd, CGPoint(x: self.origin.x, y: self.origin.y + self.size.height), CGPoint(x: self.origin.x, y: self.origin.y)) || (contains(lineStart) && contains(lineEnd))) } } 
0
source

Source: https://habr.com/ru/post/1492396/


All Articles