Skip to content

Instantly share code, notes, and snippets.

@ex-nerd
Last active December 21, 2018 07:14
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 ex-nerd/2413d8e6f876b3857bde552f61235071 to your computer and use it in GitHub Desktop.
Save ex-nerd/2413d8e6f876b3857bde552f61235071 to your computer and use it in GitHub Desktop.
Automatic rendering script for Russian Doll Maze Puzzle Box
#!/usr/bin/env python3
#
# Automatic rendering script for Russian Doll Maze Puzzle Box
# https://www.thingiverse.com/thing:2410748
#
# This file is licensed under: https://creativecommons.org/licenses/by/3.0/
# Source for file is at: https://gist.github.com/ex-nerd/2413d8e6f876b3857bde552f61235071
# Number of nested mazes to generate (you will also get
num_mazes = 3
# Height in mm of inner maze
height = 75
# Additional mm spacing above inner maze when it's inserted into the next largest
padding = 5
# Diameter in mm of inner maze tube
diameter = 25
# Number of processor threads to use (probably don't touch this)
NUM_THREADS = 3
#################################################################################
# Don't touch below this line
import os
import platform
import requests
import subprocess
from concurrent.futures import ThreadPoolExecutor, as_completed
def openscad():
try:
if OPENSCAD_PATH:
return OPENSCAD_PATH
except NameError:
pass
if os.getenv("OPENSCAD_PATH"):
return os.getenv("OPENSCAD_PATH")
if platform.system() == "Darwin":
return "/Applications/OpenSCAD.app/Contents/MacOS/OpenSCAD"
if platform.system() == "Windows":
# Note: Windows allows forward slashes now
return '"C:/Program Files/OpenSCAD/openscad"'
# Default to linux-friendly CLI program name
return "openscad"
def get_and_render(url, fname):
response = requests.get(url, stream=True)
response.raise_for_status()
with open(f"{fname}.scad", "wb") as scad:
for chunk in response.iter_content(1024):
scad.write(chunk)
scad_file = f"{fname}.scad"
stl_file = f"{fname}.stl"
cmd = [openscad(), "-o", stl_file, scad_file]
# print(cmd)
subprocess.run(cmd)
return stl_file
def generate(num, height, diameter, padding):
with ThreadPoolExecutor(max_workers=NUM_THREADS) as pool:
futures = []
for i in range(1, num + 1):
ni = "i" * (i - 1)
no = "o" * (num - i)
# The parts on the end of the URL are firstly whole numbers that are
# the inside height, inside diameter, and extra height on the inner
# box (in mm).
# Then letters, where "i" means there is a box inside this one, and
# "o" means there is a box outside this one. More "i"s mean mean more
# boxes inside and the overall size is increased accordingly.
# The set of 4 parts is designed around a rolled up £20 note. So
# 15mm wide and 75mm high but with 5mm space to allow the £20 to
# stick out and be accessible when the boxes are finally open.
url = f"http://e.gg/puzzlebox.cgi/{height}/{diameter}/{padding}/{ni}{no}"
fname = f"nested_labyrinth_{i}-of-{num}_{height}h_{diameter}d_{padding}p_{ni}{no}"
print(f"Queueing {i} of {num}")
futures.append(pool.submit(get_and_render, url, fname))
# get_and_render(url, fname)
print("Rendering...")
for future in as_completed(futures):
stl_file = future.result()
print(f"Finished: {stl_file}")
print("Done.")
if __name__ == "__main__":
generate(num_mazes, height, diameter, padding)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment