Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Output Formats

All exports derive from the internal Vec<Polyline> representation. Each serializer is a pure function in the mujou-export crate (core layer, no I/O).

For a device-compatibility view of which tables accept which formats, see File Formats by Device.

Theta-Rho (.thr)

For Sisyphus tables, Oasis Mini, and DIY polar sand tables.

Format Specification

  • Plain text, one theta rho pair per line (space-separated)
  • Theta: continuous radians (accumulating, does NOT wrap at 2pi)
  • Rho: 0.0 (center) to 1.0 (edge), normalized
  • Lines beginning with # are comments, ignored by table firmware

Example

# mujou
# Source: cherry-blossoms.jpg
# blur=1.4, canny=15/40, simplify=2, tracer=BorderFollowing, joiner=Mst, mask=75%, res=256
# Exported: 2026-02-14_12-30-45
# Config: {"blur_sigma":1.4,"canny_low":15.0,...}
0.00000 0.00000
0.10000 0.15000
0.20000 0.30000
0.50000 0.45000
1.00000 0.60000

Metadata

Metadata is embedded as #-prefixed comment lines at the top of the file. This mirrors the SVG exporter’s <title>, <desc>, and <metadata> approach and follows the convention established by Sandify, which uses # comments for file name, type, and section markers.

Line prefixContentPurpose
# mujouFixed identifierIdentifies the file as mujou-generated
# Source:Source image filenameProvenance
# (free-form)Pipeline parameters summaryHuman-readable settings (blur, canny, simplify, etc.)
# Exported:TimestampWhen the file was exported
# Config:Full PipelineConfig JSONMachine-parseable settings for reproducibility

All metadata lines are optional. Parsers should skip any line beginning with #.

Each metadata value must occupy a single line. Producers must not embed newline characters within a # comment value — continuation text after a newline would lack the # prefix and be misinterpreted as theta-rho data by table firmware.

The # Config: line contains the complete serialized PipelineConfig as a single JSON object, matching the content of the SVG exporter’s <mujou:pipeline> element. This allows re-importing settings to reproduce the exact same output.

XY-to-Polar Conversion

This is the most complex export step.

  1. Center: Image center = polar origin
  2. Axes: Cartesian +X points right, +Y points up (the pipeline’s normalized space is already +Y up)
  3. Rho: rho = sqrt(x^2 + y^2) / max_radius, normalized to [0.0, 1.0]
  4. Theta: theta = atan2(x, y), with continuous accumulation

The Sisyphus ecosystem uses atan2(x, y)not the standard math atan2(y, x). This means theta=0 points up (along +Y), and the Cartesian-to-polar / polar-to-Cartesian conversions are:

  • theta = atan2(x, y)
  • x = rho * sin(theta), y = rho * cos(theta)

This is confirmed by both Sandify (geometry.js, toThetaRho) and jsisyphus (Point.java: “The zero radial is coincident with the positive y axis”).

Continuous theta unwinding is critical. Theta must accumulate across the full path – if the path spirals clockwise, theta decreases past 0, -pi, -2pi, etc. If it spirals counterclockwise, theta increases past 2pi, 4pi, etc.

Algorithm:

#![allow(unused)]
fn main() {
for each point after the first:
    raw_theta = atan2(x, y)
    // Choose the equivalent angle closest to previous theta
    delta = raw_theta - prev_theta
    while delta > PI:
        delta -= 2 * PI
    while delta < -PI:
        delta += 2 * PI
    theta = prev_theta + delta
    prev_theta = theta
}

Path Start/End Requirements

The path must start and end with rho at 0 (center) or 1 (edge). If the contours don’t naturally start/end there, add a spiral-in or spiral-out segment.

G-code (.gcode)

For XY/Cartesian sand tables (ZenXY, GRBL/Marlin machines).

