使用 Python 和 Matplotlib 进行交互式点三角剖分
Interactive point triangulation with Python and Matplotlib
我正在尝试做一个简单的绘图界面,允许我单击以将点添加到列表,然后使用另一个键或再次单击,调用这些点的三角剖分。
Matplotlib 提供了一个向直线添加点的小示例,但我不知道如何制作它,所以我只是向列表添加点,然后调用函数进行三角剖分
from matplotlib import pyplot as plt
class LineBuilder:
def __init__(self, line):
self.line = line
self.xs = list(line.get_xdata())
self.ys = list(line.get_ydata())
self.cid = line.figure.canvas.mpl_connect('button_press_event', self)
def __call__(self, event):
print('click', event)
if event.inaxes!=self.line.axes: return
self.xs.append(event.xdata)
self.ys.append(event.ydata)
self.line.set_data(self.xs, self.ys)
self.line.figure.canvas.draw()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_title('click to build line segments')
line, = ax.plot([0], [0]) # empty line
linebuilder = LineBuilder(line)
plt.show()
我使用 scikit delunay 三角剖分
import numpy as np
from scipy.spatial import Delaunay
points=np.array([[134,30],[215,114],[160,212],[56,181],[41,78]])
tri = Delaunay(points)
plt.triplot(points[:,0], points[:,1], tri.simplices.copy())
plt.plot(points[:,0], points[:,1], 'o')
plt.show()
谢谢
我认为您已经准备好获得所需的点击点三联图所需的一切。您只需要将第二个代码移动到第一个代码的 __call__
中,并使其适应以前选择的点。
import numpy as np
from scipy.spatial import Delaunay
from matplotlib import pyplot as plt
class LineBuilder:
def __init__(self, line):
self.line = line
self.xs = []
self.ys = []
self.cid = line.figure.canvas.mpl_connect('button_press_event', self)
def __call__(self, event):
if event.inaxes!=self.line.axes: return
if event.button == 1:
self.xs.append(event.xdata)
self.ys.append(event.ydata)
self.line.set_data(self.xs, self.ys)
elif event.button == 3:
points=np.c_[self.xs, self.ys]
tri = Delaunay(points)
self.line.axes.triplot(points[:,0], points[:,1], tri.simplices.copy())
self.line.figure.canvas.draw()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_title('left click to choose points, \n \
right click to plot delaunay triangulation')
line, = ax.plot([], [], marker="o", ms=10, ls="") # empty line
linebuilder = LineBuilder(line)
plt.show()
为了显示绘制的每个新点的三角剖分以及能够重新启动整个交互,解决方案会涉及更多。然后需要检查轴上是否已经有绘图并在绘制新绘图之前将其删除。
import numpy as np
from scipy.spatial import Delaunay
from matplotlib import pyplot as plt
class LineBuilder:
def __init__(self, line):
self.line = line
self.cid = line.figure.canvas.mpl_connect('button_press_event', self)
self.trip = None
self.reset()
def reset(self):
self.xs = []
self.ys = []
if self.trip:
for t in self.trip:
t.remove()
self.trip = None
self.line.set_data(self.xs, self.ys)
def __call__(self, event):
if event.inaxes!=self.line.axes: return
if event.button == 1:
self.xs.append(event.xdata)
self.ys.append(event.ydata)
self.line.set_data(self.xs, self.ys)
points=np.c_[self.xs, self.ys]
if len(self.xs) >= 3:
tri = Delaunay(points)
if self.trip:
for t in self.trip:
t.remove()
self.trip = self.line.axes.triplot(points[:,0], points[:,1],
tri.simplices.copy(), color="C0")
elif event.button==3:
self.reset()
self.line.figure.canvas.draw()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.axis([0,1,0,1])
ax.set_title('left click to choose points,right click restart')
line, = ax.plot([], [], marker="o", ms=10, ls="") # empty line
linebuilder = LineBuilder(line)
plt.show()
我正在尝试做一个简单的绘图界面,允许我单击以将点添加到列表,然后使用另一个键或再次单击,调用这些点的三角剖分。
Matplotlib 提供了一个向直线添加点的小示例,但我不知道如何制作它,所以我只是向列表添加点,然后调用函数进行三角剖分
from matplotlib import pyplot as plt
class LineBuilder:
def __init__(self, line):
self.line = line
self.xs = list(line.get_xdata())
self.ys = list(line.get_ydata())
self.cid = line.figure.canvas.mpl_connect('button_press_event', self)
def __call__(self, event):
print('click', event)
if event.inaxes!=self.line.axes: return
self.xs.append(event.xdata)
self.ys.append(event.ydata)
self.line.set_data(self.xs, self.ys)
self.line.figure.canvas.draw()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_title('click to build line segments')
line, = ax.plot([0], [0]) # empty line
linebuilder = LineBuilder(line)
plt.show()
我使用 scikit delunay 三角剖分
import numpy as np
from scipy.spatial import Delaunay
points=np.array([[134,30],[215,114],[160,212],[56,181],[41,78]])
tri = Delaunay(points)
plt.triplot(points[:,0], points[:,1], tri.simplices.copy())
plt.plot(points[:,0], points[:,1], 'o')
plt.show()
谢谢
我认为您已经准备好获得所需的点击点三联图所需的一切。您只需要将第二个代码移动到第一个代码的 __call__
中,并使其适应以前选择的点。
import numpy as np
from scipy.spatial import Delaunay
from matplotlib import pyplot as plt
class LineBuilder:
def __init__(self, line):
self.line = line
self.xs = []
self.ys = []
self.cid = line.figure.canvas.mpl_connect('button_press_event', self)
def __call__(self, event):
if event.inaxes!=self.line.axes: return
if event.button == 1:
self.xs.append(event.xdata)
self.ys.append(event.ydata)
self.line.set_data(self.xs, self.ys)
elif event.button == 3:
points=np.c_[self.xs, self.ys]
tri = Delaunay(points)
self.line.axes.triplot(points[:,0], points[:,1], tri.simplices.copy())
self.line.figure.canvas.draw()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set_title('left click to choose points, \n \
right click to plot delaunay triangulation')
line, = ax.plot([], [], marker="o", ms=10, ls="") # empty line
linebuilder = LineBuilder(line)
plt.show()
为了显示绘制的每个新点的三角剖分以及能够重新启动整个交互,解决方案会涉及更多。然后需要检查轴上是否已经有绘图并在绘制新绘图之前将其删除。
import numpy as np
from scipy.spatial import Delaunay
from matplotlib import pyplot as plt
class LineBuilder:
def __init__(self, line):
self.line = line
self.cid = line.figure.canvas.mpl_connect('button_press_event', self)
self.trip = None
self.reset()
def reset(self):
self.xs = []
self.ys = []
if self.trip:
for t in self.trip:
t.remove()
self.trip = None
self.line.set_data(self.xs, self.ys)
def __call__(self, event):
if event.inaxes!=self.line.axes: return
if event.button == 1:
self.xs.append(event.xdata)
self.ys.append(event.ydata)
self.line.set_data(self.xs, self.ys)
points=np.c_[self.xs, self.ys]
if len(self.xs) >= 3:
tri = Delaunay(points)
if self.trip:
for t in self.trip:
t.remove()
self.trip = self.line.axes.triplot(points[:,0], points[:,1],
tri.simplices.copy(), color="C0")
elif event.button==3:
self.reset()
self.line.figure.canvas.draw()
fig = plt.figure()
ax = fig.add_subplot(111)
ax.axis([0,1,0,1])
ax.set_title('left click to choose points,right click restart')
line, = ax.plot([], [], marker="o", ms=10, ls="") # empty line
linebuilder = LineBuilder(line)
plt.show()