Problème avec des coordonnées

Résolu

Bonjour à tous,

J'ai code qui marche  bien avec les coordonnées mis en commentaire. Mais quand le nombre de coordonnées A B augmente, je n'ai pas le résultat attendu.

Est-ce-que quelqu'un à une idée de pourquoi ça ne marche pas ?

Merci d'avance

import csv
import matplotlib.pyplot
from matplotlib import pyplot as plt


def equdroite(x0, y0, x1, y1):
    a = y1 - y0
    b = x0 - x1
    c = -(b * y0 + a * x0)
    return a, b, c


def inside(Poly, p):
    for P in Poly:
        a, b, c, s, x, y = float(P[0]), float(P[1]), float(P[2]), float(P[3]), float(pp[0]), float(pp[1])
        if s * sign(x, y, a, b, c) < 0:
            #            print("outside:",a,b,c,s,x,y)
            return False
    return True


def sign(x, y, a, b, c):
    return a * x + b * y + c


x = [325025, 325000, 325000, 325025]
y = [2077495, 2077495, 2077520, 2077520]

# x = [325010.01, 325015.120, 325015.2, 325010.210]
# y = [2077560.012, 2077560.05, 2077555.21, 2077555.045]
sg = 5
A = [324987.612, 324987.549, 324987.525, 324986.697, 324984.445, 324989.878, 324994.957, 325001.832, 325006.195,
     325015.463, 325019.355, 325035.482, 325037.5, 325045.742, 325060.603, 324987.2]
B = [2077487.5, 2077487.897, 2077518.372, 2077523.137, 2077527.005, 2077537.484, 2077536.422, 2077536.602, 2077536.922,
     2077536.433, 2077536.6, 2077536.314, 2077537.5, 2077537.5, 2077487.5, 2077487.5]

