okgeometry-api 1.25.0 → 1.26.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "okgeometry-api",
3
- "version": "1.25.0",
3
+ "version": "1.26.1",
4
4
  "description": "Geometry engine API for AEC applications - NURBS, meshes, booleans, intersections. Powered by Rust/WASM.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -35,7 +35,8 @@
35
35
  "smoke:geometry-boolean": "tsx scripts/smoke-geometry-boolean.ts",
36
36
  "smoke:curve-region": "tsx scripts/smoke-curve-region.ts",
37
37
  "smoke:sculpt": "tsx scripts/smoke-sculpt.ts",
38
- "smoke:offset-chamfer": "tsx scripts/smoke-offset-chamfer.ts"
38
+ "smoke:offset-chamfer": "tsx scripts/smoke-offset-chamfer.ts",
39
+ "smoke:rebuild": "tsx scripts/smoke-rebuild.ts"
39
40
  },
40
41
  "keywords": [
41
42
  "geometry",
package/src/Brep.ts CHANGED
@@ -509,6 +509,62 @@ export class Brep {
509
509
  return Brep.parseCurveList(buf);
510
510
  }
511
511
 
512
+ /**
513
+ * Rebuild every NURBS face surface of this Brep with the given degrees and
514
+ * control counts (Rhino-style Rebuild), keeping the topology (trims,
515
+ * pcurves, edges) intact. Each face surface is refit AT ITS ORIGINAL
516
+ * PARAMETERS over its original domain, so parameter-space references stay
517
+ * coherent within the reported deviation.
518
+ *
519
+ * Each face replacement is gated by `tolerance` (default 1e-4): a face
520
+ * whose fit misses tolerance keeps its exact original surface and is
521
+ * counted in `skippedFaces`. Pass `tolerance: 0` to accept every fit.
522
+ * Planar faces pass through untouched (`planarFaces`).
523
+ *
524
+ * Throws for invalid degree/count combinations or unparseable bodies.
525
+ */
526
+ rebuildSurfaces(options: {
527
+ degreeU?: number;
528
+ degreeV?: number;
529
+ countU: number;
530
+ countV: number;
531
+ tolerance?: number;
532
+ }): {
533
+ brep: Brep;
534
+ maxDeviation: number;
535
+ rebuiltFaces: number;
536
+ skippedFaces: number;
537
+ planarFaces: number;
538
+ } {
539
+ ensureInit();
540
+ const raw = wasm.brep_rebuild_surfaces(
541
+ this.json,
542
+ options.degreeU ?? 3,
543
+ options.degreeV ?? 3,
544
+ options.countU,
545
+ options.countV,
546
+ options.tolerance ?? 1e-4,
547
+ );
548
+ const parsed = JSON.parse(raw) as {
549
+ error?: string;
550
+ maxDeviation?: number;
551
+ rebuiltFaces?: number;
552
+ skippedFaces?: number;
553
+ planarFaces?: number;
554
+ brep?: unknown;
555
+ };
556
+ if (parsed.error || parsed.brep === undefined) {
557
+ throw new Error(`Brep.rebuildSurfaces() failed: ${parsed.error || "unknown error"}`);
558
+ }
559
+ return {
560
+ brep: Brep.fromJson(JSON.stringify(parsed.brep)),
561
+ maxDeviation: parsed.maxDeviation ?? 0,
562
+ rebuiltFaces: parsed.rebuiltFaces ?? 0,
563
+ skippedFaces: parsed.skippedFaces ?? 0,
564
+ planarFaces: parsed.planarFaces ?? 0,
565
+ };
566
+ }
567
+
512
568
  /** Parse [count, (bufLen, curveData…)·count] into NurbsCurves. */
513
569
  private static parseCurveList(buf: Float64Array): NurbsCurve[] {
514
570
  if (buf.length < 1) return [];
package/src/NurbsCurve.ts CHANGED
@@ -591,6 +591,38 @@ export class NurbsCurve {
591
591
  return NurbsCurve.fromData(buf);
592
592
  }
593
593
 
594
+ /**
595
+ * Rebuild this curve with the given degree and control point count
596
+ * (Rhino-style Rebuild): a global least-squares refit with clean
597
+ * approximation knots and chord-length-ish parameterization over [0, 1].
598
+ * The result is always NON-RATIONAL; geometrically closed curves stay
599
+ * seamlessly closed (periodic basis, C^(degree-1) across the seam); open
600
+ * curves keep their exact end points.
601
+ *
602
+ * Returns the rebuilt curve together with the measured deviation from the
603
+ * original (max and mean over dense validation samples).
604
+ *
605
+ * Throws for invalid degree/count combinations (degree 1..11, pointCount
606
+ * >= degree + 1) or degenerate (zero-length) curves.
607
+ */
608
+ rebuild(
609
+ degree: number,
610
+ pointCount: number,
611
+ ): { curve: NurbsCurve; maxDeviation: number; avgDeviation: number } {
612
+ ensureInit();
613
+ const buf = wasm.nurbs_curve_rebuild(this.data, degree, pointCount);
614
+ if (buf.length < 4) {
615
+ throw new Error(
616
+ `NurbsCurve.rebuild() failed: ${wasm.geometry_last_error() || "unknown error"}`,
617
+ );
618
+ }
619
+ return {
620
+ maxDeviation: Number(buf[0]),
621
+ avgDeviation: Number(buf[1]),
622
+ curve: NurbsCurve.fromData(buf.subarray(2)),
623
+ };
624
+ }
625
+
594
626
  /**
595
627
  * Get internal WASM data buffer.
596
628
  * For advanced use cases requiring direct WASM interop.
@@ -351,6 +351,47 @@ export class NurbsSurface implements Surface {
351
351
  return NurbsSurface.fromData(buf);
352
352
  }
353
353
 
354
+ /**
355
+ * Rebuild this surface with the given degrees and control point counts
356
+ * (Rhino-style Rebuild): a two-stage global least-squares refit with clean
357
+ * approximation knots and chord-length-ish parameterization over
358
+ * [0, 1] x [0, 1]. The result is always NON-RATIONAL; closed directions
359
+ * stay seamlessly closed (periodic basis); degenerate pole rows (spheres,
360
+ * cones of revolution) stay exactly degenerate; open boundaries keep their
361
+ * exact corner points.
362
+ *
363
+ * Returns the rebuilt surface together with the measured deviation from
364
+ * the original (max and mean over a dense validation grid).
365
+ *
366
+ * Throws for invalid degree/count combinations (degree 1..11, counts
367
+ * >= degree + 1, per-direction cap 512) or degenerate surfaces.
368
+ */
369
+ rebuild(options: {
370
+ degreeU: number;
371
+ degreeV: number;
372
+ countU: number;
373
+ countV: number;
374
+ }): { surface: NurbsSurface; maxDeviation: number; avgDeviation: number } {
375
+ ensureInit();
376
+ const buf = wasm.nurbs_surface_rebuild(
377
+ this.data,
378
+ options.degreeU,
379
+ options.degreeV,
380
+ options.countU,
381
+ options.countV,
382
+ );
383
+ if (buf.length < 6) {
384
+ throw new Error(
385
+ `NurbsSurface.rebuild() failed: ${wasm.geometry_last_error() || "unknown error"}`,
386
+ );
387
+ }
388
+ return {
389
+ maxDeviation: Number(buf[0]),
390
+ avgDeviation: Number(buf[1]),
391
+ surface: NurbsSurface.fromData(buf.subarray(2)),
392
+ };
393
+ }
394
+
354
395
  // ── Analytic queries ──
355
396
 
356
397
  /**