cadorange 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -80,12 +80,16 @@ type CurveKind = "line" | "circle" | "ellipse" | "bspline" | "other";
80
80
  /**
81
81
  * Metadata for one face, normalized from the kernel's interrogation output.
82
82
  * `index` is the kernel's 1-based selection index (fillet/draft/shell targets).
83
+ *
84
+ * `center` is a reference point on the face's axis of symmetry where one
85
+ * exists (kernel `axisPoint` — cylinder/cone/sphere/torus), the integral
86
+ * centroid for planes and generic surfaces. Selection semantics key on it;
87
+ * occt.ts ≥0.10.0 reports both, we keep the axis-stable one.
83
88
  */
84
89
  interface FaceMeta {
85
90
  readonly index: number;
86
91
  readonly surface: SurfaceKind;
87
92
  readonly area: number;
88
- /** A reference point: plane origin, cylinder/cone axis point, sphere/torus center. */
89
93
  readonly center: Vec3;
90
94
  /** Plane only — unit normal. */
91
95
  readonly normal?: Vec3;
@@ -99,7 +103,11 @@ interface EdgeMeta {
99
103
  readonly index: number;
100
104
  readonly curve: CurveKind;
101
105
  readonly length: number;
102
- /** Line: midpoint. Circle/ellipse: center. Others: bounding-box midpoint. */
106
+ /**
107
+ * Line: midpoint. Circle/ellipse: the underlying circle/ellipse center
108
+ * (kernel `axisPoint`, not the arc's integral centroid — matches
109
+ * build123d selector semantics). Others: integral centroid.
110
+ */
103
111
  readonly center: Vec3;
104
112
  /** Line only — unit direction (start → end). */
105
113
  readonly direction?: Vec3;
@@ -146,7 +154,14 @@ interface Kernel {
146
154
  makeSphere(radius: number, at?: Vec3): ShapeHandle;
147
155
  makeCone(radius1: number, radius2: number, height: number, at?: Vec3): ShapeHandle;
148
156
  makeTorus(radius1: number, radius2: number, at?: Vec3): ShapeHandle;
149
- boolean(op: "fuse" | "cut" | "common", a: ShapeHandle, b: ShapeHandle): ShapeHandle;
157
+ /**
158
+ * Booleans clean by default (UnifySameDomain — same as build123d/CadQuery):
159
+ * coplanar faces merge, collinear edges join. `clean: false` keeps raw
160
+ * fragment topology for callers that count fragments.
161
+ */
162
+ boolean(op: "fuse" | "cut" | "common", a: ShapeHandle, b: ShapeHandle, opts?: {
163
+ clean?: boolean;
164
+ }): ShapeHandle;
150
165
  /** `edgeIndices` are 1-based indices into `meta(s).edges`. Empty = all edges. */
151
166
  fillet(s: ShapeHandle, radius: number, edgeIndices: number[]): ShapeHandle;
152
167
  chamfer(s: ShapeHandle, distance: number, edgeIndices: number[]): ShapeHandle;
@@ -200,10 +215,17 @@ declare class Shape {
200
215
  * records (docs/occt-requirements.md R5). Will land with that kernel API.
201
216
  */
202
217
  vertices(): ShapeList<never>;
203
- cut(b: Shape): Solid;
204
- fuse(b: Shape): Solid;
218
+ /** See `Kernel.boolean` — cleaned by default (UnifySameDomain). */
219
+ cut(b: Shape, opts?: {
220
+ clean?: boolean;
221
+ }): Solid;
222
+ fuse(b: Shape, opts?: {
223
+ clean?: boolean;
224
+ }): Solid;
205
225
  /** build123d's `intersect` (OCCT `common`). */
206
- common(b: Shape): Solid;
226
+ common(b: Shape, opts?: {
227
+ clean?: boolean;
228
+ }): Solid;
207
229
  /** Immediate-bake transform (occt.ts has no lazy location chain). */
208
230
  translate(by: Vec3): Solid;
209
231
  fillet(edges: ShapeList<Edge> | readonly Edge[], radius: number): Solid;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { C as Vec3, E as v, S as Plane, T as planeFrom, _ as AxisName, a as ShapeList, b as Location, c as EdgeMeta, d as Kernel, f as ShapeHandle, g as Axis3, h as Axis, i as Shape, l as FaceMeta, m as SurfaceKind, n as Edge, o as Solid, p as ShapeMeta, r as Face, s as CurveKind, t as Describe, u as HoleMeta, v as BBox, w as axisByName, x as Mesh, y as Loc } from "./index-CBGNe8Hy.js";
1
+ import { C as Vec3, E as v, S as Plane, T as planeFrom, _ as AxisName, a as ShapeList, b as Location, c as EdgeMeta, d as Kernel, f as ShapeHandle, g as Axis3, h as Axis, i as Shape, l as FaceMeta, m as SurfaceKind, n as Edge, o as Solid, p as ShapeMeta, r as Face, s as CurveKind, t as Describe, u as HoleMeta, v as BBox, w as axisByName, x as Mesh, y as Loc } from "./index-DceghC4N.js";
2
2
  import "occt.ts";
3
3
  //#region src/io/index.d.ts
4
4
  type ExportFormat = "step" | "stl" | "glb";
@@ -20,10 +20,16 @@ interface InitOptions {
20
20
  export declare function init(opts?: InitOptions): Promise<void>;
21
21
  //#endregion
22
22
  //#region src/ops/index.d.ts
23
- export declare function fuse(a: Solid, b: Shape): Solid;
24
- export declare function cut(a: Solid, b: Shape): Solid;
23
+ export declare function fuse(a: Solid, b: Shape, opts?: {
24
+ clean?: boolean;
25
+ }): Solid;
26
+ export declare function cut(a: Solid, b: Shape, opts?: {
27
+ clean?: boolean;
28
+ }): Solid;
25
29
  /** build123d `intersect` — OCCT `common`. */
26
- export declare function intersect(a: Solid, b: Shape): Solid;
30
+ export declare function intersect(a: Solid, b: Shape, opts?: {
31
+ clean?: boolean;
32
+ }): Solid;
27
33
  /** Keep the OCCT name for code translated from CadQuery. */
28
34
  export declare const common: typeof intersect;
29
35
  export declare function fillet(s: Shape, edges: ShapeList<Edge> | readonly Edge[], radius: number): Solid;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { a as importStep, i as exportStl, n as exportShape, r as exportStep, t as exportGlb } from "./io-N0C2K1hO.js";
2
- import { _ as Axis, a as Sphere, b as v, c as Face, d as Solid, g as init, i as Cylinder, l as Shape, m as record, n as Box, o as Torus, p as onOp, r as Cone, s as Edge, t as parseSelector, u as ShapeList, v as axisByName, y as planeFrom } from "./selectors-CEhRDaf2.js";
1
+ import { a as importStep, i as exportStl, n as exportShape, r as exportStep, t as exportGlb } from "./io-DD2D1UYF.js";
2
+ import { _ as Axis, a as Sphere, b as v, c as Face, d as Solid, g as init, i as Cylinder, l as Shape, m as record, n as Box, o as Torus, p as onOp, r as Cone, s as Edge, t as parseSelector, u as ShapeList, v as axisByName, y as planeFrom } from "./selectors-C0-da9aQ.js";
3
3
  //#region src/util.ts
4
4
  /** Thrown by every skeleton stub until the real M0 implementation lands. */
5
5
  var NotImplementedError = class extends Error {
@@ -14,15 +14,15 @@ function todo(what) {
14
14
  }
15
15
  //#endregion
16
16
  //#region src/ops/index.ts
17
- function fuse(a, b) {
18
- return a.fuse(b);
17
+ function fuse(a, b, opts) {
18
+ return a.fuse(b, opts);
19
19
  }
20
- function cut(a, b) {
21
- return a.cut(b);
20
+ function cut(a, b, opts) {
21
+ return a.cut(b, opts);
22
22
  }
23
23
  /** build123d `intersect` — OCCT `common`. */
24
- function intersect(a, b) {
25
- return a.common(b);
24
+ function intersect(a, b, opts) {
25
+ return a.common(b, opts);
26
26
  }
27
27
  /** Keep the OCCT name for code translated from CadQuery. */
28
28
  const common = intersect;
@@ -1,4 +1,4 @@
1
- import { f as solidFromKernel, h as getKernel, m as record } from "./selectors-CEhRDaf2.js";
1
+ import { f as solidFromKernel, h as getKernel, m as record } from "./selectors-C0-da9aQ.js";
2
2
  //#region \0rolldown/runtime.js
3
3
  var __defProp = Object.defineProperty;
4
4
  var __exportAll = (all, no_symbols) => {
@@ -226,10 +226,10 @@ var OcctKernel = class {
226
226
  const s = this.#occ.makeTorus(radius1, radius2);
227
227
  return this.#adopt(at ? this.#occ.translate(s, at) : s);
228
228
  }
229
- boolean(op, a, b) {
229
+ boolean(op, a, b, opts) {
230
230
  const ra = this.#raw(a);
231
231
  const rb = this.#raw(b);
232
- const result = op === "fuse" ? this.#occ.fuse(ra, rb) : op === "cut" ? this.#occ.cut(ra, rb) : this.#occ.common(ra, rb);
232
+ const result = op === "fuse" ? this.#occ.fuse(ra, rb, opts) : op === "cut" ? this.#occ.cut(ra, rb, opts) : this.#occ.common(ra, rb, opts);
233
233
  return this.#adopt(result);
234
234
  }
235
235
  fillet(s, radius, edgeIndices) {
@@ -254,25 +254,18 @@ var OcctKernel = class {
254
254
  const bbox = raw.bounds();
255
255
  const edges = d.edges.map((e) => {
256
256
  const curve = CURVE_KINDS.has(e.curve) ? e.curve : "other";
257
- if (e.curve === "line") {
258
- const center = [
259
- (e.start[0] + e.end[0]) / 2,
260
- (e.start[1] + e.end[1]) / 2,
261
- (e.start[2] + e.end[2]) / 2
262
- ];
263
- return {
264
- index: e.index,
265
- curve,
266
- length: e.length,
267
- center,
268
- direction: e.direction
269
- };
270
- }
271
- if (e.curve === "circle") return {
257
+ if (e.curve === "line") return {
272
258
  index: e.index,
273
259
  curve,
274
260
  length: e.length,
275
261
  center: e.center,
262
+ direction: e.direction
263
+ };
264
+ if (e.curve === "circle") return {
265
+ index: e.index,
266
+ curve,
267
+ length: e.length,
268
+ center: e.axisPoint,
276
269
  axis: e.axis,
277
270
  radius: e.radius
278
271
  };
@@ -280,39 +273,25 @@ var OcctKernel = class {
280
273
  index: e.index,
281
274
  curve,
282
275
  length: e.length,
283
- center: e.center,
276
+ center: e.axisPoint,
284
277
  axis: e.axis
285
278
  };
286
- const fallback = [
287
- (bbox.min[0] + bbox.max[0]) / 2,
288
- (bbox.min[1] + bbox.max[1]) / 2,
289
- (bbox.min[2] + bbox.max[2]) / 2
290
- ];
291
279
  return {
292
280
  index: e.index,
293
281
  curve,
294
282
  length: e.length,
295
- center: fallback
283
+ center: e.center
296
284
  };
297
285
  });
298
286
  const faces = d.faces.map((f) => {
299
287
  const surface = SURFACE_KINDS.has(f.surface) ? f.surface : "other";
300
- if (f.surface === "plane") {
301
- const refPoint = f.origin;
302
- const onPlane = edges.filter((e) => Math.abs(v.dot(e.center, f.normal) - v.dot(refPoint, f.normal)) <= 1e-4);
303
- const center = onPlane.length > 0 ? [
304
- onPlane.reduce((acc, e) => acc + e.center[0], 0) / onPlane.length,
305
- onPlane.reduce((acc, e) => acc + e.center[1], 0) / onPlane.length,
306
- onPlane.reduce((acc, e) => acc + e.center[2], 0) / onPlane.length
307
- ] : refPoint;
308
- return {
309
- index: f.index,
310
- surface,
311
- area: f.area,
312
- center,
313
- normal: f.normal
314
- };
315
- }
288
+ if (f.surface === "plane") return {
289
+ index: f.index,
290
+ surface,
291
+ area: f.area,
292
+ center: f.center,
293
+ normal: f.normal
294
+ };
316
295
  if (f.surface === "cylinder") return {
317
296
  index: f.index,
318
297
  surface,
@@ -332,27 +311,22 @@ var OcctKernel = class {
332
311
  index: f.index,
333
312
  surface,
334
313
  area: f.area,
335
- center: f.center,
314
+ center: f.axisPoint,
336
315
  radius: f.radius
337
316
  };
338
317
  if (f.surface === "torus") return {
339
318
  index: f.index,
340
319
  surface,
341
320
  area: f.area,
342
- center: f.center,
321
+ center: f.axisPoint,
343
322
  axis: f.axis,
344
323
  radius: f.majorRadius
345
324
  };
346
- const genericCenter = [
347
- (bbox.min[0] + bbox.max[0]) / 2,
348
- (bbox.min[1] + bbox.max[1]) / 2,
349
- (bbox.min[2] + bbox.max[2]) / 2
350
- ];
351
325
  return {
352
326
  index: f.index,
353
327
  surface,
354
328
  area: f.area,
355
- center: genericCenter
329
+ center: f.center
356
330
  };
357
331
  });
358
332
  const meta = {
@@ -514,24 +488,28 @@ var Shape = class {
514
488
  vertices() {
515
489
  throw new Error("vertices() requires kernel support (occt.ts R5: describe() vertex records) — not available yet.");
516
490
  }
517
- cut(b) {
491
+ /** See `Kernel.boolean` — cleaned by default (UnifySameDomain). */
492
+ cut(b, opts) {
518
493
  return record("cut", {
519
494
  target: this.handle.id,
520
- tool: b.handle.id
521
- }, () => solidFromKernel(getKernel().boolean("cut", this.handle, b.handle)));
495
+ tool: b.handle.id,
496
+ ...opts
497
+ }, () => solidFromKernel(getKernel().boolean("cut", this.handle, b.handle, opts)));
522
498
  }
523
- fuse(b) {
499
+ fuse(b, opts) {
524
500
  return record("fuse", {
525
501
  target: this.handle.id,
526
- tool: b.handle.id
527
- }, () => solidFromKernel(getKernel().boolean("fuse", this.handle, b.handle)));
502
+ tool: b.handle.id,
503
+ ...opts
504
+ }, () => solidFromKernel(getKernel().boolean("fuse", this.handle, b.handle, opts)));
528
505
  }
529
506
  /** build123d's `intersect` (OCCT `common`). */
530
- common(b) {
507
+ common(b, opts) {
531
508
  return record("common", {
532
509
  target: this.handle.id,
533
- tool: b.handle.id
534
- }, () => solidFromKernel(getKernel().boolean("common", this.handle, b.handle)));
510
+ tool: b.handle.id,
511
+ ...opts
512
+ }, () => solidFromKernel(getKernel().boolean("common", this.handle, b.handle, opts)));
535
513
  }
536
514
  /** Immediate-bake transform (occt.ts has no lazy location chain). */
537
515
  translate(by) {
@@ -548,7 +526,7 @@ var Shape = class {
548
526
  }
549
527
  /** Export by file extension (.step/.stl/.glb). Node writes to disk. */
550
528
  async export(path, opts) {
551
- const { exportShape } = await import("./io-N0C2K1hO.js").then((n) => n.o);
529
+ const { exportShape } = await import("./io-DD2D1UYF.js").then((n) => n.o);
552
530
  await exportShape(this, path, opts);
553
531
  }
554
532
  dispose() {
@@ -1,4 +1,4 @@
1
- import { S as Plane, o as Solid } from "../index-CBGNe8Hy.js";
1
+ import { S as Plane, o as Solid } from "../index-DceghC4N.js";
2
2
  //#region src/workplane/index.d.ts
3
3
  export type PlaneName = "XY" | "YZ" | "XZ" | "front" | "back" | "left" | "right" | "top" | "bottom";
4
4
  export type Selector = string;
@@ -1,4 +1,4 @@
1
- import { b as v, i as Cylinder, n as Box, t as parseSelector, y as planeFrom } from "../selectors-CEhRDaf2.js";
1
+ import { b as v, i as Cylinder, n as Box, t as parseSelector, y as planeFrom } from "../selectors-C0-da9aQ.js";
2
2
  //#region src/workplane/index.ts
3
3
  /**
4
4
  * CadQuery-style fluent facade over the explicit core API.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cadorange",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Agent-native CAD runtime in TypeScript, powered by occt.ts (OCCT/WASM). Core modeling API: shapes, selectors, booleans, features, import/export.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -24,7 +24,7 @@
24
24
  "dist"
25
25
  ],
26
26
  "dependencies": {
27
- "occt.ts": "^0.7.0"
27
+ "occt.ts": "^0.10.0"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/node": "^26.6.4"