3
votes

Trouver l'intersection de deux cercles

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 commentaires

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é de 0.00000000001 , votre intersection ne trouve rien. Vous aurez besoin d'une meilleure méthode pour trouver l'intersection.


4 Réponses :


1
votes

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 .


0 commentaires

1
votes

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


0 commentaires

8
votes

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

  • Si la distance entre les origines des deux cercles> somme du rayon de deux cercles, cela signifie que les cercles sont séparés et ne se croisent donc pas.
  • Si la distance entre les origines des deux cercles

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:

entrer l'image description ici


0 commentaires

0
votes

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}
 }]&


0 commentaires