opengeometry 2.0.2 → 2.0.4

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 (39) hide show
  1. package/README.md +34 -6
  2. package/index.d.ts +30 -13
  3. package/index.js +794 -326
  4. package/index.js.map +1 -1
  5. package/opengeometry/pkg/opengeometry.d.ts +152 -137
  6. package/opengeometry/pkg/opengeometry.js +89 -7
  7. package/opengeometry/pkg/opengeometry_bg.wasm +0 -0
  8. package/opengeometry/pkg/opengeometry_bg.wasm.d.ts +143 -137
  9. package/opengeometry_bg.wasm +0 -0
  10. package/opengeometry_bg.wasm.d.ts +143 -137
  11. package/package.json +18 -8
  12. package/src/base-types.d.ts +7 -1
  13. package/src/editor/freeform.d.ts +63 -0
  14. package/src/editor/index.d.ts +3 -0
  15. package/src/editor/parametric.d.ts +10 -0
  16. package/src/editor/types.d.ts +72 -0
  17. package/src/freeform/geometry.d.ts +59 -0
  18. package/src/freeform/index.d.ts +3 -0
  19. package/src/freeform/types.d.ts +12 -0
  20. package/src/operations/boolean.d.ts +28 -0
  21. package/src/operations/extrude.d.ts +9 -0
  22. package/src/operations/index.d.ts +1 -0
  23. package/src/primitives/arc.d.ts +15 -0
  24. package/src/primitives/curve.d.ts +18 -0
  25. package/src/primitives/line.d.ts +15 -0
  26. package/src/primitives/polyline.d.ts +18 -0
  27. package/src/primitives/rectangle.d.ts +18 -0
  28. package/src/shapes/boolean-subtract.d.ts +14 -1
  29. package/src/shapes/cuboid.d.ts +18 -3
  30. package/src/shapes/cylinder.d.ts +18 -3
  31. package/src/shapes/extrusion.d.ts +64 -0
  32. package/src/shapes/index.d.ts +1 -0
  33. package/src/shapes/opening.d.ts +21 -3
  34. package/src/shapes/outline-utils.d.ts +21 -0
  35. package/src/shapes/polygon.d.ts +36 -6
  36. package/src/shapes/solid.d.ts +116 -0
  37. package/src/shapes/sphere.d.ts +18 -3
  38. package/src/shapes/sweep.d.ts +18 -3
  39. package/src/shapes/wedge.d.ts +18 -3
package/index.js CHANGED
@@ -159,6 +159,32 @@ function getArrayF64FromWasm0(ptr, len) {
159
159
  ptr = ptr >>> 0;
160
160
  return getFloat64ArrayMemory0().subarray(ptr / 8, ptr / 8 + len);
161
161
  }
