Indicatrix GitHub
Desktop application

The studio & faceting CAD

indicatrix-cut — a Slint desktop application: design library, live spectral viewport, and a constraint-based faceting editor.

STATUS

The faceting CAD is in beta. Solving now runs on a background solve service with real mid-solve cancellation and a progress-tracked activity list rather than freezing the editor, new designs are guided by a template gallery and an in-app worked example, and results carry stale badges the moment they no longer match the current design — but the editor's interaction model is still evolving, and results should be checked against a conventional CAD before cutting. The design library and 3D viewport (sections 1–4 below) are more stable than the editor itself and the rough planner (sections 5–8).

1Overview

apps/indicatrix-cut is built with Slint. It combines a design-library browser, a live 3D spectral viewport, and the faceting CAD engine in one window.

Studio main window: library and viewport
Fig. 1 — Design library on the left, live spectral viewport on the right.

2The design library

Designs are stored in a local SQLite database (indicatrix-vault) by default — no account, no telemetry — though the library view can also switch to browsing the remote coordinator's catalogue over the network instead. Filterable by shape, index-gear tooth count, refractive-index range, length/width ratio, and facet count. The shape filter is populated partly by automatic classification: girdle facet count and length/width ratio identify a confident round, triangle, square, hexagon, or octagon outline; elongated shapes such as oval, cushion, and emerald are not auto-detected and keep whatever label the source data or a manual edit gives them. Import brings in single .asc files or entire folders; the original file is preserved alongside the parsed schedule.

The Library menu holds the whole-library actions. Regenerate All Preview Images..., Regenerate All Tilt Curves... and Regenerate Both... rebuild the cached preview thumbnails and tilt curves for every design in the library; each one opens a confirmation step first and is greyed out only while such a batch is already running. (The filter panel has a matching pair of buttons that regenerate just the filtered set.) Plan Rough... opens the Rough planner (section 7), which draws its candidate designs from this library.

3The 3D viewport

The viewport switches between a fast solid preview and the full spectral path tracer. Orbit, pan, and zoom with the mouse; the progressive path tracer accumulates samples while the camera is still and resets on any camera or material change. Seven lighting presets — an analytic studio rig in four moods, an ISO hemisphere, a jewellery light tent and a daylight sky (see the physics page) — plus an optional grey or white backdrop card behind the stone, and custom HDR equirectangular environment maps, are all supported, along with live readouts of brilliance, fire, scintillation, windowing, and extinction as the stone is orbited. If the optional GPU compute path loses its device mid-session, the viewport re-acquires it once and retries the same frame; if that also fails it falls back to the CPU tracer for the rest of the session with a visible status message, rather than freezing.

4Tilt performance sweeps

Tilt performance curve graph
Fig. 2 — Brilliance, windowing, and extinction across a tilt sweep.

A cut that looks brilliant face-up can black out or window heavily at a few degrees of tilt. Indicatrix sweeps a 181-point tilt profile (±90°) at each of 4 fixed camera azimuths — 0°, 45°, 90°, 135° (PROFILE_AZIMUTHS_DEG, crates/indicatrix/src/color/metrics.rs) — and plots brilliance, windowing, and extinction together so a design's behaviour in the hand, not just face-up, is visible.

A tilt sweep can also be exported as a video: pick one of the four camera azimuths as the sweep axis, a step from 0.01° up to 5° between frames (MIN_STEP_DEG/MAX_STEP_DEG, apps/indicatrix-cut/src/gui/tilt/video_export/params.rs), and a resolution from 128 × 128 up to 8K (7680 × 4320), or a custom size clamped to the same 128–8192 px range per axis. An optional performance overlay burns the brilliance/windowing/extinction readout into each frame in a layout that adapts to the chosen width. Every frame renders through the same local CPU/GPU/hybrid setting and configured remote coordinator as a still-image export — not a separate, CPU-only tracer — including the same Transfer choice while a remote is configured: Full data merges the remote's samples with the local lanes, Final picture only has the coordinator send one finished PNG per frame while the local lanes stay idle. The live viewport pauses for the whole video's duration exactly as it does during a still-image export, and never shares the app's single GPU adapter with it while it runs. The numbered PNG sequence is then muxed into an H.264 MP4 with ffmpeg when it is found on PATH, an animated GIF via the image crate when it is not, or, failing both, left as a PNG sequence with a README.txt explaining how to mux it by hand.

