Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,23 @@ All notable changes to the `opengeometry` package are in this file. The format f
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the package follows
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- Solid primitives `OG_PRIMITIVE_SLOT_PRISM`, `OG_PRIMITIVE_ROUNDED_BOX` and
`OG_PRIMITIVE_PIPE_SEGMENT`, with their `OG_PRIMITIVE_PARAMS_*` helpers and the
`SlotPrismParams`, `RoundedBoxParams` and `PipeSegmentParams` types.
- `OG_PRIMITIVE_POLYSOLID`: a solid wall of constant width and height along a path of straight
legs, with `justify` `'centre'`, `'left'` or `'right'`, mitred corners and an open or closed
path. `OG_PRIMITIVE_PARAMS_POLYSOLID` and the type `PolysolidParams` give it a
type.
- Wire primitives `OG_PRIMITIVE_REGULAR_POLYGON`, `OG_PRIMITIVE_SLOT` and
`OG_PRIMITIVE_ROUNDED_RECTANGLE`, with their `OG_PRIMITIVE_PARAMS_*` helpers and the
`RegularPolygonParams`, `SlotParams` and `RoundedRectangleParams` types.
- `OG_PRIMITIVE_POLYSOLID` paths take arc segments that join their neighbours tangentially. A
joint where an arc meets a segment at an angle throws `InvalidParameter` that names the joint.

## [3.0.0] - 2026-11-09

3.0 is a new API. Code written for 2.0 does not run without changes. Version 2.5 was not
Expand Down Expand Up @@ -70,7 +87,11 @@ published. Follow [MIGRATION.md](./MIGRATION.md): it gives every change with cod
### Removed

- **Breaking:** IFC file text, STL and PDF export, projection, loft, triangulation as a public
call, curves other than lines, circles and arcs, and wedges. They have no replacement in 3.0.
call, and curves other than lines, circles, arcs and polylines, such as the elliptical arc.
They have no replacement in 3.0. 3.0 has no spline, no ellipse and no elliptical arc. The
wedge and the 2.0 `Curve` class are gone too. Build a wedge as a five-face
`OG_PRIMITIVE_POLYHEDRON`, and a 2.0 `Curve` as an `OG_PRIMITIVE_POLYLINE` wire through its
points.

### Fixed

