In this post, we will present a python script to do ad hoc 3D plot.
The idea is to plot the surface of 3D objects using the Axes3D.scatter method. The surface is simply a list of points and it can be represented by a 2D numpy array of size n * 3
where n
is the number of points.
We will use the following helper method in our script:
12345
def plotPoints(ax, points, color = 'red', marker='o', markerSize=1):
x = points[:, 0]
y = points[:, 1]
z = points[:, 2]
ax.scatter(x, y, z, c = color, marker = marker, s = markerSize)
The main structure of the script would look like something like the following:
1234567891011121314
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
plotPoints(ax, my3dObject.getSurfacePoints(), color=np.array([[1, 0, 0, 0.2]]))
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()
Now let's define two common 3D objects.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
class Sphere:
def __init__(self, c, r, theta_sample_num=30, phi_sample_num=30):
self.c = c
self.r = r
self.theta_sample_num = theta_sample_num
self.phi_sample_num = phi_sample_num
def getSurfacePoints(self):
points = []
for theta in np.linspace(0, 2 * np.pi, num = self.theta_sample_num):
for phi in np.linspace(0, 2 * np.pi, num = self.phi_sample_num):
d = np.cos(phi) * self.r
x = d * np.cos(theta)
y = d * np.sin(theta)
z = self.r * np.sin(phi)
points.append([x, y, z])
return np.asarray(points) + self.c
class Cuboid:
def __init__(self, center, width, length, height, nx, ny, nz):
self.center = center
self.width = width
self.length = length
self.height = height
self.nx = nx
self.ny = ny
self.nz = nz
def getSurfacePoints(self):
x = np.linspace(0, self.width, num = self.nx)
y = np.linspace(0, self.length, num = self.ny)
z = np.linspace(0, self.height, num = self.nz)
xy = np.meshgrid(x, y)
bottom = np.hstack( (xy[0].reshape(-1, 1), xy[1].reshape(-1, 1), np.zeros_like(xy[0]).reshape(-1, 1)))
top = np.hstack( ( xy[0].reshape(-1, 1),
xy[1].reshape(-1, 1),
np.full_like(xy[0], self.height).reshape(-1, 1)
) )
yz = np.meshgrid(y, z)
left = np.hstack( (np.zeros_like(yz[0]).reshape(-1, 1), yz[0].reshape(-1, 1), yz[1].reshape(-1, 1)) )
right = np.hstack( (np.full_like(yz[0], self.width).reshape(-1, 1), yz[0].reshape(-1, 1), yz[1].reshape(-1, 1)) )
xz = np.meshgrid(x, z)
front = np.hstack( (xz[0].reshape(-1, 1), np.zeros_like(xz[0]).reshape(-1, 1), xz[1].reshape(-1, 1)) )
rear = np.hstack( (xz[0].reshape(-1, 1), np.full_like(xz[0], self.length).reshape(-1, 1), xz[1].reshape(-1, 1)) )
center = np.array([self.width / 2., self.length / 2., self.height / 2.])
return np.vstack((bottom, top, left, right, front, rear)) + self.center - center
Put everything together, we have:
1234567891011121314
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
sphere = Sphere(c = np.array([7, 7, 7]), r = 6, theta_sample_num=120, phi_sample_num=120)
cuboid = Cuboid(center=np.array([-10, -10, -10]), width = 10, length = 20, height=15, nx = 80, ny = 80, nz= 80)
plotPoints(ax, sphere.getSurfacePoints(), color=np.array([[1, 0, 0, 0.2]]))
plotPoints(ax, cuboid.getSurfacePoints(), color=np.array([[0, 0, 1, 0.2]]))
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()

----- END -----
©2019 - 2023 all rights reserved