@huukhanhnguyen/model / nodeMethods/utils
nodeMethods/utils
clusterFaces()
clusterFaces(
faces,tolerance?):BrepData[][]
Union-find over brep data documents that share a boundary vertex (within tolerance, world units/mm) — derives the connected partition of a flat BrepData[]; the partition is never stored. Used by packages/collision (a part-boundary tolerance, deliberately coarser than nodeMethods/solid/mesh.ts's internal connectedFaceGroups, which uses a much tighter 1e-6 mesh-weld tolerance for a different purpose).
Parameters
faces
BrepData[]
tolerance?
number = 1e-3
Returns
BrepData[][]
computedCount()
computedCount(
value,minimum,op,name?):number
A count the author normally COMPUTES (divide(curve, length / spacing), a sweep's step count) rather than writes as a literal.
The registry declares these args as number, so a fraction is permitted by the contract and flooring it is the operation's own definition — asking for 7.3 segments means 7 whole segments, and no tolerance is broken. That is what separates this from wholeCount, where flooring or clamping would substitute a DIFFERENT model than the one authored (polygon(sides: 2) is not a triangle, arrayLinear(copies: 2.7) is not 2 copies).
What it still refuses is a value that cannot mean a count at all: NaN (a failed expression), infinite, or below the minimum the maths needs.
Parameters
value
number
minimum
number
op
string
name?
string = "count"
Returns
number
dataId()
dataId():
string
Returns
string
facesToIndices()
facesToIndices(
faces):number[]
Flatten polygon faces to a TRIANGLE index buffer. Tessellated output is always 3-gons; an n-gon fans from its first vertex.
Parameters
faces
number[][]
Returns
number[]
flattenPoints()
flattenPoints(
points):Float64Array
Door codec: a point list as the flat [x, y, z, ...] buffer every geometry wasm door takes. A 2-long point reads z as 0 — the 2D-input case curve.ts feeds; a Point always has its third slot.
Parameters
points
readonly readonly number[][]
Returns
Float64Array
meshPointAt()
meshPointAt(
positions,index):Point
Door codec: one corner of a flat triangulation (types' TriangleMesh) as a Point. The nested point spelling exists only at doors that speak points (faceGeometryFromLoops, pin predicates) — never as a sibling mesh type.
Parameters
positions
readonly number[]
index
number
Returns
newellSum()
newellSum(
loop):Vector
Parameters
loop
Point[]
Returns
pointInPolygon2d()
pointInPolygon2d(
p,polygon):boolean
Ray-cast point-in-polygon (even-odd rule) in 2D.
Parameters
p
[number, number]
polygon
[number, number][]
Returns
boolean
projectToPlane2d()
projectToPlane2d(
p,origin,u,v): [number,number]
Project a 3D world point onto a 2D plane basis (orthonormal u/v axes through origin) — a dot-product projection, not a matrix solve.
Parameters
p
origin
u
v
Returns
[number, number]
signedDistanceToPlane()
signedDistanceToPlane(
point,planePoint,normal):number
Signed distance from point to the plane through planePoint with unit normal — positive on the +normal side, negative on the -normal side.
Parameters
point
planePoint
normal
Returns
number
weldKey()
weldKey(
point,scale?):string
Quantize a point into a stable string key for vertex-welding (Map/Set dedup by position) — two points within 1/scale of each other collide to the SAME key. Default 1e6 = 1e-6 world-unit tolerance; pass a different scale for a looser/tighter weld.
Parameters
point
readonly number[]
scale?
number = 1e6
Returns
string
wholeCount()
wholeCount(
value,minimum,op,name?):number
A whole-number argument (a copy count, a side count, a division count) that drives a loop — checked instead of clamped.
Measured 2026-08-15: the ops taking one either did not check at all (arrayLinear) or clamped with Math.max(minimum, Math.round(value)) (polygon, divide, pointsInLoops). Both shapes turn a bad argument into a believable answer:
Math.max(3, Math.round(NaN))is NaN, not 3 — the clamp does not clamp, the loop below it never runs, and the op returns an empty or unchanged result. NaN is the value an argument takes when its expression fails to evaluate, so this is a case real documents reach.- a clamp that DOES fire silently substitutes a different model than the one authored:
polygon(sides: 2)drew a triangle,divide(count: 0)returned two points.
minimum states what the maths needs (a polygon needs 3 sides, a division needs 1 segment). It is a rejection threshold, never a substitution.
Parameters
value
number
minimum
number
op
string
name?
string = "count"
Returns
number