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
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

OpenGeometry is an **open-source, browser-native CAD kernel**. The geometry engine is written in **Rust**, compiled to **WebAssembly**, and paired with a **Three.js-friendly TypeScript layer** so you can build real CAD tools that run in the browser.

OpenGeometry is best suited for **browser-based CAD, AEC/BIM, configurators, and geometry-heavy web tools**. Whether you're building a parametric modeler, a wall/opening workflow, a BIM viewer, or a custom Three.js modeling tool, OpenGeometry gives you deterministic, kernel-backed primitives and operations without leaving JavaScript.
OpenGeometry is best suited for **browser-based CAD, configurators, and geometry-heavy web tools**. Whether you're building a parametric modeler, a solid modeling workflow, a geometry viewer, or a custom Three.js modeling tool, OpenGeometry gives you deterministic, kernel-backed primitives and operations without leaving JavaScript.

It is the geometry engine layer, not a full CAD application. OpenPlans is a downstream application/toolkit built on top of OpenGeometry for AEC workflows. In this repository, OpenGeometry is the primary SDK and engine.

Expand All @@ -41,7 +41,7 @@ It is the geometry engine layer, not a full CAD application. OpenPlans is a down
Use OpenGeometry when you need:

- browser-based parametric modeling with Rust + WebAssembly performance
- wall/opening subtraction and other solid boolean workflows
- cutout subtraction and other solid boolean workflows
- polygon extrusion into solids for CAD or AEC modeling
- IFC, STEP, STL, and PDF-style export/projection in web apps
- a Three.js-friendly CAD kernel instead of ad hoc mesh math
Expand All @@ -61,7 +61,7 @@ Good examples include:

**Good fit**

- browser CAD, AEC/BIM, Mechanical, and geometry-heavy web applications
- browser CAD, mechanical design, and geometry-heavy web applications
- Three.js-based modeling tools that need a real kernel behind them
- AI first CAD frontends that need deterministic geometry execution in the browser

Expand Down Expand Up @@ -186,7 +186,7 @@ npm test

## Who is this for?

