opengeometry 2.0.17 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/LICENSE.md +373 -0
  2. package/README.md +187 -128
  3. package/body-registry-MbAD6Hyq.js +3159 -0
  4. package/body-registry-MbAD6Hyq.js.map +1 -0
  5. package/index.d.ts +18 -115
  6. package/index.js +1170 -11687
  7. package/index.js.map +1 -1
  8. package/opengeometry/pkg/opengeometry.d.ts +144 -1304
  9. package/opengeometry/pkg/opengeometry.js +1316 -5803
  10. package/opengeometry/pkg/opengeometry_bg.wasm +0 -0
  11. package/opengeometry/pkg/opengeometry_bg.wasm.d.ts +62 -458
  12. package/opengeometry_bg.wasm +0 -0
  13. package/opengeometry_bg.wasm.d.ts +62 -458
  14. package/package.json +54 -34
  15. package/src/bodies/body-factory.d.ts +3 -0
  16. package/src/bodies/body-options.d.ts +19 -0
  17. package/src/bodies/body-placement.d.ts +10 -0
  18. package/src/bodies/body-registry.d.ts +3 -0
  19. package/src/bodies/body.d.ts +71 -0
  20. package/src/bodies/display-clone.d.ts +10 -0
  21. package/src/bodies/node-methods.d.ts +30 -0
  22. package/src/bodies/sheet.d.ts +14 -0
  23. package/src/bodies/solid.d.ts +23 -0
  24. package/src/bodies/system-assembly.d.ts +26 -0
  25. package/src/bodies/wire.d.ts +14 -0
  26. package/src/constants/index.d.ts +4 -0
  27. package/src/constants/operations.d.ts +58 -0
  28. package/src/constants/primitives.d.ts +69 -0
  29. package/src/constants/regions.d.ts +1 -0
  30. package/src/constants/transforms.d.ts +4 -0
  31. package/src/dto/boolean-report.d.ts +24 -0
  32. package/src/dto/bounds.d.ts +1 -0
  33. package/src/dto/brep.d.ts +99 -0
  34. package/src/dto/change-set.d.ts +13 -0
  35. package/src/dto/creation.d.ts +3 -0
  36. package/src/dto/display-buffers.d.ts +14 -0
  37. package/src/dto/events.d.ts +2 -0
  38. package/src/{export/analytic-ifc.d.ts → dto/ifc-body.d.ts} +16 -18
  39. package/src/dto/mark-stats.d.ts +4 -0
  40. package/src/dto/measure.d.ts +16 -0
  41. package/src/dto/mirror.d.ts +4 -0
  42. package/src/dto/node-info.d.ts +11 -0
  43. package/src/dto/pick-result.d.ts +6 -0
  44. package/src/dto/placement.d.ts +6 -0
  45. package/src/dto/primitives.d.ts +77 -0
  46. package/src/dto/regions.d.ts +42 -0
  47. package/src/dto/step-export.d.ts +42 -0
  48. package/src/errors.d.ts +20 -0
  49. package/src/export/export-step.d.ts +10 -0
  50. package/src/export/ifc-body.d.ts +4 -0
  51. package/src/kernel/kernel-errors.d.ts +5 -0
  52. package/src/kernel/kernel-loader.d.ts +5 -0
  53. package/src/kernel/kernel-session.d.ts +2 -0
  54. package/src/limits.d.ts +12 -0
  55. package/src/marks/limbo.d.ts +6 -0
  56. package/src/marks/og-mark.d.ts +10 -0
  57. package/src/marks/transaction.d.ts +3 -0
  58. package/src/opengeometry.d.ts +69 -0
  59. package/src/operations/offsets.d.ts +5 -0
  60. package/src/operations/regions.d.ts +4 -0
  61. package/src/picking/pick-targets.d.ts +6 -0
  62. package/src/picking/resolve-hit.d.ts +3 -0
  63. package/src/rendering/deferred.d.ts +7 -0
  64. package/src/rendering/geometry/geometry-scheduler.d.ts +12 -0
  65. package/src/rendering/geometry/host-group.d.ts +10 -0
  66. package/src/rendering/geometry/render-pass.d.ts +8 -0
  67. package/src/rendering/geometry/settle.d.ts +10 -0
  68. package/src/rendering/inline-backend.d.ts +14 -0
  69. package/src/rendering/lod/body-size.d.ts +11 -0
  70. package/src/rendering/lod/camera-observer.d.ts +2 -0
  71. package/src/rendering/lod/deflection.d.ts +2 -0
  72. package/src/rendering/lod/display-bounds.d.ts +4 -0
  73. package/src/rendering/lod/displayed.d.ts +7 -0
  74. package/src/rendering/lod/host-drawn.d.ts +5 -0
  75. package/src/rendering/lod/host-groups.d.ts +28 -0
  76. package/src/rendering/lod/lod-controller.d.ts +75 -0
  77. package/src/rendering/lod/screen-metrics.d.ts +2 -0
  78. package/src/rendering/materials/material-pool.d.ts +12 -0
  79. package/src/rendering/materials/ref-counted-pool.d.ts +12 -0
  80. package/src/rendering/provider.d.ts +19 -0
  81. package/src/rendering/records/geometry-record.d.ts +21 -0
  82. package/src/rendering/records/record-pool.d.ts +29 -0
  83. package/src/rendering/records/validate-display-buffers.d.ts +2 -0
  84. package/src/rendering/tessellation-worker.d.ts +1 -0
  85. package/src/rendering/worker/job-queue.d.ts +8 -0
  86. package/src/rendering/worker/message-guards.d.ts +9 -0
  87. package/src/rendering/worker/snapshot-cache.d.ts +10 -0
  88. package/src/rendering/worker-backend.d.ts +44 -0
  89. package/src/rendering/worker-protocol.d.ts +52 -0
  90. package/src/runtime/create-runtime.d.ts +7 -0
  91. package/src/runtime/event-bus.d.ts +3 -0
  92. package/src/runtime/reset.d.ts +1 -0
  93. package/src/runtime/runtime-state.d.ts +68 -0
  94. package/src/testing/internals.d.ts +18 -0
  95. package/src/world-graph/codec.d.ts +45 -0
  96. package/src/world-graph/world-graph-client.d.ts +13 -0
  97. package/tessellation-worker.js +634 -0
  98. package/tessellation-worker.js.map +1 -0
  99. package/testing.d.ts +1 -0
  100. package/testing.js +87 -0
  101. package/testing.js.map +1 -0
  102. package/analytic-worker.js +0 -90
  103. package/src/base-types.d.ts +0 -13
  104. package/src/editor/freeform.d.ts +0 -91
  105. package/src/editor/index.d.ts +0 -6
  106. package/src/editor/parametric.d.ts +0 -15
  107. package/src/editor/types.d.ts +0 -223
  108. package/src/examples/booleans.d.ts +0 -24
  109. package/src/examples/editor-modes.d.ts +0 -20
  110. package/src/examples/index.d.ts +0 -11
  111. package/src/examples/offset-ring-variable.d.ts +0 -13
  112. package/src/examples/offset.d.ts +0 -18
  113. package/src/examples/primitives.d.ts +0 -16
  114. package/src/examples/ribbon-from-offsets.d.ts +0 -33
  115. package/src/examples/shapes.d.ts +0 -20
  116. package/src/examples/sweep.d.ts +0 -9
  117. package/src/freeform/geometry.d.ts +0 -82
  118. package/src/freeform/index.d.ts +0 -5
  119. package/src/freeform/types.d.ts +0 -36
  120. package/src/markup/spotMarker.d.ts +0 -4
  121. package/src/operations/analytic-errors.d.ts +0 -8
  122. package/src/operations/boolean-regions.d.ts +0 -20
  123. package/src/operations/boolean.d.ts +0 -16
  124. package/src/operations/editor/freeform.d.ts +0 -1
  125. package/src/operations/editor/index.d.ts +0 -1
  126. package/src/operations/editor/parametric.d.ts +0 -1
  127. package/src/operations/editor/types.d.ts +0 -1
  128. package/src/operations/extrude.d.ts +0 -9
  129. package/src/operations/index.d.ts +0 -9
  130. package/src/operations/loft.d.ts +0 -13
  131. package/src/operations/offset-regions.d.ts +0 -76
  132. package/src/primitives/analytic-curve.d.ts +0 -42
  133. package/src/primitives/arc.d.ts +0 -36
  134. package/src/primitives/curve.d.ts +0 -64
  135. package/src/primitives/elliptical_arc.d.ts +0 -38
  136. package/src/primitives/index.d.ts +0 -9
  137. package/src/primitives/line.d.ts +0 -77
  138. package/src/primitives/polyline.d.ts +0 -78
  139. package/src/primitives/rectangle.d.ts +0 -72
  140. package/src/rendering/analytic-lod.d.ts +0 -32
  141. package/src/rendering/analytic-tessellation.d.ts +0 -32
  142. package/src/shapes/analytic-pattern.d.ts +0 -36
  143. package/src/shapes/analytic-solid.d.ts +0 -304
  144. package/src/shapes/cuboid.d.ts +0 -62
  145. package/src/shapes/cylinder.d.ts +0 -36
  146. package/src/shapes/index.d.ts +0 -11
  147. package/src/shapes/opening.d.ts +0 -31
  148. package/src/shapes/outline-utils.d.ts +0 -35
  149. package/src/shapes/polygon.d.ts +0 -102
  150. package/src/shapes/solid.d.ts +0 -108
  151. package/src/shapes/sphere.d.ts +0 -27
  152. package/src/shapes/sweep.d.ts +0 -76
  153. package/src/shapes/wedge.d.ts +0 -75
  154. package/src/utils/event.d.ts +0 -29
  155. package/src/utils/randomizer.d.ts +0 -1
  156. package/src/world/world-graph.d.ts +0 -112
