colino
Converts triangle meshes into narrow-band signed distance fields on brodo's sparse volumes, and reports how the conversion may have changed the shape: a hole closed, a cavity opened, a wall too thin or a gap too narrow for the voxel size. ARCHITECTURE.md §5 says what a conversion gives and what each part of the report finds.
- Reading: binary and ASCII STL, Wavefront OBJ and 3MF, each into a
Mesh, under theLimitsyou set on triangles, vertices and bytes, so that an untrusted file cannot exhaust memory. A mesh from elsewhere, a CAD kernel's triangulation say, is built as aMeshdirectly; itsgroupsandgroup_namescarry the faces' names into the Hermite data. - Converting:
convertwithOptions, chiefly the voxel size in the mesh's unit and the band's half-width in voxels (with_band). It gives the topology, the distances (negative inside, in the mesh's unit) and the grid's metadata. Inside and outside are told by the generalised winding number, which holds where parts pass into each other or walls are doubled, approximate by default or exact (with_accuracy); or, for a mesh whose triangles face either way at random, by counting crossings (with_sign(Sign::Parity)). - Reporting:
reportcounts the components, tunnels and cavities of the solid and of the space around it; compares the Euler characteristic with the input's when the input is closed and manifold; says which component each point you name lies in; and lists the places thinner, or gaps narrower, than two voxels. - Hermite data: where the mesh crosses each voxel edge, with its normal and the
triangle's group, beside the signs at the corners, in brodo's format
(
colino::hermite).
Features, each a part a user may leave out or opt into:
| Feature | Default | Gives |
|---|---|---|
stl |
on | reading STL |
obj |
on | reading OBJ |
threemf |
on | reading 3MF, with its ZIP and XML parsing |
serde |
off | the report serialisable with serde |
Example
An octahedron read from OBJ text, converted, and its report checked:
use ;
use Limits;
use ;
// An octahedron, its faces turned outward, as OBJ text.
let obj = b"v 10 0 0\nv -10 0 0\nv 0 10 0\nv 0 -10 0\nv 0 0 10\nv 0 0 -10\n\
f 1 3 5\nf 3 2 5\nf 2 4 5\nf 4 1 5\nf 3 1 6\nf 2 3 6\nf 4 2 6\nf 1 4 6\n";
// At most 2²⁰ triangles, 2²⁰ vertices and 64 MiB read.
let limits = new;
let mesh = from_bytes?;
// Voxels of 0.5 in the mesh's unit; OBJ states none, so the grid is told its own.
let options = new.with_unit;
let converted = convert?;
let points = ;
// One solid piece with no tunnel or cavity, its Euler characteristic as the mesh's, and
// the first point inside it.
let r = report?;
assert_eq!;
assert_eq!;
assert_eq!;
# Ok::
The examples convert a torus, checked against its exact distance, and a vented box whose
vent closes at a coarser voxel size. Each writes a slice as PNG and its report to
out/examples/colino/:
Given a mesh file of your own and a voxel size in its unit, the torus example converts that file instead:
It is written by a human, its owner, together with AI coding agents, chiefly Claude Code and Antigravity in support: the owner decides and approves, the agents write under the repository's rules, and every change passes the same checks and tests (the repository's README says more).
Issues are welcome at https://github.com/akahmys/brodo/issues, a bug with the steps that show it or a request. Pull requests are not accepted: code written elsewhere cannot be shown free of copyleft sources, so fixes are written here from issues.
Licensed under either of MIT or Apache-2.0, at your option.