/** * STLExporter — Manufacturing-grade SurfaceMesh → STL serializer. * * Replaces the test-grade `buildSTL` in STLParser.ts, which writes zero normals. * This exporter computes correct unit face normals from vertex winding (right-hand rule). * * ## STL Binary Format (ISO/ASTM 52915 / de-facto standard) * * 80-byte ASCII header (caller-supplied or default constant) * uint32 LE — triangle count N * N × 50 bytes per triangle: * float32 LE × 3 — unit face normal (nx, ny, nz) * float32 LE × 3 — vertex 0 (x0, y0, z0) * float32 LE × 3 — vertex 1 * float32 LE × 3 — vertex 2 * uint16 LE — attribute byte count (always 0 here) * * ## Normal Computation * * Given vertices A, B, C in winding order: * edge1 = B − A * edge2 = C − A * raw = edge1 × edge2 (cross product, right-hand rule) * normal = raw / |raw| (unit vector) * * For degenerate triangles (|raw| = 0), the STL spec does not forbid zero * normals; we write (0, 0, 0) rather than NaN to remain spec-safe. * * ## Units * * HoloScript geometry is unit-agnostic. STL consumers (slicers, CAM tools) * conventionally interpret coordinates as millimeters. Use the `scale` option * to convert from your working units to millimeters on write — e.g. if your * scene is in metres, pass `scale: 1000`. * * Vault rule G.GOLD.485: physical assumptions are config, never hardcoded. * No unit conversion is applied without an explicit `scale` value. * * @see SurfaceMesh (AutoMesher.ts) — shared mesh contract * @see parseSTL (import/STLParser.ts) — round-trip parser */ import type { SurfaceMesh } from '../AutoMesher'; /** * Options for binary STL export. */ export interface STLBinaryOptions { /** * Text to write into the 80-byte header field. * Truncated to 79 characters + null if longer; zero-padded if shorter. * Default: a constant identifying string (no wall-clock timestamps). */ header?: string; /** * Coordinate scale factor applied to all vertex positions on write. * Does NOT affect normals (direction vectors are scale-invariant). * * STL consumers conventionally expect millimeters. If your scene uses * metres, pass `scale: 1000`. If already in millimeters, omit or pass 1. * Default: 1 (no scaling). */ scale?: number; } /** * Options for ASCII STL export. */ export interface STLAsciiOptions { /** * Solid name written on the `solid` / `endsolid` lines. * Default: 'HoloScriptMesh'. */ name?: string; /** * Coordinate scale factor — same semantics as STLBinaryOptions.scale. * Default: 1 (no scaling). */ scale?: number; /** * Number of decimal places for floating-point output. * Default: 6. */ precision?: number; } /** * Export a SurfaceMesh to a binary STL ArrayBuffer. * * Format: little-endian, 80-byte header + uint32 count + N × 50-byte records. * Normals are computed from vertex winding (right-hand rule); the zero-normal * degenerate fallback is used when a triangle has zero area. * * @param mesh Shared SurfaceMesh (vertices: Float64Array|Float32Array, triangles: Uint32Array) * @param opts Optional header text and coordinate scale factor * @returns ArrayBuffer containing a valid binary STL file * * @example * const buf = exportSTLBinary(myMesh, { scale: 1000 }); // metres → millimetres * fs.writeFileSync('part.stl', Buffer.from(buf)); */ export declare function exportSTLBinary(mesh: SurfaceMesh, opts?: STLBinaryOptions): ArrayBuffer; /** * Export a SurfaceMesh to an ASCII STL string. * * Format: 'solid ' / 'endsolid ', with one facet block per triangle. * Normals are computed the same way as exportSTLBinary. * * @param mesh Shared SurfaceMesh * @param opts Optional solid name, scale factor, and decimal precision * @returns ASCII STL string * * @example * const stl = exportSTLAscii(myMesh, { name: 'bracket', precision: 8 }); * fs.writeFileSync('part.stl', stl); */ export declare function exportSTLAscii(mesh: SurfaceMesh, opts?: STLAsciiOptions): string; //# sourceMappingURL=STLExporter.d.ts.map