Last active
December 21, 2018 07:14
-
-
Save ex-nerd/2413d8e6f876b3857bde552f61235071 to your computer and use it in GitHub Desktop.
Automatic rendering script for Russian Doll Maze Puzzle Box
This file contains hidden or 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
#!/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