Expand Down
8 changes: 5 additions & 3 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const sector = new AnalyticSolid({
height: 3,
});
const arc = new Arc({ center: new Vector3(0, 0, 0), radius: 2, startAngle: 0, sweepAngle: Math.PI / 2 });
const wedge = new AnalyticSolid({ kind: 'cylinderSector', radius: 2, height: 3, startAngle: 0, sweepAngle: Math.PI / 2 });
const quarterCylinder = new AnalyticSolid({ kind: 'cylinderSector', radius: 2, height: 3, startAngle: 0, sweepAngle: Math.PI / 2 });
const roof = new AnalyticSolid({
kind: 'planarPolyhedron',
vertices: [[0, 0, 0], [4, 0, 0], [4, 0, 2], [0, 0, 2], [1, 1, 1], [3, 1, 1]],
Expand Down Expand Up @@ -115,7 +115,7 @@ const sector = new Solid(OG_OPERATION_EXTRUDE, { profile, distance: 3 });

const arc = new Wire(OG_PRIMITIVE_ARC, OG_PRIMITIVE_PARAMS_ARC({ radius: 2, startAngle: 0, sweepAngle: Math.PI / 2 }));

const wedge = new Solid(
const quarterCylinder = new Solid(
OG_PRIMITIVE_CYLINDER_SECTOR,
OG_PRIMITIVE_PARAMS_CYLINDER_SECTOR({ radius: 2, height: 3, startAngle: 0, sweepAngle: Math.PI / 2 }),
);
Expand Down Expand Up @@ -760,14 +760,16 @@ In the 2.5 column, a `?` after a parameter name marks it as optional, and rows t
- `WorldGraph`: nodes and hierarchy become `SystemAssembly`, `addChild` or the `parent` option; `getWorldBounds(id)` becomes `body.getBounds()`, six numbers instead of a `THREE.Box3`; `removeNode(id)` becomes `parent.removeChild(body)`, which keeps the body (pass `{ keepWorld: true }` to leave it where it is), or `body.dispose()`, which frees it and everything under it; a body with no parent has only `dispose()`; `exportStep` becomes `OpenGeometry.exportStep({ nodes })` (nodes may be bodies or assemblies). Its `clash`, `clearance`, `distance`, `projectLines`, `projectViews` and `bind` are gone.
- The pattern helpers (`AnalyticPattern`, `linearPattern`, `rectangularPattern`, `circularPattern`): make copies with `solid.instance()` and move each with `transform`; check the positions, since 2.0 drew a pattern around its own origin. `rebuild` and `operate` on an instanced body need `{ instances: 'all' }` or `makeUnique()` first.
- `AnalyticSolid` kinds: `linearExtrusion` becomes `OG_OPERATION_EXTRUDE` with closed polyline wires for the outline and each hole, each 2.0 point `[u, v]` written `[u, 0, -v]` when the 2.0 `frame` was the default (with another `frame`, also give each wire `plane: { origin: frame.origin, normal: frame.z, xDirection: frame.x }` and check which way it extrudes); `revolvedRectangle` (a tube) becomes `OG_OPERATION_EXTRUDE` with a circle wire as `profile` and a smaller circle wire with the same centre as the one hole.
- `Wedge`: `OG_OPERATION_EXTRUDE` with a closed triangle polyline wire as `profile`; give the wire `plane: { normal: [0, 0, 1], xDirection: [1, 0, 0] }` so it extrudes along z as the 2.0 wedge did, and move it by the 2.0 `center`; from 3.0, also a five-face `OG_PRIMITIVE_POLYHEDRON`.
- `Curve`: a polyline through its control points, so `new Wire(OG_PRIMITIVE_POLYLINE, { points })` through the same points.

### Removed in 2.5

These are gone:

- STL and IFC export. PDF export was never in the browser build.
- Projection and 2D views, offset, loft, and public triangulation (`tessellate_brep`, `tessellateFacetedBrep`).
- `Sphere`, `Wedge`, `Curve`, `EllipticalArc`, `AnalyticCurve`, arcs that are not full circles, and cylinder sectors.
- `Sphere`, `EllipticalArc`, `AnalyticCurve`, arcs that are not full circles, and cylinder sectors.
- `AnalyticSolid` kinds other than cuboid, cylinder, `linearExtrusion` and `revolvedRectangle`, `AnalyticSolid.fromBrep`, and `new Solid({ brep })`.
- `WorldGraph`'s queries and projection: `clash`, `clearance`, `distance`, `projectLines`, `projectViews` and `bind`.
- The older scene manager (`add*ToScene`, `replaceBrepEntityInScene`, `refreshBrepEntityInScene`), already removed in 2.0.16.
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ It is the geometry engine layer, not a full CAD application. Floorkit is a downs

| Area | What 3.0 has |
| --- | --- |
| **Primitives** | Wires: rectangle, circle, polyline (open or closed), line-and-arc profile, arc. Solids: cuboid, cylinder, cylinder sector, sphere, cone or frustum, ring torus, planar polyhedron. Each can be placed on any plane. |
| **Primitives** | Wires: rectangle, circle, polyline (open or closed), line-and-arc profile, arc, regular polygon, slot, rounded rectangle. Solids: cuboid, cylinder, cylinder sector, sphere, cone or frustum, ring torus, planar polyhedron, slot prism, rounded box, pipe segment, polysolid wall along a path of straight legs and tangent arcs. Each can be placed on any plane. |
| **Operations** | Extrude a closed wire into a solid, with holes. Sweep a profile along an open or closed path of lines and arcs, each arc an exact bend, capped into a solid, open-ended into a sheet, or closed into a ring. Revolve a closed line-and-arc profile a full turn about an axis in its plane. Shell a solid into a hollow one with walls of one thickness. Union, subtract and intersect, with one to a hundred tool solids in one call. |
| **Parametric edits** | `rebuild` gives an existing body new parameters in place. `mirror` rebuilds a body as its reflection across a plane. |
| **Assemblies** | Assemblies with parent and child placement; translate, rotate, scale and place; independent copies and shared instances. |
Expand All @@ -51,7 +51,7 @@ It is the geometry engine layer, not a full CAD application. Floorkit is a downs
| **Queries** | Bounds, placements, the B-rep of a body, that B-rep placed in the world, the normal of a face at a point, whether a point is inside, volume and area within a stated error bound, whether a body is valid and closed, and the report of its last boolean. |
| **Export** | STEP, in millimetres or metres, with Y or Z up, together with an export report. The IFC exchange body of a solid, in world metres with Z up, for an IFC writer. |

Not in 3.0, though 2.0 had them: IFC file text and STL export; projection; loft; triangulation as a public call; curves other than lines, circles and arcs; wedges; and the 2.0 classes such as `Cuboid`, `Polygon`, `Opening` and `Vector3`.
Not in 3.0, though 2.0 had them: IFC file text and STL export; projection; loft; triangulation as a public call; curves other than lines, circles, arcs and polylines, such as the elliptical arc; and the 2.0 classes such as `Cuboid`, `Polygon`, `Opening` and `Vector3`. 3.0 has no spline, no ellipse and no elliptical arc. Build a wedge as a five-face `OG_PRIMITIVE_POLYHEDRON`, and a 2.0 `Curve` as an `OG_PRIMITIVE_POLYLINE` wire through its points.

## Installation

Expand Down Expand Up @@ -164,10 +164,10 @@ This section is a compact reference for writing OpenGeometry 3.0 code, by hand o
| Export | Call and parameters |
| --- | --- |
| `OpenGeometry.create` | `await OpenGeometry.create(input?, options?)`. `input`: `{ wasmURL?, wasmModule? }`. `options`: `{ workerURL?, tessellation?: 'worker' \| 'inline' }`. |
| `Wire` | `new Wire(kind, params, options?)`. `OG_PRIMITIVE_RECTANGLE` `{ width, breadth }`, `OG_PRIMITIVE_CIRCLE` `{ radius }`, `OG_PRIMITIVE_POLYLINE` `{ points, closed? }`. |
| `Wire` | `new Wire(kind, params, options?)`. `OG_PRIMITIVE_RECTANGLE` `{ width, breadth }`, `OG_PRIMITIVE_CIRCLE` `{ radius }`, `OG_PRIMITIVE_POLYLINE` `{ points, closed? }`, `OG_PRIMITIVE_REGULAR_POLYGON` `{ sides, radius }` (3 to 1024 corners on a circle about the `plane` origin, the first on the x direction), `OG_PRIMITIVE_SLOT` `{ length, width }` (the outline of `OG_PRIMITIVE_SLOT_PRISM`), `OG_PRIMITIVE_ROUNDED_RECTANGLE` `{ width, breadth, radius }` (a rectangle with rounded corners; `radius` below half the width and half the breadth). |
| Profile wire | `new Wire(OG_PRIMITIVE_PROFILE, { start, segments, closed }, options?)`. Points are `[u, v]` in `plane`; a segment is `{ to }` for a line or `{ to, arc: { center, counterClockwise } }` for an arc. A closed profile is an extrude profile or hole. |
| Arc wire | `new Wire(OG_PRIMITIVE_ARC, { radius, startAngle, sweepAngle }, options?)`. Angles in radians from the `plane` x direction, centred on the `plane` origin; the sweep is nonzero and less than one turn. |
| `Solid` | `new Solid(kind, params, options?)`. `OG_PRIMITIVE_CUBOID` `{ width, height, depth }`, `OG_PRIMITIVE_CYLINDER` `{ radius, height }`, `OG_PRIMITIVE_CYLINDER_SECTOR` `{ radius, height, startAngle, sweepAngle }` (radians from the `plane` x direction, counter-clockwise seen from the side the normal points to; sweep nonzero and less than one turn), `OG_PRIMITIVE_POLYHEDRON` `{ points, faces }` (planar faces as rings of point indices, counter-clockwise seen from outside), `OG_PRIMITIVE_SPHERE` `{ radius }` (centred on the `plane` origin), `OG_PRIMITIVE_CONE` `{ radiusBottom, radiusTop, height }` (standing on the `plane`; one radius may be zero, equal radii make a cylinder), `OG_PRIMITIVE_TORUS` `{ majorRadius, minorRadius }` (lying on the `plane`; minor below major), `OG_OPERATION_EXTRUDE` `{ profile, holes?, distance }`, `OG_OPERATION_SWEEP` `{ profile, path, caps? }`, `OG_OPERATION_REVOLVE` `{ profile, axis? }` (a full turn about `axis` `{ point: [u, v], direction: [du, dv] }` in the profile's `[u, v]`, by default its v axis); `profile`, `holes` and `path` are wires. |
| `Solid` | `new Solid(kind, params, options?)`. `OG_PRIMITIVE_CUBOID` `{ width, height, depth }`, `OG_PRIMITIVE_CYLINDER` `{ radius, height }`, `OG_PRIMITIVE_CYLINDER_SECTOR` `{ radius, height, startAngle, sweepAngle }` (radians from the `plane` x direction, counter-clockwise seen from the side the normal points to; sweep nonzero and less than one turn), `OG_PRIMITIVE_POLYHEDRON` `{ points, faces }` (planar faces as rings of point indices, counter-clockwise seen from outside), `OG_PRIMITIVE_SPHERE` `{ radius }` (centred on the `plane` origin), `OG_PRIMITIVE_CONE` `{ radiusBottom, radiusTop, height }` (standing on the `plane`; one radius may be zero, equal radii make a cylinder), `OG_PRIMITIVE_TORUS` `{ majorRadius, minorRadius }` (lying on the `plane`; minor below major), `OG_OPERATION_EXTRUDE` `{ profile, holes?, distance }`, `OG_OPERATION_SWEEP` `{ profile, path, caps? }`, `OG_OPERATION_REVOLVE` `{ profile, axis? }` (a full turn about `axis` `{ point: [u, v], direction: [du, dv] }` in the profile's `[u, v]`, by default its v axis), `OG_PRIMITIVE_SLOT_PRISM` `{ length, width, height }` (a stadium standing on the `plane`, centred on its origin; `length` between the arc centres along the x direction), `OG_PRIMITIVE_ROUNDED_BOX` `{ width, height, depth, radius }` (a cuboid with its four upright edges rounded; `radius` below half the width and half the depth), `OG_PRIMITIVE_PIPE_SEGMENT` `{ outerRadius, innerRadius, height, startAngle, sweepAngle }` (a ring sector placed and angled like the cylinder sector), `OG_PRIMITIVE_POLYSOLID` `{ path, width, height, justify? }` (a wall of constant width along `path`, a `{ start, segments, closed }` of straight legs and tangent arcs in the `plane`'s `[u, v]`, standing on the `plane` and rising along its normal; `justify` is `'centre'` (default), `'left'` or `'right'` of the path direction); `profile`, `holes` and `path` are wires. |
| `Sheet` | `new Sheet(OG_OPERATION_SWEEP, { profile, path, caps: false })`: an open-ended sweep, faces that enclose no volume. It shows its surface, from the front only, and its outline; `OpenGeometry.exportStep` refuses it. |
| Body options | `{ ogId?, parent?, appearance?, plane? }`. `plane` is `{ origin?, normal?, xDirection? }` and applies to primitives only; by default it is the ground plane through the origin, normal `[0, 1, 0]`, x direction `[1, 0, 0]`. |
| Booleans | `solid.operate(kind, { tools, instances? })` with `OG_OPERATION_SUBTRACT`, `OG_OPERATION_UNION` or `OG_OPERATION_INTERSECT`; `tools` is one to a hundred solids. |
Expand All @@ -189,7 +189,7 @@ This section is a compact reference for writing OpenGeometry 3.0 code, by hand o
| 2D offsets | `OpenGeometry.offsetRingVariable(ring, distances, holes?)` insets a closed ring by one distance per edge, each hole `{ ring, distances }` grown by its own; `OpenGeometry.offsetCurvedRingVariable(region, distances, holeDistances?)` insets one `CurvedRegion2D` of lines and arcs by one distance (>= 0) per edge, one list per hole, each arc kept on its centre at its own distance and refused when that distance passes the centre; `OpenGeometry.offsetPolylineRegions(path, width, closed, miterLimit?)` strokes a path. Both return `CurvedRegion2D[]` with exact arcs. `OpenGeometry.insetCurvedRegion2D(region, distance)` insets one `CurvedRegion2D` by a distance above zero, holes grown by the same, and returns `CurvedRegion2D[]` of exact lines and arcs: each arc keeps its centre and a reflex corner rounds to an arc of the distance; an inset past the half width is an empty list. `OpenGeometry.offsetPolyline(path, distance, { acuteThresholdDegrees?, bevel?, closed? })` offsets a path to one side and returns `{ edges, bevelled, closed }` (type `OffsetPath2D`). Rings and paths are flat `[x, y, z, ...]` lists; `y` is ignored. |
| `OGError` | Failures throw an `OGError` with `code` (for example `InvalidParameter`, `SharedShape`, `Disposed`), `call`, `message` and `details`. |
| Reset | `OpenGeometry.reset()` frees every body and leaves an empty document. |
| Typed parameters | `OG_PRIMITIVE_PARAMS_<KIND>(params)`, `OG_OPERATION_PARAMS_EXTRUDE(params)`, `OG_OPERATION_PARAMS_SWEEP(params)` and `OG_OPERATION_PARAMS_REVOLVE(params)` return their argument unchanged; they only give the object a type. |
| Typed parameters | `OG_PRIMITIVE_PARAMS_<KIND>(params)`, `OG_OPERATION_PARAMS_EXTRUDE(params)`, `OG_OPERATION_PARAMS_SWEEP(params)` and `OG_OPERATION_PARAMS_REVOLVE(params)` return their argument unchanged; they only give the object a type. The entry exports the parameter types too, such as `ProfileParams` and `PolysolidParams`. |

**Rules that are easy to get wrong.**

Expand Down Expand Up @@ -218,7 +218,7 @@ This section is a compact reference for writing OpenGeometry 3.0 code, by hand o
- Call `dispose()` on bodies and assemblies you no longer need.
- Catch `OGError` and branch on `code`. After a `'fatal'` event the runtime refuses every call until `OpenGeometry.reset()`.

**What does not exist.** IFC file text, STL and PDF export, projection, loft, public triangulation, curves other than lines, circles and arcs, wedges, and the 2.0 classes. Do not call them.
**What does not exist.** IFC file text, STL and PDF export, projection, loft, public triangulation, curves other than lines, circles, arcs and polylines, such as the elliptical arc, and the 2.0 classes. Do not call them. 3.0 has no spline, no ellipse and no elliptical arc. Build a wedge as a five-face `OG_PRIMITIVE_POLYHEDRON`, and a 2.0 `Curve` as an `OG_PRIMITIVE_POLYLINE` wire through its points.

**Where the truth is.** `index.d.ts` in the installed package lists every export and its types. The examples in [`main/opengeometry-three/examples-vite/`](./main/opengeometry-three/examples-vite/) are working 3.0 code, except that they import the built package by path (`../../../dist/index.js`) where an app imports from `'opengeometry'`.

Expand Down
105 changes: 105 additions & 0 deletions docs/api-coverage.json
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,41 @@
"kind": "type",
"page": "opengeometry/api/constants"
},
{
"export": "SlotPrismParams",
"kind": "type",
"page": "opengeometry/api/constants"
},
{
"export": "RoundedBoxParams",
"kind": "type",
"page": "opengeometry/api/constants"
},
{
"export": "PipeSegmentParams",
"kind": "type",
"page": "opengeometry/api/constants"
},
{
"export": "PolysolidParams",
"kind": "type",
"page": "opengeometry/api/constants"
},
{
"export": "RegularPolygonParams",
"kind": "type",
"page": "opengeometry/api/constants"
},
{
"export": "SlotParams",
"kind": "type",
"page": "opengeometry/api/constants"
},
{
"export": "RoundedRectangleParams",
"kind": "type",
"page": "opengeometry/api/constants"
},
{
"export": "CurvedRegion2D",
"kind": "type",
Expand Down Expand Up @@ -219,6 +254,41 @@
"kind": "value",
"page": "opengeometry/api/constants"
},
{
"export": "OG_PRIMITIVE_SLOT_PRISM",
"kind": "value",
"page": "opengeometry/api/constants"
},
{
"export": "OG_PRIMITIVE_ROUNDED_BOX",
"kind": "value",
"page": "opengeometry/api/constants"
},
{
"export": "OG_PRIMITIVE_PIPE_SEGMENT",
"kind": "value",
"page": "opengeometry/api/constants"
},
{
"export": "OG_PRIMITIVE_POLYSOLID",
"kind": "value",
"page": "opengeometry/api/constants"
},
{
"export": "OG_PRIMITIVE_REGULAR_POLYGON",
"kind": "value",
"page": "opengeometry/api/constants"
},
{
"export": "OG_PRIMITIVE_SLOT",
"kind": "value",
"page": "opengeometry/api/constants"
},
{
"export": "OG_PRIMITIVE_ROUNDED_RECTANGLE",
"kind": "value",
"page": "opengeometry/api/constants"
},
{
"export": "OG_PRIMITIVE_PARAMS_RECTANGLE",
"kind": "value",
Expand Down Expand Up @@ -279,6 +349,41 @@
"kind": "value",
"page": "opengeometry/api/constants"
},
{
"export": "OG_PRIMITIVE_PARAMS_SLOT_PRISM",
"kind": "value",
"page": "opengeometry/api/constants"
},
{
"export": "OG_PRIMITIVE_PARAMS_ROUNDED_BOX",
"kind": "value",
"page": "opengeometry/api/constants"
},
{
"export": "OG_PRIMITIVE_PARAMS_PIPE_SEGMENT",
"kind": "value",
"page": "opengeometry/api/constants"
},
{
"export": "OG_PRIMITIVE_PARAMS_POLYSOLID",
"kind": "value",
"page": "opengeometry/api/constants"
},
{
"export": "OG_PRIMITIVE_PARAMS_REGULAR_POLYGON",
"kind": "value",
"page": "opengeometry/api/constants"
},
{
"export": "OG_PRIMITIVE_PARAMS_SLOT",
"kind": "value",
"page": "opengeometry/api/constants"
},
{
"export": "OG_PRIMITIVE_PARAMS_ROUNDED_RECTANGLE",
"kind": "value",
"page": "opengeometry/api/constants"
},
{
"export": "OG_OPERATION_EXTRUDE",
"kind": "value",
Expand Down
Loading
Loading