Source-available · Non-commercial — licensed under the PolyForm Noncommercial License 1.0.0.
Provided as is, with no warranty and no liability. Check converted files before relying on them.
Not legal advice; see Licence below.
One portable app that turns things into real STEP solids (true planes, cylinders, spheres and fitted
NURBS, not thousands of triangles), with the mesh converter at its core:
| Tab | What it does |
|---|---|
| Convert | STL / OBJ / PLY / 3MF mesh → STEP solid: planes, cylinders, spheres and NURBS for organic areas. Experimental engines (Staged, v2, Second pass), Guesstimate, and Extrude outline / Loft for flat-profile and tapered parts. |
| Hardpoints | Open a hardpoint STL (an ordinary STL that also remembers which CAD face each triangle came from) and rebuild the solid from its faces instead of guessing them; or turn any plain STL into one. |
| SCAD → STEP | Rebuild an OpenSCAD model as real CAD geometry (true cylinders, spheres, swept surfaces, exact booleans) instead of exporting a mesh and guessing afterwards. Customizer parameters, 3D preview and a live link that re-exports every time you save. |
| Image → STEP | Trace a photo, scan or drawing of a flat part into its outline as real CAD curves (lines, arcs, circles, ellipses, splines; holes found by nesting) and save it as STEP: a solid of the thickness you type, or the flat shape. Scale from a printed scale token (paper or plastic), a marker sheet, a scan's own resolution, or a number. Experimental: every colour change, where each colour area of an icon or logo becomes its own piece. |
| Jetwash | Cleans junk (slivers, 0.0001 mm steps, thin fins, specks, tiny holes/chamfers) out of existing STEP files. |
| Plugins | One-click FreeCAD workbench and Fusion add-in, app-menu entry, right-click entries. |
It runs in your web browser from one portable folder; no Tk, nothing installed on your system. Mac, Windows
and Linux. Page with screenshots: https://The-Dorkknight.github.io/stl2step/
Reporting a problem? The 3D preview window carries a Diagnostic panel: the job's mode, surface fitter,
quality settings and result as a QR code and in plain words. One screenshot of that window says it all; see
Diagnostic code.
Portable and self-contained
Everything stays inside this folder:
STL2STEP/
app/ the program
runtime/ private Python 3.12 + libraries, one subfolder per CPU type
Output/ your results (also offered as a browser download)
- The first start downloads uv (the installer, ~20 MB), Python 3.12 (~30 MB) and the libraries (~500 MB); about 1.5 GB on disk. That takes a few minutes. Later starts are instant.
- It never uses or changes your system Python, Homebrew, conda or anything else. User
settings (
PYTHONPATH, pip/uv config files,~/.localpackages) are ignored. - Nothing is written outside the folder: temporary files go to
runtime/tmp. - Move or copy the folder anywhere — another disk, another Mac, a USB drive — and it keeps working without reinstalling. An Intel Mac and an Apple Silicon Mac can share one folder: each sets up its own runtime subfolder the first time. (USB drives: use an APFS or Mac OS Extended format; exFAT is untested.)
-
Uninstall: delete the folder. Reset: delete
runtime/.
Hardpoints tab: STL files that remember their CAD faces
A hardpoint STL is an ordinary binary STL, same triangles, same file size, same .stl
extension, that also records in its spare bytes which CAD face every triangle came from, what
kind of surface that face is (flat, cylinder, sphere, cone, torus, freeform) and where the CAD corners
are. Slicers and viewers open it as a normal mesh. STL2STEP can skip the guessing and rebuild each
face as the surface it really was. The format is described in HARDPOINT_STL.md.
- Drop an STL and the tab says what it is: a hardpoint STL with valid labels (with its faces, units and tolerance), one whose triangles were edited after labelling (the labels are then ignored), or a plain STL.
- Convert using the labels rebuilds the solid from the faces in the file. Every labelled face is checked against the tolerance before it is trusted; a face that doesn't fit its label goes through the normal detection instead, so a wrong label can cost speed but not correctness.
- Convert ignoring the labels does the same file the normal way, to compare.
- Convert and make a hardpoint STL converts a plain STL and also writes the same mesh back out as a hardpoint STL carrying the faces it found (the triangles are copied byte for byte), so the next conversion of that file is faster and cleaner.
- The FreeCAD and Fusion plug-ins have an Export hardpoint STL command that writes the real CAD faces straight from your model.
On the test knob (a cylinder, a torus blend and a ball) the plain STL gives 1,103 faces (max deviation
0.129 mm) and the hardpoint STL gives 8 faces (0.060 mm). A bracket gives 21 faces plain and 17 with labels.
Command line: python app/stl2step.py hardpoints part.stl shows what a file contains, --no-labels ignores
them, and --save-labelled also writes the hardpoint STL. Labels are only used on the full mesh, not on one that
was reduced first. Tested on four small sample files and nothing else; cones and tori become fitted NURBS
faces, not true cone and torus surfaces.
SCAD → STEP tab: OpenSCAD models as real CAD
Turns an OpenSCAD model (.scad, or a .csg export) into a solid STEP file with true geometry: cubes become
boxes, cylinders true cylinders and cones, spheres true spheres, extrusions and revolutions true swept
surfaces, booleans exact solid booleans. A low $fn on purpose (a $fn=6 nut trap) stays the polygon it is.
hull() and minkowski() of common shapes are built exactly too; text and imported 2D outlines come in as exact
outlines; the rare parts with no exact CAD form (an imported STL, surface()) are rendered by OpenSCAD and joined
in as flat facets. The engine is the SCAD2STEP project, now built into this app.
-
Choose a .scad… (or paste its path, or drop it on the page). Choosing from disk keeps
include/uselibraries next to the file working and lets the live link watch it. -
Parameters: the model's own Customizer variables appear as fields (ranges, drop-downs and
/* [Groups] */are respected), so you can export a variant without editing the file. -
Options: units, which circles stay polygons, where the STEP goes (next to the
.scad, orOutput/), a comparison with OpenSCAD's own render (volume and size), and smooth text outlines. - Convert to STEP. The result opens in the same 3D preview as the Convert tab.
-
Live link: keep editing in OpenSCAD; each time you save (F2) the STEP beside the
.scadis rebuilt within a second or two (including when a library it uses changes).
You need OpenSCAD installed (2021.01 or newer; only 2021.01 was tried) unless you only convert .csg
files. The app looks for it in the usual places (normal install, AppImage in your home, Downloads or Applications
folder, Flatpak, Snap); otherwise enter its location on the tab. OpenSCAD is not bundled and keeps its own licence.
On the example bracket the STEP has 31 faces and its volume is within 0.002 % of OpenSCAD's render.
Command line: python app/stl2step.py scad model.scad -D width=40, --watch for the live link, --no-verify.
Right-click entries (Linux Mint Nemo, GNOME Files, Windows Send to) and FreeCAD / Fusion OpenSCAD → STEP solid commands
come from the Plugins tab.
Image → STEP tab: a photo, scan or drawing as a STEP outline
Drop a picture of a flat part (PNG, JPG, BMP, TIFF, WebP). Its outline is traced into the fewest lines, arcs,
circles, ellipses and splines that fit, outlines inside outlines become holes, and the result is written as STEP in
millimetres. The engine is the ImageToSketch project (a FreeCAD add-in by the same author); the parts of it that
need no FreeCAD are built into app/imagetosketch (this build carries ImageToSketch 0.9.1).
- Picture. A dark part on plain white paper, lit evenly, photographed from above works best. Scans and clean drawings work too (a line drawing is traced along the middle of its lines). The preview shows what will be kept: green becomes geometry, amber is borderline and left out, red is rejected.
-
Scale. The tab looks at the picture and picks what it finds:
- Scale token: a black square (40 mm) with one clipped and one rounded corner. Printed on paper: download the token sheet (PDF, A4 or Letter; a token in two opposite corners), print it at 100 %, measure a square with a ruler and type what you measure, lay the part on the sheet. One token gives the scale; with both in view the camera's tilt is measured across the whole sheet. 3D-printed plastic: download the STL (40 x 40 x 1.2 mm), print it in matt black, lay it on white paper beside the part. Either way a photo taken a little off vertical is straightened.
- Part's top above the token: something nearer the camera looks bigger (a 10 mm part from 300 mm: about 3 %). Type the part's height here and that is taken out. It needs the camera distance, which a phone or camera JPEG carries in its lens data (0.9.1: the lens data now comes first, and a typed distance is only compared with it); for a PNG, a screenshot or an edited photo, type Camera distance. A distance that is only roughly right just scales the outline evenly (from 1 m, 10 % out costs about 1.6 % on a 140 mm tall part); with neither, a phone's main camera is assumed. The side-wall correction is skipped, with a message, when the camera's position is too uncertain. Send photos of tall parts straight from the phone, not through a messenger (it strips the lens data). Part's top above the token, Camera distance and Part has straight vertical sides now sit just above Convert to STEP.
- Marker sheet (four printed markers around the part), the file's own resolution (flatbed scans), the picture's width, millimetres per pixel, or a plain square of known size.
-
STEP. Thickness: 0 writes the flat shape as a face, any other value a solid of that thickness
standing on Z = 0. A STEP file does not have to contain a solid, so there is no need to extrude by a dummy 1 mm
just to be able to save: the file then holds a surface, which you can extrude in your CAD program. Curves
only writes just the lines and arcs with no face; that is valid STEP too, but some programs skip bare curves
when importing (Fusion's STEP import reads faces and solids), so the face is the safer flat form.
Include borderline shapes adds the amber ones the tracer was unsure of. Also save the outline as SVG / DXF
writes the same outline as a millimetre drawing into
Output/beside the STEP, for laser cutters and 2D CAD. - A shape that fills the picture. A logo or icon often runs right to the picture's edge. Shape runs off the picture → work it out continues drawn graphics a little beyond the edge so the whole shape is traced, and leaves photos alone; the other two choices force it either way. (Before 0.5.1 such a shape was left out and only what was inside it was written.)
- Convert to STEP. The result opens in the same 3D preview as the other tabs.
Every colour change (experimental, new in 0.5.2-wip; neighbours meet exactly since 0.7.0-wip)
Normally the part is traced against its background: one outline per part, plus its holes. A picture with
several colours has more edges than that. On an app icon (a grey rounded square, a cube drawn in three shades of
blue, a yellow ring) the ordinary trace outlines the square and the light blob standing in it, and nothing says
where the cube ends and the ring begins, or where one face of the cube meets the next. Set What to trace to
every colour change and:
- every colour area gets its own outline, and in the STEP its own face or solid: the pieces lie side by side like a jigsaw (the icon above: 6 solids, each within 0.1 % of its true area on the test redrawing);
- a smooth blend is not an edge: a gradient, a soft drop shadow or light falling off across a table gives no line;
- neighbours may shade: two faces with a light-to-dark gradient are told apart even where their colours overlap;
- the colour round the picture's edge is the background, and the same colour seen through a hole is a hole;
- Colour difference that counts sets how different two colours must be (left to work it out, it is cautious with noisy photos and JPEGs); Edge shared by two areas only matters for the SVG / DXF copies.
Tracing the ordinary way, a clean picture with three or more flat colours gets a line in the log saying that this
mode exists. It is 2 to 4 times slower than the ordinary trace and works on pictures up to 1600 px a side (larger
ones are reduced first). It has only been tried on pictures drawn by the test code, among them a redrawing of
the icon it was reported with, made from a photograph of a screen: not that icon's file, no real logo, no real
photograph. Known limits: drawn outlines between areas (each area is traced to the inside of the line), the same
colour on both sides of a thin line (one area), greys closer than about 10 levels, pictures under about 96 px,
blur over about 2 px. What was tried and dropped, the numbers and the limits:
docs/research/TRANSITION_TRACING.md.
To try it without printing anything: examples/plate-on-token-sheet-simulated.jpg is a simulated photo (it carries
lens data like a phone photo) of a 90 x 60 x 10 mm plate with a 16 mm bore on the token sheet. Drop it in, type 10
under Part's top above the token and 10 under Thickness.
Command line: python app/stl2step.py image photo.jpg --part-above-token 10 --thickness 10, --markers, --dpi,
--mm-per-px 0.1, --picture-edge edge, --include-borderline, --also-svg, --also-dxf,
--find transitions (with --colour-step, --shared-edges), --make-token-sheet sheet.pdf,
--make-token token.stl (image --help lists the rest).
How far this has been tested: on pictures drawn by the test code and on photographs made by a simulated camera,
where the true sizes are known (plate sides within about 0.2 % with the part's height typed in; without the camera
distance a 10 mm part reads 2 - 4 % large, and the log says so). No token has been printed and no real photo
traced. Lens distortion is not corrected. Details and the accuracy table are in the ImageToSketch repository.
The mesh side already had its own depth setting: in Convert → Extrude outline, Extrude height (0 = the part's
own height; --height on the command line) sets how deep a traced mesh outline is extruded.
Neighbours meet exactly (on by default, new with ImageToSketch 0.9.0): where two colour areas touch, both use
one and the same curve for the edge they share, so the faces or solids fit together with no gap and no overlap. Untick
it (command line --no-weld) to let each area keep its own fit of the edge, as in 0.5.2.
Diagnostic code: one screenshot says what was set and what came out
New in 0.5.2-wip. When a conversion finishes, the 3D preview opens with a Diagnostic panel on its right:
- a QR code that carries the job's settings and result;
- the same in plain words: mode, surface fitter, the quality settings (tolerance, guesstimate, angles, patch size, switches), the performance profile with its time budget and fill allowance, then the result: closed solid or not, geometry check, route taken, face counts, deviation, volume difference, time, and which limits were hit (time budget reached, checkpoint kept, memory tight, faces left as facets ...);
- the code as text with a Copy code button.
Take one screenshot of the preview window and the report is complete: nothing to remember, nothing to copy
from the log. The Diagnostic button in the window's bar hides the panel. A job that failed has no preview,
so its red result box has a Show the diagnostic code button that opens the same panel. A Smooth surfaces or
Exact facets conversion run from the command line prints its code at the end.
Reading one back, from a screenshot (or a phone photo of the screen) or from the code itself:
./stl2step-linux.sh diag screenshot.png
./stl2step-linux.sh diag S2S1-H0C9EZAYQ02GA00-C22W0053RY7KR0000AB186-RT0800Q3G07C000B8004003G00207H013G0Y800G-KFWJ
What is in the code: the app version, the time to the minute (UTC), a tag for the job, the settings and
numbers listed above, and "Linux / Windows / macOS". What is not: the file's name, any path, the log, the
error text, anything else about your computer. The panel shows the file name and an error's text in words and
marks them "(not in the code)". Nothing is sent anywhere: the QR is a picture on the page.
The code follows the conventions of the author's ErrCode project (several records multiplexed into one string,
Crockford base32, the same time stamp and tag) but is its own format, S2S1; it does not contain ErrCode's error
dictionary. It carries the settings of STL → STEP conversions; Jetwash, SCAD and Image jobs get the header and
the result only, and the panel says so. The QR picture needs the small segno package, which the start file adds
on its next start (needs the internet once); without it the words and the code are still shown. Format, sizes and
how far it was tested: docs/research/DIAGNOSTIC_CODE.md. Tested on Linux in a
headless browser only; a real phone photo of a real screen has not been tried.
Front panel, activity LEDs and effort LEDs
The top bar is styled like an 80s/90s PC case. Left to right: tabs, a CPU % display and VU bar, a red DISK LED, a green RUN heartbeat that blinks every second while a job is running (amber if it has been quiet for 45 s), and a 3-position LOCK / NORM / TURBO key switch that is purely decorative for now.
Every setting has two little LED stacks: red = how hard it works your computer, green = quality of the result. Red high + green high means the computer will drag but the output will be as good as it gets. They are rough guides computed from the value, not measurements, and update as you change a setting.
Smooth sketch (optional, in Extrude outline mode)
Extrude outline normally redraws a part's outline as straight segments, so an oval hole becomes dozens of tiny flats. Tick Smooth sketch and each loop is redrawn as the simplest shapes that stay within the outline tolerance: straight lines, true arcs and circles, ellipses, and splines with as few control points as possible. Press Preview outline to see it; red dots mark where two pieces meet. Command line: --mode extrude --smooth-sketch.
On a test plate with rounded corners, a slot, a D-shaped hole, a hex hole, a round hole, an ellipse and a freeform "bean" hole, the result has 25 faces, the same as the original CAD model (94 without Smooth sketch at the automatic tolerance, 319 at 0.02 mm). The ellipse comes back as one true ellipse and the bean as one closed spline (11 control points at the automatic tolerance, 33 at 0.02 mm).
Limits: it only applies to Extrude outline (not Loft, not Smooth surfaces). A loop that can't be fitted within tolerance stays as straight segments, and the log says so. Noisy or scanned outlines come out in more pieces. A very coarse round fillet (steps over 25°) is read as corners. The plug-ins don't offer it yet.
Guesstimate organic areas (optional, off by default)
Tick Guesstimate organic areas (fast) in Settings when the freeform parts of a model only need to be roughly right. Organic tolerance (default 0.3 mm) is how far a freeform surface may sit from the mesh inside a patch. Flat faces, round holes (cylinders), spheres and all edges keep the normal tight tolerance. With it on, dense meshes are first reduced (staying within a third of the normal tolerance, checked, and kept closed) and the slow patch filler is skipped. Command line: --guess or --guess 0.3. Works with the Classic and Staged fitters; the FreeCAD and Fusion plug-ins don't offer it yet.
Measured on a 160,000-triangle organic test model (2-core machine): 41 min → 4.3 min, 107 MB → 28 MB STEP, 40,484 → 9,239 faces, max deviation 0.105 → 0.211 mm. It does not reduce the number of areas left as triangles (513 vs 450 regions); that needs the boundary work planned next. Parts made only of flats and round features come out identical with it on or off.
Performance profiles, GPU, queue and scheduling
Pick a profile in the Performance card (or leave it on Auto, which looks at your cores and RAM):
| Profile | For | What it does |
|---|---|---|
| Potato | old or small laptops (e.g. 8 GB RAM, 4 cores) | 1 thread, low priority, no GPU. Slowest, lightest. |
| Moderate | typical modern laptops | about half the threads, GPU where supported. |
| Extreme | Apple Silicon Macs, workstations | every thread, Classic and v2 run side by side in Second pass, several queued files at once, GPU where supported. |
Command line: --profile potato|moderate|extreme|auto (and --no-gpu).
Graphics card (optional, experimental). OpenCASCADE, which builds faces and writes STEP, is CPU-only, so a GPU cannot speed those parts up. Only the v2 fitter's shape-guess scoring can use a GPU, through an optional GPU pack (PyTorch: Apple Metal or Nvidia CUDA). Click Install GPU pack in the Performance card on a supported machine (about 80 MB on an Apple Silicon Mac, about 2.5 GB for Nvidia CUDA), then restart. After installing, the log says whether the pack can actually see your card; on Nvidia an old graphics driver is the usual reason it can't. Without the pack everything runs on the CPU. The default Classic converter does not use the GPU.
Queue and scheduling. Click Convert more than once (same file with different settings, or other files) and the jobs line up in a Queue card; the profile decides how many run at once. Start next to the Convert button can delay a job: in 1 or 3 hours, tonight at 01:00, or at a time you choose. The app stays open and keeps the computer awake while it waits; if you close the app, scheduled jobs are lost.
Cancel and activity monitor
While a job runs, Cancel stops it (the work is in a separate process that is killed) and resets the tab so you can drop a new file. The header shows a CPU VU bar and a big red DISK LED that lights on disk activity; under the progress bar you see the running time and how long since the last message. Long steps can leave the percentage still for minutes — if the CPU bar is busy, it is working. (STL2STEP uses the CPU only, so there is no GPU meter.)
Big meshes and slower computers
Speed only affects how long a job takes; running out of memory is what can crash it.
Measured peak memory:
| Triangles | Smooth surfaces | Exact facets |
|---|---|---|
| 10,000 | 0.4 GB, 5 s | 0.55 GB, 12 s |
| 40,000 | 0.5 GB, 20 s | 1.0 GB, 1–2 min |
| 160,000 | 0.9 GB, 30 s | 2.2 GB, 9 min |
Reducing big meshes keeps features. "Reduce to N triangles" (and the memory guard below)
first finds flat faces, holes, cylinders, spheres and sharp edges on the full mesh, then
simplifies only inside each region with its outline locked. Flat faces are rebuilt from their
outline alone, round features stay on their exact cylinder/sphere, so a 60-sided hole is
still recognised as one true cylinder afterwards. Example, a 224,000-triangle plate reduced to
22,000: 12 exact faces (0.005 mm), where blind reduction gave 44 fragments and 5 mm of damage.
"Protect memory" (on by default) checks this computer's free RAM before starting and reduces
meshes that wouldn't fit. On an 8 GB laptop that's above ~190,000 triangles in Exact facets
mode or ~775,000 in Smooth surfaces mode. The log says when this happens. While a job
runs, the app works at low priority, so the computer stays usable, and stops it from
idle-sleeping, so an hour-long job isn't interrupted.
Staged engine (experimental, off by default)
Choose Surface fitter → Staged in Settings (or --engine staged) to try roughing first. Before any patch fitting, the whole smooth part of the model is searched for lathe shapes (one revolve axis, a profile spline) and for extruded freeform outlines. Where they fit within tolerance they become single exact faces — a true cylinder, cone or sphere when the profile is straight or circular, otherwise a spline profile revolved or extruded — instead of hundreds of NURBS patches. Everything left over goes through the normal Classic patch fitter. Faces are trimmed directly on their own surface, then the STEP is written, read back, and any face that did not survive is demoted and rebuilt, so the solid stays closed.
It is opt-in because it is new: Classic is still the default and its results are unchanged. Guesstimate works with it too (shapes are found on the full mesh, then the mesh is reduced with those regions locked).
Measured (2-core Linux machine, synthetic test parts, default settings):
| Part | Classic | Staged |
|---|---|---|
| Turned vase | 8,665 faces, 199 s | 14 faces, 12 s |
| Torus | 605 faces, 72 s | 9 faces, 4 s |
| Fine tray (flats, holes, rounded edges) | 1,927 faces, 23 s | 131 faces, 15 s |
| Coarse tray | 635 faces | 119 faces |
| Bracket, sphere, blob | identical | identical |
Max deviation from the mesh was equal or smaller on every one of these. On very dense (about 100,000-triangle) CAD-like test meshes with Guesstimate on, it also finished (vase 191 faces in 38 s, tray 4,080 faces in 3 min, oval-cut plate 1,497 faces in under 2 min, all valid closed solids within 0.14 mm). On a 160,000-triangle organic ghost model with Guesstimate it took 272 s and gave 3,271 faces (Classic with Guesstimate: 262 s, 9,239 faces). Where it is not better: the same ghost at full strict tolerance without Guesstimate took 75 minutes, 4.3 GB of memory and ended as an all-triangle solid (Classic: 41 min, 40,484 faces), and a non-watertight 100,000-triangle plate test did not finish in 25 minutes. So: try it on turned, round or prismatic parts, and add Guesstimate for dense organic scans. Tested on synthetic parts and one organic ghost model only, on a 2-core Linux machine — not yet on a range of real-world parts. Please try it on yours and compare; python tools/bench.py part.stl --engines classic staged prints the same table (faces, share of area as exact shapes, deviation, time, peak memory) for any mesh.
Ladder engine (experimental, off by default)
Settings → Surface fitter → Ladder or --engine ladder. Easy things first: the mesh is looked at for a few
milliseconds (its edge-angle histogram, which flats are bounded by sharp edges, whether the curved area is a
surface of revolution about some axis) and routed as prismatic, lathe, organic or mixed. Exact
shapes are claimed before anything slow runs, searches that cannot succeed are skipped, and problem areas are
guesstimated (freeform patches within the Guesstimate tolerance, 0.3 mm by default) or kept as facets instead
of being refined for minutes. Classic is untouched and stays the default.
| Part (this 2-core Linux machine) | Classic | Ladder |
|---|---|---|
| Dense lathe vase, 24k triangles | 264 s, 8,980 faces | 8.0 s, 14 faces, max 0.025 mm |
| Organic blob, 10k triangles | 17 s, 20 faces, 0.059 mm | 2.4 s, 20 faces, 0.108 mm (guesstimated) |
| Knob | 17 s, 1,103 faces, 0.129 mm | 12 s, 951 faces, 0.129 mm |
| Fine stepped shaft with a cross hole | 23 s, 2,190 facets | 1.8 s, 8 faces, 0.007 mm |
| Block with a 15 mm fillet | 20 planes (the fillet as flats) | 9 faces, the fillet a true cylinder |
| Bracket, plate, tray | same result, same time | |
| Organic figure, 160k triangles (Potato profile) | Classic + Guesstimate: 262 s, 9,239 faces, 0.21 mm | 318 s, 3,271 faces, 0.26 mm, checkpoint written, peak 1.3 GB |
Never ending with nothing. Every performance profile has a time ceiling (Potato 2.5 h, Moderate / Extreme
40 min) after which unfinished areas are kept as exact facets and the file is written; on big meshes a checkpoint
STEP (exact faces, the rest as facets) is written before the slow fitting starts and is kept if the fitter dies,
out of memory included; the slow plate filler is skipped when memory is nearly full; the faceted fallback is
capped at about 20,000 faces so the file stays openable. These apply to Classic too (they only change what happens
to a run that would otherwise go past the ceiling or crash).
Options: --no-ceiling switches the time ceiling and fill allowance off (refine for as long as it takes); --route prismatic|lathe|organic|mixed forces a route; --no-ladder-guess keeps everything at the
tight tolerance (problem areas become facets); --budget 60 turns anything still outside tolerance into facets
once 60 s have passed; --max-fills 10 limits the slow plate filler; --plane-rule length is the flat-border
test the prismatic route uses (usable with Classic too). Tested on 13 synthetic CAD meshes and two synthetic
organic shapes only, on this machine; not on scans, not on real downloads, not on the target laptops. The
reasoning and measurements are in docs/research/.
Research notes (for anyone who wants to dig in)
Why does converting a mesh to STEP take so long and give so many faces? docs/research/
has a plain-English summary with pictures of a research report on exactly that: the slow fallbacks are the real
cost, exact shapes (flats, holes, lathe shapes, extrusions) should be claimed first, and the freeform rest is
better built from four-sided patches that need no trimming. It also lists what is already built into STL2STEP
(the experimental Staged engine), what is not, and the open questions. The full 7,000-word report with every
source link is FULL_REPORT.md. It was written with AI assistance and is not
independently verified; it is there so others can check it, argue with it and build on it. A second round
(October 2026) asked whether cheap machine vision could help (mostly no: use the vision toolbox on the mesh's own
normals and sections, not on pictures), how the techniques combine (one ladder; the saving is in what it skips),
and what "easy things first, guesstimate the rest" costs in accuracy; those three reports are in the same folder
and led to the Ladder engine above. A third round (POTATO.md) covers never crashing on a small computer and finishing within a time ceiling, and a fourth (SLICER.md) asks whether the app could work like a 3D-printing slicer (short answer: Loft and Extrude outline already do; borrow the slicer's rules for where to put layers, not the layers themselves; nothing from it is built yet). Two sets of working notes from building 0.5.2 are there too: TRANSITION_TRACING.md (tracing every colour change of a picture: the first design that was dropped, the one that was built, 29 measured cases) and DIAGNOSTIC_CODE.md (the code in the preview window: format, why packed bits and not JSON, what was tested).
What to expect
- CAD-style parts (flat faces, holes, rounded edges and corners, chamfers): flat faces become true planes; edge rounds and corner balls are split apart and become true cylinders and spheres. Every face is checked (valid, right size, on the mesh) and anything that fails is kept as exact facets, so the result is always a closed solid.
- Organic shapes (sculpts, scans) become smooth fitted patches.
- Organic shapes with many sharp rims or tunnels work but are slow and come out partly faceted. A 160k-triangle test ghost took 30 min and gave a valid, accurate solid with many facets. For those, "Exact facets" mode is quicker if you only need a closed STEP.
- Preview: when a conversion finishes, a 3D preview opens in the app (drag to rotate, scroll to zoom). Blue = flat, green = cylinder/sphere, light grey = smooth NURBS, dark = kept as facets. Original shows the input mesh for comparison.
Experimental options
The default converter is the proven Classic one. These are opt-in:
- Surface fitter → v2: a newer fitter (adaptive NURBS, stricter checks). Better on some CAD parts, worse on others (can give more faces or facets).
- Surface fitter → Staged: roughing first — lathe and extruded shapes become exact faces before patch fitting (see above). Far fewer faces on turned, round or prismatic parts.
- Surface fitter → Second pass: runs Classic, then v2, and keeps whichever came out better — it can only improve on Classic, but takes about twice as long.
-
Extrude outline / Loft cross-sections modes: only for flat-profile or tapered/stepped
parts. On organic shapes they give a striped mess — use Smooth surfaces for those.
Command line:
--engine staged,--engine ladder(with--route,--budget,--max-fills,--no-ladder-guess,--plane-rule),--engine v2,--engine best,--mode extrude,--mode loft.
Command line (optional)
Pass arguments to the launcher, e.g. on Mac/Linux:
./stl2step-linux.sh part.stl # → part.step
./stl2step-linux.sh part.stl out.step --units in --mode faceted
./stl2step-linux.sh wash old.step --threshold 0.05 --coarseness 2
./stl2step-linux.sh plate.stl --mode extrude --axis z # redraw from its outline
./stl2step-linux.sh taper.stl --mode loft --max-slices 10
./stl2step-linux.sh plate.stl --mode extrude --height 5 # the same, extruded 5 mm deep
./stl2step-linux.sh image photo.jpg --part-above-token 10 --thickness 10 # photo on the token sheet → 10 mm solid
./stl2step-linux.sh image scan.png --dpi # flatbed scan → flat STEP face
./stl2step-linux.sh image --make-token-sheet token_sheet.pdf # the sheet to print (--make-token x.stl for plastic)
./stl2step-linux.sh image icon.png --width-mm 50 --thickness 2 --find transitions # EXPERIMENTAL: every colour area its own solid
./stl2step-linux.sh diag screenshot.png # read a diagnostic code back from a screenshot (or: diag CODE)
./stl2step-linux.sh scad model.scad -D width=40 # OpenSCAD model → solid STEP
./stl2step-linux.sh scad model.scad --watch # live link: re-export on every save
./stl2step-linux.sh hardpoints part.stl # what a hardpoint STL contains
./stl2step-linux.sh part.stl --save-labelled # also write a hardpoint STL
./stl2step-linux.sh install files # right-click entries (add --remove to undo)
(On a Mac: bash app/portable.sh …, on Windows: "STL2STEP (Windows).bat" …)
Using it
Convert: drop a mesh, pick the input units (mm / inches / cm / m) and a mode:
- Smooth surfaces: planes, cylinders and spheres become true surfaces and organic areas become fitted NURBS patches. Any patch that can't meet the tolerance stays as exact facets, so the result is still a closed solid.
- Exact facets: every triangle kept, coplanar ones merged. Fast; always matches the mesh.
- Extrude outline (experimental): the part is redrawn instead of rebuilt — its outline along an axis (the whole-part silhouette, or an exact cross-section at a height you pick) is cleaned up and extruded. Perfect for plates, brackets, gaskets and logos: every face is an ideal plane and round holes become true circles. Height defaults to the part's own height.
-
Loft cross-sections (experimental): for tapered or stepped parts. A handful of slices is picked where
the profile actually changes shape (not a dense stack, so no staircase and it stays fast),
and lofted into one smooth solid. Holes are lofted when every slice has the same number.
Preview outline shows what will be traced before you convert.
Extrude symmetric splits the extrude height both ways around the cross-section (or the part's middle), and
Slice heights lets you choose the loft slices yourself instead of picking them automatically.
(These two modes come from the earlier stand-alone outline-tracing STL2STEP, now built in. Command line:
--symmetric,--heights 2,10,30; in Python:profile2d.convert_stl_to_step(...).)
Hardpoints, SCAD → STEP and Image → STEP are described above.
Jetwash: drop a STEP (or an STL, which is converted first), or click
"Use last converted STEP". Threshold is the size below which something counts as junk
(0.01–0.05 mm for cut-extrude debris). Coarseness: 1 gentle, 2 normal, 3 aggressive
(also removes holes, fillets and chamfers smaller than the threshold).
Each removal is checked and undone if it would damage the part.
FreeCAD and Fusion plugins
Easiest: start STL2STEP, open the Plugins tab and click Install FreeCAD plugin
(or Install Fusion add-in). It finds every FreeCAD on the computer (normal install,
AppImage, Flatpak, Snap, 1.0 and 1.1 settings folders), copies the workbench in and tells
it where this folder is. Restart FreeCAD and pick STL2STEP from the workbench list.
(It won't appear in FreeCAD's Addon Manager — that only lists add-ons it downloaded itself.)
Linux: Add STL2STEP to the app menu makes it start like any other app.
Add right-click entries puts Convert to STEP (for meshes and OpenSCAD models) and Live-link (for a .scad) in
Linux Mint's Nemo, GNOME Files' Scripts menu or Windows' Send to menu (install files, undo with install files --remove).
Command line: ./stl2step-linux.sh install (or install freecad, install fusion, install menu, install files).
Linux: the app opened FreeCAD instead of a browser? Some programs claim web links.
STL2STEP now skips those and opens Firefox/Chrome/Chromium; the address is also printed in
the terminal window if you want to paste it yourself.
Manual install, if you prefer:
The plugins folder has a FreeCAD workbench and a Fusion add-in (Fusion's free Personal
Use licence runs add-ins too). They are thin front ends: they send the mesh to this
STL2STEP folder, it does the conversion in the background, and the solid comes back into
your model. Double-click the STL2STEP start file once first so its setup is done; the
plugins won't download anything themselves. They look for this folder in your home
folder, Applications, Desktop, Documents and Downloads, and ask where it is if it isn't
there. Results are also saved in Output/.
FreeCAD (0.20 or newer)
- Copy
plugins/FreeCAD/STL2STEPinto FreeCAD'sModfolder:- Linux:
~/.local/share/FreeCAD/Mod/(for FreeCAD 1.0+ AppImage/Flatpak the same path usually works; in FreeCAD,Macro → Macros…shows the user folder, andModsits next to it) - macOS:
~/Library/Application Support/FreeCAD/Mod/ - Windows:
%APPDATA%\FreeCAD\Mod\
- Linux:
- Restart FreeCAD and pick the STL2STEP workbench.
-
Mesh → STEP solid: converts the selected mesh object(s). With nothing selected it
asks for mesh files. The solid is added as
<name>_solidand the mesh is hidden. -
OpenSCAD → STEP solid: pick a
.scad/.csg; it is rebuilt as real geometry and added as a solid. -
Jetwash (clean STEP): cleans the selected solid(s), or STEP files you pick. Result:
<name>_clean. - Export hardpoint STL: saves the selected solid(s) as a hardpoint STL (done inside FreeCAD, no STL2STEP folder needed).
- STL2STEP folder…: choose where STL2STEP is. Progress shows in a dialog with Cancel; the full log is in View → Panels → Report view.
-
Mesh → STEP solid: converts the selected mesh object(s). With nothing selected it
asks for mesh files. The solid is added as
Fusion
- Copy
plugins/Fusion/STL2STEPsomewhere permanent (e.g. next to this folder). - In Fusion: Utilities → Add-Ins (or Shift+S) → Add-Ins tab → the + → choose that
STL2STEPfolder → select it → Run. Tick Run on Startup to keep it. - The buttons are under Utilities → Add-Ins:
- Mesh → STEP solid: select mesh bodies (or choose a mesh file), set options, OK. The STEP is imported into the same component and the mesh is hidden.
-
OpenSCAD → STEP solid: choose a
.scad/.csg; the solid is imported. - Jetwash STEP: choose a STEP file (defaults to the last converted one); the cleaned result is imported.
- Export hardpoint STL: select solid bodies and save them as a hardpoint STL. Fusion works in cm internally; the add-in converts to mm for you.
Screenshots
![]() Convert tab |
![]() Settings and log |
![]() Jetwash tab |
![]() Plugins tab (one-click FreeCAD / Fusion install) |
![]() First-start notice |
![]() Experimental Staged fitter |
![]() Hardpoints tab |
![]() SCAD → STEP tab |
![]() Image → STEP tab |
![]() A traced plate as a solid |
![]() Image → STEP: every colour change (experimental) |
![]() ... as six solids |
![]() Diagnostic panel: settings and result as QR and words |
Where the pieces came from
This app was built up from five earlier builds, all by the same author with AI assistance (Claude, from Anthropic): the
mesh converter at its core, the stand-alone outline-tracing tool (its Extrude and Loft modes live on as Extrude outline and
Loft cross-sections), the hardpoint STL work (the Hardpoints tab, the plug-in Export hardpoint STL commands and
HARDPOINT_STL.md), SCAD2STEP (the SCAD → STEP tab; app/scad2step_core.py is a copy of its engine) and ImageToSketch (the Image → STEP
tab; app/imagetosketch is a copy of its tracing library, refreshed with tools/sync_imagetosketch.py).






















Top comments (0)