Skip to content

Voxelization Workshop

In this workshop we will learn how to voxelize a geometry and construct a lattice from it.

0. Initialization

Importing all necessary libraries and specifying the inputs

import os
import topogenesis as tg
import pyvista as pv
import trimesh as tm
import numpy as np
#Voxelization to largest voxel size
vs = 14.4
unit = [vs, vs, vs]
mesh_path = os.path.relpath("data\envelope.stl")

1. Input Mesh

# load the mesh from file
mesh = tm.load(mesh_path)

# Check if the mesh is watertight
print(mesh.is_watertight)
True

# Visualize the mesh using pyvista plotter
#######

# initiating the plotter
p = pv.Plotter(notebook=True)

# convert mesh to pv_mesh
faces = np.pad(mesh.faces, ((0, 0),(1,0)), 'constant', constant_values=3)
pv_mesh = pv.PolyData(mesh.vertices, faces)
# adding the base mesh: light blue
p.add_mesh(pv_mesh, color='#abd8ff')

# plotting
p.show(use_ipyvtk=True)
[(214.14118435960086, 112.66172841172488, 198.372349768689),
 (44.16883182525635, -57.31062412261963, 28.399997234344482),
 (0.0, 0.0, 1.0)]

2. Voxelize the Mesh

# initialize the base lattice

base_lattice = tg.lattice(mesh.bounds, unit=unit, default_value=1, dtype=int)
print(base_lattice)
# check which voxel centroids is inside the mesh
interior_condition = mesh.contains(base_lattice.centroids)
true_list = [True] * len(interior_condition)
true_array = np.array(true_list)

print(len(interior_condition))
print(len(true_list))

# reshape the interior condition to the shape of the base_lattice
interior_array = interior_condition.reshape(base_lattice.shape)
true_reshape = true_array.reshape(base_lattice.shape)

# convert the interior array into a lattice
interior_lattice = tg.to_lattice(interior_array, base_lattice.minbound, base_lattice.unit)
full_lattice = tg.to_lattice(true_reshape, base_lattice.minbound, base_lattice.unit)
[[[1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]]

 [[1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]]

 [[1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]]

 [[1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]]

 [[1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]]

 [[1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]]

 [[1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]]

 [[1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]]

 [[1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]]

 [[1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]]

 [[1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]
  [1 1 1 1]]]
220
220

# Visualize the voxelization using pyvista plotter
#####

# initiating the plotter
p = pv.Plotter(notebook=True)

# fast visualization of the lattice
full_lattice.fast_vis(p)        #interior_lattice.fast_vis(p)

# convert mesh to pv_mesh
faces = np.pad(mesh.faces, ((0, 0),(1,0)), 'constant', constant_values=3)
pv_mesh = pv.PolyData(mesh.vertices, faces)
# adding the base mesh: light blue
p.add_mesh(pv_mesh, color='#abd8ff')

# plotting
p.show(use_ipyvtk=True)
[(247.62459675305257, 146.8245965623177, 226.02459684842),
 (43.20000076293945, -57.59999942779541, 21.600000858306885),
 (0.0, 0.0, 1.0)]

3. Saving the lattice to CSV

csv_path = os.path.relpath("data\lattice_14_4.csv")
full_lattice.to_csv(csv_path)  #interior_lattice.to_csv(csv_path)

Credits

__author__ = "Shervin Azadi"
__license__ = "MIT"
__version__ = "1.0"
__url__ = "https://github.com/shervinazadi/spatial_computing_workshops"
__summary__ = "Spatial Computing Design Studio Workshop on Voxelization"

Last update: January 25, 2021