Skip to content
Shapemetry

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's Edge.curve is 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 authored false contradicted 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 a PolyCurve2d chain (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 as null when it IS the owning face's, which it always is in practice; the curve is written as null only 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. anchors carries the seam-unwrap references verbatim, null for 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;
}
Last updated: 📖 6 min readEdit on GitHub