2013-07-19 25 views
4

確定線是否與矩形相交的最有效方法是什麼?確定線是否相交CGRect

我在尋找類似這樣的東西:

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 
} 

回答

6

沒有什麼建的,但是這應該做到這一點:

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's horizontal length 
      (line1Start.y - line2Start.y) * (line2End.x - line2Start.x) 
      //Distance between the lines' starting columns times line2's vertical length 
      - (line1Start.x - line2Start.x) * (line2End.y - line2Start.y); 
     CGFloat d = 
      //Line 1's horizontal length times line 2's vertical length 
      (line1End.x - line1Start.x) * (line2End.y - line2Start.y) 
      //Line 1's vertical length times line 2's 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's horizontal length 
      (line1Start.y - line2Start.y) * (line1End.x - line1Start.x) 
      //Distance between the lines' starting columns times line 1's 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))); 
} 

從這個問題中平凡移植:How to know if a line intersects a rectangle

+1

大起大落彼得Hosey與解釋性意見!謝謝。 – ipmcc

+0

工作得很好。謝謝! – mosca1337

1

對於任何人使用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's horizontal length 
    (line1Start.y - line2Start.y) * (line2End.x - line2Start.x) 
    //Distance between the lines' starting columns times line2's vertical length 
    - (line1Start.x - line2Start.x) * (line2End.y - line2Start.y); 
    CGFloat d = 
    //Line 1's horizontal length times line 2's vertical length 
    (line1End.x - line1Start.x) * (line2End.y - line2Start.y) 
    //Line 1's vertical length times line 2's 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's horizontal length 
    (line1Start.y - line2Start.y) * (line1End.x - line1Start.x) 
    //Distance between the lines' starting columns times line 1's 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))); 
} 
0

斯威夫特版本:

extension CGRect { 
    private func lineIntersectsLine(_ line1Start: CGPoint, _ line1End: CGPoint, _ line2Start: CGPoint, _ line2End: CGPoint) -> Bool { 
     // Distance between the lines' starting rows times line2's horizontal length 
     var q = (line1Start.y - line2Start.y) * (line2End.x - line2Start.x) 
      //Distance between the lines' starting columns times line2's vertical length 
      - (line1Start.x - line2Start.x) * (line2End.y - line2Start.y) 
     let d = 
     //Line 1's horizontal length times line 2's vertical length 
     (line1End.x - line1Start.x) * (line2End.y - line2Start.y) 
     //Line 1's vertical length times line 2's 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's horizontal length 
      (line1Start.y - line2Start.y) * (line1End.x - line1Start.x) 
      //Distance between the lines' starting columns times line 1's 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))) 
    } 
}