package/README.md CHANGED
@@ -1,13 +1,16 @@
1
1
  <p align="center">
2
- <a href="https://opengeometry.io?utm_source=github">
3
- <img src="https://raw.githubusercontent.com/OpenGeometry-io/.github/main/profile/opengeometryTextLogo.png" alt="OpenGeometry" />
2
+ <a href="https://opengeometry.io?utm_source=npm">
3
+ <picture>
4
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/OpenGeometry-io/OpenGeometry/main/docs/logo/logo-dark.png" />
5
+ <img src="https://raw.githubusercontent.com/OpenGeometry-io/OpenGeometry/main/docs/logo/logo-light.png" alt="OpenGeometry" width="420" />
6
+ </picture>
4
7
  </a>
5
8
  </p>
6
9
 
7
10
  <h1 align="center">OpenGeometry</h1>
8
11
 
9
12
  <p align="center">
10
- <strong>Browser-native CAD kernel for Web Apps and AI CAD built with Rust, WebAssembly, and Three.js.</strong>
13
+ <strong>Open-source CAD kernel for the web: exact B-rep solids, booleans, extrude, sweep and revolve, and STEP export, in Rust and WebAssembly with a TypeScript SDK for Three.js. For product configurators, mechanical parts, buildings, robotics and AI agents that model.</strong>
11
14
  </p>
12
15
 
13
16
  <p align="center">
@@ -19,179 +22,237 @@
19
22
  </p>
20
23
 
21
24
  <p align="center">
22
- <a href="https://opengeometry.io?utm_source=github">Website</a> · <a href="https://docs.opengeometry.io/OpenGeometry?utm_source=github">Documentation</a> · <a href="https://demos.opengeometry.io?utm_source=github">Live Demos</a> · <a href="https://blog.opengeometry.io?utm_source=github">Blog</a> · <a href="https://www.npmjs.com/package/opengeometry">npm</a>
25
+ <a href="https://opengeometry.io?utm_source=npm">Website</a> · <a href="https://docs.opengeometry.io?utm_source=npm">Documentation</a> · <a href="https://demos.opengeometry.io?utm_source=npm">Live Demos</a> · <a href="https://blog.opengeometry.io?utm_source=npm">Blog</a> · <a href="https://www.npmjs.com/package/opengeometry">npm</a>
23
26
  </p>