162
+ /**
163
+ * @param {string} local_brep_serialized
164
+ * @param {number} height
165
+ * @returns {string}
166
+ */
167
+ function extrudeBrepFace$1(local_brep_serialized, height) {
168
+ let deferred3_0;
169
+ let deferred3_1;
170
+ try {
171
+ const ptr0 = passStringToWasm0(local_brep_serialized, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
172
+ const len0 = WASM_VECTOR_LEN;
173
+ const ret = wasm.extrudeBrepFace(ptr0, len0, height);
174
+ var ptr2 = ret[0];
175
+ var len2 = ret[1];
176
+ if (ret[3]) {
177
+ ptr2 = 0;
178
+ len2 = 0;
179
+ throw takeFromExternrefTable0(ret[2]);
180
+ }
181
+ deferred3_0 = ptr2;
182
+ deferred3_1 = len2;
183
+ return getStringFromWasm0(ptr2, len2);
184
+ } finally {
185
+ wasm.__wbindgen_free(deferred3_0, deferred3_1, 1);
186
+ }
187
+ }
162
188
  let cachedDataViewMemory0 = null;
163
189
  function getDataViewMemory0() {
164
190
  if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer) {
@@ -175,9 +201,6 @@ function passArrayJsValueToWasm0(array, malloc) {
175
201
  WASM_VECTOR_LEN = array.length;
176
202
  return ptr;
177
203
  }
178
- function isLikeNone(x) {
179
- return x === undefined || x === null;
180
- }
181
204
  function getArrayJsValueFromWasm0(ptr, len) {
182
205
  ptr = ptr >>> 0;
183
206
  const mem = getDataViewMemory0();
@@ -188,6 +211,9 @@ function getArrayJsValueFromWasm0(ptr, len) {
188
211
  wasm.__externref_drop_slice(ptr, len);
189
212
  return result;
190
213
  }
214
+ function isLikeNone(x) {
215
+ return x === undefined || x === null;
216
+ }
191
217
  /**
192
218
  * Wasm entry point for union.
193
219
  * @param {string} lhs_brep_serialized
@@ -250,6 +276,27 @@ function booleanSubtraction$1(lhs_brep_serialized, rhs_brep_serialized, options_
250
276
  }
251
277
  return OGBooleanResult.__wrap(ret[0]);
252
278
  }
279
+
280
+ /**
281
+ * Wasm entry point for array-backed repeated subtraction.
282
+ * @param {string} lhs_brep_serialized
283
+ * @param {string} cutters_brep_serialized
284
+ * @param {string | null} [options_json]
285
+ * @returns {OGBooleanResult}
286
+ */
287
+ function booleanSubtractionMany(lhs_brep_serialized, cutters_brep_serialized, options_json) {
288
+ const ptr0 = passStringToWasm0(lhs_brep_serialized, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
289
+ const len0 = WASM_VECTOR_LEN;
290
+ const ptr1 = passStringToWasm0(cutters_brep_serialized, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
291
+ const len1 = WASM_VECTOR_LEN;
292
+ var ptr2 = isLikeNone(options_json) ? 0 : passStringToWasm0(options_json, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
293
+ var len2 = WASM_VECTOR_LEN;
294
+ const ret = wasm.booleanSubtractionMany(ptr0, len0, ptr1, len1, ptr2, len2);
295
+ if (ret[2]) {
296
+ throw takeFromExternrefTable0(ret[1]);
297
+ }
298
+ return OGBooleanResult.__wrap(ret[0]);
299
+ }
253
300
  const Matrix3Finalization = typeof FinalizationRegistry === 'undefined' ? {
254
301
  register: () => {},
255
302
  unregister: () => {}
@@ -2229,6 +2276,24 @@ class OGFreeformGeometry {
2229
2276
  wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
2230
2277
  }
2231
2278
  }
2279
+ /**
2280
+ * @returns {Float64Array}
2281
+ */
2282
+ getGeometryBuffer() {
2283
+ const ret = wasm.ogfreeformgeometry_getGeometryBuffer(this.__wbg_ptr);
2284
+ var v1 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
2285
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
2286
+ return v1;
2287
+ }
2288
+ /**
2289
+ * @returns {Float64Array}
2290
+ */
2291
+ getLocalGeometryBuffer() {
2292
+ const ret = wasm.ogfreeformgeometry_getLocalGeometryBuffer(this.__wbg_ptr);
2293
+ var v1 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
2294
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
2295
+ return v1;
2296
+ }
2232
2297
  /**
2233
2298
  * @returns {string}
2234
2299
  */
@@ -2244,6 +2309,24 @@ class OGFreeformGeometry {
2244
2309
  wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
2245
2310
  }
2246
2311
  }
2312
+ /**
2313
+ * @returns {Float64Array}
2314
+ */
2315
+ getOutlineGeometryBuffer() {
2316
+ const ret = wasm.ogfreeformgeometry_getOutlineGeometryBuffer(this.__wbg_ptr);
2317
+ var v1 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
2318
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
2319
+ return v1;
2320
+ }
2321
+ /**
2322
+ * @returns {Float64Array}
2323
+ */
2324
+ getLocalOutlineGeometryBuffer() {
2325
+ const ret = wasm.ogfreeformgeometry_getLocalOutlineGeometryBuffer(this.__wbg_ptr);
2326
+ var v1 = getArrayF64FromWasm0(ret[0], ret[1]).slice();
2327
+ wasm.__wbindgen_free(ret[0], ret[1] * 8, 8);
2328
+ return v1;
2329
+ }
2247
2330
  /**
2248
2331
  * @returns {string}
2249
2332
  */
@@ -2577,7 +2660,7 @@ class OGLine {
2577
2660
  * @returns {Vector3}
2578
2661
  */
2579
2662
  get_anchor() {
2580
- const ret = wasm.ogline_get_anchor(this.__wbg_ptr);
2663
+ const ret = wasm.ogcurve_get_anchor(this.__wbg_ptr);
2581
2664
  return Vector3.__wrap(ret);
2582
2665
  }
2583
2666
  /**
@@ -3203,7 +3286,7 @@ class OGPolyline {
3203
3286
  * @returns {Vector3}
3204
3287
  */
3205
3288
  get_anchor() {
3206
- const ret = wasm.ogline_get_anchor(this.__wbg_ptr);
3289
+ const ret = wasm.ogcurve_get_anchor(this.__wbg_ptr);
3207
3290
  return Vector3.__wrap(ret);
3208
3291
  }
3209
3292
  /**
@@ -5194,7 +5277,7 @@ class OGWedge {
5194
5277
  * @returns {Vector3}
5195
5278
  */
5196
5279
  get_anchor() {
5197
- const ret = wasm.ogline_get_anchor(this.__wbg_ptr);
5280
+ const ret = wasm.ogwedge_get_anchor(this.__wbg_ptr);
5198
5281
  return Vector3.__wrap(ret);
5199
5282
  }
5200
5283
  }
@@ -5625,8 +5708,10 @@ var OGKernel = /*#__PURE__*/Object.freeze({
5625
5708
  Vector3: Vector3,
5626
5709
  booleanIntersection: booleanIntersection$1,
5627
5710
  booleanSubtraction: booleanSubtraction$1,
5711
+ booleanSubtractionMany: booleanSubtractionMany,
5628
5712
  booleanUnion: booleanUnion$1,
5629
5713
  default: __wbg_init,
5714
+ extrudeBrepFace: extrudeBrepFace$1,
5630
5715
  initSync: initSync
5631
5716
  });
5632
5717
 
@@ -5648,7 +5733,10 @@ class SpotLabel extends CSS2DObject {
5648
5733
  }
5649
5734
  }
5650
5735
 
5651
- const OPEN_GEOMETRY_THREE_VERSION = '0.0.6';
5736
+ /**
5737
+ * Version string exposed by the Three.js adapter at runtime.
5738
+ */
5739
+ const OPEN_GEOMETRY_THREE_VERSION = "2.0.3";
5652
5740
 
5653
5741
  /**
5654
5742
  * Convert array of 16 byte values to UUID string format of the form:
@@ -5708,10 +5796,13 @@ function getUUID() {
5708
5796
  return uuid;
5709
5797
  }
5710
5798
 
5711
- function cloneVector$1(vector, fallback) {
5799
+ function cloneVector$2(vector, fallback) {
5712
5800
  var _a;
5713
5801
  return (_a = vector === null || vector === void 0 ? void 0 : vector.clone()) !== null && _a !== void 0 ? _a : new Vector3(...fallback);
5714
5802
  }
5803
+ /**
5804
+ * Returns the canonical capability payload exposed by parametric wrappers.
5805
+ */
5715
5806
  function createParametricEditCapabilities(entityType, editFamily) {
5716
5807
  return {
5717
5808
  editingMode: "parametric",
@@ -5722,27 +5813,34 @@ function createParametricEditCapabilities(entityType, editFamily) {
5722
5813
  canConvertToFreeform: true,
5723
5814
  };
5724
5815
  }
5816
+ /**
5817
+ * Normalizes optional placement fields into concrete vectors.
5818
+ */
5725
5819
  function clonePlacement(placement) {
5726
5820
  return {
5727
- translation: cloneVector$1(placement.translation, [0, 0, 0]),
5728
- rotation: cloneVector$1(placement.rotation, [0, 0, 0]),
5729
- scale: cloneVector$1(placement.scale, [1, 1, 1]),
5821
+ translation: cloneVector$2(placement.translation, [0, 0, 0]),
5822
+ rotation: cloneVector$2(placement.rotation, [0, 0, 0]),
5823
+ scale: cloneVector$2(placement.scale, [1, 1, 1]),
5730
5824
  };
5731
5825
  }
5826
+ /**
5827
+ * Converts a parametric placement payload into the freeform/object transform
5828
+ * structure expected by BRep-backed helpers.
5829
+ */
5732
5830
  function toObjectTransformation$1(placement) {
5733
5831
  if ("anchor" in placement) {
5734
5832
  return {
5735
- anchor: cloneVector$1(placement.anchor, [0, 0, 0]),
5736
- translation: cloneVector$1(placement.translation, [0, 0, 0]),
5737
- rotation: cloneVector$1(placement.rotation, [0, 0, 0]),
5738
- scale: cloneVector$1(placement.scale, [1, 1, 1]),
5833
+ anchor: cloneVector$2(placement.anchor, [0, 0, 0]),
5834
+ translation: cloneVector$2(placement.translation, [0, 0, 0]),
5835
+ rotation: cloneVector$2(placement.rotation, [0, 0, 0]),
5836
+ scale: cloneVector$2(placement.scale, [1, 1, 1]),
5739
5837
  };
5740
5838
  }
5741
5839
  return {
5742
5840
  anchor: new Vector3(0, 0, 0),
5743
- translation: cloneVector$1(placement.translation, [0, 0, 0]),
5744
- rotation: cloneVector$1(placement.rotation, [0, 0, 0]),
5745
- scale: cloneVector$1(placement.scale, [1, 1, 1]),
5841
+ translation: cloneVector$2(placement.translation, [0, 0, 0]),
5842
+ rotation: cloneVector$2(placement.rotation, [0, 0, 0]),
5843
+ scale: cloneVector$2(placement.scale, [1, 1, 1]),
5746
5844
  };
5747
5845
  }
5748
5846
 
@@ -5834,69 +5932,132 @@ function serializeOptions(options) {
5834
5932
  ? toPlainVector3$1(options.constraintPlaneNormal)
5835
5933
  : undefined }));
5836
5934
  }
5935
+ /**
5936
+ * High-level editor facade over the kernel freeform editing API.
5937
+ */
5837
5938
  class FreeformEditor {
5838
5939
  constructor(geometry, editor = new OGFreeformEditor()) {
5839
5940
  this.geometry = geometry;
5840
5941
  this.editor = editor;
5841
5942
  }
5943
+ /**
5944
+ * Returns the freeform geometry currently managed by this editor.
5945
+ */
5842
5946
  getFreeformGeometry() {
5843
5947
  return this.geometry;
5844
5948
  }
5949
+ /**
5950
+ * Returns renderable topology buffers for faces, edges, and vertices.
5951
+ */
5845
5952
  getTopologyRenderData() {
5846
5953
  return normalizeTopologyRenderData(parseJson$1(this.editor.getTopologyRenderData(this.geometry.getKernelGeometry())));
5847
5954
  }
5955
+ /**
5956
+ * Returns semantic and topological information for a face id.
5957
+ */
5848
5958
  getFaceInfo(faceId) {
5849
5959
  return normalizeFaceInfo(parseJson$1(this.editor.getFaceInfo(this.geometry.getKernelGeometry(), faceId)));
5850
5960
  }
5961
+ /**
5962
+ * Returns semantic and topological information for an edge id.
5963
+ */
5851
5964
  getEdgeInfo(edgeId) {
5852
5965
  return normalizeEdgeInfo(parseJson$1(this.editor.getEdgeInfo(this.geometry.getKernelGeometry(), edgeId)));
5853
5966
  }
5967
+ /**
5968
+ * Returns semantic and topological information for a vertex id.
5969
+ */
5854
5970
  getVertexInfo(vertexId) {
5855
5971
  return normalizeVertexInfo(parseJson$1(this.editor.getVertexInfo(this.geometry.getKernelGeometry(), vertexId)));
5856
5972
  }
5973
+ /**
5974
+ * Returns global edit capabilities for the current freeform model.
5975
+ */
5857
5976
  getEditCapabilities() {
5858
5977
  return normalizeFreeformCapabilities(parseJson$1(this.editor.getEditCapabilities(this.geometry.getKernelGeometry())));
5859
5978
  }
5979
+ /**
5980
+ * Returns edit capabilities scoped to a single face.
5981
+ */
5860
5982
  getFaceEditCapabilities(faceId) {
5861
5983
  return normalizeFeatureCapabilities(parseJson$1(this.editor.getFaceEditCapabilities(this.geometry.getKernelGeometry(), faceId)));
5862
5984
  }
5985
+ /**
5986
+ * Returns edit capabilities scoped to a single edge.
5987
+ */
5863
5988
  getEdgeEditCapabilities(edgeId) {
5864
5989
  return normalizeFeatureCapabilities(parseJson$1(this.editor.getEdgeEditCapabilities(this.geometry.getKernelGeometry(), edgeId)));
5865
5990
  }
5991
+ /**
5992
+ * Returns edit capabilities scoped to a single vertex.
5993
+ */
5866
5994
  getVertexEditCapabilities(vertexId) {
5867
5995
  return normalizeFeatureCapabilities(parseJson$1(this.editor.getVertexEditCapabilities(this.geometry.getKernelGeometry(), vertexId)));
5868
5996
  }
5997
+ /**
5998
+ * Offset a face along its editable normal direction.
5999
+ */
5869
6000
  pushPullFace(faceId, distance, options) {
5870
6001
  return parseEditResult(this.editor.pushPullFace(this.geometry.getKernelGeometry(), faceId, distance, serializeOptions(options)));
5871
6002
  }
6003
+ /**
6004
+ * Creates new side faces by extruding a face region.
6005
+ */
5872
6006
  extrudeFace(faceId, distance, options) {
5873
6007
  return parseEditResult(this.editor.extrudeFace(this.geometry.getKernelGeometry(), faceId, distance, serializeOptions(options)));
5874
6008
  }
6009
+ /**
6010
+ * Splits a face by connecting two points sampled on its boundary edges.
6011
+ */
5875
6012
  cutFace(faceId, startEdgeId, startT, endEdgeId, endT, options) {
5876
6013
  return parseEditResult(this.editor.cutFace(this.geometry.getKernelGeometry(), faceId, startEdgeId, startT, endEdgeId, endT, serializeOptions(options)));
5877
6014
  }
6015
+ /**
6016
+ * Moves a face by a translation vector, subject to kernel constraints.
6017
+ */
5878
6018
  moveFace(faceId, translation, options) {
5879
6019
  return parseEditResult(this.editor.moveFace(this.geometry.getKernelGeometry(), faceId, translation, serializeOptions(options)));
5880
6020
  }
6021
+ /**
6022
+ * Moves an edge by a translation vector, subject to kernel constraints.
6023
+ */
5881
6024
  moveEdge(edgeId, translation, options) {
5882
6025
  return parseEditResult(this.editor.moveEdge(this.geometry.getKernelGeometry(), edgeId, translation, serializeOptions(options)));
5883
6026
  }
6027
+ /**
6028
+ * Moves a vertex by a translation vector, subject to kernel constraints.
6029
+ */
5884
6030
  moveVertex(vertexId, translation, options) {
5885
6031
  return parseEditResult(this.editor.moveVertex(this.geometry.getKernelGeometry(), vertexId, translation, serializeOptions(options)));
5886
6032
  }
6033
+ /**
6034
+ * Inserts a vertex at parametric position `t` along an edge.
6035
+ */
5887
6036
  insertVertexOnEdge(edgeId, t, options) {
5888
6037
  return parseEditResult(this.editor.insertVertexOnEdge(this.geometry.getKernelGeometry(), edgeId, t, serializeOptions(options)));
5889
6038
  }
6039
+ /**
6040
+ * Splits an edge at parametric position `t`.
6041
+ */
5890
6042
  splitEdge(edgeId, t, options) {
5891
6043
  return parseEditResult(this.editor.splitEdge(this.geometry.getKernelGeometry(), edgeId, t, serializeOptions(options)));
5892
6044
  }
6045
+ /**
6046
+ * Creates a loop cut that propagates from the selected edge when possible.
6047
+ */
5893
6048
  loopCut(edgeId, t, options) {
5894
6049
  return parseEditResult(this.editor.loopCut(this.geometry.getKernelGeometry(), edgeId, t, serializeOptions(options)));
5895
6050
  }
6051
+ /**
6052
+ * Removes a vertex when the current topology allows the edit.
6053
+ */
5896
6054
  removeVertex(vertexId, options) {
5897
6055
  return parseEditResult(this.editor.removeVertex(this.geometry.getKernelGeometry(), vertexId, serializeOptions(options)));
5898
6056
  }
5899
6057
  }
6058
+ /**
6059
+ * Convenience factory for creating a freeform editor around a geometry wrapper.
6060
+ */
5900
6061
  function createFreeformEditor(geometry) {
5901
6062
  return new FreeformEditor(geometry);
5902
6063
  }
@@ -5914,7 +6075,7 @@ function toPlainVector3(value) {
5914
6075
  z: value.z,
5915
6076
  };
5916
6077
  }
5917
- function cloneVector(vector, fallback) {
6078
+ function cloneVector$1(vector, fallback) {
5918
6079
  var _a;
5919
6080
  return (_a = vector === null || vector === void 0 ? void 0 : vector.clone()) !== null && _a !== void 0 ? _a : new Vector3(...fallback);
5920
6081
  }
@@ -5928,10 +6089,10 @@ function normalizePlacement(placement) {
5928
6089
  }
5929
6090
  function toObjectTransformation(placement) {
5930
6091
  return {
5931
- anchor: cloneVector(placement.anchor, [0, 0, 0]),
5932
- translation: cloneVector(placement.translation, [0, 0, 0]),
5933
- rotation: cloneVector(placement.rotation, [0, 0, 0]),
5934
- scale: cloneVector(placement.scale, [1, 1, 1]),
6092
+ anchor: cloneVector$1(placement.anchor, [0, 0, 0]),
6093
+ translation: cloneVector$1(placement.translation, [0, 0, 0]),
6094
+ rotation: cloneVector$1(placement.rotation, [0, 0, 0]),
6095
+ scale: cloneVector$1(placement.scale, [1, 1, 1]),
5935
6096
  };
5936
6097
  }
5937
6098
  function toPlainObjectTransformation(transform) {
@@ -5942,7 +6103,7 @@ function toPlainObjectTransformation(transform) {
5942
6103
  scale: toPlainVector3(transform.scale),
5943
6104
  };
5944
6105
  }
5945
- function serializeBrepLike$1(value) {
6106
+ function serializeBrepLike$2(value) {
5946
6107
  return typeof value === "string" ? value : JSON.stringify(value);
5947
6108
  }
5948
6109
  function normalizeFreeformSerialized(source) {
@@ -5953,56 +6114,119 @@ function normalizeFreeformSerialized(source) {
5953
6114
  return source.getLocalBrepSerialized();
5954
6115
  }
5955
6116
  if (typeof source.getLocalBrepData === "function") {
5956
- return serializeBrepLike$1(source.getLocalBrepData());
6117
+ return serializeBrepLike$2(source.getLocalBrepData());
5957
6118
  }
5958
6119
  if (typeof source.getBrepSerialized === "function") {
5959
6120
  return source.getBrepSerialized();
5960
6121
  }
5961
6122
  if (typeof source.getBrepData === "function") {
5962
- return serializeBrepLike$1(source.getBrepData());
6123
+ return serializeBrepLike$2(source.getBrepData());
5963
6124
  }
5964
6125
  if (typeof source.getBrep === "function") {
5965
- return serializeBrepLike$1(source.getBrep());
6126
+ return serializeBrepLike$2(source.getBrep());
5966
6127
  }
5967
6128
  return JSON.stringify(source);
5968
6129
  }
6130
+ /**
6131
+ * Thin client-side wrapper around the kernel `OGFreeformGeometry` object.
6132
+ */
5969
6133
  class FreeformGeometry {
5970
6134
  constructor(geometry) {
5971
6135
  this.geometry = geometry;
5972
6136
  }
6137
+ /**
6138
+ * Returns the stable kernel-side id for this freeform geometry object.
6139
+ */
5973
6140
  getId() {
5974
6141
  return this.geometry.id;
5975
6142
  }
6143
+ /**
6144
+ * Returns the world-space serialized BRep payload.
6145
+ */
5976
6146
  getBrepSerialized() {
5977
6147
  return this.geometry.getBrepSerialized();
5978
6148
  }
6149
+ /**
6150
+ * Returns the local-space serialized BRep payload.
6151
+ */
5979
6152
  getLocalBrepSerialized() {
5980
6153
  return this.geometry.getLocalBrepSerialized();
5981
6154
  }
6155
+ /**
6156
+ * Returns the serialized triangle position buffer emitted by the kernel.
6157
+ */
5982
6158
  getGeometrySerialized() {
5983
6159
  return this.geometry.getGeometrySerialized();
5984
6160
  }
6161
+ /**
6162
+ * Returns world-space triangle positions as a plain number array.
6163
+ */
6164
+ getGeometryBuffer() {
6165
+ return Array.from(this.geometry.getGeometryBuffer());
6166
+ }
6167
+ /**
6168
+ * Returns local-space triangle positions as a plain number array.
6169
+ */
6170
+ getLocalGeometryBuffer() {
6171
+ return Array.from(this.geometry.getLocalGeometryBuffer());
6172
+ }
6173
+ /**
6174
+ * Returns the serialized outline buffer emitted by the kernel.
6175
+ */
5985
6176
  getOutlineGeometrySerialized() {
5986
6177
  return this.geometry.getOutlineGeometrySerialized();
5987
6178
  }
6179
+ /**
6180
+ * Returns world-space outline segment positions as a plain number array.
6181
+ */
6182
+ getOutlineGeometryBuffer() {
6183
+ return Array.from(this.geometry.getOutlineGeometryBuffer());
6184
+ }
6185
+ /**
6186
+ * Returns local-space outline segment positions as a plain number array.
6187
+ */
6188
+ getLocalOutlineGeometryBuffer() {
6189
+ return Array.from(this.geometry.getLocalOutlineGeometryBuffer());
6190
+ }
6191
+ /**
6192
+ * Returns the current normalized placement for this freeform geometry.
6193
+ */
5988
6194
  getPlacement() {
5989
6195
  return normalizePlacement(parseJson(this.geometry.getPlacementSerialized()));
5990
6196
  }
6197
+ /**
6198
+ * Replaces the full placement transform in one call.
6199
+ */
5991
6200
  setPlacement(transform) {
5992
6201
  this.geometry.setPlacementSerialized(JSON.stringify(toPlainObjectTransformation(transform)));
5993
6202
  }
6203
+ /**
6204
+ * Sets translation, rotation, and scale without changing the current anchor.
6205
+ */
5994
6206
  setTransform(translation, rotation, scale) {
5995
6207
  this.geometry.setTransform(translation, rotation, scale);
5996
6208
  }
6209
+ /**
6210
+ * Updates only the translation component of the placement.
6211
+ */
5997
6212
  setTranslation(translation) {
5998
6213
  this.geometry.setTranslation(translation);
5999
6214
  }
6215
+ /**
6216
+ * Updates only the rotation component of the placement.
6217
+ */
6000
6218
  setRotation(rotation) {
6001
6219
  this.geometry.setRotation(rotation);
6002
6220
  }
6221
+ /**
6222
+ * Updates only the scale component of the placement.
6223
+ */
6003
6224
  setScale(scale) {
6004
6225
  this.geometry.setScale(scale);
6005
6226
  }
6227
+ /**
6228
+ * Updates the explicit modeling anchor used by downstream transforms.
6229
+ */
6006
6230
  setAnchor(anchor) {
6007
6231
  this.geometry.setAnchor(anchor);
6008
6232
  }
@@ -6011,6 +6235,10 @@ class FreeformGeometry {
6011
6235
  return this.geometry;
6012
6236
  }
6013
6237
  }
6238
+ /**
6239
+ * Creates a `FreeformGeometry` wrapper from serialized BRep JSON, a parsed
6240
+ * BRep object, or another wrapper exposing BRep accessors.
6241
+ */
6014
6242
  function createFreeformGeometry(source, options) {
6015
6243
  var _a;
6016
6244
  const id = (_a = options === null || options === void 0 ? void 0 : options.id) !== null && _a !== void 0 ? _a : `freeform-${Date.now()}`;
@@ -6246,6 +6474,9 @@ class Line extends THREE.Line {
6246
6474
  }
6247
6475
 
6248
6476
  /* eslint-enable no-unused-vars */
6477
+ /**
6478
+ * Polyline wrapper backed by the kernel OGPolyline primitive.
6479
+ */
6249
6480
  class Polyline extends THREE.Line {
6250
6481
  set color(color) {
6251
6482
  this.options.color = color;
@@ -6473,6 +6704,9 @@ class Polyline extends THREE.Line {
6473
6704
  }
6474
6705
  }
6475
6706
 
6707
+ /**
6708
+ * Arc wrapper backed by the kernel OGArc primitive.
6709
+ */
6476
6710
  class Arc extends THREE.Line {
6477
6711
  set color(color) {
6478
6712
  this.options.color = color;
@@ -6680,6 +6914,9 @@ class Arc extends THREE.Line {
6680
6914
  }
6681
6915
 
6682
6916
  /* eslint-enable no-unused-vars */
6917
+ /**
6918
+ * Rectangle wrapper backed by the kernel OGRectangle primitive.
6919
+ */
6683
6920
  class Rectangle extends THREE.Line {
6684
6921
  // set width(width: number) {
6685
6922
  // this.options.width = width;
@@ -6915,6 +7152,9 @@ class Rectangle extends THREE.Line {
6915
7152
  }
6916
7153
 
6917
7154
  /* eslint-enable no-unused-vars */
7155
+ /**
7156
+ * Curve wrapper backed by the kernel OGCurve primitive.
7157
+ */
6918
7158
  class Curve extends THREE.Line {
6919
7159
  set color(color) {
6920
7160
  this.options.color = color;
@@ -7075,12 +7315,18 @@ function getOutlineResolution() {
7075
7315
  }
7076
7316
  return new THREE.Vector2(window.innerWidth, window.innerHeight);
7077
7317
  }
7318
+ /**
7319
+ * Clamps outline width inputs to the supported positive finite range.
7320
+ */
7078
7321
  function sanitizeOutlineWidth(width) {
7079
7322
  if (!Number.isFinite(width) || typeof width !== "number" || width <= 0) {
7080
7323
  return DEFAULT_OUTLINE_WIDTH;
7081
7324
  }
7082
7325
  return width;
7083
7326
  }
7327
+ /**
7328
+ * Creates either a thin or fat outline mesh from line segment positions.
7329
+ */
7084
7330
  function createShapeOutlineMesh({ positions, color = DEFAULT_OUTLINE_COLOR, fatOutlines = false, outlineWidth = DEFAULT_OUTLINE_WIDTH, }) {
7085
7331
  if (fatOutlines) {
7086
7332
  const fatGeometry = new LineSegmentsGeometry();
@@ -7099,6 +7345,9 @@ function createShapeOutlineMesh({ positions, color = DEFAULT_OUTLINE_COLOR, fatO
7099
7345
  const outlineMaterial = new THREE.LineBasicMaterial({ color });
7100
7346
  return new THREE.LineSegments(outlineGeometry, outlineMaterial);
7101
7347
  }
7348
+ /**
7349
+ * Disposes the geometry and material owned by an outline mesh.
7350
+ */
7102
7351
  function disposeShapeOutlineMesh(mesh) {
7103
7352
  if (!mesh) {
7104
7353
  return;
@@ -7110,6 +7359,9 @@ function disposeShapeOutlineMesh(mesh) {
7110
7359
  }
7111
7360
  mesh.material.dispose();
7112
7361
  }
7362
+ /**
7363
+ * Updates the color of an existing outline mesh in place.
7364
+ */
7113
7365
  function setShapeOutlineColor(mesh, color) {
7114
7366
  if (!mesh) {
7115
7367
  return;
@@ -7122,6 +7374,9 @@ function setShapeOutlineColor(mesh, color) {
7122
7374
  mesh.material.color.set(color);
7123
7375
  }
7124
7376
  }
7377
+ /**
7378
+ * Reads the current outline color, falling back when no outline exists.
7379
+ */
7125
7380
  function getShapeOutlineColor(mesh, fallback = DEFAULT_OUTLINE_COLOR) {
7126
7381
  if (!mesh) {
7127
7382
  return fallback;
@@ -7135,6 +7390,42 @@ function getShapeOutlineColor(mesh, fallback = DEFAULT_OUTLINE_COLOR) {
7135
7390
  return fallback;
7136
7391
  }
7137
7392
 
7393
+ /**
7394
+ * Extrudes the first face or wire in a local BRep payload into a closed solid BRep.
7395
+ */
7396
+ function extrudeBrepFace(source, height) {
7397
+ const extrudeExport = extrudeBrepFace$1;
7398
+ if (typeof extrudeExport !== "function") {
7399
+ throw new Error("extrudeBrepFace is not available in the loaded wasm package. Rebuild opengeometry wasm bindings.");
7400
+ }
7401
+ const kernelFunction = extrudeExport;
7402
+ return kernelFunction(resolveLocalBrepSerialized(source), height);
7403
+ }
7404
+ function resolveLocalBrepSerialized(source) {
7405
+ if (typeof source === "string") {
7406
+ return source;
7407
+ }
7408
+ if (typeof source.getLocalBrepSerialized === "function") {
7409
+ return source.getLocalBrepSerialized();
7410
+ }
7411
+ if (typeof source.getLocalBrepData === "function") {
7412
+ return serializeBrepLike$1(source.getLocalBrepData());
7413
+ }
7414
+ if (typeof source.getBrepSerialized === "function") {
7415
+ return source.getBrepSerialized();
7416
+ }
7417
+ if (typeof source.getBrepData === "function") {
7418
+ return serializeBrepLike$1(source.getBrepData());
7419
+ }
7420
+ if (typeof source.getBrep === "function") {
7421
+ return serializeBrepLike$1(source.getBrep());
7422
+ }
7423
+ return JSON.stringify(source);
7424
+ }
7425
+ function serializeBrepLike$1(value) {
7426
+ return typeof value === "string" ? value : JSON.stringify(value);
7427
+ }
7428
+
7138
7429
  var _BooleanResult_outlineMesh;
7139
7430
  /* eslint-enable no-unused-vars */
7140
7431
  const BOOLEAN_CREASE_ANGLE = Math.PI / 5;
@@ -7276,6 +7567,9 @@ class BooleanResult extends THREE.Mesh {
7276
7567
  _BooleanResult_outlineMesh = new WeakMap();
7277
7568
  /**
7278
7569
  * Computes a kernel-backed boolean union and returns a renderable result mesh.
7570
+ *
7571
+ * Accepts wrapper objects directly, including `Solid`, `Cuboid`, `Opening`,
7572
+ * and other shapes that expose BRep accessors.
7279
7573
  */
7280
7574
  function booleanUnion(lhs, rhs, options) {
7281
7575
  return executeBoolean("booleanUnion", lhs, rhs, options);
@@ -7288,16 +7582,34 @@ function booleanIntersection(lhs, rhs, options) {
7288
7582
  }
7289
7583
  /**
7290
7584
  * Computes a kernel-backed boolean subtraction and returns a renderable result mesh.
7585
+ *
7586
+ * Use this when you want a standalone helper rather than a shape-level
7587
+ * convenience method like `opening.subtractFrom(host)`.
7291
7588
  */
7292
7589
  function booleanSubtraction(lhs, rhs, options) {
7293
7590
  return executeBoolean("booleanSubtraction", lhs, rhs, options);
7294
7591
  }
7592
+ /**
7593
+ * Computes a kernel-backed repeated subtraction using a left-to-right cutter array.
7594
+ *
7595
+ * This is used by the shape-level `.subtract([...])` helpers so the heavy
7596
+ * boolean orchestration stays in the Rust/WASM layer instead of JavaScript.
7597
+ */
7598
+ function executeBooleanSubtractionMany(lhs, cutters, options) {
7599
+ const booleanExport = booleanSubtractionMany;
7600
+ if (typeof booleanExport !== "function") {
7601
+ throw new Error("booleanSubtractionMany is not available in the loaded wasm package. Rebuild opengeometry wasm bindings.");
7602
+ }
7603
+ const kernelFunction = booleanExport;
7604
+ const kernelOptions = serializeKernelOptions(options === null || options === void 0 ? void 0 : options.kernel);
7605
+ const kernelResult = kernelFunction(resolveOperandSerialized(lhs), JSON.stringify(cutters.map(resolveOperandPayload)), kernelOptions);
7606
+ return createBooleanResult(kernelResult, options);
7607
+ }
7295
7608
  /**
7296
7609
  * Normalizes mixed wrapper/raw operands, invokes the wasm boolean export, and
7297
7610
  * returns the renderable result wrapper.
7298
7611
  */
7299
7612
  function executeBoolean(exportName, lhs, rhs, options) {
7300
- var _a;
7301
7613
  const booleanExport = OGKernel[exportName];
7302
7614
  if (typeof booleanExport !== "function") {
7303
7615
  throw new Error(`${exportName} is not available in the loaded wasm package. Rebuild opengeometry wasm bindings.`);
@@ -7305,11 +7617,7 @@ function executeBoolean(exportName, lhs, rhs, options) {
7305
7617
  const kernelFunction = booleanExport;
7306
7618
  const kernelOptions = serializeKernelOptions(options === null || options === void 0 ? void 0 : options.kernel);
7307
7619
  const kernelResult = kernelFunction(resolveOperandSerialized(lhs), resolveOperandSerialized(rhs), kernelOptions);
7308
- const result = new BooleanResult(kernelResult, options);
7309
- if ((_a = options === null || options === void 0 ? void 0 : options.outline) !== null && _a !== void 0 ? _a : true) {
7310
- result.outline = true;
7311
- }
7312
- return result;
7620
+ return createBooleanResult(kernelResult, options);
7313
7621
  }
7314
7622
  /**
7315
7623
  * Accepts wrapper objects, raw BRep data, or serialized JSON and normalizes
@@ -7330,6 +7638,19 @@ function resolveOperandSerialized(operand) {
7330
7638
  }
7331
7639
  return serializeBrepLike(operand);
7332
7640
  }
7641
+ /**
7642
+ * Parses a boolean operand into a raw BRep payload so array-backed boolean
7643
+ * calls can serialize a JSON array of BReps instead of a JSON array of strings.
7644
+ */
7645
+ function resolveOperandPayload(operand) {
7646
+ const serialized = resolveOperandSerialized(operand);
7647
+ try {
7648
+ return JSON.parse(serialized);
7649
+ }
7650
+ catch (_a) {
7651
+ throw new Error("Boolean operands must resolve to valid serialized BRep JSON before array subtraction.");
7652
+ }
7653
+ }
7333
7654
  /**
7334
7655
  * Accepts either a parsed BRep object or an already serialized JSON payload
7335
7656
  * and always returns the canonical serialized form expected by the wasm API.
@@ -7352,6 +7673,14 @@ function serializeKernelOptions(options) {
7352
7673
  merge_coplanar_faces: options.mergeCoplanarFaces,
7353
7674
  });
7354
7675
  }
7676
+ function createBooleanResult(kernelResult, options) {
7677
+ var _a;
7678
+ const result = new BooleanResult(kernelResult, options);
7679
+ if ((_a = options === null || options === void 0 ? void 0 : options.outline) !== null && _a !== void 0 ? _a : true) {
7680
+ result.outline = true;
7681
+ }
7682
+ return result;
7683
+ }
7355
7684
  /**
7356
7685
  * Builds a display-quality outline buffer from the rendered mesh and falls back
7357
7686
  * to the kernel-provided edges when the client-side extraction is empty.
@@ -7372,50 +7701,322 @@ function getRenderableOutlinePositions(geometry, fallbackSerialized) {
7372
7701
  /**
7373
7702
  * Executes a kernel-backed subtraction for a shape wrapper against another boolean operand.
7374
7703
  */
7375
- function subtractShapeOperand(host, operand, options) {
7376
- return booleanSubtraction(host, operand, options);
7704
+ function subtractShapeOperand(host, operands, options) {
7705
+ if (!Array.isArray(operands)) {
7706
+ throw new Error("shape.subtract(...) now requires an operand array. Pass shape.subtract([operand], options) even for a single cutter.");
7707
+ }
7708
+ return executeBooleanSubtractionMany(host, operands, options);
7377
7709
  }
7378
7710
 
7379
- var _Polygon_outlineMesh;
7380
- class Polygon extends THREE.Mesh {
7711
+ var _Solid_outlineMesh;
7712
+ /**
7713
+ * Generic renderable BRep-backed solid used for extrusion outputs and other
7714
+ * kernel results that are not dedicated parametric shapes.
7715
+ */
7716
+ class Solid extends THREE.Mesh {
7381
7717
  set color(color) {
7382
7718
  this.options.color = color;
7383
- if (this.material instanceof THREE.MeshBasicMaterial) {
7719
+ if (this.material instanceof THREE.MeshStandardMaterial) {
7384
7720
  this.material.color.set(color);
7385
7721
  }
7386
7722
  }
7387
7723
  get color() {
7388
7724
  return this.options.color;
7389
7725
  }
7390
- // TODO: Make Options Optional
7391
- // constructor(vertices?: Vector3[]) // If no vertices are provided, it will be an empty polygon
7392
7726
  constructor(options) {
7393
- var _a, _b, _c, _d, _e;
7727
+ var _a, _b;
7394
7728
  super();
7395
7729
  this.options = {
7396
- vertices: [],
7397
- holes: [],
7730
+ brep: "{}",
7398
7731
  color: 0x00ff00,
7399
7732
  fatOutlines: false,
7400
7733
  outlineWidth: 1,
7734
+ anchor: new Vector3(0, 0, 0),
7401
7735
  translation: new Vector3(0, 0, 0),
7402
7736
  rotation: new Vector3(0, 0, 0),
7403
7737
  scale: new Vector3(1, 1, 1),
7404
7738
  };
7405
- _Polygon_outlineMesh.set(this, null);
7739
+ _Solid_outlineMesh.set(this, null);
7406
7740
  this._outlineEnabled = false;
7407
7741
  this._fatOutlines = false;
7408
7742
  this._outlineWidth = 1;
7409
7743
  this._outlineColor = 0x000000;
7410
- this.transformationMatrix = new THREE.Matrix4();
7411
- // private _placement: THREE.Vector3 = new THREE.Vector3(0, 0, 0);
7412
- // private _yaw: number = 0;
7413
- // Store local center offset to align outlines
7414
- // TODO: Can this be moved to Engine? It can increase performance | Needs to be used in other shapes too
7415
- this._geometryCenterOffset = new THREE.Vector3();
7416
- this.ogid = (_a = options === null || options === void 0 ? void 0 : options.ogid) !== null && _a !== void 0 ? _a : getUUID();
7417
- this.polygon = new OGPolygon(this.ogid);
7418
- this.options = Object.assign(Object.assign({}, this.options), options);
7744
+ this.ogid = (_a = options.ogid) !== null && _a !== void 0 ? _a : getUUID();
7745
+ this.options = Object.assign(Object.assign(Object.assign({}, this.options), options), { ogid: this.ogid, anchor: cloneVector(options.anchor, [0, 0, 0]), translation: cloneVector(options.translation, [0, 0, 0]), rotation: cloneVector(options.rotation, [0, 0, 0]), scale: cloneVector(options.scale, [1, 1, 1]) });
7746
+ this._fatOutlines = (_b = this.options.fatOutlines) !== null && _b !== void 0 ? _b : false;
7747
+ this._outlineWidth = sanitizeOutlineWidth(this.options.outlineWidth);
7748
+ this.options.fatOutlines = this._fatOutlines;
7749
+ this.options.outlineWidth = this._outlineWidth;
7750
+ this.solid = createFreeformGeometry(this.options.brep, {
7751
+ id: this.ogid,
7752
+ placement: this.getPlacementTransform(),
7753
+ });
7754
+ this.generateGeometry();
7755
+ }
7756
+ /**
7757
+ * Extrudes a face-like BRep source and wraps the result as a renderable solid.
7758
+ *
7759
+ * Prefer `polygon.extrude(height)` when the source is already a `Polygon`.
7760
+ */
7761
+ static extrude(source, height, options) {
7762
+ return new Solid(Object.assign(Object.assign({}, options), { brep: extrudeBrepFace(source, height) }));
7763
+ }
7764
+ /**
7765
+ * Returns the current placement values as cloned vectors.
7766
+ */
7767
+ getPlacement() {
7768
+ return clonePlacement(this.getPlacementTransform());
7769
+ }
7770
+ /**
7771
+ * Applies translation, rotation, and scale updates to the wrapped BRep.
7772
+ */
7773
+ setPlacement(placement) {
7774
+ var _a, _b, _c;
7775
+ this.options.translation = cloneVector((_a = placement.translation) !== null && _a !== void 0 ? _a : this.options.translation, [0, 0, 0]);
7776
+ this.options.rotation = cloneVector((_b = placement.rotation) !== null && _b !== void 0 ? _b : this.options.rotation, [0, 0, 0]);
7777
+ this.options.scale = cloneVector((_c = placement.scale) !== null && _c !== void 0 ? _c : this.options.scale, [1, 1, 1]);
7778
+ this.solid.setPlacement(this.getPlacementTransform());
7779
+ this.generateGeometry();
7780
+ }
7781
+ setTransform(translation, rotation, scale) {
7782
+ this.setPlacement({
7783
+ translation,
7784
+ rotation,
7785
+ scale,
7786
+ });
7787
+ }
7788
+ setTranslation(translation) {
7789
+ this.setPlacement({ translation });
7790
+ }
7791
+ setRotation(rotation) {
7792
+ this.setPlacement({ rotation });
7793
+ }
7794
+ setScale(scale) {
7795
+ this.setPlacement({ scale });
7796
+ }
7797
+ getAnchor() {
7798
+ return this.getPlacementTransform().anchor.clone();
7799
+ }
7800
+ setAnchor(anchor) {
7801
+ this.options.anchor = anchor.clone();
7802
+ this.solid.setPlacement(this.getPlacementTransform());
7803
+ this.generateGeometry();
7804
+ }
7805
+ /**
7806
+ * Solid is always convertible back to the freeform editing wrapper.
7807
+ */
7808
+ canConvertToFreeform() {
7809
+ return true;
7810
+ }
7811
+ /**
7812
+ * Returns a freeform wrapper for direct editing of this solid's BRep.
7813
+ */
7814
+ toFreeform(id = this.ogid) {
7815
+ if (!this.canConvertToFreeform()) {
7816
+ throw new Error("This entity cannot be converted to freeform.");
7817
+ }
7818
+ return createFreeformGeometry(this.getLocalBrepSerialized(), {
7819
+ id,
7820
+ placement: this.getPlacementTransform(),
7821
+ });
7822
+ }
7823
+ /**
7824
+ * Returns the world-space serialized BRep payload for this solid.
7825
+ */
7826
+ getBrepSerialized() {
7827
+ return this.solid.getBrepSerialized();
7828
+ }
7829
+ /**
7830
+ * Returns the local-space serialized BRep payload for this solid.
7831
+ */
7832
+ getLocalBrepSerialized() {
7833
+ return this.solid.getLocalBrepSerialized();
7834
+ }
7835
+ /**
7836
+ * Returns the parsed world-space BRep object for this solid.
7837
+ */
7838
+ getBrepData() {
7839
+ const brepSerialized = this.getBrepSerialized();
7840
+ if (!brepSerialized) {
7841
+ throw new Error("Brep data is not available for this solid.");
7842
+ }
7843
+ return JSON.parse(brepSerialized);
7844
+ }
7845
+ /**
7846
+ * Subtracts one or more boolean operands from this solid.
7847
+ *
7848
+ * This is the main shape-level boolean workflow after operations like
7849
+ * `polygon.extrude(height)` or `Solid.extrude(...)`.
7850
+ */
7851
+ subtract(operands, options) {
7852
+ return subtractShapeOperand(this, operands, options);
7853
+ }
7854
+ /**
7855
+ * Rebuilds the visible mesh and outline from the current freeform geometry.
7856
+ */
7857
+ generateGeometry() {
7858
+ var _a;
7859
+ const bufferData = this.solid.getGeometryBuffer();
7860
+ this.writePositionsToGeometry(this.geometry, bufferData);
7861
+ if (this.material instanceof THREE.MeshStandardMaterial) {
7862
+ this.material.color.set(this.options.color);
7863
+ this.material.transparent = true;
7864
+ this.material.opacity = 0.6;
7865
+ }
7866
+ else {
7867
+ if (Array.isArray(this.material)) {
7868
+ this.material.forEach((material) => material.dispose());
7869
+ }
7870
+ else {
7871
+ this.material.dispose();
7872
+ }
7873
+ this.material = new THREE.MeshStandardMaterial({
7874
+ color: this.options.color,
7875
+ transparent: true,
7876
+ opacity: 0.6,
7877
+ });
7878
+ }
7879
+ if (bufferData.length > 0) {
7880
+ this.geometry.computeVertexNormals();
7881
+ this.geometry.computeBoundingBox();
7882
+ this.geometry.computeBoundingSphere();
7883
+ }
7884
+ else {
7885
+ this.geometry.deleteAttribute("normal");
7886
+ this.geometry.boundingBox = null;
7887
+ this.geometry.boundingSphere = null;
7888
+ }
7889
+ if (!this._outlineEnabled) {
7890
+ return;
7891
+ }
7892
+ const outlineData = this.solid.getOutlineGeometryBuffer();
7893
+ if (!__classPrivateFieldGet(this, _Solid_outlineMesh, "f")) {
7894
+ this.outline = true;
7895
+ return;
7896
+ }
7897
+ if (__classPrivateFieldGet(this, _Solid_outlineMesh, "f") instanceof THREE.LineSegments) {
7898
+ this.writePositionsToGeometry(__classPrivateFieldGet(this, _Solid_outlineMesh, "f").geometry, outlineData);
7899
+ __classPrivateFieldGet(this, _Solid_outlineMesh, "f").geometry.computeBoundingBox();
7900
+ __classPrivateFieldGet(this, _Solid_outlineMesh, "f").geometry.computeBoundingSphere();
7901
+ return;
7902
+ }
7903
+ const fatGeometry = __classPrivateFieldGet(this, _Solid_outlineMesh, "f").geometry;
7904
+ fatGeometry.setPositions(outlineData);
7905
+ const fatOutline = __classPrivateFieldGet(this, _Solid_outlineMesh, "f");
7906
+ (_a = fatOutline.computeLineDistances) === null || _a === void 0 ? void 0 : _a.call(fatOutline);
7907
+ }
7908
+ set outlineColor(color) {
7909
+ this._outlineColor = color;
7910
+ setShapeOutlineColor(__classPrivateFieldGet(this, _Solid_outlineMesh, "f"), color);
7911
+ }
7912
+ get outlineColor() {
7913
+ return getShapeOutlineColor(__classPrivateFieldGet(this, _Solid_outlineMesh, "f"), this._outlineColor);
7914
+ }
7915
+ set outline(enable) {
7916
+ this._outlineEnabled = enable;
7917
+ this.clearOutlineMesh();
7918
+ if (enable) {
7919
+ __classPrivateFieldSet(this, _Solid_outlineMesh, createShapeOutlineMesh({
7920
+ positions: this.solid.getOutlineGeometryBuffer(),
7921
+ color: this._outlineColor,
7922
+ fatOutlines: this._fatOutlines,
7923
+ outlineWidth: this._outlineWidth,
7924
+ }), "f");
7925
+ this.add(__classPrivateFieldGet(this, _Solid_outlineMesh, "f"));
7926
+ }
7927
+ }
7928
+ get outline() {
7929
+ return this._outlineEnabled;
7930
+ }
7931
+ set fatOutlines(value) {
7932
+ this._fatOutlines = value;
7933
+ this.options.fatOutlines = value;
7934
+ if (this._outlineEnabled) {
7935
+ this.outline = true;
7936
+ }
7937
+ }
7938
+ get fatOutlines() {
7939
+ return this._fatOutlines;
7940
+ }
7941
+ set outlineWidth(value) {
7942
+ this._outlineWidth = sanitizeOutlineWidth(value);
7943
+ this.options.outlineWidth = this._outlineWidth;
7944
+ if (this._outlineEnabled) {
7945
+ this.outline = true;
7946
+ }
7947
+ }
7948
+ get outlineWidth() {
7949
+ return this._outlineWidth;
7950
+ }
7951
+ clearOutlineMesh() {
7952
+ if (!__classPrivateFieldGet(this, _Solid_outlineMesh, "f")) {
7953
+ return;
7954
+ }
7955
+ this.remove(__classPrivateFieldGet(this, _Solid_outlineMesh, "f"));
7956
+ disposeShapeOutlineMesh(__classPrivateFieldGet(this, _Solid_outlineMesh, "f"));
7957
+ __classPrivateFieldSet(this, _Solid_outlineMesh, null, "f");
7958
+ }
7959
+ getPlacementTransform() {
7960
+ return toObjectTransformation$1({
7961
+ anchor: cloneVector(this.options.anchor, [0, 0, 0]),
7962
+ translation: cloneVector(this.options.translation, [0, 0, 0]),
7963
+ rotation: cloneVector(this.options.rotation, [0, 0, 0]),
7964
+ scale: cloneVector(this.options.scale, [1, 1, 1]),
7965
+ });
7966
+ }
7967
+ writePositionsToGeometry(geometry, positions) {
7968
+ const attribute = geometry.getAttribute("position");
7969
+ if (!(attribute instanceof THREE.BufferAttribute) ||
7970
+ attribute.itemSize !== 3 ||
7971
+ attribute.count !== positions.length / 3) {
7972
+ geometry.setAttribute("position", new THREE.Float32BufferAttribute(positions, 3));
7973
+ return;
7974
+ }
7975
+ attribute.array.set(positions);
7976
+ attribute.needsUpdate = true;
7977
+ }
7978
+ }
7979
+ _Solid_outlineMesh = new WeakMap();
7980
+ function cloneVector(vector, fallback) {
7981
+ var _a;
7982
+ return (_a = vector === null || vector === void 0 ? void 0 : vector.clone()) !== null && _a !== void 0 ? _a : new Vector3(...fallback);
7983
+ }
7984
+
7985
+ var _Polygon_outlineMesh;
7986
+ /**
7987
+ * Planar polygon mesh with support for holes, booleans, and extrusion to `Solid`.
7988
+ */
7989
+ class Polygon extends THREE.Mesh {
7990
+ set color(color) {
7991
+ this.options.color = color;
7992
+ if (this.material instanceof THREE.MeshBasicMaterial) {
7993
+ this.material.color.set(color);
7994
+ }
7995
+ }
7996
+ get color() {
7997
+ return this.options.color;
7998
+ }
7999
+ constructor(options) {
8000
+ var _a, _b, _c, _d, _e;
8001
+ super();
8002
+ this.options = {
8003
+ vertices: [],
8004
+ holes: [],
8005
+ color: 0x00ff00,
8006
+ fatOutlines: false,
8007
+ outlineWidth: 1,
8008
+ translation: new Vector3(0, 0, 0),
8009
+ rotation: new Vector3(0, 0, 0),
8010
+ scale: new Vector3(1, 1, 1),
8011
+ };
8012
+ _Polygon_outlineMesh.set(this, null);
8013
+ this._outlineEnabled = false;
8014
+ this._fatOutlines = false;
8015
+ this._outlineWidth = 1;
8016
+ this._outlineColor = 0x000000;
8017
+ this.ogid = (_a = options === null || options === void 0 ? void 0 : options.ogid) !== null && _a !== void 0 ? _a : getUUID();
8018
+ this.polygon = new OGPolygon(this.ogid);
8019
+ this.options = Object.assign(Object.assign({}, this.options), options);
7419
8020
  this.options.ogid = this.ogid;
7420
8021
  this.setConfig({
7421
8022
  vertices: this.options.vertices.map((vertex) => vertex.clone()),
@@ -7429,19 +8030,6 @@ class Polygon extends THREE.Mesh {
7429
8030
  rotation: (_d = this.options.rotation) === null || _d === void 0 ? void 0 : _d.clone(),
7430
8031
  scale: (_e = this.options.scale) === null || _e === void 0 ? void 0 : _e.clone(),
7431
8032
  });
7432
- // TODO: THIS MIGHT HELP WITH SHARING THE POSITION with KERNEL when something is changed
7433
- // const originalSet = this.position.set.bind(this.position);
7434
- // this.position.set = (x: number, y: number, z: number) => {
7435
- // console.log(`Position set to (${x}, ${y}, ${z})`);
7436
- // // your custom logic here (e.g., notify OpenGeometry)
7437
- // return originalSet(x, y, z);
7438
- // };
7439
- // // Optional: Override copy if you're using .copy() too
7440
- // const originalCopy = this.position.copy.bind(this.position);
7441
- // this.position.copy = (v: THREE.Vector3) => {
7442
- // console.log(`Position copied from ${v.x}, ${v.y}, ${v.z}`);
7443
- // return originalCopy(v);
7444
- // };
7445
8033
  }
7446
8034
  validateOptions() {
7447
8035
  if (!this.options) {
@@ -7523,12 +8111,21 @@ class Polygon extends THREE.Mesh {
7523
8111
  scale: this.options.scale,
7524
8112
  });
7525
8113
  }
8114
+ /**
8115
+ * Returns the editing capability payload advertised by parametric wrappers.
8116
+ */
7526
8117
  getEditCapabilities() {
7527
8118
  return createParametricEditCapabilities("polygon", "profile");
7528
8119
  }
8120
+ /**
8121
+ * Polygon always supports conversion into the freeform editing wrapper.
8122
+ */
7529
8123
  canConvertToFreeform() {
7530
8124
  return true;
7531
8125
  }
8126
+ /**
8127
+ * Returns a freeform wrapper for direct BRep editing of this polygon.
8128
+ */
7532
8129
  toFreeform(id = this.ogid) {
7533
8130
  if (!this.canConvertToFreeform()) {
7534
8131
  throw new Error("This entity cannot be converted to freeform.");
@@ -7538,62 +8135,8 @@ class Polygon extends THREE.Mesh {
7538
8135
  placement: this.getPlacement(),
7539
8136
  });
7540
8137
  }
7541
- // /**
7542
- // * Sets the placement of the polygon in 3D space.
7543
- // * @param x X-coordinate
7544
- // * @param y Y-coordinate
7545
- // * @param z Z-coordinate
7546
- // */
7547
- // placement(x: number, y: number, z: number) {
7548
- // this._placement.set(x, y, z);
7549
- // // Do the recalculation of position based on the placement
7550
- // const clonedObject = this.clone();
7551
- // clonedObject.rotation.set(0, 0, 0);
7552
- // clonedObject.geometry.computeBoundingBox();
7553
- // if (!clonedObject.geometry.boundingBox) return;
7554
- // const center = new THREE.Vector3();
7555
- // clonedObject.geometry.boundingBox.getCenter(center);
7556
- // const min = clonedObject.geometry.boundingBox.min;
7557
- // this.position.set(
7558
- // center.x + this._placement.x - min.x,
7559
- // // this._placement.y,
7560
- // 0.01, // Set Y to a small value to avoid z-fighting
7561
- // center.z + this._placement.z - min.z
7562
- // );
7563
- // }
7564
- // positionToPlacement() {
7565
- // const clonedObject = this.clone();
7566
- // clonedObject.rotation.set(0, 0, 0);
7567
- // clonedObject.geometry.computeBoundingBox();
7568
- // if (!clonedObject.geometry.boundingBox) return;
7569
- // const min = clonedObject.geometry.boundingBox.min;
7570
- // this._placement.set(
7571
- // this.position.x + min.x,
7572
- // this.position.y + min.y,
7573
- // this.position.z + min.z
7574
- // );
7575
- // // console.log("Placement set to:", this._placement.x, this._placement.y, this._placement.z);
7576
- // }
7577
- // /**
7578
- // * Rotates the polygon around the Y-axis.
7579
- // * @param angle Rotation angle in Degrees
7580
- // */
7581
- // set yaw(angle: number) {
7582
- // this._yaw = angle;
7583
- // this.rotation.set(0, 0, 0);
7584
- // this.rotation.y = THREE.MathUtils.degToRad(this._yaw);
7585
- // }
7586
- // get yaw() {
7587
- // return this._yaw;
7588
- // }
7589
8138
  cleanGeometry() {
7590
- this.geometry.dispose();
7591
- if (Array.isArray(this.material)) {
7592
- this.material.forEach(mat => mat.dispose());
7593
- }
7594
- else {
7595
- this.material.dispose();
7596
- }
8139
+ this.disposeResources();
7597
8140
  }
7598
8141
  generateGeometry() {
7599
8142
  var _a;
@@ -7643,24 +8186,6 @@ class Polygon extends THREE.Mesh {
7643
8186
  fatGeometry.setPositions(outlineData);
7644
8187
  const fatOutline = __classPrivateFieldGet(this, _Polygon_outlineMesh, "f");
7645
8188
  (_a = fatOutline.computeLineDistances) === null || _a === void 0 ? void 0 : _a.call(fatOutline);
7646
- // this.geometry.computeBoundingBox();
7647
- // const originalCenter = new THREE.Vector3();
7648
- // this.geometry.boundingBox?.getCenter(originalCenter);
7649
- // console.log("Original Center:", originalCenter.x, originalCenter.y, originalCenter.z);
7650
- // this.geometry.center();
7651
- // this.geometry.computeBoundingBox();
7652
- // const newCenter = new THREE.Vector3();
7653
- // this.geometry.boundingBox?.getCenter(newCenter);
7654
- // console.log("New Center after centering:", newCenter.x, newCenter.y, newCenter.z);
7655
- // if (!this.geometry.boundingBox) return;
7656
- // const min = this.geometry.boundingBox.min;
7657
- // // console.log("Position before centering:", this.position.x, this.position.y, this.position.z);
7658
- // console.log("Bounding Box Min:", min.x, min.y, min.z);
7659
- // this.position.set(-min.x, 0, -min.z);
7660
- // if (this._placement) {
7661
- // this.placement(this._placement.x, this._placement.y, this._placement.z);
7662
- // }
7663
- // console.log("New Position after centering:", this.position.x, this.position.y, this.position.z);
7664
8189
  }
7665
8190
  addVertices(vertices) {
7666
8191
  if (!this.polygon)
@@ -7669,59 +8194,6 @@ class Polygon extends THREE.Mesh {
7669
8194
  vertices: vertices.map((vertex) => vertex.clone()),
7670
8195
  });
7671
8196
  }
7672
- saveTransformationToBREP() {
7673
- if (!this.polygon)
7674
- return;
7675
- }
7676
- // /**
7677
- // * Rotates the object around the Y-axis.
7678
- // * @param angle Rotation angle in Degrees
7679
- // * @returns
7680
- // * @summary If rotation methods from threejs is used, it will rotate around the first vertex which might not be desired.
7681
- // */
7682
- // rotateOnYAxis(angle: number) {
7683
- // if (!this.polygon) return;
7684
- // }
7685
- // resetVertices() {
7686
- // if (!this.polygon) return;
7687
- // this.layerVertices = [];
7688
- // this.geometry.dispose();
7689
- // this.polygon?.clear_vertices();
7690
- // this.isTriangulated = false;
7691
- // }
7692
- // addVertex(threeVertex: Vector3) {
7693
- // if (this.isTriangulated) {
7694
- // this.layerVertices = [];
7695
- // this.geometry.dispose();
7696
- // this.polygon?.clear_vertices();
7697
- // this.isTriangulated = false;
7698
- // for (const vertex of this.layerBackVertices) {
7699
- // this.layerVertices.push(vertex.clone());
7700
- // }
7701
- // };
7702
- // const backupVertex = new Vector3(
7703
- // parseFloat(threeVertex.x.toFixed(2)),
7704
- // 0,
7705
- // parseFloat(threeVertex.z.toFixed(2))
7706
- // );
7707
- // this.layerBackVertices.push(backupVertex);
7708
- // const vertex = new Vector3(
7709
- // parseFloat(threeVertex.x.toFixed(2)),
7710
- // // when doing the parse operation getting -0 instead of 0
7711
- // 0,
7712
- // parseFloat(threeVertex.z.toFixed(2))
7713
- // );
7714
- // this.layerVertices.push(vertex);
7715
- // if (this.layerVertices.length > 3) {
7716
- // this.polygon?.add_vertices(this.layerVertices);
7717
- // const bufFlush = this.polygon?.triangulate();
7718
- // if (!bufFlush) {
7719
- // return;
7720
- // }
7721
- // this.addFlushBufferToScene(bufFlush);
7722
- // this.isTriangulated = true;
7723
- // }
7724
- // }
7725
8197
  addHole(holeVertices) {
7726
8198
  var _a, _b;
7727
8199
  if (!this.polygon)
@@ -7734,29 +8206,32 @@ class Polygon extends THREE.Mesh {
7734
8206
  holes: ((_b = this.options.holes) !== null && _b !== void 0 ? _b : []).map((hole) => hole.map((vertex) => vertex.clone())),
7735
8207
  });
7736
8208
  }
7737
- // extrude(height: number) {
7738
- // if (!this.polygon) return;
7739
- // const extruded_buff = this.polygon.extrude_by_height(height);
7740
- // console.log(extruded_buff);
7741
- // this.generateExtrudedGeometry(extruded_buff);
7742
- // }
7743
- // generateExtrudedGeometry(extruded_buff: string) {
7744
- // // THIS WORKS
7745
- // const flushBuffer = JSON.parse(extruded_buff);
7746
- // console.log(flushBuffer);
7747
- // const geometry = new THREE.BufferGeometry();
7748
- // geometry.setAttribute("position", new THREE.BufferAttribute(new Float32Array(flushBuffer), 3));
7749
- // geometry.computeVertexNormals();
7750
- // this.geometry = geometry;
7751
- // const material = new THREE.MeshStandardMaterial({
7752
- // color: 0x00ff00,
7753
- // side: THREE.FrontSide,
7754
- // transparent: true,
7755
- // opacity: 0.5,
7756
- // // wireframe: true
7757
- // });
7758
- // this.material = material;
7759
- // }
8209
+ /**
8210
+ * Builds a kernel-backed `Solid` by extruding this polygon face by `height`.
8211
+ *
8212
+ * This is the recommended public path when a browser CAD or AEC workflow
8213
+ * starts from a planar profile and needs a boolean-ready solid.
8214
+ */
8215
+ extrude(height) {
8216
+ const config = this.getConfig();
8217
+ const placement = this.getPlacement();
8218
+ const solid = new Solid({
8219
+ brep: extrudeBrepFace(this.polygon.get_local_brep_serialized(), height),
8220
+ color: config.color,
8221
+ fatOutlines: config.fatOutlines,
8222
+ outlineWidth: config.outlineWidth,
8223
+ anchor: this.getAnchor(),
8224
+ translation: placement.translation.clone(),
8225
+ rotation: placement.rotation.clone(),
8226
+ scale: placement.scale.clone(),
8227
+ });
8228
+ solid.outline = this.outline;
8229
+ solid.outlineColor = this.outlineColor;
8230
+ return solid;
8231
+ }
8232
+ /**
8233
+ * Returns the serialized BRep payload for this polygon.
8234
+ */
7760
8235
  getBrepData() {
7761
8236
  if (!this.polygon)
7762
8237
  return null;
@@ -7764,10 +8239,10 @@ class Polygon extends THREE.Mesh {
7764
8239
  return brepData;
7765
8240
  }
7766
8241
  /**
7767
- * Subtracts another boolean operand from this polygon.
8242
+ * Subtracts one or more boolean operands from this polygon.
7768
8243
  */
7769
- subtract(operand, options) {
7770
- return subtractShapeOperand(this, operand, options);
8244
+ subtract(operands, options) {
8245
+ return subtractShapeOperand(this, operands, options);
7771
8246
  }
7772
8247
  set outlineColor(color) {
7773
8248
  this._outlineColor = color;
@@ -7776,7 +8251,6 @@ class Polygon extends THREE.Mesh {
7776
8251
  get outlineColor() {
7777
8252
  return getShapeOutlineColor(__classPrivateFieldGet(this, _Polygon_outlineMesh, "f"), this._outlineColor);
7778
8253
  }
7779
- // TODO: Do we need a separate method for Hole Outlines?
7780
8254
  set outline(enable) {
7781
8255
  this._outlineEnabled = enable;
7782
8256
  this.clearOutlineMesh();
@@ -7788,8 +8262,6 @@ class Polygon extends THREE.Mesh {
7788
8262
  fatOutlines: this._fatOutlines,
7789
8263
  outlineWidth: this._outlineWidth,
7790
8264
  }), "f");
7791
- // this.#outlineMesh.geometry.center();
7792
- // this.#outlineMesh.applyMatrix4(this.transformationMatrix);
7793
8265
  this.add(__classPrivateFieldGet(this, _Polygon_outlineMesh, "f"));
7794
8266
  }
7795
8267
  }
@@ -7816,20 +8288,8 @@ class Polygon extends THREE.Mesh {
7816
8288
  get outlineWidth() {
7817
8289
  return this._outlineWidth;
7818
8290
  }
7819
- // bTree() {
7820
- // if (!this.polygon) return;
7821
- // const bTree = this.polygon.binary_tree();
7822
- // const parsedData = JSON.parse(bTree);
7823
- // console.log(parsedData);
7824
- // }
7825
8291
  disposeGeometryMaterial() {
7826
- if (this.geometry) {
7827
- this.geometry.dispose();
7828
- }
7829
- if (this.material instanceof THREE.Material) {
7830
- this.material.dispose();
7831
- }
7832
- this.clearOutlineMesh();
8292
+ this.disposeResources();
7833
8293
  }
7834
8294
  clearOutlineMesh() {
7835
8295
  if (!__classPrivateFieldGet(this, _Polygon_outlineMesh, "f")) {
@@ -7840,20 +8300,7 @@ class Polygon extends THREE.Mesh {
7840
8300
  __classPrivateFieldSet(this, _Polygon_outlineMesh, null, "f");
7841
8301
  }
7842
8302
  dispose() {
7843
- // // console.log("Disposing OG - Polygon");
7844
- // this.geometry.dispose();
7845
- // if (this.material instanceof THREE.Material) {
7846
- // this.material.dispose();
7847
- // }
7848
- // if (this.#outlineMesh) {
7849
- // this.#outlineMesh.geometry.dispose();
7850
- // if (this.#outlineMesh.material instanceof THREE.Material) {
7851
- // this.#outlineMesh.material.dispose();
7852
- // }
7853
- // }
7854
- // this.polygon = null;
7855
- // this.layerVertices = [];
7856
- // this.layerBackVertices = [];
8303
+ this.disposeResources();
7857
8304
  }
7858
8305
  writePositionsToGeometry(geometry, positions) {
7859
8306
  const existing = geometry.getAttribute("position");
@@ -7867,10 +8314,25 @@ class Polygon extends THREE.Mesh {
7867
8314
  array.set(positions);
7868
8315
  existing.needsUpdate = true;
7869
8316
  }
8317
+ disposeResources() {
8318
+ if (this.geometry) {
8319
+ this.geometry.dispose();
8320
+ }
8321
+ if (Array.isArray(this.material)) {
8322
+ this.material.forEach((material) => material.dispose());
8323
+ }
8324
+ else if (this.material instanceof THREE.Material) {
8325
+ this.material.dispose();
8326
+ }
8327
+ this.clearOutlineMesh();
8328
+ }
7870
8329
  }
7871
8330
  _Polygon_outlineMesh = new WeakMap();
7872
8331
 
7873
8332
  var _Cylinder_outlineMesh;
8333
+ /**
8334
+ * Cylinder wrapper backed by the kernel cylindrical primitive.
8335
+ */
7874
8336
  class Cylinder extends THREE.Mesh {
7875
8337
  set radius(value) {
7876
8338
  this.setConfig({ radius: value });
@@ -8072,10 +8534,10 @@ class Cylinder extends THREE.Mesh {
8072
8534
  return JSON.parse(brepData);
8073
8535
  }
8074
8536
  /**
8075
- * Subtracts another boolean operand, such as an Opening, from this cylinder.
8537
+ * Subtracts one or more boolean operands, such as Opening volumes, from this cylinder.
8076
8538
  */
8077
- subtract(operand, options) {
8078
- return subtractShapeOperand(this, operand, options);
8539
+ subtract(operands, options) {
8540
+ return subtractShapeOperand(this, operands, options);
8079
8541
  }
8080
8542
  set outline(enable) {
8081
8543
  this._outlineEnabled = enable;
@@ -8141,6 +8603,9 @@ class Cylinder extends THREE.Mesh {
8141
8603
  _Cylinder_outlineMesh = new WeakMap();
8142
8604
 
8143
8605
  var _Cuboid_outlineMesh;
8606
+ /**
8607
+ * Box-shaped solid wrapper backed by the kernel cuboid primitive.
8608
+ */
8144
8609
  class Cuboid extends THREE.Mesh {
8145
8610
  set width(value) {
8146
8611
  this.setConfig({ width: value });
@@ -8280,10 +8745,10 @@ class Cuboid extends THREE.Mesh {
8280
8745
  return JSON.parse(brepData);
8281
8746
  }
8282
8747
  /**
8283
- * Subtracts another boolean operand, such as an Opening, from this cuboid.
8748
+ * Subtracts one or more boolean operands, such as Opening volumes, from this cuboid.
8284
8749
  */
8285
- subtract(operand, options) {
8286
- return subtractShapeOperand(this, operand, options);
8750
+ subtract(operands, options) {
8751
+ return subtractShapeOperand(this, operands, options);
8287
8752
  }
8288
8753
  set outline(enable) {
8289
8754
  this._outlineEnabled = enable;
@@ -8395,6 +8860,9 @@ class Cuboid extends THREE.Mesh {
8395
8860
  _Cuboid_outlineMesh = new WeakMap();
8396
8861
 
8397
8862
  var _Opening_outlineMesh;
8863
+ /**
8864
+ * Opening wrapper used as a subtractive solid in architectural workflows.
8865
+ */
8398
8866
  class Opening extends THREE.Mesh {
8399
8867
  set width(value) {
8400
8868
  this.setConfig({ width: value });
@@ -8602,16 +9070,19 @@ class Opening extends THREE.Mesh {
8602
9070
  return JSON.parse(brepData);
8603
9071
  }
8604
9072
  /**
8605
- * Subtracts another boolean operand from this opening volume.
9073
+ * Subtracts one or more boolean operands from this opening volume.
8606
9074
  */
8607
- subtract(operand, options) {
8608
- return subtractShapeOperand(this, operand, options);
9075
+ subtract(operands, options) {
9076
+ return subtractShapeOperand(this, operands, options);
8609
9077
  }
8610
9078
  /**
8611
9079
  * Uses this opening volume to cut a host shape.
9080
+ *
9081
+ * Prefer this helper for wall, slab, and other host-cutting workflows in
9082
+ * browser-based AEC/BIM tools.
8612
9083
  */
8613
9084
  subtractFrom(host, options) {
8614
- return subtractShapeOperand(host, this, options);
9085
+ return booleanSubtraction(host, this, options);
8615
9086
  }
8616
9087
  set outline(enable) {
8617
9088
  this._outlineEnabled = enable;
@@ -8681,6 +9152,9 @@ _Opening_outlineMesh = new WeakMap();
8681
9152
 
8682
9153
  var _Sphere_outlineMesh;
8683
9154
  /* eslint-enable no-unused-vars */
9155
+ /**
9156
+ * Sphere wrapper backed by the kernel sphere primitive.
9157
+ */
8684
9158
  class Sphere extends THREE.Mesh {
8685
9159
  set radius(value) {
8686
9160
  this.setConfig({ radius: value });
@@ -8882,10 +9356,10 @@ class Sphere extends THREE.Mesh {
8882
9356
  return JSON.parse(brepData);
8883
9357
  }
8884
9358
  /**
8885
- * Subtracts another boolean operand, such as an Opening, from this sphere.
9359
+ * Subtracts one or more boolean operands, such as Opening volumes, from this sphere.
8886
9360
  */
8887
- subtract(operand, options) {
8888
- return subtractShapeOperand(this, operand, options);
9361
+ subtract(operands, options) {
9362
+ return subtractShapeOperand(this, operands, options);
8889
9363
  }
8890
9364
  set outline(enable) {
8891
9365
  this._outlineEnabled = enable;
@@ -8954,6 +9428,9 @@ class Sphere extends THREE.Mesh {
8954
9428
  _Sphere_outlineMesh = new WeakMap();
8955
9429
 
8956
9430
  var _Wedge_outlineMesh;
9431
+ /**
9432
+ * Wedge wrapper backed by the kernel wedge primitive.
9433
+ */
8957
9434
  class Wedge extends THREE.Mesh {
8958
9435
  set color(color) {
8959
9436
  this.options.color = color;
@@ -9147,10 +9624,10 @@ class Wedge extends THREE.Mesh {
9147
9624
  return JSON.parse(brepData);
9148
9625
  }
9149
9626
  /**
9150
- * Subtracts another boolean operand, such as an Opening, from this wedge.
9627
+ * Subtracts one or more boolean operands, such as Opening volumes, from this wedge.
9151
9628
  */
9152
- subtract(operand, options) {
9153
- return subtractShapeOperand(this, operand, options);
9629
+ subtract(operands, options) {
9630
+ return subtractShapeOperand(this, operands, options);
9154
9631
  }
9155
9632
  set outline(enable) {
9156
9633
  this._outlineEnabled = enable;
@@ -9220,6 +9697,9 @@ _Wedge_outlineMesh = new WeakMap();
9220
9697
 
9221
9698
  var _Sweep_outlineMesh;
9222
9699
  /* eslint-enable no-unused-vars */
9700
+ /**
9701
+ * Sweep wrapper backed by the kernel sweep primitive.
9702
+ */
9223
9703
  class Sweep extends THREE.Mesh {
9224
9704
  set color(color) {
9225
9705
  this.options.color = color;
@@ -9443,10 +9923,10 @@ class Sweep extends THREE.Mesh {
9443
9923
  return JSON.parse(brepData);
9444
9924
  }
9445
9925
  /**
9446
- * Subtracts another boolean operand, such as an Opening, from this sweep.
9926
+ * Subtracts one or more boolean operands, such as Opening volumes, from this sweep.
9447
9927
  */
9448
- subtract(operand, options) {
9449
- return subtractShapeOperand(this, operand, options);
9928
+ subtract(operands, options) {
9929
+ return subtractShapeOperand(this, operands, options);
9450
9930
  }
9451
9931
  set outline(enable) {
9452
9932
  this._outlineEnabled = enable;
@@ -9867,11 +10347,7 @@ function createWallFromOffsetsExample(scene) {
9867
10347
  * Builds a complete operand/result scene group for a boolean example page.
9868
10348
  */
9869
10349
  function createBooleanExample(operation, options) {
9870
- const preset = options.mode === "solid"
9871
- ? createSolidPreset(operation, options)
9872
- : options.mode === "polygon"
9873
- ? createPolygonPreset(operation, options)
9874
- : createExtrudedPreset(operation, options);
10350
+ const preset = createPreset(operation, options);
9875
10351
  const execute = getBooleanExecutor(operation);
9876
10352
  const result = execute(preset.lhsOperand, preset.rhsOperand, options);
9877
10353
  const group = new THREE.Group();
@@ -9887,6 +10363,16 @@ function createBooleanExample(operation, options) {
9887
10363
  description: preset.description,
9888
10364
  };
9889
10365
  }
10366
+ function createPreset(operation, options) {
10367
+ switch (options.mode) {
10368
+ case "solid":
10369
+ return createSolidPreset(operation, options);
10370
+ case "polygon":
10371
+ return createPolygonPreset(operation, options);
10372
+ case "extruded":
10373
+ return createExtrudedPreset(operation, options);
10374
+ }
10375
+ }
9890
10376
  /**
9891
10377
  * Builds the solid-operand preset used by the example pages.
9892
10378
  */
@@ -9972,63 +10458,47 @@ function createPolygonPreset(operation, options) {
9972
10458
  };
9973
10459
  }
9974
10460
  /**
9975
- * Builds the straight-sweep solid preset used to demonstrate extruded booleans.
10461
+ * Builds an extrusion-first preset that exercises polygon.extrude(height) and
10462
+ * reuses the standard solid boolean pipeline.
9976
10463
  */
9977
10464
  function createExtrudedPreset(operation, options) {
9978
10465
  var _a, _b, _c, _d, _e, _f;
9979
10466
  const outlineWidth = (_a = options.outlineWidth) !== null && _a !== void 0 ? _a : 3;
9980
10467
  const extrudedOffset = (_b = options.extrudedOffset) !== null && _b !== void 0 ? _b : new Vector3(0.0, 0.0, 0.0);
9981
- const path = [
9982
- new Vector3(0.0, 0.0, 0.0),
9983
- new Vector3(0.0, 1.6, 0.0),
9984
- ];
9985
- const lhsProfile = [
9986
- new Vector3(-2, 0.0, -0.65),
9987
- new Vector3(2.1, 0.0, -0.65),
9988
- new Vector3(1.75, 0.0, 0.7),
9989
- new Vector3(-1.55, 0.0, 0.7),
9990
- ];
9991
- const rhsProfile = operation === "subtraction"
9992
- ? [
9993
- new Vector3(-0.42, 0.0, -0.24),
9994
- new Vector3(0.42, 0.0, -0.24),
9995
- new Vector3(0.42, 0.0, 0.24),
9996
- new Vector3(-0.42, 0.0, 0.24),
9997
- ]
9998
- : [
9999
- new Vector3(-0.8, 0.0, -0.42),
10000
- new Vector3(0.72, 0.0, -0.42),
10001
- new Vector3(0.72, 0.0, 0.42),
10002
- new Vector3(-0.8, 0.0, 0.42),
10003
- ];
10004
- const lhs = new Sweep({
10005
- path,
10006
- profile: lhsProfile,
10468
+ const wallProfile = new Polygon({
10469
+ vertices: [
10470
+ new Vector3(-2.2, 0.0, -0.18),
10471
+ new Vector3(2.2, 0.0, -0.18),
10472
+ new Vector3(2.2, 0.0, 0.18),
10473
+ new Vector3(-2.2, 0.0, 0.18),
10474
+ ],
10007
10475
  color: 0x60a5fa,
10008
- capStart: true,
10009
- capEnd: true,
10010
10476
  fatOutlines: (_c = options.fatOutlines) !== null && _c !== void 0 ? _c : true,
10011
10477
  outlineWidth,
10012
10478
  });
10013
- const rhs = new Sweep({
10014
- path: path.map((point) => point.clone()),
10015
- profile: rhsProfile,
10479
+ const openingProfile = new Polygon({
10480
+ vertices: [
10481
+ new Vector3(-0.7, 0.0, -0.34),
10482
+ new Vector3(0.9, 0.0, -0.34),
10483
+ new Vector3(0.9, 0.0, 0.34),
10484
+ new Vector3(-0.7, 0.0, 0.34),
10485
+ ],
10016
10486
  color: 0xf97316,
10017
- capStart: true,
10018
- capEnd: true,
10019
- translation: extrudedOffset.clone(),
10020
10487
  fatOutlines: (_d = options.fatOutlines) !== null && _d !== void 0 ? _d : true,
10021
10488
  outlineWidth,
10022
10489
  });
10023
- lhs.outline = (_e = options.outline) !== null && _e !== void 0 ? _e : true;
10024
- rhs.outline = (_f = options.outline) !== null && _f !== void 0 ? _f : true;
10490
+ const wall = wallProfile.extrude(2.8);
10491
+ const opening = openingProfile.extrude(operation === "intersection" ? 1.45 : 1.35);
10492
+ opening.setTranslation(new Vector3(extrudedOffset.x, 0.85, extrudedOffset.z));
10493
+ wall.outline = (_e = options.outline) !== null && _e !== void 0 ? _e : true;
10494
+ opening.outline = (_f = options.outline) !== null && _f !== void 0 ? _f : true;
10025
10495
  return {
10026
- title: `${capitalize(operation)} Extruded Solids`,
10027
- description: "Two capped straight sweeps demonstrate boolean operations on extruded solid profiles.",
10028
- lhsOperand: lhs,
10029
- rhsOperand: rhs,
10030
- lhsVisual: lhs,
10031
- rhsVisual: rhs,
10496
+ title: `${capitalize(operation)} Extruded Solid`,
10497
+ description: "Two polygon.extrude(height) solids overlap to demonstrate renderable BRep booleans.",
10498
+ lhsOperand: wall,
10499
+ rhsOperand: opening,
10500
+ lhsVisual: wall,
10501
+ rhsVisual: opening,
10032
10502
  };
10033
10503
  }
10034
10504
  /**
@@ -10168,6 +10638,9 @@ function createEditorModesExample(scene) {
10168
10638
  };
10169
10639
  }
10170
10640
 
10641
+ /**
10642
+ * Shared runtime entrypoint used to initialize the OpenGeometry wasm module.
10643
+ */
10171
10644
  class OpenGeometry {
10172
10645
  get enableDebug() {
10173
10646
  return this._enableDebug;
@@ -10191,23 +10664,18 @@ class OpenGeometry {
10191
10664
  this._enableDebug = false;
10192
10665
  }
10193
10666
  /**
10194
- * Asynchronously creates and initializes an instance of OpenGeometry.
10667
+ * Asynchronously initializes the OpenGeometry wasm runtime and returns a
10668
+ * cached singleton instance on subsequent calls.
10195
10669
  *
10196
- * This factory method sets up the OpenGeometry engine by linking it with the
10197
- * rendering context and the WebAssembly module. It ensures all required
10198
- * options are provided and prepares the instance for 3D geometry operations.
10670
+ * Call this before constructing `Vector3` or any kernel-backed wrapper.
10199
10671
  *
10200
10672
  * @param options - Configuration object for initializing OpenGeometry.
10201
10673
  * @returns A promise that resolves to a fully initialized OpenGeometry instance.
10202
- * @throws If any of the required options (`container`, `scene`, or `camera`) are missing.
10203
10674
  *
10204
10675
  * @example
10205
10676
  * ```ts
10206
- * const openGeometry = await OpenGeometry.create({
10207
- * container: document.getElementById('myContainer')!,
10208
- * scene: threeScene,
10209
- * camera: threeCamera,
10210
- * wasmURL: '/assets/opengeometry.wasm'
10677
+ * await OpenGeometry.create({
10678
+ * wasmURL: "/opengeometry_bg.wasm",
10211
10679
  * });
10212
10680
  * ```
10213
10681
  */
@@ -10234,5 +10702,5 @@ class OpenGeometry {
10234
10702
  OpenGeometry.version = OPEN_GEOMETRY_THREE_VERSION;
10235
10703
  OpenGeometry.instance = null;
10236
10704
 
10237
- export { Arc, BooleanResult, Cuboid, Curve, Cylinder, FreeformEditor, FreeformGeometry, Line, OGSceneManager, OpenGeometry, Opening, Polygon, Polyline, Rectangle, Sphere, SpotLabel, Sweep, Vector3, Wedge, booleanIntersection, booleanSubtraction, booleanUnion, clonePlacement, createBooleanExample, createEditorModesExample, createFreeformEditor, createFreeformGeometry, createOffsetExample, createParametricEditCapabilities, createPrimitivesExample, createShapesExample, createSweepExample, createWallFromOffsetsExample, toObjectTransformation$1 as toObjectTransformation };
10705
+ export { Arc, BooleanResult, Cuboid, Curve, Cylinder, FreeformEditor, FreeformGeometry, Line, OGSceneManager, OpenGeometry, Opening, Polygon, Polyline, Rectangle, Solid, Sphere, SpotLabel, Sweep, Vector3, Wedge, booleanIntersection, booleanSubtraction, booleanUnion, clonePlacement, createBooleanExample, createEditorModesExample, createFreeformEditor, createFreeformGeometry, createOffsetExample, createParametricEditCapabilities, createPrimitivesExample, createShapesExample, createSweepExample, createWallFromOffsetsExample, executeBooleanSubtractionMany, extrudeBrepFace, toObjectTransformation$1 as toObjectTransformation };
10238
10706
  //# sourceMappingURL=index.js.map