opengeometry 2.0.7 → 2.0.8

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.
package/README.md CHANGED
@@ -75,11 +75,8 @@ Good examples include:
75
75
 
76
76
  If you are using ChatGPT, Claude, Gemini, Copilot, or other coding agents on this repository, start here:
77
77
 
78
+ - [AGENTS.md](./AGENTS.md) - single source of truth for all coding agents (architecture, commands, gotchas, behavioral rules)
78
79
  - [README.md](./README.md) - product overview, positioning, and quick start
79
- - [llms.txt](./llms.txt) - concise repo and API guide for coding agents
80
- - [llms-full.txt](./llms-full.txt) - expanded agent guide with workflows and examples
81
- - [llm.txt](./llm.txt) - redirect for tools that look for a single LLM entrypoint
82
- - [AGENTS.md](./AGENTS.md) - repository workflow rules and validation expectations
83
80
  - [Quickstart](https://docs.opengeometry.io/quickstart)
84
81
  - [Three.js integration](https://docs.opengeometry.io/integration/threejs)
85
82
  - [Boolean operations](https://docs.opengeometry.io/api/operations/boolean-operations)
@@ -92,7 +89,7 @@ If you are using ChatGPT, Claude, Gemini, Copilot, or other coding agents on thi
92
89
  | **Primitives** | Lines, arcs, curves, polylines, rectangles |
93
90
  | **Shapes** | Polygons, solids, cuboids, cylinders, spheres, wedges, sweeps, openings |
94
91
  | **Operations** | Triangulation, extrusion, sweep, offset, boolean operations |
95
- | **Exports** | STL, STEP, IFC, PDF projection |
92
+ | **Exports** | STL, STEP, IFC, PDF projection (PDF is currently native/Node-only — browser PDF is on the roadmap) |
96
93
  | **Integration** | Three.js scene management, WebAssembly-powered performance |
97
94
 
98
95
  ## Demos
@@ -212,14 +209,12 @@ OpenGeometry is open source under the [MPL-2.0 license](./LICENSE.md). Contribut
212
209
 
213
210
  ## AI Agent Docs Policy
214
211
 
215
- - Repository-level AI agent instructions are in [AGENTS.md](./AGENTS.md).
216
- - LLM-friendly repo entrypoints are [llms.txt](./llms.txt), [llms-full.txt](./llms-full.txt), and
217
- [llm.txt](./llm.txt).
218
- - In the current workflow, [`AI-DOCs/`](./AI-DOCs/) is used for AI-generated handoffs, runbooks,
219
- testing notes, and temporary implementation context.
220
- - The maintained user-facing docs live in [`docs/`](./docs/), and stable architecture/domain notes
221
- are tracked in [`knowledge/`](./knowledge/).
222
- - AI-generated docs should not be added under app/code folders unless explicitly requested.
212
+ - All AI coding agent instructions live in a single file: [AGENTS.md](./AGENTS.md).
213
+ `CLAUDE.md` and `.github/copilot-instructions.md` are thin redirects to it.
214
+ - Stable architecture and domain notes are tracked in [`knowledge/`](./knowledge/).
215
+ - User-facing docs live in [`docs/`](./docs/) (Mintlify source).
216
+ - Agents should not create planning, handoff, or runbook files during a task. The
217
+ conversation, the diff, and the commit message are the handoff.
223
218
 
224
219
  ---
225
220
 
package/index.js CHANGED
@@ -159,6 +159,22 @@ function getArrayF64FromWasm0(ptr, len) {
159
159
  ptr = ptr >>> 0;
160
160
  return getFloat64ArrayMemory0().subarray(ptr / 8, ptr / 8 + len);
161
161
  }
162
+ let cachedDataViewMemory0 = null;
163
+ function getDataViewMemory0() {
164
+ if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer) {
165
+ cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
166
+ }
167
+ return cachedDataViewMemory0;
168
+ }
169
+ function passArrayJsValueToWasm0(array, malloc) {
170
+ const ptr = malloc(array.length * 4, 4) >>> 0;
171
+ for (let i = 0; i < array.length; i++) {
172
+ const add = addToExternrefTable0(array[i]);
173
+ getDataViewMemory0().setUint32(ptr + 4 * i, add, true);
174
+ }
175
+ WASM_VECTOR_LEN = array.length;
176
+ return ptr;
177
+ }
162
178
  /**
163
179
  * @param {string} local_brep_serialized
164
180
  * @param {number} height
@@ -185,21 +201,15 @@ function extrudeBrepFace$1(local_brep_serialized, height) {
185
201
  wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
186
202
  }
187
203
  }
188
- let cachedDataViewMemory0 = null;
189
- function getDataViewMemory0() {
190
- if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer) {
191
- cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
192
- }
193
- return cachedDataViewMemory0;
194
- }
195
- function passArrayJsValueToWasm0(array, malloc) {
196
- const ptr = malloc(array.length * 4, 4) >>> 0;
197
- for (let i = 0; i < array.length; i++) {
198
- const add = addToExternrefTable0(array[i]);
199
- getDataViewMemory0().setUint32(ptr + 4 * i, add, true);
204
+ function getArrayJsValueFromWasm0(ptr, len) {
205
+ ptr = ptr >>> 0;
206
+ const mem = getDataViewMemory0();
207
+ const result = [];
208
+ for (let i = ptr; i < ptr + 4 * len; i += 4) {
209
+ result.push(wasm.__wbindgen_export_2.get(mem.getUint32(i, true)));
200
210
  }
201
- WASM_VECTOR_LEN = array.length;
202
- return ptr;
211
+ wasm.__externref_drop_slice(ptr, len);
212
+ return result;
203
213
  }
204
214
  function isLikeNone(x) {
205
215
  return x === undefined || x === null;
@@ -287,16 +297,6 @@ function booleanSubtractionMany(lhs_brep_serialized, cutters_brep_serialized, op
287
297
  }
288
298
  return OGBooleanResult.__wrap(ret[0]);
289
299
  }
290
- function getArrayJsValueFromWasm0(ptr, len) {
291
- ptr = ptr >>> 0;
292
- const mem = getDataViewMemory0();
293
- const result = [];
294
- for (let i = ptr; i < ptr + 4 * len; i += 4) {
295
- result.push(wasm.__wbindgen_export_2.get(mem.getUint32(i, true)));
296
- }
297
- wasm.__externref_drop_slice(ptr, len);
298
- return result;
299
- }
300
300
  const Matrix3Finalization = typeof FinalizationRegistry === 'undefined' ? {
301
301
  register: () => {},
302
302
  unregister: () => {}
@@ -1666,6 +1666,99 @@ class OGCylinder {
1666
1666
  return Vector3.__wrap(ret);
1667
1667
  }
1668
1668
  }
1669
+ const OGEntityRegistryFinalization = typeof FinalizationRegistry === 'undefined' ? {
1670
+ register: () => {},
1671
+ unregister: () => {}
1672
+ } : new FinalizationRegistry(ptr => wasm.__wbg_ogentityregistry_free(ptr >>> 0, 1));
1673
+ /**
1674
+ * Flat entity registry with a batched multi-view projection API.
1675
+ * Replaces the scene-centric OGSceneManager pattern for export use cases.
1676
+ */
1677
+ class OGEntityRegistry {
1678
+ __destroy_into_raw() {
1679
+ const ptr = this.__wbg_ptr;
1680
+ this.__wbg_ptr = 0;
1681
+ OGEntityRegistryFinalization.unregister(this);
1682
+ return ptr;
1683
+ }
1684
+ free() {
1685
+ const ptr = this.__destroy_into_raw();
1686
+ wasm.__wbg_ogentityregistry_free(ptr, 0);
1687
+ }
1688
+ constructor() {
1689
+ const ret = wasm.ogentityregistry_new();
1690
+ this.__wbg_ptr = ret >>> 0;
1691
+ OGEntityRegistryFinalization.register(this, this.__wbg_ptr, this);
1692
+ return this;
1693
+ }
1694
+ /**
1695
+ * Register (or replace) an entity. `kind` must be an OGEntityKind string.
1696
+ * @param {string} id
1697
+ * @param {string} kind
1698
+ * @param {string} brep_json
1699
+ */
1700
+ registerEntity(id, kind, brep_json) {
1701
+ const ptr0 = passStringToWasm0(id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1702
+ const len0 = WASM_VECTOR_LEN;
1703
+ const ptr1 = passStringToWasm0(kind, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1704
+ const len1 = WASM_VECTOR_LEN;
1705
+ const ptr2 = passStringToWasm0(brep_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1706
+ const len2 = WASM_VECTOR_LEN;
1707
+ const ret = wasm.ogentityregistry_registerEntity(this.__wbg_ptr, ptr0, len0, ptr1, len1, ptr2, len2);
1708
+ if (ret[1]) {
1709
+ throw takeFromExternrefTable0(ret[0]);
1710
+ }
1711
+ }
1712
+ /**
1713
+ * Remove a previously registered entity.
1714
+ * @param {string} id
1715
+ * @returns {boolean}
1716
+ */
1717
+ unregisterEntity(id) {
1718
+ const ptr0 = passStringToWasm0(id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1719
+ const len0 = WASM_VECTOR_LEN;
1720
+ const ret = wasm.ogentityregistry_unregisterEntity(this.__wbg_ptr, ptr0, len0);
1721
+ return ret !== 0;
1722
+ }
1723
+ /**
1724
+ * Remove all registered entities.
1725
+ */
1726
+ clearEntities() {
1727
+ wasm.ogentityregistry_clearEntities(this.__wbg_ptr);
1728
+ }
1729
+ /**
1730
+ * Batched multi-view projection.
1731
+ *
1732
+ * Input: JSON array of `{ id, camera, hlr?, section_plane? }` (ViewRequest).
1733
+ * Output: JSON map of `{ viewportId: Scene2D }`.
1734
+ *
1735
+ * All viewports are projected in a single WASM call, amortising
1736
+ * serialisation overhead and keeping BRep data in WASM memory.
1737
+ * @param {string} views_json
1738
+ * @returns {string}
1739
+ */
1740
+ projectCurrentToViews(views_json) {
1741
+ let deferred3_0;
1742
+ let deferred3_1;
1743
+ try {
1744
+ const ptr0 = passStringToWasm0(views_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
1745
+ const len0 = WASM_VECTOR_LEN;
1746
+ const ret = wasm.ogentityregistry_projectCurrentToViews(this.__wbg_ptr, ptr0, len0);
1747
+ var ptr2 = ret[0];
1748
+ var len2 = ret[1];
1749
+ if (ret[3]) {
1750
+ ptr2 = 0;
1751
+ len2 = 0;
1752
+ throw takeFromExternrefTable0(ret[2]);
1753
+ }
1754
+ deferred3_0 = ptr2;
1755
+ deferred3_1 = len2;
1756
+ return getStringFromWasm0(ptr2, len2);
1757
+ } finally {
1758
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
1759
+ }
1760
+ }
1761
+ }
1669
1762
  const OGFreeformEditorFinalization = typeof FinalizationRegistry === 'undefined' ? {
1670
1763
  register: () => {},
1671
1764
  unregister: () => {}
@@ -4996,7 +5089,7 @@ class OGSweep {
4996
5089
  * @returns {Vector3}
4997
5090
  */
4998
5091
  get_anchor() {
4999
- const ret = wasm.ogarc_get_anchor(this.__wbg_ptr);
5092
+ const ret = wasm.ogsweep_get_anchor(this.__wbg_ptr);
5000
5093
  return Vector3.__wrap(ret);
5001
5094
  }
5002
5095
  /**
@@ -5277,7 +5370,7 @@ class OGWedge {
5277
5370
  * @returns {Vector3}
5278
5371
  */
5279
5372
  get_anchor() {
5280
- const ret = wasm.ogwedge_get_anchor(this.__wbg_ptr);
5373
+ const ret = wasm.ogsweep_get_anchor(this.__wbg_ptr);
5281
5374
  return Vector3.__wrap(ret);
5282
5375
  }
5283
5376
  }
@@ -5692,6 +5785,7 @@ var OGKernel = /*#__PURE__*/Object.freeze({
5692
5785
  OGCuboid: OGCuboid,
5693
5786
  OGCurve: OGCurve,
5694
5787
  OGCylinder: OGCylinder,
5788
+ OGEntityRegistry: OGEntityRegistry,
5695
5789
  OGFreeformEditor: OGFreeformEditor,
5696
5790
  OGFreeformGeometry: OGFreeformGeometry,
5697
5791
  OGIfcExportResult: OGIfcExportResult,
@@ -6250,7 +6344,6 @@ function createFreeformGeometry(source, options) {
6250
6344
  return geometry;
6251
6345
  }
6252
6346
 
6253
- /* eslint-enable no-unused-vars */
6254
6347
  /**
6255
6348
  * Simple Line defined by Two Points
6256
6349
  */
@@ -6473,7 +6566,6 @@ class Line extends THREE.Line {
6473
6566
  }
6474
6567
  }
6475
6568
 
6476
- /* eslint-enable no-unused-vars */
6477
6569
  /**
6478
6570
  * Polyline wrapper backed by the kernel OGPolyline primitive.
6479
6571
  */
@@ -6913,7 +7005,6 @@ class Arc extends THREE.Line {
6913
7005
  }
6914
7006
  }
6915
7007
 
6916
- /* eslint-enable no-unused-vars */
6917
7008
  /**
6918
7009
  * Rectangle wrapper backed by the kernel OGRectangle primitive.
6919
7010
  */
@@ -7151,7 +7242,6 @@ class Rectangle extends THREE.Line {
7151
7242
  }
7152
7243
  }
7153
7244
 
7154
- /* eslint-enable no-unused-vars */
7155
7245
  /**
7156
7246
  * Curve wrapper backed by the kernel OGCurve primitive.
7157
7247
  */
@@ -7427,15 +7517,14 @@ function serializeBrepLike$1(value) {
7427
7517
  }
7428
7518
 
7429
7519
  var _BooleanResult_outlineMesh;
7430
- /* eslint-enable no-unused-vars */
7431
7520
  const BOOLEAN_CREASE_ANGLE = Math.PI / 5;
7432
7521
  const BOOLEAN_OUTLINE_THRESHOLD_DEGREES = 26;
7433
7522
  /**
7434
7523
  * Renderable result mesh returned by the kernel boolean helpers.
7435
7524
  */
7436
7525
  class BooleanResult extends THREE.Mesh {
7437
- constructor(kernelResult, options) {
7438
- var _a, _b, _c;
7526
+ constructor(kernelResult, options, sourceMaterial = null) {
7527
+ var _a, _b;
7439
7528
  super();
7440
7529
  this.report = null;
7441
7530
  this.brepSerialized = "";
@@ -7448,15 +7537,15 @@ class BooleanResult extends THREE.Mesh {
7448
7537
  this.ogid = getUUID();
7449
7538
  this._fatOutlines = (_a = options === null || options === void 0 ? void 0 : options.fatOutlines) !== null && _a !== void 0 ? _a : false;
7450
7539
  this._outlineWidth = sanitizeOutlineWidth(options === null || options === void 0 ? void 0 : options.outlineWidth);
7451
- this.applyKernelResult(kernelResult, (_b = options === null || options === void 0 ? void 0 : options.color) !== null && _b !== void 0 ? _b : 0x2563eb);
7452
- if ((_c = options === null || options === void 0 ? void 0 : options.outline) !== null && _c !== void 0 ? _c : false) {
7540
+ this.applyKernelResult(kernelResult, options, sourceMaterial);
7541
+ if ((_b = options === null || options === void 0 ? void 0 : options.outline) !== null && _b !== void 0 ? _b : false) {
7453
7542
  this.outline = true;
7454
7543
  }
7455
7544
  }
7456
7545
  /**
7457
7546
  * Rebuilds the mesh, cached BRep payload, and outline geometry from the kernel output.
7458
7547
  */
7459
- applyKernelResult(kernelResult, color = 0x2563eb) {
7548
+ applyKernelResult(kernelResult, options, sourceMaterial = null) {
7460
7549
  this.disposeGeometry();
7461
7550
  this.brepSerialized = kernelResult.brepSerialized;
7462
7551
  this.brepData = JSON.parse(kernelResult.brepSerialized);
@@ -7467,15 +7556,7 @@ class BooleanResult extends THREE.Mesh {
7467
7556
  const geometry = toCreasedNormals(baseGeometry, BOOLEAN_CREASE_ANGLE);
7468
7557
  geometry.computeBoundingBox();
7469
7558
  this.outlinePositions = getRenderableOutlinePositions(geometry, kernelResult.outlineGeometrySerialized);
7470
- const material = new THREE.MeshStandardMaterial({
7471
- color,
7472
- transparent: true,
7473
- opacity: 0.82,
7474
- side: THREE.FrontSide,
7475
- polygonOffset: true,
7476
- polygonOffsetFactor: 1,
7477
- polygonOffsetUnits: 1,
7478
- });
7559
+ const material = buildResultMaterial(sourceMaterial, options);
7479
7560
  this.geometry = geometry;
7480
7561
  this.material = material;
7481
7562
  if (this._outlineEnabled) {
@@ -7603,7 +7684,7 @@ function executeBooleanSubtractionMany(lhs, cutters, options) {
7603
7684
  const kernelFunction = booleanExport;
7604
7685
  const kernelOptions = serializeKernelOptions(options === null || options === void 0 ? void 0 : options.kernel);
7605
7686
  const kernelResult = kernelFunction(resolveOperandSerialized(lhs), JSON.stringify(cutters.map(resolveOperandPayload)), kernelOptions);
7606
- return createBooleanResult(kernelResult, options);
7687
+ return createBooleanResult(kernelResult, options, resolveOperandMaterial(lhs));
7607
7688
  }
7608
7689
  /**
7609
7690
  * Normalizes mixed wrapper/raw operands, invokes the wasm boolean export, and
@@ -7617,7 +7698,7 @@ function executeBoolean(exportName, lhs, rhs, options) {
7617
7698
  const kernelFunction = booleanExport;
7618
7699
  const kernelOptions = serializeKernelOptions(options === null || options === void 0 ? void 0 : options.kernel);
7619
7700
  const kernelResult = kernelFunction(resolveOperandSerialized(lhs), resolveOperandSerialized(rhs), kernelOptions);
7620
- return createBooleanResult(kernelResult, options);
7701
+ return createBooleanResult(kernelResult, options, resolveOperandMaterial(lhs));
7621
7702
  }
7622
7703
  /**
7623
7704
  * Accepts wrapper objects, raw BRep data, or serialized JSON and normalizes
@@ -7673,14 +7754,69 @@ function serializeKernelOptions(options) {
7673
7754
  merge_coplanar_faces: options.mergeCoplanarFaces,
7674
7755
  });
7675
7756
  }
7676
- function createBooleanResult(kernelResult, options) {
7757
+ function createBooleanResult(kernelResult, options, sourceMaterial = null) {
7677
7758
  var _a;
7678
- const result = new BooleanResult(kernelResult, options);
7759
+ const result = new BooleanResult(kernelResult, options, sourceMaterial);
7679
7760
  if ((_a = options === null || options === void 0 ? void 0 : options.outline) !== null && _a !== void 0 ? _a : true) {
7680
7761
  result.outline = true;
7681
7762
  }
7682
7763
  return result;
7683
7764
  }
7765
+ /**
7766
+ * Returns a clonable `THREE.Material` from the operand when it is a Three mesh
7767
+ * subclass (Solid, Polygon, Cuboid, Opening, BooleanResult, etc.). Returns
7768
+ * `null` for serialized JSON, parsed BRep objects, or anything else without a
7769
+ * reachable material so the boolean result can fall back to the legacy default.
7770
+ */
7771
+ function resolveOperandMaterial(operand) {
7772
+ var _a;
7773
+ if (typeof operand !== "object" || operand === null) {
7774
+ return null;
7775
+ }
7776
+ if (!(operand instanceof THREE.Mesh)) {
7777
+ return null;
7778
+ }
7779
+ const material = operand.material;
7780
+ if (Array.isArray(material)) {
7781
+ return (_a = material[0]) !== null && _a !== void 0 ? _a : null;
7782
+ }
7783
+ return material instanceof THREE.Material ? material : null;
7784
+ }
7785
+ /**
7786
+ * Builds the boolean result mesh's material by cloning the host (LHS) material
7787
+ * when available so the result inherits the host's color, transparency, and
7788
+ * side mode. Caller-provided overrides on `BooleanRenderOptions` win, and the
7789
+ * polygon-offset settings that prevent z-fighting with the result outline are
7790
+ * always reapplied after cloning.
7791
+ */
7792
+ function buildResultMaterial(sourceMaterial, options) {
7793
+ const material = sourceMaterial
7794
+ ? sourceMaterial.clone()
7795
+ : new THREE.MeshStandardMaterial({
7796
+ color: 0x2563eb,
7797
+ transparent: true,
7798
+ opacity: 0.82,
7799
+ side: THREE.FrontSide,
7800
+ });
7801
+ if ((options === null || options === void 0 ? void 0 : options.color) !== undefined && "color" in material) {
7802
+ material.color.set(options.color);
7803
+ }
7804
+ if ((options === null || options === void 0 ? void 0 : options.opacity) !== undefined) {
7805
+ material.opacity = options.opacity;
7806
+ material.transparent = options.opacity < 1 || material.transparent;
7807
+ }
7808
+ if ((options === null || options === void 0 ? void 0 : options.transparent) !== undefined) {
7809
+ material.transparent = options.transparent;
7810
+ }
7811
+ if ((options === null || options === void 0 ? void 0 : options.side) !== undefined) {
7812
+ material.side = options.side;
7813
+ }
7814
+ material.polygonOffset = true;
7815
+ material.polygonOffsetFactor = 1;
7816
+ material.polygonOffsetUnits = 1;
7817
+ material.needsUpdate = true;
7818
+ return material;
7819
+ }
7684
7820
  /**
7685
7821
  * Builds a display-quality outline buffer from the rendered mesh and falls back
7686
7822
  * to the kernel-provided edges when the client-side extraction is empty.
@@ -9159,7 +9295,6 @@ class Opening extends THREE.Mesh {
9159
9295
  _Opening_outlineMesh = new WeakMap();
9160
9296
 
9161
9297
  var _Sphere_outlineMesh;
9162
- /* eslint-enable no-unused-vars */
9163
9298
  /**
9164
9299
  * Sphere wrapper backed by the kernel sphere primitive.
9165
9300
  */
@@ -9704,7 +9839,6 @@ class Wedge extends THREE.Mesh {
9704
9839
  _Wedge_outlineMesh = new WeakMap();
9705
9840
 
9706
9841
  var _Sweep_outlineMesh;
9707
- /* eslint-enable no-unused-vars */
9708
9842
  /**
9709
9843
  * Sweep wrapper backed by the kernel sweep primitive.
9710
9844
  */