Skip to content

Instantly share code, notes, and snippets.

@AndreVallestero
Last active August 24, 2025 03:46
Show Gist options
  • Select an option

  • Save AndreVallestero/ead6b0b09e9e3277c868f1ca841168d0 to your computer and use it in GitHub Desktop.

Select an option

Save AndreVallestero/ead6b0b09e9e3277c868f1ca841168d0 to your computer and use it in GitHub Desktop.
Rohmbic Dodecahedron Cross Section
"""
This creates an animation of generating a rhombic dodecahedron point by point.
It works by generating each layer based on a the current z-height, and the
target hexagon edge length. This is a precursor to the g-code infill version of
the same geometry, used for 3d printing to maximize isometric specific strength
(most strength in all directions for the lowest weight)
"""
import math
import time
import pygame
DEG_TO_RAD = math.pi / 180
SQRT3 = 3**0.5
size = 720 #720
def main():
z = 240
pygame.init()
screen = pygame.display.set_mode([size, size])
running = True
while running:
#time.sleep(0.2)
screen.fill((255, 255, 255))
layer_points = get_layer_points(z, 64)
for i in range(1, len(layer_points)):
if pygame.QUIT in (event.type for event in pygame.event.get()):
running = False
break
pygame.draw.line(screen, pygame.Color("black"), layer_points[i-1], layer_points[i])
#time.sleep(0.1)
pygame.display.flip()
time.sleep(0.033)
z += 1
pygame.quit()
# raw_z: raw z height
# l: hexagon edge length
def get_layer_points(raw_z: float, l: float):
z = (raw_z / l) % 4.5 # normalize it from 1 to 4.5, which is relative to l
permutation = 0 # perm0 is upright triangles, perm1 is upside down triangles
phase_x_offset = 0
phase_y_offset = 0
w = l * SQRT3 # width of hexagon
if z < 1: # phase 1 hex hold
tri_frac = 0
elif z < 1.25: # phase 2 transition
tri_frac = (z - 1) * 4
elif z < 1.5: # phase 3 perm1 reverse transition
tri_frac = (1.5 - z) * 4
permutation = 1
phase_y_offset = l / 2
elif z < 2.5: # phase 4 perm1 hex hold
tri_frac = 0
permutation = 1
phase_y_offset = l / 2
elif z < 2.75: # phase 5 perm0 transition
tri_frac = (z - 2.5) * 4
permutation = 0
phase_y_offset = l / 2
phase_x_offset = -w / 2
elif z < 3: # phase 6 perm1 reverse transition
tri_frac = (3 - z) * 4
permutation = 1
phase_y_offset = l
phase_x_offset = -w / 2
elif z < 4: # phase 7 hold
tri_frac = 0
permutation = 1
phase_y_offset = l
phase_x_offset = -w / 2
elif z < 4.25: # perm 0 transition
tri_frac = (z-4) * 4
phase_y_offset = l
elif z < 4.5: # perm 1 reverse transition
tri_frac = (4.5-z) * 4
phase_y_offset = 0
permutation = 1
phase_x_offset = -w / 2
pattern_h = l * 1.5
tri_w = w * tri_frac # width of triangle
tri_half_w = tri_w / 2
layer_points = []
num_rows = 2 + math.ceil(size / pattern_h)
num_cols = 2 + math.ceil(size / w)
for i in range(num_rows):
row_offset = (i-1) * (l + l / 2) + phase_y_offset
if permutation == 0:
if i % 2 == 0:
for j in range(num_cols):
col_offset = j * w + phase_x_offset
top_left_tri_origin = (col_offset - w / 2, row_offset - l/2) # left hex top center
layer_points.append((top_left_tri_origin[0] + tri_half_w, top_left_tri_origin[1] + tri_half_w / SQRT3)) # top left tri right
layer_points.append((col_offset, row_offset)) # hex top left
left_tri_origin = (col_offset, row_offset + l) # hex bottom left
layer_points.append((left_tri_origin[0], left_tri_origin[1] - tri_w * SQRT3 / 3)) # left tri top
layer_points.append((left_tri_origin[0] - tri_half_w, left_tri_origin[1] + tri_half_w / SQRT3)) # left tri left
if j == num_cols - 1: break
layer_points.append((left_tri_origin[0] + tri_half_w, left_tri_origin[1] + tri_half_w / SQRT3)) # left tri right
layer_points.append((left_tri_origin[0], left_tri_origin[1] - tri_w * SQRT3 / 3)) # left tri top
layer_points.append((col_offset, row_offset)) # hex top left
top_tri_origin = (col_offset + w / 2, row_offset - l/2) # hex top center
layer_points.append((top_tri_origin[0] - tri_half_w, top_tri_origin[1] + tri_half_w / SQRT3)) # top tri left
else:
for j in range(num_cols - 1, -1, -1):
col_offset = j * w - w / 2 + phase_x_offset
layer_points.append((col_offset, row_offset)) # hex top right
right_tri_origin = (col_offset, row_offset + l) # hex bottom right
layer_points.append((right_tri_origin[0], right_tri_origin[1] - tri_w * SQRT3 / 3)) # right tri top
layer_points.append((right_tri_origin[0] + tri_half_w, right_tri_origin[1] + tri_half_w / SQRT3)) # right tri right
if j == 0: break
layer_points.append((right_tri_origin[0] - tri_half_w, right_tri_origin[1] + tri_half_w / SQRT3)) # right tri left
layer_points.append((right_tri_origin[0], right_tri_origin[1] - tri_w * SQRT3 / 3)) # right tri top
layer_points.append((col_offset, row_offset)) # hex top right
top_tri_origin = (col_offset - w / 2, row_offset - l/2) # hex top center
layer_points.append((top_tri_origin[0] + tri_half_w, top_tri_origin[1] + tri_half_w / SQRT3)) # top tri right
layer_points.append((top_tri_origin[0] - tri_half_w, top_tri_origin[1] + tri_half_w / SQRT3)) # top tri left
else:
if i % 2 == 0:
for j in range(num_cols):
col_offset = j * w - w / 2 + phase_x_offset
left_tri_origin = (col_offset, row_offset) # hex top left
layer_points.append((left_tri_origin[0] + tri_half_w, left_tri_origin[1] - tri_half_w / SQRT3)) # left tri right
layer_points.append((left_tri_origin[0], left_tri_origin[1] + tri_w * SQRT3 / 3)) # left tri bot
layer_points.append((col_offset, row_offset + l)) # hex bottom left
bot_tri_origin = (col_offset + w / 2, row_offset+ 3*l/2) # hex bottom center
layer_points.append((bot_tri_origin[0] - tri_half_w, bot_tri_origin[1] - tri_half_w / SQRT3)) # bot tri left
if j == num_cols - 1: break
layer_points.append((bot_tri_origin[0] + tri_half_w, bot_tri_origin[1] - tri_half_w / SQRT3)) # bot tri right
layer_points.append((col_offset + w, row_offset + l)) # hex bottom right
right_tri_origin = (col_offset + w, row_offset) # hex top right
layer_points.append((right_tri_origin[0], right_tri_origin[1] + tri_w * SQRT3 / 3)) # right tri bot
layer_points.append((right_tri_origin[0] - tri_half_w, right_tri_origin[1] - tri_half_w / SQRT3)) # right tri left
else:
for j in range(num_cols - 1, -1, -1):
col_offset = j * w + phase_x_offset
right_tri_origin = (col_offset, row_offset) # hex top right
layer_points.append((right_tri_origin[0] - tri_half_w, right_tri_origin[1] - tri_half_w / SQRT3)) # right tri left
layer_points.append((right_tri_origin[0], right_tri_origin[1] + tri_w * SQRT3 / 3)) # right tri bot
layer_points.append((col_offset, row_offset + l)) # hex bottom right
bot_tri_origin = (col_offset - w / 2, row_offset + 3*l/2) # hex bottom center
layer_points.append((bot_tri_origin[0] + tri_half_w, bot_tri_origin[1] - tri_half_w / SQRT3)) # bot tri right
if j == 0: break
layer_points.append((bot_tri_origin[0] - tri_half_w, bot_tri_origin[1] - tri_half_w / SQRT3)) # bot tri left
layer_points.append((col_offset - w, row_offset + l)) # hex bottom left
left_tri_origin = (col_offset - w, row_offset) # hex top left
layer_points.append((left_tri_origin[0], left_tri_origin[1] + tri_w * SQRT3 / 3)) # left tri bot
layer_points.append((left_tri_origin[0] + tri_half_w, left_tri_origin[1] - tri_half_w / SQRT3)) # left tri right
return layer_points
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment