opengeometry 2.0.14 → 2.0.16

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.
@@ -0,0 +1,20 @@
1
+ import type { OffsetRegion } from "./offset-regions.js";
2
+ export type PlanarBooleanOperation = "union" | "intersection" | "subtraction";
3
+ export type CurvedRegionEdge = {
4
+ kind: "line";
5
+ from: [number, number];
6
+ to: [number, number];
7
+ } | {
8
+ kind: "arc";
9
+ center: [number, number];
10
+ radius: number;
11
+ start_angle: number;
12
+ sweep_angle: number;
13
+ };
14
+ export interface CurvedRegion2D {
15
+ outer: CurvedRegionEdge[];
16
+ holes: CurvedRegionEdge[][];
17
+ }
18
+ export declare function booleanRegions2D(a: readonly OffsetRegion[], b: readonly OffsetRegion[], operation: PlanarBooleanOperation): OffsetRegion[];
19
+ /** Analytic line/arc region Boolean; output arcs retain their exact circles. */
20
+ export declare function booleanCurvedRegions2D(a: readonly CurvedRegion2D[], b: readonly CurvedRegion2D[], operation: PlanarBooleanOperation): CurvedRegion2D[];
@@ -2,6 +2,7 @@
2
2
  * Kernel-backed boolean helpers and renderable result mesh.
3
3
  */
4
4
  export * from "./boolean.js";
5
+ export * from "./boolean-regions.js";
5
6
  export * from "./analytic-errors.js";
6
7
  export * from "./extrude.js";
7
8
  export * from "./loft.js";
@@ -17,7 +17,7 @@ export interface OffsetRegion {
17
17
  * trims, and nonzero-winding resolution of reflex / closed loops. NO boolean union
18
18
  * (so it is deterministic, unlike the 3D-mesh CSG path). A simple centreline returns
19
19
  * one region; a self-crossing closed centreline (e.g. a figure-8) returns one per
20
- * simple sub-loop. Returns an EMPTY array for a genuinely unbuildable input (does
20
+ * simple sub-loop. Returns an EMPTY array for a collapsed input (does
21
21
  * not throw, so it never looks like a kernel crash). Rings are CW-outer / CCW-holes.
22
22
  *
23
23
  * @param centrelineFlat centreline points as `[x,y,z, …]`.
@@ -25,9 +25,8 @@ export interface OffsetRegion {
25
25
  * @param miterLimit SVG stroke-miterlimit; corners sharper than this bevel. Default 4.
26
26
  */
27
27
  export declare function offsetPolylineRegions(centrelineFlat: number[] | Float64Array, width: number, closed: boolean, miterLimit?: number): OffsetRegion[];
28
- /** An excluded interior ring of a variable inset (an easement island, a
29
- * protected tree pit): its closed ring `[x,y,z, …]` plus one clearance
30
- * distance per hole edge. The inset GROWS the hole by its distances. */
28
+ /** An excluded interior ring of a variable inset. Its closed ring has one
29
+ * clearance distance per edge; the inset grows the hole by those distances. */
31
30
  export interface OffsetHole {
32
31
  ring: number[] | Float64Array;
33
32
  distances: number[] | Float64Array;
@@ -35,17 +34,17 @@ export interface OffsetHole {
35
34
  /**
36
35
  * Inset a CLOSED ring inward with one distance per edge (edge i =
37
36
  * `ring[i] → ring[i+1]`; an explicit closing duplicate point is accepted and
38
- * stripped, the distance count stays one per unique edge). Built for setback
39
- * envelopes: the result is the CLEARANCE-EXACT buildable region — the ring's
40
- * interior minus every point within `distances[i]` of edge i's SEGMENT, so
41
- * distant lot lines are honoured across notches and corners where distances
42
- * differ become circumscribed clearance arcs (conservative). There is no
37
+ * stripped, the distance count stays one per unique edge). The result is a
38
+ * clearance-exact inset region: the ring's interior minus every point within
39
+ * `distances[i]` of edge i's segment. Distant boundary segments remain
40
+ * effective across notches; different distances produce circumscribed
41
+ * clearance arcs. There is no
43
42
  * `miterLimit` parameter, deliberately: miters and bevels only approximate the
44
43
  * clearance arc, and a bevel would claim points inside the required distance.
45
44
  *
46
45
  * `holes` are excluded interior rings, each grown outward by its own per-edge
47
46
  * distances — the region keeps clear of a hole's edges exactly as it keeps
48
- * clear of the lot lines, so a hole can split the region or swallow it.
47
+ * clear of the outer boundary, so a hole can split the region or swallow it.
49
48
  *
50
49
  * Returns CW-outer / CCW-hole regions (canonical start vertex), possibly
51
50
  * SEVERAL when a deep inset (or a hole) splits a waisted ring into disjoint
@@ -57,7 +56,7 @@ export interface OffsetHole {
57
56
  *
58
57
  * @param ring closed ring points as `[x,y,z, …]` (Y is carried through).
59
58
  * @param distances inward inset distance per edge, metres, each >= 0
60
- * (0 = the edge stays in place, e.g. lot-line construction).
59
+ * (0 keeps that boundary edge in place).
61
60
  * @param holes excluded interior rings with their own per-edge distances.
62
61
  */
63
62
  export declare function offsetRingVariable(ring: number[] | Float64Array, distances: number[] | Float64Array, holes?: OffsetHole[]): OffsetRegion[];
@@ -71,7 +70,7 @@ export interface OffsetPolyline {
71
70
  * Merge a GROUP of separate polylines (a crossing T / X / L overlap) into one clean
72
71
  * region by nonzero-winding union of their mitered bands — the overlapping strokes
73
72
  * merge into a single region with mitered/bevelled corners, no internal edges.
74
- * Returns CW-outer / CCW-hole regions (one or more); empty if nothing is buildable.
73
+ * Returns CW-outer / CCW-hole regions (one or more); empty if no region remains.
75
74
  * No CSG. Used to render/extrude an overlapping crossing as one joined mass.
76
75
  */
77
76
  export declare function offsetPolylineGroupRegions(polylines: OffsetPolyline[]): OffsetRegion[];
@@ -13,13 +13,24 @@ export interface AnalyticAccuracy {
13
13
  tessellation: number;
14
14
  exchange: number;
15
15
  }
16
- export interface AnalyticCircularWallOpening {
16
+ export interface AnalyticAnnularSectorOpening {
17
17
  id: string;
18
18
  angle: number;
19
19
  width: number;
20
20
  bottom: number;
21
21
  height: number;
22
22
  }
23
+ export type AnalyticProfileEdge = {
24
+ kind: "line";
25
+ from: [number, number];
26
+ to: [number, number];
27
+ } | {
28
+ kind: "arc";
29
+ center: [number, number];
30
+ radius: number;
31
+ startAngle: number;
32
+ sweepAngle: number;
33
+ };
23
34
  export type AnalyticPolygonLoftAlignment = "auto" | {
24
35
  upperStartIndex: number;
25
36
  reverseUpper?: boolean;
@@ -63,13 +74,18 @@ export type AnalyticPrimitiveOptions = AnalyticOptions & ({
63
74
  outer: [number, number][];
64
75
  holes: [number, number][][];
65
76
  height: number;
77
+ } | {
78
+ kind: "arcEdgedExtrusion";
79
+ outer: AnalyticProfileEdge[];
80
+ holes?: AnalyticProfileEdge[][];
81
+ height: number;
66
82
  } | {
67
83
  kind: "polygonLoft";
68
84
  lower: [number, number, number][];
69
85
  upper: [number, number, number][];
70
86
  alignment?: AnalyticPolygonLoftAlignment;
71
87
  } | {
72
- kind: "straightWallWithArchedOpening";
88
+ kind: "boxWithArchedOpening";
73
89
  width: number;
74
90
  depth: number;
75
91
  height: number;
@@ -107,28 +123,28 @@ export type AnalyticPrimitiveOptions = AnalyticOptions & ({
107
123
  majorRadius: number;
108
124
  minorRadius: number;
109
125
  } | {
110
- kind: "circularWall";
126
+ kind: "annularSectorExtrusion";
111
127
  radius: number;
112
128
  thickness: number;
113
129
  height: number;
114
130
  startAngle: number;
115
131
  sweepAngle: number;
116
132
  } | {
117
- kind: "circularWallWithOpenings";
133
+ kind: "annularSectorExtrusionWithOpenings";
118
134
  radius: number;
119
135
  thickness: number;
120
136
  height: number;
121
137
  startAngle: number;
122
138
  sweepAngle: number;
123
- openings: AnalyticCircularWallOpening[];
139
+ openings: AnalyticAnnularSectorOpening[];
124
140
  } | {
125
- kind: "circularWallWithArchedOpening";
141
+ kind: "annularSectorExtrusionWithArchedOpening";
126
142
  radius: number;
127
143
  thickness: number;
128
144
  height: number;
129
145
  startAngle: number;
130
146
  sweepAngle: number;
131
- opening: AnalyticCircularWallOpening;
147
+ opening: AnalyticAnnularSectorOpening;
132
148
  } | {
133
149
  kind: "coaxialCircleLoft";
134
150
  lowerRadius: number;
@@ -0,0 +1,112 @@
1
+ import * as THREE from "three";
2
+ import type { AnalyticFrame, AnalyticProjectionCamera, AnalyticProjectionHlr, AnalyticSolid } from "../shapes/analytic-solid.js";
3
+ export interface WorldTransform {
4
+ frame: AnalyticFrame;
5
+ scale: number;
6
+ }
7
+ export interface WorldNodeOptions {
8
+ id: string;
9
+ parent?: string;
10
+ definition?: string;
11
+ local?: THREE.Matrix4;
12
+ kind?: string;
13
+ }
14
+ export interface WorldProjectedLine {
15
+ start: {
16
+ x: number;
17
+ y: number;
18
+ };
19
+ end: {
20
+ x: number;
21
+ y: number;
22
+ };
23
+ stroke_width: number | null;
24
+ stroke_color: [number, number, number] | null;
25
+ class?: string;
26
+ }
27
+ export interface WorldProjectedLines {
28
+ name: string | null;
29
+ lines: WorldProjectedLine[];
30
+ }
31
+ export interface WorldProjectedSegment {
32
+ geometry: unknown;
33
+ class: string;
34
+ layer?: string | null;
35
+ source_entity_id?: string | null;
36
+ }
37
+ export interface WorldProjectedScene {
38
+ name: string | null;
39
+ segments: WorldProjectedSegment[];
40
+ }
41
+ export interface WorldProjectionView {
42
+ id: string;
43
+ camera: AnalyticProjectionCamera;
44
+ hlr?: AnalyticProjectionHlr;
45
+ }
46
+ export interface WorldExportedMesh {
47
+ bytes: Uint8Array;
48
+ report: unknown;
49
+ }
50
+ export interface WorldExportedFile {
51
+ text: string;
52
+ report: unknown;
53
+ }
54
+ export type WorldClashKind = "hard" | "touch" | "unresolved";
55
+ export interface WorldClash {
56
+ a: string;
57
+ b: string;
58
+ kind: WorldClashKind;
59
+ parts: [string, string];
60
+ detail?: string;
61
+ }
62
+ export interface WorldClashOptions {
63
+ depth?: number;
64
+ }
65
+ export interface WorldProximity {
66
+ a: string;
67
+ b: string;
68
+ distance: number;
69
+ errorBound: number;
70
+ parts: [string, string];
71
+ points: [[number, number, number], [number, number, number]];
72
+ }
73
+ export type WorldGraphErrorCode = "duplicate_node" | "unknown_node" | "duplicate_definition" | "unknown_definition" | "definition_in_use" | "cycle" | "invalid_input" | "export" | "geometry" | "unknown";
74
+ export declare class WorldGraphError extends Error {
75
+ readonly code: WorldGraphErrorCode;
76
+ readonly detail: unknown;
77
+ constructor(code: WorldGraphErrorCode, message: string, detail?: unknown);
78
+ }
79
+ export declare function matrixToWorldTransform(matrix: THREE.Matrix4): WorldTransform;
80
+ export declare class WorldGraph {
81
+ private readonly kernel;
82
+ private readonly bindings;
83
+ private bindingOrder;
84
+ private disposed;
85
+ get nodeCount(): number;
86
+ get definitionCount(): number;
87
+ define(id: string, solid: AnalyticSolid): void;
88
+ defineLegacy(id: string, brepSerialized: string): void;
89
+ hasDefinition(id: string): boolean;
90
+ undefine(id: string): void;
91
+ addNode(options: WorldNodeOptions): void;
92
+ hasNode(id: string): boolean;
93
+ setLocal(id: string, local: THREE.Matrix4): void;
94
+ reparent(id: string, parent?: string): void;
95
+ removeNode(id: string): void;
96
+ getWorldMatrix(id: string): THREE.Matrix4;
97
+ getWorldBounds(id: string): THREE.Box3 | null;
98
+ clash(itemsA: string[], itemsB: string[], options?: WorldClashOptions): WorldClash[];
99
+ clearance(itemsA: string[], itemsB: string[], clearance: number): WorldProximity[];
100
+ distance(itemA: string, itemB: string, tolerance?: number): WorldProximity | null;
101
+ projectLines(items: string[], camera: AnalyticProjectionCamera, hlr?: AnalyticProjectionHlr, deflection?: number): WorldProjectedLines;
102
+ projectViews(items: string[], views: WorldProjectionView[], deflection?: number): Record<string, WorldProjectedScene>;
103
+ exportStl(items: string[], config?: Record<string, unknown>): WorldExportedMesh;
104
+ exportStep(items: string[], config?: Record<string, unknown>): WorldExportedFile;
105
+ exportIfc(items: string[], config?: Record<string, unknown>): WorldExportedFile;
106
+ bind(object: THREE.Object3D, id: string): void;
107
+ unbind(id: string): void;
108
+ sync(): void;
109
+ dispose(): void;
110
+ private syncObject;
111
+ private checkActive;
112
+ }
@@ -1,90 +0,0 @@
1
- /**
2
- * Typed error hierarchy for boolean operations.
3
- *
4
- * The Rust kernel emits a structured `BooleanError` as JSON across the WASM
5
- * boundary (see `main/opengeometry/src/booleans/error.rs`). This module parses
6
- * that JSON and re-throws it as a typed `BooleanError` (or a more specific
7
- * subclass) so app code can `instanceof`-discriminate without parsing message
8
- * strings.
9
- *
10
- * Cutter indices are **0-based** to match `Vec` / array indexing on both
11
- * sides of the boundary.
12
- */
13
- import * as THREE from "three";
14
- export type BooleanErrorPhase = "input_validation" | "union_pre_pass" | "subtract_step" | "output_validation";
15
- export type BooleanErrorReason = "invalid_operand" | "malformed_input" | "mixed_operand_kinds" | "unsupported_operand_kind" | "non_coplanar_planar_operands" | "topology_error" | "kernel_failure" | "non_manifold_edges" | "open_shell" | "coincident_faces" | "degenerate_triangle" | "empty_result" | "overlapping_cutters" | "cutter_exceeds_host";
16
- interface KindPayload {
17
- code: BooleanErrorReason;
18
- other_index?: number;
19
- axis?: string;
20
- overshoot?: number;
21
- }
22
- interface BooleanErrorJson {
23
- kind: KindPayload;
24
- phase: BooleanErrorPhase;
25
- cutter_index: number | null;
26
- message: string;
27
- details: string | null;
28
- edge_samples: Array<[{
29
- x: number;
30
- y: number;
31
- z: number;
32
- }, {
33
- x: number;
34
- y: number;
35
- z: number;
36
- }]> | null;
37
- }
38
- /**
39
- * Base class for every typed boolean error. Carries the structured payload the
40
- * kernel emitted across WASM. Specialized subclasses (`OverlappingCuttersError`,
41
- * `CutterExceedsHostError`, `NonManifoldOutputError`, `CoincidentFacesError`)
42
- * narrow the payload for the variants that carry extra fields.
43
- */
44
- export declare class BooleanError extends Error {
45
- readonly reason: BooleanErrorReason;
46
- readonly phase: BooleanErrorPhase;
47
- readonly cutterIndex: number | null;
48
- readonly details: string | null;
49
- readonly edgeSamples: ReadonlyArray<[THREE.Vector3, THREE.Vector3]> | null;
50
- constructor(payload: BooleanErrorJson);
51
- }
52
- /**
53
- * Two cutters overlap each other. `otherIndex` is the 0-based index of the
54
- * cutter that conflicts with the one at `cutterIndex`.
55
- */
56
- export declare class OverlappingCuttersError extends BooleanError {
57
- readonly otherIndex: number;
58
- constructor(payload: BooleanErrorJson);
59
- }
60
- /**
61
- * A cutter extends past the host's hull along the named axis.
62
- */
63
- export declare class CutterExceedsHostError extends BooleanError {
64
- readonly axis: "x" | "y" | "z";
65
- readonly overshoot: number;
66
- constructor(payload: BooleanErrorJson);
67
- }
68
- /**
69
- * Output mesh has open or over-shared edges after a boolean. `edgeSamples`
70
- * carries up to ~8 sample non-manifold edges to aid app-side debugging.
71
- */
72
- export declare class NonManifoldOutputError extends BooleanError {
73
- constructor(payload: BooleanErrorJson);
74
- }
75
- /**
76
- * Cutter and host share a coplanar face. Distinct from
77
- * `DegenerateTriangleError` (zero-area input) — see `06a-snap-tolerance.md`.
78
- */
79
- export declare class CoincidentFacesError extends BooleanError {
80
- constructor(payload: BooleanErrorJson);
81
- }
82
- /**
83
- * Parses a WASM-thrown error and returns the appropriate typed `BooleanError`
84
- * subclass. If the error's message is not valid `BooleanError` JSON, returns a
85
- * fallback `BooleanError` with `reason: "kernel_failure"` carrying the original
86
- * string, so callers always get a typed error and never have to `try/catch`
87
- * twice.
88
- */
89
- export declare function parseBooleanError(raw: unknown): BooleanError;
90
- export {};
@@ -1,21 +0,0 @@
1
- import type { BooleanExecutionOptions, BooleanOperand, BooleanResult } from "../operations/boolean.js";
2
- /**
3
- * Operand types accepted by shape instance `.subtract(...)` helpers.
4
- */
5
- export type ShapeSubtractOperand = BooleanOperand;
6
- /**
7
- * Array-only operand list accepted by shape instance `.subtract(...)` helpers.
8
- */
9
- export type ShapeSubtractOperands = ShapeSubtractOperand[];
10
- /**
11
- * Options accepted by shape instance `.subtract(...)` helpers.
12
- */
13
- export type ShapeSubtractOptions = BooleanExecutionOptions;
14
- /**
15
- * Return type for shape instance `.subtract(...)` helpers.
16
- */
17
- export type ShapeSubtractResult = BooleanResult;
18
- /**
19
- * Executes a kernel-backed subtraction for a shape wrapper against another boolean operand.
20
- */
21
- export declare function subtractShapeOperand(host: ShapeSubtractOperand, operands: ShapeSubtractOperands, options?: ShapeSubtractOptions): ShapeSubtractResult;