在 matplotlib 3D 绘图中实现平移
Implementing panning in matplotlib 3D plot
我在 tkinter
中嵌入了一个 3D 图,我试图通过将鼠标事件绑定到旋转、缩放和平移来实现交互。旋转缩放功能我参考了他们的axes3d source code,自己分别修改了elev和azim或者x,y,z的限制
但是,源代码中没有实现平移部分。它只是说
# elif self.button_pressed == 2:
# pan view
# project xv, yv, zv -> xw, yw, zw
# pan
# pass
所以我尝试自己实现它,但我做不对。如果将其放入他们的源代码中,这就是我所拥有的:
我遇到的问题是如何将鼠标移动的 2 dx and dy
值投影到 3d 轴的 3 dxx, dyy and dzz
值中。我现在所拥有的是错误的,尽管我真的不明白为什么。它并不总是按照我想要的方式平移,除了 elev 和 azim 的某些值,例如当 elev=0 和 azim=0 时,或者只有其中一个是 90 的倍数时。当 elev 和 azim 都在90 的非零倍数,它不会平移或以相反的方式平移某些轴。当它处于任何其他值时,它不会正确地投影到所有轴,这样看起来我正在平移整个图形 left/right/up/down。
elif self.button_pressed == 2:
# get the x and y pixel coords
if dx == 0 and dy == 0:
return
# how to convert dx dy -> dxx dyy dzz? this is wrong
minx, maxx, miny, maxy, minz, maxz = self.get_w_lims()
elev, azim = np.deg2rad(self.elev), np.deg2rad(self.azim)
dxx = (maxx-minx) * ( (dx/w) * np.sin(azim) + (dy/h) * np.sin(elev) )
dyy = (maxy-miny) * ( - (dx/w) * np.cos(azim) )
dzz = (maxz-minz) * ( - (dy/h) * np.cos(elev) )
# pan
self.set_xlim3d(minx + dxx, maxx + dxx)
self.set_ylim3d(miny + dyy, maxy + dyy)
self.set_zlim3d(minz + dzz, maxz + dzz)
self.get_proj()
self.figure.canvas.draw_idle()
编辑:最新的 matplotlib 源代码已经实现了平移。
不知怎的,这行得通
elif self.button_pressed == 2:
# get the x and y pixel coords
if dx == 0 and dy == 0:
return
# convert dx dy -> dxx dyy dzz
minx, maxx, miny, maxy, minz, maxz = self.get_w_lims()
elev, azim = np.deg2rad(self.elev), np.deg2rad(self.azim)
dxe = (dy/h) * np.sin(elev)
dye = - (dx/w)
dze = - (dy/h) * np.cos(elev)
dxx = (maxx-minx) * ( dxe * np.cos(azim) - dye * np.sin(azim) )
dyy = (maxy-miny) * ( dye * np.cos(azim) + dxe * np.sin(azim) )
dzz = (maxz-minz) * ( dze )
# pan
self.set_xlim3d(minx + dxx, maxx + dxx)
self.set_ylim3d(miny + dyy, maxy + dyy)
self.set_zlim3d(minz + dzz, maxz + dzz)
self.get_proj()
self.figure.canvas.draw_idle()
我注意到之前只有当 elev 或 azim 中的任何一个为 0 时它才有效,所以我想也许我需要先通过 elev 投影,然后再通过 azim 投影。
我在 tkinter
中嵌入了一个 3D 图,我试图通过将鼠标事件绑定到旋转、缩放和平移来实现交互。旋转缩放功能我参考了他们的axes3d source code,自己分别修改了elev和azim或者x,y,z的限制
但是,源代码中没有实现平移部分。它只是说
# elif self.button_pressed == 2:
# pan view
# project xv, yv, zv -> xw, yw, zw
# pan
# pass
所以我尝试自己实现它,但我做不对。如果将其放入他们的源代码中,这就是我所拥有的:
我遇到的问题是如何将鼠标移动的 2 dx and dy
值投影到 3d 轴的 3 dxx, dyy and dzz
值中。我现在所拥有的是错误的,尽管我真的不明白为什么。它并不总是按照我想要的方式平移,除了 elev 和 azim 的某些值,例如当 elev=0 和 azim=0 时,或者只有其中一个是 90 的倍数时。当 elev 和 azim 都在90 的非零倍数,它不会平移或以相反的方式平移某些轴。当它处于任何其他值时,它不会正确地投影到所有轴,这样看起来我正在平移整个图形 left/right/up/down。
elif self.button_pressed == 2:
# get the x and y pixel coords
if dx == 0 and dy == 0:
return
# how to convert dx dy -> dxx dyy dzz? this is wrong
minx, maxx, miny, maxy, minz, maxz = self.get_w_lims()
elev, azim = np.deg2rad(self.elev), np.deg2rad(self.azim)
dxx = (maxx-minx) * ( (dx/w) * np.sin(azim) + (dy/h) * np.sin(elev) )
dyy = (maxy-miny) * ( - (dx/w) * np.cos(azim) )
dzz = (maxz-minz) * ( - (dy/h) * np.cos(elev) )
# pan
self.set_xlim3d(minx + dxx, maxx + dxx)
self.set_ylim3d(miny + dyy, maxy + dyy)
self.set_zlim3d(minz + dzz, maxz + dzz)
self.get_proj()
self.figure.canvas.draw_idle()
编辑:最新的 matplotlib 源代码已经实现了平移。
不知怎的,这行得通
elif self.button_pressed == 2:
# get the x and y pixel coords
if dx == 0 and dy == 0:
return
# convert dx dy -> dxx dyy dzz
minx, maxx, miny, maxy, minz, maxz = self.get_w_lims()
elev, azim = np.deg2rad(self.elev), np.deg2rad(self.azim)
dxe = (dy/h) * np.sin(elev)
dye = - (dx/w)
dze = - (dy/h) * np.cos(elev)
dxx = (maxx-minx) * ( dxe * np.cos(azim) - dye * np.sin(azim) )
dyy = (maxy-miny) * ( dye * np.cos(azim) + dxe * np.sin(azim) )
dzz = (maxz-minz) * ( dze )
# pan
self.set_xlim3d(minx + dxx, maxx + dxx)
self.set_ylim3d(miny + dyy, maxy + dyy)
self.set_zlim3d(minz + dzz, maxz + dzz)
self.get_proj()
self.figure.canvas.draw_idle()
我注意到之前只有当 elev 或 azim 中的任何一个为 0 时它才有效,所以我想也许我需要先通过 elev 投影,然后再通过 azim 投影。