Format Specification

  • Standard G-code text
  • G0 X... Y... – rapid move (travel between contours)
  • G1 X... Y... F... – linear move (drawing)
  • Coordinates scaled to configurable bed size

Example

G28 ; Home
G90 ; Absolute positioning
G0 X10.00 Y15.00
G1 X12.50 Y18.30 F3000
G1 X14.00 Y20.10 F3000
G0 X30.00 Y5.00
G1 X32.50 Y7.80 F3000

Configuration

ParameterTypeDefaultDescription
bed_widthf64200.0Bed width in mm
bed_heightf64200.0Bed height in mm
feed_ratef643000.0Feed rate (mm/min)

SVG (.svg)

The most versatile output format. Also accepted by the Oasis Mini app (upload at app.grounded.so), though THR is preferred for Oasis because SVG sizing and centering can be incorrect in certain cases (see Oasis SVG sizing). Useful for plotters, laser cutters, vinyl cutters, or viewing in a browser.

Format Specification

  • Standard SVG XML
  • Optional <title> element with the source image name (for accessibility and file manager identification)
  • Optional <desc> element with pipeline parameters and export timestamp
  • Optional <metadata> element containing the full PipelineConfig as JSON, wrapped in a namespaced <mujou:pipeline> element for machine-parseable reproducibility
  • Each polyline becomes a <path> element with a d attribute containing M (move to) and L (line to) commands
  • Disconnected contours are separate <path> elements
  • viewBox set to the image dimensions

Example

<?xml version="1.0" encoding="UTF-8"?>
<svg height="600" viewBox="0 0 800 600" width="800" xmlns="http://www.w3.org/2000/svg">
<title>cherry-blossoms</title>
<desc>blur=1.4, canny=15/40, simplify=2, tracer=BorderFollowing, joiner=Mst, mask=75%, res=256
Exported: 2026-02-14_12-30-45</desc>
<metadata>
<mujou:pipeline xmlns:mujou="https://mujou.app/ns/1">{"blur_sigma":1.4,"canny_low":15.0,...}</mujou:pipeline>
</metadata>
<path d="M10,15 L12.5,18.3 L14,20.1" fill="none" stroke="black" stroke-width="1"/>
<path d="M30,5 L32.5,7.8 L35,10.2" fill="none" stroke="black" stroke-width="1"/>
</svg>

Note: SVG output is generated by the svg crate. Attribute ordering is determined by the library (typically alphabetical). Path coordinates use the library’s default f32 precision formatting. The JSON inside <mujou:pipeline> is XML-escaped — < becomes &lt;, & becomes &amp;, etc. Parsers should XML-unescape the text content before JSON-parsing it.

DXF (.dxf)

CAD interchange format for OnShape, Fusion 360, etc.

Format Specification

  • Minimal DXF using LINE entities in the ENTITIES section
  • Each segment of each polyline becomes a LINE entity
  • ASCII DXF format (not binary)

Example

0
SECTION
2
ENTITIES
0
LINE
8
0
10
10.0
20
15.0
11
12.5
21
18.3
0
LINE
8
0
10
12.5
20
18.3
11
14.0
21
20.1
0
ENDSEC
0
EOF

PNG Preview

Rasterized render of the traced paths for quick sharing and thumbnailing.

Specification

  • Render polylines onto a pixel buffer using the image crate
  • White background, black strokes (or configurable colors)
  • Output as PNG-encoded bytes
  • Resolution matches the input image dimensions

Live SVG Preview (UI)

In the browser UI, traced paths are rendered as inline SVG elements directly in the Dioxus DOM. This provides crisp vector rendering at any zoom level without requiring canvas or JS interop.

The preview uses a simplified version of the paths (higher RDP tolerance) to keep the DOM lightweight when the full path set is very large.

Preview Modes

ModeDescription
OriginalSource image displayed as-is
EdgesBinary edge map (Canny output)
PathsTraced polylines overlaid on original
Paths onlyTraced polylines on blank background