Problème avec des coordonnées

Résolu
LALO_5656 Messages postés 29 Date d'inscription   Statut Membre Dernière intervention   -  
mamiemando Messages postés 33769 Date d'inscription   Statut Modérateur Dernière intervention   -

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()


 

A voir également:

5 réponses

luckydu43 Messages postés 4259 Date d'inscription   Statut Membre Dernière intervention   1 057
 

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
mamiemando Messages postés 33769 Date d'inscription   Statut Modérateur Dernière intervention   7 879
 

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
yg_be Messages postés 23541 Date d'inscription   Statut Contributeur Dernière intervention   Ambassadeur 1 584
 

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
mamiemando Messages postés 33769 Date d'inscription   Statut Modérateur Dernière intervention   7 879
 

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
yg_be Messages postés 23541 Date d'inscription   Statut Contributeur Dernière intervention   Ambassadeur 1 584
 

bonjour,

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

0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
LALO_5656 Messages postés 29 Date d'inscription   Statut Membre Dernière intervention   2
 

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