# A = [324989.345, 324987.133, 324987.502, 325037.452, 325035.977, 324989.345]
# B = [2077586.246, 2077553.622, 2077537.955, 2077537.402, 2077589.933, 2077586.246]
nc = (len(A) - 1)
print(nc)
E = []
for p0 in range(nc):
    p1 = (p0 + 1) % nc
    p2 = (p0 + int(nc // 2)) % nc
    a, b, c = equdroite(A[p0], B[p0], A[p1], B[p1])
    s = sign(A[p2], B[p2], a, b, c)
    print("inloop:", p0, a, b, c, s)
    E.append([a, b, c, s, p0, p1])
print("E:", E)
for p in range(nc):
    for C in E:
        if p != C[4] and p != C[5]:
            a, b, c, s, xp, yp = C[0], C[1], C[2], C[3], A[p], B[p]
            v = sign(xp, yp, a, b, c)
            if s * v < 0:
                print("outside:", a, b, c, s, xp, yp)
                print("OUPS!", s, v)
matplotlib.pyplot.plot(A, B)
matplotlib.pyplot.scatter(x, y, color="r")
matplotlib.pyplot.axis("equal")
matplotlib.pyplot.grid(True)
plt.title("Coordonnées planifiés")
plt.xlabel("Axe des X")
plt.ylabel("Axe des Y")

phg = (int(min(A) // sg) * sg, int(min(B) // sg) * sg)
pbd = (int(max(A) // sg + 1) * sg, int(max(B) // sg + 1) * sg)
nrow = int((pbd[0] - phg[0]) // sg) + 1
ncol = int((pbd[1] - phg[1]) // sg) + 1
print(phg)
print(pbd)
print(nrow, ncol)
prouge = []
for row in range(nrow):
    for col in range(ncol):
        pp = (phg[0] + sg * row, phg[1] + sg * col)
        if inside(E, pp):
            prouge.append(pp)
xrouge = [ppp[0] for ppp in prouge]
yrouge = [ppp[1] for ppp in prouge]
matplotlib.pyplot.scatter(xrouge, yrouge, color="g")
matplotlib.pyplot.scatter(x, y, color="r")
with open("coordout.csv", "w") as f:
    print("X;Y", file=f)
    for xrouge, yrouge in prouge:
        print(f"{xrouge};{yrouge}", file=f)

data = A, B
with open('coordout.csv', 'a') as f:
    writer = csv.writer(f)
    writer.writerows(data)
matplotlib.pyplot.show()


 

5 réponses

  1. Contributeur

    bonjour,

    Si tu as une idée de ce que fait ce programme, pourrais-tu l'expliquer?

    0
    1. Bonjour,

      Le code est complexe à lire, je vais m'arrêter à quelques points de détail.

      - Tes imports sont redondants, simplifie par

      import matplotlib.pyplot as plt

      - La méthode inside() de vérification du point dans le polygone est brutale, matplotlib contient déjà de quoi vérifier ça ! Par le fait ça allège quelques fonctions.

      • Importe Path de matplotlib et remplace def inside(Poly, p): par
      from matplotlib.path import Path
      
      ...
      
      def inside(Poly, p):
          path = Path(Poly)
          return path.contains_points([p])[0]
      • Remplace ta big double boucle for par :
      path_for_oups = Path(list(zip(A, B)))
      for i in range(nc):
          if not path_for_oups.contains_point((A[i], B[i])):
              print("OUPS!", A[i], B[i])
      

      Tiens au jus !


      1
      1. Modérateur

        Si on utilise cette nouvelle version de la fonction inside, il faut revoir la manière dont l'enveloppe E est construire :

        E = list(zip(A, B))

        On peut alors se débarrasser :

        • de la boucle qui construisait E (l41-49)
        • des fonctions equdroites, sign
        • de la variable nc

        Bonne chance

        1
    2. Contributeur

      Je pense que ton polygone est concave, tout simplement.

      Les points 0 et 9 ne sont pas du même côté de la droite passant par les points 2 et 3
      Les points 0 et 10 ne sont pas du même côté de la droite passant par les points 3 et 4
      Les points 0 et 12 ne sont pas du même côté de la droite passant par les points 5 et 6
      Les points 0 et 3 ne sont pas du même côté de la droite passant par les points 11 et 12
      Les points 1 et 9 ne sont pas du même côté de la droite passant par les points 2 et 3
      Les points 1 et 10 ne sont pas du même côté de la droite passant par les points 3 et 4
      Les points 1 et 12 ne sont pas du même côté de la droite passant par les points 5 et 6
      Les points 1 et 3 ne sont pas du même côté de la droite passant par les points 11 et 12
      Les points 2 et 10 ne sont pas du même côté de la droite passant par les points 3 et 4
      Les points 2 et 12 ne sont pas du même côté de la droite passant par les points 5 et 6
      Les points 3 et 8 ne sont pas du même côté de la droite passant par les points 1 et 2
      Les points 3 et 12 ne sont pas du même côté de la droite passant par les points 5 et 6
      Les points 4 et 8 ne sont pas du même côté de la droite passant par les points 1 et 2
      Les points 4 et 9 ne sont pas du même côté de la droite passant par les points 2 et 3
      Les points 4 et 12 ne sont pas du même côté de la droite passant par les points 5 et 6
      Les points 5 et 13 ne sont pas du même côté de la droite passant par les points 6 et 7
      Les points 5 et 14 ne sont pas du même côté de la droite passant par les points 7 et 8
      Les points 5 et 1 ne sont pas du même côté de la droite passant par les points 9 et 10
      Les points 5 et 2 ne sont pas du même côté de la droite passant par les points 10 et 11
      Les points 6 et 14 ne sont pas du même côté de la droite passant par les points 7 et 8
      Les points 6 et 1 ne sont pas du même côté de la droite passant par les points 9 et 10
      Les points 7 et 1 ne sont pas du même côté de la droite passant par les points 9 et 10
      Les points 8 et 13 ne sont pas du même côté de la droite passant par les points 6 et 7
      Les points 8 et 1 ne sont pas du même côté de la droite passant par les points 9 et 10
      Les points 8 et 2 ne sont pas du même côté de la droite passant par les points 10 et 11
      Les points 10 et 0 ne sont pas du même côté de la droite passant par les points 8 et 9
      Les points 11 et 0 ne sont pas du même côté de la droite passant par les points 8 et 9
      Les points 12 et 0 ne sont pas du même côté de la droite passant par les points 8 et 9
      Les points 12 et 1 ne sont pas du même côté de la droite passant par les points 9 et 10
      Les points 12 et 2 ne sont pas du même côté de la droite passant par les points 10 et 11
      Les points 13 et 0 ne sont pas du même côté de la droite passant par les points 8 et 9
      Les points 13 et 2 ne sont pas du même côté de la droite passant par les points 10 et 11
      Les points 13 et 3 ne sont pas du même côté de la droite passant par les points 11 et 12
      Les points 14 et 12 ne sont pas du même côté de la droite passant par les points 5 et 6
      Les points 14 et 3 ne sont pas du même côté de la droite passant par les points 11 et 12

      1
      1. Bonjour,

        merci beaucoup luckydu43 pour vos observations merci a vous aussi yg_be effectivement il est concave, je veux utiliser shapely et la methode avec matplotlib voir

        0
        1. Modérateur

          Bonjour,

          Je te propose cette réécriture plus simple de ce programme, qui j'espère, fait ce que tu veux en réutilisant les remarques faites dans les messages #2 et #5. J'ai renommé quelques variables afin qu'il soit plus clair et décomposé le code en fonction pour qu'il soit plus lisible. J'ai retiré la partie csv car elle n'est pas au centre de la question, mais libre à toi de la remettre.

          Si j'ai bien compris, le but est de trouver, étant donnée une enveloppe polygonale (blue_points), de trouver tous les points contenus dans cette enveloppe (green_points) étant donné un pas discret arbitraire (step).

          from matplotlib import pyplot as plt
          from matplotlib.path import Path
          
          def inside(poly, p):
              path = Path(poly)
              return path.contains_points([p])[0]
          
          def quantize(x, step):
              return (x // step) * step
          
          def make_dataset(dataset_id):
              if dataset_id == 1:
                  red_xs = [325025, 325000, 325000, 325025]
                  red_ys = [2077495, 2077495, 2077520, 2077520]
                  blue_xs = [324987.612, 324987.549, 324987.525, 324986.697, 324984.445, 324989.878, 324994.957, 325001.832, 325006.195,
                       325015.463, 325019.355, 325035.482, 325037.5, 325045.742, 325060.603, 324987.2]
                  blue_ys = [2077487.5, 2077487.897, 2077518.372, 2077523.137, 2077527.005, 2077537.484, 2077536.422, 2077536.602, 2077536.922,
                       2077536.433, 2077536.6, 2077536.314, 2077537.5, 2077537.5, 2077487.5, 2077487.5]
              elif dataset_id == 2:
                  red_xs = [325010.01, 325015.120, 325015.2, 325010.210]
                  red_ys = [2077560.012, 2077560.05, 2077555.21, 2077555.045]
                  blue_xs = [324989.345, 324987.133, 324987.502, 325037.452, 325035.977, 324989.345]
                  blue_ys = [2077586.246, 2077553.622, 2077537.955, 2077537.402, 2077589.933, 2077586.246]
              else:
                  raise ValueError("Invalid dataset_id")
              return (red_xs, red_ys, blue_xs, blue_ys)
          
          def find_discrete_points_in_hull(xs, ys, step):
              min_x = int(quantize(min(xs), step)) + step
              min_y = int(quantize(min(ys), step)) + step
              max_x = int(quantize(max(xs), step)) + step
              max_y = int(quantize(max(ys), step)) + step
              hull = list(zip(xs, ys))
              return [
                  (px, py)
                  for px in range(min_x, max_x, step)
                  for py in range(min_y, max_y, step)
                  if inside(hull, (px, py))
              ]
          
          def my_plot(red_xs, red_ys, blue_xs, blue_ys, green_xs, green_ys):
              plt.plot(blue_xs, blue_ys)
              plt.axis("equal")
              plt.grid(True)
              plt.title("Coordonnées planifiées")
              plt.xlabel("Axe des X")
              plt.ylabel("Axe des Y")
              plt.scatter(green_xs, green_ys, color="g")
              plt.scatter(red_xs, red_ys, color="r")
          
          def main():
              step = 5
              for dataset_id in (1, 2):
                  (red_xs, red_ys, blue_xs, blue_ys) = make_dataset(dataset_id)
                  green_points = find_discrete_points_in_hull(blue_xs, blue_ys, step)
                  (green_xs, green_ys) = zip(*green_points)
                  my_plot(red_xs, red_ys, blue_xs, blue_ys, green_xs, green_ys)
                  plt.show()
          
          main()

          Bonne chance

          1