brepjs 2.0.0 → 2.0.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/dist/brepjs.cjs +1097 -1044
- package/dist/brepjs.d.ts +32 -22
- package/dist/brepjs.js +1097 -1044
- package/package.json +3 -3
package/dist/brepjs.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
|
|
2
|
+
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
|
|
3
3
|
var __typeError = (msg) => {
|
|
4
4
|
throw TypeError(msg);
|
|
5
5
|
};
|
|
@@ -46,6 +46,13 @@ var __callDispose = (stack, error, hasError) => {
|
|
|
46
46
|
};
|
|
47
47
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
48
48
|
const opentype = require("opentype.js");
|
|
49
|
+
let _counter = 0;
|
|
50
|
+
function uniqueIOFilename(prefix, ext) {
|
|
51
|
+
return `${prefix}_${++_counter}.${ext}`;
|
|
52
|
+
}
|
|
53
|
+
function uniqueId() {
|
|
54
|
+
return `_io_${++_counter}`;
|
|
55
|
+
}
|
|
49
56
|
const HASH_CODE_MAX$1 = 2147483647;
|
|
50
57
|
class OCCTAdapter {
|
|
51
58
|
oc;
|
|
@@ -78,9 +85,10 @@ class OCCTAdapter {
|
|
|
78
85
|
return result;
|
|
79
86
|
}
|
|
80
87
|
intersect(shape, tool, options = {}) {
|
|
81
|
-
const { simplify = false } = options;
|
|
88
|
+
const { optimisation, simplify = false } = options;
|
|
82
89
|
const progress = new this.oc.Message_ProgressRange_1();
|
|
83
90
|
const commonOp = new this.oc.BRepAlgoAPI_Common_3(shape, tool, progress);
|
|
91
|
+
this._applyGlue(commonOp, optimisation);
|
|
84
92
|
commonOp.Build(progress);
|
|
85
93
|
if (simplify) commonOp.SimplifyResult(true, true, 1e-3);
|
|
86
94
|
const result = commonOp.Shape();
|
|
@@ -154,7 +162,9 @@ class OCCTAdapter {
|
|
|
154
162
|
return this._cutAllBatch(shape, tools, options);
|
|
155
163
|
}
|
|
156
164
|
const toolCompound = this._buildCompound(tools);
|
|
157
|
-
|
|
165
|
+
const result = this.cut(shape, toolCompound, options);
|
|
166
|
+
toolCompound.delete();
|
|
167
|
+
return result;
|
|
158
168
|
}
|
|
159
169
|
_cutAllBatch(shape, tools, options = {}) {
|
|
160
170
|
const { optimisation, simplify = false } = options;
|
|
@@ -568,37 +578,157 @@ class OCCTAdapter {
|
|
|
568
578
|
explorer.delete();
|
|
569
579
|
return { vertices, normals, triangles, faceGroups };
|
|
570
580
|
}
|
|
571
|
-
meshEdges(shape, tolerance
|
|
572
|
-
|
|
573
|
-
|
|
581
|
+
meshEdges(shape, tolerance, angularTolerance) {
|
|
582
|
+
if (this.oc.EdgeMeshExtractor) {
|
|
583
|
+
return this._meshEdgesBulk(shape, tolerance, angularTolerance);
|
|
584
|
+
}
|
|
585
|
+
return this._meshEdgesJS(shape, tolerance, angularTolerance);
|
|
586
|
+
}
|
|
587
|
+
_meshEdgesBulk(shape, tolerance, angularTolerance) {
|
|
588
|
+
const raw = this.oc.EdgeMeshExtractor.extract(shape, tolerance, angularTolerance);
|
|
589
|
+
const linesSize = raw.getLinesSize();
|
|
590
|
+
const edgeGroupsSize = raw.getEdgeGroupsSize();
|
|
591
|
+
let lines;
|
|
592
|
+
if (linesSize > 0) {
|
|
593
|
+
const linesPtr = raw.getLinesPtr() / 4;
|
|
594
|
+
lines = this.oc.HEAPF32.slice(linesPtr, linesPtr + linesSize);
|
|
595
|
+
} else {
|
|
596
|
+
lines = new Float32Array(0);
|
|
597
|
+
}
|
|
598
|
+
const edgeGroups = [];
|
|
599
|
+
if (edgeGroupsSize > 0) {
|
|
600
|
+
const egPtr = raw.getEdgeGroupsPtr() / 4;
|
|
601
|
+
const egRaw = this.oc.HEAP32.slice(egPtr, egPtr + edgeGroupsSize);
|
|
602
|
+
for (let i = 0; i < egRaw.length; i += 3) {
|
|
603
|
+
edgeGroups.push({
|
|
604
|
+
start: egRaw[i],
|
|
605
|
+
count: egRaw[i + 1],
|
|
606
|
+
edgeHash: egRaw[i + 2]
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
raw.delete();
|
|
611
|
+
return { lines, edgeGroups };
|
|
612
|
+
}
|
|
613
|
+
_meshEdgesJS(shape, tolerance, angularTolerance) {
|
|
614
|
+
const mesher = new this.oc.BRepMesh_IncrementalMesh_2(
|
|
615
|
+
shape,
|
|
616
|
+
tolerance,
|
|
617
|
+
false,
|
|
618
|
+
angularTolerance,
|
|
619
|
+
false
|
|
620
|
+
);
|
|
621
|
+
mesher.delete();
|
|
622
|
+
const lines = [];
|
|
623
|
+
const edgeGroups = [];
|
|
624
|
+
const seenHashes = /* @__PURE__ */ new Set();
|
|
625
|
+
const faceExplorer = new this.oc.TopExp_Explorer_2(
|
|
626
|
+
shape,
|
|
627
|
+
this.oc.TopAbs_ShapeEnum.TopAbs_FACE,
|
|
628
|
+
this.oc.TopAbs_ShapeEnum.TopAbs_SHAPE
|
|
629
|
+
);
|
|
630
|
+
while (faceExplorer.More()) {
|
|
631
|
+
const face = this.oc.TopoDS.Face_1(faceExplorer.Current());
|
|
632
|
+
const faceLoc = new this.oc.TopLoc_Location_1();
|
|
633
|
+
const tri = this.oc.BRep_Tool.Triangulation(face, faceLoc, 0);
|
|
634
|
+
if (!tri.IsNull()) {
|
|
635
|
+
const triObj = tri.get();
|
|
636
|
+
const edgeExplorer2 = new this.oc.TopExp_Explorer_2(
|
|
637
|
+
face,
|
|
638
|
+
this.oc.TopAbs_ShapeEnum.TopAbs_EDGE,
|
|
639
|
+
this.oc.TopAbs_ShapeEnum.TopAbs_SHAPE
|
|
640
|
+
);
|
|
641
|
+
while (edgeExplorer2.More()) {
|
|
642
|
+
const edgeShape = edgeExplorer2.Current();
|
|
643
|
+
const edge = this.oc.TopoDS.Edge_1(edgeShape);
|
|
644
|
+
const edgeHash = edge.HashCode(HASH_CODE_MAX$1);
|
|
645
|
+
if (!seenHashes.has(edgeHash)) {
|
|
646
|
+
seenHashes.add(edgeHash);
|
|
647
|
+
const edgeLoc = new this.oc.TopLoc_Location_1();
|
|
648
|
+
const polygon = this.oc.BRep_Tool.PolygonOnTriangulation_1(edge, tri, edgeLoc);
|
|
649
|
+
const edgeNodes = polygon && !polygon.IsNull() ? polygon.get().Nodes() : null;
|
|
650
|
+
if (edgeNodes) {
|
|
651
|
+
const lineStart = lines.length / 3;
|
|
652
|
+
let prevX = 0, prevY = 0, prevZ = 0;
|
|
653
|
+
let hasPrev = false;
|
|
654
|
+
for (let i = edgeNodes.Lower(); i <= edgeNodes.Upper(); i++) {
|
|
655
|
+
const p = triObj.Node(edgeNodes.Value(i)).Transformed(edgeLoc.Transformation());
|
|
656
|
+
const x = p.X(), y = p.Y(), z = p.Z();
|
|
657
|
+
if (hasPrev) {
|
|
658
|
+
lines.push(prevX, prevY, prevZ, x, y, z);
|
|
659
|
+
}
|
|
660
|
+
prevX = x;
|
|
661
|
+
prevY = y;
|
|
662
|
+
prevZ = z;
|
|
663
|
+
hasPrev = true;
|
|
664
|
+
p.delete();
|
|
665
|
+
}
|
|
666
|
+
edgeGroups.push({
|
|
667
|
+
start: lineStart,
|
|
668
|
+
count: lines.length / 3 - lineStart,
|
|
669
|
+
edgeHash
|
|
670
|
+
});
|
|
671
|
+
edgeNodes.delete();
|
|
672
|
+
}
|
|
673
|
+
if (polygon && !polygon.IsNull()) polygon.delete();
|
|
674
|
+
edgeLoc.delete();
|
|
675
|
+
}
|
|
676
|
+
edgeExplorer2.Next();
|
|
677
|
+
}
|
|
678
|
+
edgeExplorer2.delete();
|
|
679
|
+
}
|
|
680
|
+
tri.delete();
|
|
681
|
+
faceLoc.delete();
|
|
682
|
+
faceExplorer.Next();
|
|
683
|
+
}
|
|
684
|
+
faceExplorer.delete();
|
|
685
|
+
const edgeExplorer = new this.oc.TopExp_Explorer_2(
|
|
574
686
|
shape,
|
|
575
687
|
this.oc.TopAbs_ShapeEnum.TopAbs_EDGE,
|
|
576
688
|
this.oc.TopAbs_ShapeEnum.TopAbs_SHAPE
|
|
577
689
|
);
|
|
578
|
-
while (
|
|
579
|
-
const
|
|
580
|
-
const
|
|
581
|
-
const
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
690
|
+
while (edgeExplorer.More()) {
|
|
691
|
+
const edgeShape = edgeExplorer.Current();
|
|
692
|
+
const edge = this.oc.TopoDS.Edge_1(edgeShape);
|
|
693
|
+
const edgeHash = edge.HashCode(HASH_CODE_MAX$1);
|
|
694
|
+
if (!seenHashes.has(edgeHash)) {
|
|
695
|
+
seenHashes.add(edgeHash);
|
|
696
|
+
const adaptor = new this.oc.BRepAdaptor_Curve_2(edge);
|
|
697
|
+
const tangDef = new this.oc.GCPnts_TangentialDeflection_2(
|
|
698
|
+
adaptor,
|
|
699
|
+
tolerance,
|
|
700
|
+
angularTolerance,
|
|
701
|
+
2,
|
|
702
|
+
1e-9,
|
|
703
|
+
1e-7
|
|
704
|
+
);
|
|
705
|
+
const lineStart = lines.length / 3;
|
|
706
|
+
let prevX = 0, prevY = 0, prevZ = 0;
|
|
707
|
+
let hasPrev = false;
|
|
708
|
+
for (let j = 1; j <= tangDef.NbPoints(); j++) {
|
|
709
|
+
const p = tangDef.Value(j);
|
|
710
|
+
const x = p.X(), y = p.Y(), z = p.Z();
|
|
711
|
+
if (hasPrev) {
|
|
712
|
+
lines.push(prevX, prevY, prevZ, x, y, z);
|
|
713
|
+
}
|
|
714
|
+
prevX = x;
|
|
715
|
+
prevY = y;
|
|
716
|
+
prevZ = z;
|
|
717
|
+
hasPrev = true;
|
|
718
|
+
p.delete();
|
|
719
|
+
}
|
|
720
|
+
edgeGroups.push({
|
|
721
|
+
start: lineStart,
|
|
722
|
+
count: lines.length / 3 - lineStart,
|
|
723
|
+
edgeHash
|
|
724
|
+
});
|
|
725
|
+
tangDef.delete();
|
|
726
|
+
adaptor.delete();
|
|
594
727
|
}
|
|
595
|
-
|
|
596
|
-
tangDef.delete();
|
|
597
|
-
adaptor.delete();
|
|
598
|
-
explorer.Next();
|
|
728
|
+
edgeExplorer.Next();
|
|
599
729
|
}
|
|
600
|
-
|
|
601
|
-
return
|
|
730
|
+
edgeExplorer.delete();
|
|
731
|
+
return { lines: new Float32Array(lines), edgeGroups };
|
|
602
732
|
}
|
|
603
733
|
// --- File I/O ---
|
|
604
734
|
exportSTEP(shapes) {
|
|
@@ -609,7 +739,7 @@ class OCCTAdapter {
|
|
|
609
739
|
for (const shape of shapes) {
|
|
610
740
|
writer.Transfer(shape, this.oc.STEPControl_StepModelType.STEPControl_AsIs, true, progress);
|
|
611
741
|
}
|
|
612
|
-
const filename = "_export
|
|
742
|
+
const filename = uniqueIOFilename("_export", "step");
|
|
613
743
|
const done = writer.Write(filename);
|
|
614
744
|
writer.delete();
|
|
615
745
|
progress.delete();
|
|
@@ -621,7 +751,7 @@ class OCCTAdapter {
|
|
|
621
751
|
throw new Error("STEP export failed: writer did not complete successfully");
|
|
622
752
|
}
|
|
623
753
|
exportSTL(shape, binary = false) {
|
|
624
|
-
const filename = "_export
|
|
754
|
+
const filename = uniqueIOFilename("_export", "stl");
|
|
625
755
|
const done = this.oc.StlAPI.Write(shape, filename, !binary);
|
|
626
756
|
if (done) {
|
|
627
757
|
const file = this.oc.FS.readFile("/" + filename);
|
|
@@ -632,7 +762,7 @@ class OCCTAdapter {
|
|
|
632
762
|
throw new Error("STL export failed: StlAPI.Write returned false");
|
|
633
763
|
}
|
|
634
764
|
importSTEP(data) {
|
|
635
|
-
const filename = "_import
|
|
765
|
+
const filename = uniqueIOFilename("_import", "step");
|
|
636
766
|
const buffer = typeof data === "string" ? new TextEncoder().encode(data) : new Uint8Array(data);
|
|
637
767
|
this.oc.FS.writeFile("/" + filename, buffer);
|
|
638
768
|
const reader = new this.oc.STEPControl_Reader_1();
|
|
@@ -650,7 +780,7 @@ class OCCTAdapter {
|
|
|
650
780
|
throw new Error("Failed to import STEP file: reader could not parse the input data");
|
|
651
781
|
}
|
|
652
782
|
importSTL(data) {
|
|
653
|
-
const filename = "_import
|
|
783
|
+
const filename = uniqueIOFilename("_import", "stl");
|
|
654
784
|
const buffer = typeof data === "string" ? new TextEncoder().encode(data) : new Uint8Array(data);
|
|
655
785
|
this.oc.FS.writeFile("/" + filename, buffer);
|
|
656
786
|
const reader = new this.oc.StlAPI_Reader();
|
|
@@ -663,12 +793,14 @@ class OCCTAdapter {
|
|
|
663
793
|
const solidBuilder = new this.oc.BRepBuilderAPI_MakeSolid_1();
|
|
664
794
|
solidBuilder.Add(this.oc.TopoDS.Shell_1(upgraded));
|
|
665
795
|
const solid = solidBuilder.Solid();
|
|
796
|
+
readShape.delete();
|
|
666
797
|
upgrader.delete();
|
|
667
798
|
solidBuilder.delete();
|
|
668
799
|
reader.delete();
|
|
669
800
|
return solid;
|
|
670
801
|
}
|
|
671
802
|
this.oc.FS.unlink("/" + filename);
|
|
803
|
+
readShape.delete();
|
|
672
804
|
reader.delete();
|
|
673
805
|
throw new Error("Failed to import STL file: reader could not parse the input data");
|
|
674
806
|
}
|
|
@@ -721,6 +853,32 @@ class OCCTAdapter {
|
|
|
721
853
|
}
|
|
722
854
|
// --- Topology iteration ---
|
|
723
855
|
iterShapes(shape, type) {
|
|
856
|
+
if (this.oc.TopologyExtractor) {
|
|
857
|
+
return this._iterShapesBulk(shape, type);
|
|
858
|
+
}
|
|
859
|
+
return this._iterShapesJS(shape, type);
|
|
860
|
+
}
|
|
861
|
+
_iterShapesBulk(shape, type) {
|
|
862
|
+
const typeEnumMap = {
|
|
863
|
+
vertex: 7,
|
|
864
|
+
edge: 6,
|
|
865
|
+
wire: 5,
|
|
866
|
+
face: 4,
|
|
867
|
+
shell: 3,
|
|
868
|
+
solid: 2,
|
|
869
|
+
compsolid: 1,
|
|
870
|
+
compound: 0
|
|
871
|
+
};
|
|
872
|
+
const raw = this.oc.TopologyExtractor.extract(shape, typeEnumMap[type]);
|
|
873
|
+
const count = raw.getShapesCount();
|
|
874
|
+
const result = [];
|
|
875
|
+
for (let i = 0; i < count; i++) {
|
|
876
|
+
result.push(raw.getShape(i));
|
|
877
|
+
}
|
|
878
|
+
raw.delete();
|
|
879
|
+
return result;
|
|
880
|
+
}
|
|
881
|
+
_iterShapesJS(shape, type) {
|
|
724
882
|
const typeMap = {
|
|
725
883
|
vertex: this.oc.TopAbs_ShapeEnum.TopAbs_VERTEX,
|
|
726
884
|
edge: this.oc.TopAbs_ShapeEnum.TopAbs_EDGE,
|
|
@@ -1064,14 +1222,6 @@ function localGC(debug) {
|
|
|
1064
1222
|
debug ? cleaner : void 0
|
|
1065
1223
|
];
|
|
1066
1224
|
}
|
|
1067
|
-
if (!globalThis.FinalizationRegistry) {
|
|
1068
|
-
console.warn("brepjs: FinalizationRegistry unavailable — garbage collection will not work");
|
|
1069
|
-
globalThis.FinalizationRegistry = (() => ({
|
|
1070
|
-
register: () => null,
|
|
1071
|
-
unregister: () => null
|
|
1072
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- polyfill shim
|
|
1073
|
-
}));
|
|
1074
|
-
}
|
|
1075
1225
|
const deletableRegistry = new globalThis.FinalizationRegistry((heldValue) => {
|
|
1076
1226
|
try {
|
|
1077
1227
|
heldValue.delete();
|
|
@@ -1155,7 +1305,7 @@ function vecDistance(a, b) {
|
|
|
1155
1305
|
}
|
|
1156
1306
|
function vecNormalize(v) {
|
|
1157
1307
|
const len = vecLength(v);
|
|
1158
|
-
if (len
|
|
1308
|
+
if (len < 1e-10) return [0, 0, 0];
|
|
1159
1309
|
return [v[0] / len, v[1] / len, v[2] / len];
|
|
1160
1310
|
}
|
|
1161
1311
|
function vecEquals(a, b, tolerance = 1e-5) {
|
|
@@ -1284,42 +1434,46 @@ const makeAx3 = (center, dir, xDir) => {
|
|
|
1284
1434
|
const oc = getKernel().oc;
|
|
1285
1435
|
const origin = asPnt(center);
|
|
1286
1436
|
const direction = asDir(dir);
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1437
|
+
const xDirection = xDir ? asDir(xDir) : null;
|
|
1438
|
+
try {
|
|
1439
|
+
if (xDirection) {
|
|
1440
|
+
return new oc.gp_Ax3_3(origin, direction, xDirection);
|
|
1441
|
+
} else {
|
|
1442
|
+
return new oc.gp_Ax3_4(origin, direction);
|
|
1443
|
+
}
|
|
1444
|
+
} finally {
|
|
1445
|
+
origin.delete();
|
|
1446
|
+
direction.delete();
|
|
1447
|
+
if (xDirection) xDirection.delete();
|
|
1294
1448
|
}
|
|
1295
|
-
origin.delete();
|
|
1296
|
-
direction.delete();
|
|
1297
|
-
return axis;
|
|
1298
1449
|
};
|
|
1299
1450
|
const makeAx2 = (center, dir, xDir) => {
|
|
1300
1451
|
const oc = getKernel().oc;
|
|
1301
1452
|
const origin = asPnt(center);
|
|
1302
1453
|
const direction = asDir(dir);
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1454
|
+
const xDirection = xDir ? asDir(xDir) : null;
|
|
1455
|
+
try {
|
|
1456
|
+
if (xDirection) {
|
|
1457
|
+
return new oc.gp_Ax2_2(origin, direction, xDirection);
|
|
1458
|
+
} else {
|
|
1459
|
+
return new oc.gp_Ax2_3(origin, direction);
|
|
1460
|
+
}
|
|
1461
|
+
} finally {
|
|
1462
|
+
origin.delete();
|
|
1463
|
+
direction.delete();
|
|
1464
|
+
if (xDirection) xDirection.delete();
|
|
1310
1465
|
}
|
|
1311
|
-
origin.delete();
|
|
1312
|
-
direction.delete();
|
|
1313
|
-
return axis;
|
|
1314
1466
|
};
|
|
1315
1467
|
const makeAx1 = (center, dir) => {
|
|
1316
1468
|
const oc = getKernel().oc;
|
|
1317
1469
|
const origin = asPnt(center);
|
|
1318
1470
|
const direction = asDir(dir);
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1471
|
+
try {
|
|
1472
|
+
return new oc.gp_Ax1_2(origin, direction);
|
|
1473
|
+
} finally {
|
|
1474
|
+
origin.delete();
|
|
1475
|
+
direction.delete();
|
|
1476
|
+
}
|
|
1323
1477
|
};
|
|
1324
1478
|
const makeVec = (vector = [0, 0, 0]) => {
|
|
1325
1479
|
const oc = getKernel().oc;
|
|
@@ -1586,24 +1740,24 @@ class Plane {
|
|
|
1586
1740
|
const dir = makeDirection(direction);
|
|
1587
1741
|
const zDir = new Vector(this.zDir).rotate(angle, [0, 0, 0], dir);
|
|
1588
1742
|
const xDir = new Vector(this.xDir).rotate(angle, [0, 0, 0], dir);
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1743
|
+
try {
|
|
1744
|
+
return new Plane(this.origin, xDir, zDir);
|
|
1745
|
+
} finally {
|
|
1746
|
+
zDir.delete();
|
|
1747
|
+
xDir.delete();
|
|
1748
|
+
}
|
|
1593
1749
|
}
|
|
1594
1750
|
rotate2DAxes(angle) {
|
|
1595
1751
|
const xDir = new Vector(this.xDir).rotate(angle, [0, 0, 0], this.zDir);
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1752
|
+
try {
|
|
1753
|
+
return new Plane(this.origin, xDir, this.zDir);
|
|
1754
|
+
} finally {
|
|
1755
|
+
xDir.delete();
|
|
1756
|
+
}
|
|
1599
1757
|
}
|
|
1600
1758
|
_calcTransforms() {
|
|
1601
1759
|
if (this.globalToLocal) this.globalToLocal.delete();
|
|
1602
1760
|
if (this.localToGlobal) this.localToGlobal.delete();
|
|
1603
|
-
const _globalCoordSystem = new this.oc.gp_Ax3_1();
|
|
1604
|
-
const _localCoordSystem = makeAx3(this.origin, this.zDir, this.xDir);
|
|
1605
|
-
const _forwardT = new this.oc.gp_Trsf_1();
|
|
1606
|
-
_forwardT.SetTransformation_1(_globalCoordSystem, _localCoordSystem);
|
|
1607
1761
|
this.globalToLocal = new Transformation();
|
|
1608
1762
|
this.globalToLocal.coordSystemChange("reference", {
|
|
1609
1763
|
origin: this.origin,
|
|
@@ -1619,9 +1773,6 @@ class Plane {
|
|
|
1619
1773
|
},
|
|
1620
1774
|
"reference"
|
|
1621
1775
|
);
|
|
1622
|
-
_globalCoordSystem.delete();
|
|
1623
|
-
_localCoordSystem.delete();
|
|
1624
|
-
_forwardT.delete();
|
|
1625
1776
|
}
|
|
1626
1777
|
setOrigin2d(x, y) {
|
|
1627
1778
|
this.origin = this.toWorldCoords([x, y]);
|
|
@@ -1715,19 +1866,18 @@ class BoundingBox extends WrappingObj {
|
|
|
1715
1866
|
}
|
|
1716
1867
|
}
|
|
1717
1868
|
const makePlaneFromFace = (face, originOnSurface = [0, 0]) => {
|
|
1718
|
-
const
|
|
1719
|
-
const
|
|
1720
|
-
const
|
|
1869
|
+
const [r, gc] = localGC();
|
|
1870
|
+
const originPoint = r(face.pointOnSurface(...originOnSurface));
|
|
1871
|
+
const normal = r(face.normalAt(originPoint));
|
|
1872
|
+
const v = r(new Vector([0, 0, 1]));
|
|
1721
1873
|
let xd = v.cross(normal);
|
|
1722
1874
|
if (xd.Length < 1e-8) {
|
|
1723
1875
|
xd.delete();
|
|
1724
1876
|
xd = new Vector([1, 0, 0]);
|
|
1725
1877
|
}
|
|
1726
|
-
|
|
1878
|
+
r(xd);
|
|
1727
1879
|
const plane = new Plane(originPoint, xd, normal);
|
|
1728
|
-
|
|
1729
|
-
normal.delete();
|
|
1730
|
-
xd.delete();
|
|
1880
|
+
gc();
|
|
1731
1881
|
return plane;
|
|
1732
1882
|
};
|
|
1733
1883
|
function makePlane(plane = "XY", origin = [0, 0, 0]) {
|
|
@@ -1738,31 +1888,35 @@ function makePlane(plane = "XY", origin = [0, 0, 0]) {
|
|
|
1738
1888
|
}
|
|
1739
1889
|
}
|
|
1740
1890
|
function rotate(shape, angle, position = [0, 0, 0], direction = [0, 0, 1]) {
|
|
1741
|
-
const
|
|
1891
|
+
const [r, gc] = localGC();
|
|
1892
|
+
const transformation = r(new Transformation());
|
|
1742
1893
|
transformation.rotate(angle, position, direction);
|
|
1743
1894
|
const newShape = transformation.transform(shape);
|
|
1744
|
-
|
|
1895
|
+
gc();
|
|
1745
1896
|
return newShape;
|
|
1746
1897
|
}
|
|
1747
1898
|
function translate(shape, vector) {
|
|
1748
|
-
const
|
|
1899
|
+
const [r, gc] = localGC();
|
|
1900
|
+
const transformation = r(new Transformation());
|
|
1749
1901
|
transformation.translate(vector);
|
|
1750
1902
|
const newShape = transformation.transform(shape);
|
|
1751
|
-
|
|
1903
|
+
gc();
|
|
1752
1904
|
return newShape;
|
|
1753
1905
|
}
|
|
1754
1906
|
function mirror(shape, inputPlane, origin) {
|
|
1755
|
-
const
|
|
1907
|
+
const [r, gc] = localGC();
|
|
1908
|
+
const transformation = r(new Transformation());
|
|
1756
1909
|
transformation.mirror(inputPlane, origin);
|
|
1757
1910
|
const newShape = transformation.transform(shape);
|
|
1758
|
-
|
|
1911
|
+
gc();
|
|
1759
1912
|
return newShape;
|
|
1760
1913
|
}
|
|
1761
1914
|
function scale(shape, center, scaleFactor) {
|
|
1762
|
-
const
|
|
1915
|
+
const [r, gc] = localGC();
|
|
1916
|
+
const transformation = r(new Transformation());
|
|
1763
1917
|
transformation.scale(center, scaleFactor);
|
|
1764
1918
|
const newShape = transformation.transform(shape);
|
|
1765
|
-
|
|
1919
|
+
gc();
|
|
1766
1920
|
return newShape;
|
|
1767
1921
|
}
|
|
1768
1922
|
let CURVE_TYPES_MAP = null;
|
|
@@ -1789,6 +1943,149 @@ const findCurveType = (type) => {
|
|
|
1789
1943
|
if (!shapeType2) return err(typeCastError("UNKNOWN_CURVE_TYPE", "Unknown curve type"));
|
|
1790
1944
|
return ok(shapeType2);
|
|
1791
1945
|
};
|
|
1946
|
+
function buildMeshCacheKey(_shapeHash, tolerance, angularTolerance, skipNormals) {
|
|
1947
|
+
return `${tolerance}:${angularTolerance}:${skipNormals}`;
|
|
1948
|
+
}
|
|
1949
|
+
function buildEdgeMeshCacheKey(_shapeHash, tolerance, angularTolerance) {
|
|
1950
|
+
return `edge:${tolerance}:${angularTolerance}`;
|
|
1951
|
+
}
|
|
1952
|
+
let meshCache = /* @__PURE__ */ new WeakMap();
|
|
1953
|
+
let edgeMeshCache = /* @__PURE__ */ new WeakMap();
|
|
1954
|
+
function getMeshForShape(shape, key) {
|
|
1955
|
+
const shapeCache = meshCache.get(shape);
|
|
1956
|
+
if (!shapeCache) return void 0;
|
|
1957
|
+
return shapeCache.get(key);
|
|
1958
|
+
}
|
|
1959
|
+
function setMeshForShape(shape, key, value) {
|
|
1960
|
+
let shapeCache = meshCache.get(shape);
|
|
1961
|
+
if (!shapeCache) {
|
|
1962
|
+
shapeCache = /* @__PURE__ */ new Map();
|
|
1963
|
+
meshCache.set(shape, shapeCache);
|
|
1964
|
+
}
|
|
1965
|
+
shapeCache.set(key, value);
|
|
1966
|
+
}
|
|
1967
|
+
function getEdgeMeshForShape(shape, key) {
|
|
1968
|
+
const shapeCache = edgeMeshCache.get(shape);
|
|
1969
|
+
if (!shapeCache) return void 0;
|
|
1970
|
+
return shapeCache.get(key);
|
|
1971
|
+
}
|
|
1972
|
+
function setEdgeMeshForShape(shape, key, value) {
|
|
1973
|
+
let shapeCache = edgeMeshCache.get(shape);
|
|
1974
|
+
if (!shapeCache) {
|
|
1975
|
+
shapeCache = /* @__PURE__ */ new Map();
|
|
1976
|
+
edgeMeshCache.set(shape, shapeCache);
|
|
1977
|
+
}
|
|
1978
|
+
shapeCache.set(key, value);
|
|
1979
|
+
}
|
|
1980
|
+
function clearMeshCache() {
|
|
1981
|
+
meshCache = /* @__PURE__ */ new WeakMap();
|
|
1982
|
+
edgeMeshCache = /* @__PURE__ */ new WeakMap();
|
|
1983
|
+
}
|
|
1984
|
+
function setMeshCacheSize(_size) {
|
|
1985
|
+
}
|
|
1986
|
+
function meshShape(shape, {
|
|
1987
|
+
tolerance = 1e-3,
|
|
1988
|
+
angularTolerance = 0.1,
|
|
1989
|
+
skipNormals = false,
|
|
1990
|
+
cache = true
|
|
1991
|
+
} = {}) {
|
|
1992
|
+
const cacheKey = buildMeshCacheKey(0, tolerance, angularTolerance, skipNormals);
|
|
1993
|
+
if (cache) {
|
|
1994
|
+
const cached = getMeshForShape(shape.wrapped, cacheKey);
|
|
1995
|
+
if (cached) return cached;
|
|
1996
|
+
}
|
|
1997
|
+
const result = getKernel().mesh(shape.wrapped, {
|
|
1998
|
+
tolerance,
|
|
1999
|
+
angularTolerance,
|
|
2000
|
+
skipNormals
|
|
2001
|
+
});
|
|
2002
|
+
const mesh = {
|
|
2003
|
+
vertices: result.vertices,
|
|
2004
|
+
normals: result.normals,
|
|
2005
|
+
triangles: result.triangles,
|
|
2006
|
+
faceGroups: result.faceGroups.map((g) => ({
|
|
2007
|
+
start: g.start,
|
|
2008
|
+
count: g.count,
|
|
2009
|
+
faceId: g.faceHash
|
|
2010
|
+
}))
|
|
2011
|
+
};
|
|
2012
|
+
if (cache) {
|
|
2013
|
+
setMeshForShape(shape.wrapped, cacheKey, mesh);
|
|
2014
|
+
}
|
|
2015
|
+
return mesh;
|
|
2016
|
+
}
|
|
2017
|
+
function meshShapeEdges(shape, { tolerance = 1e-3, angularTolerance = 0.1, cache = true } = {}) {
|
|
2018
|
+
const cacheKey = buildEdgeMeshCacheKey(0, tolerance, angularTolerance);
|
|
2019
|
+
if (cache) {
|
|
2020
|
+
const cached = getEdgeMeshForShape(shape.wrapped, cacheKey);
|
|
2021
|
+
if (cached) return cached;
|
|
2022
|
+
}
|
|
2023
|
+
const kernelResult = getKernel().meshEdges(shape.wrapped, tolerance, angularTolerance);
|
|
2024
|
+
const result = {
|
|
2025
|
+
lines: Array.from(kernelResult.lines),
|
|
2026
|
+
edgeGroups: kernelResult.edgeGroups.map((g) => ({
|
|
2027
|
+
start: g.start,
|
|
2028
|
+
count: g.count,
|
|
2029
|
+
edgeId: g.edgeHash
|
|
2030
|
+
}))
|
|
2031
|
+
};
|
|
2032
|
+
if (cache) {
|
|
2033
|
+
setEdgeMeshForShape(shape.wrapped, cacheKey, result);
|
|
2034
|
+
}
|
|
2035
|
+
return result;
|
|
2036
|
+
}
|
|
2037
|
+
function exportSTEP$1(shape) {
|
|
2038
|
+
const oc = getKernel().oc;
|
|
2039
|
+
const filename = uniqueIOFilename("_blob", "step");
|
|
2040
|
+
const writer = new oc.STEPControl_Writer_1();
|
|
2041
|
+
const progress = new oc.Message_ProgressRange_1();
|
|
2042
|
+
try {
|
|
2043
|
+
oc.Interface_Static.SetIVal("write.step.schema", 5);
|
|
2044
|
+
writer.Model(true).delete();
|
|
2045
|
+
writer.Transfer(shape.wrapped, oc.STEPControl_StepModelType.STEPControl_AsIs, true, progress);
|
|
2046
|
+
const done = writer.Write(filename);
|
|
2047
|
+
if (done === oc.IFSelect_ReturnStatus.IFSelect_RetDone) {
|
|
2048
|
+
try {
|
|
2049
|
+
const file = oc.FS.readFile("/" + filename);
|
|
2050
|
+
oc.FS.unlink("/" + filename);
|
|
2051
|
+
return ok(new Blob([file], { type: "application/STEP" }));
|
|
2052
|
+
} catch (e) {
|
|
2053
|
+
return err(ioError("STEP_FILE_READ_ERROR", "Failed to read exported STEP file", e));
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
2056
|
+
return err(ioError("STEP_EXPORT_FAILED", "Failed to write STEP file"));
|
|
2057
|
+
} finally {
|
|
2058
|
+
writer.delete();
|
|
2059
|
+
progress.delete();
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
function exportSTL(shape, {
|
|
2063
|
+
tolerance = 1e-3,
|
|
2064
|
+
angularTolerance = 0.1,
|
|
2065
|
+
binary = false
|
|
2066
|
+
} = {}) {
|
|
2067
|
+
const oc = getKernel().oc;
|
|
2068
|
+
const mesher = new oc.BRepMesh_IncrementalMesh_2(
|
|
2069
|
+
shape.wrapped,
|
|
2070
|
+
tolerance,
|
|
2071
|
+
false,
|
|
2072
|
+
angularTolerance,
|
|
2073
|
+
false
|
|
2074
|
+
);
|
|
2075
|
+
mesher.delete();
|
|
2076
|
+
const filename = uniqueIOFilename("_blob", "stl");
|
|
2077
|
+
const done = oc.StlAPI.Write(shape.wrapped, filename, !binary);
|
|
2078
|
+
if (done) {
|
|
2079
|
+
try {
|
|
2080
|
+
const file = oc.FS.readFile("/" + filename);
|
|
2081
|
+
oc.FS.unlink("/" + filename);
|
|
2082
|
+
return ok(new Blob([file], { type: "application/sla" }));
|
|
2083
|
+
} catch (e) {
|
|
2084
|
+
return err(ioError("STL_FILE_READ_ERROR", "Failed to read exported STL file", e));
|
|
2085
|
+
}
|
|
2086
|
+
}
|
|
2087
|
+
return err(ioError("STL_EXPORT_FAILED", "Failed to write STL file"));
|
|
2088
|
+
}
|
|
1792
2089
|
let _shapesModule = null;
|
|
1793
2090
|
function getShapesModuleSync() {
|
|
1794
2091
|
if (!_shapesModule) {
|
|
@@ -1817,23 +2114,23 @@ const asTopo = (entity) => {
|
|
|
1817
2114
|
}[entity];
|
|
1818
2115
|
};
|
|
1819
2116
|
const iterTopo = function* iterTopo2(shape, topo) {
|
|
1820
|
-
const
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
2117
|
+
const topoToShapeType = {
|
|
2118
|
+
vertex: "vertex",
|
|
2119
|
+
edge: "edge",
|
|
2120
|
+
wire: "wire",
|
|
2121
|
+
face: "face",
|
|
2122
|
+
shell: "shell",
|
|
2123
|
+
solid: "solid",
|
|
2124
|
+
solidCompound: "compsolid",
|
|
2125
|
+
compound: "compound",
|
|
2126
|
+
shape: "compound"
|
|
2127
|
+
// fallback; 'shape' isn't used in iterShapes
|
|
2128
|
+
};
|
|
2129
|
+
const shapeType2 = topoToShapeType[topo];
|
|
2130
|
+
if (shapeType2) {
|
|
2131
|
+
const shapes = getKernel().iterShapes(shape, shapeType2);
|
|
2132
|
+
for (const s of shapes) yield s;
|
|
1835
2133
|
}
|
|
1836
|
-
explorer.delete();
|
|
1837
2134
|
};
|
|
1838
2135
|
const shapeType = (shape) => {
|
|
1839
2136
|
if (shape.IsNull()) return err(typeCastError("NULL_SHAPE", "This shape has no type, it is null"));
|
|
@@ -2067,7 +2364,14 @@ class Shape extends WrappingObj {
|
|
|
2067
2364
|
return bbox;
|
|
2068
2365
|
}
|
|
2069
2366
|
_mesh({ tolerance = 1e-3, angularTolerance = 0.1 } = {}) {
|
|
2070
|
-
new this.oc.BRepMesh_IncrementalMesh_2(
|
|
2367
|
+
const mesher = new this.oc.BRepMesh_IncrementalMesh_2(
|
|
2368
|
+
this.wrapped,
|
|
2369
|
+
tolerance,
|
|
2370
|
+
false,
|
|
2371
|
+
angularTolerance,
|
|
2372
|
+
false
|
|
2373
|
+
);
|
|
2374
|
+
mesher.delete();
|
|
2071
2375
|
}
|
|
2072
2376
|
/**
|
|
2073
2377
|
* Exports the current shape as a set of triangles for rendering.
|
|
@@ -2100,93 +2404,12 @@ class Shape extends WrappingObj {
|
|
|
2100
2404
|
*
|
|
2101
2405
|
* @category Shape Export
|
|
2102
2406
|
*/
|
|
2103
|
-
meshEdges({
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
const start = lines.length;
|
|
2110
|
-
let prevX = 0;
|
|
2111
|
-
let prevY = 0;
|
|
2112
|
-
let prevZ = 0;
|
|
2113
|
-
let hasPrev = false;
|
|
2114
|
-
return [
|
|
2115
|
-
(p) => {
|
|
2116
|
-
const x = p.X();
|
|
2117
|
-
const y = p.Y();
|
|
2118
|
-
const z = p.Z();
|
|
2119
|
-
if (hasPrev) {
|
|
2120
|
-
lines.push(prevX, prevY, prevZ, x, y, z);
|
|
2121
|
-
}
|
|
2122
|
-
prevX = x;
|
|
2123
|
-
prevY = y;
|
|
2124
|
-
prevZ = z;
|
|
2125
|
-
hasPrev = true;
|
|
2126
|
-
},
|
|
2127
|
-
(edgeHash) => {
|
|
2128
|
-
edgeGroups.push({
|
|
2129
|
-
start: start / 3,
|
|
2130
|
-
count: (lines.length - start) / 3,
|
|
2131
|
-
edgeId: edgeHash
|
|
2132
|
-
});
|
|
2133
|
-
recordedEdges.add(edgeHash);
|
|
2134
|
-
}
|
|
2135
|
-
];
|
|
2136
|
-
};
|
|
2137
|
-
const aLocation = r(new this.oc.TopLoc_Location_1());
|
|
2138
|
-
const faces = this.faces;
|
|
2139
|
-
for (const face of faces) {
|
|
2140
|
-
const triangulation = r(this.oc.BRep_Tool.Triangulation(face.wrapped, aLocation, 0));
|
|
2141
|
-
if (triangulation.IsNull()) {
|
|
2142
|
-
continue;
|
|
2143
|
-
}
|
|
2144
|
-
const tri = triangulation.get();
|
|
2145
|
-
const faceEdges = face.edges;
|
|
2146
|
-
for (const edge of faceEdges) {
|
|
2147
|
-
r(edge);
|
|
2148
|
-
if (recordedEdges.has(edge.hashCode)) continue;
|
|
2149
|
-
const edgeLoc = r(new this.oc.TopLoc_Location_1());
|
|
2150
|
-
const polygon = r(
|
|
2151
|
-
this.oc.BRep_Tool.PolygonOnTriangulation_1(edge.wrapped, triangulation, edgeLoc)
|
|
2152
|
-
);
|
|
2153
|
-
const edgeNodes = polygon?.get()?.Nodes();
|
|
2154
|
-
if (!edgeNodes) {
|
|
2155
|
-
continue;
|
|
2156
|
-
}
|
|
2157
|
-
r(edgeNodes);
|
|
2158
|
-
const [recordPoint, done] = addEdge();
|
|
2159
|
-
for (let i = edgeNodes.Lower(); i <= edgeNodes.Upper(); i++) {
|
|
2160
|
-
const p = r(r(tri.Node(edgeNodes.Value(i))).Transformed(edgeLoc.Transformation()));
|
|
2161
|
-
recordPoint(p);
|
|
2162
|
-
}
|
|
2163
|
-
done(edge.hashCode);
|
|
2164
|
-
}
|
|
2165
|
-
}
|
|
2166
|
-
const allEdges = this.edges;
|
|
2167
|
-
for (const edge of allEdges) {
|
|
2168
|
-
r(edge);
|
|
2169
|
-
const edgeHash = edge.hashCode;
|
|
2170
|
-
if (recordedEdges.has(edgeHash)) continue;
|
|
2171
|
-
const adaptorCurve = r(new this.oc.BRepAdaptor_Curve_2(edge.wrapped));
|
|
2172
|
-
const tangDef = r(
|
|
2173
|
-
new this.oc.GCPnts_TangentialDeflection_2(
|
|
2174
|
-
adaptorCurve,
|
|
2175
|
-
tolerance,
|
|
2176
|
-
angularTolerance,
|
|
2177
|
-
2,
|
|
2178
|
-
1e-9,
|
|
2179
|
-
1e-7
|
|
2180
|
-
)
|
|
2181
|
-
);
|
|
2182
|
-
const [recordPoint, done] = addEdge();
|
|
2183
|
-
for (let j = 0; j < tangDef.NbPoints(); j++) {
|
|
2184
|
-
const p = r(tangDef.Value(j + 1).Transformed(aLocation.Transformation()));
|
|
2185
|
-
recordPoint(p);
|
|
2186
|
-
}
|
|
2187
|
-
done(edgeHash);
|
|
2188
|
-
}
|
|
2189
|
-
return { lines, edgeGroups };
|
|
2407
|
+
meshEdges({
|
|
2408
|
+
tolerance = 1e-3,
|
|
2409
|
+
angularTolerance = 0.1,
|
|
2410
|
+
cache = true
|
|
2411
|
+
} = {}) {
|
|
2412
|
+
return meshShapeEdges(this, { tolerance, angularTolerance, cache });
|
|
2190
2413
|
}
|
|
2191
2414
|
/**
|
|
2192
2415
|
* Exports the current shape as a STEP file Blob.
|
|
@@ -2194,7 +2417,7 @@ class Shape extends WrappingObj {
|
|
|
2194
2417
|
* @category Shape Export
|
|
2195
2418
|
*/
|
|
2196
2419
|
blobSTEP() {
|
|
2197
|
-
const filename = "
|
|
2420
|
+
const filename = uniqueIOFilename("_blob", "step");
|
|
2198
2421
|
const writer = new this.oc.STEPControl_Writer_1();
|
|
2199
2422
|
this.oc.Interface_Static.SetIVal("write.step.schema", 5);
|
|
2200
2423
|
writer.Model(true).delete();
|
|
@@ -2228,7 +2451,7 @@ class Shape extends WrappingObj {
|
|
|
2228
2451
|
*/
|
|
2229
2452
|
blobSTL({ tolerance = 1e-3, angularTolerance = 0.1, binary = false } = {}) {
|
|
2230
2453
|
this._mesh({ tolerance, angularTolerance });
|
|
2231
|
-
const filename = "
|
|
2454
|
+
const filename = uniqueIOFilename("_blob", "stl");
|
|
2232
2455
|
const done = this.oc.StlAPI.Write(this.wrapped, filename, !binary);
|
|
2233
2456
|
if (done) {
|
|
2234
2457
|
try {
|
|
@@ -2312,28 +2535,52 @@ class _1DShape extends Shape {
|
|
|
2312
2535
|
return new Curve(this._geomAdaptor());
|
|
2313
2536
|
}
|
|
2314
2537
|
get startPoint() {
|
|
2315
|
-
|
|
2538
|
+
const c = this.curve;
|
|
2539
|
+
const result = c.startPoint;
|
|
2540
|
+
c.delete();
|
|
2541
|
+
return result;
|
|
2316
2542
|
}
|
|
2317
2543
|
get endPoint() {
|
|
2318
|
-
|
|
2544
|
+
const c = this.curve;
|
|
2545
|
+
const result = c.endPoint;
|
|
2546
|
+
c.delete();
|
|
2547
|
+
return result;
|
|
2319
2548
|
}
|
|
2320
2549
|
tangentAt(position = 0) {
|
|
2321
|
-
|
|
2550
|
+
const c = this.curve;
|
|
2551
|
+
const result = c.tangentAt(position);
|
|
2552
|
+
c.delete();
|
|
2553
|
+
return result;
|
|
2322
2554
|
}
|
|
2323
2555
|
pointAt(position = 0) {
|
|
2324
|
-
|
|
2556
|
+
const c = this.curve;
|
|
2557
|
+
const result = c.pointAt(position);
|
|
2558
|
+
c.delete();
|
|
2559
|
+
return result;
|
|
2325
2560
|
}
|
|
2326
2561
|
get isClosed() {
|
|
2327
|
-
|
|
2562
|
+
const c = this.curve;
|
|
2563
|
+
const result = c.isClosed;
|
|
2564
|
+
c.delete();
|
|
2565
|
+
return result;
|
|
2328
2566
|
}
|
|
2329
2567
|
get isPeriodic() {
|
|
2330
|
-
|
|
2568
|
+
const c = this.curve;
|
|
2569
|
+
const result = c.isPeriodic;
|
|
2570
|
+
c.delete();
|
|
2571
|
+
return result;
|
|
2331
2572
|
}
|
|
2332
2573
|
get period() {
|
|
2333
|
-
|
|
2574
|
+
const c = this.curve;
|
|
2575
|
+
const result = c.period;
|
|
2576
|
+
c.delete();
|
|
2577
|
+
return result;
|
|
2334
2578
|
}
|
|
2335
2579
|
get geomType() {
|
|
2336
|
-
|
|
2580
|
+
const c = this.curve;
|
|
2581
|
+
const result = c.curveType;
|
|
2582
|
+
c.delete();
|
|
2583
|
+
return result;
|
|
2337
2584
|
}
|
|
2338
2585
|
get length() {
|
|
2339
2586
|
const properties = new this.oc.GProp_GProps_1();
|
|
@@ -2425,11 +2672,13 @@ class Face extends Shape {
|
|
|
2425
2672
|
}
|
|
2426
2673
|
get geomType() {
|
|
2427
2674
|
const surface = this.surface;
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2675
|
+
try {
|
|
2676
|
+
return unwrap(surface.surfaceType);
|
|
2677
|
+
} finally {
|
|
2678
|
+
surface.delete();
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
get UVBounds() {
|
|
2433
2682
|
const uMin = { current: 0 };
|
|
2434
2683
|
const uMax = { current: 0 };
|
|
2435
2684
|
const vMin = { current: 0 };
|
|
@@ -2891,7 +3140,13 @@ function zip(arrays) {
|
|
|
2891
3140
|
}
|
|
2892
3141
|
const makeLine = (v1, v2) => {
|
|
2893
3142
|
const oc = getKernel().oc;
|
|
2894
|
-
|
|
3143
|
+
const [r, gc] = localGC();
|
|
3144
|
+
const p1 = r(asPnt(v1));
|
|
3145
|
+
const p2 = r(asPnt(v2));
|
|
3146
|
+
const maker = r(new oc.BRepBuilderAPI_MakeEdge_3(p1, p2));
|
|
3147
|
+
const edge = new Edge(maker.Edge());
|
|
3148
|
+
gc();
|
|
3149
|
+
return edge;
|
|
2895
3150
|
};
|
|
2896
3151
|
const makeCircle = (radius, center = [0, 0, 0], normal = [0, 0, 1]) => {
|
|
2897
3152
|
const oc = getKernel().oc;
|
|
@@ -2930,8 +3185,8 @@ const makeHelix = (pitch, height, radius, center = [0, 0, 0], dir = [0, 0, 1], l
|
|
|
2930
3185
|
new oc.Geom2d_Line_3(r(new oc.gp_Pnt2d_3(0, 0)), r(new oc.gp_Dir2d_4(myDir, pitch)))
|
|
2931
3186
|
);
|
|
2932
3187
|
const nTurns = height / pitch;
|
|
2933
|
-
const uStart = geomLine.Value(0);
|
|
2934
|
-
const uStop = geomLine.Value(nTurns * Math.sqrt((2 * Math.PI) ** 2 + pitch ** 2));
|
|
3188
|
+
const uStart = r(geomLine.Value(0));
|
|
3189
|
+
const uStop = r(geomLine.Value(nTurns * Math.sqrt((2 * Math.PI) ** 2 + pitch ** 2)));
|
|
2935
3190
|
const geomSeg = r(new oc.GCE2d_MakeSegment_1(uStart, uStop));
|
|
2936
3191
|
const geomSurf = new oc.Geom_CylindricalSurface_1(r(makeAx3(center, dir)), radius);
|
|
2937
3192
|
const e = r(
|
|
@@ -2947,9 +3202,17 @@ const makeHelix = (pitch, height, radius, center = [0, 0, 0], dir = [0, 0, 1], l
|
|
|
2947
3202
|
};
|
|
2948
3203
|
const makeThreePointArc = (v1, v2, v3) => {
|
|
2949
3204
|
const oc = getKernel().oc;
|
|
2950
|
-
const
|
|
2951
|
-
const
|
|
2952
|
-
|
|
3205
|
+
const [r, gc] = localGC();
|
|
3206
|
+
const p1 = r(asPnt(v1));
|
|
3207
|
+
const p2 = r(asPnt(v2));
|
|
3208
|
+
const p3 = r(asPnt(v3));
|
|
3209
|
+
const arcMaker = r(new oc.GC_MakeArcOfCircle_4(p1, p2, p3));
|
|
3210
|
+
const circleGeom = r(arcMaker.Value());
|
|
3211
|
+
const curve = r(new oc.Handle_Geom_Curve_2(circleGeom.get()));
|
|
3212
|
+
const edgeMaker = r(new oc.BRepBuilderAPI_MakeEdge_24(curve));
|
|
3213
|
+
const edge = new Edge(edgeMaker.Edge());
|
|
3214
|
+
gc();
|
|
3215
|
+
return edge;
|
|
2953
3216
|
};
|
|
2954
3217
|
const makeEllipseArc = (majorRadius, minorRadius, startAngle, endAngle, center = [0, 0, 0], normal = [0, 0, 1], xDir) => {
|
|
2955
3218
|
const oc = getKernel().oc;
|
|
@@ -3013,13 +3276,17 @@ const makeBezierCurve = (points) => {
|
|
|
3013
3276
|
bug("makeBezierCurve", `Need at least 2 points for a Bezier curve, got ${points.length}`);
|
|
3014
3277
|
}
|
|
3015
3278
|
const oc = getKernel().oc;
|
|
3016
|
-
const
|
|
3279
|
+
const [r, gc] = localGC();
|
|
3280
|
+
const arrayOfPoints = r(new oc.TColgp_Array1OfPnt_2(1, points.length));
|
|
3017
3281
|
points.forEach((p, i) => {
|
|
3018
|
-
arrayOfPoints.SetValue(i + 1, asPnt(p));
|
|
3282
|
+
arrayOfPoints.SetValue(i + 1, r(asPnt(p)));
|
|
3019
3283
|
});
|
|
3020
3284
|
const bezCurve = new oc.Geom_BezierCurve_1(arrayOfPoints);
|
|
3021
|
-
const curve = new oc.Handle_Geom_Curve_2(bezCurve);
|
|
3022
|
-
|
|
3285
|
+
const curve = r(new oc.Handle_Geom_Curve_2(bezCurve));
|
|
3286
|
+
const edgeMaker = r(new oc.BRepBuilderAPI_MakeEdge_24(curve));
|
|
3287
|
+
const edge = new Edge(edgeMaker.Edge());
|
|
3288
|
+
gc();
|
|
3289
|
+
return edge;
|
|
3023
3290
|
};
|
|
3024
3291
|
const makeTangentArc = (startPoint, startTgt, endPoint) => {
|
|
3025
3292
|
const oc = getKernel().oc;
|
|
@@ -3038,7 +3305,8 @@ const makeTangentArc = (startPoint, startTgt, endPoint) => {
|
|
|
3038
3305
|
};
|
|
3039
3306
|
const assembleWire$1 = (listOfEdges) => {
|
|
3040
3307
|
const oc = getKernel().oc;
|
|
3041
|
-
const
|
|
3308
|
+
const [r, gc] = localGC();
|
|
3309
|
+
const wireBuilder = r(new oc.BRepBuilderAPI_MakeWire_1());
|
|
3042
3310
|
listOfEdges.forEach((e) => {
|
|
3043
3311
|
if (e instanceof Edge) {
|
|
3044
3312
|
wireBuilder.Add_1(e.wrapped);
|
|
@@ -3047,7 +3315,7 @@ const assembleWire$1 = (listOfEdges) => {
|
|
|
3047
3315
|
wireBuilder.Add_2(e.wrapped);
|
|
3048
3316
|
}
|
|
3049
3317
|
});
|
|
3050
|
-
const progress = new oc.Message_ProgressRange_1();
|
|
3318
|
+
const progress = r(new oc.Message_ProgressRange_1());
|
|
3051
3319
|
wireBuilder.Build(progress);
|
|
3052
3320
|
const res = wireBuilder.Error();
|
|
3053
3321
|
if (res !== oc.BRepBuilderAPI_WireError.BRepBuilderAPI_WireDone) {
|
|
@@ -3056,8 +3324,7 @@ const assembleWire$1 = (listOfEdges) => {
|
|
|
3056
3324
|
[oc.BRepBuilderAPI_WireError.BRepBuilderAPI_NonManifoldWire, "non manifold wire"],
|
|
3057
3325
|
[oc.BRepBuilderAPI_WireError.BRepBuilderAPI_DisconnectedWire, "disconnected wire"]
|
|
3058
3326
|
]);
|
|
3059
|
-
|
|
3060
|
-
progress.delete();
|
|
3327
|
+
gc();
|
|
3061
3328
|
return err(
|
|
3062
3329
|
occtError(
|
|
3063
3330
|
"WIRE_BUILD_FAILED",
|
|
@@ -3066,8 +3333,7 @@ const assembleWire$1 = (listOfEdges) => {
|
|
|
3066
3333
|
);
|
|
3067
3334
|
}
|
|
3068
3335
|
const wire = new Wire(wireBuilder.Wire());
|
|
3069
|
-
|
|
3070
|
-
progress.delete();
|
|
3336
|
+
gc();
|
|
3071
3337
|
return ok(wire);
|
|
3072
3338
|
};
|
|
3073
3339
|
const makeFace = (wire, holes) => {
|
|
@@ -3120,33 +3386,37 @@ const makeNonPlanarFace = (wire) => {
|
|
|
3120
3386
|
};
|
|
3121
3387
|
const makeCylinder = (radius, height, location = [0, 0, 0], direction = [0, 0, 1]) => {
|
|
3122
3388
|
const oc = getKernel().oc;
|
|
3123
|
-
const
|
|
3124
|
-
const
|
|
3389
|
+
const [r, gc] = localGC();
|
|
3390
|
+
const axis = r(makeAx2(location, direction));
|
|
3391
|
+
const cylinder = r(new oc.BRepPrimAPI_MakeCylinder_3(axis, radius, height));
|
|
3125
3392
|
const solid = new Solid(cylinder.Shape());
|
|
3126
|
-
|
|
3127
|
-
cylinder.delete();
|
|
3393
|
+
gc();
|
|
3128
3394
|
return solid;
|
|
3129
3395
|
};
|
|
3130
3396
|
const makeSphere = (radius) => {
|
|
3131
3397
|
const oc = getKernel().oc;
|
|
3132
|
-
const
|
|
3398
|
+
const [r, gc] = localGC();
|
|
3399
|
+
const sphereMaker = r(new oc.BRepPrimAPI_MakeSphere_1(radius));
|
|
3133
3400
|
const sphere = new Solid(sphereMaker.Shape());
|
|
3134
|
-
|
|
3401
|
+
gc();
|
|
3135
3402
|
return sphere;
|
|
3136
3403
|
};
|
|
3137
|
-
class
|
|
3404
|
+
class EllipsoidTransform extends WrappingObj {
|
|
3138
3405
|
constructor(x, y, z) {
|
|
3139
3406
|
const oc = getKernel().oc;
|
|
3140
3407
|
const r = gcWithScope();
|
|
3141
3408
|
const xyRatio = Math.sqrt(x * y / z);
|
|
3142
3409
|
const xzRatio = x / xyRatio;
|
|
3143
3410
|
const yzRatio = y / xyRatio;
|
|
3411
|
+
const ax1 = r(makeAx1([0, 0, 0], [0, 1, 0]));
|
|
3412
|
+
const ax2 = r(makeAx1([0, 0, 0], [0, 0, 1]));
|
|
3413
|
+
const ax3 = r(makeAx1([0, 0, 0], [1, 0, 0]));
|
|
3144
3414
|
const transform = new oc.gp_GTrsf_1();
|
|
3145
|
-
transform.SetAffinity_1(
|
|
3415
|
+
transform.SetAffinity_1(ax1, xzRatio);
|
|
3146
3416
|
const xy = r(new oc.gp_GTrsf_1());
|
|
3147
|
-
xy.SetAffinity_1(
|
|
3417
|
+
xy.SetAffinity_1(ax2, xyRatio);
|
|
3148
3418
|
const yz = r(new oc.gp_GTrsf_1());
|
|
3149
|
-
yz.SetAffinity_1(
|
|
3419
|
+
yz.SetAffinity_1(ax3, yzRatio);
|
|
3150
3420
|
transform.Multiply(xy);
|
|
3151
3421
|
transform.Multiply(yz);
|
|
3152
3422
|
super(transform);
|
|
@@ -3178,60 +3448,71 @@ const makeEllipsoid = (aLength, bLength, cLength) => {
|
|
|
3178
3448
|
sphere.SetRadius(1);
|
|
3179
3449
|
const sphericalSurface = r(new oc.Geom_SphericalSurface_2(sphere));
|
|
3180
3450
|
const baseSurface = oc.GeomConvert.SurfaceToBSplineSurface(sphericalSurface.UReversed()).get();
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3451
|
+
try {
|
|
3452
|
+
const poles = convertToJSArray(baseSurface.Poles_2());
|
|
3453
|
+
const transform = new EllipsoidTransform(aLength, bLength, cLength);
|
|
3454
|
+
poles.forEach((columns, rowIdx) => {
|
|
3455
|
+
columns.forEach((value, colIdx) => {
|
|
3456
|
+
const newPoint = transform.applyToPoint(value);
|
|
3457
|
+
baseSurface.SetPole_1(rowIdx + 1, colIdx + 1, newPoint);
|
|
3458
|
+
newPoint.delete();
|
|
3459
|
+
});
|
|
3187
3460
|
});
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3461
|
+
const shell = unwrap(
|
|
3462
|
+
cast(r(new oc.BRepBuilderAPI_MakeShell_2(baseSurface.UReversed(), false)).Shell())
|
|
3463
|
+
);
|
|
3464
|
+
return unwrap(makeSolid([shell]));
|
|
3465
|
+
} finally {
|
|
3466
|
+
baseSurface.delete();
|
|
3467
|
+
}
|
|
3193
3468
|
};
|
|
3194
3469
|
const makeBox = (corner1, corner2) => {
|
|
3195
3470
|
const oc = getKernel().oc;
|
|
3196
|
-
const
|
|
3471
|
+
const [r, gc] = localGC();
|
|
3472
|
+
const p1 = r(asPnt(corner1));
|
|
3473
|
+
const p2 = r(asPnt(corner2));
|
|
3474
|
+
const boxMaker = r(new oc.BRepPrimAPI_MakeBox_4(p1, p2));
|
|
3197
3475
|
const box = new Solid(boxMaker.Solid());
|
|
3198
|
-
|
|
3476
|
+
gc();
|
|
3199
3477
|
return box;
|
|
3200
3478
|
};
|
|
3201
3479
|
const makeVertex = (point) => {
|
|
3202
3480
|
const oc = getKernel().oc;
|
|
3203
|
-
const
|
|
3204
|
-
const
|
|
3481
|
+
const [r, gc] = localGC();
|
|
3482
|
+
const pnt2 = r(asPnt(point));
|
|
3483
|
+
const vertexMaker = r(new oc.BRepBuilderAPI_MakeVertex(pnt2));
|
|
3205
3484
|
const vertex = vertexMaker.Vertex();
|
|
3206
|
-
|
|
3485
|
+
gc();
|
|
3207
3486
|
return new Vertex(vertex);
|
|
3208
3487
|
};
|
|
3209
3488
|
const makeOffset = (face, offset2, tolerance = 1e-6) => {
|
|
3210
3489
|
const oc = getKernel().oc;
|
|
3211
3490
|
const progress = new oc.Message_ProgressRange_1();
|
|
3212
3491
|
const offsetBuilder = new oc.BRepOffsetAPI_MakeOffsetShape();
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3492
|
+
try {
|
|
3493
|
+
offsetBuilder.PerformByJoin(
|
|
3494
|
+
face.wrapped,
|
|
3495
|
+
offset2,
|
|
3496
|
+
tolerance,
|
|
3497
|
+
oc.BRepOffset_Mode.BRepOffset_Skin,
|
|
3498
|
+
false,
|
|
3499
|
+
false,
|
|
3500
|
+
oc.GeomAbs_JoinType.GeomAbs_Arc,
|
|
3501
|
+
false,
|
|
3502
|
+
progress
|
|
3503
|
+
);
|
|
3504
|
+
return andThen(
|
|
3505
|
+
downcast(offsetBuilder.Shape()),
|
|
3506
|
+
(downcasted) => andThen(cast(downcasted), (newShape) => {
|
|
3507
|
+
if (!isShape3D$1(newShape))
|
|
3508
|
+
return err(typeCastError("OFFSET_NOT_3D", "Could not offset to a 3d shape"));
|
|
3509
|
+
return ok(newShape);
|
|
3510
|
+
})
|
|
3511
|
+
);
|
|
3512
|
+
} finally {
|
|
3513
|
+
offsetBuilder.delete();
|
|
3514
|
+
progress.delete();
|
|
3515
|
+
}
|
|
3235
3516
|
};
|
|
3236
3517
|
const compoundShapes = (shapeArray) => {
|
|
3237
3518
|
const oc = getKernel().oc;
|
|
@@ -3615,13 +3896,15 @@ function offsetWire2D(wire, offset2, kind = "arc") {
|
|
|
3615
3896
|
const wrapped = castShape(resultShape);
|
|
3616
3897
|
offsetter.delete();
|
|
3617
3898
|
if (!isWire(wrapped)) {
|
|
3899
|
+
wrapped[Symbol.dispose]();
|
|
3618
3900
|
return err(typeCastError("OFFSET_NOT_WIRE", "Offset did not produce a Wire"));
|
|
3619
3901
|
}
|
|
3620
3902
|
return ok(wrapped);
|
|
3621
3903
|
}
|
|
3622
3904
|
function getSurfaceType(face) {
|
|
3623
3905
|
const oc = getKernel().oc;
|
|
3624
|
-
const
|
|
3906
|
+
const r = gcWithScope();
|
|
3907
|
+
const adaptor = r(new oc.BRepAdaptor_Surface_2(face.wrapped, false));
|
|
3625
3908
|
const ga = oc.GeomAbs_SurfaceType;
|
|
3626
3909
|
const CAST_MAP = /* @__PURE__ */ new Map([
|
|
3627
3910
|
[ga.GeomAbs_Plane, "PLANE"],
|
|
@@ -3637,7 +3920,6 @@ function getSurfaceType(face) {
|
|
|
3637
3920
|
[ga.GeomAbs_OtherSurface, "OTHER_SURFACE"]
|
|
3638
3921
|
]);
|
|
3639
3922
|
const surfType = CAST_MAP.get(adaptor.GetType());
|
|
3640
|
-
adaptor.delete();
|
|
3641
3923
|
if (!surfType) {
|
|
3642
3924
|
return err(
|
|
3643
3925
|
typeCastError("UNKNOWN_SURFACE_TYPE", "Unrecognized surface type from OCCT adapter")
|
|
@@ -3672,16 +3954,14 @@ function uvBounds(face) {
|
|
|
3672
3954
|
}
|
|
3673
3955
|
function pointOnSurface(face, u, v) {
|
|
3674
3956
|
const oc = getKernel().oc;
|
|
3957
|
+
const r = gcWithScope();
|
|
3675
3958
|
const bounds = uvBounds(face);
|
|
3676
|
-
const adaptor = new oc.BRepAdaptor_Surface_2(face.wrapped, false);
|
|
3677
|
-
const p = new oc.gp_Pnt_1();
|
|
3959
|
+
const adaptor = r(new oc.BRepAdaptor_Surface_2(face.wrapped, false));
|
|
3960
|
+
const p = r(new oc.gp_Pnt_1());
|
|
3678
3961
|
const absU = u * (bounds.uMax - bounds.uMin) + bounds.uMin;
|
|
3679
3962
|
const absV = v * (bounds.vMax - bounds.vMin) + bounds.vMin;
|
|
3680
3963
|
adaptor.D0(absU, absV, p);
|
|
3681
|
-
|
|
3682
|
-
p.delete();
|
|
3683
|
-
adaptor.delete();
|
|
3684
|
-
return result;
|
|
3964
|
+
return [p.X(), p.Y(), p.Z()];
|
|
3685
3965
|
}
|
|
3686
3966
|
function uvCoordinates(face, point) {
|
|
3687
3967
|
const oc = getKernel().oc;
|
|
@@ -3720,13 +4000,11 @@ function normalAt(face, locationPoint) {
|
|
|
3720
4000
|
}
|
|
3721
4001
|
function faceCenter(face) {
|
|
3722
4002
|
const oc = getKernel().oc;
|
|
3723
|
-
const
|
|
4003
|
+
const r = gcWithScope();
|
|
4004
|
+
const props = r(new oc.GProp_GProps_1());
|
|
3724
4005
|
oc.BRepGProp.SurfaceProperties_2(face.wrapped, props, 1e-7, true);
|
|
3725
|
-
const center = props.CentreOfMass();
|
|
3726
|
-
|
|
3727
|
-
center.delete();
|
|
3728
|
-
props.delete();
|
|
3729
|
-
return result;
|
|
4006
|
+
const center = r(props.CentreOfMass());
|
|
4007
|
+
return [center.X(), center.Y(), center.Z()];
|
|
3730
4008
|
}
|
|
3731
4009
|
function outerWire(face) {
|
|
3732
4010
|
const oc = getKernel().oc;
|
|
@@ -3737,8 +4015,7 @@ function innerWires(face) {
|
|
|
3737
4015
|
const allWires = Array.from(iterTopo(face.wrapped, "wire")).map(
|
|
3738
4016
|
(w) => castShape(unwrap(downcast(w)))
|
|
3739
4017
|
);
|
|
3740
|
-
const
|
|
3741
|
-
const result = allWires.filter((w) => w.wrapped.HashCode(2147483647) !== outerHash);
|
|
4018
|
+
const result = allWires.filter((w) => !w.wrapped.IsSame(outer.wrapped));
|
|
3742
4019
|
return result;
|
|
3743
4020
|
}
|
|
3744
4021
|
function triangulateFace(face, index0 = 0, skipNormals = false) {
|
|
@@ -3794,195 +4071,6 @@ function triangulateFace(face, index0 = 0, skipNormals = false) {
|
|
|
3794
4071
|
}
|
|
3795
4072
|
return result;
|
|
3796
4073
|
}
|
|
3797
|
-
const DEFAULT_MAX_SIZE = 128;
|
|
3798
|
-
let cache = /* @__PURE__ */ new Map();
|
|
3799
|
-
let maxSize = DEFAULT_MAX_SIZE;
|
|
3800
|
-
function buildMeshCacheKey(shapeHash, tolerance, angularTolerance, skipNormals) {
|
|
3801
|
-
return `${shapeHash}:${tolerance}:${angularTolerance}:${skipNormals}`;
|
|
3802
|
-
}
|
|
3803
|
-
function getMesh(key) {
|
|
3804
|
-
const entry = cache.get(key);
|
|
3805
|
-
if (!entry) return void 0;
|
|
3806
|
-
cache.delete(key);
|
|
3807
|
-
cache.set(key, entry);
|
|
3808
|
-
return entry.value;
|
|
3809
|
-
}
|
|
3810
|
-
function setMesh(key, value) {
|
|
3811
|
-
if (cache.has(key)) {
|
|
3812
|
-
cache.delete(key);
|
|
3813
|
-
}
|
|
3814
|
-
if (cache.size >= maxSize) {
|
|
3815
|
-
const oldest = cache.keys().next().value;
|
|
3816
|
-
if (oldest !== void 0) {
|
|
3817
|
-
cache.delete(oldest);
|
|
3818
|
-
}
|
|
3819
|
-
}
|
|
3820
|
-
cache.set(key, { key, value });
|
|
3821
|
-
}
|
|
3822
|
-
function clearMeshCache() {
|
|
3823
|
-
cache = /* @__PURE__ */ new Map();
|
|
3824
|
-
}
|
|
3825
|
-
function setMeshCacheSize(size) {
|
|
3826
|
-
maxSize = size;
|
|
3827
|
-
while (cache.size > maxSize) {
|
|
3828
|
-
const oldest = cache.keys().next().value;
|
|
3829
|
-
if (oldest !== void 0) {
|
|
3830
|
-
cache.delete(oldest);
|
|
3831
|
-
}
|
|
3832
|
-
}
|
|
3833
|
-
}
|
|
3834
|
-
function meshShape(shape, {
|
|
3835
|
-
tolerance = 1e-3,
|
|
3836
|
-
angularTolerance = 0.1,
|
|
3837
|
-
skipNormals = false,
|
|
3838
|
-
cache: cache2 = true
|
|
3839
|
-
} = {}) {
|
|
3840
|
-
const shapeHash = shape.wrapped.HashCode(HASH_CODE_MAX);
|
|
3841
|
-
if (cache2) {
|
|
3842
|
-
const cacheKey = buildMeshCacheKey(shapeHash, tolerance, angularTolerance, skipNormals);
|
|
3843
|
-
const cached = getMesh(cacheKey);
|
|
3844
|
-
if (cached) return cached;
|
|
3845
|
-
}
|
|
3846
|
-
const result = getKernel().mesh(shape.wrapped, {
|
|
3847
|
-
tolerance,
|
|
3848
|
-
angularTolerance,
|
|
3849
|
-
skipNormals
|
|
3850
|
-
});
|
|
3851
|
-
const mesh = {
|
|
3852
|
-
vertices: result.vertices,
|
|
3853
|
-
normals: result.normals,
|
|
3854
|
-
triangles: result.triangles,
|
|
3855
|
-
faceGroups: result.faceGroups.map((g) => ({
|
|
3856
|
-
start: g.start,
|
|
3857
|
-
count: g.count,
|
|
3858
|
-
faceId: g.faceHash
|
|
3859
|
-
}))
|
|
3860
|
-
};
|
|
3861
|
-
if (cache2) {
|
|
3862
|
-
const cacheKey = buildMeshCacheKey(shapeHash, tolerance, angularTolerance, skipNormals);
|
|
3863
|
-
setMesh(cacheKey, mesh);
|
|
3864
|
-
}
|
|
3865
|
-
return mesh;
|
|
3866
|
-
}
|
|
3867
|
-
function meshShapeEdges(shape, { tolerance = 1e-3, angularTolerance = 0.1 } = {}) {
|
|
3868
|
-
const oc = getKernel().oc;
|
|
3869
|
-
const r = gcWithScope();
|
|
3870
|
-
const recordedEdges = /* @__PURE__ */ new Set();
|
|
3871
|
-
const lines = [];
|
|
3872
|
-
const edgeGroups = [];
|
|
3873
|
-
const addEdge = () => {
|
|
3874
|
-
const start = lines.length;
|
|
3875
|
-
let prevX = 0;
|
|
3876
|
-
let prevY = 0;
|
|
3877
|
-
let prevZ = 0;
|
|
3878
|
-
let hasPrev = false;
|
|
3879
|
-
return [
|
|
3880
|
-
(p) => {
|
|
3881
|
-
const x = p.X();
|
|
3882
|
-
const y = p.Y();
|
|
3883
|
-
const z = p.Z();
|
|
3884
|
-
if (hasPrev) {
|
|
3885
|
-
lines.push(prevX, prevY, prevZ, x, y, z);
|
|
3886
|
-
}
|
|
3887
|
-
prevX = x;
|
|
3888
|
-
prevY = y;
|
|
3889
|
-
prevZ = z;
|
|
3890
|
-
hasPrev = true;
|
|
3891
|
-
},
|
|
3892
|
-
(edgeHash) => {
|
|
3893
|
-
edgeGroups.push({
|
|
3894
|
-
start: start / 3,
|
|
3895
|
-
count: (lines.length - start) / 3,
|
|
3896
|
-
edgeId: edgeHash
|
|
3897
|
-
});
|
|
3898
|
-
recordedEdges.add(edgeHash);
|
|
3899
|
-
}
|
|
3900
|
-
];
|
|
3901
|
-
};
|
|
3902
|
-
const aLocation = r(new oc.TopLoc_Location_1());
|
|
3903
|
-
const faces = getFaces(shape);
|
|
3904
|
-
for (const face of faces) {
|
|
3905
|
-
const triangulation = r(oc.BRep_Tool.Triangulation(face.wrapped, aLocation, 0));
|
|
3906
|
-
if (triangulation.IsNull()) continue;
|
|
3907
|
-
const tri = triangulation.get();
|
|
3908
|
-
const faceEdges = getEdges$1(face);
|
|
3909
|
-
for (const edge of faceEdges) {
|
|
3910
|
-
const edgeHash = edge.wrapped.HashCode(HASH_CODE_MAX);
|
|
3911
|
-
if (recordedEdges.has(edgeHash)) continue;
|
|
3912
|
-
const edgeLoc = r(new oc.TopLoc_Location_1());
|
|
3913
|
-
const polygon = r(
|
|
3914
|
-
oc.BRep_Tool.PolygonOnTriangulation_1(edge.wrapped, triangulation, edgeLoc)
|
|
3915
|
-
);
|
|
3916
|
-
const edgeNodes = polygon?.get()?.Nodes();
|
|
3917
|
-
if (!edgeNodes) continue;
|
|
3918
|
-
r(edgeNodes);
|
|
3919
|
-
const [recordPoint, done] = addEdge();
|
|
3920
|
-
for (let i = edgeNodes.Lower(); i <= edgeNodes.Upper(); i++) {
|
|
3921
|
-
const p = r(r(tri.Node(edgeNodes.Value(i))).Transformed(edgeLoc.Transformation()));
|
|
3922
|
-
recordPoint(p);
|
|
3923
|
-
}
|
|
3924
|
-
done(edgeHash);
|
|
3925
|
-
}
|
|
3926
|
-
}
|
|
3927
|
-
const allEdges = getEdges$1(shape);
|
|
3928
|
-
for (const edge of allEdges) {
|
|
3929
|
-
const edgeHash = edge.wrapped.HashCode(HASH_CODE_MAX);
|
|
3930
|
-
if (recordedEdges.has(edgeHash)) continue;
|
|
3931
|
-
const adaptorCurve = r(new oc.BRepAdaptor_Curve_2(edge.wrapped));
|
|
3932
|
-
const tangDef = r(
|
|
3933
|
-
new oc.GCPnts_TangentialDeflection_2(adaptorCurve, tolerance, angularTolerance, 2, 1e-9, 1e-7)
|
|
3934
|
-
);
|
|
3935
|
-
const [recordPoint, done] = addEdge();
|
|
3936
|
-
for (let j = 0; j < tangDef.NbPoints(); j++) {
|
|
3937
|
-
const p = r(tangDef.Value(j + 1).Transformed(aLocation.Transformation()));
|
|
3938
|
-
recordPoint(p);
|
|
3939
|
-
}
|
|
3940
|
-
done(edgeHash);
|
|
3941
|
-
}
|
|
3942
|
-
return { lines, edgeGroups };
|
|
3943
|
-
}
|
|
3944
|
-
function exportSTEP$1(shape) {
|
|
3945
|
-
const oc = getKernel().oc;
|
|
3946
|
-
const filename = "blob.step";
|
|
3947
|
-
const writer = new oc.STEPControl_Writer_1();
|
|
3948
|
-
oc.Interface_Static.SetIVal("write.step.schema", 5);
|
|
3949
|
-
writer.Model(true).delete();
|
|
3950
|
-
const progress = new oc.Message_ProgressRange_1();
|
|
3951
|
-
writer.Transfer(shape.wrapped, oc.STEPControl_StepModelType.STEPControl_AsIs, true, progress);
|
|
3952
|
-
const done = writer.Write(filename);
|
|
3953
|
-
writer.delete();
|
|
3954
|
-
progress.delete();
|
|
3955
|
-
if (done === oc.IFSelect_ReturnStatus.IFSelect_RetDone) {
|
|
3956
|
-
try {
|
|
3957
|
-
const file = oc.FS.readFile("/" + filename);
|
|
3958
|
-
oc.FS.unlink("/" + filename);
|
|
3959
|
-
return ok(new Blob([file], { type: "application/STEP" }));
|
|
3960
|
-
} catch (e) {
|
|
3961
|
-
return err(ioError("STEP_FILE_READ_ERROR", "Failed to read exported STEP file", e));
|
|
3962
|
-
}
|
|
3963
|
-
}
|
|
3964
|
-
return err(ioError("STEP_EXPORT_FAILED", "Failed to write STEP file"));
|
|
3965
|
-
}
|
|
3966
|
-
function exportSTL(shape, {
|
|
3967
|
-
tolerance = 1e-3,
|
|
3968
|
-
angularTolerance = 0.1,
|
|
3969
|
-
binary = false
|
|
3970
|
-
} = {}) {
|
|
3971
|
-
const oc = getKernel().oc;
|
|
3972
|
-
new oc.BRepMesh_IncrementalMesh_2(shape.wrapped, tolerance, false, angularTolerance, false);
|
|
3973
|
-
const filename = "blob.stl";
|
|
3974
|
-
const done = oc.StlAPI.Write(shape.wrapped, filename, !binary);
|
|
3975
|
-
if (done) {
|
|
3976
|
-
try {
|
|
3977
|
-
const file = oc.FS.readFile("/" + filename);
|
|
3978
|
-
oc.FS.unlink("/" + filename);
|
|
3979
|
-
return ok(new Blob([file], { type: "application/sla" }));
|
|
3980
|
-
} catch (e) {
|
|
3981
|
-
return err(ioError("STL_FILE_READ_ERROR", "Failed to read exported STL file", e));
|
|
3982
|
-
}
|
|
3983
|
-
}
|
|
3984
|
-
return err(ioError("STL_EXPORT_FAILED", "Failed to write STL file"));
|
|
3985
|
-
}
|
|
3986
4074
|
function applyGlue(op, optimisation) {
|
|
3987
4075
|
const oc = getKernel().oc;
|
|
3988
4076
|
if (optimisation === "commonFace") {
|
|
@@ -4006,6 +4094,7 @@ function buildCompoundOcInternal(shapes) {
|
|
|
4006
4094
|
function castToShape3D(shape, errorCode, errorMsg) {
|
|
4007
4095
|
const wrapped = castShape(shape);
|
|
4008
4096
|
if (!isShape3D(wrapped)) {
|
|
4097
|
+
wrapped[Symbol.dispose]();
|
|
4009
4098
|
return err(typeCastError(errorCode, errorMsg));
|
|
4010
4099
|
}
|
|
4011
4100
|
return ok(wrapped);
|
|
@@ -4074,29 +4163,44 @@ function buildCompound(shapes) {
|
|
|
4074
4163
|
return createCompound(compound);
|
|
4075
4164
|
}
|
|
4076
4165
|
initCast(shapesModule);
|
|
4166
|
+
function buildLawFromProfile(extrusionLength, { profile, endFactor = 1 }) {
|
|
4167
|
+
const oc = getKernel().oc;
|
|
4168
|
+
const r = gcWithScope();
|
|
4169
|
+
let law;
|
|
4170
|
+
if (profile === "s-curve") {
|
|
4171
|
+
law = r(new oc.Law_S());
|
|
4172
|
+
law.Set_1(0, 1, extrusionLength, endFactor);
|
|
4173
|
+
} else if (profile === "linear") {
|
|
4174
|
+
law = r(new oc.Law_Linear());
|
|
4175
|
+
law.Set(0, 1, extrusionLength, endFactor);
|
|
4176
|
+
} else {
|
|
4177
|
+
return err(
|
|
4178
|
+
validationError("UNSUPPORTED_PROFILE", `Unsupported extrusion profile: ${String(profile)}`)
|
|
4179
|
+
);
|
|
4180
|
+
}
|
|
4181
|
+
return ok(law.Trim(0, extrusionLength, 1e-6));
|
|
4182
|
+
}
|
|
4077
4183
|
const basicFaceExtrusion = (face, extrusionVec) => {
|
|
4078
4184
|
const oc = getKernel().oc;
|
|
4079
|
-
const
|
|
4080
|
-
|
|
4081
|
-
extrusionVec.wrapped,
|
|
4082
|
-
false,
|
|
4083
|
-
true
|
|
4185
|
+
const [r, gc] = localGC();
|
|
4186
|
+
const solidBuilder = r(
|
|
4187
|
+
new oc.BRepPrimAPI_MakePrism_1(face.wrapped, extrusionVec.wrapped, false, true)
|
|
4084
4188
|
);
|
|
4085
4189
|
const solid = new Solid(unwrap(downcast(solidBuilder.Shape())));
|
|
4086
|
-
|
|
4190
|
+
gc();
|
|
4087
4191
|
return solid;
|
|
4088
4192
|
};
|
|
4089
4193
|
const revolution = (face, center = [0, 0, 0], direction = [0, 0, 1], angle = 360) => {
|
|
4090
4194
|
const oc = getKernel().oc;
|
|
4091
|
-
const
|
|
4092
|
-
const
|
|
4195
|
+
const [r, gc] = localGC();
|
|
4196
|
+
const ax = r(makeAx1(center, direction));
|
|
4197
|
+
const revolBuilder = r(new oc.BRepPrimAPI_MakeRevol_1(face.wrapped, ax, angle * DEG2RAD, false));
|
|
4093
4198
|
const result = andThen(cast(revolBuilder.Shape()), (shape) => {
|
|
4094
4199
|
if (!isShape3D$2(shape))
|
|
4095
4200
|
return err(typeCastError("REVOLUTION_NOT_3D", "Revolution did not produce a 3D shape"));
|
|
4096
4201
|
return ok(shape);
|
|
4097
4202
|
});
|
|
4098
|
-
|
|
4099
|
-
revolBuilder.delete();
|
|
4203
|
+
gc();
|
|
4100
4204
|
return result;
|
|
4101
4205
|
};
|
|
4102
4206
|
function genericSweep(wire, spine, {
|
|
@@ -4109,8 +4213,9 @@ function genericSweep(wire, spine, {
|
|
|
4109
4213
|
forceProfileSpineOthogonality
|
|
4110
4214
|
} = {}, shellMode = false) {
|
|
4111
4215
|
const oc = getKernel().oc;
|
|
4216
|
+
const [r, gc] = localGC();
|
|
4112
4217
|
const withCorrection = transitionMode === "round" ? true : !!forceProfileSpineOthogonality;
|
|
4113
|
-
const sweepBuilder = new oc.BRepOffsetAPI_MakePipeShell(spine.wrapped);
|
|
4218
|
+
const sweepBuilder = r(new oc.BRepOffsetAPI_MakePipeShell(spine.wrapped));
|
|
4114
4219
|
{
|
|
4115
4220
|
const mode = {
|
|
4116
4221
|
transformed: oc.BRepBuilderAPI_TransitionMode.BRepBuilderAPI_Transformed,
|
|
@@ -4133,91 +4238,71 @@ function genericSweep(wire, spine, {
|
|
|
4133
4238
|
}
|
|
4134
4239
|
if (!law) sweepBuilder.Add_1(wire.wrapped, !!withContact, withCorrection);
|
|
4135
4240
|
else sweepBuilder.SetLaw_1(wire.wrapped, law, !!withContact, withCorrection);
|
|
4136
|
-
const progress = new oc.Message_ProgressRange_1();
|
|
4241
|
+
const progress = r(new oc.Message_ProgressRange_1());
|
|
4137
4242
|
sweepBuilder.Build(progress);
|
|
4138
4243
|
if (!shellMode) {
|
|
4139
4244
|
sweepBuilder.MakeSolid();
|
|
4140
4245
|
}
|
|
4141
4246
|
const shape = unwrap(cast(sweepBuilder.Shape()));
|
|
4142
4247
|
if (!isShape3D$2(shape)) {
|
|
4143
|
-
|
|
4144
|
-
progress.delete();
|
|
4248
|
+
gc();
|
|
4145
4249
|
return err(typeCastError("SWEEP_NOT_3D", "Sweep did not produce a 3D shape"));
|
|
4146
4250
|
}
|
|
4147
4251
|
if (shellMode) {
|
|
4148
4252
|
const startWire = unwrap(cast(sweepBuilder.FirstShape()));
|
|
4149
4253
|
const endWire = unwrap(cast(sweepBuilder.LastShape()));
|
|
4150
4254
|
if (!isWire$1(startWire)) {
|
|
4151
|
-
|
|
4255
|
+
gc();
|
|
4152
4256
|
return err(typeCastError("SWEEP_START_NOT_WIRE", "Sweep did not produce a start Wire"));
|
|
4153
4257
|
}
|
|
4154
4258
|
if (!isWire$1(endWire)) {
|
|
4155
|
-
|
|
4259
|
+
gc();
|
|
4156
4260
|
return err(typeCastError("SWEEP_END_NOT_WIRE", "Sweep did not produce an end Wire"));
|
|
4157
4261
|
}
|
|
4158
|
-
|
|
4262
|
+
gc();
|
|
4159
4263
|
return ok([shape, startWire, endWire]);
|
|
4160
4264
|
}
|
|
4161
|
-
|
|
4162
|
-
progress.delete();
|
|
4265
|
+
gc();
|
|
4163
4266
|
return ok(shape);
|
|
4164
4267
|
}
|
|
4165
|
-
const buildLawFromProfile$1 = (extrusionLength, { profile, endFactor = 1 }) => {
|
|
4166
|
-
const oc = getKernel().oc;
|
|
4167
|
-
let law;
|
|
4168
|
-
if (profile === "s-curve") {
|
|
4169
|
-
law = new oc.Law_S();
|
|
4170
|
-
law.Set_1(0, 1, extrusionLength, endFactor);
|
|
4171
|
-
} else if (profile === "linear") {
|
|
4172
|
-
law = new oc.Law_Linear();
|
|
4173
|
-
law.Set(0, 1, extrusionLength, endFactor);
|
|
4174
|
-
} else {
|
|
4175
|
-
return err(
|
|
4176
|
-
validationError("UNSUPPORTED_PROFILE", `Unsupported extrusion profile: ${String(profile)}`)
|
|
4177
|
-
);
|
|
4178
|
-
}
|
|
4179
|
-
const trimmed = law.Trim(0, extrusionLength, 1e-6);
|
|
4180
|
-
law.delete();
|
|
4181
|
-
return ok(trimmed);
|
|
4182
|
-
};
|
|
4183
4268
|
const supportExtrude$1 = (wire, center, normal, support) => {
|
|
4184
|
-
const
|
|
4185
|
-
const
|
|
4186
|
-
const
|
|
4187
|
-
const
|
|
4188
|
-
const
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
return
|
|
4269
|
+
const [r, gc] = localGC();
|
|
4270
|
+
const centerVec = r(new Vector(center));
|
|
4271
|
+
const normalVec = r(new Vector(normal));
|
|
4272
|
+
const endVec = r(centerVec.add(normalVec));
|
|
4273
|
+
const mainSpineEdge = r(makeLine(centerVec, endVec));
|
|
4274
|
+
const spine = r(unwrap(assembleWire$1([mainSpineEdge])));
|
|
4275
|
+
const result = genericSweep(wire, spine, { support });
|
|
4276
|
+
gc();
|
|
4277
|
+
return result;
|
|
4193
4278
|
};
|
|
4194
4279
|
function complexExtrude$1(wire, center, normal, profileShape, shellMode = false) {
|
|
4195
|
-
const
|
|
4196
|
-
const
|
|
4197
|
-
const
|
|
4198
|
-
const
|
|
4199
|
-
const
|
|
4200
|
-
const
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
return
|
|
4280
|
+
const [r, gc] = localGC();
|
|
4281
|
+
const centerVec = r(new Vector(center));
|
|
4282
|
+
const normalVec = r(new Vector(normal));
|
|
4283
|
+
const endVec = r(centerVec.add(normalVec));
|
|
4284
|
+
const mainSpineEdge = r(makeLine(centerVec, endVec));
|
|
4285
|
+
const spine = r(unwrap(assembleWire$1([mainSpineEdge])));
|
|
4286
|
+
const law = profileShape ? r(unwrap(buildLawFromProfile(normalVec.Length, profileShape))) : null;
|
|
4287
|
+
const result = shellMode ? genericSweep(wire, spine, { law }, shellMode) : genericSweep(wire, spine, { law }, shellMode);
|
|
4288
|
+
gc();
|
|
4289
|
+
return result;
|
|
4205
4290
|
}
|
|
4206
4291
|
function twistExtrude$1(wire, angleDegrees, center, normal, profileShape, shellMode = false) {
|
|
4207
|
-
const
|
|
4208
|
-
const
|
|
4209
|
-
const
|
|
4210
|
-
const
|
|
4211
|
-
const
|
|
4292
|
+
const [r, gc] = localGC();
|
|
4293
|
+
const centerVec = r(new Vector(center));
|
|
4294
|
+
const normalVec = r(new Vector(normal));
|
|
4295
|
+
const endVec = r(centerVec.add(normalVec));
|
|
4296
|
+
const mainSpineEdge = r(makeLine(centerVec, endVec));
|
|
4297
|
+
const spine = r(unwrap(assembleWire$1([mainSpineEdge])));
|
|
4212
4298
|
const extrusionLength = normalVec.Length;
|
|
4213
4299
|
const pitch = 360 / angleDegrees * extrusionLength;
|
|
4214
4300
|
const radius = 1;
|
|
4215
|
-
const auxiliarySpine = makeHelix(pitch, extrusionLength, radius, center, normal);
|
|
4216
|
-
const law = profileShape ? unwrap(buildLawFromProfile
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
return shellMode ? genericSweep(wire, spine, { auxiliarySpine, law }, shellMode) : genericSweep(wire, spine, { auxiliarySpine, law }, shellMode);
|
|
4301
|
+
const auxiliarySpine = r(makeHelix(pitch, extrusionLength, radius, center, normal));
|
|
4302
|
+
const law = profileShape ? r(unwrap(buildLawFromProfile(extrusionLength, profileShape))) : null;
|
|
4303
|
+
const result = shellMode ? genericSweep(wire, spine, { auxiliarySpine, law }, shellMode) : genericSweep(wire, spine, { auxiliarySpine, law }, shellMode);
|
|
4304
|
+
gc();
|
|
4305
|
+
return result;
|
|
4221
4306
|
}
|
|
4222
4307
|
const loft = (wires, { ruled = true, startPoint, endPoint } = {}, returnShell = false) => {
|
|
4223
4308
|
const oc = getKernel().oc;
|
|
@@ -4247,31 +4332,48 @@ function uuidv() {
|
|
|
4247
4332
|
crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> Number(c) / 4).toString(16)
|
|
4248
4333
|
);
|
|
4249
4334
|
}
|
|
4250
|
-
|
|
4335
|
+
function wrapString(str) {
|
|
4251
4336
|
const oc = getKernel().oc;
|
|
4252
4337
|
return new oc.TCollection_ExtendedString_2(str, true);
|
|
4253
|
-
}
|
|
4254
|
-
function parseSlice
|
|
4338
|
+
}
|
|
4339
|
+
function parseSlice(hex, index) {
|
|
4255
4340
|
return parseInt(hex.slice(index * 2, (index + 1) * 2), 16);
|
|
4256
4341
|
}
|
|
4257
|
-
function colorFromHex
|
|
4342
|
+
function colorFromHex(hex) {
|
|
4258
4343
|
let color = hex;
|
|
4259
4344
|
if (color.indexOf("#") === 0) color = color.slice(1);
|
|
4260
4345
|
if (color.length === 3) {
|
|
4261
4346
|
color = color.replace(/([0-9a-f])/gi, "$1$1");
|
|
4262
4347
|
}
|
|
4263
|
-
return [parseSlice
|
|
4348
|
+
return [parseSlice(color, 0), parseSlice(color, 1), parseSlice(color, 2)];
|
|
4264
4349
|
}
|
|
4265
|
-
|
|
4350
|
+
function wrapColor(hex, alpha = 1) {
|
|
4266
4351
|
const oc = getKernel().oc;
|
|
4267
|
-
const [
|
|
4268
|
-
return new oc.Quantity_ColorRGBA_5(
|
|
4269
|
-
}
|
|
4352
|
+
const [red, green, blue] = colorFromHex(hex);
|
|
4353
|
+
return new oc.Quantity_ColorRGBA_5(red / 255, green / 255, blue / 255, alpha);
|
|
4354
|
+
}
|
|
4355
|
+
function configureStepUnits(unit, modelUnit, r) {
|
|
4356
|
+
if (!unit && !modelUnit) return;
|
|
4357
|
+
const oc = getKernel().oc;
|
|
4358
|
+
r(new oc.STEPCAFControl_Writer_1());
|
|
4359
|
+
oc.Interface_Static.SetCVal("xstep.cascade.unit", (modelUnit || unit || "MM").toUpperCase());
|
|
4360
|
+
oc.Interface_Static.SetCVal("write.step.unit", (unit || modelUnit || "MM").toUpperCase());
|
|
4361
|
+
}
|
|
4362
|
+
function configureStepWriter(writer) {
|
|
4363
|
+
const oc = getKernel().oc;
|
|
4364
|
+
writer.SetColorMode(true);
|
|
4365
|
+
writer.SetLayerMode(true);
|
|
4366
|
+
writer.SetNameMode(true);
|
|
4367
|
+
oc.Interface_Static.SetIVal("write.surfacecurve.mode", true);
|
|
4368
|
+
oc.Interface_Static.SetIVal("write.precision.mode", 0);
|
|
4369
|
+
oc.Interface_Static.SetIVal("write.step.assembly", 2);
|
|
4370
|
+
oc.Interface_Static.SetIVal("write.step.schema", 5);
|
|
4371
|
+
}
|
|
4270
4372
|
class AssemblyExporter extends WrappingObj {
|
|
4271
4373
|
}
|
|
4272
4374
|
function createAssembly(shapes = []) {
|
|
4273
4375
|
const oc = getKernel().oc;
|
|
4274
|
-
const doc = new oc.TDocStd_Document(wrapString
|
|
4376
|
+
const doc = new oc.TDocStd_Document(wrapString("XmlOcaf"));
|
|
4275
4377
|
oc.XCAFDoc_ShapeTool.SetAutoNaming(false);
|
|
4276
4378
|
const mainLabel = doc.Main();
|
|
4277
4379
|
const tool = oc.XCAFDoc_DocumentTool.ShapeTool(mainLabel).get();
|
|
@@ -4279,10 +4381,10 @@ function createAssembly(shapes = []) {
|
|
|
4279
4381
|
for (const { shape, name, color, alpha } of shapes) {
|
|
4280
4382
|
const shapeNode = tool.NewShape();
|
|
4281
4383
|
tool.SetShape(shapeNode, shape.wrapped);
|
|
4282
|
-
oc.TDataStd_Name.Set_1(shapeNode, wrapString
|
|
4384
|
+
oc.TDataStd_Name.Set_1(shapeNode, wrapString(name || uuidv()));
|
|
4283
4385
|
ctool.SetColor_3(
|
|
4284
4386
|
shapeNode,
|
|
4285
|
-
wrapColor
|
|
4387
|
+
wrapColor(color || "#f00", alpha ?? 1),
|
|
4286
4388
|
oc.XCAFDoc_ColorType.XCAFDoc_ColorSurf
|
|
4287
4389
|
);
|
|
4288
4390
|
}
|
|
@@ -4293,38 +4395,32 @@ function exportSTEP(shapes = [], { unit, modelUnit } = {}) {
|
|
|
4293
4395
|
const oc = getKernel().oc;
|
|
4294
4396
|
const r = gcWithScope();
|
|
4295
4397
|
const doc = createAssembly(shapes);
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
const file = oc.FS.readFile("/" + filename);
|
|
4323
|
-
oc.FS.unlink("/" + filename);
|
|
4324
|
-
const blob = new Blob([file], { type: "application/STEP" });
|
|
4325
|
-
return ok(blob);
|
|
4326
|
-
} else {
|
|
4327
|
-
return err(ioError("STEP_EXPORT_FAILED", "Failed to write STEP file"));
|
|
4398
|
+
try {
|
|
4399
|
+
configureStepUnits(unit, modelUnit, r);
|
|
4400
|
+
const session = r(new oc.XSControl_WorkSession());
|
|
4401
|
+
const writer = r(
|
|
4402
|
+
new oc.STEPCAFControl_Writer_2(r(new oc.Handle_XSControl_WorkSession_2(session)), false)
|
|
4403
|
+
);
|
|
4404
|
+
configureStepWriter(writer);
|
|
4405
|
+
const progress = r(new oc.Message_ProgressRange_1());
|
|
4406
|
+
writer.Transfer_1(
|
|
4407
|
+
new oc.Handle_TDocStd_Document_2(doc.wrapped),
|
|
4408
|
+
oc.STEPControl_StepModelType.STEPControl_AsIs,
|
|
4409
|
+
null,
|
|
4410
|
+
progress
|
|
4411
|
+
);
|
|
4412
|
+
const filename = uniqueIOFilename("_export", "step");
|
|
4413
|
+
const done = writer.Write(filename);
|
|
4414
|
+
if (done === oc.IFSelect_ReturnStatus.IFSelect_RetDone) {
|
|
4415
|
+
const file = oc.FS.readFile("/" + filename);
|
|
4416
|
+
oc.FS.unlink("/" + filename);
|
|
4417
|
+
const blob = new Blob([file], { type: "application/STEP" });
|
|
4418
|
+
return ok(blob);
|
|
4419
|
+
} else {
|
|
4420
|
+
return err(ioError("STEP_EXPORT_FAILED", "Failed to write STEP file"));
|
|
4421
|
+
}
|
|
4422
|
+
} finally {
|
|
4423
|
+
doc.delete();
|
|
4328
4424
|
}
|
|
4329
4425
|
}
|
|
4330
4426
|
function fuseAllShapes(shapes, { optimisation = "none", simplify = false, strategy = "native" } = {}) {
|
|
@@ -4532,9 +4628,6 @@ const cartesianToPolar = ([x, y]) => {
|
|
|
4532
4628
|
const theta = Math.atan2(y, x);
|
|
4533
4629
|
return [r, theta];
|
|
4534
4630
|
};
|
|
4535
|
-
const determinant2x2 = (matrix) => {
|
|
4536
|
-
return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0];
|
|
4537
|
-
};
|
|
4538
4631
|
function deserializeCurve2D(data) {
|
|
4539
4632
|
const oc = getKernel().oc;
|
|
4540
4633
|
const handle = oc.GeomToolsWrapper.Read(data);
|
|
@@ -4831,23 +4924,24 @@ function* commonSegmentsIteration(intersector) {
|
|
|
4831
4924
|
const nSegments = intersector.NbSegments();
|
|
4832
4925
|
if (!nSegments) return;
|
|
4833
4926
|
const oc = getKernel().oc;
|
|
4927
|
+
const r = gcWithScope();
|
|
4834
4928
|
for (let i = 1; i <= nSegments; i++) {
|
|
4835
4929
|
const h1 = new oc.Handle_Geom2d_Curve_1();
|
|
4836
|
-
const h2 = new oc.Handle_Geom2d_Curve_1();
|
|
4930
|
+
const h2 = r(new oc.Handle_Geom2d_Curve_1());
|
|
4837
4931
|
try {
|
|
4838
4932
|
intersector.Segment(i, h1, h2);
|
|
4839
4933
|
} catch {
|
|
4840
4934
|
continue;
|
|
4841
4935
|
}
|
|
4842
4936
|
yield new Curve2D(h1);
|
|
4843
|
-
h2.delete();
|
|
4844
4937
|
}
|
|
4845
4938
|
}
|
|
4846
4939
|
const intersectCurves = (first, second, precision = 1e-9) => {
|
|
4847
4940
|
if (first.boundingBox.isOut(second.boundingBox))
|
|
4848
4941
|
return ok({ intersections: [], commonSegments: [], commonSegmentsPoints: [] });
|
|
4849
4942
|
const oc = getKernel().oc;
|
|
4850
|
-
const
|
|
4943
|
+
const r = gcWithScope();
|
|
4944
|
+
const intersector = r(new oc.Geom2dAPI_InterCurveCurve_1());
|
|
4851
4945
|
let intersections;
|
|
4852
4946
|
let commonSegments;
|
|
4853
4947
|
try {
|
|
@@ -4856,8 +4950,6 @@ const intersectCurves = (first, second, precision = 1e-9) => {
|
|
|
4856
4950
|
commonSegments = Array.from(commonSegmentsIteration(intersector));
|
|
4857
4951
|
} catch (e) {
|
|
4858
4952
|
return err(computationError("INTERSECTION_FAILED", "Intersections failed between curves", e));
|
|
4859
|
-
} finally {
|
|
4860
|
-
intersector.delete();
|
|
4861
4953
|
}
|
|
4862
4954
|
const segmentsAsPoints = commonSegments.filter((c) => samePoint$2(c.firstPoint, c.lastPoint, precision)).map((c) => c.firstPoint);
|
|
4863
4955
|
if (segmentsAsPoints.length) {
|
|
@@ -4869,15 +4961,14 @@ const intersectCurves = (first, second, precision = 1e-9) => {
|
|
|
4869
4961
|
};
|
|
4870
4962
|
const selfIntersections = (curve, precision = 1e-9) => {
|
|
4871
4963
|
const oc = getKernel().oc;
|
|
4872
|
-
const
|
|
4964
|
+
const r = gcWithScope();
|
|
4965
|
+
const intersector = r(new oc.Geom2dAPI_InterCurveCurve_1());
|
|
4873
4966
|
let intersections;
|
|
4874
4967
|
try {
|
|
4875
4968
|
intersector.Init_1(curve.wrapped, curve.wrapped, precision);
|
|
4876
4969
|
intersections = Array.from(pointsIteration(intersector));
|
|
4877
4970
|
} catch (e) {
|
|
4878
4971
|
return err(computationError("SELF_INTERSECTION_FAILED", "Self intersection failed", e));
|
|
4879
|
-
} finally {
|
|
4880
|
-
intersector.delete();
|
|
4881
4972
|
}
|
|
4882
4973
|
return ok(intersections);
|
|
4883
4974
|
};
|
|
@@ -5636,6 +5727,7 @@ function round5(v) {
|
|
|
5636
5727
|
const fromPnt = (pnt2) => `${round2(pnt2.X())} ${round2(pnt2.Y())}`;
|
|
5637
5728
|
const adaptedCurveToPathElem = (adaptor, lastPoint) => {
|
|
5638
5729
|
const oc = getKernel().oc;
|
|
5730
|
+
const r = gcWithScope();
|
|
5639
5731
|
const curveType = unwrap(findCurveType(adaptor.GetType()));
|
|
5640
5732
|
const [endX, endY] = lastPoint;
|
|
5641
5733
|
const endpoint = `${round5(endX)} ${round5(endY)}`;
|
|
@@ -5643,22 +5735,26 @@ const adaptedCurveToPathElem = (adaptor, lastPoint) => {
|
|
|
5643
5735
|
return `L ${endpoint}`;
|
|
5644
5736
|
}
|
|
5645
5737
|
if (curveType === "BEZIER_CURVE") {
|
|
5646
|
-
const
|
|
5738
|
+
const bezierHandle = r(adaptor.Bezier());
|
|
5739
|
+
const curve = bezierHandle.get();
|
|
5647
5740
|
const deg = curve.Degree();
|
|
5648
5741
|
if (deg === 1) {
|
|
5649
5742
|
return `L ${endpoint}`;
|
|
5650
5743
|
}
|
|
5651
5744
|
if (deg === 2) {
|
|
5652
|
-
|
|
5745
|
+
const pole2 = r(curve.Pole(2));
|
|
5746
|
+
return `Q ${fromPnt(pole2)} ${endpoint}`;
|
|
5653
5747
|
}
|
|
5654
5748
|
if (deg === 3) {
|
|
5655
|
-
const
|
|
5656
|
-
const
|
|
5749
|
+
const pole2 = r(curve.Pole(2));
|
|
5750
|
+
const pole3 = r(curve.Pole(3));
|
|
5751
|
+
const p1 = fromPnt(pole2);
|
|
5752
|
+
const p2 = fromPnt(pole3);
|
|
5657
5753
|
return `C ${p1} ${p2} ${endpoint}`;
|
|
5658
5754
|
}
|
|
5659
5755
|
}
|
|
5660
5756
|
if (curveType === "CIRCLE") {
|
|
5661
|
-
const curve = adaptor.Circle();
|
|
5757
|
+
const curve = r(adaptor.Circle());
|
|
5662
5758
|
const radius = curve.Radius();
|
|
5663
5759
|
const p1 = adaptor.FirstParameter();
|
|
5664
5760
|
const p2 = adaptor.LastParameter();
|
|
@@ -5667,16 +5763,17 @@ const adaptedCurveToPathElem = (adaptor, lastPoint) => {
|
|
|
5667
5763
|
return `A ${radius} ${radius} 0 ${Math.abs(paramAngle) > 180 ? "1" : "0"} ${curve.IsDirect() ? "1" : "0"} ${end}`;
|
|
5668
5764
|
}
|
|
5669
5765
|
if (curveType === "ELLIPSE") {
|
|
5670
|
-
const curve = adaptor.Ellipse();
|
|
5766
|
+
const curve = r(adaptor.Ellipse());
|
|
5671
5767
|
const rx = curve.MajorRadius();
|
|
5672
5768
|
const ry = curve.MinorRadius();
|
|
5673
5769
|
const p1 = adaptor.FirstParameter();
|
|
5674
5770
|
const p2 = adaptor.LastParameter();
|
|
5675
5771
|
const paramAngle = (p2 - p1) * RAD2DEG;
|
|
5676
5772
|
const end = paramAngle !== 360 ? endpoint : `${round5(endX)} ${round5(endY + 1e-4)}`;
|
|
5677
|
-
const dir0 = new oc.gp_Dir2d_1();
|
|
5678
|
-
const
|
|
5679
|
-
|
|
5773
|
+
const dir0 = r(new oc.gp_Dir2d_1());
|
|
5774
|
+
const xAxis = r(curve.XAxis());
|
|
5775
|
+
const xDir = r(xAxis.Direction());
|
|
5776
|
+
const angle = 180 - xDir.Angle(dir0) * RAD2DEG;
|
|
5680
5777
|
return `A ${round5(rx)} ${round5(ry)} ${round5(angle)} ${Math.abs(paramAngle) > 180 ? "1" : "0"} ${curve.IsDirect() ? "1" : "0"} ${end}`;
|
|
5681
5778
|
}
|
|
5682
5779
|
bug("adaptedCurveToPathElem", `Unsupported curve type: ${curveType}`);
|
|
@@ -5694,8 +5791,9 @@ function curvesAsEdgesOnPlane(curves, plane) {
|
|
|
5694
5791
|
const ax = r(makeAx2(plane.origin, plane.zDir, plane.xDir));
|
|
5695
5792
|
const oc = getKernel().oc;
|
|
5696
5793
|
const edges = curves.map((curve) => {
|
|
5697
|
-
const curve3d = oc.GeomLib.To3d(ax, curve.wrapped);
|
|
5698
|
-
|
|
5794
|
+
const curve3d = r(oc.GeomLib.To3d(ax, curve.wrapped));
|
|
5795
|
+
const edgeBuilder = r(new oc.BRepBuilderAPI_MakeEdge_24(curve3d));
|
|
5796
|
+
return new Edge(edgeBuilder.Edge());
|
|
5699
5797
|
});
|
|
5700
5798
|
gc();
|
|
5701
5799
|
return edges;
|
|
@@ -6107,12 +6205,15 @@ class FaceFinder extends Finder3d {
|
|
|
6107
6205
|
* @category Filter
|
|
6108
6206
|
*/
|
|
6109
6207
|
parallelTo(plane) {
|
|
6208
|
+
const [r, gc] = localGC();
|
|
6110
6209
|
if (typeof plane === "string") return this.atAngleWith(PLANE_TO_DIR[plane]);
|
|
6111
6210
|
if (typeof plane !== "string" && plane instanceof Plane)
|
|
6112
6211
|
return this.atAngleWith(plane.zDir);
|
|
6113
6212
|
if (typeof plane !== "string" && "normalAt" in plane) {
|
|
6114
|
-
const normal = plane.normalAt();
|
|
6115
|
-
|
|
6213
|
+
const normal = r(plane.normalAt());
|
|
6214
|
+
const normalPoint = [normal.x, normal.y, normal.z];
|
|
6215
|
+
gc();
|
|
6216
|
+
return this.atAngleWith(normalPoint);
|
|
6116
6217
|
}
|
|
6117
6218
|
return this;
|
|
6118
6219
|
}
|
|
@@ -6138,13 +6239,22 @@ class FaceFinder extends Finder3d {
|
|
|
6138
6239
|
inPlane(inputPlane, origin) {
|
|
6139
6240
|
const plane = inputPlane instanceof Plane ? makePlane(inputPlane) : makePlane(inputPlane, origin);
|
|
6140
6241
|
this.parallelTo(plane);
|
|
6141
|
-
const centerInPlane = ({ element }) =>
|
|
6242
|
+
const centerInPlane = ({ element }) => {
|
|
6243
|
+
const [r, gc] = localGC();
|
|
6244
|
+
const center = element.center;
|
|
6245
|
+
const projected = r(center.projectToPlane(plane));
|
|
6246
|
+
const result = center.equals(projected);
|
|
6247
|
+
gc();
|
|
6248
|
+
return result;
|
|
6249
|
+
};
|
|
6142
6250
|
this.filters.push(centerInPlane);
|
|
6143
6251
|
return this;
|
|
6144
6252
|
}
|
|
6145
6253
|
shouldKeep(element) {
|
|
6146
|
-
const
|
|
6254
|
+
const [r, gc] = localGC();
|
|
6255
|
+
const normal = r(element.normalAt());
|
|
6147
6256
|
const shouldKeep = this.filters.every((filter) => filter({ normal, element }));
|
|
6257
|
+
gc();
|
|
6148
6258
|
return shouldKeep;
|
|
6149
6259
|
}
|
|
6150
6260
|
applyFilter(shape) {
|
|
@@ -6155,7 +6265,7 @@ class FaceFinder extends Finder3d {
|
|
|
6155
6265
|
}
|
|
6156
6266
|
}
|
|
6157
6267
|
function getSingleFace(f, shape) {
|
|
6158
|
-
if (
|
|
6268
|
+
if (f instanceof Face) return ok(f);
|
|
6159
6269
|
const finder = f instanceof FaceFinder ? f : f(new FaceFinder());
|
|
6160
6270
|
return finder.find(shape, { unique: true });
|
|
6161
6271
|
}
|
|
@@ -6173,6 +6283,9 @@ class Blueprint {
|
|
|
6173
6283
|
_orientation;
|
|
6174
6284
|
_guessedOrientation;
|
|
6175
6285
|
constructor(curves) {
|
|
6286
|
+
if (curves.length === 0) {
|
|
6287
|
+
throw new Error("Blueprint requires at least one curve");
|
|
6288
|
+
}
|
|
6176
6289
|
this.curves = curves;
|
|
6177
6290
|
this._boundingBox = null;
|
|
6178
6291
|
this._orientation = null;
|
|
@@ -6185,7 +6298,7 @@ class Blueprint {
|
|
|
6185
6298
|
if (this._boundingBox) this._boundingBox.delete();
|
|
6186
6299
|
}
|
|
6187
6300
|
clone() {
|
|
6188
|
-
return new Blueprint(this.curves);
|
|
6301
|
+
return new Blueprint(this.curves.map((c) => c.clone()));
|
|
6189
6302
|
}
|
|
6190
6303
|
get repr() {
|
|
6191
6304
|
return ["Blueprint", ...this.curves.map((c) => c.repr)].join("\n");
|
|
@@ -6319,45 +6432,54 @@ class Blueprint {
|
|
|
6319
6432
|
if (!this.boundingBox.containsPoint(point)) return false;
|
|
6320
6433
|
const oc = getKernel().oc;
|
|
6321
6434
|
const intersector = new oc.Geom2dAPI_InterCurveCurve_1();
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
|
|
6330
|
-
|
|
6331
|
-
|
|
6332
|
-
|
|
6435
|
+
try {
|
|
6436
|
+
const segment = make2dSegmentCurve(point, this.boundingBox.outsidePoint());
|
|
6437
|
+
let crossCounts = 0;
|
|
6438
|
+
const onCurve = this.curves.find((c) => c.isOnCurve(point));
|
|
6439
|
+
if (onCurve) return false;
|
|
6440
|
+
this.curves.forEach((c) => {
|
|
6441
|
+
if (c.boundingBox.isOut(segment.boundingBox)) return;
|
|
6442
|
+
intersector.Init_1(segment.wrapped, c.wrapped, 1e-9);
|
|
6443
|
+
crossCounts += Number(intersector.NbPoints());
|
|
6444
|
+
});
|
|
6445
|
+
return !!(crossCounts % 2);
|
|
6446
|
+
} finally {
|
|
6447
|
+
intersector.delete();
|
|
6448
|
+
}
|
|
6333
6449
|
}
|
|
6334
6450
|
isClosed() {
|
|
6335
6451
|
return samePoint$2(this.firstPoint, this.lastPoint);
|
|
6336
6452
|
}
|
|
6337
6453
|
intersects(other) {
|
|
6454
|
+
if (this.boundingBox.isOut(other.boundingBox)) return false;
|
|
6338
6455
|
const oc = getKernel().oc;
|
|
6339
6456
|
const intersector = new oc.Geom2dAPI_InterCurveCurve_1();
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
6344
|
-
|
|
6345
|
-
|
|
6457
|
+
try {
|
|
6458
|
+
for (const myCurve of this.curves) {
|
|
6459
|
+
for (const otherCurve of other.curves) {
|
|
6460
|
+
if (myCurve.boundingBox.isOut(otherCurve.boundingBox)) continue;
|
|
6461
|
+
intersector.Init_1(myCurve.wrapped, otherCurve.wrapped, 1e-9);
|
|
6462
|
+
if (intersector.NbPoints() || intersector.NbSegments()) return true;
|
|
6463
|
+
}
|
|
6346
6464
|
}
|
|
6465
|
+
return false;
|
|
6466
|
+
} finally {
|
|
6467
|
+
intersector.delete();
|
|
6347
6468
|
}
|
|
6348
|
-
intersector.delete();
|
|
6349
|
-
return false;
|
|
6350
6469
|
}
|
|
6351
6470
|
}
|
|
6352
6471
|
class CompoundBlueprint {
|
|
6353
6472
|
blueprints;
|
|
6354
6473
|
_boundingBox;
|
|
6355
6474
|
constructor(blueprints) {
|
|
6475
|
+
if (blueprints.length === 0) {
|
|
6476
|
+
throw new Error("CompoundBlueprint requires at least one blueprint (the outer boundary)");
|
|
6477
|
+
}
|
|
6356
6478
|
this.blueprints = blueprints;
|
|
6357
6479
|
this._boundingBox = null;
|
|
6358
6480
|
}
|
|
6359
6481
|
clone() {
|
|
6360
|
-
return new CompoundBlueprint(this.blueprints);
|
|
6482
|
+
return new CompoundBlueprint(this.blueprints.map((bp) => bp.clone()));
|
|
6361
6483
|
}
|
|
6362
6484
|
get boundingBox() {
|
|
6363
6485
|
if (!this._boundingBox) {
|
|
@@ -6433,7 +6555,7 @@ class Blueprints {
|
|
|
6433
6555
|
return ["Blueprints", ...this.blueprints.map((b) => b.repr)].join("\n");
|
|
6434
6556
|
}
|
|
6435
6557
|
clone() {
|
|
6436
|
-
return new Blueprints(this.blueprints);
|
|
6558
|
+
return new Blueprints(this.blueprints.map((bp) => bp.clone()));
|
|
6437
6559
|
}
|
|
6438
6560
|
get boundingBox() {
|
|
6439
6561
|
if (!this._boundingBox) {
|
|
@@ -6591,8 +6713,7 @@ class Sketch {
|
|
|
6591
6713
|
}
|
|
6592
6714
|
set baseFace(newFace) {
|
|
6593
6715
|
if (this._baseFace) this._baseFace.delete();
|
|
6594
|
-
|
|
6595
|
-
else this._baseFace = newFace.clone();
|
|
6716
|
+
this._baseFace = newFace ? newFace.clone() : newFace;
|
|
6596
6717
|
}
|
|
6597
6718
|
delete() {
|
|
6598
6719
|
this.wire.delete();
|
|
@@ -7180,7 +7301,7 @@ class BaseSketcher2d {
|
|
|
7180
7301
|
(c) => new Curve2D(c.innerCurve.Mirrored_2(mirrorAxis))
|
|
7181
7302
|
);
|
|
7182
7303
|
mirroredCurves.reverse();
|
|
7183
|
-
mirroredCurves.
|
|
7304
|
+
mirroredCurves.forEach((c) => {
|
|
7184
7305
|
c.reverse();
|
|
7185
7306
|
});
|
|
7186
7307
|
this.pendingCurves.push(...mirroredCurves);
|
|
@@ -7365,16 +7486,22 @@ const rotateToStartAtSegment = (curves, segment) => {
|
|
|
7365
7486
|
const end = curves.slice(startIndex);
|
|
7366
7487
|
return end.concat(start);
|
|
7367
7488
|
};
|
|
7489
|
+
const hashPoint = (p) => `${p[0].toFixed(6)},${p[1].toFixed(6)}`;
|
|
7490
|
+
const hashSegment = (first, last) => {
|
|
7491
|
+
const h1 = hashPoint(first);
|
|
7492
|
+
const h2 = hashPoint(last);
|
|
7493
|
+
return h1 < h2 ? `${h1}|${h2}` : `${h2}|${h1}`;
|
|
7494
|
+
};
|
|
7368
7495
|
function* createSegmentOnPoints(curves, allIntersections, allCommonSegments) {
|
|
7496
|
+
const intersectionSet = new Set(allIntersections.map(hashPoint));
|
|
7497
|
+
const commonSegmentSet = new Set(
|
|
7498
|
+
allCommonSegments.map((seg) => hashSegment(seg.firstPoint, seg.lastPoint))
|
|
7499
|
+
);
|
|
7369
7500
|
const endsAtIntersection = (curve) => {
|
|
7370
|
-
return
|
|
7371
|
-
return samePoint$1(intersection, curve.lastPoint);
|
|
7372
|
-
});
|
|
7501
|
+
return intersectionSet.has(hashPoint(curve.lastPoint));
|
|
7373
7502
|
};
|
|
7374
7503
|
const isCommonSegment = (curve) => {
|
|
7375
|
-
return
|
|
7376
|
-
return samePoint$1(segment.firstPoint, curve.firstPoint) && samePoint$1(segment.lastPoint, curve.lastPoint) || samePoint$1(segment.firstPoint, curve.lastPoint) && samePoint$1(segment.lastPoint, curve.firstPoint);
|
|
7377
|
-
});
|
|
7504
|
+
return commonSegmentSet.has(hashSegment(curve.firstPoint, curve.lastPoint));
|
|
7378
7505
|
};
|
|
7379
7506
|
let currentCurves = [];
|
|
7380
7507
|
for (const curve of curves) {
|
|
@@ -7881,16 +8008,30 @@ function intersect2D(first, second) {
|
|
|
7881
8008
|
}
|
|
7882
8009
|
if (first instanceof CompoundBlueprint) {
|
|
7883
8010
|
const wrapper = first.blueprints[0];
|
|
7884
|
-
const
|
|
7885
|
-
|
|
8011
|
+
const cuts = first.blueprints.slice(1);
|
|
8012
|
+
if (cuts.length === 0) {
|
|
8013
|
+
return intersect2D(wrapper, second);
|
|
8014
|
+
}
|
|
8015
|
+
let result = intersect2D(wrapper, second);
|
|
8016
|
+
for (const cut of cuts) {
|
|
8017
|
+
result = cut2D(result, cut);
|
|
8018
|
+
}
|
|
8019
|
+
return result;
|
|
7886
8020
|
}
|
|
7887
8021
|
if (second instanceof Blueprints) {
|
|
7888
8022
|
return mergeNonIntersecting(second.blueprints.map((bp) => intersect2D(first, bp)));
|
|
7889
8023
|
}
|
|
7890
8024
|
if (second instanceof CompoundBlueprint) {
|
|
7891
8025
|
const wrapper = second.blueprints[0];
|
|
7892
|
-
const
|
|
7893
|
-
|
|
8026
|
+
const cuts = second.blueprints.slice(1);
|
|
8027
|
+
if (cuts.length === 0) {
|
|
8028
|
+
return intersect2D(wrapper, first);
|
|
8029
|
+
}
|
|
8030
|
+
let result = intersect2D(wrapper, first);
|
|
8031
|
+
for (const cut of cuts) {
|
|
8032
|
+
result = cut2D(result, cut);
|
|
8033
|
+
}
|
|
8034
|
+
return result;
|
|
7894
8035
|
}
|
|
7895
8036
|
bug("intersect2D", "Unhandled Shape2D combination");
|
|
7896
8037
|
}
|
|
@@ -8011,12 +8152,15 @@ class EdgeFinder extends Finder3d {
|
|
|
8011
8152
|
* @category Filter
|
|
8012
8153
|
*/
|
|
8013
8154
|
parallelTo(plane) {
|
|
8155
|
+
const [r, gc] = localGC();
|
|
8014
8156
|
if (typeof plane === "string") return this.atAngleWith(PLANE_TO_DIR[plane], 90);
|
|
8015
8157
|
if (typeof plane !== "string" && plane instanceof Plane)
|
|
8016
8158
|
return this.atAngleWith(plane.zDir, 90);
|
|
8017
8159
|
if (typeof plane !== "string" && "normalAt" in plane) {
|
|
8018
|
-
const normal = plane.normalAt();
|
|
8019
|
-
|
|
8160
|
+
const normal = r(plane.normalAt());
|
|
8161
|
+
const normalPoint = [normal.x, normal.y, normal.z];
|
|
8162
|
+
gc();
|
|
8163
|
+
return this.atAngleWith(normalPoint, 90);
|
|
8020
8164
|
}
|
|
8021
8165
|
return this;
|
|
8022
8166
|
}
|
|
@@ -8031,17 +8175,29 @@ class EdgeFinder extends Finder3d {
|
|
|
8031
8175
|
inPlane(inputPlane, origin) {
|
|
8032
8176
|
const plane = inputPlane instanceof Plane ? makePlane(inputPlane) : makePlane(inputPlane, origin);
|
|
8033
8177
|
this.parallelTo(plane);
|
|
8034
|
-
const firstPointInPlane = ({ element }) =>
|
|
8178
|
+
const firstPointInPlane = ({ element }) => {
|
|
8179
|
+
const [r, gc] = localGC();
|
|
8180
|
+
const startPoint = element.startPoint;
|
|
8181
|
+
const projected = r(startPoint.projectToPlane(plane));
|
|
8182
|
+
const result = startPoint.equals(projected);
|
|
8183
|
+
gc();
|
|
8184
|
+
return result;
|
|
8185
|
+
};
|
|
8035
8186
|
this.filters.push(firstPointInPlane);
|
|
8036
8187
|
return this;
|
|
8037
8188
|
}
|
|
8038
8189
|
shouldKeep(element) {
|
|
8190
|
+
const [r, gc] = localGC();
|
|
8039
8191
|
let normal = null;
|
|
8192
|
+
let tangent = null;
|
|
8040
8193
|
try {
|
|
8041
|
-
|
|
8194
|
+
tangent = r(element.tangentAt());
|
|
8195
|
+
normal = r(tangent.normalized());
|
|
8042
8196
|
} catch {
|
|
8043
8197
|
}
|
|
8044
|
-
|
|
8198
|
+
const result = this.filters.every((filter) => filter({ normal, element }));
|
|
8199
|
+
gc();
|
|
8200
|
+
return result;
|
|
8045
8201
|
}
|
|
8046
8202
|
applyFilter(shape) {
|
|
8047
8203
|
return shape.edges.filter((edge) => {
|
|
@@ -8207,13 +8363,25 @@ function measureShapeVolumeProperties(shape) {
|
|
|
8207
8363
|
return new VolumePhysicalProperties(properties);
|
|
8208
8364
|
}
|
|
8209
8365
|
function measureVolume$1(shape) {
|
|
8210
|
-
|
|
8366
|
+
const [r, gc] = localGC();
|
|
8367
|
+
const props = r(measureShapeVolumeProperties(shape));
|
|
8368
|
+
const v = props.volume;
|
|
8369
|
+
gc();
|
|
8370
|
+
return v;
|
|
8211
8371
|
}
|
|
8212
8372
|
function measureArea$1(shape) {
|
|
8213
|
-
|
|
8373
|
+
const [r, gc] = localGC();
|
|
8374
|
+
const props = r(measureShapeSurfaceProperties(shape));
|
|
8375
|
+
const a = props.area;
|
|
8376
|
+
gc();
|
|
8377
|
+
return a;
|
|
8214
8378
|
}
|
|
8215
8379
|
function measureLength$1(shape) {
|
|
8216
|
-
|
|
8380
|
+
const [r, gc] = localGC();
|
|
8381
|
+
const props = r(measureShapeLinearProperties(shape));
|
|
8382
|
+
const l = props.length;
|
|
8383
|
+
gc();
|
|
8384
|
+
return l;
|
|
8217
8385
|
}
|
|
8218
8386
|
class DistanceTool extends WrappingObj {
|
|
8219
8387
|
constructor() {
|
|
@@ -8221,17 +8389,22 @@ class DistanceTool extends WrappingObj {
|
|
|
8221
8389
|
super(new oc.BRepExtrema_DistShapeShape_1());
|
|
8222
8390
|
}
|
|
8223
8391
|
distanceBetween(shape1, shape2) {
|
|
8392
|
+
const [r, gc] = localGC();
|
|
8224
8393
|
this.wrapped.LoadS1(shape1.wrapped);
|
|
8225
8394
|
this.wrapped.LoadS2(shape2.wrapped);
|
|
8226
8395
|
const oc = getKernel().oc;
|
|
8227
|
-
const progress = new oc.Message_ProgressRange_1();
|
|
8396
|
+
const progress = r(new oc.Message_ProgressRange_1());
|
|
8228
8397
|
this.wrapped.Perform(progress);
|
|
8229
|
-
|
|
8398
|
+
gc();
|
|
8230
8399
|
return this.wrapped.Value();
|
|
8231
8400
|
}
|
|
8232
8401
|
}
|
|
8233
8402
|
function measureDistanceBetween(shape1, shape2) {
|
|
8234
|
-
|
|
8403
|
+
const [r, gc] = localGC();
|
|
8404
|
+
const tool = r(new DistanceTool());
|
|
8405
|
+
const dist = tool.distanceBetween(shape1, shape2);
|
|
8406
|
+
gc();
|
|
8407
|
+
return dist;
|
|
8235
8408
|
}
|
|
8236
8409
|
class DistanceQuery extends WrappingObj {
|
|
8237
8410
|
constructor(shape) {
|
|
@@ -8240,19 +8413,19 @@ class DistanceQuery extends WrappingObj {
|
|
|
8240
8413
|
this.wrapped.LoadS1(shape.wrapped);
|
|
8241
8414
|
}
|
|
8242
8415
|
distanceTo(shape) {
|
|
8416
|
+
const [r, gc] = localGC();
|
|
8243
8417
|
this.wrapped.LoadS2(shape.wrapped);
|
|
8244
8418
|
const oc = getKernel().oc;
|
|
8245
|
-
const progress = new oc.Message_ProgressRange_1();
|
|
8419
|
+
const progress = r(new oc.Message_ProgressRange_1());
|
|
8246
8420
|
this.wrapped.Perform(progress);
|
|
8247
|
-
|
|
8421
|
+
gc();
|
|
8248
8422
|
return this.wrapped.Value();
|
|
8249
8423
|
}
|
|
8250
8424
|
}
|
|
8251
|
-
const uniqueId$1 = () => Date.now().toString(36) + Math.random().toString(36).substring(2);
|
|
8252
8425
|
async function importSTEP$1(STEPBlob) {
|
|
8253
8426
|
const oc = getKernel().oc;
|
|
8254
8427
|
const [r, gc] = localGC();
|
|
8255
|
-
const fileName = uniqueId
|
|
8428
|
+
const fileName = uniqueId();
|
|
8256
8429
|
try {
|
|
8257
8430
|
const bufferView = new Uint8Array(await STEPBlob.arrayBuffer());
|
|
8258
8431
|
oc.FS.writeFile(`/${fileName}`, bufferView);
|
|
@@ -8274,7 +8447,7 @@ async function importSTEP$1(STEPBlob) {
|
|
|
8274
8447
|
async function importSTL$1(STLBlob) {
|
|
8275
8448
|
const oc = getKernel().oc;
|
|
8276
8449
|
const [r, gc] = localGC();
|
|
8277
|
-
const fileName = uniqueId
|
|
8450
|
+
const fileName = uniqueId();
|
|
8278
8451
|
try {
|
|
8279
8452
|
const bufferView = new Uint8Array(await STLBlob.arrayBuffer());
|
|
8280
8453
|
oc.FS.writeFile(`/${fileName}`, bufferView);
|
|
@@ -8315,6 +8488,10 @@ class Sketcher {
|
|
|
8315
8488
|
this.plane.delete();
|
|
8316
8489
|
this.pointer.delete();
|
|
8317
8490
|
this.firstPoint.delete();
|
|
8491
|
+
for (const edge of this.pendingEdges) {
|
|
8492
|
+
edge.delete();
|
|
8493
|
+
}
|
|
8494
|
+
this.pendingEdges = [];
|
|
8318
8495
|
}
|
|
8319
8496
|
_updatePointer(newPointer) {
|
|
8320
8497
|
this.pointer.delete();
|
|
@@ -8389,12 +8566,16 @@ class Sketcher {
|
|
|
8389
8566
|
);
|
|
8390
8567
|
}
|
|
8391
8568
|
tangentArcTo(end) {
|
|
8569
|
+
const [r, gc] = localGC();
|
|
8392
8570
|
const endPoint = this.plane.toWorldCoords(end);
|
|
8393
|
-
const previousEdge = this.pendingEdges[this.pendingEdges.length - 1];
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
);
|
|
8571
|
+
const previousEdge = this.pendingEdges.length ? this.pendingEdges[this.pendingEdges.length - 1] : null;
|
|
8572
|
+
if (!previousEdge)
|
|
8573
|
+
bug("Sketcher.tangentArcTo", "You need a previous edge to create a tangent arc");
|
|
8574
|
+
const prevEnd = r(previousEdge.endPoint);
|
|
8575
|
+
const prevTangent = r(previousEdge.tangentAt(1));
|
|
8576
|
+
this.pendingEdges.push(makeTangentArc(prevEnd, prevTangent, endPoint));
|
|
8397
8577
|
this._updatePointer(endPoint);
|
|
8578
|
+
gc();
|
|
8398
8579
|
return this;
|
|
8399
8580
|
}
|
|
8400
8581
|
tangentArc(xDist, yDist) {
|
|
@@ -8402,16 +8583,18 @@ class Sketcher {
|
|
|
8402
8583
|
return this.tangentArcTo([xDist + pointer.x, yDist + pointer.y]);
|
|
8403
8584
|
}
|
|
8404
8585
|
sagittaArcTo(end, sagitta) {
|
|
8586
|
+
const [r, gc] = localGC();
|
|
8405
8587
|
const startPoint = this.pointer;
|
|
8406
8588
|
const endPoint = this.plane.toWorldCoords(end);
|
|
8407
|
-
|
|
8408
|
-
const midPoint =
|
|
8409
|
-
|
|
8410
|
-
const sagDirection =
|
|
8411
|
-
const sagVector = sagDirection.multiply(sagitta);
|
|
8412
|
-
const sagPoint = midPoint.add(sagVector);
|
|
8589
|
+
const sum = r(endPoint.add(startPoint));
|
|
8590
|
+
const midPoint = r(sum.multiply(0.5));
|
|
8591
|
+
const diff = r(endPoint.sub(startPoint));
|
|
8592
|
+
const sagDirection = r(r(diff.cross(this.plane.zDir)).normalized());
|
|
8593
|
+
const sagVector = r(sagDirection.multiply(sagitta));
|
|
8594
|
+
const sagPoint = r(midPoint.add(sagVector));
|
|
8413
8595
|
this.pendingEdges.push(makeThreePointArc(this.pointer, sagPoint, endPoint));
|
|
8414
8596
|
this._updatePointer(endPoint);
|
|
8597
|
+
gc();
|
|
8415
8598
|
return this;
|
|
8416
8599
|
}
|
|
8417
8600
|
sagittaArc(xDist, yDist, sagitta) {
|
|
@@ -8569,10 +8752,13 @@ class Sketcher {
|
|
|
8569
8752
|
return this.smoothSplineTo([xDist + pointer.x, yDist + pointer.y], splineConfig);
|
|
8570
8753
|
}
|
|
8571
8754
|
_mirrorWireOnStartEnd(wire) {
|
|
8572
|
-
const
|
|
8573
|
-
const
|
|
8755
|
+
const [r, gc] = localGC();
|
|
8756
|
+
const diff = r(this.pointer.sub(this.firstPoint));
|
|
8757
|
+
const startToEndVector = r(diff.normalize());
|
|
8758
|
+
const normal = r(startToEndVector.cross(this.plane.zDir));
|
|
8574
8759
|
const mirroredWire = wire.clone().mirror(normal, this.pointer);
|
|
8575
8760
|
const combinedWire = unwrap(assembleWire$1([wire, mirroredWire]));
|
|
8761
|
+
gc();
|
|
8576
8762
|
return combinedWire;
|
|
8577
8763
|
}
|
|
8578
8764
|
buildWire() {
|
|
@@ -8607,32 +8793,19 @@ class Sketcher {
|
|
|
8607
8793
|
}
|
|
8608
8794
|
const guessFaceFromWires = (wires) => {
|
|
8609
8795
|
const oc = getKernel().oc;
|
|
8610
|
-
const
|
|
8611
|
-
|
|
8612
|
-
15,
|
|
8613
|
-
2,
|
|
8614
|
-
false,
|
|
8615
|
-
1e-5,
|
|
8616
|
-
1e-4,
|
|
8617
|
-
0.01,
|
|
8618
|
-
0.1,
|
|
8619
|
-
8,
|
|
8620
|
-
9
|
|
8796
|
+
const [r, gc] = localGC();
|
|
8797
|
+
const faceBuilder = r(
|
|
8798
|
+
new oc.BRepOffsetAPI_MakeFilling(3, 15, 2, false, 1e-5, 1e-4, 0.01, 0.1, 8, 9)
|
|
8621
8799
|
);
|
|
8622
8800
|
wires.forEach((wire, wireIndex) => {
|
|
8623
8801
|
wire.edges.forEach((edge) => {
|
|
8624
|
-
faceBuilder.Add_1(
|
|
8625
|
-
edge.wrapped,
|
|
8626
|
-
oc.GeomAbs_Shape.GeomAbs_C0,
|
|
8627
|
-
wireIndex === 0
|
|
8628
|
-
);
|
|
8802
|
+
faceBuilder.Add_1(edge.wrapped, oc.GeomAbs_Shape.GeomAbs_C0, wireIndex === 0);
|
|
8629
8803
|
});
|
|
8630
8804
|
});
|
|
8631
|
-
const progress = new oc.Message_ProgressRange_1();
|
|
8805
|
+
const progress = r(new oc.Message_ProgressRange_1());
|
|
8632
8806
|
faceBuilder.Build(progress);
|
|
8633
|
-
progress.delete();
|
|
8634
8807
|
const newFace = unwrap(cast(faceBuilder.Shape()));
|
|
8635
|
-
|
|
8808
|
+
gc();
|
|
8636
8809
|
if (!(newFace instanceof Face)) {
|
|
8637
8810
|
bug("guessFaceFromWires", "Failed to create a face");
|
|
8638
8811
|
}
|
|
@@ -8640,9 +8813,10 @@ const guessFaceFromWires = (wires) => {
|
|
|
8640
8813
|
};
|
|
8641
8814
|
const fixWire = (wire, baseFace) => {
|
|
8642
8815
|
const oc = getKernel().oc;
|
|
8643
|
-
const
|
|
8816
|
+
const [r, gc] = localGC();
|
|
8817
|
+
const wireFixer = r(new oc.ShapeFix_Wire_2(wire.wrapped, baseFace.wrapped, 1e-9));
|
|
8644
8818
|
wireFixer.FixEdgeCurves();
|
|
8645
|
-
|
|
8819
|
+
gc();
|
|
8646
8820
|
return wire;
|
|
8647
8821
|
};
|
|
8648
8822
|
const faceFromWires = (wires) => {
|
|
@@ -8710,41 +8884,39 @@ class CompoundSketch {
|
|
|
8710
8884
|
twistAngle,
|
|
8711
8885
|
origin
|
|
8712
8886
|
} = {}) {
|
|
8713
|
-
const
|
|
8714
|
-
const
|
|
8715
|
-
const
|
|
8716
|
-
|
|
8717
|
-
|
|
8718
|
-
|
|
8719
|
-
|
|
8720
|
-
|
|
8721
|
-
|
|
8722
|
-
|
|
8723
|
-
|
|
8724
|
-
|
|
8725
|
-
|
|
8726
|
-
|
|
8727
|
-
|
|
8728
|
-
|
|
8729
|
-
|
|
8730
|
-
|
|
8731
|
-
|
|
8732
|
-
|
|
8733
|
-
|
|
8734
|
-
|
|
8735
|
-
|
|
8736
|
-
|
|
8737
|
-
|
|
8738
|
-
|
|
8739
|
-
|
|
8740
|
-
|
|
8741
|
-
|
|
8742
|
-
|
|
8743
|
-
}
|
|
8744
|
-
return basicFaceExtrusion(this.face(), extrusionVec);
|
|
8745
|
-
} finally {
|
|
8746
|
-
extrusionVec.delete();
|
|
8887
|
+
const [r, gc] = localGC();
|
|
8888
|
+
const rawVec = r(new Vector(extrusionDirection || this.outerSketch.defaultDirection));
|
|
8889
|
+
const normVec = r(rawVec.normalized());
|
|
8890
|
+
const extrusionVec = r(normVec.multiply(extrusionDistance));
|
|
8891
|
+
let result;
|
|
8892
|
+
if (extrusionProfile && !twistAngle) {
|
|
8893
|
+
result = solidFromShellGenerator(
|
|
8894
|
+
this.sketches,
|
|
8895
|
+
(sketch) => complexExtrude$1(
|
|
8896
|
+
sketch.wire,
|
|
8897
|
+
origin || this.outerSketch.defaultOrigin,
|
|
8898
|
+
extrusionVec,
|
|
8899
|
+
extrusionProfile,
|
|
8900
|
+
true
|
|
8901
|
+
)
|
|
8902
|
+
);
|
|
8903
|
+
} else if (twistAngle) {
|
|
8904
|
+
result = solidFromShellGenerator(
|
|
8905
|
+
this.sketches,
|
|
8906
|
+
(sketch) => twistExtrude$1(
|
|
8907
|
+
sketch.wire,
|
|
8908
|
+
twistAngle,
|
|
8909
|
+
origin || this.outerSketch.defaultOrigin,
|
|
8910
|
+
extrusionVec,
|
|
8911
|
+
extrusionProfile,
|
|
8912
|
+
true
|
|
8913
|
+
)
|
|
8914
|
+
);
|
|
8915
|
+
} else {
|
|
8916
|
+
result = basicFaceExtrusion(this.face(), extrusionVec);
|
|
8747
8917
|
}
|
|
8918
|
+
gc();
|
|
8919
|
+
return result;
|
|
8748
8920
|
}
|
|
8749
8921
|
/**
|
|
8750
8922
|
* Revolves the drawing on an axis (defined by its direction and an origin
|
|
@@ -8913,69 +9085,16 @@ const makeBaseBox = (xLength, yLength, zLength) => {
|
|
|
8913
9085
|
};
|
|
8914
9086
|
const samePoint = (x, y) => samePoint$2(x, y, PRECISION_OFFSET * 10);
|
|
8915
9087
|
const getIntersectionPoint = (line1Start, line1End, line2Start, line2End) => {
|
|
8916
|
-
const
|
|
8917
|
-
|
|
8918
|
-
|
|
8919
|
-
|
|
8920
|
-
|
|
8921
|
-
]),
|
|
8922
|
-
determinant2x2([
|
|
8923
|
-
[line1Start[1], 1],
|
|
8924
|
-
[line1End[1], 1]
|
|
8925
|
-
])
|
|
8926
|
-
],
|
|
8927
|
-
[
|
|
8928
|
-
determinant2x2([
|
|
8929
|
-
[line2Start[0], 1],
|
|
8930
|
-
[line2End[0], 1]
|
|
8931
|
-
]),
|
|
8932
|
-
determinant2x2([
|
|
8933
|
-
[line2Start[1], 1],
|
|
8934
|
-
[line2End[1], 1]
|
|
8935
|
-
])
|
|
8936
|
-
]
|
|
8937
|
-
]);
|
|
9088
|
+
const dx1 = line1Start[0] - line1End[0];
|
|
9089
|
+
const dy1 = line1Start[1] - line1End[1];
|
|
9090
|
+
const dx2 = line2Start[0] - line2End[0];
|
|
9091
|
+
const dy2 = line2Start[1] - line2End[1];
|
|
9092
|
+
const denom = dx1 * dy2 - dy1 * dx2;
|
|
8938
9093
|
if (Math.abs(denom) < 1e-12) return null;
|
|
8939
|
-
const cross1 =
|
|
8940
|
-
|
|
8941
|
-
|
|
8942
|
-
|
|
8943
|
-
const cross2 = determinant2x2([
|
|
8944
|
-
[line2Start[0], line2Start[1]],
|
|
8945
|
-
[line2End[0], line2End[1]]
|
|
8946
|
-
]);
|
|
8947
|
-
const x = determinant2x2([
|
|
8948
|
-
[
|
|
8949
|
-
cross1,
|
|
8950
|
-
determinant2x2([
|
|
8951
|
-
[line1Start[0], 1],
|
|
8952
|
-
[line1End[0], 1]
|
|
8953
|
-
])
|
|
8954
|
-
],
|
|
8955
|
-
[
|
|
8956
|
-
cross2,
|
|
8957
|
-
determinant2x2([
|
|
8958
|
-
[line2Start[0], 1],
|
|
8959
|
-
[line2End[0], 1]
|
|
8960
|
-
])
|
|
8961
|
-
]
|
|
8962
|
-
]) / denom;
|
|
8963
|
-
const y = determinant2x2([
|
|
8964
|
-
[
|
|
8965
|
-
cross1,
|
|
8966
|
-
determinant2x2([
|
|
8967
|
-
[line1Start[1], 1],
|
|
8968
|
-
[line1End[1], 1]
|
|
8969
|
-
])
|
|
8970
|
-
],
|
|
8971
|
-
[
|
|
8972
|
-
cross2,
|
|
8973
|
-
determinant2x2([
|
|
8974
|
-
[line2Start[1], 1],
|
|
8975
|
-
[line2End[1], 1]
|
|
8976
|
-
])
|
|
8977
|
-
]
|
|
8978
|
-
]) / denom;
|
|
9094
|
+
const cross1 = line1Start[0] * line1End[1] - line1Start[1] * line1End[0];
|
|
9095
|
+
const cross2 = line2Start[0] * line2End[1] - line2Start[1] * line2End[0];
|
|
9096
|
+
const x = (cross1 * dx2 - cross2 * dx1) / denom;
|
|
9097
|
+
const y = (cross1 * dy2 - cross2 * dy1) / denom;
|
|
8979
9098
|
return [x, y];
|
|
8980
9099
|
};
|
|
8981
9100
|
function joinRound(appendCurve, previousLastPoint, firstPoint, previousCurve, _curve) {
|
|
@@ -9028,7 +9147,6 @@ function rawOffsets(blueprint, offset2, offsetConfig = {}) {
|
|
|
9028
9147
|
let savedLastCurve = null;
|
|
9029
9148
|
let previousCurve = offsetCurves.at(-1);
|
|
9030
9149
|
if (!previousCurve) return [];
|
|
9031
|
-
if (offsettedArray.length === 1) return offsettedArray;
|
|
9032
9150
|
function appendCurve(curve) {
|
|
9033
9151
|
if (curve instanceof Curve2D) {
|
|
9034
9152
|
offsettedArray.push(curve);
|
|
@@ -9231,6 +9349,17 @@ function fillet2D(shape, radius, finder) {
|
|
|
9231
9349
|
function chamfer2D(shape, radius, finder) {
|
|
9232
9350
|
return modifyCorner2D(chamferCurves, shape, radius, finder);
|
|
9233
9351
|
}
|
|
9352
|
+
function wrapSketchData(data) {
|
|
9353
|
+
const opts = {};
|
|
9354
|
+
if (data.defaultOrigin) opts.defaultOrigin = data.defaultOrigin;
|
|
9355
|
+
if (data.defaultDirection) opts.defaultDirection = data.defaultDirection;
|
|
9356
|
+
const sketch = new Sketch(data.wire, opts);
|
|
9357
|
+
if (data.baseFace) sketch.baseFace = data.baseFace;
|
|
9358
|
+
return sketch;
|
|
9359
|
+
}
|
|
9360
|
+
function wrapSketchDataArray(dataArr) {
|
|
9361
|
+
return new CompoundSketch(dataArr.map(wrapSketchData));
|
|
9362
|
+
}
|
|
9234
9363
|
const FONT_REGISTER = {};
|
|
9235
9364
|
async function loadFont(fontPath, fontFamily = "default", force = false) {
|
|
9236
9365
|
if (!force && FONT_REGISTER[fontFamily]) {
|
|
@@ -9294,20 +9423,12 @@ function textBlueprints(text, { startX = 0, startY = 0, fontSize = 16, fontFamil
|
|
|
9294
9423
|
const blueprints = Array.from(sketchFontCommands(writtenText.commands));
|
|
9295
9424
|
return organiseBlueprints(blueprints).mirror([0, 0]);
|
|
9296
9425
|
}
|
|
9297
|
-
function wrapSketchData$1(data) {
|
|
9298
|
-
const opts = {};
|
|
9299
|
-
if (data.defaultOrigin) opts.defaultOrigin = data.defaultOrigin;
|
|
9300
|
-
if (data.defaultDirection) opts.defaultDirection = data.defaultDirection;
|
|
9301
|
-
const sketch = new Sketch(data.wire, opts);
|
|
9302
|
-
if (data.baseFace) sketch.baseFace = data.baseFace;
|
|
9303
|
-
return sketch;
|
|
9304
|
-
}
|
|
9305
9426
|
function sketchText(text, textConfig, planeConfig = {}) {
|
|
9306
9427
|
const textBp = textBlueprints(text, textConfig);
|
|
9307
9428
|
const results = typeof planeConfig.plane === "string" || planeConfig.plane === void 0 ? textBp.sketchOnPlane(planeConfig.plane, planeConfig.origin) : textBp.sketchOnPlane(planeConfig.plane);
|
|
9308
9429
|
return new Sketches(
|
|
9309
9430
|
results.map(
|
|
9310
|
-
(item) => Array.isArray(item) ? new CompoundSketch(item.map(wrapSketchData
|
|
9431
|
+
(item) => Array.isArray(item) ? new CompoundSketch(item.map(wrapSketchData)) : wrapSketchData(item)
|
|
9311
9432
|
)
|
|
9312
9433
|
);
|
|
9313
9434
|
}
|
|
@@ -9330,28 +9451,32 @@ function isProjectionPlane(plane) {
|
|
|
9330
9451
|
}
|
|
9331
9452
|
function lookFromPlane(projectionPlane) {
|
|
9332
9453
|
const { dir, xAxis } = PROJECTION_PLANES[projectionPlane];
|
|
9333
|
-
return new ProjectionCamera(
|
|
9454
|
+
return new ProjectionCamera(
|
|
9455
|
+
[0, 0, 0],
|
|
9456
|
+
dir,
|
|
9457
|
+
xAxis
|
|
9458
|
+
);
|
|
9334
9459
|
}
|
|
9335
9460
|
function defaultXDir(direction) {
|
|
9336
|
-
const
|
|
9337
|
-
|
|
9461
|
+
const [r, gc] = localGC();
|
|
9462
|
+
const dir = r(new Vector(direction));
|
|
9463
|
+
let yAxis = r(new Vector([0, 0, 1]));
|
|
9338
9464
|
let xAxis = yAxis.cross(dir);
|
|
9339
9465
|
if (xAxis.Length === 0) {
|
|
9340
|
-
yAxis.delete();
|
|
9341
9466
|
xAxis.delete();
|
|
9342
|
-
yAxis = new Vector([0, 1, 0]);
|
|
9467
|
+
yAxis = r(new Vector([0, 1, 0]));
|
|
9343
9468
|
xAxis = yAxis.cross(dir);
|
|
9344
9469
|
}
|
|
9345
|
-
|
|
9346
|
-
yAxis.delete();
|
|
9470
|
+
gc();
|
|
9347
9471
|
return xAxis.normalize();
|
|
9348
9472
|
}
|
|
9349
9473
|
class ProjectionCamera extends WrappingObj {
|
|
9350
9474
|
constructor(position = [0, 0, 0], direction = [0, 0, 1], xAxis) {
|
|
9351
|
-
const
|
|
9475
|
+
const [r, gc] = localGC();
|
|
9476
|
+
const xDir = xAxis ? r(new Vector(xAxis)) : r(defaultXDir(direction));
|
|
9352
9477
|
const ax2 = makeAx2(position, direction, xDir);
|
|
9478
|
+
gc();
|
|
9353
9479
|
super(ax2);
|
|
9354
|
-
xDir.delete();
|
|
9355
9480
|
}
|
|
9356
9481
|
get position() {
|
|
9357
9482
|
return new Vector(this.wrapped.Location());
|
|
@@ -9366,32 +9491,47 @@ class ProjectionCamera extends WrappingObj {
|
|
|
9366
9491
|
return new Vector(this.wrapped.YDirection());
|
|
9367
9492
|
}
|
|
9368
9493
|
autoAxes() {
|
|
9369
|
-
const
|
|
9370
|
-
const
|
|
9371
|
-
|
|
9372
|
-
|
|
9373
|
-
|
|
9494
|
+
const [r, gc] = localGC();
|
|
9495
|
+
const dir = r(this.direction);
|
|
9496
|
+
const xAxis = r(defaultXDir(dir));
|
|
9497
|
+
const ocDir = r(asDir(xAxis));
|
|
9498
|
+
this.wrapped.SetXDirection(ocDir);
|
|
9499
|
+
gc();
|
|
9374
9500
|
}
|
|
9375
9501
|
setPosition(position) {
|
|
9376
|
-
|
|
9502
|
+
const [r, gc] = localGC();
|
|
9503
|
+
const pnt2 = r(asPnt(position));
|
|
9504
|
+
this.wrapped.SetLocation(pnt2);
|
|
9505
|
+
gc();
|
|
9377
9506
|
return this;
|
|
9378
9507
|
}
|
|
9379
9508
|
setXAxis(xAxis) {
|
|
9380
|
-
|
|
9509
|
+
const [r, gc] = localGC();
|
|
9510
|
+
const dir = r(asDir(xAxis));
|
|
9511
|
+
this.wrapped.SetXDirection(dir);
|
|
9512
|
+
gc();
|
|
9381
9513
|
return this;
|
|
9382
9514
|
}
|
|
9383
9515
|
setYAxis(yAxis) {
|
|
9384
|
-
|
|
9516
|
+
const [r, gc] = localGC();
|
|
9517
|
+
const dir = r(asDir(yAxis));
|
|
9518
|
+
this.wrapped.SetYDirection(dir);
|
|
9519
|
+
gc();
|
|
9385
9520
|
return this;
|
|
9386
9521
|
}
|
|
9387
9522
|
lookAt(shape) {
|
|
9388
|
-
const
|
|
9389
|
-
|
|
9523
|
+
const [r, gc] = localGC();
|
|
9524
|
+
const lookAtPoint = r(
|
|
9525
|
+
new Vector(
|
|
9526
|
+
"boundingBox" in shape ? shape.boundingBox.center : shape
|
|
9527
|
+
)
|
|
9390
9528
|
);
|
|
9391
|
-
const
|
|
9392
|
-
|
|
9393
|
-
|
|
9394
|
-
direction.
|
|
9529
|
+
const pos = r(this.position);
|
|
9530
|
+
const diff = r(pos.sub(lookAtPoint));
|
|
9531
|
+
const direction = r(diff.normalized());
|
|
9532
|
+
const ocDir = r(direction.toDir());
|
|
9533
|
+
this.wrapped.SetDirection(ocDir);
|
|
9534
|
+
gc();
|
|
9395
9535
|
this.autoAxes();
|
|
9396
9536
|
return this;
|
|
9397
9537
|
}
|
|
@@ -9409,7 +9549,9 @@ function makeProjectedEdges(shape, camera, withHiddenLines = true) {
|
|
|
9409
9549
|
hiddenLineRemoval.Projector_1(projector);
|
|
9410
9550
|
hiddenLineRemoval.Update();
|
|
9411
9551
|
hiddenLineRemoval.Hide_1();
|
|
9412
|
-
const hlrShapes =
|
|
9552
|
+
const hlrShapes = r(
|
|
9553
|
+
new oc.HLRBRep_HLRToShape(r(new oc.Handle_HLRBRep_Algo_2(hiddenLineRemoval)))
|
|
9554
|
+
);
|
|
9413
9555
|
const visible = [
|
|
9414
9556
|
...getEdges(hlrShapes.VCompound_1()),
|
|
9415
9557
|
...getEdges(hlrShapes.Rg1LineVCompound_1()),
|
|
@@ -9424,17 +9566,6 @@ function makeProjectedEdges(shape, camera, withHiddenLines = true) {
|
|
|
9424
9566
|
hidden.forEach((e) => oc.BRepLib.BuildCurves3d_2(e.wrapped));
|
|
9425
9567
|
return { visible, hidden };
|
|
9426
9568
|
}
|
|
9427
|
-
function wrapSketchData(data) {
|
|
9428
|
-
const opts = {};
|
|
9429
|
-
if (data.defaultOrigin) opts.defaultOrigin = data.defaultOrigin;
|
|
9430
|
-
if (data.defaultDirection) opts.defaultDirection = data.defaultDirection;
|
|
9431
|
-
const sketch = new Sketch(data.wire, opts);
|
|
9432
|
-
if (data.baseFace) sketch.baseFace = data.baseFace;
|
|
9433
|
-
return sketch;
|
|
9434
|
-
}
|
|
9435
|
-
function wrapSketchDataArray(dataArr) {
|
|
9436
|
-
return new CompoundSketch(dataArr.map(wrapSketchData));
|
|
9437
|
-
}
|
|
9438
9569
|
function wrapBlueprintResult(shape, result) {
|
|
9439
9570
|
if (shape instanceof Blueprint) {
|
|
9440
9571
|
return wrapSketchData(result);
|
|
@@ -9686,33 +9817,38 @@ const drawParametricFunction = (func, { pointsCount = 400, start = 0, stop = 1,
|
|
|
9686
9817
|
return drawPointsInterpolation(points, approximationConfig, { closeShape });
|
|
9687
9818
|
};
|
|
9688
9819
|
const edgesToDrawing = (edges) => {
|
|
9820
|
+
const [r, gc] = localGC();
|
|
9689
9821
|
const planeSketch = drawRectangle(1e3, 1e3).sketchOnPlane();
|
|
9690
|
-
const planeFace = unwrap(makeFace(planeSketch.wire));
|
|
9822
|
+
const planeFace = r(unwrap(makeFace(planeSketch.wire)));
|
|
9691
9823
|
const curves = edges.map((e) => edgeToCurve(e, planeFace));
|
|
9692
|
-
|
|
9824
|
+
gc();
|
|
9693
9825
|
const stitchedCurves = stitchCurves(curves).map((s) => new Blueprint(s));
|
|
9694
9826
|
if (stitchedCurves.length === 0) return new Drawing();
|
|
9695
9827
|
if (stitchedCurves.length === 1) return new Drawing(stitchedCurves[0]);
|
|
9696
9828
|
return new Drawing(new Blueprints(stitchedCurves));
|
|
9697
9829
|
};
|
|
9698
9830
|
function drawProjection(shape, projectionCamera = "front") {
|
|
9831
|
+
const [r, gc] = localGC();
|
|
9699
9832
|
let camera;
|
|
9700
|
-
|
|
9833
|
+
const ownCamera = !(projectionCamera instanceof ProjectionCamera);
|
|
9834
|
+
if (!ownCamera) {
|
|
9701
9835
|
camera = projectionCamera;
|
|
9702
9836
|
} else {
|
|
9703
|
-
camera = lookFromPlane(projectionCamera);
|
|
9837
|
+
camera = r(lookFromPlane(projectionCamera));
|
|
9704
9838
|
}
|
|
9705
9839
|
const { visible, hidden } = makeProjectedEdges(shape, camera);
|
|
9840
|
+
gc();
|
|
9706
9841
|
return {
|
|
9707
9842
|
visible: edgesToDrawing(visible),
|
|
9708
9843
|
hidden: edgesToDrawing(hidden)
|
|
9709
9844
|
};
|
|
9710
9845
|
}
|
|
9711
9846
|
function drawFaceOutline(face) {
|
|
9712
|
-
const
|
|
9713
|
-
const
|
|
9847
|
+
const [r, gc] = localGC();
|
|
9848
|
+
const clonedFace = r(face.clone());
|
|
9849
|
+
const outerWire2 = r(clonedFace.outerWire());
|
|
9714
9850
|
const curves = outerWire2.edges.map((e) => edgeToCurve(e, face));
|
|
9715
|
-
|
|
9851
|
+
gc();
|
|
9716
9852
|
const stitchedCurves = stitchCurves(curves).map((s) => new Blueprint(s));
|
|
9717
9853
|
if (stitchedCurves.length === 0) return new Drawing();
|
|
9718
9854
|
if (stitchedCurves.length === 1) return new Drawing(stitchedCurves[0]);
|
|
@@ -9783,7 +9919,7 @@ function mirrorDrawing(drawing, centerOrDirection, origin, mode) {
|
|
|
9783
9919
|
}
|
|
9784
9920
|
function createPlane(origin, xDirection = null, normal = [0, 0, 1]) {
|
|
9785
9921
|
const zDir = vecNormalize(normal);
|
|
9786
|
-
if (
|
|
9922
|
+
if (vecIsZero(zDir)) throw new Error("Plane normal must be non-zero");
|
|
9787
9923
|
let xDir;
|
|
9788
9924
|
if (!xDirection) {
|
|
9789
9925
|
const ax3 = makeOcAx3(origin, zDir);
|
|
@@ -9794,7 +9930,7 @@ function createPlane(origin, xDirection = null, normal = [0, 0, 1]) {
|
|
|
9794
9930
|
} else {
|
|
9795
9931
|
xDir = vecNormalize(xDirection);
|
|
9796
9932
|
}
|
|
9797
|
-
if (
|
|
9933
|
+
if (vecIsZero(xDir)) throw new Error("Plane xDir must be non-zero");
|
|
9798
9934
|
const yDir = vecNormalize(vecCross(zDir, xDir));
|
|
9799
9935
|
return { origin, xDir, yDir, zDir };
|
|
9800
9936
|
}
|
|
@@ -9843,16 +9979,12 @@ function pivotPlane(plane, angleDeg, axis = [1, 0, 0]) {
|
|
|
9843
9979
|
}
|
|
9844
9980
|
function makeSpineWire(start, end) {
|
|
9845
9981
|
const oc = getKernel().oc;
|
|
9846
|
-
const
|
|
9847
|
-
const
|
|
9848
|
-
const
|
|
9849
|
-
const
|
|
9850
|
-
const
|
|
9851
|
-
|
|
9852
|
-
wireMaker.delete();
|
|
9853
|
-
pnt1.delete();
|
|
9854
|
-
pnt2.delete();
|
|
9855
|
-
return wire;
|
|
9982
|
+
const r = gcWithScope();
|
|
9983
|
+
const pnt1 = r(toOcPnt(start));
|
|
9984
|
+
const pnt2 = r(toOcPnt(end));
|
|
9985
|
+
const edgeMaker = r(new oc.BRepBuilderAPI_MakeEdge_3(pnt1, pnt2));
|
|
9986
|
+
const wireMaker = r(new oc.BRepBuilderAPI_MakeWire_2(edgeMaker.Edge()));
|
|
9987
|
+
return castShape(wireMaker.Wire());
|
|
9856
9988
|
}
|
|
9857
9989
|
function makeHelixWire(pitch, height, radius, center, dir, lefthand = false) {
|
|
9858
9990
|
const oc = getKernel().oc;
|
|
@@ -9863,8 +9995,8 @@ function makeHelixWire(pitch, height, radius, center, dir, lefthand = false) {
|
|
|
9863
9995
|
new oc.Geom2d_Line_3(r(new oc.gp_Pnt2d_3(0, 0)), r(new oc.gp_Dir2d_4(myDir, pitch)))
|
|
9864
9996
|
);
|
|
9865
9997
|
const nTurns = height / pitch;
|
|
9866
|
-
const uStart = geomLine.Value(0);
|
|
9867
|
-
const uStop = geomLine.Value(nTurns * Math.sqrt((2 * Math.PI) ** 2 + pitch ** 2));
|
|
9998
|
+
const uStart = r(geomLine.Value(0));
|
|
9999
|
+
const uStop = r(geomLine.Value(nTurns * Math.sqrt((2 * Math.PI) ** 2 + pitch ** 2)));
|
|
9868
10000
|
const geomSeg = r(new oc.GCE2d_MakeSegment_1(uStart, uStop));
|
|
9869
10001
|
const ax3 = makeOcAx3(center, dir);
|
|
9870
10002
|
const geomSurf = new oc.Geom_CylindricalSurface_1(ax3, radius);
|
|
@@ -9881,12 +10013,10 @@ function makeHelixWire(pitch, height, radius, center, dir, lefthand = false) {
|
|
|
9881
10013
|
}
|
|
9882
10014
|
function extrudeFace(face, extrusionVec) {
|
|
9883
10015
|
const oc = getKernel().oc;
|
|
9884
|
-
const
|
|
9885
|
-
const
|
|
9886
|
-
const
|
|
9887
|
-
builder.
|
|
9888
|
-
vec2.delete();
|
|
9889
|
-
return solid;
|
|
10016
|
+
const r = gcWithScope();
|
|
10017
|
+
const vec2 = r(toOcVec(extrusionVec));
|
|
10018
|
+
const builder = r(new oc.BRepPrimAPI_MakePrism_1(face.wrapped, vec2, false, true));
|
|
10019
|
+
return createSolid(unwrap(downcast(builder.Shape())));
|
|
9890
10020
|
}
|
|
9891
10021
|
function revolveFace(face, center = [0, 0, 0], direction = [0, 0, 1], angle = 360) {
|
|
9892
10022
|
const oc = getKernel().oc;
|
|
@@ -9903,6 +10033,7 @@ function revolveFace(face, center = [0, 0, 0], direction = [0, 0, 1], angle = 36
|
|
|
9903
10033
|
}
|
|
9904
10034
|
function sweep(wire, spine, config = {}, shellMode = false) {
|
|
9905
10035
|
const oc = getKernel().oc;
|
|
10036
|
+
const r = gcWithScope();
|
|
9906
10037
|
const {
|
|
9907
10038
|
frenet = false,
|
|
9908
10039
|
auxiliarySpine,
|
|
@@ -9913,7 +10044,7 @@ function sweep(wire, spine, config = {}, shellMode = false) {
|
|
|
9913
10044
|
forceProfileSpineOthogonality
|
|
9914
10045
|
} = config;
|
|
9915
10046
|
const withCorrection = transitionMode === "round" ? true : !!forceProfileSpineOthogonality;
|
|
9916
|
-
const builder = new oc.BRepOffsetAPI_MakePipeShell(spine.wrapped);
|
|
10047
|
+
const builder = r(new oc.BRepOffsetAPI_MakePipeShell(spine.wrapped));
|
|
9917
10048
|
{
|
|
9918
10049
|
const mode = {
|
|
9919
10050
|
transformed: oc.BRepBuilderAPI_TransitionMode.BRepBuilderAPI_Transformed,
|
|
@@ -9932,20 +10063,16 @@ function sweep(wire, spine, config = {}, shellMode = false) {
|
|
|
9932
10063
|
}
|
|
9933
10064
|
if (!law) builder.Add_1(wire.wrapped, !!withContact, withCorrection);
|
|
9934
10065
|
else builder.SetLaw_1(wire.wrapped, law, !!withContact, withCorrection);
|
|
9935
|
-
const progress = new oc.Message_ProgressRange_1();
|
|
10066
|
+
const progress = r(new oc.Message_ProgressRange_1());
|
|
9936
10067
|
builder.Build(progress);
|
|
9937
10068
|
if (!shellMode) builder.MakeSolid();
|
|
9938
10069
|
const shape = castShape(builder.Shape());
|
|
9939
10070
|
if (!isShape3D(shape)) {
|
|
9940
|
-
builder.delete();
|
|
9941
|
-
progress.delete();
|
|
9942
10071
|
return err(typeCastError("SWEEP_NOT_3D", "Sweep did not produce a 3D shape"));
|
|
9943
10072
|
}
|
|
9944
10073
|
if (shellMode) {
|
|
9945
10074
|
const startWire = castShape(builder.FirstShape());
|
|
9946
10075
|
const endWire = castShape(builder.LastShape());
|
|
9947
|
-
builder.delete();
|
|
9948
|
-
progress.delete();
|
|
9949
10076
|
if (!isWire(startWire)) {
|
|
9950
10077
|
return err(typeCastError("SWEEP_START_NOT_WIRE", "Sweep did not produce a start Wire"));
|
|
9951
10078
|
}
|
|
@@ -9954,28 +10081,8 @@ function sweep(wire, spine, config = {}, shellMode = false) {
|
|
|
9954
10081
|
}
|
|
9955
10082
|
return ok([shape, startWire, endWire]);
|
|
9956
10083
|
}
|
|
9957
|
-
builder.delete();
|
|
9958
|
-
progress.delete();
|
|
9959
10084
|
return ok(shape);
|
|
9960
10085
|
}
|
|
9961
|
-
function buildLawFromProfile(extrusionLength, { profile, endFactor = 1 }) {
|
|
9962
|
-
const oc = getKernel().oc;
|
|
9963
|
-
let law;
|
|
9964
|
-
if (profile === "s-curve") {
|
|
9965
|
-
law = new oc.Law_S();
|
|
9966
|
-
law.Set_1(0, 1, extrusionLength, endFactor);
|
|
9967
|
-
} else if (profile === "linear") {
|
|
9968
|
-
law = new oc.Law_Linear();
|
|
9969
|
-
law.Set(0, 1, extrusionLength, endFactor);
|
|
9970
|
-
} else {
|
|
9971
|
-
return err(
|
|
9972
|
-
validationError("UNSUPPORTED_PROFILE", `Unsupported extrusion profile: ${String(profile)}`)
|
|
9973
|
-
);
|
|
9974
|
-
}
|
|
9975
|
-
const trimmed = law.Trim(0, extrusionLength, 1e-6);
|
|
9976
|
-
law.delete();
|
|
9977
|
-
return ok(trimmed);
|
|
9978
|
-
}
|
|
9979
10086
|
function supportExtrude(wire, center, normal, support) {
|
|
9980
10087
|
const endPoint = vecAdd(center, normal);
|
|
9981
10088
|
const spine = makeSpineWire(center, endPoint);
|
|
@@ -10021,116 +10128,83 @@ function loftWires(wires, { ruled = true, startPoint, endPoint } = {}, returnShe
|
|
|
10021
10128
|
}
|
|
10022
10129
|
return ok(result);
|
|
10023
10130
|
}
|
|
10024
|
-
function wrapString(str) {
|
|
10025
|
-
const oc = getKernel().oc;
|
|
10026
|
-
return new oc.TCollection_ExtendedString_2(str, true);
|
|
10027
|
-
}
|
|
10028
|
-
function parseSlice(hex, index) {
|
|
10029
|
-
return parseInt(hex.slice(index * 2, (index + 1) * 2), 16);
|
|
10030
|
-
}
|
|
10031
|
-
function colorFromHex(hex) {
|
|
10032
|
-
let color = hex;
|
|
10033
|
-
if (color.indexOf("#") === 0) color = color.slice(1);
|
|
10034
|
-
if (color.length === 3) {
|
|
10035
|
-
color = color.replace(/([0-9a-f])/gi, "$1$1");
|
|
10036
|
-
}
|
|
10037
|
-
return [parseSlice(color, 0), parseSlice(color, 1), parseSlice(color, 2)];
|
|
10038
|
-
}
|
|
10039
|
-
function wrapColor(hex, alpha = 1) {
|
|
10040
|
-
const oc = getKernel().oc;
|
|
10041
|
-
const [red, green, blue] = colorFromHex(hex);
|
|
10042
|
-
return new oc.Quantity_ColorRGBA_5(red / 255, green / 255, blue / 255, alpha);
|
|
10043
|
-
}
|
|
10044
10131
|
function exportAssemblySTEP(shapes = [], { unit, modelUnit } = {}) {
|
|
10045
10132
|
const oc = getKernel().oc;
|
|
10046
10133
|
const r = gcWithScope();
|
|
10047
10134
|
const doc = new oc.TDocStd_Document(wrapString("XmlOcaf"));
|
|
10048
|
-
|
|
10049
|
-
|
|
10050
|
-
|
|
10051
|
-
|
|
10052
|
-
|
|
10053
|
-
const
|
|
10054
|
-
|
|
10055
|
-
|
|
10056
|
-
|
|
10057
|
-
|
|
10058
|
-
|
|
10059
|
-
|
|
10135
|
+
try {
|
|
10136
|
+
oc.XCAFDoc_ShapeTool.SetAutoNaming(false);
|
|
10137
|
+
const mainLabel = doc.Main();
|
|
10138
|
+
const tool = oc.XCAFDoc_DocumentTool.ShapeTool(mainLabel).get();
|
|
10139
|
+
const ctool = oc.XCAFDoc_DocumentTool.ColorTool(mainLabel).get();
|
|
10140
|
+
for (const { shape, name, color, alpha } of shapes) {
|
|
10141
|
+
const shapeNode = tool.NewShape();
|
|
10142
|
+
tool.SetShape(shapeNode, shape.wrapped);
|
|
10143
|
+
oc.TDataStd_Name.Set_1(shapeNode, wrapString(name || uuidv()));
|
|
10144
|
+
ctool.SetColor_3(
|
|
10145
|
+
shapeNode,
|
|
10146
|
+
wrapColor(color || "#f00", alpha ?? 1),
|
|
10147
|
+
oc.XCAFDoc_ColorType.XCAFDoc_ColorSurf
|
|
10148
|
+
);
|
|
10149
|
+
}
|
|
10150
|
+
tool.UpdateAssemblies();
|
|
10151
|
+
configureStepUnits(unit, modelUnit, r);
|
|
10152
|
+
const session = r(new oc.XSControl_WorkSession());
|
|
10153
|
+
const writer = r(
|
|
10154
|
+
new oc.STEPCAFControl_Writer_2(r(new oc.Handle_XSControl_WorkSession_2(session)), false)
|
|
10060
10155
|
);
|
|
10156
|
+
configureStepWriter(writer);
|
|
10157
|
+
const progress = r(new oc.Message_ProgressRange_1());
|
|
10158
|
+
writer.Transfer_1(
|
|
10159
|
+
new oc.Handle_TDocStd_Document_2(doc),
|
|
10160
|
+
oc.STEPControl_StepModelType.STEPControl_AsIs,
|
|
10161
|
+
null,
|
|
10162
|
+
progress
|
|
10163
|
+
);
|
|
10164
|
+
const filename = uniqueIOFilename("_export", "step");
|
|
10165
|
+
const done = writer.Write(filename);
|
|
10166
|
+
if (done === oc.IFSelect_ReturnStatus.IFSelect_RetDone) {
|
|
10167
|
+
const file = oc.FS.readFile("/" + filename);
|
|
10168
|
+
oc.FS.unlink("/" + filename);
|
|
10169
|
+
return ok(new Blob([file], { type: "application/STEP" }));
|
|
10170
|
+
}
|
|
10171
|
+
return err(ioError("STEP_EXPORT_FAILED", "Failed to write STEP file"));
|
|
10172
|
+
} finally {
|
|
10173
|
+
doc.delete();
|
|
10061
10174
|
}
|
|
10062
|
-
tool.UpdateAssemblies();
|
|
10063
|
-
if (unit || modelUnit) {
|
|
10064
|
-
r(new oc.STEPCAFControl_Writer_1());
|
|
10065
|
-
oc.Interface_Static.SetCVal("xstep.cascade.unit", (modelUnit || unit || "MM").toUpperCase());
|
|
10066
|
-
oc.Interface_Static.SetCVal("write.step.unit", (unit || modelUnit || "MM").toUpperCase());
|
|
10067
|
-
}
|
|
10068
|
-
const session = r(new oc.XSControl_WorkSession());
|
|
10069
|
-
const writer = r(
|
|
10070
|
-
new oc.STEPCAFControl_Writer_2(r(new oc.Handle_XSControl_WorkSession_2(session)), false)
|
|
10071
|
-
);
|
|
10072
|
-
writer.SetColorMode(true);
|
|
10073
|
-
writer.SetLayerMode(true);
|
|
10074
|
-
writer.SetNameMode(true);
|
|
10075
|
-
oc.Interface_Static.SetIVal("write.surfacecurve.mode", true);
|
|
10076
|
-
oc.Interface_Static.SetIVal("write.precision.mode", 0);
|
|
10077
|
-
oc.Interface_Static.SetIVal("write.step.assembly", 2);
|
|
10078
|
-
oc.Interface_Static.SetIVal("write.step.schema", 5);
|
|
10079
|
-
const progress = r(new oc.Message_ProgressRange_1());
|
|
10080
|
-
writer.Transfer_1(
|
|
10081
|
-
new oc.Handle_TDocStd_Document_2(doc),
|
|
10082
|
-
oc.STEPControl_StepModelType.STEPControl_AsIs,
|
|
10083
|
-
null,
|
|
10084
|
-
progress
|
|
10085
|
-
);
|
|
10086
|
-
const filename = "export.step";
|
|
10087
|
-
const done = writer.Write(filename);
|
|
10088
|
-
doc.delete();
|
|
10089
|
-
if (done === oc.IFSelect_ReturnStatus.IFSelect_RetDone) {
|
|
10090
|
-
const file = oc.FS.readFile("/" + filename);
|
|
10091
|
-
oc.FS.unlink("/" + filename);
|
|
10092
|
-
return ok(new Blob([file], { type: "application/STEP" }));
|
|
10093
|
-
}
|
|
10094
|
-
return err(ioError("STEP_EXPORT_FAILED", "Failed to write STEP file"));
|
|
10095
10175
|
}
|
|
10096
10176
|
function measureVolumeProps(shape) {
|
|
10097
10177
|
const oc = getKernel().oc;
|
|
10098
|
-
const
|
|
10178
|
+
const r = gcWithScope();
|
|
10179
|
+
const props = r(new oc.GProp_GProps_1());
|
|
10099
10180
|
oc.BRepGProp.VolumeProperties_1(shape.wrapped, props, false, false, false);
|
|
10100
|
-
const pnt2 = props.CentreOfMass();
|
|
10101
|
-
|
|
10181
|
+
const pnt2 = r(props.CentreOfMass());
|
|
10182
|
+
return {
|
|
10102
10183
|
mass: props.Mass(),
|
|
10103
10184
|
centerOfMass: [pnt2.X(), pnt2.Y(), pnt2.Z()]
|
|
10104
10185
|
};
|
|
10105
|
-
pnt2.delete();
|
|
10106
|
-
props.delete();
|
|
10107
|
-
return result;
|
|
10108
10186
|
}
|
|
10109
10187
|
function measureSurfaceProps(shape) {
|
|
10110
10188
|
const oc = getKernel().oc;
|
|
10111
|
-
const
|
|
10189
|
+
const r = gcWithScope();
|
|
10190
|
+
const props = r(new oc.GProp_GProps_1());
|
|
10112
10191
|
oc.BRepGProp.SurfaceProperties_1(shape.wrapped, props, false, false);
|
|
10113
|
-
const pnt2 = props.CentreOfMass();
|
|
10114
|
-
|
|
10192
|
+
const pnt2 = r(props.CentreOfMass());
|
|
10193
|
+
return {
|
|
10115
10194
|
mass: props.Mass(),
|
|
10116
10195
|
centerOfMass: [pnt2.X(), pnt2.Y(), pnt2.Z()]
|
|
10117
10196
|
};
|
|
10118
|
-
pnt2.delete();
|
|
10119
|
-
props.delete();
|
|
10120
|
-
return result;
|
|
10121
10197
|
}
|
|
10122
10198
|
function measureLinearProps(shape) {
|
|
10123
10199
|
const oc = getKernel().oc;
|
|
10124
|
-
const
|
|
10200
|
+
const r = gcWithScope();
|
|
10201
|
+
const props = r(new oc.GProp_GProps_1());
|
|
10125
10202
|
oc.BRepGProp.LinearProperties(shape.wrapped, props, false, false);
|
|
10126
|
-
const pnt2 = props.CentreOfMass();
|
|
10127
|
-
|
|
10203
|
+
const pnt2 = r(props.CentreOfMass());
|
|
10204
|
+
return {
|
|
10128
10205
|
mass: props.Mass(),
|
|
10129
10206
|
centerOfMass: [pnt2.X(), pnt2.Y(), pnt2.Z()]
|
|
10130
10207
|
};
|
|
10131
|
-
pnt2.delete();
|
|
10132
|
-
props.delete();
|
|
10133
|
-
return result;
|
|
10134
10208
|
}
|
|
10135
10209
|
function measureVolume(shape) {
|
|
10136
10210
|
return measureVolumeProps(shape).mass;
|
|
@@ -10143,15 +10217,13 @@ function measureLength(shape) {
|
|
|
10143
10217
|
}
|
|
10144
10218
|
function measureDistance(shape1, shape2) {
|
|
10145
10219
|
const oc = getKernel().oc;
|
|
10146
|
-
const
|
|
10220
|
+
const r = gcWithScope();
|
|
10221
|
+
const distTool = r(new oc.BRepExtrema_DistShapeShape_1());
|
|
10147
10222
|
distTool.LoadS1(shape1.wrapped);
|
|
10148
10223
|
distTool.LoadS2(shape2.wrapped);
|
|
10149
|
-
const progress = new oc.Message_ProgressRange_1();
|
|
10224
|
+
const progress = r(new oc.Message_ProgressRange_1());
|
|
10150
10225
|
distTool.Perform(progress);
|
|
10151
|
-
|
|
10152
|
-
progress.delete();
|
|
10153
|
-
distTool.delete();
|
|
10154
|
-
return dist;
|
|
10226
|
+
return distTool.Value();
|
|
10155
10227
|
}
|
|
10156
10228
|
function createDistanceQuery(referenceShape) {
|
|
10157
10229
|
const oc = getKernel().oc;
|
|
@@ -10161,17 +10233,18 @@ function createDistanceQuery(referenceShape) {
|
|
|
10161
10233
|
distanceTo(other) {
|
|
10162
10234
|
distTool.LoadS2(other.wrapped);
|
|
10163
10235
|
const progress = new oc.Message_ProgressRange_1();
|
|
10164
|
-
|
|
10165
|
-
|
|
10166
|
-
|
|
10167
|
-
|
|
10236
|
+
try {
|
|
10237
|
+
distTool.Perform(progress);
|
|
10238
|
+
return distTool.Value();
|
|
10239
|
+
} finally {
|
|
10240
|
+
progress.delete();
|
|
10241
|
+
}
|
|
10168
10242
|
},
|
|
10169
10243
|
dispose() {
|
|
10170
10244
|
distTool.delete();
|
|
10171
10245
|
}
|
|
10172
10246
|
};
|
|
10173
10247
|
}
|
|
10174
|
-
const uniqueId = () => Date.now().toString(36) + Math.random().toString(36).substring(2);
|
|
10175
10248
|
async function importSTEP(blob) {
|
|
10176
10249
|
const oc = getKernel().oc;
|
|
10177
10250
|
const r = gcWithScope();
|
|
@@ -10185,6 +10258,9 @@ async function importSTEP(blob) {
|
|
|
10185
10258
|
}
|
|
10186
10259
|
reader.TransferRoots(r(new oc.Message_ProgressRange_1()));
|
|
10187
10260
|
const stepShape = reader.OneShape();
|
|
10261
|
+
if (stepShape.IsNull()) {
|
|
10262
|
+
return err(ioError("STEP_IMPORT_FAILED", "STEP file contains no valid geometry"));
|
|
10263
|
+
}
|
|
10188
10264
|
return ok(castShape(stepShape));
|
|
10189
10265
|
} finally {
|
|
10190
10266
|
try {
|
|
@@ -10293,15 +10369,13 @@ function createEdgeFinder(filters) {
|
|
|
10293
10369
|
const d = vecNormalize(resolveDir(dir));
|
|
10294
10370
|
return withFilter((edge) => {
|
|
10295
10371
|
const oc = getKernel().oc;
|
|
10296
|
-
const
|
|
10297
|
-
const
|
|
10298
|
-
const
|
|
10372
|
+
const r = gcWithScope();
|
|
10373
|
+
const adaptor = r(new oc.BRepAdaptor_Curve_2(edge.wrapped));
|
|
10374
|
+
const tmpPnt = r(new oc.gp_Pnt_1());
|
|
10375
|
+
const tmpVec = r(new oc.gp_Vec_1());
|
|
10299
10376
|
const mid = (Number(adaptor.FirstParameter()) + Number(adaptor.LastParameter())) / 2;
|
|
10300
10377
|
adaptor.D1(mid, tmpPnt, tmpVec);
|
|
10301
10378
|
const tangent = vecNormalize([tmpVec.X(), tmpVec.Y(), tmpVec.Z()]);
|
|
10302
|
-
tmpPnt.delete();
|
|
10303
|
-
tmpVec.delete();
|
|
10304
|
-
adaptor.delete();
|
|
10305
10379
|
const ang = Math.acos(Math.min(1, Math.abs(vecDot(tangent, d))));
|
|
10306
10380
|
return Math.abs(ang - DEG2RAD * angle) < 1e-6;
|
|
10307
10381
|
});
|
|
@@ -10309,24 +10383,20 @@ function createEdgeFinder(filters) {
|
|
|
10309
10383
|
ofLength: (length, tolerance = 1e-3) => withFilter((edge) => Math.abs(curveLength(edge) - length) < tolerance),
|
|
10310
10384
|
ofCurveType: (curveType) => withFilter((edge) => getCurveType(edge) === curveType),
|
|
10311
10385
|
parallelTo: (dir = "Z") => createEdgeFinder([...filters]).inDirection(dir, 0),
|
|
10312
|
-
atDistance: (distance, point = [0, 0, 0]) => {
|
|
10386
|
+
atDistance: (distance, point = [0, 0, 0]) => withFilter((edge) => {
|
|
10313
10387
|
const oc = getKernel().oc;
|
|
10314
|
-
const
|
|
10315
|
-
const
|
|
10388
|
+
const r = gcWithScope();
|
|
10389
|
+
const pnt2 = r(toOcPnt(point));
|
|
10390
|
+
const vtxMaker = r(new oc.BRepBuilderAPI_MakeVertex(pnt2));
|
|
10316
10391
|
const vtx = vtxMaker.Vertex();
|
|
10317
|
-
|
|
10318
|
-
pnt2.delete();
|
|
10319
|
-
const distTool = new oc.BRepExtrema_DistShapeShape_1();
|
|
10392
|
+
const distTool = r(new oc.BRepExtrema_DistShapeShape_1());
|
|
10320
10393
|
distTool.LoadS1(vtx);
|
|
10321
|
-
|
|
10322
|
-
|
|
10323
|
-
|
|
10324
|
-
|
|
10325
|
-
|
|
10326
|
-
|
|
10327
|
-
return Math.abs(d - distance) < 1e-6;
|
|
10328
|
-
});
|
|
10329
|
-
}
|
|
10394
|
+
distTool.LoadS2(edge.wrapped);
|
|
10395
|
+
const progress = r(new oc.Message_ProgressRange_1());
|
|
10396
|
+
distTool.Perform(progress);
|
|
10397
|
+
const d = distTool.Value();
|
|
10398
|
+
return Math.abs(d - distance) < 1e-6;
|
|
10399
|
+
})
|
|
10330
10400
|
};
|
|
10331
10401
|
}
|
|
10332
10402
|
function faceFinder() {
|
|
@@ -10353,24 +10423,20 @@ function createFaceFinder(filters) {
|
|
|
10353
10423
|
},
|
|
10354
10424
|
parallelTo: (dir = "Z") => createFaceFinder([...filters]).inDirection(dir, 0),
|
|
10355
10425
|
ofSurfaceType: (surfaceType) => withFilter((face) => unwrap(getSurfaceType(face)) === surfaceType),
|
|
10356
|
-
atDistance: (distance, point = [0, 0, 0]) => {
|
|
10426
|
+
atDistance: (distance, point = [0, 0, 0]) => withFilter((face) => {
|
|
10357
10427
|
const oc = getKernel().oc;
|
|
10358
|
-
const
|
|
10359
|
-
const
|
|
10428
|
+
const r = gcWithScope();
|
|
10429
|
+
const pnt2 = r(toOcPnt(point));
|
|
10430
|
+
const vtxMaker = r(new oc.BRepBuilderAPI_MakeVertex(pnt2));
|
|
10360
10431
|
const vtx = vtxMaker.Vertex();
|
|
10361
|
-
|
|
10362
|
-
pnt2.delete();
|
|
10363
|
-
const distTool = new oc.BRepExtrema_DistShapeShape_1();
|
|
10432
|
+
const distTool = r(new oc.BRepExtrema_DistShapeShape_1());
|
|
10364
10433
|
distTool.LoadS1(vtx);
|
|
10365
|
-
|
|
10366
|
-
|
|
10367
|
-
|
|
10368
|
-
|
|
10369
|
-
|
|
10370
|
-
|
|
10371
|
-
return Math.abs(d - distance) < 1e-6;
|
|
10372
|
-
});
|
|
10373
|
-
}
|
|
10434
|
+
distTool.LoadS2(face.wrapped);
|
|
10435
|
+
const progress = r(new oc.Message_ProgressRange_1());
|
|
10436
|
+
distTool.Perform(progress);
|
|
10437
|
+
const d = distTool.Value();
|
|
10438
|
+
return Math.abs(d - distance) < 1e-6;
|
|
10439
|
+
})
|
|
10374
10440
|
};
|
|
10375
10441
|
}
|
|
10376
10442
|
function createCamera(position = [0, 0, 0], direction = [0, 0, 1], xAxis) {
|
|
@@ -10396,23 +10462,8 @@ function cameraLookAt(camera, target) {
|
|
|
10396
10462
|
const direction = vecNormalize(vecSub(camera.position, target));
|
|
10397
10463
|
return createCamera(camera.position, direction);
|
|
10398
10464
|
}
|
|
10399
|
-
const PLANE_MAP = {
|
|
10400
|
-
XY: { dir: [0, 0, 1], xAxis: [1, 0, 0] },
|
|
10401
|
-
XZ: { dir: [0, -1, 0], xAxis: [1, 0, 0] },
|
|
10402
|
-
YZ: { dir: [1, 0, 0], xAxis: [0, 1, 0] },
|
|
10403
|
-
YX: { dir: [0, 0, -1], xAxis: [0, 1, 0] },
|
|
10404
|
-
ZX: { dir: [0, 1, 0], xAxis: [0, 0, 1] },
|
|
10405
|
-
ZY: { dir: [-1, 0, 0], xAxis: [0, 0, 1] },
|
|
10406
|
-
front: { dir: [0, -1, 0], xAxis: [1, 0, 0] },
|
|
10407
|
-
back: { dir: [0, 1, 0], xAxis: [-1, 0, 0] },
|
|
10408
|
-
right: { dir: [-1, 0, 0], xAxis: [0, -1, 0] },
|
|
10409
|
-
left: { dir: [1, 0, 0], xAxis: [0, 1, 0] },
|
|
10410
|
-
bottom: { dir: [0, 0, 1], xAxis: [1, 0, 0] },
|
|
10411
|
-
top: { dir: [0, 0, -1], xAxis: [1, 0, 0] }
|
|
10412
|
-
};
|
|
10413
10465
|
function cameraFromPlane(planeName) {
|
|
10414
|
-
const config =
|
|
10415
|
-
if (!config) throw new Error(`Unknown projection plane: ${planeName}`);
|
|
10466
|
+
const config = PROJECTION_PLANES[planeName];
|
|
10416
10467
|
return createCamera([0, 0, 0], config.dir, config.xAxis);
|
|
10417
10468
|
}
|
|
10418
10469
|
function cameraToProjectionCamera(camera) {
|
|
@@ -10626,6 +10677,8 @@ exports.fuseAllShapes = fuseAllShapes;
|
|
|
10626
10677
|
exports.fuseBlueprint2D = fuseBlueprint2D;
|
|
10627
10678
|
exports.fuseBlueprints = fuseBlueprints;
|
|
10628
10679
|
exports.fuseShapes = fuseShapes;
|
|
10680
|
+
exports.gcWithObject = gcWithObject;
|
|
10681
|
+
exports.gcWithScope = gcWithScope;
|
|
10629
10682
|
exports.genericSweep = genericSweep;
|
|
10630
10683
|
exports.getBounds = getBounds;
|
|
10631
10684
|
exports.getEdges = getEdges$1;
|