Export 3MF with B-rep face tags (#834)
3MF export carries each triangle's B-rep face tag.
This commit is contained in:
1 parent
ff7a347013
commit
5d661fa2af
10 files changed
+286
-47
No files matched your search
@@ -7,6 +7,7 @@
|
||||
| STEP (AP203, AP214, AP242) | solids, assemblies, units, names, colours | AP242 with names, colours and the component tree |
|
||||
| IGES 5.3 | manifold solids, or trimmed surfaces sewn into solids | manifold solids with names and colours |
|
||||
| 3MF, STL, OBJ | mesh bodies | yes |
|
||||
| 3MF with face tags | as 3MF | each triangle tagged with its B-rep face, exact coordinates |
|
||||
| DXF, SVG | into a sketch | sketches and flat patterns as DXF |
|
||||
| PNG, JPEG | canvases and decals | |
|
||||
|
||||
@@ -28,6 +29,12 @@ tapers, stepped parts and organic scans are refused by this first reconstruction
|
||||
method; it does not silently substitute a faceted solid. Conversion currently
|
||||
accepts at most 50,000 triangles and a bounded number of boundary segments.
|
||||
|
||||
**File → Export 3MF with Face Tags** (`file.export` with `format: "3mf-tagged"`) writes an
|
||||
ordinary 3MF in which every triangle also names the B-rep face it lies on and every coordinate
|
||||
is the tessellation's own double-precision value. Meshing and analysis tools can use the tags to
|
||||
keep a model's faces (for loads, boundary conditions or feature edges); other 3MF readers ignore
|
||||
them. The format is specified in [`docs/formats/3mf-face-tags.md`](https://github.com/bherbruck/solidcraft/blob/main/docs/formats/3mf-face-tags.md).
|
||||
|
||||
Saves are atomic: a crash at any moment leaves either the old file or the new one, and the
|
||||
replaced version is kept as `<file>.bak`. Unsaved changes are autosaved to a recovery folder,
|
||||
and the next launch offers to recover them. Older design files are upgraded on open, and files
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
# 3MF with B-rep face tags
|
||||
|
||||
Version 1 (2026-10). Namespace `https://github.com/bherbruck/solidcraft/formats/3mf-face-tags/2026/10`,
|
||||
prefix `ft`.
|
||||
|
||||
A tessellated body loses its faces: a plain mesh says where the surface is, not which B-rep face
|
||||
each triangle came from. Downstream tools that mesh or analyse a part need that back. They apply
|
||||
loads and boundary conditions to faces, keep face boundaries as feature edges, and group
|
||||
results by face. SolidCraft therefore exports a 3MF in which every triangle carries the index of
|
||||
the B-rep face it lies on (**File → Export 3MF with Face Tags**, or `file.export` with
|
||||
`format: "3mf-tagged"`).
|
||||
|
||||
## Why 3MF
|
||||
|
||||
The file is an ordinary **3MF package** (3MF Consortium, *3D Manufacturing Format Core
|
||||
Specification* 1.3). The tags are one attribute in a namespace of SolidCraft's. The Core
|
||||
specification allows that attribute on `<triangle>` and `<object>`, and every consumer ignores it
|
||||
because the namespace is not listed in `requiredextensions`. Slicers, viewers and SolidCraft's
|
||||
own mesh import open the file as plain 3MF. A tool that knows the namespace gets the faces too.
|
||||
A purpose-built binary format would have needed its own specification and readers, and would
|
||||
open nowhere else. Decimal coordinates lose nothing: written in shortest round-trip form, every
|
||||
`f64` reads back bit for bit.
|
||||
|
||||
## Example
|
||||
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<model unit="millimeter" xml:lang="en-US"
|
||||
xmlns="http://schemas.microsoft.com/3dmanufacturing/core/2015/02"
|
||||
xmlns:ft="https://github.com/bherbruck/solidcraft/formats/3mf-face-tags/2026/10">
|
||||
<metadata name="Application">SolidCraft</metadata>
|
||||
<resources>
|
||||
<object id="2" type="model" name="Body1" ft:faces="7">
|
||||
<mesh>
|
||||
<vertices>
|
||||
<vertex x="0" y="0" z="0"/>
|
||||
...
|
||||
</vertices>
|
||||
<triangles>
|
||||
<triangle v1="0" v2="2" v3="1" ft:face="0"/>
|
||||
...
|
||||
</triangles>
|
||||
</mesh>
|
||||
</object>
|
||||
</resources>
|
||||
<build>
|
||||
<item objectid="2"/>
|
||||
</build>
|
||||
</model>
|
||||
```
|
||||
|
||||
## Attributes
|
||||
|
||||
| Attribute | On | Value | Meaning |
|
||||
|---|---|---|---|
|
||||
| `ft:faces` | `<object>` | integer ≥ 1 | Number of B-rep faces of the body. Every `ft:face` of the object is below it. Faces without triangles still count. |
|
||||
| `ft:face` | `<triangle>` | integer ≥ 0 | The B-rep face (0-based, in the body's own face order) the triangle lies on. |
|
||||
|
||||
An object's triangles are either all tagged or none. A reader treats an object without tags as a
|
||||
single face (tag 0).
|
||||
|
||||
## What SolidCraft writes
|
||||
|
||||
- `unit="millimeter"`, Z up. There is one `<object type="model">` with a `<mesh>` per body,
|
||||
named after the body, and one `<item>` per object, with no transform and no components.
|
||||
- The tessellation is the export mesh (chord tolerance 2·10⁻⁴ of the body size). It is welded
|
||||
watertight: vertices within 10⁻⁶ of the body size are merged and T-junctions between faces are
|
||||
split. Each piece of a split triangle keeps its face. Triangles are counter-clockwise seen from
|
||||
outside, and degenerate triangles are dropped.
|
||||
- Coordinates are the tessellation's own `f64` values in shortest round-trip form, and vertices
|
||||
are shared by exact value.
|
||||
- Colours use 3MF's own `basematerials` (`pid`/`p1`), as in the plain 3MF export, independent of
|
||||
the tags.
|
||||
- The bytes are deterministic: fixed part order, fixed zip timestamps, no hash-ordered output.
|
||||
|
||||
## Versions
|
||||
|
||||
A later version gets a new namespace (`…/3mf-face-tags/<year>/<month>`). A reader accepts the
|
||||
versions it knows and treats an unknown face-tag namespace as untagged.
|
||||
+1
-1
@@ -65,7 +65,7 @@ They cover the workflow, the command shapes, how to verify with `measure`, and t
|
||||
| `body_topology` | `body` | Edges (index, midpoint, length, ends) and faces (index, area, centroid, normal). An edge midpoint is the `[x,y,z]` that picks that edge for fillet and chamfer. |
|
||||
| `set_parameter` | `name`, `value` (number or expression), `unit?`, `comment?` | Create or change a user parameter and recompute; reports `recomputed` (features rebuilt), `restored` (features whose earlier result for the same inputs was reused, e.g. a value set back) and features that now fail. |
|
||||
| `screenshot` | `view?` (iso, top, front, back, bottom, left, right, home, fit, or a named view saved with `view.save`), `camera?` (`{target, yaw, pitch, distance, fov?}`, as `view.apply`), `path?`, `width?`, `height?`, `source?` (window, model) | A PNG image content block. Headless: CPU render fitted to the model, or from the named view or camera. Bridged: the app window (default) or a model render with the app's camera; a named view or camera moves the app's viewport there first (`execute` `view.apply` does the same without a screenshot). |
|
||||
| `export` | `path`, `format?` (step, 3mf, stl, stla, obj), `bodies?` | STEP, 3MF or mesh export. |
|
||||
| `export` | `path`, `format?` (step, 3mf, 3mf-tagged, stl, stla, obj), `bodies?` | STEP, 3MF or mesh export. |
|
||||
| `undo`, `redo` | — | Undo / redo one change. |
|
||||
| `crash_reports` | `id?`, `limit?` | The crash reports on this computer, newest first; with `id`, the whole report (backtrace, command, recent commands, `design_path`/`replay_path`). See [crash-reports.md](crash-reports.md). |
|
||||
| `new_design` | `name?` | Start an empty design. |
|
||||
|
||||
Reference in new issue
Block a user