fluidcad 0.0.26 → 0.0.28
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/lib/dist/common/scene-object.d.ts +45 -0
- package/lib/dist/common/scene-object.js +121 -0
- package/lib/dist/common/shape-factory.d.ts +1 -1
- package/lib/dist/common/shape-history-tracker.d.ts +35 -0
- package/lib/dist/common/shape-history-tracker.js +114 -0
- package/lib/dist/common/shape.js +7 -1
- package/lib/dist/common/shapes.d.ts +0 -1
- package/lib/dist/common/shapes.js +0 -1
- package/lib/dist/common/solid.js +5 -1
- package/lib/dist/core/extrude.d.ts +12 -13
- package/lib/dist/core/extrude.js +19 -1
- package/lib/dist/core/part.d.ts +2 -1
- package/lib/dist/core/part.js +4 -1
- package/lib/dist/core/sketch.d.ts +4 -3
- package/lib/dist/core/sketch.js +4 -1
- package/lib/dist/features/chamfer.js +12 -6
- package/lib/dist/features/extrude-base.d.ts +43 -1
- package/lib/dist/features/extrude-base.js +141 -36
- package/lib/dist/features/extrude-to-face.d.ts +1 -1
- package/lib/dist/features/extrude-to-face.js +42 -19
- package/lib/dist/features/extrude-two-distances.d.ts +1 -1
- package/lib/dist/features/extrude-two-distances.js +41 -15
- package/lib/dist/features/extrude.d.ts +1 -1
- package/lib/dist/features/extrude.js +75 -20
- package/lib/dist/features/fillet.js +3 -4
- package/lib/dist/features/fuse.js +14 -0
- package/lib/dist/features/infinite-extrude.d.ts +1 -0
- package/lib/dist/features/infinite-extrude.js +33 -4
- package/lib/dist/features/loft.js +18 -5
- package/lib/dist/features/mirror-shape.d.ts +1 -3
- package/lib/dist/features/mirror-shape.js +2 -1
- package/lib/dist/features/revolve.js +17 -4
- package/lib/dist/features/rotate.js +1 -0
- package/lib/dist/features/simple-extruder.js +5 -0
- package/lib/dist/features/sweep.js +13 -2
- package/lib/dist/features/translate.js +3 -1
- package/lib/dist/filters/face/face-filter.d.ts +12 -0
- package/lib/dist/filters/face/face-filter.js +21 -0
- package/lib/dist/filters/face/torus-filter.d.ts +19 -0
- package/lib/dist/filters/face/torus-filter.js +38 -0
- package/lib/dist/helpers/scene-helpers.d.ts +10 -2
- package/lib/dist/helpers/scene-helpers.js +278 -10
- package/lib/dist/index.d.ts +1 -0
- package/lib/dist/oc/boolean-ops.d.ts +32 -4
- package/lib/dist/oc/boolean-ops.js +122 -11
- package/lib/dist/oc/color-transfer.d.ts +37 -0
- package/lib/dist/oc/color-transfer.js +135 -0
- package/lib/dist/oc/extrude-ops.js +25 -3
- package/lib/dist/oc/face-ops.d.ts +0 -1
- package/lib/dist/oc/face-ops.js +0 -13
- package/lib/dist/oc/face-query.d.ts +2 -0
- package/lib/dist/oc/face-query.js +30 -0
- package/lib/dist/oc/fillet-ops.d.ts +5 -3
- package/lib/dist/oc/fillet-ops.js +107 -70
- package/lib/dist/oc/intersection.js +6 -3
- package/lib/dist/oc/mesh.d.ts +25 -2
- package/lib/dist/oc/mesh.js +112 -35
- package/lib/dist/oc/shape-ops.d.ts +25 -20
- package/lib/dist/oc/shape-ops.js +129 -113
- package/lib/dist/rendering/mesh-transform.js +17 -1
- package/lib/dist/rendering/render-solid.js +19 -6
- package/lib/dist/rendering/render-wire.js +2 -0
- package/lib/dist/rendering/render.d.ts +12 -2
- package/lib/dist/rendering/render.js +195 -220
- package/lib/dist/scene-manager.d.ts +2 -0
- package/lib/dist/scene-manager.js +4 -3
- package/lib/dist/tests/common/scene-object-history.test.d.ts +1 -0
- package/lib/dist/tests/common/scene-object-history.test.js +274 -0
- package/lib/dist/tests/common/shape-history-tracker.test.d.ts +1 -0
- package/lib/dist/tests/common/shape-history-tracker.test.js +110 -0
- package/lib/dist/tests/features/2d/project-regression.test.d.ts +1 -0
- package/lib/dist/tests/features/2d/project-regression.test.js +69 -0
- package/lib/dist/tests/features/2d/project-user-regression.test.d.ts +1 -0
- package/lib/dist/tests/features/2d/project-user-regression.test.js +37 -0
- package/lib/dist/tests/features/color-lineage.test.d.ts +1 -0
- package/lib/dist/tests/features/color-lineage.test.js +213 -0
- package/lib/dist/tests/features/cut-symmetric-through-all.test.d.ts +1 -0
- package/lib/dist/tests/features/cut-symmetric-through-all.test.js +32 -0
- package/lib/dist/tests/features/extrude-history.test.d.ts +1 -0
- package/lib/dist/tests/features/extrude-history.test.js +248 -0
- package/lib/dist/tests/features/extrude.test.js +71 -0
- package/lib/dist/tests/features/fillet2d.test.js +16 -1
- package/lib/dist/tests/features/peer-ops-history.test.d.ts +1 -0
- package/lib/dist/tests/features/peer-ops-history.test.js +119 -0
- package/lib/dist/tests/features/select.test.js +50 -0
- package/lib/dist/tests/features/subtract.test.js +21 -1
- package/lib/dist/tests/setup.js +3 -2
- package/lib/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/ui/dist/assets/{index-BeLxRMCv.js → index-BrW_x4uc.js} +37 -37
- package/ui/dist/index.html +1 -1
- package/lib/dist/common/solid-face.d.ts +0 -9
- package/lib/dist/common/solid-face.js +0 -22
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { Shape, ShapeFilter } from "./shape.js";
|
|
2
|
+
import { Face } from "./face.js";
|
|
3
|
+
import { Edge } from "./edge.js";
|
|
2
4
|
import { Matrix4 } from "../math/matrix4.js";
|
|
3
5
|
import { ISceneObject } from "../core/interfaces.js";
|
|
4
6
|
import { FusionScope, OperationMode } from "../features/extrude-options.js";
|
|
@@ -8,6 +10,19 @@ export type SourceLocation = {
|
|
|
8
10
|
line: number;
|
|
9
11
|
column: number;
|
|
10
12
|
};
|
|
13
|
+
export type AdditionRecord<T> = {
|
|
14
|
+
shape: T;
|
|
15
|
+
addedBy: SceneObject;
|
|
16
|
+
};
|
|
17
|
+
export type RemovalRecord<T> = {
|
|
18
|
+
shape: T;
|
|
19
|
+
removedBy: SceneObject;
|
|
20
|
+
};
|
|
21
|
+
export type ModificationRecord<T> = {
|
|
22
|
+
sources: T[];
|
|
23
|
+
results: T[];
|
|
24
|
+
modifiedBy: SceneObject;
|
|
25
|
+
};
|
|
11
26
|
export interface Comparable<T> {
|
|
12
27
|
compareTo(other: T): boolean;
|
|
13
28
|
}
|
|
@@ -74,11 +89,41 @@ export declare abstract class SceneObject implements Comparable<SceneObject>, Se
|
|
|
74
89
|
private set addedShapes(value);
|
|
75
90
|
private get removedShapes();
|
|
76
91
|
private set removedShapes(value);
|
|
92
|
+
private get addedFaces();
|
|
93
|
+
private set addedFaces(value);
|
|
94
|
+
private get modifiedFaces();
|
|
95
|
+
private set modifiedFaces(value);
|
|
96
|
+
private get removedFaces();
|
|
97
|
+
private set removedFaces(value);
|
|
98
|
+
private get addedEdges();
|
|
99
|
+
private set addedEdges(value);
|
|
100
|
+
private get modifiedEdges();
|
|
101
|
+
private set modifiedEdges(value);
|
|
102
|
+
private get removedEdges();
|
|
103
|
+
private set removedEdges(value);
|
|
104
|
+
private get finalShapes();
|
|
105
|
+
private set finalShapes(value);
|
|
77
106
|
getUniqueType(): string;
|
|
78
107
|
addShape(shape: Shape): void;
|
|
79
108
|
addShapes(shapes: Shape[]): void;
|
|
80
109
|
removeShape(shape: Shape, removedBy: SceneObject): void;
|
|
81
110
|
removeShapes(removedBy: SceneObject, force?: boolean): void;
|
|
111
|
+
recordAddedFace(face: Face, addedBy: SceneObject): void;
|
|
112
|
+
recordAddedEdge(edge: Edge, addedBy: SceneObject): void;
|
|
113
|
+
recordModifiedFaces(sources: Face[], results: Face[], modifiedBy: SceneObject): void;
|
|
114
|
+
recordModifiedEdges(sources: Edge[], results: Edge[], modifiedBy: SceneObject): void;
|
|
115
|
+
recordRemovedFace(face: Face, removedBy: SceneObject): void;
|
|
116
|
+
recordRemovedEdge(edge: Edge, removedBy: SceneObject): void;
|
|
117
|
+
private ownsFace;
|
|
118
|
+
private ownsEdge;
|
|
119
|
+
getAddedFaces(scope?: Set<SceneObject>): Face[];
|
|
120
|
+
getModifiedFaces(scope?: Set<SceneObject>): ModificationRecord<Face>[];
|
|
121
|
+
getRemovedFaces(scope?: Set<SceneObject>): Face[];
|
|
122
|
+
getAddedEdges(scope?: Set<SceneObject>): Edge[];
|
|
123
|
+
getModifiedEdges(scope?: Set<SceneObject>): ModificationRecord<Edge>[];
|
|
124
|
+
getRemovedEdges(scope?: Set<SceneObject>): Edge[];
|
|
125
|
+
setFinalShapes(shapes: Shape[]): void;
|
|
126
|
+
getFinalShapes(): Shape[];
|
|
82
127
|
getOwnShapes(filter?: ShapeFilter, scope?: Set<SceneObject>): Shape[];
|
|
83
128
|
getChildShapes(filter?: ShapeFilter, type?: ShapeType): Shape[];
|
|
84
129
|
getShapes(filter?: ShapeFilter, type?: ShapeType): Shape[];
|
|
@@ -21,6 +21,13 @@ export class SceneObject {
|
|
|
21
21
|
this.state = new Map();
|
|
22
22
|
this.state.set('addedShapes', []);
|
|
23
23
|
this.state.set('removedShapes', []);
|
|
24
|
+
this.state.set('addedFaces', []);
|
|
25
|
+
this.state.set('modifiedFaces', []);
|
|
26
|
+
this.state.set('removedFaces', []);
|
|
27
|
+
this.state.set('addedEdges', []);
|
|
28
|
+
this.state.set('modifiedEdges', []);
|
|
29
|
+
this.state.set('removedEdges', []);
|
|
30
|
+
this.state.set('finalShapes', []);
|
|
24
31
|
this._id = randomUUID().toString();
|
|
25
32
|
}
|
|
26
33
|
get id() {
|
|
@@ -208,6 +215,48 @@ export class SceneObject {
|
|
|
208
215
|
set removedShapes(shapes) {
|
|
209
216
|
this.state.set('removedShapes', shapes);
|
|
210
217
|
}
|
|
218
|
+
get addedFaces() {
|
|
219
|
+
return this.state.get('addedFaces');
|
|
220
|
+
}
|
|
221
|
+
set addedFaces(records) {
|
|
222
|
+
this.state.set('addedFaces', records);
|
|
223
|
+
}
|
|
224
|
+
get modifiedFaces() {
|
|
225
|
+
return this.state.get('modifiedFaces');
|
|
226
|
+
}
|
|
227
|
+
set modifiedFaces(records) {
|
|
228
|
+
this.state.set('modifiedFaces', records);
|
|
229
|
+
}
|
|
230
|
+
get removedFaces() {
|
|
231
|
+
return this.state.get('removedFaces');
|
|
232
|
+
}
|
|
233
|
+
set removedFaces(records) {
|
|
234
|
+
this.state.set('removedFaces', records);
|
|
235
|
+
}
|
|
236
|
+
get addedEdges() {
|
|
237
|
+
return this.state.get('addedEdges');
|
|
238
|
+
}
|
|
239
|
+
set addedEdges(records) {
|
|
240
|
+
this.state.set('addedEdges', records);
|
|
241
|
+
}
|
|
242
|
+
get modifiedEdges() {
|
|
243
|
+
return this.state.get('modifiedEdges');
|
|
244
|
+
}
|
|
245
|
+
set modifiedEdges(records) {
|
|
246
|
+
this.state.set('modifiedEdges', records);
|
|
247
|
+
}
|
|
248
|
+
get removedEdges() {
|
|
249
|
+
return this.state.get('removedEdges');
|
|
250
|
+
}
|
|
251
|
+
set removedEdges(records) {
|
|
252
|
+
this.state.set('removedEdges', records);
|
|
253
|
+
}
|
|
254
|
+
get finalShapes() {
|
|
255
|
+
return this.state.get('finalShapes');
|
|
256
|
+
}
|
|
257
|
+
set finalShapes(shapes) {
|
|
258
|
+
this.state.set('finalShapes', shapes);
|
|
259
|
+
}
|
|
211
260
|
getUniqueType() {
|
|
212
261
|
return this.getType();
|
|
213
262
|
}
|
|
@@ -251,6 +300,78 @@ export class SceneObject {
|
|
|
251
300
|
this.removeShape(shape, removedBy);
|
|
252
301
|
}
|
|
253
302
|
}
|
|
303
|
+
recordAddedFace(face, addedBy) {
|
|
304
|
+
this.addedFaces.push({ shape: face, addedBy });
|
|
305
|
+
}
|
|
306
|
+
recordAddedEdge(edge, addedBy) {
|
|
307
|
+
this.addedEdges.push({ shape: edge, addedBy });
|
|
308
|
+
}
|
|
309
|
+
recordModifiedFaces(sources, results, modifiedBy) {
|
|
310
|
+
this.modifiedFaces.push({ sources, results, modifiedBy });
|
|
311
|
+
}
|
|
312
|
+
recordModifiedEdges(sources, results, modifiedBy) {
|
|
313
|
+
this.modifiedEdges.push({ sources, results, modifiedBy });
|
|
314
|
+
}
|
|
315
|
+
recordRemovedFace(face, removedBy) {
|
|
316
|
+
if (this.isContainer()) {
|
|
317
|
+
for (const child of this.children) {
|
|
318
|
+
if (child.ownsFace(face)) {
|
|
319
|
+
child.recordRemovedFace(face, removedBy);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
this.removedFaces.push({ shape: face, removedBy });
|
|
325
|
+
}
|
|
326
|
+
recordRemovedEdge(edge, removedBy) {
|
|
327
|
+
if (this.isContainer()) {
|
|
328
|
+
for (const child of this.children) {
|
|
329
|
+
if (child.ownsEdge(edge)) {
|
|
330
|
+
child.recordRemovedEdge(edge, removedBy);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
this.removedEdges.push({ shape: edge, removedBy });
|
|
336
|
+
}
|
|
337
|
+
ownsFace(face) {
|
|
338
|
+
return this.addedFaces.some(r => r.shape === face);
|
|
339
|
+
}
|
|
340
|
+
ownsEdge(edge) {
|
|
341
|
+
return this.addedEdges.some(r => r.shape === edge);
|
|
342
|
+
}
|
|
343
|
+
getAddedFaces(scope) {
|
|
344
|
+
return this.addedFaces
|
|
345
|
+
.filter(r => !scope || scope.has(r.addedBy))
|
|
346
|
+
.map(r => r.shape);
|
|
347
|
+
}
|
|
348
|
+
getModifiedFaces(scope) {
|
|
349
|
+
return this.modifiedFaces.filter(r => !scope || scope.has(r.modifiedBy));
|
|
350
|
+
}
|
|
351
|
+
getRemovedFaces(scope) {
|
|
352
|
+
return this.removedFaces
|
|
353
|
+
.filter(r => !scope || scope.has(r.removedBy))
|
|
354
|
+
.map(r => r.shape);
|
|
355
|
+
}
|
|
356
|
+
getAddedEdges(scope) {
|
|
357
|
+
return this.addedEdges
|
|
358
|
+
.filter(r => !scope || scope.has(r.addedBy))
|
|
359
|
+
.map(r => r.shape);
|
|
360
|
+
}
|
|
361
|
+
getModifiedEdges(scope) {
|
|
362
|
+
return this.modifiedEdges.filter(r => !scope || scope.has(r.modifiedBy));
|
|
363
|
+
}
|
|
364
|
+
getRemovedEdges(scope) {
|
|
365
|
+
return this.removedEdges
|
|
366
|
+
.filter(r => !scope || scope.has(r.removedBy))
|
|
367
|
+
.map(r => r.shape);
|
|
368
|
+
}
|
|
369
|
+
setFinalShapes(shapes) {
|
|
370
|
+
this.finalShapes = shapes;
|
|
371
|
+
}
|
|
372
|
+
getFinalShapes() {
|
|
373
|
+
return this.finalShapes;
|
|
374
|
+
}
|
|
254
375
|
getOwnShapes(filter, scope) {
|
|
255
376
|
filter = {
|
|
256
377
|
excludeMeta: filter?.excludeMeta ?? true,
|
|
@@ -4,5 +4,5 @@ import { Wire } from "./wire.js";
|
|
|
4
4
|
import { Face } from "./face.js";
|
|
5
5
|
import { Edge } from "./edge.js";
|
|
6
6
|
export declare class ShapeFactory {
|
|
7
|
-
static fromShape(shape: TopoDS_Shape):
|
|
7
|
+
static fromShape(shape: TopoDS_Shape): Solid | Face | Edge | Wire;
|
|
8
8
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { BRepBuilderAPI_MakeShape } from "occjs-wrapper";
|
|
2
|
+
import { Face } from "./face.js";
|
|
3
|
+
import { Edge } from "./edge.js";
|
|
4
|
+
import { Shape } from "./shape.js";
|
|
5
|
+
export type ShapeHistoryRecord<T> = {
|
|
6
|
+
sources: T[];
|
|
7
|
+
results: T[];
|
|
8
|
+
};
|
|
9
|
+
export type ShapeHistory = {
|
|
10
|
+
addedFaces: Face[];
|
|
11
|
+
modifiedFaces: ShapeHistoryRecord<Face>[];
|
|
12
|
+
generatedFaces: ShapeHistoryRecord<Face>[];
|
|
13
|
+
removedFaces: Face[];
|
|
14
|
+
addedEdges: Edge[];
|
|
15
|
+
modifiedEdges: ShapeHistoryRecord<Edge>[];
|
|
16
|
+
generatedEdges: ShapeHistoryRecord<Edge>[];
|
|
17
|
+
removedEdges: Edge[];
|
|
18
|
+
};
|
|
19
|
+
export declare class ShapeHistoryTracker {
|
|
20
|
+
/**
|
|
21
|
+
* Remap a list of pre-operation faces through a `ShapeHistory`'s
|
|
22
|
+
* modifications. For each input face:
|
|
23
|
+
* - If it appears as a source in `modifiedFaces`, emit the corresponding
|
|
24
|
+
* result faces (1:N).
|
|
25
|
+
* - Otherwise, pass it through unchanged (it survived the operation with
|
|
26
|
+
* the same TShape pointer).
|
|
27
|
+
*
|
|
28
|
+
* Use this to keep classification arrays (start/end/side/…) valid after a
|
|
29
|
+
* fusion has modified some of their faces.
|
|
30
|
+
*/
|
|
31
|
+
static remapFaces(faces: Face[], history: ShapeHistory): Face[];
|
|
32
|
+
static remapEdges(edges: Edge[], history: ShapeHistory): Edge[];
|
|
33
|
+
static collect(maker: BRepBuilderAPI_MakeShape, inputs: Shape[]): ShapeHistory;
|
|
34
|
+
private static collectForType;
|
|
35
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { getOC } from "../oc/init.js";
|
|
2
|
+
import { Explorer } from "../oc/explorer.js";
|
|
3
|
+
import { ShapeOps } from "../oc/shape-ops.js";
|
|
4
|
+
import { Face } from "./face.js";
|
|
5
|
+
import { Edge } from "./edge.js";
|
|
6
|
+
export class ShapeHistoryTracker {
|
|
7
|
+
/**
|
|
8
|
+
* Remap a list of pre-operation faces through a `ShapeHistory`'s
|
|
9
|
+
* modifications. For each input face:
|
|
10
|
+
* - If it appears as a source in `modifiedFaces`, emit the corresponding
|
|
11
|
+
* result faces (1:N).
|
|
12
|
+
* - Otherwise, pass it through unchanged (it survived the operation with
|
|
13
|
+
* the same TShape pointer).
|
|
14
|
+
*
|
|
15
|
+
* Use this to keep classification arrays (start/end/side/…) valid after a
|
|
16
|
+
* fusion has modified some of their faces.
|
|
17
|
+
*/
|
|
18
|
+
static remapFaces(faces, history) {
|
|
19
|
+
const result = [];
|
|
20
|
+
for (const face of faces) {
|
|
21
|
+
const record = history.modifiedFaces.find(m => m.sources.some(s => s.getShape().IsSame(face.getShape())));
|
|
22
|
+
if (record) {
|
|
23
|
+
result.push(...record.results);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
result.push(face);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
static remapEdges(edges, history) {
|
|
32
|
+
const result = [];
|
|
33
|
+
for (const edge of edges) {
|
|
34
|
+
const record = history.modifiedEdges.find(m => m.sources.some(s => s.getShape().IsSame(edge.getShape())));
|
|
35
|
+
if (record) {
|
|
36
|
+
result.push(...record.results);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
result.push(edge);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
static collect(maker, inputs) {
|
|
45
|
+
const oc = getOC();
|
|
46
|
+
const FACE = oc.TopAbs_ShapeEnum.TopAbs_FACE;
|
|
47
|
+
const EDGE = oc.TopAbs_ShapeEnum.TopAbs_EDGE;
|
|
48
|
+
const output = maker.Shape();
|
|
49
|
+
const outputFaces = Explorer.findShapes(output, FACE);
|
|
50
|
+
const outputEdges = Explorer.findShapes(output, EDGE);
|
|
51
|
+
const faces = ShapeHistoryTracker.collectForType(maker, inputs, FACE, outputFaces, (raw) => Face.fromTopoDSFace(Explorer.toFace(raw)));
|
|
52
|
+
const edges = ShapeHistoryTracker.collectForType(maker, inputs, EDGE, outputEdges, (raw) => Edge.fromTopoDSEdge(Explorer.toEdge(raw)));
|
|
53
|
+
return {
|
|
54
|
+
addedFaces: faces.added,
|
|
55
|
+
modifiedFaces: faces.modified,
|
|
56
|
+
generatedFaces: faces.generated,
|
|
57
|
+
removedFaces: faces.removed,
|
|
58
|
+
addedEdges: edges.added,
|
|
59
|
+
modifiedEdges: edges.modified,
|
|
60
|
+
generatedEdges: edges.generated,
|
|
61
|
+
removedEdges: edges.removed,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
static collectForType(maker, inputs, type, outputRaws, wrap) {
|
|
65
|
+
const oc = getOC();
|
|
66
|
+
const modified = [];
|
|
67
|
+
const generated = [];
|
|
68
|
+
const removed = [];
|
|
69
|
+
// Collect every output raw that was either Modified or Generated from an input,
|
|
70
|
+
// so we can later classify the remaining outputs as pure additions.
|
|
71
|
+
const claimed = new oc.TopTools_MapOfShape();
|
|
72
|
+
const isOfType = (raw) => raw.ShapeType() === type;
|
|
73
|
+
for (const input of inputs) {
|
|
74
|
+
const inputRaws = Explorer.findShapes(input.getShape(), type);
|
|
75
|
+
for (const inputRaw of inputRaws) {
|
|
76
|
+
const modifiedRaws = ShapeOps.shapeListToArray(maker.Modified(inputRaw)).filter(isOfType);
|
|
77
|
+
const generatedRaws = ShapeOps.shapeListToArray(maker.Generated(inputRaw)).filter(isOfType);
|
|
78
|
+
const isDeleted = maker.IsDeleted(inputRaw);
|
|
79
|
+
if (modifiedRaws.length > 0) {
|
|
80
|
+
modified.push({
|
|
81
|
+
sources: [wrap(inputRaw)],
|
|
82
|
+
results: modifiedRaws.map(wrap),
|
|
83
|
+
});
|
|
84
|
+
for (const r of modifiedRaws) {
|
|
85
|
+
claimed.Add(r);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (generatedRaws.length > 0) {
|
|
89
|
+
generated.push({
|
|
90
|
+
sources: [wrap(inputRaw)],
|
|
91
|
+
results: generatedRaws.map(wrap),
|
|
92
|
+
});
|
|
93
|
+
for (const r of generatedRaws) {
|
|
94
|
+
claimed.Add(r);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// An input that is deleted with no successor is a removal. If it was
|
|
98
|
+
// Modified into something, the modification record already captures
|
|
99
|
+
// its fate — don't double-count as removed.
|
|
100
|
+
if (isDeleted && modifiedRaws.length === 0 && generatedRaws.length === 0) {
|
|
101
|
+
removed.push(wrap(inputRaw));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
const added = [];
|
|
106
|
+
for (const raw of outputRaws) {
|
|
107
|
+
if (!claimed.Contains(raw)) {
|
|
108
|
+
added.push(wrap(raw));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
claimed.delete();
|
|
112
|
+
return { added, modified, generated, removed };
|
|
113
|
+
}
|
|
114
|
+
}
|
package/lib/dist/common/shape.js
CHANGED
|
@@ -87,7 +87,13 @@ export class Shape {
|
|
|
87
87
|
if (this.isVertex()) {
|
|
88
88
|
throw new Error("Cannot set color on vertex shape");
|
|
89
89
|
}
|
|
90
|
-
this.colorMap.
|
|
90
|
+
const existing = this.colorMap.findIndex(c => c.shape.IsSame(face));
|
|
91
|
+
if (existing >= 0) {
|
|
92
|
+
this.colorMap[existing] = { shape: face, color };
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
this.colorMap.push({ shape: face, color });
|
|
96
|
+
}
|
|
91
97
|
}
|
|
92
98
|
getColor(face) {
|
|
93
99
|
const entry = this.colorMap.find(c => c.shape.IsSame(face));
|
package/lib/dist/common/solid.js
CHANGED
|
@@ -60,7 +60,11 @@ export class Solid extends Shape {
|
|
|
60
60
|
return null;
|
|
61
61
|
}
|
|
62
62
|
copy() {
|
|
63
|
-
|
|
63
|
+
const copied = new Solid(this.getShape());
|
|
64
|
+
for (const entry of this.colorMap) {
|
|
65
|
+
copied.colorMap.push({ shape: entry.shape, color: entry.color });
|
|
66
|
+
}
|
|
67
|
+
return copied;
|
|
64
68
|
}
|
|
65
69
|
static fromTopoDSSolid(solid) {
|
|
66
70
|
return new Solid(solid);
|
|
@@ -2,45 +2,44 @@ import { IExtrude, ISceneObject } from "./interfaces.js";
|
|
|
2
2
|
interface ExtrudeFunction {
|
|
3
3
|
/**
|
|
4
4
|
* Extrudes the last sketch with a default distance.
|
|
5
|
-
* @param target - The sketch to extrude
|
|
5
|
+
* @param target - The sketch or face-bearing scene object to extrude
|
|
6
6
|
*/
|
|
7
7
|
(target?: ISceneObject): IExtrude;
|
|
8
8
|
/**
|
|
9
|
-
* Extrudes
|
|
9
|
+
* Extrudes by a given distance.
|
|
10
10
|
* @param distance - The extrusion distance
|
|
11
|
-
* @param target - The sketch to extrude
|
|
11
|
+
* @param target - The sketch or face-bearing scene object to extrude
|
|
12
12
|
*/
|
|
13
13
|
(distance: number, target?: ISceneObject): IExtrude;
|
|
14
14
|
/**
|
|
15
|
-
* Extrudes
|
|
15
|
+
* Extrudes between two distances.
|
|
16
16
|
* @param distance1 - The first extrusion distance
|
|
17
17
|
* @param distance2 - The second extrusion distance
|
|
18
|
-
* @param target - The sketch to extrude
|
|
19
18
|
*/
|
|
20
19
|
(distance1: number, distance2: number): IExtrude;
|
|
21
20
|
/**
|
|
22
|
-
* Extrudes
|
|
21
|
+
* Extrudes between two distances.
|
|
23
22
|
* @param distance1 - The first extrusion distance
|
|
24
23
|
* @param distance2 - The second extrusion distance
|
|
25
|
-
* @param target - The sketch to extrude
|
|
24
|
+
* @param target - The sketch or face-bearing scene object to extrude
|
|
26
25
|
*/
|
|
27
26
|
(distance1: number, distance2: number, target: ISceneObject): IExtrude;
|
|
28
27
|
/**
|
|
29
|
-
* Extrudes
|
|
28
|
+
* Extrudes up to a specific face.
|
|
30
29
|
* @param face - A face selection to extrude up to
|
|
31
|
-
* @param target - The sketch to extrude
|
|
30
|
+
* @param target - The sketch or face-bearing scene object to extrude
|
|
32
31
|
*/
|
|
33
32
|
(face: ISceneObject, target?: ISceneObject): IExtrude;
|
|
34
33
|
/**
|
|
35
|
-
* Extrudes
|
|
34
|
+
* Extrudes up to the first intersecting face.
|
|
36
35
|
* @param face - The literal `'first-face'`
|
|
37
|
-
* @param target - The sketch to extrude
|
|
36
|
+
* @param target - The sketch or face-bearing scene object to extrude
|
|
38
37
|
*/
|
|
39
38
|
(face: 'first-face', target?: ISceneObject): IExtrude;
|
|
40
39
|
/**
|
|
41
|
-
* Extrudes
|
|
40
|
+
* Extrudes up to the last intersecting face.
|
|
42
41
|
* @param face - The literal `'last-face'`
|
|
43
|
-
* @param target - The sketch to extrude
|
|
42
|
+
* @param target - The sketch or face-bearing scene object to extrude
|
|
44
43
|
*/
|
|
45
44
|
(face: 'last-face', target?: ISceneObject): IExtrude;
|
|
46
45
|
}
|
package/lib/dist/core/extrude.js
CHANGED
|
@@ -3,9 +3,22 @@ import { registerBuilder } from "../index.js";
|
|
|
3
3
|
import { Extrude } from "../features/extrude.js";
|
|
4
4
|
import { ExtrudeTwoDistances } from "../features/extrude-two-distances.js";
|
|
5
5
|
import { ExtrudeToFace } from "../features/extrude-to-face.js";
|
|
6
|
+
import { SelectSceneObject } from "../features/select.js";
|
|
6
7
|
function isExtrudable(obj) {
|
|
7
8
|
return obj instanceof SceneObject && obj.isExtrudable();
|
|
8
9
|
}
|
|
10
|
+
function isFaceSource(obj) {
|
|
11
|
+
if (!(obj instanceof SceneObject)) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
if (isExtrudable(obj)) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
if (obj instanceof SelectSceneObject) {
|
|
18
|
+
return obj.shapeType() === 'face';
|
|
19
|
+
}
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
9
22
|
function build(context) {
|
|
10
23
|
function doExtrude(params, extrudable) {
|
|
11
24
|
const defaultDistance = 25;
|
|
@@ -41,8 +54,13 @@ function build(context) {
|
|
|
41
54
|
return function extrude() {
|
|
42
55
|
const args = [...arguments];
|
|
43
56
|
let extrudable;
|
|
44
|
-
|
|
57
|
+
const last = args.length > 0 ? args[args.length - 1] : undefined;
|
|
58
|
+
if (last !== undefined && isExtrudable(last)) {
|
|
59
|
+
extrudable = args.pop();
|
|
60
|
+
}
|
|
61
|
+
else if (last !== undefined && args.length >= 2 && isFaceSource(last)) {
|
|
45
62
|
extrudable = args.pop();
|
|
63
|
+
context.addSceneObject(extrudable);
|
|
46
64
|
}
|
|
47
65
|
else {
|
|
48
66
|
extrudable = context.getLastExtrudable() || undefined;
|
package/lib/dist/core/part.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { ISceneObject } from "./interfaces.js";
|
|
2
|
-
|
|
2
|
+
type Extend<T> = T extends object ? T : {};
|
|
3
|
+
declare function part<T>(name: string, callback: () => T): ISceneObject & Extend<T>;
|
|
3
4
|
export default part;
|
package/lib/dist/core/part.js
CHANGED
|
@@ -12,8 +12,11 @@ function part(name, callback) {
|
|
|
12
12
|
partObj.setSourceLocation(sourceLocation);
|
|
13
13
|
}
|
|
14
14
|
scene.startProgressiveContainer(partObj);
|
|
15
|
-
callback();
|
|
15
|
+
const extensions = callback();
|
|
16
16
|
scene.endProgressiveContainer();
|
|
17
|
+
if (extensions && typeof extensions === 'object') {
|
|
18
|
+
Object.assign(partObj, extensions);
|
|
19
|
+
}
|
|
17
20
|
return partObj;
|
|
18
21
|
}
|
|
19
22
|
export default part;
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
import { PlaneLike } from "../math/plane.js";
|
|
2
2
|
import { IPlane, ISceneObject } from "./interfaces.js";
|
|
3
|
+
type Extend<T> = T extends object ? T : {};
|
|
3
4
|
interface SketchFunction {
|
|
4
5
|
/**
|
|
5
6
|
* Draws 2D geometry on a standard plane.
|
|
6
7
|
* @param plane - The plane to sketch on
|
|
7
8
|
* @param sketcher - Callback containing sketch operations
|
|
8
9
|
*/
|
|
9
|
-
(plane: PlaneLike, sketcher: () =>
|
|
10
|
+
<T>(plane: PlaneLike, sketcher: () => T): ISceneObject & Extend<T>;
|
|
10
11
|
/**
|
|
11
12
|
* Draws 2D geometry on a face selection.
|
|
12
13
|
* @param face - The face to sketch on
|
|
13
14
|
* @param sketcher - Callback containing sketch operations
|
|
14
15
|
*/
|
|
15
|
-
(face: ISceneObject, sketcher: () =>
|
|
16
|
+
<T>(face: ISceneObject, sketcher: () => T): ISceneObject & Extend<T>;
|
|
16
17
|
/**
|
|
17
18
|
* Draws 2D geometry on an existing Plane object.
|
|
18
19
|
* @param plane - The Plane object to sketch on
|
|
19
20
|
* @param sketcher - Callback containing sketch operations
|
|
20
21
|
*/
|
|
21
|
-
(plane: IPlane, sketcher: () =>
|
|
22
|
+
<T>(plane: IPlane, sketcher: () => T): ISceneObject & Extend<T>;
|
|
22
23
|
}
|
|
23
24
|
declare const _default: SketchFunction;
|
|
24
25
|
export default _default;
|
package/lib/dist/core/sketch.js
CHANGED
|
@@ -26,8 +26,11 @@ function build(context) {
|
|
|
26
26
|
}
|
|
27
27
|
const sketch = new Sketch(planeObj);
|
|
28
28
|
context.startProgressiveContainer(sketch);
|
|
29
|
-
sketcher();
|
|
29
|
+
const extensions = sketcher();
|
|
30
30
|
context.endProgressiveContainer();
|
|
31
|
+
if (extensions && typeof extensions === 'object') {
|
|
32
|
+
Object.assign(sketch, extensions);
|
|
33
|
+
}
|
|
31
34
|
return sketch;
|
|
32
35
|
};
|
|
33
36
|
}
|
|
@@ -2,6 +2,7 @@ import { SceneObject } from "../common/scene-object.js";
|
|
|
2
2
|
import { FilletOps } from "../oc/fillet-ops.js";
|
|
3
3
|
import { Explorer } from "../oc/explorer.js";
|
|
4
4
|
import { ShapeOps } from "../oc/shape-ops.js";
|
|
5
|
+
import { ColorTransfer } from "../oc/color-transfer.js";
|
|
5
6
|
export class Chamfer extends SceneObject {
|
|
6
7
|
distance;
|
|
7
8
|
distance2;
|
|
@@ -62,9 +63,9 @@ export class Chamfer extends SceneObject {
|
|
|
62
63
|
}
|
|
63
64
|
edges = edges.filter(e => !targetEdges.includes(e));
|
|
64
65
|
try {
|
|
65
|
-
let
|
|
66
|
+
let preCleanSolids;
|
|
66
67
|
if (!this.distance2) {
|
|
67
|
-
|
|
68
|
+
preCleanSolids = FilletOps.makeChamfer(solid, targetEdges, this.distance);
|
|
68
69
|
}
|
|
69
70
|
else {
|
|
70
71
|
const faces = solid.getFaces();
|
|
@@ -78,13 +79,18 @@ export class Chamfer extends SceneObject {
|
|
|
78
79
|
}
|
|
79
80
|
commonFaces.push(firstCommonFace);
|
|
80
81
|
}
|
|
81
|
-
|
|
82
|
+
preCleanSolids = FilletOps.makeChamferTwoDistances(solid, targetEdges, this.distance, this.distance2, commonFaces, this.isAngle);
|
|
82
83
|
}
|
|
83
84
|
const obj = shapeObjectMap.get(shape);
|
|
84
85
|
obj.removeShape(shape, this);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
// Clean each chamfer result and chain colors through the cleanup's
|
|
87
|
+
// UnifySameDomain history so any merged faces keep their colors.
|
|
88
|
+
for (const preClean of preCleanSolids) {
|
|
89
|
+
const cleanup = ShapeOps.cleanShapeWithLineage(preClean);
|
|
90
|
+
ColorTransfer.applyThroughCleanup(preClean, cleanup);
|
|
91
|
+
const cleaned = cleanup.shape;
|
|
92
|
+
cleanup.dispose();
|
|
93
|
+
newShapes.push(cleaned);
|
|
88
94
|
}
|
|
89
95
|
}
|
|
90
96
|
catch {
|