2013-03-28 25 views
5

Potrafię wykryć punkt przecięcia dwóch linii, ale jeśli moja linia nie ma długości mojego ekranu, wykrywa punkt, gdzie nie powinien być.Przecięcie dwóch linii na współrzędnych

Tutaj podgląd: Intersection Nie powinien więc wykrywać tego przecięcia, ponieważ linia pozioma nie jest długa.

Kod:

- (NSMutableArray *) intersectWithLines:(CGPoint)startPoint andEnd:(CGPoint)endPoint { 
    NSMutableArray *intersects = [[NSMutableArray alloc] init]; 

    for(GameLine *line in [_lineBackground getLines]) { 

     double lineStartX = line.startPos.x; 
     double lineStartY = line.startPos.y; 
     double tempEndX = line.endPos.x; 
     double tempEndY = line.endPos.y; 

     double d = ((startPoint.x - endPoint.x)*(lineStartY - tempEndY)) - ((startPoint.y - endPoint.y) * (lineStartX - tempEndX)); 

     if(d != 0) {    
      double sX = ((lineStartX - tempEndX) * (startPoint.x * endPoint.y - startPoint.y * endPoint.x) - (startPoint.x - endPoint.x) * (lineStartX * tempEndY - lineStartY * tempEndX))/d; 
      double sY = ((lineStartY - tempEndY) * (startPoint.x * endPoint.y - startPoint.y * endPoint.x) - (startPoint.y - endPoint.y) * (lineStartX * tempEndY - lineStartY * tempEndX))/d; 


      if([self isValidCGPoint:CGPointMake(sX, sY)]) { 
       [intersects addObject:[NSValue valueWithCGPoint:CGPointMake(sX, sY)]]; 
      }    
     } 
    } 

    return intersects; 
} 
+0

Nie wiem co masz na myśli, że linia pozioma przecina wyraźnie jeden z tych pionowych. – Tony

+0

tak, oczywiście, ale nie graficznie - myślę, że muszę określić, czy punkt przecięcia znajduje się na jednej z tych linii, jeśli nie - mogę go narysować na górze. wiesz o co mi chodzi? –

Odpowiedz

25

Jeśli rozumiem pytanie poprawnie, trzeba określić punkt przecięcia dwóch odcinków. To powinno działać w następujący sposób:

- (NSValue *)intersectionOfLineFrom:(CGPoint)p1 to:(CGPoint)p2 withLineFrom:(CGPoint)p3 to:(CGPoint)p4 
{ 
    CGFloat d = (p2.x - p1.x)*(p4.y - p3.y) - (p2.y - p1.y)*(p4.x - p3.x); 
    if (d == 0) 
     return nil; // parallel lines 
    CGFloat u = ((p3.x - p1.x)*(p4.y - p3.y) - (p3.y - p1.y)*(p4.x - p3.x))/d; 
    CGFloat v = ((p3.x - p1.x)*(p2.y - p1.y) - (p3.y - p1.y)*(p2.x - p1.x))/d; 
    if (u < 0.0 || u > 1.0) 
     return nil; // intersection point not between p1 and p2 
    if (v < 0.0 || v > 1.0) 
     return nil; // intersection point not between p3 and p4 
    CGPoint intersection; 
    intersection.x = p1.x + u * (p2.x - p1.x); 
    intersection.y = p1.y + u * (p2.y - p1.y); 

    return [NSValue valueWithCGPoint:intersection]; 
} 
+0

działa poprawnie (po edycji) - wielkie dzięki! –

+0

UWAGA: Próbując tego użyć, stwierdziłem, że 'przecięcie.y = p1.y + v * (p2.y - p1.y);' musi być równe 'przecięcie.y = p1.y + u * (p2. y - p1.y); "jak pierwotnie było. Nie wiem, kto edytował 'u' na' v', ale musi być edytowany z powrotem - "u" i "v" są wartościami interpolacji wzdłuż każdego segmentu linii - przy użyciu dwóch różnych wartości interpolacji dla każdego oś tej samej interpolacji jest absurdem. –

+1

@GeorgesOatesLarsen: Masz rację oczywiście. To moja wina, że ​​nie sprawdzałem uważnie "sugerowanej edycji", cofnąłem odpowiedź do poprzedniej wersji. Dzięki! –

2

To prawidłowe równanie:

+(CGPoint) intersection2:(CGPoint)u1 u2:(CGPoint)u2 v1:(CGPoint)v1 v2:(CGPoint)v2 { 
    CGPoint ret=u1; 
    double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x)) 
    /((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x)); 
    ret.x+=(u2.x-u1.x)*t; 
    ret.y+=(u2.y-u1.y)*t; 
    return ret; 
} 

Ponadto, można sprawdzić tę bibliotekę do obliczania przecięć linia: http://www.cprogramdevelop.com/5045485/

+0

To rozwiązanie nie działa. Próbowano tego właśnie wartości: 'Linia A: (0,0) i (0, 20)' 'Linia B: (3, 2) i (-5, 2)' Podane Wynik 0 320, co jest ewidentnie błędne. – MatterGoal

3

wersji Swift

func getIntersectionOfLines(line1: (a: CGPoint, b: CGPoint), line2: (a: CGPoint, b: CGPoint)) -> CGPoint { 
     let distance = (line1.b.x - line1.a.x) * (line2.b.y - line2.a.y) - (line1.b.y - line1.a.y) * (line2.b.x - line2.a.x) 
     if distance == 0 { 
      print("error, parallel lines") 
      return CGPointZero 
     } 

     let u = ((line2.a.x - line1.a.x) * (line2.b.y - line2.a.y) - (line2.a.y - line1.a.y) * (line2.b.x - line2.a.x))/distance 
     let v = ((line2.a.x - line1.a.x) * (line1.b.y - line1.a.y) - (line2.a.y - line1.a.y) * (line1.b.x - line1.a.x))/distance 

     if (u < 0.0 || u > 1.0) { 
      print("error, intersection not inside line1") 
      return CGPointZero 
     } 
     if (v < 0.0 || v > 1.0) { 
      print("error, intersection not inside line2") 
      return CGPointZero 
     } 

     return CGPointMake(line1.a.x + u * (line1.b.x - line1.a.x), line1.a.y + u * (line1.b.y - line1.a.y)) 
    } 
5

To jest nieco modi Fied wersja Hayden Holligan's answer pracować Swift 3:

func getIntersectionOfLines(line1: (a: CGPoint, b: CGPoint), line2: (a: CGPoint, b: CGPoint)) -> CGPoint { 

    let distance = (line1.b.x - line1.a.x) * (line2.b.y - line2.a.y) - (line1.b.y - line1.a.y) * (line2.b.x - line2.a.x) 
    if distance == 0 { 
     print("error, parallel lines") 
     return CGPoint.zero 
    } 

    let u = ((line2.a.x - line1.a.x) * (line2.b.y - line2.a.y) - (line2.a.y - line1.a.y) * (line2.b.x - line2.a.x))/distance 
    let v = ((line2.a.x - line1.a.x) * (line1.b.y - line1.a.y) - (line2.a.y - line1.a.y) * (line1.b.x - line1.a.x))/distance 

    if (u < 0.0 || u > 1.0) { 
     print("error, intersection not inside line1") 
     return CGPoint.zero 
    } 
    if (v < 0.0 || v > 1.0) { 
     print("error, intersection not inside line2") 
     return CGPoint.zero 
    } 

    return CGPoint(x: line1.a.x + u * (line1.b.x - line1.a.x), y: line1.a.y + u * (line1.b.y - line1.a.y)) 
} 
Powiązane problemy