5Constraint solver and tier editor beta

Faceting tier editor
Fig. 3 — Editing tier angles and meet constraints.
Faceting diagram with resolved meet points
Fig. 4 — The faceting diagram after the meet-point solver runs.

Cutting instructions are a geometric constraint graph, not a static list of numbers. A meet-point instruction ("cut tier P2 until it meets P1 and G1 at a single point") specifies a facet's depth implicitly; the solver in crates/indicatrix/src/geometry/meet_solver resolves that depth by intersecting the facet plane with its neighbours' already-known vertices, walking the schedule in dependency order so that changing one tier's angle recomputes every tier that depends on it. Where a design has no .asc file to anchor against, the solver can instead anchor a block against the design's own printed C/W/P/W proportions (meet_solver/anchors.rs).

Solving runs on a background solve service (one persistent worker thread with last-wins request coalescing and real mid-solve cancellation) once a design is large enough that solving stops being instantaneous; the Solve/Deep Solve/Optimize buttons relabel to a running state with an Abandon/Cancel action, and a status-strip activity list shows every long-running operation — background solve, Deep Solve, Optimize, Retarget, a tilt curve or video export — with elapsed time and, where the operation can measure one, a progress fraction. Editing the design while a solve is in flight discards the stale result rather than applying it over a newer edit, and every analysis result the editor keeps on screen (Retarget's proposal, a tier's manufacturability warnings, the tilt curve cache) carries a stale badge the instant an edit invalidates it, cleared only by re-running that analysis.

A pavilion tier's row shows a colour-coded critical-angle margin bar next to its angle field, live as you type, and the first time (per session) a design has no anchor tier, a one-time explainer card walks through why the solver needs one before you hit the "no anchor" status message cold. New designs start from an empty-state card offering the New Design dialog's template gallery or an in-app guided worked example. New Design always opens a design: even the Empty template leaves a zero-tier design with its preform in the viewport, a "no tiers yet" hint and an + Add Tier button. The worked example (Help → Guide: New Design Walkthrough) walks you through building a simple round-brilliant-style stone yourself, tier by tier — it does not build the stone for you. Each step lists its actions as numbered lines with the exact values to type, outlines the control it is about, and moves on by itself once its goal is reached — the tier exists with the right name, angle and indices, the material is applied, the design solves to a closed stone — whichever route got there (the tier form, a quick-add button, an inline edit, Undo/Redo, or auto-solve); a status chip reads "Waiting for: …" until then. Skip step moves on without the goal, Back returns to the previous step, and the two reading steps wait for Next. Controls the current step does not use are locked — dimmed, with a tooltip saying so, keyboard shortcuts included — until the guide is closed. The guide panel sits beside the tier table on a wide Edit layout and floats at the window's right edge everywhere else, where it can be dragged out of the way; either way it collapses to a small "Guide · Step N of M" pill (apps/indicatrix-cut/docs/manual/07-new-design-worked-example.md). A full keyboard-shortcut overlay is one press of ? away (or Help → Keyboard Shortcuts) whenever no text field has focus.

6Preforms and the angle optimizer beta

indicatrix-cut-core's preform module models the rough gem material as a rectangular block or a round/oval cylinder. Its yield_metrics module reports volumetric yield, an estimated carat weight from the material's specific gravity, and flags a design whose facets cut outside the stated rough. The optimize module runs a coordinate-search optimizer over free facet angles, holding pinned tiers (such as the girdle) fixed and rejecting any candidate that breaks closed polyhedral geometry or introduces a new manufacturability warning.

Manufacturability checks (manufacturability/) run against every edit: vanishing facets that fail to form a real face, facets too small to cut reliably, index-gear quantization error, and meets referencing a tier that has not been cut yet.

