Types - Brep
API reference for ./geometry/brep on @huukhanhnguyen/types.
See the Guide for the package's role.
API reference
Signatures are generated from the live package .d.ts - not hand-written.
AnalyticSurface
type
The named analytic form of a document surface: a plane is already one, a revolve is RECOGNISED from its profile, a nurbs has none (null).
It exists because a document that stores a profile has to be recognised by anything that wants named parameters, and the STEP and IGES writers want exactly that: they emit CYLINDRICAL_SURFACE with an axis and a radius, not a swept profile. The recogniser itself (surfaceForm / analyticFromRevolve) is RUNTIME and lives in @huukhanhnguyen/geometry; this is the shape it — and the kernel's own Brep.faceFormsJson — hand back, so a writer can take its form from either source and switch once.
type AnalyticSurface
// = {
type: "plane";
normal: Vector;
d: number;
uvMin: [number, number];
uvMax: [number, number];
}Brep
type
Solid-root B-Rep document (wasm serialize format): version 2 + shared tables + multi-shell partition. Same stem as the Brep ops namespace. Scene entities still store one-shell Shell; converters toKernelDocument / fromKernelDocument add or strip the envelope.
type Brep
// = {
version: 2;
vertices: Vertex[];
edges: Edge[];
loops: Loop[];
faces: Face[];
/** Shell partition — not a scene field. */
shells: {
faces: number[];
}[];
}Edge
type
A curve bounded by two vertices, given as indices into the document's vertex table. The parameter window is the carrier's own natural range.
Two flags that used to sit here are gone, because both are exactly derivable and a stored copy can only contradict what it describes:
degenerate— an edge collapsed to a point. DERIVE: the carrier's length is 0. A degenerate edge still carries a real, zero-length curve (verified 2026-08-09: the kernel'sEdge.curveis non-optional at every construction site), so there is always something to measure. A probe over the kernel's 321-test suite found 16 edges whose authoredfalsecontradicted a carrier of length 0 — the flag was not merely redundant, it was wrong.sameRange— DERIVE: compare the carrier's parameter interval with the uv curve's. Two pairs of numbers, no sampling.
sameParameter STAYS. Checking it means sampling, and sampling gives FALSE POSITIVES here: campaign 2026-08-05 W5 measured ~6k samples/edge missing a 3.2e-4 jump, with 200k needed to see it. The producer knows; a consumer cannot cheaply re-establish it. Absent means true.
type Edge
// = {
start: number;
end: number;
curve: Curve;
tolerance?: number;
attributes?: Record<string, unknown>;
sameParameter?: boolean;
}Face
type
A bounded patch of a surface: one outer loop, plus inner loops that cut holes.
Both geometry carriers are this document's own unions (Surface, UvCurve), declared above beside the rows that hold them.
Chart window (naturalBounds) is NOT stored: the geometry kernel derives it from surface + outer trim (OpenNURBS / OCCT alignment). See Store::natural_bounds in the Rust kernel.
reversed — whether the face's outward normal opposes its surface's natural normal. Surfaces are shared via Rc across faces, so orientation cannot be folded into the carrier.
uvCurves — the uv image of each boundary edge. Seam-unwrap anchors make pure 3D projection non-recoverable; stored per face.
reversedUseUvCurves — the second uv image a REVERSED use of a seam edge reads, a full period away in u. Omitted on every face with no seam.
type Face
// = {
surface: Surface;
outerLoop: number;
innerLoops: number[];
reversed: boolean;
uvCurves: FaceUvCurve[];
reversedUseUvCurves?: FaceUvCurve[];
/**
* Authored row-major 4×4 plane→world UV frame for THIS face
* (`world = uvMatrix · [u,v,0,1]`). Absent ⇒ derived from the face's own
* surface on read. Per-face, never per-shell.
*/
uvMatrix?: Transformation;
/** Surface-fit tolerance; omitted when at the 1e-7 default. */
tolerance?: number;
attributes?: Record<string, unknown>;
}FaceUvCurve
type
A uv curve recorded on a face for one of its boundary edges.
type FaceUvCurve
// = {
edge: number;
uvCurve: UvCurve;
}Loop
type
An ordered, closed chain of oriented edges bounding a region of a face.
No type parameter, no tolerance, no attributes: a loop carries no geometry, only the order its edges are walked in.
It does NOT say whether it is the outer boundary or a hole — the FACE declares which of its loops is outer. OpenNURBS carries the claim on both, where they can disagree; one source cannot.
type Loop
// = {
orientedEdges: OrientedEdge[];
}OrderableBrepDocument
type
The topology tables a face/edge reorder walks — a B-Rep document slice, not a file format. Runtime: @huukhanhnguyen/io brepOrder.ts.
type OrderableBrepDocument
// = {
edges: unknown[];
loops: {
orientedEdges: {
edge: number;
}[];
}[];
faces: {
outerLoop: number;
innerLoops: number[];
}[];
shells: {
faces: number[];
}[];
}OrientedEdge
type
An edge taken in a traversal direction. forward walks start → end.
type OrientedEdge
// = {
edge: number;
forward: boolean;
}Shell
type
One shell: the entity tables, and nothing else. One entity = one shell (connected faces). Whole-body grouping of several shells is derived (classifyShells), not stored. No per-document version — the model carries SCHEMA_VERSION.
type Shell
// = {
vertices: Vertex[];
edges: Edge[];
loops: Loop[];
faces: Face[];
}Surface
type
The document's surface carrier: the three kinds of the PlaneSurface / RevolveSurface / NurbsSurface union (surface.ts) wearing their type tags, plus carrier-only fields on the nurbs arm that are document concerns rather than geometry.
type Surface
// = ({ type: "plane"; } & PlaneSurface) | ({ type: "revolve"; } & RevolveSurface) | ({ type: "nurbs"; /** Explicit closure flags of a form carrier. A plain nurbs surface * re-detects these by sampling; a form carrier records them rather * than re-deriving. */ uPeriodic?: boolean; vPeriodic?: boolean; /** * The surface's form was frozen ABSENT — a STEP nurbs import, or an * explicit null seed. This records INTENT and is not derivable: the * whole point is that lazy recovery WOULD find a form here (a nurbs * extrude wall recovers as a cylinder), re-tag the carrier, and desync * evaluation from the uv the uv curves were built in. */ formAbsent?: boolean; } & NurbsSurface)TrimmedFace
type
One trimmed face as self-contained tables (exactly one face). Used by hatch: the face is the uv domain and its trim is the boundary.
type TrimmedFace
// = {
vertices: Vertex[];
edges: Edge[];
loops: Loop[];
faces: [Face];
}UvAnchor
type
uv pair plus the 3D-curve parameter at which that uv was anchored.
type UvAnchor
// = {
t: number;
u: number;
v: number;
}UvCurve
type
A face uv-curve CARRIER — the curve in the face's UV parameter space for one boundary edge. Written as the carrier's own description rather than as a resampling of it, so a reload reconstructs the same curve instead of an interpolation through points taken off it.
NOT a world Path / Path2d. This lives in surface (u, v).
polycurve— explicit UV geometry as aPolyCurve2dchain (line / arc / ellipse / nurbs segments). Straight uv segments and station chains land here.projected— the uv image evaluated by projecting a 3D curve onto a surface. The surface is written asnullwhen it IS the owning face's, which it always is in practice; the curve is written asnullonly when it is the owning edge's own carrier, which it often is NOT — a section uv curve keeps the curve the intersector traced while the edge may have been re-carried on a different parameterization since, so that operand is normally spelled out.anchorscarries the seam-unwrap references verbatim,nullfor a plain projection with none.reversed— a carrier walked backwards.
type UvCurve
// = {
type: "polycurve";
curve: PolyCurve2d;
}Vertex
type
A point in the topology, plus the ball inside which two coincident vertices are the same vertex.
tolerance ABSENT means 0 means EXACT — the convention every optional tolerance in this package keeps, so the lean document is also the exact one.
KNOWN GAP: no producer in this repo satisfies that convention yet. Measured 2026-08-09 across brep_cylinder, brep_sphere, brep_box and box − cylinder: every vertex and every edge carries the same stamped constant 1e-7, and nothing carries 0. So "exact" is an empty category today, and tolerance cannot be used to tell an exact entity from a fitted one — a rule of the form "do X only when tolerance > 0" fires on everything. The convention above states the INTENT; treat a 1e-7 you read as "unset", not as a measured deviation. This matters beyond bookkeeping: Vertex.tolerance is read both as an identity ball and as a closure band, and a stamped constant makes those bands identical regardless of how the point was produced.
type Vertex
// = {
position: Point;
tolerance?: number;
attributes?: Record<string, unknown>;
}Wire
type
A standalone 1D topological complex — flat vertex/edge tables. Connectivity is derived from shared vertex indices (no stored polyCurve index list — it restated what the tables already say).
NOT curve-entity geometry. Drawn / stream curve entities use PolyCurve (curve.ts, ordered chain). Wire is only for B-Rep-adjacent 1D graphs that may branch (T-junctions).
type Wire
// = {
vertices: Vertex[];
edges: Edge[];
/** Present only on shells — keeps Wire from accepting Shell. */
faces?: never;
loops?: never;
}