2016-09-08 13 views
2

J'ai utilisé le code qui a été affiché here. Voici le code à nouveau:Détecter si deux segments de ligne se croisent en utilisant Cramer

from __future__ import division 

def line(p1, p2): 
    A = (p1[1] - p2[1]) 
    B = (p2[0] - p1[0]) 
    C = (p1[0]*p2[1] - p2[0]*p1[1]) 
    return A, B, -C 

def intersection(L1, L2): 
    D = L1[0] * L2[1] - L1[1] * L2[0] 
    Dx = L1[2] * L2[1] - L1[1] * L2[2] 
    Dy = L1[0] * L2[2] - L1[2] * L2[0] 
    if D != 0: 
     x = Dx/D 
     y = Dy/D 
     return x,y 
    else: 
     return False 

# Usage 
L1 = line([0,1], [2,3]) 
L2 = line([2,3], [0,4]) 

R = intersection(L1, L2) 
if R: 
    print "Intersection detected:", R 
else: 
    print "No single intersection point detected" 

Il met en œuvre la règle Cramer (adapté pour les lignes, si déterminant de l'équation linéaire construite pour deux lignes données est 0, les lignes ne sont pas sécantes). Cependant, le problème que j'ai avec lui est qu'il détecte également les intersections qui résultent de la continuation des deux lignes en cours. Voici un terrain que je l'ai fait à l'aide matplotlib qui démontre la question:

enter image description here

J'ai aussi une classe Triangle qui contient 3 Line objets et il démontre la question encore plus loin puisque la classe a également son propre intersect(...) fonction qui prend un autre triangle et vérifie que les bords des deux triangles se croisent et où:

enter image description here

je souhaite détecter intersection de segment de ligne en utilisant l'algorithme du lien. Les segments de ligne et ont une intersection. Comment je fais ça?

J'ai deux classes - Point et Line - qui sont utilisées pour travailler avec ces éléments géométriques d'une manière plus lisible. Je l'ai maintenu le script ci-dessus et enroulé autour de lui (voir Line.intersect(...)):

class Point: 
    def __init__(self, x, y, z): 
     self.x = x 
     self.y = y 
     self.z = z 

    # Override __add__, __sub__ etc. to allow arithmetic operations with Point objects 
    # ... 

class Line: 
    def __init__(self, p1, p2): 
     self.p1 = p1 
     self.p2 = p2 
    # ... 
    def intersect(self, l): 
     def line(p1, p2): 
      A = (p1.y - p2.y) 
      B = (p2.x - p1.x) 
      C = (p1.x*p2.y - p2.x*p1.y) 
      return A, B, -C 

     L1 = line(self.p1, self.p2) 
     L2 = line(l.p1, l.p2) 

     D = L1[0]*L2[1] - L1[1]*L2[0] 
     Dx = L1[2]*L2[1] - L1[1]*L2[2] 
     Dy = L1[0]*L2[2] - L1[2]*L2[0] 

     if D != 0: 
      x = Dx/D 
      y = Dy/D 
      p = Point(x, y) 
      return True, p 

     return False, None 

#Usage 
l1 = Line(Point(0, 0), Point(10, 4)) 
l2 = Line(Point(-4, -3), Point(-4, 10)) 

res, p = l1.intersect(l2) 
if not res: 
    print('Lines don\'t intersect') 
else: 
    print('Lines intersect at [%f, %f]' % (p.x, p.y)) 

Je cherche aussi une optimale (comme aussi peu coûteuses opérations non avec aussi peu empreinte mémoire possible) solution.

Une solution possible consiste à filtrer les points d'intersection résultants (ceux qui ne font pas partie des deux segments) en utilisant la distance euclidienne pour déterminer si ces points se trouvent sur les deux segments ou non. Si ce n'est pas le cas, l'intersection est le résultat de la continuation d'une ou des deux lignes et doit être considérée comme invalide. Ceci est cependant une opération coûteuse et implique également de prendre en compte tous les points d'intersection (peu importe si le point fait partie ou non des deux segments).


MISE À JOUR: Je pensais que je l'ai résolu le problème, mais hélas! ce qui suit a un problème. Après avoir examiné attentivement les observations que j'ai vu celle faite par @JerryCoffin qui a un double possible avec this post:

def intersect(self, l, contious=False): 
     # Before anything else check if lines have a mutual abcisses 
     interval_1 = [min(self.p1.x, self.p2.x), max(self.p1.x, self.p2.x)] 
     interval_2 = [min(l.p1.x, l.p2.x), max(l.p1.x, l.p2.x)] 
     interval = [ 
      min(interval_1[1], interval_2[1]), 
      max(interval_1[0], interval_2[0]) 
     ] 

     if interval_1[1] < interval_2[0]: 
      print('No mutual abcisses!') 
      return False, None 

     # Try to compute interception 
     def line(p1, p2): 
      A = (p1.y - p2.y) 
      B = (p2.x - p1.x) 
      C = (p1.x*p2.y - p2.x*p1.y) 
      return A, B, -C 

     L1 = line(self.p1, self.p2) 
     L2 = line(l.p1, l.p2) 

     D = L1[0]*L2[1] - L1[1]*L2[0] 
     Dx = L1[2]*L2[1] - L1[1]*L2[2] 
     Dy = L1[0]*L2[2] - L1[2]*L2[0] 

     if D != 0: 
      x = Dx/D 
      y = Dy/D 
      p = Point(x, y) 
      if contiuous: # continuous parameter allows switching between line and line segment interception 
       return True, p 
      else: 
       if p.x < interval[1] or p.x > interval[0]: 
        print('Intersection out of bound') 
        return False, None 
       else: 
        return True, p 
     else: 
      print('Not intersecting') 
      return False, None 

Le résultat:

enter image description here

qui a l'air agréable et exactement ce que je veux avoir. Cependant J'ai ajouté une ligne (les coordonnées étaient plus ou moins aléatoire mais facile pour moi de vérifier sur l'intrigue) à savoir Line(Point(-4, 12), Point(12, -4)). Et imaginez ma surprise quand je suis arrivé encore une fois un faux positif:

enter image description here

Comme vous pouvez le voir il y a une intersection détectée dans le coin supérieur gauche au début de mon segment de ligne.Il croise en effet avec la suite de la ligne verticale mais pas avec le segment de ligne réel. Il semble que le fait que les deux segments de ligne aient le même x alors que celui qui est vertical pose problème. Donc je ne sais toujours pas comment résoudre le problème.

Répondre

0

Eh bien, on a besoin d'apprendre à lire ... La solution était en fait dans les commentaires à une suggestion faite par double @JerryCoffin à savoir here:

def intersect(self, l, contious=False): 
     # Before anything else check if lines have a mutual abcisses 
     interval_1 = [min(self.p1.x, self.p2.x), max(self.p1.x, self.p2.x)] 
     interval_2 = [min(l.p1.x, l.p2.x), max(l.p1.x, l.p2.x)] 
     interval = [ 
      min(interval_1[1], interval_2[1]), 
      max(interval_1[0], interval_2[0]) 
     ] 

     if interval_1[1] < interval_2[0]: 
      print('No mutual abcisses!') 
      return False, None 

     # Try to compute interception 
     def line(p1, p2): 
      A = (p1.y - p2.y) 
      B = (p2.x - p1.x) 
      C = (p1.x*p2.y - p2.x*p1.y) 
      return A, B, -C 

     L1 = line(self.p1, self.p2) 
     L2 = line(l.p1, l.p2) 

     D = L1[0]*L2[1] - L1[1]*L2[0] 
     Dx = L1[2]*L2[1] - L1[1]*L2[2] 
     Dy = L1[0]*L2[2] - L1[2]*L2[0] 

     if D != 0: 
      x = Dx/D 
      y = Dy/D 
      p = Point(x, y) 
      if contiuous: # continuous parameter allows switching between line and line segment interception 
       return True, p 
      else: 
       if p.x < interval[1] or p.x > interval[0]: 
        print('Intersection out of bound') 
        return False, None 
       else: 
        return True, p 
     else: 
      print('Not intersecting') 
      return False, None 

Le résultat:

enter image description here