Turn the geometric Makeability Lab logo (SVG) into a 3D-printable STL, with independent extrusion heights per region.
The "ML" mark is a tessellation of right triangles on a 72-unit grid — 16 form the L, 12 form the M wings, and 4 are black accent cutouts. This tool reads those triangles from the SVG and extrudes each into a prism at a height you control per region, including optional "semi-random" jitter. Because the triangles share edges and a common base plane, a slicer fuses them into a single printable object.
The geometry is exact and grid-aligned, so a small parametric script gives precise, reproducible height control that's tedious to reproduce by hand in a GUI — and it doubles as a teaching example of generative/parametric design. The core has no third-party dependencies: it parses the SVG with the standard library and writes a binary STL by hand.
The relief is a guaranteed three-tier layout — cutouts (low) < faceted M field < L (top) — with two printability guarantees:
- the L stands at least
--l-saliencemm above the entire M field, so it always reads clearly; and - no two edge-adjacent M triangles share a height (neighbors differ by at
least
--min-stepmm), so every internal seam shows.
Both come from the same idea: triangles meet edge-to-edge on an exact grid, so
neighbors are found exactly (shared edge = two shared vertices). The M field is
assigned discrete height levels by greedy graph-coloring (seeded-random within
the constraint, so it stays "semi-random"); the L and cutouts are intentional
flat plateaus. A verification pass re-checks every seam and prints the result
under -v.
# (optional) isolate, though the core needs no third-party packages
python3 -m venv .venv && source .venv/bin/activate
# generate stl/makeability-logo.stl with the defaults
python3 logo_to_stl.py svg/makeability-logo.svg -vOpen the resulting STL in any slicer (PrusaSlicer, Cura, Bambu Studio, OrcaSlicer).
python3 logo_to_stl.py SVG [-o OUT] [--width-mm W] [--seed N] [--base-mm T] [-v]
[--min-step S] [--m-height H] [--m-jitter J]
[--black-height H] [--l-salience S]
| Flag | Default | Meaning |
|---|---|---|
svg |
— | input SVG (positional) |
-o, --output |
stl/<name>.stl |
output STL path |
--width-mm |
130 |
overall width in mm (scales x and y uniformly) |
--seed |
42 |
RNG seed for the level assignment (reproducible) |
--base-mm |
0 |
optional solid floor under the whole model |
--min-step |
1.0 |
min height difference between adjacent M triangles |
--m-height |
6 |
center height of the M field |
--m-jitter |
2.5 |
half-range of the M field around --m-height |
--black-height |
2.5 |
cutout plateau height (the low tier) |
--l-salience |
2.0 |
how far the L plateau clears the tallest M |
-v, --verbose |
off | print levels, L plateau, and neighbor-step checks |
Examples:
# bolder steps and a more prominent L
python3 logo_to_stl.py svg/makeability-logo.svg --min-step 1.5 --l-salience 3 -v
# 100 mm wide on a 1.5 mm base plate
python3 logo_to_stl.py svg/makeability-logo.svg --width-mm 100 --base-mm 1.5Each triangle's region is read from the id of its nearest ancestor <g>:
- id contains
Black→ cutouts - id starts with
L_→ L - id contains
M_Inner_Fills→ M
Other groups (outlines, construction helpers, duplicate color layers) and all
<line>/<polyline>/<path> elements are ignored. See the module docstring in
logo_to_stl.py for the full list of input assumptions.
The colored artwork uses ~11 pastels + black — more than the four AMS slots on a
single AMS unit — so the pastels are bucketed into three hue families + black
(see SLOT_PALETTE in logo_to_stl_color.py; edit it to match your loaded filaments).
Pass a colored SVG as the color source; geometry still comes from the first SVG, and fills are matched to triangles by coordinate:
Color lives in a separate script, logo_to_stl_color.py, which reuses the
same geometry, height model, and STL writer (so the relief is identical) and adds
only the palette/slot logic:
python3 logo_to_stl_color.py svg/makeability-logo.svg \
--colors svg/makeability-logo-color.svg -vThis writes one STL per slot, all sharing the same origin:
stl/makeability-logo.slot1-yellow-green.stl
stl/makeability-logo.slot2-pink-orange.stl
stl/makeability-logo.slot3-blue-purple.stl
stl/makeability-logo.slot4-black.stl
By default the L-center and the cutouts both go to slot 4 (black), giving the
"colorful M, dark L" look. Use --l-slot N (on the color script) to move the L (e.g. to a light
filament so it reads as negative space — you'd repurpose one pastel slot for it).
In Bambu Studio (X1 Carbon + AMS): import all four STLs at once; when asked, load them as parts of a single object (they line up exactly because they share an origin). Then assign each part an AMS filament via the object/part list. It slices as one multi-color print — no manual swaps. (The face-painting tool is the other route, but it's tedious for 32 precise triangles, so prefer the per-part method.) Filaments won't match these exact hexes; pick the nearest loaded colors.
- Output prints as one piece: triangles share edges and a z=0 base, so the slicer
unions them. The mesh is not strictly watertight (prisms meet at coincident
internal walls), which slicers handle fine. If you need a pristine single
manifold (e.g. for STEP export or strict repair tools), run a boolean union in
trimesh/Blender — seerequirements-dev.txt. - Defaults give a 130 × 87 × 8 mm model. Adjust
--width-mmfor your bed/use.
- Wordmark text. The
svg/makeability-logo-with-text.svgfile contains the "Makeability Lab" text as<path>outlines. Those are font curves with interior holes, which need bezier flattening + hole-aware triangulation — a different problem from the grid triangles, and finicky to print at logo scale. The mark is extruded today; text is intentionally out of scope for v1. A clean future approach: parse the paths into polygons-with-holes and extrude them as one flat layer viatrimesh.creation.extrude_polygon. - Optional STEP/3MF export.
logo-to-stl/
├── logo_to_stl.py # single-color tool (stdlib only)
├── logo_to_stl_color.py # multi-color AMS export (imports the core)
├── requirements.txt # runtime deps (none) — notes only
├── requirements-dev.txt # optional: trimesh for validation/preview
├── svg/
│ ├── makeability-logo.svg # the ML mark (geometry source)
│ ├── makeability-logo-with-text.svg # mark + wordmark paths
│ └── makeability-logo-color.svg # per-triangle fills (color source)
├── stl/ # generated output (a few samples committed)
├── LICENSE
└── README.md
MIT — see LICENSE.