J'ai une classe décrivant un point (a 2 coordonnées x et y) et une classe décrivant un polygone qui a une liste de points qui correspondent aux coins (self.corners) J'ai besoin de vérifier si un point est dans un polygone
Voici la fonction qui est censée vérifier si le point dans le polygone. J'utilise la méthode Ray Casting
def in_me(self, point):
result = False
n = len(self.corners)
p1x = int(self.corners[0].x)
p1y = int(self.corners[0].y)
for i in range(n+1):
p2x = int(self.corners[i % n].x)
p2y = int(self.corners[i % n].y)
if point.y > min(p1y,p2y):
if point.x <= max(p1x,p2x):
if p1y != p2y:
xinters = (point.y-p1y)*(p2x-p1x)/(p2y-p1y)+p1x
print xinters
if p1x == p2x or point.x <= xinters:
result = not result
p1x,p1y = p2x,p2y
return result
Je lance un test avec la forme et le point suivants:
PG1 = (0,0), (0,2), (2,2), (2,0)
point = (1,1)
Le script retourne heureusement False même s'il le pointe dans la ligne. Je n'arrive pas à trouver l'erreur
Je suggère d'utiliser la classe Path
de matplotlib
import matplotlib.path as mplPath
import numpy as np
poly = [190, 50, 500, 310]
bbPath = mplPath.Path(np.array([[poly[0], poly[1]],
[poly[1], poly[2]],
[poly[2], poly[3]],
[poly[3], poly[0]]]))
bbPath.contains_point((200, 100))
(Il y a aussi contains_points
fonction si vous voulez tester plusieurs points)
Je voudrais suggérer quelques autres changements:
def contains(self, point):
if not self.corners:
return False
def lines():
p0 = self.corners[-1]
for p1 in self.corners:
yield p0, p1
p0 = p1
for p1, p2 in lines():
... # perform actual checks here
Remarques:
continue
ou utiliser and
.Pas:
Utilisation de la fonction intersect
de This SO Question
def ccw(A,B,C):
return (C.y-A.y) * (B.x-A.x) > (B.y-A.y) * (C.x-A.x)
# Return true if line segments AB and CD intersect
def intersect(A,B,C,D):
return ccw(A,C,D) != ccw(B,C,D) and ccw(A,B,C) != ccw(A,B,D)
def point_in_polygon(pt, poly, inf):
result = False
for i in range(len(poly.corners)-1):
if intersect((poly.corners[i].x, poly.corners[i].y), ( poly.corners[i+1].x, poly.corners[i+1].y), (pt.x, pt.y), (inf, pt.y)):
result = not result
if intersect((poly.corners[-1].x, poly.corners[-1].y), (poly.corners[0].x, poly.corners[0].y), (pt.x, pt.y), (inf, pt.y)):
result = not result
return result
Veuillez noter que le paramètre inf
doit être le point maximum sur l'axe des x dans votre figure.