A tier's constraint can also be authored as a real-world target rather than a dimensionless mast: cut to a stated depth in millimetres, or bisect the tier's mast until the design's measured girdle thickness or table width lands on a stated millimetre figure (TierTarget::DepthMm/GirdleThicknessMm/ TableWidthMm, indicatrix-cut-core/src/design/targets.rs). Every tier also keeps a stable id (tier_id) that survives reordering, duplication, and a Save Native/reopen round trip through the native .indicatrix.toml sidecar, so a manufacturability warning or an authored target keeps pointing at the same tier across edits rather than a table row position.

7Rough planner beta

Library → Plan Rough... answers a question the preform's single-design yield figure cannot: given a block of rough and the designs in the library, what is the heaviest set of stones that can be sawn out of it? You enter the block's X, Y and Z in millimetres, a Stones (up to) limit from 1 to 99 (a maximum, not a target: a layout may cut fewer), and a material. Only materials with a known specific gravity are offered, because the specific gravity turns volume into carats. The planner returns up to 10 layouts, heaviest first.

The candidate designs are either the designs the library's search and filters currently show, or the whole library. The loss settings default to 0.30 mm saw kerf, 0.20 mm allowance per side of each stone, 0 mm rough skin and a 1.00 mm minimum stone width, and can be edited in the dialog. Each result row shows the total weight in carats, the yield (finished stone volume as a share of the block's volume), the stone count, and the designs used — one design repeated, or a mix.

Each layout also carries a cut plan written as sawing instructions: the block is cut into slabs, each slab into bars, each bar into pieces, with the kerf lost at every cut, and each piece names the design cut from it, which rough face its table faces, and the finished size and weight. Cuts run edge to edge across the whole part, and the planner tries all 6 orders of the three axes. A design's finished size (footprint, height and volume) is measured once by solving its facets, then stored in the library database, so only the first run over a large library is slow; the measurement is repeated automatically when a design's geometry changes. Designs without a usable design file — catalogue entries known only by an angle table, or schedules that rely on the preform to close the stone — are skipped and counted in the results.

READ THE NUMBERS AS AN ESTIMATE

The results are an upper bound for a clean block. The planner assumes rectangular rough without inclusions or cracks and stones that come out exactly to their design's proportions, and it fits each stone to the smallest rectangle around it, so a round stone is treated as needing a square footprint. It works with the local library only; if a remote catalogue is selected, the dialog asks you to switch back. Use the ranking to compare options, and do the final marking-up on the rough itself.

Sources: crates/indicatrix-cut-core/src/rough_plan/, apps/indicatrix-cut/src/gui/rough_plan/, and the manual chapter apps/indicatrix-cut/docs/manual/15-planning-a-rough.md. Fitting a design into scanned, irregular rough is a separate item on the roadmap.

8Solid inspection view

Solid inspection view with facet picking
Fig. 5 — Solid inspection: click a facet to jump to its row in the schedule.

A secondary 3D view shows the exact polyhedral solid (facet edges and vertices, not a tessellated approximation). Clicking a facet selects its row in the cutting-schedule table.

9Export

Cutting instructions table
Fig. 6 — The cutting instructions table: index, angle, mast per facet.

A split button in the command bar groups the master-still render export with two further File-menu exports built from the same solved schedule: Export Cutting Sheet (HTML), a self-contained printable page with an embedded crown/pavilion/profile diagram and one row per tier (sequence, name, angle, indices, solved mast, meet instruction, and any cheater/azimuth offset), and Export Diagram (PNG), the same facet drawing alone at print quality. Where a real girdle diameter is set, the cutting sheet also prints each facet's cutting depth in millimetres and its unsigned angle of elevation for a machine's dial, alongside the dimensionless mast.

Max resolution
8192 × 8192 px (MAX_EXPORT_DIM)
Max samples
32 768 per pixel (MAX_EXPORT_SPP)
Max bounces
128 (MAX_EXPORT_BOUNCES)
Colour spaces
sRGB, Display P3, Rec. 2020 (Display P3/Rec. 2020 exports embed an ICC profile so they aren't misread as sRGB)
File formats
Read and write: GemCAD .asc, native .indicatrix.toml sidecar, 8-bit PNG renders. Read, import and open: .gem (GemCAD's binary save format, geometry decoded) and .gcs (Gem Cut Studio), both converted to .asc cutting instructions. Write, experimental: .gcs

Constants from apps/indicatrix-cut/src/bridge/export_thread/params.rs.