Skip to content

Instantly share code, notes, and snippets.

@bramp
Last active July 2, 2023 18:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bramp/ad9e0cf6781bf9e20454dd2e07be82bd to your computer and use it in GitHub Desktop.
Save bramp/ad9e0cf6781bf9e20454dd2e07be82bd to your computer and use it in GitHub Desktop.
Creates a model of a 3D Hilbert curve, suitable for 3D printing.
#!/usr/bin/env python3
# Creates a model of a 3D Hilbert curve, suitable for 3D printing.
# by Andrew Brampton (bramp.net) 2023
# See https://www.printables.com/model/518431
#
# Usage:
# python3 make.py 4 4 4 --voxelizer voxelmap --spacing 3
# python3 make.py 4 4 4 --voxelizer trimesh --spacing 2
#
from gilbert import gilbert3d
import numpy as np
import argparse
def vxmVoxel(array):
"""Uses MarchingMesh and tends to create diamond shaped tunneled."""
import voxelmap as vxm
model = vxm.Model()
model.array = array
print('Display as a voxel')
#model.draw(wireframe=True, background_color='#3e404e',window_size=[1024,1024])
print('Convert to mesh')
model.MarchingMesh(method="lewiner")
model.MeshView(wireframe=True,alpha=1,background_color='#b064fd',viewport=[1024,1024])
def trimeshVoxel(array):
"""Uses as_boxes and creates square shaped tunneled."""
from trimesh import voxel as v
voxels = v.VoxelGrid(array)
print('Convert to mesh (saved as trimesh.obj)')
boxes = voxels.as_boxes()
boxes.export("trimesh.obj")
boxes.show()
#voxels.marching_cubes.show()
def cmp(a, b):
return (a > b) - (a < b)
def line(a, start, end, value):
"""Very quick and dirty 3D line drawing in steps of 1"""
while start != end:
a[start] = value
start = (
start[0] - cmp(start[0], end[0]),
start[1] - cmp(start[1], end[1]),
start[2] - cmp(start[2], end[2])
)
a[start] = value
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('width', type=int)
parser.add_argument('height', type=int)
parser.add_argument('depth', type=int)
parser.add_argument('--margin', default=1, type=int)
parser.add_argument('--spacing', default=3, type=int)
parser.add_argument('--voxelizer', choices=["voxelmap", "trimesh"], default="voxelmap")
args = parser.parse_args()
array = np.zeros((
args.width * args.spacing + 2*args.margin,
args.height * args.spacing + 2*args.margin,
args.depth * args.spacing + 2*args.margin,
))
last = None
for x, y, z in gilbert3d.gilbert3d(args.width, args.height, args.depth):
cur = (
x * args.spacing + args.margin,
y * args.spacing + args.margin,
z * args.spacing + args.margin,
)
if last != None:
# Draw line from las to cur
line(array, last, cur, 1)
last = cur
if args.voxelizer == "voxelmap":
vxmVoxel(array)
elif args.voxelizer == "trimesh":
trimeshVoxel(array)
else:
print("unknown voxel engine")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment