Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
985 views
in Technique[技术] by (71.8m points)

python - Dynamic Point Manipulation in 3D Matplotlib

In trying to manipulate a graph in matplotlib, I came across something interesting. when using the plot function, x and y coordinates can be modified through aliasing, however the z cannot. Is this easily explained? I have included a small example, note that I was trying to get the point to move in a helix along the cylinder.

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")

radius = 8

# Cylinder
x = np.linspace(-radius, radius, 100)
z = np.linspace(0, 2, 100)
X, Z = np.meshgrid(x, z)

Y = np.sqrt(radius**2 - X**2)

ax.plot_surface(X, Y, Z, alpha=0.3, linewidth=0)
ax.plot_surface(X, (-Y), Z,alpha=0.3, linewidth=0)

X = np.array(np.zeros(1))
Y = np.array(np.zeros(1))
Z = np.array(np.zeros(1))

X[0]= radius*np.cos(np.deg2rad(0))
Y[0]= radius*np.sin(np.deg2rad(0))
Z[0]= 0.

ax.plot(X,Y,Z, 'or',markersize=3)

for i in range(0,360,5):

    X[0]= radius*np.cos(np.deg2rad(i))  
    Y[0]= radius*np.sin(np.deg2rad(i))
    Z[0]= i/140.

    plt.draw()
    plt.pause(0.01)

For reference, the end goal of this exercise is to be able to position the point based on sensor inputs in real-time, in three dimensions.

Thank you to anyone who has insight as to why this is occurring and possible solutions!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This is indeed interesting.. Line3D is derived from Line2D, so functions like get_xdata or set_xdata are also not available in the z direction. Looking into the source code (art3d.py), it seems that the z values are completely ignored:

def draw(self, renderer):
    xs3d, ys3d, zs3d = self._verts3d
    xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M)
    self.set_data(xs, ys)
    lines.Line2D.draw(self, renderer)

But perhaps I don't correctly understand how the Line3D's work...

There is however a function available to manipulate the z values (set_3d_properties), but since that function calls get_xdata and get_ydata itself, the only way I could get this to work is:

p = ax.plot(X,Y,Z, 'or', markersize=3)[0]

for i in range(0,360,5):
    p.set_xdata(radius*np.cos(np.deg2rad(i)))
    p.set_ydata(radius*np.sin(np.deg2rad(i)))
    p.set_3d_properties(zs=i/140.)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...