1

The Python program below plots a random set of 3 points and circles around them according to the eps slider value.

When changing the slider value, the circles change.

Also, if two circles touch each other, a segment connecting their centers is drawn.

My problem is: how to remove such segment if the eps decreases so there is no intersection anymore?

In resume, how to remove the line collection from the plot?

MWE

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button, RadioButtons
from matplotlib import collections  as mc


# create circles
circles = []
def create_circles(N):
    for i in range(N):
        circles.append(plt.Circle(pts[i], min_distance/10, ec="b", fill=False))
        ax.add_patch(circles[i])

# create edges
def create_edges(eps):
    edges = []
    tmp = np.where(distance_matrix < 2 * eps)
    edges_ij = zip(tmp[0], tmp[1])
    for e in edges_ij:
        if e[0] < e[1]:
            edges.append([pts[e[0]], pts[e[1]]])
    lc = mc.LineCollection(edges, colors='r', linewidths=1)
    ax.add_collection(lc)

# create points
def create_points(N):
    ptsx = np.random.random(N)
    ptsy = np.random.random(N)
    pts = zip(ptsx, ptsy)
    return pts

# create distance matrix
def create_distance_matrix(pts):
    N = len(pts)
    distance_matrix = np.zeros((N, N))
    for i in range(N-1):
        for j in range(i+1,N):
            P = pts[i]
            Q = pts[j]
            distance_matrix[i, j] = np.sqrt((P[0]-Q[0])**2 + (P[1]-Q[1])**2)
            distance_matrix[j, i] = distance_matrix[i, j]
    max_distance = np.max(distance_matrix)
    min_distance = np.min(distance_matrix[distance_matrix > 0])
    return min_distance, max_distance, distance_matrix

# when epsilon slider changes
def update_eps(val):
    eps1 = eps_slider.val
    create_edges(eps1)
    for i in range(len(circles)):
        circles[i].set_radius(eps1) 
    fig.canvas.draw_idle()

axis_color = 'lightgoldenrodyellow'
bullet_size = 4

xmin, xmax = 0, 1
ymin, ymax = 0, 1
delta = .2
xlim = [xmin-delta, xmax+delta]
ylim = [ymin-delta, ymax+delta]

fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
ax.axis([xlim[0], xlim[1], ylim[0], ylim[1]])
ax.set_aspect("equal")

N_0 = 3
N_max = 10

pts = create_points(N_0)
min_distance, max_distance, distance_matrix = create_distance_matrix(pts)
create_circles(N_0)
eps_0 = min_distance / 3

# create sliders
eps_slider_ax  = fig.add_axes([0.25, 0.15, .65, 0.03], facecolor=axis_color)
N_slider_ax = fig.add_axes([0.25, 0.1, 0.65, 0.03], facecolor=axis_color)
eps_slider = Slider(eps_slider_ax, 'eps', min_distance/3, max_distance, valinit=eps_0)
N_slider = Slider(N_slider_ax, 'Num pts', 1, N_max, valinit=2, valfmt="%i")
eps_slider.on_changed(update_eps)

# Draw the initial plot
desenho = ax.scatter([x[0] for x in pts], [x[1] for x in pts], alpha=1, s=bullet_size)
plt.show()
Sigur
  • 355
  • 8
  • 19
  • 1
    I think this question might be of use to you https://stackoverflow.com/questions/19569052/matplotlib-how-to-remove-a-specific-line-or-curve/19571848 – GILO Apr 12 '19 at 18:11
  • @GILO, let me read. Thanks. – Sigur Apr 12 '19 at 18:19

0 Answers0