J'essaie de trouver les intersections entre deux cercles en Python (en utilisant Matplotlib) mais je ne peux pas récupérer de valeurs.
Je fais cela en créant des listes de X et Y pour chaque cercle individuel (Matplotlib prend le premier argument comme valeurs X et le second comme valeurs Y lors du dessin d'un cercle), puis intersecte les listes en conséquence (par exemple, cercle1 x valeurs avec cercle2 x valeurs).
import numpy import math import matplotlib.pyplot as plt import random def origin_circle(): global x_points global y_points global r global n r=1 n=2**16 x_points=[(r*math.cos(t)) for t in numpy.linspace(0, 2*numpy.pi*r, n+1)] y_points=[(r*math.sin(t)) for t in numpy.linspace(0, 2*numpy.pi*r, n+1)] def new_circle(x_offset, y_offset): global x_points1 global y_points1 x_points1=[x_offset+(r*math.cos(t)) for t in numpy.linspace(0, 2*numpy.pi*r, n+1)] y_points1=[y_offset+(r*math.sin(t)) for t in numpy.linspace(0, 2*numpy.pi*r, n+1)] origin_circle() new_center= random.randint(0, len(x_points)) x_offset = x_points[new_center] y_offset = y_points[new_center] new_circle(x_offset, y_offset) print(set(x_points1).intersection(set(x_points))) print(set(y_points1).intersection(set(y_points)))
Je m'attendais à récupérer les valeurs, mais l'ensemble renvoyé était vide.
4 Réponses :
Regardez ce que vous avez généré:
[-1.0, -0.9807852804032304, -0.9807852804032304, -0.9238795325112868, -0.9238795325112867, -0.8314696123025455, -0.8314696123025453, -0.7071067811865477, -0.7071067811865475, -0.5555702330196022, -0.555570233019602, -0.38268343236509034, -0.3826834323650897, -0.19509032201612866, -0.1950903220161282, -1.8369701987210297e-16, 6.123233995736766e-17, 0.1950903220161283, 0.19509032201612833, 0.38268343236508984, 0.38268343236509, 0.5555702330196018 , 0.5555702330196023, 0.7071067811865474, 0.7071067811865476, 0.8314696123025452, 0.8314696123025452, 0.9238795325112865, 0.9238795325112867, 0.9807852804032303, 0.9807852804032304, 1.0, 1.0] [-2.0, -1.9807852804032304, -1.9807852804032304, -1.923879532511287, -1.9238795325112867, -1.8314696123025453, -1.8314696123025453, -1.7071067811865477, -1.7071067811865475, -1.5555702330196022, -1.555570233019602, -1.3826834323650903, -1.3826834323650896, -1.1950903220161286, -1.1950903220161282, -1.0000000000000002, -0.9999999999999999, -0.8049096779838717, -0.8049096779838717, -0.6173165676349102, -0.6173165676349099, -0.44442976698039816, -0.4444297669803977, -0.29289321881345265, -0.2928932188134524, -0.16853038769745476, -0.16853038769745476, -0.07612046748871348, -0.07612046748871326, -0.01921471959676968, -0.01921471959676957, 0.0, 0.0]
Résultat:
new_center= random.randint(0, len(x_points)) x_offset = x_points[new_center] y_offset = y_points[new_center] new_circle(x_offset, y_offset) # I'm sorting these for easier visualization print(sorted(x_points)) print(sorted(x_points1))
Tout d'abord, vous avez généré des listes de coordonnées indépendantes ; vous n'avez pas de points en tant que paire coordonnée d'aucune sorte.
Deuxièmement, vous n'avez pas répertorié tous les points sur le cercle: vous ne pouvez pas, puisque c'est un ensemble infini. Au lieu de cela, vous avez généré une liste (enfin, une pour x
et y
) d'espacement égal. Il n'y a aucune raison mathématique de penser que vous aurez un correspondance exacte entre deux de ces coordonnées, et encore moins pour choisir les deux points sur chaque cercle qui sont exactement les points d'intersection.
Vous ne récupérez rien car vos listes n'ont pas de points communs. Si vous voulez trouver les points d'intersection, vous devrez le faire par solution algébrique, ou par approximation successive, ou par une autre méthode. Par exemple, prenez la différence des deux cercles et résolvez cette équation pour y == 0
.
Si vous travaillez avec des cercles, la bonne approche pour obtenir les intersections est d'utiliser une certaine algèbre. Il existe quatre cas possibles: aucune intersection, une intersection (tangence), deux intersections et une intersection infinie (ce sont le même cercle). Concentrons-nous sur le cas de deux intersections.
De https://math.stackexchange.com/a/256123/647423 ce que vous pouvez faire est d'obtenir une équation linéaire qui relie x à y le long du ligne qui passe par les deux points d'intersection:
root_array = np.roots(quadratic_coeff, linear_coeff, constant_coef)
De là, vous obtenez une formule pour y en fonction de x, puis remplacez y dans l'une de vos formules de cercle pour obtenir un quadratique pour x. Si vous ne souhaitez pas implémenter un solveur d'équation quadratique, vous pouvez utiliser numpy.roots comme ceci:
â2x(x1centerâx2center)â2y(y1centerây2center) = (r1)^2â(r2)^2â((x1center)^2â(x2center)^2)â((y1center)^2â(y2center)^2).
La méthode correcte pour résoudre les points d'intersection de deux cercles est algébriquement. Vous ne pouvez pas le faire en utilisant des points (coordonnées x, y) en raison de la précision infinie du système de coordonnées (nombres réels).
Si deux cercles se croisent en deux points, il existe un moyen simple de calculer ces deux points d'intersection. L'algèbre est détaillée ici sous la section Intersection de deux cercles
. p>
On peut aussi éliminer les cas où deux cercles ne se croisent pas comme ci-dessous
Code pour renvoyer les deux points d'intersection de deux cercles. Chaque cricle est décrit par son centre (x, y) et son rayon (r)
# intersection circles x0, y0 = 0, 0 r0 = 5 x1, y1 = 2, 2 r1 = 5 # intersecting with (x1, y1) but not with (x0, y0) x2, y2 = -1,0 r2 = 2.5 circle1 = plt.Circle((x0, y0), r0, color='b', fill=False) circle2 = plt.Circle((x1, y1), r1, color='b', fill=False) circle3 = plt.Circle((x2, y2), r2, color='b', fill=False) fig, ax = plt.subplots() ax.set_xlim((-10, 10)) ax.set_ylim((-10, 10)) ax.add_artist(circle1) ax.add_artist(circle2) ax.add_artist(circle3) intersections = get_intersections(x0, y0, r0, x1, y1, r1) if intersections is not None: i_x3, i_y3, i_x4, i_y4 = intersections plt.plot([i_x3, i_x4], [i_y3, i_y4], '.', color='r') intersections = get_intersections(x0, y0, r0, x2, y2, r2) if intersections is not None: i_x3, i_y3, i_x4, i_y4 = intersections plt.plot([i_x3, i_x4], [i_y3, i_y4], '.', color='r') intersections = get_intersections(x1, y1, r1, x2, y2, r2) if intersections is not None: i_x3, i_y3, i_x4, i_y4 = intersections plt.plot([i_x3, i_x4], [i_y3, i_y4], '.', color='r') plt.gca().set_aspect('equal', adjustable='box')
Testons-le (visuellement) en traçant
def get_intersections(x0, y0, r0, x1, y1, r1): # circle 1: (x0, y0), radius r0 # circle 2: (x1, y1), radius r1 d=math.sqrt((x1-x0)**2 + (y1-y0)**2) # non intersecting if d > r0 + r1 : return None # One circle within other if d < abs(r0-r1): return None # coincident circles if d == 0 and r0 == r1: return None else: a=(r0**2-r1**2+d**2)/(2*d) h=math.sqrt(r0**2-a**2) x2=x0+a*(x1-x0)/d y2=y0+a*(y1-y0)/d x3=x2+h*(y1-y0)/d y3=y2-h*(x1-x0)/d x4=x2-h*(y1-y0)/d y4=y2+h*(x1-x0)/d return (x3, y3, x4, y4)
Résultat:
Mauvaise langue pour les choses mathématiques / géométrie. Voici à quoi cela ressemble dans un langage plus approprié (WL)
Circle @@@ Thread @ {RandomReal[{-1,1},{3,2}], RandomReal[{.5,1},3]} // Graphics[{ #, Red, RegionIntersection @@@ #~Subsets~{2} }]&
Chacune de vos fonctions doit renvoyer ses points x et y si vous souhaitez pouvoir utiliser ces données en dehors de la fonction. docs.python.org/3/tutorial/controlflow.html#defining- fonctions
Puisque vos cicles sont composés d'un nombre fini de points, êtes-vous sûr qu'ils ont des points en commun? Ils peuvent avoir des points communs uniquement dans la limite du continuum.
Il existe des formules pour calculer l'intersection (le cas échéant) de deux cercles donnés là-bas des centres et des rayons qui n'impliquent pas d'énumérer des points sur leur circonférence.
Cette ligne ici
(set (x_points1) .intersection (set (x_points)))
ne trouvera pratiquement jamais d'intersection entre ces deux ensembles, juste des points qui existent dans les deux ensembles. Étant donné que vous générez des points à l'extérieur de chaque cercle, il est extrêmement improbable que deux de ces points soient exactement les mêmes sur des cercles différents, même en étant décalé de0.00000000001
, votre intersection ne trouve rien. Vous aurez besoin d'une meilleure méthode pour trouver l'intersection.