Mesh2Param is an evidence-first mesh-to-CAD reconstruction workspace. It preserves an uploaded STL, OBJ, or PLY mesh, analyzes its geometry, and follows one of three honest conversion paths: an editable parametric CADGraph, a tolerance-controlled curved B-Rep, or a source-bound faceted STEP fallback. Every claimed STEP solid is exported through Open CASCADE, independently reimported, and checked again before the UI presents it as valid.
Mesh reconstruction is an inverse problem. Mesh2Param can recover supported geometry and build a new editable model, but it cannot guarantee the source designer's original sketches, constraints, dimensions, or feature order.
Mesh2Param is beta software. Unsupported or ambiguous geometry fails with diagnostics; it is not silently replaced by a plausible-looking model.
| Path | Result | Current supported scope | Validation meaning |
|---|---|---|---|
| Parametric inference | Editable CADGraph and analytic OCCT B-Rep | Straight extrusions with matched planar caps and closed line/arc/circle profiles, including profile holes; bounded spline-profile spanners may also recover a regular-polygon cut, constant-radius rim fillets, and qualifying shallow cap details | Kernel-valid, STEP-reimport-valid, and compared with the source mesh; functional detail suppression is the default, while full additive-detail recovery is opt-in |
| Native curved reconstruction | Approximate B-spline/analytic surface-network B-Rep | Bounded plate-like STL topology with one or two freeform top regions, sharp or user-declared smooth joins, recognized cylindrical holes, and supported spherical, conical, or toroidal protrusions | Measured source deviation, continuity evidence, B-Rep checks, STEP round trip, surface inventory, and structural STEP audit |
| Browser-local reconstruction | Analytic, mixed, or faceted B-Rep from the Rust reconstruction core compiled to WebAssembly | Any STL, 3MF, OBJ, or PLY mesh within the triangle budget; the core reports the tier it reached rather than being forced to one | Kernel validity, STEP round trip through the kernel's own reader, surface inventory, and measured deviation from the source mesh |
| Faceted fallback | Non-parametric STEP with one planar face per preserved triangle | Source-bound STL with unchanged project units and scale factor 1 |
B-Rep and STEP reimport are proven; geometric tolerance remains unmeasured, so validation is intentionally partial |
| CADGraph rebuild | Deterministic exact B-Rep for the supplied parameters | Trusted CADGraph documents and their hash-bound artifacts | Feature-by-feature compilation, kernel validation, STEP export, and STEP reimport |
“Exact” describes the B-Rep produced from a CADGraph's explicit parameters. It does not mean that an inferred model is the unique or original interpretation of a triangle mesh. “Approximate curved” means genuine analytic or B-spline STEP surfaces fitted to mesh evidence within reported tolerances—not visually smoothed triangles.
The CADGraph compiler currently supports extrusion, pocket, hole, counterbore, countersink, revolution, linear and circular patterns, mirror, chamfer, fillet, imported faceted bodies, and content-addressed reconstructed surface networks.
- General arbitrary-topology STL-to-parametric-CAD recovery is not implemented.
- OBJ and PLY are supported for ingestion and analysis; the source-bound curved and faceted conversion modes currently require STL.
- Freeform curved reconstruction is intentionally limited to qualified plate-like topologies. Open, non-manifold, self-intersecting, detached, over-budget, or unsupported analytic/freeform joins fail closed.
- Curvature-space sub-segmentation for fillet-band evidence exists behind an opt-in setting and is disabled by default. It currently refines analysis evidence only; it is not yet routed into reconstruction or STEP generation.
- The faceted fallback proves that OCCT produced and reimported a solid. It does not claim recovered features, curved faces, or a measured source-to-result deviation.
See fallbacks and limitations and the curved reconstruction implementation record for the detailed failure boundaries and acceptance gates.
The current web app uses a canvas-first workflow:
- Open an STL, OBJ, PLY, saved
.mesh2param.jsonproject, or bundled sample. - Confirm project units and scale, then analyze mesh health and surface evidence.
- Inspect patches in the real 3D viewport. Patch controls can lock, hide, reclassify, merge, or override a detected crease where the server can prove the requested edit.
- Follow the guided conversion action. Supported geometry uses parametric reconstruction; otherwise the app offers approximate curved STEP first and a clearly labeled faceted fallback.
- Inspect the ordered feature tree and detail diagnostics. Compare Source, Result, overlay, and residual/suppressed views, use movable section planes and distance/angle/radius measurements, then download STEP, GLB, STL, or OBJ or save the working project.
Projects, versions, jobs, display preferences, and artifact descriptors survive reloads. Browser mode uses IndexedDB as its local authority; server mode mirrors the workspace while enforcing revision preconditions. A saved project preserves metadata and manifests, but stale artifact URLs are never treated as live geometry after import.
flowchart TD
UI["React canvas workspace"] --> MODE{"Execution profile"}
MODE -->|"Browser-local"| IDB["IndexedDB projects and artifacts"]
IDB --> BW["Dedicated Web Worker"]
BW --> WASM["Mesh2Param core (WebAssembly)"]
MODE -->|"Native / self-hosted"| API["FastAPI + typed HTTP/SSE"]
API --> DB["SQLite/WAL projects, versions, and jobs"]
API --> CAS["SHA-256 filesystem CAS"]
DB --> GW["Spawn-isolated geometry worker"]
GW --> ENG["Mesh2Param engine"]
ENG --> OCCT["CadQuery + native OCCT"]
WASM --> OUT["CADGraph, STEP, GLB/STL/OBJ, and evidence"]
OCCT --> OUT
CADGraph—not generated Python—is the authoritative executable geometry model. Generated CadQuery source is an inspectable export and is never executed from an upload. Read architecture, CADGraph, and the API reference for the deeper contracts.
- Python
>=3.12,<3.13 - Node.js
22.22.0or newer - pnpm
11.7.0(the repository-pinned version) - Rust through rustup;
rust-toolchain.tomlpins1.96.0and the WebAssembly target - wasm-pack
0.15.0for the browser reconstruction core - uv
- Optional: Docker with Compose v2 for the production topology
- Optional: Playwright browser binaries for end-to-end tests
No login, paid conversion API, runtime CDN, or cloud account is required for local development.
Clone the public repository, then install dependencies and build the browser reconstruction core:
git clone https://github.com/esaueng/Mesh2Param.git
cd Mesh2Param
pnpm install --frozen-lockfile
XDG_CACHE_HOME=.cache uv sync --frozen --extra dev
cargo install --locked wasm-pack --version 0.15.0
pnpm build:packages
pnpm db:migrate
pnpm devOpen http://127.0.0.1:5173. The native API runs at http://127.0.0.1:8000.
Useful readiness endpoints:
http://127.0.0.1:8000/health process liveness
http://127.0.0.1:8000/ready database, storage, and geometry-supervisor readiness
http://127.0.0.1:8000/docs self-hosted API endpoint index
http://127.0.0.1:8000/openapi.json OpenAPI document
pnpm dev starts Vite and the FastAPI service together. Development defaults to the embedded local
geometry supervisor and stores data under .mesh2param-data/.
Choose Try the L-bracket sample on the landing screen, then use the Source, Result, and Compare display modes to inspect its validated reference artifacts. The generated sample corpus is ground truth produced from trusted CADGraphs; it demonstrates the workspace and compiler, not a claim that every sample's original feature tree can be inferred from its STL.
The CLI uses the same ingestion, reconstruction, compiler, comparison, and validation modules as the native API:
pnpm mesh2param -- analyze source.stl --units mm --output artifacts/
pnpm mesh2param -- repair source.stl --units mm --output artifacts/
pnpm mesh2param -- segment source.stl --units mm --output artifacts/
pnpm mesh2param -- reconstruct source.stl --units mm --output artifacts/
pnpm mesh2param -- rebuild model.cadgraph.json --output artifacts/
pnpm mesh2param -- compare source.stl model.step --units mm --output artifacts/
pnpm mesh2param -- validate model.step --units mm --output artifacts/
pnpm mesh2param -- samples list
pnpm mesh2param -- samples generate --sample l-bracket-with-holes
pnpm mesh2param -- serveThe reconstruct CLI runs bounded parametric inference. Approximate curved and faceted modes are
currently exposed through the web workspace and POST /api/projects/{id}/reconstruct:
{"settings":{"detailMode":"full"}}detailMode: "full" is an opt-in native-service setting that converts qualifying bounded shallow
cap loops into additive extrusion features. Omitting it preserves the default functional mode,
which declares and masks qualifying details without changing the preserved source mesh.
{"settings":{"mode":"curved","fitTolerance":0.25,"surfaceDeviationTolerance":0.3,"forceSplit":false}}{"settings":{"mode":"faceted","sewingTolerance":0.05}}Tolerances are expressed in project units and are physically capped. These source-bound modes also
require unchanged units and a source scale factor of 1; normalize a working copy explicitly
instead of silently changing units.
| Command | Purpose |
|---|---|
pnpm dev |
Start the native API/embedded geometry supervisor and Vite app |
pnpm build |
Build contracts, shared UI, the production web app, and Python distributions |
pnpm typecheck |
Run strict TypeScript checks and mypy |
pnpm lint |
Check generated-contract drift, ESLint, and Ruff |
pnpm test:frontend |
Run contract, shared-UI, and web unit tests |
pnpm test:api |
Run the API-focused Python tests |
pnpm test:backend |
Run the complete Python test suite |
pnpm test:geometry |
Run the exact sixteen-step geometry acceptance case |
pnpm test:e2e |
Run the native primary-workflow Playwright test |
pnpm cf:test |
Run browser-local Cloudflare integration tests against pnpm cf:dev |
pnpm samples:check |
Verify the committed procedural corpus in the pinned image (Docker required) |
pnpm curved:fixtures |
Regenerate the curved ground-truth benchmark fixtures |
pnpm curved:baseline |
Measure the faceted baseline for the curved corpus |
pnpm general:fixtures |
Regenerate the general-parametric spanner fixtures |
pnpm acceptance |
Run the scripted acceptance report |
pnpm licenses:check |
Verify dependency license policy and notices |
pnpm verify |
Run the full delivery gate, including tests, samples, build, browser acceptance, and licenses |
pnpm samples:check keeps every non-STEP artifact byte-exact. A changed STEP
serialization is accepted only when both manifests and metadata remain
self-consistent, the semantic sample record is unchanged, both files pass live
OCCT validation and reimport, topology and surface classes match, and a
scale-aware symmetric-difference check proves the solids geometrically
equivalent. Accepted serialization drift is reported explicitly.
Generated contracts begin in packages/contracts/schema/cadgraph.schema.json. Do not hand-edit a
generated TypeScript or Python contract without updating the schema and generator inputs.
Validation is a chain, not a UI label:
CADGraph/schema checks -> deterministic OCCT build -> BRepCheck -> STEP export
-> independent STEP reimport -> solid/topology/surface checks -> source comparison
A close mesh does not rescue an invalid B-Rep, and a valid B-Rep does not imply that geometric tolerance passed without comparison evidence. Curved runs additionally retain fit residuals, surface types, UV/continuity evidence, shared-edge checks, deterministic artifact hashes, and a pure-Python structural audit of the STEP Part 21 file. See validation.
Depending on the conversion path, an artifact set can include:
model.cadgraph.json model.cq.py model.step
source.glb repaired.glb analysis-proxy.glb
patches.glb reconstructed.glb reconstructed.stl
reconstructed.obj residual.glb
analysis.json metrics.json validation.json
suppressed-regions.json detail-regions.json candidates.json
curved-plate.json manifest.json mesh2param-export.zip
project.mesh2param.json
Artifact sets are immutable and content-addressed. Manifests bind project, version, source hash, units, settings, dependency versions, validation evidence, byte sizes, and SHA-256 hashes.
project.mesh2param.json is the versioned working-project interchange format. It can contain
project metadata, source descriptors or bounded embedded source bytes, CADGraph, analysis and
repair state, versions, validation, artifact descriptors, and restore-relevant UI state. Imports
validate the extension, schema, source size, bounds, and SHA-256 before hydration. See the
project-file specification.
cp .env.example .env
docker compose config
docker compose up --buildThe production topology is a same-origin Nginx web proxy, one FastAPI process, and exactly one
external geometry worker sharing an absolute data volume. The worker runs without network access.
The default web address is http://127.0.0.1:8080.
The application reads explicit MESH2PARAM_* process variables; it does not auto-load dotenv
files. .env is a Docker Compose interpolation profile only. Review
deployment before changing hosts, origins, resource bounds, or persistence.
pnpm cf:check
pnpm cf:deployCloudflare serves the built SPA and the reconstruction core's WebAssembly module as Workers Static
Assets. With MESH2PARAM_API_ORIGIN empty, bundled samples, local projects, and the browser
conversion path remain self-contained in the browser: the core segments the mesh, fits surfaces,
builds and validates a solid, and writes STEP without uploading the source. It reports the tier it
reached — analytic, mixed, or faceted — rather than claiming a recovered design history, and it
cannot rebuild a project from a CADGraph, which needs the service. See
browser-local reconstruction for its exact scope and gates. Set
MESH2PARAM_API_ORIGIN to the
public HTTPS origin of a separately hosted FastAPI/native-OCCT service to proxy /api, /health,
/ready, /docs, and /openapi.json for native reconstruction.
For a browser-local Worker deployment, monitor GET /health: it returns 200 with
executionMode: "browser-local" when the deployed static application is serving correctly. GET /ready is intentionally reserved for the optional native API and returns 503 until
MESH2PARAM_API_ORIGIN is configured. When that origin is configured, both routes proxy the native
service; use /ready to check its database, storage, and geometry-worker capacity. See
deployment for the full production and self-hosting
configuration.
Uploads and generated geometry are untrusted. Mesh2Param uses bounded stream parsing, structural
allowlists, randomized private staging, no-follow content-addressed storage, explicit job and
geometry budgets, a static trusted worker-operation map, process isolation, and production egress
denial. Project mutations use If-Match: "rev-N"; stale writes fail instead of overwriting newer
state.
The native service supports an optional shared MESH2PARAM_API_TOKEN bearer token; local
development defaults to unauthenticated loopback access. Do not expose the native service directly
to an untrusted network; use a trusted TLS/authentication boundary and configure exact hosts and origins.
Read the security model and vulnerability reporting policy.
apps/web/ React, Three.js, IndexedDB, and browser-local core-wasm workspace
cloudflare/ Worker proxy and static-assets entry point
engine/mesh2param/ Ingestion, segmentation, inference, B-Rep compilation, and validation
packages/contracts/ CADGraph schema plus generated Python and TypeScript contracts
packages/ui/ Shared UI primitives and design tokens
services/api/ FastAPI, SQLite repository, CAS storage, jobs, and worker supervision
samples/ Deterministic parametric and curved reconstruction fixtures
scripts/ Corpus generation, baselines, acceptance, security, and license tooling
tests/ Engine, API, infrastructure, and browser coverage
docs/ Architecture, formats, deployment, security, research, and design notes
- Architecture
- API
- CADGraph
- Validation
- Project-file format
- Curved STEP reconstruction
- General parametric reconstruction plan
- Freeform reconstruction research
- Fallbacks and limitations
- Deployment
- Security
- Sample corpora
- Contributing
Bug reports and pull requests are welcome. Read CONTRIBUTING.md for setup, validation, and geometry requirements. For bugs, open an issue with reproduction steps, the version or commit, and expected versus actual behavior. Attach only models you have permission to share publicly.
Report suspected vulnerabilities through private vulnerability reporting, following SECURITY.md, rather than a public issue.
Mesh2Param's original source is Apache-2.0; see LICENSE and NOTICE. Native OCCT
libraries remain LGPL-2.1 with the Open CASCADE exception, and the transitive CasADi dependency is
LGPL-3.0-or-later. Canonical texts, source references, override rationale, and the installed
dependency inventory are in THIRD_PARTY_NOTICES.md and
licenses/.
The owner-supplied CAD models and mesh exports marked Apache-2.0 (repository) are also
released under Apache-2.0. Third-party samples retain their individual licenses and attribution;
see sample licensing and the
real-world corpus inventory.
GET /healthz returns HTTP 200 with JSON status: "ok" and a service name.
HEAD /healthz returns the same headers without a body; other methods return
405 with Allow: GET, HEAD. Responses use Cache-Control: no-store.
This endpoint requires no application credentials and performs no storage or
upstream requests. It reports Worker liveness, not dependency readiness or
browser geometry/solver health. Existing health endpoints keep their behavior.
Cloudflare Access, WAF, and bot challenges run before the Worker. If a monitor
receives a login redirect or challenge, configure a narrowly scoped exception
for GET/HEAD on the exact /healthz path and the intended app hostname, then
verify the JSON response from the monitor's network. Repository changes alone
do not alter those dashboard policies.