【问题标题】:Interactive point triangulation with Python and Matplotlib使用 Python 和 Matplotlib 进行交互式点三角测量
【发布时间】:2018-06-27 10:25:48
【问题描述】:

我正在尝试做一个简单的绘图界面,允许我单击以将点添加到列表中,然后用另一个键或另一个单击,调用这些点的三角剖分。

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

谢谢

【问题讨论】:

  • 这些似乎是非常不同的问题。我建议查看the user guide 以了解与正在使用的对象相关的任何内容,并在实际问题上保持这个问题的清洁。
  • 谢谢,我删除了第二个问题,因为它和你说的很不一样。

标签: python matplotlib interactive


【解决方案1】:

我认为您已经具备了获得所需的点击点三元图所需的一切。您只需将第二个代码移动到第一个代码的__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()

【讨论】:

  • 不错!谢谢你,你是对的,一切都已经在那里了。我仍然需要学习使用 pyplot。如果我没看错,它是一个全局元素,允许我从脚本中的任何类或定义进行调用?对每个点都重新进行三角测量怎么样?你知道我怎样才能每次都清除或更新数字吗?
  • 我用一个解决方案更新了答案,尽快绘制三角测量(选择了 3 个点)。我还删除了那个“全局”元素plt,这样它现在就完全面向对象了。
猜你喜欢
  • 1970-01-01
  • 2019-11-03
  • 2015-08-20
  • 1970-01-01
  • 1970-01-01
  • 2012-06-26
  • 2019-11-14
  • 2022-12-14
  • 2012-05-29
相关资源
最近更新 更多