Ch. 6 Voxels
Last update: Thu Nov 19 17:20:43 2020 -0600 (49b93b1)
R
library(reticulate)
# reticulate::use_condaenv("r-python")
reticulate::use_condaenv("pybook")
6.1 Radial
Python
# https://matplotlib.org/api/_as_gen/mpl_toolkits.mplot3d.axes3d.Axes3D.html
#=======================================================
#3D voxel / volumetric plot with cylindrical coordinates
#=======================================================
#Demonstrates using the ``x, y, z`` arguments of ``ax.voxels``.
import matplotlib.pyplot as plt
import matplotlib.colors
import numpy as np
# This import registers the 3D projection, but is otherwise unused.
from mpl_toolkits.mplot3d import Axes3D # noqa: F401 unused import
def midpoints(x):
= ()
sl for i in range(x.ndim):
= (x[sl + np.index_exp[:-1]] + x[sl + np.index_exp[1:]]) / 2.0
x += np.index_exp[:]
sl return x
# prepare some coordinates, and attach rgb values to each
= np.mgrid[0:1:11j, 0:np.pi*2:25j, -0.5:0.5:11j]
r, theta, z = r*np.cos(theta)
x = r*np.sin(theta)
y
= midpoints(r), midpoints(theta), midpoints(z)
rc, thetac, zc
# define a wobbly torus about [0.7, *, 0]
= (rc - 0.7)**2 + (zc + 0.2*np.cos(thetac*2))**2 < 0.2**2
sphere # combine the color components
= np.zeros(sphere.shape + (3,))
hsv 0] = thetac / (np.pi*2)
hsv[..., 1] = rc
hsv[..., 2] = zc + 0.5
hsv[..., = matplotlib.colors.hsv_to_rgb(hsv)
colors # and plot everything
= plt.figure()
fig = fig.gca(projection='3d')
ax
ax.voxels(x, y, z, sphere,=colors,
facecolors=np.clip(2*colors - 0.5, 0, 1), # brighter
edgecolors=0.5)
linewidth plt.show()
6.2 Spherical
Python
import matplotlib.pyplot as plt
import numpy as np
# This import registers the 3D projection, but is otherwise unused.
from mpl_toolkits.mplot3d import Axes3D # noqa: F401 unused import
def midpoints(x):
= ()
sl for i in range(x.ndim):
= (x[sl + np.index_exp[:-1]] + x[sl + np.index_exp[1:]]) / 2.0
x += np.index_exp[:]
sl return x
# prepare some coordinates, and attach rgb values to each
= np.indices((17, 17, 17)) / 16.0
r, g, b = midpoints(r)
rc = midpoints(g)
gc = midpoints(b)
bc # define a sphere about [0.5, 0.5, 0.5]
= (rc - 0.5)**2 + (gc - 0.5)**2 + (bc - 0.5)**2 < 0.5**2
sphere # combine the color components
= np.zeros(sphere.shape + (3,))
colors 0] = rc
colors[..., 1] = gc
colors[..., 2] = bc
colors[..., # and plot everything
= plt.figure()
fig = fig.gca(projection='3d')
ax
ax.voxels(r, g, b, sphere,=colors,
facecolors=np.clip(2*colors - 0.5, 0, 1), # brighter
edgecolors=0.5)
linewidthset(xlabel='r', ylabel='g', zlabel='b')
ax. plt.show()
6.3 Solid cubes
Python
# https://github.com/matplotlib/matplotlib/blob/master/examples/mplot3d/voxels.py
import matplotlib.pyplot as plt
import numpy as np
# This import registers the 3D projection, but is otherwise unused.
from mpl_toolkits.mplot3d import Axes3D # noqa: F401 unused import
# prepare some coordinates
= np.indices((8, 8, 8))
x, y, z
# draw cuboids in the top left and bottom right corners, and a link between them
= (x < 3) & (y < 3) & (z < 3)
cube1 = (x >= 5) & (y >= 5) & (z >= 5)
cube2 = abs(x - y) + abs(y - z) + abs(z - x) <= 2
link
# combine the objects into a single boolean array
= cube1 | cube2 | link
voxels
# set the colors of each object
= np.empty(voxels.shape, dtype=object)
colors = 'red'
colors[link] = 'blue'
colors[cube1] = 'green'
colors[cube2]
# and plot everything
= plt.figure()
fig = fig.gca(projection='3d')
ax =colors, edgecolor='k')
ax.voxels(voxels, facecolors plt.show()
Python
# https://stackoverflow.com/a/49281004/5270873
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import numpy as np
import matplotlib.pyplot as plt
def cuboid_data2(o, size=(1,1,1)):
= [[[0, 1, 0], [0, 0, 0], [1, 0, 0], [1, 1, 0]],
X 0, 0, 0], [0, 0, 1], [1, 0, 1], [1, 0, 0]],
[[1, 0, 1], [1, 0, 0], [1, 1, 0], [1, 1, 1]],
[[0, 0, 1], [0, 0, 0], [0, 1, 0], [0, 1, 1]],
[[0, 1, 0], [0, 1, 1], [1, 1, 1], [1, 1, 0]],
[[0, 1, 1], [0, 0, 1], [1, 0, 1], [1, 1, 1]]]
[[= np.array(X).astype(float)
X for i in range(3):
*= size[i]
X[:,:,i] += np.array(o)
X return X
def plotCubeAt2(positions,sizes=None,colors=None, **kwargs):
if not isinstance(colors,(list,np.ndarray)): colors=["C0"]*len(positions)
if not isinstance(sizes,(list,np.ndarray)): sizes=[(1,1,1)]*len(positions)
= []
g for p,s,c in zip(positions,sizes,colors):
=s) )
g.append( cuboid_data2(p, sizereturn Poly3DCollection(np.concatenate(g),
=np.repeat(colors,6), **kwargs)
facecolors
= [(-3,5,-2),(1,7,1)]
positions = [(4,5,3), (3,3,7)]
sizes = ["crimson","limegreen"]
colors
= plt.figure()
fig = fig.gca(projection='3d')
ax 'auto')
ax.set_aspect(
= plotCubeAt2(positions,sizes,colors=colors, edgecolor="k")
pc
ax.add_collection3d(pc)
-4,6])
ax.set_xlim([4,13])
ax.set_ylim([-3,9])
ax.set_zlim([ plt.show()
6.4 Transparent cubicles
Python
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def make_ax(grid=False):
= plt.figure()
fig = fig.gca(projection='3d')
ax "x")
ax.set_xlabel("y")
ax.set_ylabel("z")
ax.set_zlabel(
ax.grid(grid)return ax
= np.array([
filled 1, 0, 1], [0, 0, 1], [0, 1, 0]],
[[0, 1, 1], [1, 0, 0], [1, 0, 1]],
[[1, 1, 0], [1, 1, 1], [0, 0, 0]]
[[
])
def explode(data):
= np.array(data.shape)
shape_arr = shape_arr[:3]*2 - 1
size = np.zeros(np.concatenate([size, shape_arr[3:]]), dtype=data.dtype)
exploded 2, ::2, ::2] = data
exploded[::return exploded
def expand_coordinates(indices):
= indices
x, y, z 1::2, :, :] += 1
x[1::2, :] += 1
y[:, 1::2] += 1
z[:, :, return x, y, z
= make_ax()
ax = np.array([[['#1f77b430']*3]*3]*3)
colors 1,1,1] = '#ff0000ff'
colors[= explode(colors)
colors = explode(np.ones((3, 3, 3)))
filled = expand_coordinates(np.indices(np.array(filled.shape) + 1))
x, y, z =colors, edgecolors='gray')
ax.voxels(x, y, z, filled, facecolors plt.show()
Python
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def make_ax(grid=False):
= plt.figure()
fig = fig.gca(projection='3d')
ax "x")
ax.set_xlabel("y")
ax.set_ylabel("z")
ax.set_zlabel(
ax.grid(grid)return ax
= np.array([
filled 1, 0, 1], [0, 0, 1], [0, 1, 0]],
[[0, 1, 1], [1, 0, 0], [1, 0, 1]],
[[1, 1, 0], [1, 1, 1], [0, 0, 0]]
[[
])
= make_ax()
ax ='#1f77b430', edgecolors='gray')
ax.voxels(filled, facecolors plt.show()
Python
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def make_ax(grid=False):
= plt.figure()
fig = fig.gca(projection='3d')
ax "x")
ax.set_xlabel("y")
ax.set_ylabel("z")
ax.set_zlabel(
ax.grid(grid)return ax
= np.array([
filled 1, 0, 1], [0, 0, 1], [0, 1, 0]],
[[0, 1, 1], [1, 0, 0], [1, 0, 1]],
[[1, 1, 0], [1, 1, 1], [0, 0, 0]]
[[
])
= make_ax()
ax 3, 3, 3)), facecolors='#1f77b430', edgecolors='gray')
ax.voxels(np.ones(( plt.show()
6.5 Semi-transparent
Python
# https://matplotlib.org/gallery/mplot3d/voxels_numpy_logo.html
import matplotlib.pyplot as plt
import numpy as np
# This import registers the 3D projection, but is otherwise unused.
from mpl_toolkits.mplot3d import Axes3D # noqa: F401 unused import
def explode(data):
= np.array(data.shape)*2
size = np.zeros(size - 1, dtype=data.dtype)
data_e 2, ::2, ::2] = data
data_e[::return data_e
# build up the numpy logo
= np.zeros((4, 3, 4), dtype=bool)
n_voxels 0, 0, :] = True
n_voxels[-1, 0, :] = True
n_voxels[1, 0, 2] = True
n_voxels[2, 0, 1] = True
n_voxels[= np.where(n_voxels, '#FFD65DC0', '#7A88CCC0')
facecolors = np.where(n_voxels, '#BFAB6E', '#7D84A6')
edgecolors = np.ones(n_voxels.shape)
filled
# upscale the above voxel image, leaving gaps
= explode(filled)
filled_2 = explode(facecolors)
fcolors_2 = explode(edgecolors)
ecolors_2
# Shrink the gaps
= np.indices(np.array(filled_2.shape) + 1).astype(float) // 2
x, y, z 0::2, :, :] += 0.05
x[0::2, :] += 0.05
y[:, 0::2] += 0.05
z[:, :, 1::2, :, :] += 0.95
x[1::2, :] += 0.95
y[:, 1::2] += 0.95
z[:, :,
= plt.figure()
fig = fig.gca(projection='3d')
ax =fcolors_2, edgecolors=ecolors_2)
ax.voxels(x, y, z, filled_2, facecolors plt.show()
6.6 Opaque cubicles
Python
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def make_ax(grid=False):
= plt.figure()
fig = fig.gca(projection='3d')
ax "x")
ax.set_xlabel("y")
ax.set_ylabel("z")
ax.set_zlabel(
ax.grid(grid)return ax
= np.array([
filled 1, 0, 1], [0, 0, 1], [0, 1, 0]],
[[0, 1, 1], [1, 0, 0], [1, 0, 1]],
[[1, 1, 0], [1, 1, 1], [0, 0, 0]]
[[
])
= make_ax(True)
ax ='gray')
ax.voxels(filled, edgecolors plt.show()