24
27
 
25
28
  ---
26
29
 
27
- > **Actively maintained and growing.** We're building OpenGeometry in the open. APIs, examples, and package structure are evolving, we are actively improving and expanding the project. Star the repo to follow along. If you have questions or want to get involved, join the [Discord](https://discord.com/invite/9wJpbfgGGA) or check out the [issues](https://github.com/OpenGeometry-io/OpenGeometry/issues)
30
+ > **Actively maintained and growing.** We're building OpenGeometry in the open. APIs, examples, and package structure are evolving, and we are actively improving and expanding the project. Star the repo to follow along. If you have questions or want to get involved, join the [Discord](https://discord.com/invite/9wJpbfgGGA) or check out the [issues](https://github.com/OpenGeometry-io/OpenGeometry/issues).
31
+
32
+ > **Version note.** This README describes OpenGeometry 3.0.0. Check which line you have installed with `npm ls opengeometry`: the 2.0 line has a different API. The documentation at [docs.opengeometry.io](https://docs.opengeometry.io?utm_source=npm) describes 3.0.
28
33
 
29
34
  ---
30
35
 
31
36
  ## What is OpenGeometry?
32
37
 
33
- 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.
34
-
35
- 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.
36
-
37
- 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.
38
-
39
- ## When to use OpenGeometry
40
-
41
- Use OpenGeometry when you need:
38
+ OpenGeometry is an **open-source CAD kernel for the web**. It models **B-rep solids** with exact planes, cylinders, spheres, cones and tori, runs **boolean operations** (union, subtract, intersect), builds solids by **extrude, sweep and revolve**, hollows them with **shell**, and writes **STEP** files that other CAD and CAM tools open. The kernel is written in **Rust** and compiled to **WebAssembly**. A **TypeScript SDK for Three.js** puts every body straight into your scene, and the same calls run in **Node.js** with no browser.
42
39
 
43
- - browser-based parametric modeling with Rust + WebAssembly performance
44
- - cutout subtraction and other solid boolean workflows
45
- - polygon extrusion into solids for CAD or AEC modeling
46
- - IFC, STEP, STL, and PDF-style export/projection in web apps
47
- - a Three.js-friendly CAD kernel instead of ad hoc mesh math
48
- - a deterministic geometry engine behind AI-assisted CAD or design workflows
40
+ It is the geometry engine, not a CAD application: you build the product, OpenGeometry does the solid modelling. The same calls give the same shape every time, so an app, a script or an AI agent can drive it and check the result with exact queries: volume, area, bounds, validity, and whether a point is inside.
49
41
 
50
- ## Why it works well for AI-powered CAD apps
42
+ ## Use cases
51
43
 
52
- OpenGeometry is a good fit for **AI-assisted CAD apps** because the kernel layer stays explicit and deterministic. An AI copilot or agent can suggest modeling steps, generate profiles, or orchestrate edits, while OpenGeometry executes the actual geometry operations, booleans, projections, and exports in a predictable browser runtime.
44
+ | Field | What you build | What OpenGeometry gives you |
45
+ | --- | --- | --- |
46
+ | **Product configurators and e-commerce** | A shopper picks sizes and options and sees the exact part, then orders it | Parametric primitives that `rebuild` in place, booleans for cut-outs, STEP for the factory |
47
+ | **Mechanical parts and enclosures** | Plates, brackets, housings, flanges, pipe parts | Rounded boxes, slots, cylinders, pipe segments, through-holes in one call, shell for walls, STEP in millimetres |
48
+ | **Manufacturing and fabrication** | Web tools that turn an order into a production file | Exact B-rep, valid and closed solids, STEP export with an export report |
49
+ | **Architecture, construction and interiors** | Walls, openings, slabs, furniture, MEP parts | Polysolid walls along a path, extrude with holes, sweeps along arcs, the IFC exchange body for an IFC writer |
50
+ | **Robotics and automation** | Fixtures, grippers, end-of-arm tools, work-cell layouts | Assemblies with placements, point-inside tests, measured volume, picking down to face and edge |
51
+ | **AI agents and prompt-to-CAD** | An agent that turns a request into a part, then checks it | Plain JSON parameters, deterministic results, `validity()` and `measure()` to verify, typed errors with a `code` |
52
+ | **Education and geometry tools** | Teaching solids, booleans and B-rep in a browser tab | Open source, runs client-side, the B-rep of every body is readable |
53
+ | **Server-side generation** | A Node.js service that makes STEP files from parameters | The same API in Node, with inline tessellation and no browser |
53
54
 
54
- Good examples include:
55
+ Floorkit, a toolkit for building design, is one application built on OpenGeometry.
55
56
 
56
- - AI copilots that translate user intent into concrete modeling operations
57
- - prompt-to-geometry or agent-driven editing flows inside browser CAD tools
58
- - AI first design interfaces that still need reliable extrusion, boolean, projection, and export workflows
57
+ ## Features
59
58
 
60
- ## Good fit / Not the right fit
59
+ | Area | What 3.0 has |
60
+ | --- | --- |
61
+ | **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. |
62
+ | **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. |
63
+ | **Parametric edits** | `rebuild` gives an existing body new parameters in place. `mirror` rebuilds a body as its reflection across a plane. |
64
+ | **Assemblies** | Assemblies with parent and child placement; translate, rotate, scale and place; independent copies and shared instances. |
65
+ | **History** | Marks with rollback and release; transactions, with a dry-run option. |
66
+ | **Display for Three.js** | Every body is a `THREE.Group`. Level of detail that follows the camera, tessellation in a web worker or inline, picking down to face and edge, outlines, colour and opacity. |
67
+ | **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. |
68
+ | **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. |
61
69
 
62
- **Good fit**
70
+ 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.
63
71
 
64
- - browser CAD, mechanical design, and geometry-heavy web applications
65
- - Three.js-based modeling tools that need a real kernel behind them
66
- - AI first CAD frontends that need deterministic geometry execution in the browser
72
+ ## Installation
67
73
 
68
- **Not the default fit**
74
+ ```bash
75
+ npm install opengeometry three
76
+ ```
69
77
 
70
- - desktop-native CAD products instead of an embeddable web SDK
71
- - non-browser runtimes with no WebAssembly or browser delivery story
72
- - pure visualization-only apps where raw Three.js is enough and kernel-backed modeling is unnecessary
78
+ - `three` is a peer dependency: versions `>=0.168.0 <0.185.0` are supported.
79
+ - The package is ES modules only, and its TypeScript types are included.
80
+ - The package ships `opengeometry_bg.wasm` (the kernel) and `tessellation-worker.js` (the display worker), and your page must be able to fetch both. With no arguments, `OpenGeometry.create()` looks for them next to the package's own `index.js`. If your bundler moves or rewrites `index.js` without the two files, that lookup fails, so the dependable way is the one the quick start uses: copy both files from `node_modules/opengeometry/` into the folder your site serves at its root (in Vite, the `public/` folder by default) and pass their URLs to `create`.
73
81
 
74
- ## AI and Coding Agent Entrypoints
82
+ ## Quick start
75
83
 
76
- If you are using ChatGPT, Claude, Gemini, Copilot, or other coding agents on this repository, start here:
84
+ ```ts
85
+ import * as THREE from 'three';
86
+ import {
87
+ OpenGeometry, Solid,
88
+ OG_OPERATION_SUBTRACT, OG_PRIMITIVE_CYLINDER, OG_PRIMITIVE_ROUNDED_BOX, OG_TRANSFORM_TRANSLATE,
89
+ } from 'opengeometry';
90
+
91
+ await OpenGeometry.create({ wasmURL: '/opengeometry_bg.wasm' }, { workerURL: '/tessellation-worker.js' });
92
+
93
+ const plate = new Solid(OG_PRIMITIVE_ROUNDED_BOX, { width: 0.12, height: 0.01, depth: 0.08, radius: 0.01 });
94
+ const holes = [[-0.045, -0.025], [0.045, -0.025], [-0.045, 0.025], [0.045, 0.025]].map(([x, z]) => {
95
+ const hole = new Solid(OG_PRIMITIVE_CYLINDER, { radius: 0.004, height: 0.02 });
96
+ hole.transform(OG_TRANSFORM_TRANSLATE, { offset: [x, -0.005, z] });
97
+ return hole;
98
+ });
99
+ plate.operate(OG_OPERATION_SUBTRACT, { tools: holes });
100
+
101
+ const scene = new THREE.Scene();
102
+ scene.add(new THREE.HemisphereLight(0xffffff, 0x444444, 2), plate);
103
+ const camera = new THREE.PerspectiveCamera(50, innerWidth / innerHeight, 0.001, 10);
104
+ camera.position.set(0.12, 0.1, 0.14);
105
+ camera.lookAt(0, 0, 0);
106
+ const renderer = new THREE.WebGLRenderer({ antialias: true });
107
+ renderer.setSize(innerWidth, innerHeight);
108
+ document.body.append(renderer.domElement);
109
+ renderer.setAnimationLoop(() => renderer.render(scene, camera));
110
+
111
+ const { text, report } = await OpenGeometry.exportStep({ nodes: [plate], unit: 'millimetre', upAxis: 'Z' });
112
+ ```
77
113
 
78
- - [AGENTS.md](./AGENTS.md) - single source of truth for all coding agents (architecture, commands, gotchas, behavioral rules)
79
- - [README.md](./README.md) - product overview, positioning, and quick start
80
- - [Quickstart](https://docs.opengeometry.io/OpenGeometry/quickstart)
81
- - [Installation](https://docs.opengeometry.io/OpenGeometry/installation)
82
- - [Boolean operations](https://docs.opengeometry.io/OpenGeometry/concepts/booleans)
83
- - [Extrude](https://docs.opengeometry.io/OpenGeometry/api/operations/extrude)
114
+ This loads the kernel and makes a 120 mm by 80 mm mounting plate, 10 mm thick, with rounded corners (model units are metres). It drills four 8 mm bolt holes through the plate with one boolean call: the four cylinders are the tools. The plate is a `THREE.Group`, so it goes into the scene like any other object and is drawn on every frame. The last line writes the plate as a STEP file in millimetres, ready for a CAD or CAM tool: `text` is the file and `report` counts what was written.
84
115
 
85
- ### What you can do today
116
+ The two URLs assume both files were copied to the site root, as described under Installation. The block uses top-level `await`, so it must run as a module. If your build rejects top-level `await`, raise its target (the examples set Vite's `build.target` to `'esnext'`) or move the code after the imports into an `async` function and call it.
86
117
 
87
- | Category | Capabilities |
88
- | --- | --- |
89
- | **Primitives** | Lines, arcs, curves, polylines, rectangles |
90
- | **Shapes** | Polygons, solids, cuboids, cylinders, spheres, wedges, sweeps, openings |
91
- | **Operations** | Triangulation, extrusion, sweep, offset, boolean operations |
92
- | **Exports** | STL, STEP, IFC, PDF projection (PDF is currently native/Node-only — browser PDF is on the roadmap) |
93
- | **Integration** | Three.js scene management, WebAssembly-powered performance |
118
+ Runnable examples live in [`main/opengeometry-three/examples-vite/`](https://github.com/OpenGeometry-io/OpenGeometry/tree/main/main/opengeometry-three/examples-vite/). Shapes: cuboid, cylinder, slot prism, rounded box, pipe segment, polysolid wall, the regular polygon, slot and rounded rectangle wires, and a rounded section. Operations: booleans, an opening, a sweep, a sweep along an arc path, a curved profile united with a straight one, and STEP export. From a clone, run `npm --prefix main ci`, `npm run build` and then `npm run dev-example`.
94
119
 
95
120
  ## Demos
96
121
 
97
- See OpenGeometry in action — interactive, browser-based demos showcasing the kernel's capabilities:
122
+ Interactive demos run the kernel in your browser, with nothing to install: **[demos.opengeometry.io](https://demos.opengeometry.io?utm_source=npm)**.
98
123
 
99
- **[demos.opengeometry.io](https://demos.opengeometry.io)**
124
+ ## When not to use it
100
125
 
101
- Demos include primitives rendering, shape generation, sweep operations, boolean operations, file exports, and more. All running client-side via WebAssembly.
126
+ - You need a desktop CAD application. OpenGeometry is a library you embed.
127
+ - You only show meshes you already have. Plain Three.js is enough.
128
+ - You need splines, ellipses, lofts, fillets or STL export. 3.0 does not have them.
102
129
 
103
- ## Quick Start
130
+ ## For AI agents and coding assistants
104
131
 
105
- Install from npm:
132
+ OpenGeometry is built to be driven by code, including code an agent writes. Every call takes plain parameters, gives the same shape for the same input, and can be checked with `validity()`, `measure()`, `getBounds()` and `classifyPoint()`.
106
133
 
107
- ```bash
108
- npm install opengeometry
109
- ```
134
+ - **[llms.txt](https://docs.opengeometry.io/llms.txt)**: an index of every documentation page, in Markdown, for a model's context.
135
+ - **[Use a coding agent](https://docs.opengeometry.io/opengeometry/agents)**: the 3.0 rules that agents get wrong most often, and the sources to trust.
136
+ - **`index.d.ts`** in the installed package: every export and its types.
137
+ - The reference below: the whole public surface on one page.
110
138
 
111
- A practical browser deployment looks like this: install `opengeometry` from npm, serve `opengeometry_bg.wasm` from your app, then initialize the runtime once with `OpenGeometry.create({ wasmURL })` before creating `Vector3` values or kernel-backed wrappers.
139
+ ### API reference on one page
112
140
 
113
- ```ts
114
- import { Cuboid, OpenGeometry, Vector3 } from "opengeometry";
141
+ This is a compact reference for writing OpenGeometry 3.0 code, by hand or with a coding assistant.
115
142
 
116
- await OpenGeometry.create({
117
- wasmURL: new URL(
118
- "node_modules/opengeometry/opengeometry_bg.wasm",
119
- import.meta.url
120
- ).href,
121
- });
143
+ **Package.** `opengeometry` on npm. ES modules only, types included, peer dependency `three` `>=0.168.0 <0.185.0`.
122
144
 
123
- // Initialize once before constructing Vector3 or any wrapper.
124
- const cuboid = new Cuboid({
125
- center: new Vector3(0, 0, 0),
126
- width: 2,
127
- height: 1,
128
- depth: 1,
129
- color: 0x33aa66,
130
- });
145
+ **Which line is installed.** The 3.0 entry exports `OpenGeometry.create`, `Solid` and `Wire`. Code that uses `Cuboid`, `Vector3` or `setPlacement` is written for 2.0 and does not work with 3.0. The `version` in `node_modules/opengeometry/package.json` settles it.
131
146
 
132
- // Placement is strict: scale must be positive + uniform.
133
- cuboid.setPlacement({
134
- translation: new Vector3(1, 0, 0),
135
- rotation: new Vector3(0, 0.25, 0),
136
- scale: new Vector3(1.25, 1.25, 1.25),
137
- });
138
- ```
147
+ **The whole public surface.** The entry exports `OpenGeometry`, `Solid`, `Sheet`, `Wire`, `SystemAssembly`, `OGMark`, `OGError` and the `OG_*` constants. Every point and vector is `[x, y, z]`. Model units are metres, and Y is up.
139
148
 
140
- Scenegraph behavior is snapshot-based: `add*ToScene` captures geometry at insert time. If you change placement/config later, push updates explicitly via `replaceBrepEntityInScene` or `refreshBrepEntityInScene`.
141
-
142
- For a complete walkthrough, see the [Quick Start guide](https://docs.opengeometry.io/OpenGeometry/quickstart) or clone the [quickstart-js](https://github.com/OpenGeometry-io/quickstart-js) repo.
149
+ | Export | Call and parameters |
150
+ | --- | --- |
151
+ | `OpenGeometry.create` | `await OpenGeometry.create(input?, options?)`. `input`: `{ wasmURL?, wasmModule? }`. `options`: `{ workerURL?, tessellation?: 'worker' \| 'inline' }`. |
152
+ | `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). |
153
+ | 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. |
154
+ | 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. |
155
+ | `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. |
156
+ | `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. |
157
+ | 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]`. |
158
+ | Booleans | `solid.operate(kind, { tools, instances? })` with `OG_OPERATION_SUBTRACT`, `OG_OPERATION_UNION` or `OG_OPERATION_INTERSECT`; `tools` is one to a hundred solids. |
159
+ | Shell | `solid.operate(OG_OPERATION_SHELL, { thickness, instances? })` hollows the solid in place and leaves walls `thickness` thick inside every face. |
160
+ | Transforms | `node.transform(kind, params)` on a body or an assembly: `OG_TRANSFORM_TRANSLATE` `{ offset }`, `OG_TRANSFORM_ROTATE` `{ axis, degrees, pivot? }`, `OG_TRANSFORM_SCALE` `{ factor, pivot? }`, `OG_TRANSFORM_PLACE` `{ origin?, xDirection?, normal?, scale? }`. `getPlacement()` and `getWorldPlacement()` return `{ origin, xDirection, normal, scale }`. |
161
+ | Edits | `body.rebuild(kind, params, { instances? })` with the kinds and parameters above; a wire stays a wire and a solid a solid. |
162
+ | Mirror | `body.mirror({ origin, normal }, { instances? })` rebuilds the shape as its reflection across the plane through `origin` with normal `normal`, both in the body's own coordinates (type `MirrorPlane`). The placement does not change. A placement cannot hold a reflection: a negative scale throws `InvalidTransform`. |
163
+ | Copies | `body.duplicate({ ogId?, parent? })` makes an independent copy; `body.instance({ ogId?, parent? })` shares the shape. `getInstanceCount()`, `makeUnique()`. |
164
+ | `SystemAssembly` | `new SystemAssembly({ ogId?, parent? })`. `addChild(children, { keepWorld? })`, `removeChild(child, { keepWorld? })`, `getChildren()`, `getParent()`, `getBounds()`, `transform`, `dispose()`. Bodies have the same tree methods. |
165
+ | Queries | `getBounds()` (`[minX, minY, minZ, maxX, maxY, maxZ]`, or `null`), `getBrep()`, `getWorldBrep()` (the BRep placed in the world), `faceNormalAt(faceId, [x, y, z])` (the face's unit normal in the body's own coordinates), `classifyPoint([x, y, z])` (`'Inside'`, `'Outside'`, `'Boundary'` or `'Unknown'`, in the body's own coordinates), `measure({ deflection? })` (`{ volume, area, errorBound, areaErrorBound, deflection }`; the volume is within `errorBound` of the exact one, the area within `areaErrorBound`), `validity()` (`{ valid, closed, bodyType, error? }`), `solid.getReport()` (the last boolean's report, or `null`). |
166
+ | Appearance | `appearance` in the options, or `body.setAppearance({ color?, opacity?, outline?, pickOutline?, deflection?, smoothAngle? })`. `smoothAngle` is in degrees, 20 by default: edges whose faces fold by less are left out of the outline and shaded smooth; `0` keeps every edge. |
167
+ | Display | `OpenGeometry.settled({ deflection? })` resolves to `{ failed }`; `OpenGeometry.flush({ geometry?: 'sync', bodies? })` (with `bodies`, meshes and places only those bodies now; hidden bodies, bodies with no shape and bodies in limbo (disposed while a mark is live) are skipped; a fully disposed body or one from a reset runtime throws `Disposed` before anything is meshed; `bodies` without `geometry: 'sync'`, a non-array `bodies` or an item that is not a Wire, Sheet or Solid throws `InvalidParameter`); `OpenGeometry.setDisplayDeflection(world?)`; `OpenGeometry.setCameraMotion(moving)`; `OpenGeometry.observeCamera(renderer, camera)` observes the first camera seen per renderer frame (`renderer.info.render.frame`) for level of detail; a `render()` nested inside an `onBeforeRender` (Reflector style) starts a new frame, and an `ArrayCamera` is observed through its first sub-camera (a host whose drawables are not kernel bodies, such as instanced or batched layers, calls it from their `onBeforeRender`); `OpenGeometry.releaseIdleGeometry()` disposes the display geometry cached for bodies not showing it and returns `{ records, bytes }`; `OpenGeometry.markDisplayed(bodies)` counts those bodies as displayed for the current render pass (a host that draws bodies through its own instanced or batched layers calls it from that layer's `onBeforeRender`; it works for a body hidden by layer, skips a body with `visible = false`, and validates `bodies` as `flush({ bodies })` does); `OpenGeometry.setHostDrawn(bodies, hostDrawn)` hands the drawing of those bodies to the host (`true`) or gives it back (`false`): while host-drawn, a body's `visible` is `false`, so three.js skips it and everything under it, and the kernel keeps the body's own visibility apart, so `markDisplayed`, a walk, `flush({ geometry: 'sync', bodies })`, level of detail and record swaps treat it as shown, and a dispose, a rollback or a reset changes that visibility instead of `visible`; giving it back sets `visible` to that visibility (a host calls it when a body joins or leaves its instanced or batched layers; do not set `visible` on a host-drawn body; it validates `bodies` as `flush({ bodies })` does, except that giving bodies back ignores a disposed or finalized body, and a `hostDrawn` that is not a boolean throws `InvalidParameter`); `OpenGeometry.hostGroup(bodies)` returns a `HostGroup` that stamps all its bodies at once: `group.drawn()` counts every member as displayed for the current render pass exactly as `markDisplayed` does, at a cost that does not grow with the number of members (a host calls it from each instanced or batched layer's `onBeforeRender` in place of `markDisplayed`), `group.set(bodies)` replaces the members and `group.dispose()` ends the group, after which `drawn()` does nothing and its members no longer count through it; a body may be in several groups, a hidden or host-drawn member keeps its own visibility and gets its geometry when it is shown again through `setHostDrawn` or a rollback, a member that is not host-drawn and has `visible` set to `true` later gets it when it is drawn or walked, a member disposed later leaves its groups, a group that is dropped without `dispose()` is ended when it is garbage collected, `hostGroup` and `set` validate `bodies` once as `markDisplayed` does, and `set` on a disposed group or one from a reset runtime throws `Disposed`. A body is displayed when it is drawn (its own `onBeforeRender` or `markDisplayed`) or walked by `updateMatrixWorld`; a draw installs new display geometry after the render, a walk at once. Each body dispatches `geometrychanged` after it installs new display geometry and `placementchanged` when a flush moves it (`BodyEventMap`); their listeners run synchronously, after the whole flush is applied or at the end of the render pass, and a listener that throws is reported through `OpenGeometry.on('error', …)` with the thrown value while the flush and the pass complete. |
168
+ | Picking | `OpenGeometry.resolveHit(intersection)` takes a Three.js raycast hit and returns `{ ogId, shapeRevision, faceId?, edgeId? }` or `undefined`. |
169
+ | `OGMark` | `const mark = OpenGeometry.mark()`, then `mark.rollback()` and `mark.release()`. `OpenGeometry.markStats()` returns `{ liveMarks, retainedRevisions }`. `OpenGeometry.transaction(fn, { dryRun? })` runs a synchronous `fn` and rolls back if it throws. |
170
+ | Events | `OpenGeometry.on(event, handler)` with `'geometry'`, `'warning'`, `'error'` or `'fatal'`; it returns a function that unsubscribes. |
171
+ | STEP | `await OpenGeometry.exportStep({ nodes, unit?, upAxis?, name?, timestamp? })` returns `{ text, report }`. `nodes`: bodies, assemblies or `ogId` strings. `unit`: `'millimetre'` (default) or `'metre'`; `upAxis`: `'Z'` (default) or `'Y'`. |
172
+ | IFC body | `OpenGeometry.exportIfcBody(solid)` returns the IFC exchange body (type `AnalyticExchangeBodyV2`): `schema_version` 2, world metres, Z up, `representation_type` `'AdvancedBrep'` or `'CSG'` for a solid with a cavity, `entities`, `solids` and `faces`. It refuses a Sheet, a Wire or an assembly. |
173
+ | 2D regions | `OpenGeometry.booleanRegions2D(a, b, operation)` and `OpenGeometry.booleanCurvedRegions2D(a, b, operation)` with `'union'`, `'intersection'` or `'subtraction'`. A region is `{ outer, holes }`: an outer ring and a list of hole rings, each ring of `{ x, y, z }` points at one height (type `OffsetRegion`) or of line and arc edges (type `CurvedRegion2D`). Outer rings run clockwise in XZ and holes counter-clockwise. A plain ring is not a region and throws `InvalidParameter`; the tolerance is `OG_REGION_TOLERANCE`. |
174
+ | 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. |
175
+ | `OGError` | Failures throw an `OGError` with `code` (for example `InvalidParameter`, `SharedShape`, `Disposed`), `call`, `message` and `details`. |
176
+ | Reset | `OpenGeometry.reset()` frees every body and leaves an empty document. |
177
+ | 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`. |
178
+
179
+ **Rules that are easy to get wrong.**
180
+
181
+ - Await `OpenGeometry.create` once before creating any body.
182
+ - `workerURL` belongs to the second argument of `create`, not the first.
183
+ - Node has no `Worker` and cannot fetch a `file:` URL. Pass the compiled module instead; tessellation then runs inline:
184
+
185
+ ```js
186
+ import { readFileSync } from 'node:fs';
187
+ import { OpenGeometry } from 'opengeometry';
188
+
189
+ const wasm = readFileSync(new URL(import.meta.resolve('opengeometry/opengeometry_bg.wasm')));
190
+ await OpenGeometry.create({ wasmModule: new WebAssembly.Module(wasm) });
191
+ ```
192
+
193
+ - `operate` changes the target's shape once. The tools stay separate, live solids: moving or disposing a tool later does not change the target, and a tool is drawn only if you add it to the scene.
194
+ - `rebuild` replaces the shape, so an earlier `operate` result is gone; call `operate` again after it.
195
+ - A shape shared by instances cannot be edited one node at a time: pass `{ instances: 'all' }` or call `makeUnique()` first, or the call throws `SharedShape`.
196
+ - Move bodies with `transform`. Setting `body.position`, `rotation` or `scale` is reverted with a `PlacementOverwritten` warning.
197
+ - Add bodies to the Three.js scene yourself; a `SystemAssembly` is not a Three.js object.
198
+ - Surfaces use `MeshStandardMaterial`, so the scene needs a light.
199
+ - Rendering is what asks for geometry. Render in a loop, or render once, `await OpenGeometry.settled()`, and render again. `settled` returns at once if nothing has been rendered.
200
+ - In Node nothing renders, so nothing asks for geometry: add the body to a `THREE.Scene`, call `scene.updateMatrixWorld()`, then call `OpenGeometry.flush({ geometry: 'sync' })` or `await OpenGeometry.settled()`; the mesh is then in `body.surface.geometry`. After an edit, `OpenGeometry.flush({ geometry: 'sync', bodies: [body] })` meshes only that body and places its mesh, so the next frame shows it with no extra scene walk.
201
+ - STEP export defaults to millimetres and Z up. A wire cannot be exported on its own: the selection must contain a solid.
202
+ - To check that a body is a valid solid, call `body.validity()`: a valid closed solid gives `{ valid: true, closed: true, bodyType: 'Solid' }`.
203
+ - Call `dispose()` on bodies and assemblies you no longer need.
204
+ - Catch `OGError` and branch on `code`. After a `'fatal'` event the runtime refuses every call until `OpenGeometry.reset()`.
205
+
206
+ **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.
207
+
208
+ **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/`](https://github.com/OpenGeometry-io/OpenGeometry/tree/main/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'`.
143
209
 
144
210
  ## Documentation
145
211
 
146
- Full API reference, guides, and concepts are available at:
212
+ The documentation at **[docs.opengeometry.io](https://docs.opengeometry.io?utm_source=npm)** describes 3.0: a quickstart, concepts, guides and the API reference. What changed in each release is in [CHANGELOG.md](https://github.com/OpenGeometry-io/OpenGeometry/blob/main/CHANGELOG.md). To move code written for 2.0 to 3.0, follow [MIGRATION.md](https://github.com/OpenGeometry-io/OpenGeometry/blob/main/MIGRATION.md).
147
213
 
148
- **[docs.opengeometry.io](https://docs.opengeometry.io)**
214
+ ## Repository structure
149
215
 
150
- Key pages:
151
- - [Installation](https://docs.opengeometry.io/OpenGeometry/installation)
152
- - [Quick Start](https://docs.opengeometry.io/OpenGeometry/quickstart)
153
- - [Architecture & Concepts](https://docs.opengeometry.io/OpenGeometry/concepts/architecture)
154
- - [API Reference](https://docs.opengeometry.io/OpenGeometry/api/)
155
-
156
- ## Repository Structure
157
-
158
- ```
159
- main/opengeometry Rust core → WebAssembly
160
- main/opengeometry-three Three.js integration layer
161
- main/opengeometry-webgl WebGL-oriented package (WIP)
162
- main/opengeometry-babylon Babylon.js-oriented package (WIP)
163
- docs/ Documentation source (Mintlify)
164
- ```
216
+ | Path | What it holds |
217
+ | --- | --- |
218
+ | [`main/opengeometry/`](https://github.com/OpenGeometry-io/OpenGeometry/tree/main/main/opengeometry/) | The Rust kernel, built to WebAssembly |
219
+ | [`main/opengeometry-three/`](https://github.com/OpenGeometry-io/OpenGeometry/tree/main/main/opengeometry-three/) | The Three.js SDK, published as `opengeometry` |
220
+ | [`main/scripts/`](https://github.com/OpenGeometry-io/OpenGeometry/tree/main/main/scripts/) | Build, check, benchmark and snapshot scripts |
221
+ | [`docs/`](https://github.com/OpenGeometry-io/OpenGeometry/tree/main/docs/) | The source of the documentation site |
165
222
 
166
- ## Building from Source
223
+ ## Building from source
167
224
 
168
- **Prerequisites:** Node.js, npm, Rust 1.89.0+ with `wasm32-unknown-unknown`, `wasm-pack`
225
+ **Prerequisites:** Node.js 26 and npm, Rust 1.88.0 with the `wasm32-unknown-unknown` target (pinned in `main/rust-toolchain.toml`), and `wasm-pack`.
169
226
 
170
227
  ```bash
171
- # Install dependencies
172
- npm install
228
+ npm --prefix main ci
229
+ npm run build
230
+ npm run dev-example
231
+ npm test
232
+ npm run check
233
+ npm run check:full
234
+ ```
173
235
 
174
- # Build Rust core → WebAssembly
175
- npm run build-core
236
+ - `npm --prefix main ci` installs the dependencies.
237
+ - `npm run build` builds the kernel to WebAssembly and the SDK, and writes the package to `main/dist/`.
238
+ - `npm run dev-example` serves the example pages on a local Vite server; build first.
239
+ - `npm test` runs the kernel's Rust tests.
240
+ - `npm run check` runs the gate: formatting, lints, type checks, source rules, the build, the Rust, WebAssembly and Node tests, and the performance budgets.
241
+ - `npm run check:full` runs the same gate plus the browser tests on three 0.168 and 0.184. The browser tests need Playwright's Chromium, installed with `npx playwright install chromium` in `main/` (on Linux, add `--with-deps` to install the system libraries, as CI does).
176
242
 
177
- # Build everything (core + Three.js + WASM copy)
178
- npm run build
243
+ More in [developer.md](https://github.com/OpenGeometry-io/OpenGeometry/blob/main/developer.md).
179
244
 
180
- # Run the Three.js example app locally
181
- npm --prefix main/opengeometry-three run dev-example-three
245
+ ## Built with OpenGeometry
182
246
 
183
- # Run tests
184
- npm test
185
- ```
247
+ If your project uses OpenGeometry, please add the badge to your README and link back to us. It helps other people find the project.
186
248
 
187
- ## Who is this for?
249
+ [![Built with OpenGeometry](https://img.shields.io/badge/built%20with-OpenGeometry-4460FF?style=flat-square)](https://opengeometry.io?utm_source=built-with-badge)
188
250
 
189
- - Teams building **browser-based CAD and geometry tools**
190
- - Developers evaluating **WebAssembly-powered 3D** for the web
191
- - Contributors interested in the **Rust → WASM geometry pipeline**
192
- - Anyone exploring **open-source CAD kernel internals**
251
+ ```md
252
+ [![Built with OpenGeometry](https://img.shields.io/badge/built%20with-OpenGeometry-4460FF?style=flat-square)](https://opengeometry.io?utm_source=built-with-badge)
253
+ ```
193
254
 
194
- If you just want a quick look, start with the [hosted demos](https://demos.opengeometry.io) or the [quickstart repo](https://github.com/OpenGeometry-io/quickstart-js).
255
+ Then tell us about it on [Discord](https://discord.com/invite/9wJpbfgGGA): we like to see what you build.
195
256
 
196
257
  ## Community
197
258
 
@@ -201,17 +262,15 @@ We'd love to have you involved — whether you're using OpenGeometry, building o
201
262
  - **[Twitter / X](https://x.com/openGeometry)** — Updates and announcements
202
263
  - **[LinkedIn](https://linkedin.com/company/openGeometry)** — Company updates
203
264
  - **[GitHub Issues](https://github.com/OpenGeometry-io/OpenGeometry/issues)** — Bug reports and feature requests
204
- - **[Blog](https://blog.opengeometry.io?utm_source=github)** — Deep dives and release notes
265
+ - **[Blog](https://blog.opengeometry.io?utm_source=npm)** — Deep dives and release notes
205
266
 
206
267
  ## Contributing
207
268
 
208
- OpenGeometry is open source under the [MPL-2.0 license](./LICENSE.md). Contributions are welcome — check the [issues](https://github.com/OpenGeometry-io/OpenGeometry/issues) for good starting points or open a discussion on [Discord](https://discord.com/invite/9wJpbfgGGA).
269
+ Contributions are welcome — check the [issues](https://github.com/OpenGeometry-io/OpenGeometry/issues) for good starting points or open a discussion on [Discord](https://discord.com/invite/9wJpbfgGGA). [developer.md](https://github.com/OpenGeometry-io/OpenGeometry/blob/main/developer.md) covers building, checks and releases.
209
270
 
210
- ## AI Agent Docs Policy
271
+ ## License
211
272
 
212
- - If you're an AI agent, start with [AGENTS.md](./AGENTS.md) for architecture, commands, and behavioral rules.
213
- - Agents should not create planning, handoff, or runbook files during a task. The
214
- conversation, the diff, and the commit message are the handoff.
273
+ OpenGeometry is released under the Mozilla Public License 2.0 (MPL-2.0). See [LICENSE.md](https://github.com/OpenGeometry-io/OpenGeometry/blob/main/LICENSE.md).
215
274
 
216
275
  ---
217
276