Last active
May 12, 2024 18:55
-
-
Save bryanhanson/fb4206132c41c96bf192f6a686d42daa to your computer and use it in GitHub Desktop.
Tetrahedral Decomposition
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Following https://micronote.tech/2020/12/Generating-STL-Models-with-Python/ | |
# | |
# Remember Python indexes starting at 0! | |
# Coordinates derived from R script tetrahedral_decomp.R | |
# The .stl file created contains one unit of the 4 from a tetrahedral decomposition (they | |
# are all identical of course). Dimensions default to mm, so the object is about 1.3 mm | |
# in its longest dimension. For 3D printing we scaled by 2500% to get an object about | |
# an inch tall, which is a good size. | |
import numpy as np | |
from stl import mesh | |
vertices = np.array([ | |
[0.0, 0.0, 0.0], | |
[1.0, 1.0, 1.0], | |
[1.0, 0.0, 0.0], | |
[0.0, 1.0, 0.0], | |
[0.0, 0.0, 1.0], | |
[0.333, 0.333, -0.333], | |
[0.333, -0.333, 0.333], | |
[-0.333, 0.333, 0.333], | |
]) | |
faces = np.array([ | |
[4, 1, 7], | |
[7, 1, 3], | |
[4, 6, 1], | |
[6, 2, 1], | |
[6, 0, 5], | |
[6, 5, 2], | |
[0, 7, 3], | |
[0, 3, 5], | |
[4, 7, 0], | |
[4, 0, 6], | |
[1, 2, 5], | |
[1, 5, 3], | |
]) | |
shape = mesh.Mesh(np.zeros(faces.shape[0], dtype=mesh.Mesh.dtype)) | |
for i, f in enumerate(faces): | |
for j in range(3): | |
shape.vectors[i][j] = vertices[f[j], :] | |
shape.save("tetra_decomp.stl") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Decomposition of a Tetrahedron | |
# Bryan Hanson, May 2024 | |
# Inspired by https://twitter.com/dreugeniacheng/status/1787725859605942480 | |
library("rgl") | |
# corners of tetrahedron inscribed inside of a cube centered on 0, 0, 0 in Cartesian coordinates | |
verts <- data.frame( | |
x = c(1, 1, -1, -1), | |
y = c(1, -1, 1, -1), | |
z = c(1, -1, -1, 1)) | |
rownames(verts) <- c("A", "B", "C", "D") # label the vertices | |
# need center of each face (ABC, ABD, ACD, BCD) | |
abc <- colMeans(verts[c("A", "B", "C"),]) | |
abd <- colMeans(verts[c("A", "B", "D"),]) | |
acd <- colMeans(verts[c("A", "C", "D"),]) | |
bcd <- colMeans(verts[c("B", "C", "D"),]) | |
# need mid-point of each edge (6 edges total, no unique order exists) | |
edges <- data.frame( | |
x = c(1, 1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1), | |
y = c(1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1), | |
z = c(1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1)) | |
rownames(edges) <- c("A1", "B1", "B2", "C1", "C2", "D1", | |
"D2", "A2", "C3", "A3", "B3", "D3") | |
# need mid-point of AB, BC, CD, DA, CA, BD (pairs of rows in edges data frame) | |
ab <- colMeans(edges[1:2, ]) | |
bc <- colMeans(edges[3:4, ]) | |
cd <- colMeans(edges[5:6, ]) | |
da <- colMeans(edges[7:8, ]) | |
ca <- colMeans(edges[9:10, ]) | |
bd <- colMeans(edges[11:12, ]) | |
# plot it; no attempt at polishing the color scheme(s) | |
points3d(verts, size = 15, point_antialias = TRUE) # vertices | |
points3d(abc, size = 15, point_antialias = TRUE, col = "red") # face centers | |
points3d(abd, size = 15, point_antialias = TRUE, col = "red") | |
points3d(acd, size = 15, point_antialias = TRUE, col = "red") | |
points3d(bcd, size = 15, point_antialias = TRUE, col = "red") | |
segments3d(edges$x, edges$y, edges$z, line_antialias = TRUE, col = "blue", lwd = 4) # edges | |
points3d(ab, size = 15, point_antialias = TRUE, col = "green") # edge mid-points | |
points3d(bc, size = 15, point_antialias = TRUE, col = "green") | |
points3d(cd, size = 15, point_antialias = TRUE, col = "green") | |
points3d(da, size = 15, point_antialias = TRUE, col = "green") | |
points3d(ca, size = 15, point_antialias = TRUE, col = "green") | |
points3d(bd, size = 15, point_antialias = TRUE, col = "green") | |
points3d(c(0, 0, 0), size = 15, point_antialias = TRUE) # the center | |
# add the vertices of one piece | |
points3d(c(0, 0, 0), size = 20, point_antialias = TRUE, col = "orange") # the center | |
points3d(verts[1,], size = 20, point_antialias = TRUE, col = "orange") # vertex A | |
points3d(ab, size = 20, point_antialias = TRUE, col = "orange") # mid-point ab | |
points3d(ca, size = 20, point_antialias = TRUE, col = "orange") # mid-point ca | |
points3d(da, size = 20, point_antialias = TRUE, col = "orange") # mid-point da | |
points3d(abc, size = 20, point_antialias = TRUE, col = "orange") # face center abc | |
points3d(abd, size = 20, point_antialias = TRUE, col = "orange") # face center abd | |
points3d(acd, size = 20, point_antialias = TRUE, col = "orange") # face center acd | |
# coordinates of a single piece | |
piece <- rbind(c(0, 0, 0), verts[1, ], ab, ca, da, abc, abd, acd) | |
rownames(piece) <- 1:8 | |
# new plot (close any open rgl windows) | |
# show the piece vertices marked inside the tetrahedron | |
points3d(verts, size = 15, point_antialias = TRUE) # vertices | |
points3d(abc, size = 15, point_antialias = TRUE) # face centers | |
points3d(abd, size = 15, point_antialias = TRUE) | |
points3d(acd, size = 15, point_antialias = TRUE) | |
points3d(bcd, size = 15, point_antialias = TRUE) | |
segments3d(edges$x, edges$y, edges$z, line_antialias = TRUE, col = "blue", lwd = 4) # edges | |
points3d(ab, size = 15, point_antialias = TRUE, col = "red") # edge mid-points | |
points3d(bc, size = 15, point_antialias = TRUE, col = "red") | |
points3d(cd, size = 15, point_antialias = TRUE, col = "red") | |
points3d(da, size = 15, point_antialias = TRUE, col = "red") | |
points3d(ca, size = 15, point_antialias = TRUE, col = "red") | |
points3d(bd, size = 15, point_antialias = TRUE, col = "red") | |
points3d(piece, size = 20, point_antialias = TRUE, col = "green") | |
text3d(piece, texts = as.character(1:8), cex = 5) # label for working out the stl details | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Use
tetrahedral_decomposition.R
to generate coordinates, and then usetetra_decomp.py
to generate the.stl
file.