2016-10-02 39 views
0

3次元の点群に平面を当てはめ、最初はnp.meshgridを使って任意のサイズにしましたが、今はその平面を中心とした円柱をプロットしようとしています同じように方向付けられています(つまり、平面フィットは円筒の高さを半分にカットします)が、半径と高さが指定されています。私が見つけることができるmatplotlibにプロットされたシリンダの唯一の例は中空で、通常は上下に開きます。私はソリッドにプロットしたいので、それが囲んでいるポイントを明確に見ることができます。Matplotlibの平面を中心とした円柱をプロットする

ランダムに生成されたプレーンを使用した最小の実例です。私が使用している平面は常に点と法線ベクトルで与えられるので、円柱はこれらのものに基づいていなければなりません(加えて、与えられた半径と平面の上下に伸びる高さ)。

from __future__ import division #Enables new-style division 
import matplotlib.pyplot as plt 
from mpl_toolkits.mplot3d import Axes3D 
import seaborn as sns 
import numpy as np 

cen_x = 0 
cen_y = 0 
cen_z = 0 

origin = np.array([cen_x,cen_y,cen_z]) 

normal = np.array([np.random.uniform(-1,1),np.random.uniform(-1,1),np.random.uniform(0,1)]) 

a = normal[0] 
b = normal[1] 
c = normal[2] 

#equation for a plane is a*x+b*y+c*z+d=0 where [a,b,c] is the normal 
#so calculate d from the normal 
d = -origin.dot(normal) 

# create x,y meshgrid 
xx, yy = np.meshgrid(np.arange(cen_x-1,cen_x+1,0.01),np.arange(cen_y-1,cen_y+1,0.01)) 

# calculate corresponding z 
zz = (-a * xx - b * yy - d) * 1./c 

halo_x = [-0.3, -0.9, 0.8, 1.3, -0.1, 0.5] 
halo_y = [0.8, 1.1, -0.5, -0.7, -1.2, 0.1] 
halo_z = [1.0, -0.4, 0.3, -1.2, 0.9, 1.2] 

fig = plt.figure(figsize=(9,9)) 
plt3d = fig.gca(projection='3d') 
plt3d.plot_surface(xx, yy, zz, color='r', alpha=0.4) 
plt3d.set_xlim3d(cen_x-3,cen_x+3) 
plt3d.set_ylim3d(cen_y-3,cen_y+3) 
plt3d.set_zlim3d(cen_z-3,cen_z+3) 
plt3d.set_xlabel('X') 
plt3d.set_ylabel('Y') 
plt3d.set_zlabel('Z') 
plt.show() 

答えて

2

私は空想シェーディングを除去して、エンドキャップを追加し、質問How to add colors to each individual face of a cylinder using matplotlibの解決策を変更しました。囲まれた点を表示する場合は、alpha=0.5などを使用して、シリンダーを半透明にすることができます。

円柱の向きは、長さmagの単位ベクトルvによって定義されます。これは、面の法線になります。

#!/usr/bin/env python2 
# -*- coding: utf-8 -*- 
""" 
Created on Sun Oct 2 18:33:10 2016 

Modified from https://stackoverflow.com/questions/38076682/how-to-add-colors-to-each-individual-face-of-a-cylinder-using-matplotlib 
to add "end caps" and to undo fancy coloring. 

@author: astrokeat 
""" 

import numpy as np 
from matplotlib import pyplot as plt 
from scipy.linalg import norm 

#axis and radius 
p0 = np.array([1, 3, 2]) #point at one end 
p1 = np.array([8, 5, 9]) #point at other end 
R = 5 

#vector in direction of axis 
v = p1 - p0 

#find magnitude of vector 
mag = norm(v) 

#unit vector in direction of axis 
v = v/mag 

#make some vector not in the same direction as v 
not_v = np.array([1, 0, 0]) 
if (v == not_v).all(): 
    not_v = np.array([0, 1, 0]) 

#make vector perpendicular to v 
n1 = np.cross(v, not_v) 
#normalize n1 
n1 /= norm(n1) 

#make unit vector perpendicular to v and n1 
n2 = np.cross(v, n1) 

#surface ranges over t from 0 to length of axis and 0 to 2*pi 
t = np.linspace(0, mag, 2) 
theta = np.linspace(0, 2 * np.pi, 100) 
rsample = np.linspace(0, R, 2) 

#use meshgrid to make 2d arrays 
t, theta2 = np.meshgrid(t, theta) 

rsample,theta = np.meshgrid(rsample, theta) 

#generate coordinates for surface 
# "Tube" 
X, Y, Z = [p0[i] + v[i] * t + R * np.sin(theta2) * n1[i] + R * np.cos(theta2) *  n2[i] for i in [0, 1, 2]] 
# "Bottom" 
X2, Y2, Z2 = [p0[i] + rsample[i] * np.sin(theta) * n1[i] + rsample[i] * np.cos(theta) * n2[i] for i in [0, 1, 2]] 
# "Top" 
X3, Y3, Z3 = [p0[i] + v[i]*mag + rsample[i] * np.sin(theta) * n1[i] + rsample[i] * np.cos(theta) * n2[i] for i in [0, 1, 2]] 


ax=plt.subplot(111, projection='3d') 
ax.plot_surface(X, Y, Z, color='blue') 
ax.plot_surface(X2, Y2, Z2, color='blue') 
ax.plot_surface(X3, Y3, Z3, color='blue') 

plt.show() 

結果:

Cylinder with end caps.