Skip to content
Shapemetry

@huukhanhnguyen/types / objects/brep

objects/brep

BrepData

BrepData = { edges: BrepEdge[]; faces: BrepFace[]; loops: BrepLoop[]; vertices: BrepVertex[]; }

Shared topology tables of one body. The geometry may contain several topological shells' faces; the partition is derived (classifyShells). Same stem as the BrepData ops namespace.

edges

edges: BrepEdge[]

faces

faces: BrepFace[]

loops

loops: BrepLoop[]

vertices

vertices: BrepVertex[]


BrepEdge

BrepEdge = { attributes?: Record<string, unknown>; curve: Segment; end: number; start: number; tolerance?: number; }

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.

attributes?

optional attributes?: Record<string, unknown>

curve

curve: Segment

end

end: number

start

start: number

tolerance?

optional tolerance?: number


BrepFace

BrepFace = { attributes?: Record<string, unknown>; innerLoops: number[]; layer?: string; material?: string; outerLoop: number; reversed: boolean; surface: Surface; tolerance?: number; uvCurves: BrepFaceUvCurve[]; uvMatrix?: Transformation; }

A bounded patch of a surface: one outer loop, plus inner loops that cut holes.

The geometry kernel derives the chart window from surface + outer trim (Store::natural_bounds).

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 — one PolyCurve2d per boundary edge. Seam-unwrap anchors are baked into that chain on write.

A seam edge is walked TWICE by one loop, once per parameter column, and the second image is not stored: the kernel computes it by translating the first one period along the periodic direction (Store::uv_curve_on_use).

attributes?

optional attributes?: Record<string, unknown>

innerLoops

innerLoops: number[]

layer?

optional layer?: string

Layer key for THIS face, overriding its placement's Instance.layer. Absent === inherit from the instance.

Per-face for the reason material already is: an IMPORTED document can carry N different layers across its faces before it is ever wrapped into one Object — DXF especially, which assigns layer per ENTITY and never per block — and collapsing that to one Instance-level layer on arrival loses what the file actually said.

material?

optional material?: string

Material key for THIS face, overriding its placement's Instance.material. Absent === inherit from the instance.

The oldest per-face lane reference and the reason layer is one too: a boolean fragment, an OBJ usemtl run or a glTF primitive names a material per FACE, and one document holds many faces, so the claim cannot ride the placement.

outerLoop

outerLoop: number

reversed

reversed: boolean

surface

surface: Surface

tolerance?

optional tolerance?: number

Surface-fit tolerance; omitted when at the 1e-7 default.

uvCurves

uvCurves: BrepFaceUvCurve[]

uvMatrix?

optional uvMatrix?: Transformation

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.


BrepFaceUvCurve

BrepFaceUvCurve = { edge: number; uvCurve: PolyCurve2d; }

A uv image recorded on a face for one of its boundary edges: one PolyCurve2d in the face's (u, v). Reverse, a partial window and a 3D-projected image are baked into that chain on write.

edge

edge: number

uvCurve

uvCurve: PolyCurve2d


BrepInstance

BrepInstance = BaseInstance & { material?: string; }


BrepLoop

BrepLoop = { orientedEdges: OrientedEdge[]; }

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.

orientedEdges

orientedEdges: OrientedEdge[]


BrepObject

BrepObject = BaseObject & { data: BrepData; instances: BrepInstance[]; type: "brep"; }

An object whose data is one kernel brep — one body.

A boolean that returns a body with cavities stays one object; the shell partition is derived inside the kernel.


BrepVertex

BrepVertex = { attributes?: Record<string, unknown>; position: Point; tolerance?: number; }

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 element 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: BrepVertex.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.

attributes?

optional attributes?: Record<string, unknown>

position

position: Point

tolerance?

optional tolerance?: number


OrientedEdge

OrientedEdge = { edge: number; forward: boolean; }

An edge taken in a traversal direction. forward walks start → end.

edge

edge: number

forward

forward: boolean


Surface

Surface = { type: "plane"; } & PlaneSurface | { type: "revolve"; } & RevolveSurface | { formAbsent?: boolean; type: "nurbs"; uPeriodic?: boolean; vPeriodic?: boolean; } & NurbsSurface

The document's surface carrier: the three kinds of the PlaneSurface / RevolveSurface / NurbsSurface union (geometry/surface.ts) wearing their type tags, plus carrier-only fields on the nurbs arm that are document concerns rather than geometry.

Last updated: 📖 6 min readEdit on GitHub