brepjs-sheetmetal 0.4.2 → 0.4.4
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-sheetmetal.cjs +28 -36
- package/dist/brepjs-sheetmetal.js +28 -36
- package/dist/miterFns.d.ts +4 -4
- package/package.json +2 -2
|
@@ -2944,29 +2944,13 @@ function buildWedge$1(axisOrigin, thetaDeg, outerR, width, direction) {
|
|
|
2944
2944
|
}
|
|
2945
2945
|
/** The flange flat, built lying along +X past the bend, then folded to angle θ. */
|
|
2946
2946
|
function buildFlangeFlat(axisOrigin, thetaDeg, width, thickness, length, direction) {
|
|
2947
|
-
if (direction === "up") {
|
|
2948
|
-
const flat = (0, brepjs.box)(length, width, thickness);
|
|
2949
|
-
const positioned = (0, brepjs.translate)(flat, [
|
|
2950
|
-
axisOrigin[0],
|
|
2951
|
-
axisOrigin[1],
|
|
2952
|
-
0
|
|
2953
|
-
]);
|
|
2954
|
-
return (0, brepjs.rotate)(positioned, -thetaDeg, {
|
|
2955
|
-
at: axisOrigin,
|
|
2956
|
-
axis: [
|
|
2957
|
-
0,
|
|
2958
|
-
1,
|
|
2959
|
-
0
|
|
2960
|
-
]
|
|
2961
|
-
});
|
|
2962
|
-
}
|
|
2963
2947
|
const flat = (0, brepjs.box)(length, width, thickness);
|
|
2964
2948
|
const positioned = (0, brepjs.translate)(flat, [
|
|
2965
2949
|
axisOrigin[0],
|
|
2966
2950
|
axisOrigin[1],
|
|
2967
|
-
|
|
2951
|
+
0
|
|
2968
2952
|
]);
|
|
2969
|
-
return (0, brepjs.rotate)(positioned, thetaDeg, {
|
|
2953
|
+
return (0, brepjs.rotate)(positioned, (direction === "up" ? -1 : 1) * thetaDeg, {
|
|
2970
2954
|
at: axisOrigin,
|
|
2971
2955
|
axis: [
|
|
2972
2956
|
0,
|
|
@@ -4869,10 +4853,10 @@ function miterCut(part, plane) {
|
|
|
4869
4853
|
});
|
|
4870
4854
|
}
|
|
4871
4855
|
/**
|
|
4872
|
-
* Auto corner-miter between two adjacent flanges. The miter plane
|
|
4873
|
-
*
|
|
4874
|
-
*
|
|
4875
|
-
*
|
|
4856
|
+
* Auto corner-miter between two adjacent flanges. The miter plane is vertical at
|
|
4857
|
+
* their shared corner, bisects the two directions that point out of the part, and
|
|
4858
|
+
* is offset outward by half the gap. The single cut trims the ends of both flanges
|
|
4859
|
+
* to a clean mitered corner and leaves the base flat and the bend lines whole.
|
|
4876
4860
|
*/
|
|
4877
4861
|
function autoMiterCorner(part, flangeIdA, flangeIdB, gap = 0) {
|
|
4878
4862
|
if (part.solid === void 0) return (0, brepjs.err)((0, brepjs.validationError)("NO_SOLID", "autoMiterCorner: part has no folded solid"));
|
|
@@ -4883,7 +4867,7 @@ function autoMiterCorner(part, flangeIdA, flangeIdB, gap = 0) {
|
|
|
4883
4867
|
const axisA = (0, brepjs.vecNormalize)(bendA.axisDir);
|
|
4884
4868
|
const axisB = (0, brepjs.vecNormalize)(bendB.axisDir);
|
|
4885
4869
|
const corner = cornerPoint(bendA.axisOrigin, axisA, bendB.axisOrigin, axisB);
|
|
4886
|
-
const planeNormal = miterNormal(axisA, axisB);
|
|
4870
|
+
const planeNormal = miterNormal(axisA, bendLineMid(part, bendA, axisA), axisB, bendLineMid(part, bendB, axisB), corner);
|
|
4887
4871
|
if (planeNormal === void 0) return (0, brepjs.err)((0, brepjs.validationError)("PARALLEL_FLANGES", "autoMiterCorner: flange bend axes are parallel; no corner to miter"));
|
|
4888
4872
|
const cutResult = miterCut(part, {
|
|
4889
4873
|
origin: (0, brepjs.vecAdd)(corner, (0, brepjs.vecScale)(planeNormal, gap * .5)),
|
|
@@ -4912,19 +4896,27 @@ function cornerPoint(originA, dirA, originB, dirB) {
|
|
|
4912
4896
|
const sc = (b * e - c * d) / denom;
|
|
4913
4897
|
return (0, brepjs.vecAdd)(originA, (0, brepjs.vecScale)(dirA, sc));
|
|
4914
4898
|
}
|
|
4915
|
-
/**
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4927
|
-
|
|
4899
|
+
/** Midpoint of a bend line. The line starts at the axis origin and runs the span of its flange. */
|
|
4900
|
+
function bendLineMid(part, bend, axis) {
|
|
4901
|
+
const span = part.flanges.find((f) => f.id === bend.id)?.span ?? 0;
|
|
4902
|
+
return (0, brepjs.vecAdd)(bend.axisOrigin, (0, brepjs.vecScale)(axis, span / 2));
|
|
4903
|
+
}
|
|
4904
|
+
/**
|
|
4905
|
+
* Normal of the miter plane between two flanges whose bend axes are `dirA`/`dirB`:
|
|
4906
|
+
* the bisector of the two directions that point out of the part. The outward
|
|
4907
|
+
* direction of a flange is perpendicular to its bend axis in the plane of the two
|
|
4908
|
+
* axes, and points away from the bend line of the other flange (`midA`/`midB` are
|
|
4909
|
+
* the midpoints of the two bend lines). The bend axes do not give this direction:
|
|
4910
|
+
* their sum lies along the diagonal of the part, and a cut there removes half of it.
|
|
4911
|
+
*/
|
|
4912
|
+
function miterNormal(dirA, midA, dirB, midB, corner) {
|
|
4913
|
+
const up = (0, brepjs.vecCross)(dirA, dirB);
|
|
4914
|
+
if (Math.hypot(up[0], up[1], up[2]) < 1e-9) return void 0;
|
|
4915
|
+
const outward = (dir, otherMid) => {
|
|
4916
|
+
const run = (0, brepjs.vecNormalize)((0, brepjs.vecCross)(dir, up));
|
|
4917
|
+
return (0, brepjs.vecDot)(run, (0, brepjs.vecSub)(otherMid, corner)) > 0 ? (0, brepjs.vecScale)(run, -1) : run;
|
|
4918
|
+
};
|
|
4919
|
+
return (0, brepjs.vecNormalize)((0, brepjs.vecAdd)(outward(dirA, midB), outward(dirB, midA)));
|
|
4928
4920
|
}
|
|
4929
4921
|
var Z_AXIS = [
|
|
4930
4922
|
0,
|
|
@@ -2943,29 +2943,13 @@ function buildWedge$1(axisOrigin, thetaDeg, outerR, width, direction) {
|
|
|
2943
2943
|
}
|
|
2944
2944
|
/** The flange flat, built lying along +X past the bend, then folded to angle θ. */
|
|
2945
2945
|
function buildFlangeFlat(axisOrigin, thetaDeg, width, thickness, length, direction) {
|
|
2946
|
-
if (direction === "up") {
|
|
2947
|
-
const flat = box(length, width, thickness);
|
|
2948
|
-
const positioned = translate(flat, [
|
|
2949
|
-
axisOrigin[0],
|
|
2950
|
-
axisOrigin[1],
|
|
2951
|
-
0
|
|
2952
|
-
]);
|
|
2953
|
-
return rotate(positioned, -thetaDeg, {
|
|
2954
|
-
at: axisOrigin,
|
|
2955
|
-
axis: [
|
|
2956
|
-
0,
|
|
2957
|
-
1,
|
|
2958
|
-
0
|
|
2959
|
-
]
|
|
2960
|
-
});
|
|
2961
|
-
}
|
|
2962
2946
|
const flat = box(length, width, thickness);
|
|
2963
2947
|
const positioned = translate(flat, [
|
|
2964
2948
|
axisOrigin[0],
|
|
2965
2949
|
axisOrigin[1],
|
|
2966
|
-
|
|
2950
|
+
0
|
|
2967
2951
|
]);
|
|
2968
|
-
return rotate(positioned, thetaDeg, {
|
|
2952
|
+
return rotate(positioned, (direction === "up" ? -1 : 1) * thetaDeg, {
|
|
2969
2953
|
at: axisOrigin,
|
|
2970
2954
|
axis: [
|
|
2971
2955
|
0,
|
|
@@ -4868,10 +4852,10 @@ function miterCut(part, plane) {
|
|
|
4868
4852
|
});
|
|
4869
4853
|
}
|
|
4870
4854
|
/**
|
|
4871
|
-
* Auto corner-miter between two adjacent flanges. The miter plane
|
|
4872
|
-
*
|
|
4873
|
-
*
|
|
4874
|
-
*
|
|
4855
|
+
* Auto corner-miter between two adjacent flanges. The miter plane is vertical at
|
|
4856
|
+
* their shared corner, bisects the two directions that point out of the part, and
|
|
4857
|
+
* is offset outward by half the gap. The single cut trims the ends of both flanges
|
|
4858
|
+
* to a clean mitered corner and leaves the base flat and the bend lines whole.
|
|
4875
4859
|
*/
|
|
4876
4860
|
function autoMiterCorner(part, flangeIdA, flangeIdB, gap = 0) {
|
|
4877
4861
|
if (part.solid === void 0) return err(validationError("NO_SOLID", "autoMiterCorner: part has no folded solid"));
|
|
@@ -4882,7 +4866,7 @@ function autoMiterCorner(part, flangeIdA, flangeIdB, gap = 0) {
|
|
|
4882
4866
|
const axisA = vecNormalize(bendA.axisDir);
|
|
4883
4867
|
const axisB = vecNormalize(bendB.axisDir);
|
|
4884
4868
|
const corner = cornerPoint(bendA.axisOrigin, axisA, bendB.axisOrigin, axisB);
|
|
4885
|
-
const planeNormal = miterNormal(axisA, axisB);
|
|
4869
|
+
const planeNormal = miterNormal(axisA, bendLineMid(part, bendA, axisA), axisB, bendLineMid(part, bendB, axisB), corner);
|
|
4886
4870
|
if (planeNormal === void 0) return err(validationError("PARALLEL_FLANGES", "autoMiterCorner: flange bend axes are parallel; no corner to miter"));
|
|
4887
4871
|
const cutResult = miterCut(part, {
|
|
4888
4872
|
origin: vecAdd(corner, vecScale(planeNormal, gap * .5)),
|
|
@@ -4911,19 +4895,27 @@ function cornerPoint(originA, dirA, originB, dirB) {
|
|
|
4911
4895
|
const sc = (b * e - c * d) / denom;
|
|
4912
4896
|
return vecAdd(originA, vecScale(dirA, sc));
|
|
4913
4897
|
}
|
|
4914
|
-
/**
|
|
4915
|
-
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
|
|
4898
|
+
/** Midpoint of a bend line. The line starts at the axis origin and runs the span of its flange. */
|
|
4899
|
+
function bendLineMid(part, bend, axis) {
|
|
4900
|
+
const span = part.flanges.find((f) => f.id === bend.id)?.span ?? 0;
|
|
4901
|
+
return vecAdd(bend.axisOrigin, vecScale(axis, span / 2));
|
|
4902
|
+
}
|
|
4903
|
+
/**
|
|
4904
|
+
* Normal of the miter plane between two flanges whose bend axes are `dirA`/`dirB`:
|
|
4905
|
+
* the bisector of the two directions that point out of the part. The outward
|
|
4906
|
+
* direction of a flange is perpendicular to its bend axis in the plane of the two
|
|
4907
|
+
* axes, and points away from the bend line of the other flange (`midA`/`midB` are
|
|
4908
|
+
* the midpoints of the two bend lines). The bend axes do not give this direction:
|
|
4909
|
+
* their sum lies along the diagonal of the part, and a cut there removes half of it.
|
|
4910
|
+
*/
|
|
4911
|
+
function miterNormal(dirA, midA, dirB, midB, corner) {
|
|
4912
|
+
const up = vecCross(dirA, dirB);
|
|
4913
|
+
if (Math.hypot(up[0], up[1], up[2]) < 1e-9) return void 0;
|
|
4914
|
+
const outward = (dir, otherMid) => {
|
|
4915
|
+
const run = vecNormalize(vecCross(dir, up));
|
|
4916
|
+
return vecDot(run, vecSub(otherMid, corner)) > 0 ? vecScale(run, -1) : run;
|
|
4917
|
+
};
|
|
4918
|
+
return vecNormalize(vecAdd(outward(dirA, midB), outward(dirB, midA)));
|
|
4927
4919
|
}
|
|
4928
4920
|
var Z_AXIS = [
|
|
4929
4921
|
0,
|
package/dist/miterFns.d.ts
CHANGED
|
@@ -12,9 +12,9 @@ export interface MiterPlane {
|
|
|
12
12
|
*/
|
|
13
13
|
export declare function miterCut(part: SheetMetalPart, plane: MiterPlane): Result<SheetMetalPart>;
|
|
14
14
|
/**
|
|
15
|
-
* Auto corner-miter between two adjacent flanges. The miter plane
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
15
|
+
* Auto corner-miter between two adjacent flanges. The miter plane is vertical at
|
|
16
|
+
* their shared corner, bisects the two directions that point out of the part, and
|
|
17
|
+
* is offset outward by half the gap. The single cut trims the ends of both flanges
|
|
18
|
+
* to a clean mitered corner and leaves the base flat and the bend lines whole.
|
|
19
19
|
*/
|
|
20
20
|
export declare function autoMiterCorner(part: SheetMetalPart, flangeIdA: string, flangeIdB: string, gap?: number): Result<SheetMetalPart>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brepjs-sheetmetal",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"description": "Sheet-metal CAD domain for brepjs — flange authoring, auto-miter, fold/unfold flat patterns",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sheet-metal",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@eslint/js": "*",
|
|
56
|
-
"@types/node": "26.6.
|
|
56
|
+
"@types/node": "26.6.6",
|
|
57
57
|
"eslint": "*",
|
|
58
58
|
"tsx": "4.23.15",
|
|
59
59
|
"typescript": "*",
|