- Teams building **browser-based CAD/BIM/geometry tools**
- Teams building **browser-based CAD and geometry tools**
- Developers evaluating **WebAssembly-powered 3D** for the web
- Contributors interested in the **Rust → WASM geometry pipeline**
- Anyone exploring **open-source CAD kernel internals**
Expand Down
6 changes: 4 additions & 2 deletions developer.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ npm run build # Full pipeline: Rust → WASM → TS bundle → dist
npm test # Cargo unit + integration tests (no TypeScript tests yet)
```

`npm run build` runs `build-core` (wasm-pack + cargo release), `build-three` (Rollup),
and `prepare-dist` in order. Running them out of order produces stale `pkg/` and bundle
`npm run build` runs `build-core` (wasm-pack + cargo release), `build-three`
(clean `dist/`, then Rollup), and `prepare-dist` (copy WASM and package metadata) in
order. The clean step removes declarations for deleted sources before Rollup emits
new ones. Running the stages out of order produces stale `pkg/` and bundle
mismatches — see `.claude/skills/wasm-build-flow.md` if you hit that.

## Running the example app
Expand Down
26 changes: 13 additions & 13 deletions docs/api/shapes/analytic-solid.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: "Analytic solid"
description: "Render authoritative analytic primitives with chord-error tessellation."
---

`AnalyticSolid` constructs line-profile extrusions, cuboids, cylinders, spheres, cones, frusta, ring tori, circular-wall segments, coaxial circle lofts, and rectangular revolutions from analytic surfaces. Its required surface and curve geometry uses BRep schema version 2. Render triangles are generated from that geometry.
`AnalyticSolid` constructs line-profile extrusions, cuboids, cylinders, spheres, cones, frusta, ring tori, annular sector extrusions, coaxial circle lofts, and rectangular revolutions from analytic surfaces. Its required surface and curve geometry uses BRep schema version 2. Render triangles are generated from that geometry.

The public boolean helpers accept only `AnalyticSolid` operands and use the in-house analytic engine.
Schema-v1 and faceted operands are rejected; there is no mesh fallback.
Expand Down Expand Up @@ -45,31 +45,31 @@ const profile = new AnalyticSolid({

Dimensions must be finite and positive. A frustum may have a zero upper radius. Ring tori require `majorRadius > minorRadius > 0`.

Use `kind: "circularWall"` with centerline `radius`, `thickness`, `height`, `startAngle`, and signed `sweepAngle` in radians. The frame origin is the arc center at the wall's base. Radius must exceed half thickness; sweep must be nonzero and smaller than a full turn. Negative sweep retains the authored start/end identity.
Use `kind: "annularSectorExtrusion"` with reference `radius`, `thickness`, `height`, `startAngle`, and signed `sweepAngle` in radians. The frame origin is the arc center at the extrusion base. Radius must exceed half thickness; sweep must be nonzero and smaller than a full turn. Negative sweep retains the authored start/end identity.

`kind: "circularWallWithOpenings"` adds a required `openings` array. Each opening supplies `id`, center `angle`, tangent `width`, `bottom`, and `height`. Interior openings retain exact inner/outer cylinder trim holes plus planar sill, header, and jamb faces with cut ancestry. Set `bottom: 0` for a door: the cylinder trims follow the bottom notch, the remaining bottom regions are split exactly, and the cut contains a header and two jambs without an inset. Openings must remain strictly inside the authored wall ends and leave resolved material above the head.
`kind: "annularSectorExtrusionWithOpenings"` adds a required `openings` array. Each opening supplies `id`, center `angle`, tangent `width`, `bottom`, and `height`. Interior openings retain exact inner/outer cylinder trim holes plus planar lower, upper, and lateral cut faces with source ancestry. Set `bottom: 0` for a bottom-reaching opening: the cylinder trims follow the bottom notch, the remaining bottom regions are split exactly, and the cut contains an upper face and two lateral faces without an inset. Openings must remain strictly inside the authored sweep ends and leave resolved material above the head.

```ts
const wall = new AnalyticSolid({
kind: "circularWallWithOpenings",
const sector = new AnalyticSolid({
kind: "annularSectorExtrusionWithOpenings",
radius: 3,
thickness: 0.3,
height: 3,
startAngle: 0,
sweepAngle: Math.PI / 2,
openings: [{ id: "window-1", angle: 0.8, width: 0.9, bottom: 0.9, height: 1.2 }],
openings: [{ id: "aperture-1", angle: 0.8, width: 0.9, bottom: 0.9, height: 1.2 }],
});
```

Use `kind: "circularWallWithArchedOpening"` for one arched opening on a circular wall.
Use `kind: "annularSectorExtrusionWithArchedOpening"` for one arched opening on an annular sector extrusion.
Its `opening` has the same fields. `height` is the total opening height and must exceed
`width / 2`. The lower jamb region is exact circular-wall trimming; the header is a cylindrical
face bounded by corrected intersection curves on the inner and outer wall supports.
`width / 2`. The lower cut region uses exact annular-sector trimming; the arch cap is a cylindrical
face bounded by corrected intersection curves on the inner and outer cylindrical supports.

Use `kind: "straightWallWithArchedOpening"` with wall `width`, `depth`, and `height`, plus
Use `kind: "boxWithArchedOpening"` with box `width`, `depth`, and `height`, plus
`opening: { id, station, width, bottom, height }`. It constructs the opening directly with two
shared semicircle edges and a cylindrical header face. The opening must remain strictly inside the
wall ends and top. These arched forms avoid overlapping cutter booleans and remain authoritative
shared semicircle edges and a cylindrical arch-cap face. The opening must remain strictly inside the
box ends and top. These arched forms avoid overlapping cutter booleans and remain authoritative
when retessellated.

`solid.shell(thickness, options?)` offsets inward and returns a closed analytic shell for canonical cuboids, cylinders, spheres, cones, frusta, ring tori, and straight-edge line-profile extrusions. It builds an oriented cavity shell, retains the source face mapping, and includes the solid's complete world placement. Cone offsets move the cavity apex by the true normal offset; frustum offsets trim both caps and retain the authored semi-angle. Profile offsets intersect neighboring offset planes at exact miter vertices and expand authored holes. Thickness must leave a resolved positive interior in every offset dimension; collapsing, reversing, or self-intersecting offsets return `UnresolvedIntersection`. Already-composite solids return `CoverageGap`.
Expand Down Expand Up @@ -106,7 +106,7 @@ Call `solid.dispose()` when you remove it permanently.

## STEP export and diagnostics

`solid.exportStep("metre")` returns `{ text, report }` directly from v2 surfaces, shared curves and oriented edge uses. It supports all five target surface families, frusta, circular walls and the current sphere and aligned-cuboid boolean results, including cavities. It does not require a viewport mesh or facet regrouping.
`solid.exportStep("metre")` returns `{ text, report }` directly from v2 surfaces, shared curves and oriented edge uses. It supports all five target surface families, frusta, annular sector extrusions and the current sphere and aligned-cuboid boolean results, including cavities. It does not require a viewport mesh or facet regrouping.

Authored coordinates are interpreted as metres. Pass `"millimetre"` to convert coordinates and dimensions once and emit the corresponding unit context. Export applies the complete Three.js world placement once, including positive uniform scale. `getWorldBrepSerialized()` returns the corresponding world model; `getBrepSerialized()` retains local geometry. Retessellation does not alter export text.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ <h3>Export authored geometry</h3>
<p
class="og-control-summary">Shared analytic surfaces, curves and oriented edge uses go directly to STEP. Display deflection never changes the exported model. Coordinates are authored in metres.</p>
<label
class="og-control-row">Body <select id="body" aria-label="Body"><option value="cuboid">Cuboid</option><option value="cylinder">Cylinder</option><option value="sphere">Sphere</option><option value="cone">Cone</option><option value="frustum">Frustum</option><option value="torus">Ring torus</option><option value="circularWall">Circular wall</option><option value="cut">Sphere subtraction</option><option value="cavity">Sphere cavity</option></select></label>
class="og-control-row">Body <select id="body" aria-label="Body"><option value="cuboid">Cuboid</option><option value="cylinder">Cylinder</option><option value="sphere">Sphere</option><option value="cone">Cone</option><option value="frustum">Frustum</option><option value="torus">Ring torus</option><option value="annularSectorExtrusion">Circular wall</option><option value="cut">Sphere subtraction</option><option value="cavity">Sphere cavity</option></select></label>
<label
class="og-control-row">STEP length unit <select id="unit" aria-label="STEP length unit"><option value="metre">Metre</option><option value="millimetre">Millimetre</option></select></label>
<label
Expand Down Expand Up @@ -97,8 +97,8 @@ <h3>Export authored geometry</h3>
minorRadius: 0.4,
frame: frame(0.4),
},
circularWall: {
kind: "circularWall",
annularSectorExtrusion: {
kind: "annularSectorExtrusion",
radius: 2,
thickness: 0.3,
height: 1.5,
Expand Down
Loading
Loading