Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
# Python wrapper around 'openscad' for rendering STL/PNG files from SCAD files.
import abc
import concurrent.futures
import dataclasses
import functools
import itertools
import pathlib
import subprocess
from typing import Optional, Any, Union
@dataclasses.dataclass
class Preset(abc.ABC):
src: Union[str, pathlib.Path]
name: str = "preset"
overrides: Optional[dict[str, Any]] = None
target_dir: pathlib.Path = pathlib.Path("target")
def render(self) -> list[str]:
filename = self._get_target_filename()
print(f"Exporting {filename}...")
self.target_dir.mkdir(exist_ok=True)
overrides = []
if self.overrides is not None:
for key, value in self.overrides.items():
overrides.append("-D")
if isinstance(value, str):
overrides.append(f'{key}="{value}"')
elif isinstance(value, bool):
bool_str = "true" if value else "false"
overrides.append(f'{key}={bool_str}')
else:
overrides.append(f"{key}={value}")
command = ["openscad",
"-o",
str(self.target_dir / filename),
*overrides,
*self.extra_render_args(),
"--quiet",
str(self.src)]
subprocess.run(command)
@abc.abstractmethod
def _get_target_filename(self) -> str:
raise NotImplementedError
def extra_render_args(self) -> list[str]:
return []
@dataclasses.dataclass
class StlPreset(Preset):
def _get_target_filename(self) -> str:
return f"{self.name}.stl"
@dataclasses.dataclass
class PngPreset(Preset):
camera_translate: tuple[float, float, float] = (0, 0, 0)
camera_rotate: tuple[float, float, float] = (55, 0, 25)
camera_distance: float = 140
camera_projection: str = "p"
height: int = 600
width: int = 600
def _get_target_filename(self) -> str:
return f"{self.name}.png"
def extra_render_args(self) -> list[str]:
cam_floats = [*self.camera_translate, *self.camera_rotate, self.camera_distance]
camera_settings = ",".join([str(f) for f in cam_floats])
return ["--camera",
camera_settings,
"--imgsize",
f"{self.width},{self.height}"]
def render_parallel(presets: list[Preset]) -> None:
with concurrent.futures.ThreadPoolExecutor() as executor:
_ = [executor.submit(Preset.render, preset) for preset in presets]
dc437037dThis file is pinned to the selected release. Download the original to open it in your design tool.