brepjs-sheetmetal 0.4.2 → 0.4.3

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.
@@ -4869,10 +4869,10 @@ function miterCut(part, plane) {
4869
4869
  });
4870
4870
  }
4871
4871
  /**
4872
- * Auto corner-miter between two adjacent flanges. The miter plane bisects the two
4873
- * flanges' fold-up directions at their shared corner and is offset by half the gap,
4874
- * so the cut falls on the flat/flange regions and never crosses a bend patch. The
4875
- * single bisector cut trims both flanges to a clean mitered corner.
4872
+ * Auto corner-miter between two adjacent flanges. The miter plane is vertical at
4873
+ * their shared corner, bisects the two directions that point out of the part, and
4874
+ * is offset outward by half the gap. The single cut trims the ends of both flanges
4875
+ * to a clean mitered corner and leaves the base flat and the bend lines whole.
4876
4876
  */
4877
4877
  function autoMiterCorner(part, flangeIdA, flangeIdB, gap = 0) {
4878
4878
  if (part.solid === void 0) return (0, brepjs.err)((0, brepjs.validationError)("NO_SOLID", "autoMiterCorner: part has no folded solid"));
@@ -4883,7 +4883,7 @@ function autoMiterCorner(part, flangeIdA, flangeIdB, gap = 0) {
4883
4883
  const axisA = (0, brepjs.vecNormalize)(bendA.axisDir);
4884
4884
  const axisB = (0, brepjs.vecNormalize)(bendB.axisDir);
4885
4885
  const corner = cornerPoint(bendA.axisOrigin, axisA, bendB.axisOrigin, axisB);
4886
- const planeNormal = miterNormal(axisA, axisB);
4886
+ const planeNormal = miterNormal(axisA, bendLineMid(part, bendA, axisA), axisB, bendLineMid(part, bendB, axisB), corner);
4887
4887
  if (planeNormal === void 0) return (0, brepjs.err)((0, brepjs.validationError)("PARALLEL_FLANGES", "autoMiterCorner: flange bend axes are parallel; no corner to miter"));
4888
4888
  const cutResult = miterCut(part, {
4889
4889
  origin: (0, brepjs.vecAdd)(corner, (0, brepjs.vecScale)(planeNormal, gap * .5)),
@@ -4912,19 +4912,27 @@ function cornerPoint(originA, dirA, originB, dirB) {
4912
4912
  const sc = (b * e - c * d) / denom;
4913
4913
  return (0, brepjs.vecAdd)(originA, (0, brepjs.vecScale)(dirA, sc));
4914
4914
  }
4915
- /**
4916
- * Normal of the miter plane between two flanges whose bend axes are `dirA`/`dirB`.
4917
- * The plane is spanned by the two axes (it contains the corner edge of each
4918
- * flange); its normal is `dirA × dirB` rotated to bisect — equivalently the
4919
- * normalized sum of the two run directions, which both lie perpendicular to the
4920
- * respective axis in the part's run plane.
4921
- */
4922
- function miterNormal(dirA, dirB) {
4923
- const cross = (0, brepjs.vecCross)(dirA, dirB);
4924
- if (Math.hypot(cross[0], cross[1], cross[2]) < 1e-9) return void 0;
4925
- const sum = (0, brepjs.vecAdd)(dirA, dirB);
4926
- if (Math.hypot(sum[0], sum[1], sum[2]) < 1e-9) return (0, brepjs.vecNormalize)(cross);
4927
- return (0, brepjs.vecNormalize)(sum);
4915
+ /** Midpoint of a bend line. The line starts at the axis origin and runs the span of its flange. */
4916
+ function bendLineMid(part, bend, axis) {
4917
+ const span = part.flanges.find((f) => f.id === bend.id)?.span ?? 0;
4918
+ return (0, brepjs.vecAdd)(bend.axisOrigin, (0, brepjs.vecScale)(axis, span / 2));
4919
+ }
4920
+ /**
4921
+ * Normal of the miter plane between two flanges whose bend axes are `dirA`/`dirB`:
4922
+ * the bisector of the two directions that point out of the part. The outward
4923
+ * direction of a flange is perpendicular to its bend axis in the plane of the two
4924
+ * axes, and points away from the bend line of the other flange (`midA`/`midB` are
4925
+ * the midpoints of the two bend lines). The bend axes do not give this direction:
4926
+ * their sum lies along the diagonal of the part, and a cut there removes half of it.
4927
+ */
4928
+ function miterNormal(dirA, midA, dirB, midB, corner) {
4929
+ const up = (0, brepjs.vecCross)(dirA, dirB);
4930
+ if (Math.hypot(up[0], up[1], up[2]) < 1e-9) return void 0;
4931
+ const outward = (dir, otherMid) => {
4932
+ const run = (0, brepjs.vecNormalize)((0, brepjs.vecCross)(dir, up));
4933
+ return (0, brepjs.vecDot)(run, (0, brepjs.vecSub)(otherMid, corner)) > 0 ? (0, brepjs.vecScale)(run, -1) : run;
4934
+ };
4935
+ return (0, brepjs.vecNormalize)((0, brepjs.vecAdd)(outward(dirA, midB), outward(dirB, midA)));
4928
4936
  }
4929
4937
  var Z_AXIS = [
4930
4938
  0,
@@ -4868,10 +4868,10 @@ function miterCut(part, plane) {
4868
4868
  });
4869
4869
  }
4870
4870
  /**
4871
- * Auto corner-miter between two adjacent flanges. The miter plane bisects the two
4872
- * flanges' fold-up directions at their shared corner and is offset by half the gap,
4873
- * so the cut falls on the flat/flange regions and never crosses a bend patch. The
4874
- * single bisector cut trims both flanges to a clean mitered corner.
4871
+ * Auto corner-miter between two adjacent flanges. The miter plane is vertical at
4872
+ * their shared corner, bisects the two directions that point out of the part, and
4873
+ * is offset outward by half the gap. The single cut trims the ends of both flanges
4874
+ * to a clean mitered corner and leaves the base flat and the bend lines whole.
4875
4875
  */
4876
4876
  function autoMiterCorner(part, flangeIdA, flangeIdB, gap = 0) {
4877
4877
  if (part.solid === void 0) return err(validationError("NO_SOLID", "autoMiterCorner: part has no folded solid"));
@@ -4882,7 +4882,7 @@ function autoMiterCorner(part, flangeIdA, flangeIdB, gap = 0) {
4882
4882
  const axisA = vecNormalize(bendA.axisDir);
4883
4883
  const axisB = vecNormalize(bendB.axisDir);
4884
4884
  const corner = cornerPoint(bendA.axisOrigin, axisA, bendB.axisOrigin, axisB);
4885
- const planeNormal = miterNormal(axisA, axisB);
4885
+ const planeNormal = miterNormal(axisA, bendLineMid(part, bendA, axisA), axisB, bendLineMid(part, bendB, axisB), corner);
4886
4886
  if (planeNormal === void 0) return err(validationError("PARALLEL_FLANGES", "autoMiterCorner: flange bend axes are parallel; no corner to miter"));
4887
4887
  const cutResult = miterCut(part, {
4888
4888
  origin: vecAdd(corner, vecScale(planeNormal, gap * .5)),
@@ -4911,19 +4911,27 @@ function cornerPoint(originA, dirA, originB, dirB) {
4911
4911
  const sc = (b * e - c * d) / denom;
4912
4912
  return vecAdd(originA, vecScale(dirA, sc));
4913
4913
  }
4914
- /**
4915
- * Normal of the miter plane between two flanges whose bend axes are `dirA`/`dirB`.
4916
- * The plane is spanned by the two axes (it contains the corner edge of each
4917
- * flange); its normal is `dirA × dirB` rotated to bisect — equivalently the
4918
- * normalized sum of the two run directions, which both lie perpendicular to the
4919
- * respective axis in the part's run plane.
4920
- */
4921
- function miterNormal(dirA, dirB) {
4922
- const cross = vecCross(dirA, dirB);
4923
- if (Math.hypot(cross[0], cross[1], cross[2]) < 1e-9) return void 0;
4924
- const sum = vecAdd(dirA, dirB);
4925
- if (Math.hypot(sum[0], sum[1], sum[2]) < 1e-9) return vecNormalize(cross);
4926
- return vecNormalize(sum);
4914
+ /** Midpoint of a bend line. The line starts at the axis origin and runs the span of its flange. */
4915
+ function bendLineMid(part, bend, axis) {
4916
+ const span = part.flanges.find((f) => f.id === bend.id)?.span ?? 0;
4917
+ return vecAdd(bend.axisOrigin, vecScale(axis, span / 2));
4918
+ }
4919
+ /**
4920
+ * Normal of the miter plane between two flanges whose bend axes are `dirA`/`dirB`:
4921
+ * the bisector of the two directions that point out of the part. The outward
4922
+ * direction of a flange is perpendicular to its bend axis in the plane of the two
4923
+ * axes, and points away from the bend line of the other flange (`midA`/`midB` are
4924
+ * the midpoints of the two bend lines). The bend axes do not give this direction:
4925
+ * their sum lies along the diagonal of the part, and a cut there removes half of it.
4926
+ */
4927
+ function miterNormal(dirA, midA, dirB, midB, corner) {
4928
+ const up = vecCross(dirA, dirB);
4929
+ if (Math.hypot(up[0], up[1], up[2]) < 1e-9) return void 0;
4930
+ const outward = (dir, otherMid) => {
4931
+ const run = vecNormalize(vecCross(dir, up));
4932
+ return vecDot(run, vecSub(otherMid, corner)) > 0 ? vecScale(run, -1) : run;
4933
+ };
4934
+ return vecNormalize(vecAdd(outward(dirA, midB), outward(dirB, midA)));
4927
4935
  }
4928
4936
  var Z_AXIS = [
4929
4937
  0,
@@ -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 bisects the two
16
- * flanges' fold-up directions at their shared corner and is offset by half the gap,
17
- * so the cut falls on the flat/flange regions and never crosses a bend patch. The
18
- * single bisector cut trims both flanges to a clean mitered corner.
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.2",
3
+ "version": "0.4.3",
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.5",
56
+ "@types/node": "26.6.6",
57
57
  "eslint": "*",
58
58
  "tsx": "4.23.15",
59
59
  "typescript": "*",