问题
I want to create a program that allows the user to first enter points in a Matplotlib plot and then creates a Voronoi Diagram using those points.
Figured out the 2 parts, but not the connection. How do I pass on the points that the user entered and use it in the Voronoi part? (I just need to know how to change the points = np.random.rand(20,2)
to the points the user entered.)
Plotting the points:
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_xlim([0, 10])
ax.set_ylim([0, 10])
def onclick(event):
print('x=%d, y=%d, xdata=%f, ydata=%f' %
(event.x, event.y, event.xdata, event.ydata))
plt.plot(event.xdata, event.ydata, 'bo')
fig.canvas.draw()
cid = fig.canvas.mpl_connect('button_press_event', onclick)
plt.show()`
Creating the Voronoi Diagram:
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import Voronoi, voronoi_plot_2d
fig = plt.figure()
points = np.random.rand(20,2)
vor = Voronoi(points)
voronoi_plot_2d(vor)
plt.show()
回答1:
You may use a class to store the points and later plot the diagram in that same plot. In the following example, you would place your points with the left mouse button and plot the voronoi diagram clicking the right mouse button. If you later want to add new points to the plot, you can do that.
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import Voronoi, voronoi_plot_2d
fig, ax = plt.subplots()
ax.set_xlim([0, 10])
ax.set_ylim([0, 10])
class V():
def __init__(self, ax = None):
self.ax = ax
if not self.ax: self.ax = plt.gca()
tx = "left click to place points\nright click to plot voronoi diagram"
self.text = self.ax.text(0.1,0.9, tx, transform=self.ax.transAxes,
ha="left", va="top")
self.cid = fig.canvas.mpl_connect('button_press_event', self.onclick)
self.points = []
def onclick(self, event):
self.text.set_visible(False)
if event.button == 1:
print('x=%d, y=%d, xdata=%f, ydata=%f' %
(event.x, event.y, event.xdata, event.ydata))
plt.plot(event.xdata, event.ydata, 'bo')
self.points.append((event.xdata, event.ydata))
else:
self.voronoi()
fig.canvas.draw()
def voronoi(self):
self.ax.clear()
vor = Voronoi(self.points)
voronoi_plot_2d(vor, ax=self.ax)
v = V(ax=ax)
plt.show()
回答2:
You can just save your x-y pairs in a list and convert it into an array later:
import matplotlib.pyplot as plt
import numpy as np
from scipy.spatial import Voronoi, voronoi_plot_2d
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_xlim([0, 10])
ax.set_ylim([0, 10])
points = []
def onclick(event):
print('x=%d, y=%d, xdata=%f, ydata=%f' %
(event.x, event.y, event.xdata, event.ydata))
points.append([event.xdata,event.ydata])
plt.plot(event.xdata, event.ydata, 'bo')
fig.canvas.draw()
cid = fig.canvas.mpl_connect('button_press_event', onclick)
plt.show()
fig2 = plt.figure()
vor = Voronoi(np.array(points))
voronoi_plot_2d(vor)
plt.show()
As long as the user clicks in the plot, points are added to the list, until the user closes the original figure. After that a new figure is created and the Voronoi plot is drawn. Hope this helps.
来源:https://stackoverflow.com/questions/45080821/how-do-i-pass-on-points-that-the-user-entered-in-matplotlib-to-a-np-array