@constructorfleet/sketchforge-engine 1.24.1 → 1.26.0

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.
Files changed (44) hide show
  1. package/dist/cadFaceMesh.d.ts +31 -0
  2. package/dist/cadFaceMesh.d.ts.map +1 -0
  3. package/dist/cadFaceMesh.js +50 -0
  4. package/dist/cadFaceMesh.js.map +1 -0
  5. package/dist/cadSolids.d.ts +32 -0
  6. package/dist/cadSolids.d.ts.map +1 -1
  7. package/dist/cadSolids.js +45 -12
  8. package/dist/cadSolids.js.map +1 -1
  9. package/dist/engine.d.ts.map +1 -1
  10. package/dist/engine.js +16 -67
  11. package/dist/engine.js.map +1 -1
  12. package/dist/faceDraftSegmentLineage.d.ts +2 -37
  13. package/dist/faceDraftSegmentLineage.d.ts.map +1 -1
  14. package/dist/faceDraftSegmentLineage.js +6 -190
  15. package/dist/faceDraftSegmentLineage.js.map +1 -1
  16. package/dist/serverCadMeasure.d.ts.map +1 -1
  17. package/dist/serverCadMeasure.js +33 -2
  18. package/dist/serverCadMeasure.js.map +1 -1
  19. package/dist/serverCadOperations.d.ts +14 -43
  20. package/dist/serverCadOperations.d.ts.map +1 -1
  21. package/dist/serverCadOperations.js +44 -142
  22. package/dist/serverCadOperations.js.map +1 -1
  23. package/dist/serverShapeBooleans.js +1 -1
  24. package/dist/serverShapeBooleans.js.map +1 -1
  25. package/dist/sketchExtrusionRequest.d.ts.map +1 -1
  26. package/dist/sketchExtrusionRequest.js +2 -25
  27. package/dist/sketchExtrusionRequest.js.map +1 -1
  28. package/dist/sketchExtrusionSolid.d.ts +4 -0
  29. package/dist/sketchExtrusionSolid.d.ts.map +1 -0
  30. package/dist/sketchExtrusionSolid.js +36 -0
  31. package/dist/sketchExtrusionSolid.js.map +1 -0
  32. package/dist/sketchFaceDraftKernel.d.ts +248 -0
  33. package/dist/sketchFaceDraftKernel.d.ts.map +1 -0
  34. package/dist/sketchFaceDraftKernel.js +573 -0
  35. package/dist/sketchFaceDraftKernel.js.map +1 -0
  36. package/dist/support/cadModifierTypes.d.ts +45 -0
  37. package/dist/support/cadModifierTypes.d.ts.map +1 -1
  38. package/dist/support/i18n/locales/en/messages.json +3 -1
  39. package/dist/support/lib/operator-configuration.json +11 -0
  40. package/dist/workplaneShapes.d.ts +6 -0
  41. package/dist/workplaneShapes.d.ts.map +1 -1
  42. package/dist/workplaneShapes.js +25 -70
  43. package/dist/workplaneShapes.js.map +1 -1
  44. package/package.json +1 -1
@@ -29,9 +29,10 @@
29
29
  */
30
30
  import { circularEdgeRadius, faceRadius, planarFaceAngle, } from "./cadMeasurements.js";
31
31
  import { withCadKernel } from "./serverCadKernel.js";
32
- import { edgeSolidForShape, orientedSolidForShape, ServerCadError } from "./serverCadOperations.js";
32
+ import { edgeSolidForShape, orientedSolidForShape, ServerCadError, treatmentBakesRotation } from "./serverCadOperations.js";
33
33
  import { faceOutwardNormal } from "./serverCadShell.js";
34
34
  import { placedSolidForShape } from "./serverShapeBooleans.js";
35
+ import { shapePlacementMatrix } from "./serverShapeGroups.js";
35
36
  function edgeMeasurement(cad, handle, index) {
36
37
  let geometryType = "unknown";
37
38
  try {
@@ -124,7 +125,37 @@ function resolveTarget(cad, target, label) {
124
125
  // listings use, and which is right for them -- hands back the solid in its own
125
126
  // frame with the rotation applied and the translation not. Two parts 60mm
126
127
  // apart both measured from the origin through that, so this read zero.
127
- const solid = placedSolidForShape(cad, target.shape);
128
+ // Edges have their own canonical solid: for an untreated plain revolve it
129
+ // is rebuilt from the retained profile, exactly like GET /edges and edge
130
+ // treatments. The stored mesh has many more edges and cannot resolve those
131
+ // listed indexes. Faces continue to use their existing placed solid.
132
+ let solid;
133
+ if (target.entity === "edge") {
134
+ solid = edgeSolidForShape(cad, target.shape);
135
+ // The edge listing and treatment solid is in the shape frame: its mirror
136
+ // is already applied, while a treatment may bake a parametric shape's
137
+ // rotation into the geometry. Put that same solid where it sits without
138
+ // applying either transform twice. Untreated revolves are the exception:
139
+ // their exact edge solid is rebuilt from the profile before rotation.
140
+ const rotationAlreadyApplied = treatmentBakesRotation(target.shape)
141
+ && target.shape.sketchOperation !== "revolve";
142
+ const placementShape = {
143
+ ...target.shape,
144
+ mirrorX: undefined,
145
+ mirrorY: undefined,
146
+ mirrorZ: undefined,
147
+ ...(rotationAlreadyApplied ? { rotation: 0, rotationX: 0, rotationZ: 0 } : {}),
148
+ };
149
+ const elements = shapePlacementMatrix(placementShape).elements;
150
+ solid = cad.transform(solid, [
151
+ elements[0], elements[4], elements[8], elements[12],
152
+ elements[1], elements[5], elements[9], elements[13],
153
+ elements[2], elements[6], elements[10], elements[14],
154
+ ]);
155
+ }
156
+ else {
157
+ solid = placedSolidForShape(cad, target.shape);
158
+ }
128
159
  if (target.entity === "shape") {
129
160
  return { handle: solid, face: null };
130
161
  }
@@ -1 +1 @@
1
- {"version":3,"file":"serverCadMeasure.js","sourceRoot":"","sources":["../src/serverCadMeasure.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"serverCadMeasure.js","sourceRoot":"","sources":["../src/serverCadMeasure.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,EACL,kBAAkB,EAClB,UAAU,EACV,eAAe,GAGhB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAC5H,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAuB9D,SAAS,eAAe,CAAC,GAAe,EAAE,MAAmB,EAAE,KAAa;IAC1E,IAAI,YAAY,GAAG,SAAS,CAAC;IAC7B,IAAI,CAAC;QACH,YAAY,GAAG,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,yEAAyE;IAC3E,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,GAAG,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,kBAAkB,CAAC;QAClC,SAAS,EAAE,YAAY;QACvB,MAAM;QACN,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,MAAM,EAAE,GAAG,CAAC,aAAa,CAAC,MAAM,CAAC;KAClC,CAAC,CAAC;IACH,OAAO;QACL,MAAM,EAAE,MAAM;QACd,KAAK;QACL,YAAY;QACZ,MAAM;QACN,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;QACnD,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI;QACvD,YAAY,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI;QACjF,iBAAiB,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI;KAC7D,CAAC;AACJ,CAAC;AAED,4FAA4F;AAC5F,SAAS,gBAAgB,CAAC,GAAe,EAAE,IAAiB;IAC1D,IAAI,CAAC;QACH,OAAO,GAAG,CAAC,mBAAmB,CAAC,IAAI,CAAC,EAAE,MAAM,IAAI,IAAI,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,2FAA2F;AAC3F,SAAS,aAAa,CAAC,GAAe,EAAE,IAAiB;IACvD,IAAI,CAAC;QACH,OAAO,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,8DAA8D;QAC9D,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,GAAe,EAAE,MAAmB,EAAE,KAAa;IAC1E,MAAM,YAAY,GAAG,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,UAAU,CAAC,YAAY,EAAE,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;IACzE,OAAO;QACL,MAAM,EAAE,MAAM;QACd,KAAK;QACL,YAAY;QACZ,MAAM,EAAE,IAAI;QACZ,IAAI,EAAE,GAAG,CAAC,cAAc,CAAC,MAAM,CAAC;QAChC,MAAM,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;QACnD,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI;QACvD,YAAY,EAAE,IAAI;QAClB,iBAAiB,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI;KAC7D,CAAC;AACJ,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,iBAAiB,CAAC,KAAqB;IACrD,OAAO,aAAa,CAAC,CAAC,GAAG,EAAE,EAAE;QAC3B,6EAA6E;QAC7E,0EAA0E;QAC1E,sEAAsE;QACtE,uEAAuE;QACvE,oEAAoE;QACpE,MAAM,SAAS,GAAG,qBAAqB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACpD,IAAI,SAAS,GAAG,SAAS,CAAC;QAC1B,IAAI,CAAC;YACH,SAAS,GAAG,iBAAiB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC5C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,CAAC,KAAK,YAAY,cAAc,CAAC;gBAAE,MAAM,KAAK,CAAC;QACtD,CAAC;QACD,OAAO;YACL,GAAG,GAAG,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YAClG,GAAG,GAAG,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;SACnG,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAoCD,SAAS,aAAa,CAAC,GAAe,EAAE,MAAyB,EAAE,KAAa;IAC9E,6EAA6E;IAC7E,yEAAyE;IACzE,+EAA+E;IAC/E,0EAA0E;IAC1E,uEAAuE;IACvE,0EAA0E;IAC1E,yEAAyE;IACzE,2EAA2E;IAC3E,qEAAqE;IACrE,IAAI,KAAkB,CAAC;IACvB,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC7B,KAAK,GAAG,iBAAiB,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;QAC7C,yEAAyE;QACzE,sEAAsE;QACtE,wEAAwE;QACxE,yEAAyE;QACzE,sEAAsE;QACtE,MAAM,sBAAsB,GAAG,sBAAsB,CAAC,MAAM,CAAC,KAAK,CAAC;eAC9D,MAAM,CAAC,KAAK,CAAC,eAAe,KAAK,SAAS,CAAC;QAChD,MAAM,cAAc,GAAG;YACrB,GAAG,MAAM,CAAC,KAAK;YACf,OAAO,EAAE,SAAS;YAClB,OAAO,EAAE,SAAS;YAClB,OAAO,EAAE,SAAS;YAClB,GAAG,CAAC,sBAAsB,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC/E,CAAC;QACF,MAAM,QAAQ,GAAG,oBAAoB,CAAC,cAAc,CAAC,CAAC,QAAQ,CAAC;QAC/D,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE;YAC3B,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC;YACnD,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC;YACnD,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC;SACrD,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,KAAK,GAAG,mBAAmB,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACjD,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAC9B,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACvC,CAAC;IACD,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;IAChC,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAChC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC;QAC5E,MAAM,IAAI,cAAc,CACtB,GAAG,KAAK,oBAAoB,SAAS,CAAC,MAAM,IAAI,MAAM,oBAAoB,MAAM,CAAC,MAAM,IAAI,KAAK,GAAG,EACnG,GAAG,CACJ,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AACpE,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAAC,IAAuB,EAAE,EAAqB;IAC3E,OAAO,aAAa,CAAC,CAAC,GAAG,EAAE,EAAE;QAC3B,MAAM,CAAC,GAAG,aAAa,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QAC3C,MAAM,CAAC,GAAG,aAAa,CAAC,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;QACvC,MAAM,QAAQ,GAAG,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;QAEzD,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACvB,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,gBAAgB,EAAE,WAAoB,EAAE,CAAC;QAClF,CAAC;QACD,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;YACzB,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,gBAAgB,EAAE,kBAA2B,EAAE,CAAC;QACzF,CAAC;QACD,MAAM,KAAK,GAAG,eAAe,CAC3B,EAAE,WAAW,EAAE,aAAa,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAC5D,EAAE,WAAW,EAAE,aAAa,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAC7D,CAAC;QACF,OAAO;YACL,QAAQ;YACR,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI;YACzD,gBAAgB,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI;SACtD,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -16,6 +16,7 @@
16
16
  */
17
17
  import type { EvolutionData, OcctKernel, ShapeHandle } from "occt-wasm";
18
18
  import type { SketchProfile, WorkplaneShape } from "./domain/sketchforge.js";
19
+ import { type SketchFaceDraftRequest } from "./sketchFaceDraftKernel.js";
19
20
  export type ServerCadEdge = {
20
21
  index: number;
21
22
  length: number;
@@ -46,43 +47,7 @@ export declare class ServerCadError extends Error {
46
47
  readonly status: number;
47
48
  constructor(message: string, status?: number);
48
49
  }
49
- declare const DRAFT_PULL_AXES: {
50
- readonly x: {
51
- readonly x: 1;
52
- readonly y: 0;
53
- readonly z: 0;
54
- };
55
- readonly y: {
56
- readonly x: 0;
57
- readonly y: 1;
58
- readonly z: 0;
59
- };
60
- readonly z: {
61
- readonly x: 0;
62
- readonly y: 0;
63
- readonly z: 1;
64
- };
65
- readonly "-x": {
66
- readonly x: -1;
67
- readonly y: 0;
68
- readonly z: 0;
69
- };
70
- readonly "-y": {
71
- readonly x: 0;
72
- readonly y: -1;
73
- readonly z: 0;
74
- };
75
- readonly "-z": {
76
- readonly x: 0;
77
- readonly y: 0;
78
- readonly z: -1;
79
- };
80
- };
81
- export type SketchFaceDraftRequest = {
82
- sourceFaceId: string;
83
- angle: number;
84
- pullDirection: keyof typeof DRAFT_PULL_AXES;
85
- };
50
+ export type { SketchFaceDraftRequest } from "./sketchFaceDraftKernel.js";
86
51
  /**
87
52
  * Whether the kernel considers a shape sound.
88
53
  *
@@ -131,8 +96,12 @@ export declare function localSolidForShape(cad: OcctKernel, shape: WorkplaneShap
131
96
  * straightened. `treatmentBakesRotation` is the other half of that bargain and
132
97
  * reads the same predicate.
133
98
  *
134
- * For stored geometry this is the local solid unchanged: the rotation stays on
135
- * the shape, which is where it already was.
99
+ * For stored geometry this is the local solid with only its mirror applied:
100
+ * the rotation stays on the shape, which is where it already was.
101
+ *
102
+ * Mirrored either way, because the result is stored with the shape's mirror
103
+ * flags cleared. Building it unmirrored handed back the unmirrored shape and
104
+ * reported success (#413).
136
105
  */
137
106
  export declare function orientedSolidForShape(cad: OcctKernel, shape: WorkplaneShape): ShapeHandle;
138
107
  /** The edges of a shape, in the order a treatment request refers to them by index. */
@@ -175,6 +144,7 @@ export declare function allEdgeTreatmentEdgeCount(shape: WorkplaneShape, _kind:
175
144
  * the treatment. For an untreated revolve that is the exact solid rebuilt from
176
145
  * its profile (#347); a revolve with no exact solid is refused rather than
177
146
  * listed or treated by its facets. Everything else is the oriented solid.
147
+ * Both carry the shape's mirror, which the treated result no longer does.
178
148
  */
179
149
  export declare function edgeSolidForShape(cad: OcctKernel, shape: WorkplaneShape): ShapeHandle;
180
150
  /** Build the analytical full-turn BREP for chamfering a retained plain revolve. */
@@ -189,9 +159,11 @@ export declare function exactPlainSketchRevolveResult(shape: WorkplaneShape): Pr
189
159
  /**
190
160
  * Apply a prism draft along the shape's vertical extrusion axis.
191
161
  *
192
- * This is intentionally a baked operation: the project does not yet retain
193
- * the source extrusion as a parametric feature. The exact BREP and viewport
194
- * mesh are persisted together, as with shell and edge treatments.
162
+ * The geometry only: the caller records the retained angle and source frame
163
+ * (`retainedPrismDraftFields`) that a sketch edit replays it from. The B-rep
164
+ * is built about the centre of the profile's bounds
165
+ * (`draftPrismProfileOffset`), and the exact BREP and viewport mesh are
166
+ * persisted together, as with shell and edge treatments.
195
167
  */
196
168
  export declare function applyDraftPrism(shape: WorkplaneShape, request: {
197
169
  angle: number;
@@ -213,5 +185,4 @@ export declare function meshedCadResult(cad: OcctKernel, result: ShapeHandle, so
213
185
  * the viewport expects -- so the shape keeps its place on the workplane.
214
186
  */
215
187
  export declare function shapeWithCadResult(shape: WorkplaneShape, result: ServerCadResult): WorkplaneShape;
216
- export {};
217
188
  //# sourceMappingURL=serverCadOperations.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"serverCadOperations.d.ts","sourceRoot":"","sources":["../src/serverCadOperations.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"serverCadOperations.d.ts","sourceRoot":"","sources":["../src/serverCadOperations.ts"],"names":[],"mappings":"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"}
@@ -16,11 +16,13 @@
16
16
  */
17
17
  import { faceIdsFromEvolution } from "./faceLineage.js";
18
18
  import { withCadKernel } from "./serverCadKernel.js";
19
- import { exactSolidForShape, shapeIsTurned, unrotatedSolidForShape, UnbuildableShapeError, EXACT_SOLID_KINDS, } from "./cadSolids.js";
19
+ import { exactSolidForShape, mirroredInShapeFrame, shapeIsTurned, unrotatedSolidForShape, UnbuildableShapeError, EXACT_SOLID_KINDS, } from "./cadSolids.js";
20
20
  import { canonicalizeShape } from "./workplaneShapes.js";
21
21
  import { createLocalId } from "./localIds.js";
22
22
  import { cadSketchRegions } from "./sketchCadProfile.js";
23
23
  import { normalizeSketchRevolveSettings, sketchProfileToRevolvePolygons } from "./sketchRevolve.js";
24
+ import { triangleFaceGroups } from "./cadFaceMesh.js";
25
+ import { draftSketchFace, draftPrismProfileOffset, faceIdsForCadResult } from "./sketchFaceDraftKernel.js";
24
26
  export class ServerCadError extends Error {
25
27
  status;
26
28
  constructor(message, status = 422) {
@@ -32,10 +34,6 @@ export class ServerCadError extends Error {
32
34
  const MESH_DEFLECTION = 0.1;
33
35
  const MIN_CAD_DIMENSION = 0.01;
34
36
  const FACE_HASH_UPPER_BOUND = 2_147_483_647;
35
- const DRAFT_PULL_AXES = {
36
- x: { x: 1, y: 0, z: 0 }, y: { x: 0, y: 1, z: 0 }, z: { x: 0, y: 0, z: 1 },
37
- "-x": { x: -1, y: 0, z: 0 }, "-y": { x: 0, y: -1, z: 0 }, "-z": { x: 0, y: 0, z: -1 },
38
- };
39
37
  function meshPositionsOf(shape) {
40
38
  const positions = shape.importedMesh?.positions;
41
39
  return positions && positions.length >= 9 ? positions : null;
@@ -184,12 +182,16 @@ export function localSolidForShape(cad, shape) {
184
182
  * straightened. `treatmentBakesRotation` is the other half of that bargain and
185
183
  * reads the same predicate.
186
184
  *
187
- * For stored geometry this is the local solid unchanged: the rotation stays on
188
- * the shape, which is where it already was.
185
+ * For stored geometry this is the local solid with only its mirror applied:
186
+ * the rotation stays on the shape, which is where it already was.
187
+ *
188
+ * Mirrored either way, because the result is stored with the shape's mirror
189
+ * flags cleared. Building it unmirrored handed back the unmirrored shape and
190
+ * reported success (#413).
189
191
  */
190
192
  export function orientedSolidForShape(cad, shape) {
191
193
  if (!rotationIsRebuilt(shape))
192
- return localSolidForShape(cad, shape);
194
+ return mirroredStoredSolid(cad, localSolidForShape(cad, shape), shape);
193
195
  try {
194
196
  return exactSolidForShape(cad, shape);
195
197
  }
@@ -199,6 +201,25 @@ export function orientedSolidForShape(cad, shape) {
199
201
  throw error;
200
202
  }
201
203
  }
204
+ /**
205
+ * A solid stored on the shape -- its BREP, its mesh, or a revolve rebuilt from
206
+ * its profile -- with the shape's mirror flags applied about its own centre.
207
+ *
208
+ * The bounds centre rather than the origin, because stored geometry is not
209
+ * always in the builders' frame (an earlier treatment's BREP keeps whatever
210
+ * frame it was made in); the viewport mirrors the normalized mesh about its
211
+ * centre, and a plane through any other point would only move the result.
212
+ */
213
+ function mirroredStoredSolid(cad, solid, shape) {
214
+ if (!shape.mirrorX && !shape.mirrorY && !shape.mirrorZ)
215
+ return solid;
216
+ const bounds = cad.getBoundingBox(solid, false);
217
+ return mirroredInShapeFrame(cad, solid, shape, {
218
+ x: (bounds.xmin + bounds.xmax) / 2,
219
+ y: (bounds.ymin + bounds.ymax) / 2,
220
+ z: (bounds.zmin + bounds.zmax) / 2,
221
+ });
222
+ }
202
223
  /** How many faces of the solid meet along this edge. A seam reports one. */
203
224
  function adjacentFaceCount(cad, solid, handle) {
204
225
  try {
@@ -272,12 +293,7 @@ export function applyBakedMirror(shape, axis, pivot) {
272
293
  throw error;
273
294
  }
274
295
  const centerY = shape.height / 2;
275
- if (shape.mirrorX)
276
- solid = cad.mirror(solid, { x: 0, y: 0, z: 0 }, { x: 1, y: 0, z: 0 });
277
- if (shape.mirrorY)
278
- solid = cad.mirror(solid, { x: 0, y: centerY, z: 0 }, { x: 0, y: 1, z: 0 });
279
- if (shape.mirrorZ)
280
- solid = cad.mirror(solid, { x: 0, y: 0, z: 0 }, { x: 0, y: 0, z: 1 });
296
+ solid = mirroredInShapeFrame(cad, solid, shape, { x: 0, y: centerY, z: 0 });
281
297
  const center = { x: 0, y: centerY, z: 0 };
282
298
  const angle = (degrees) => degrees * Math.PI / 180;
283
299
  if (shape.rotationZ)
@@ -482,12 +498,14 @@ function exactRevolveSolidForShape(cad, shape) {
482
498
  * the treatment. For an untreated revolve that is the exact solid rebuilt from
483
499
  * its profile (#347); a revolve with no exact solid is refused rather than
484
500
  * listed or treated by its facets. Everything else is the oriented solid.
501
+ * Both carry the shape's mirror, which the treated result no longer does.
485
502
  */
486
503
  export function edgeSolidForShape(cad, shape) {
487
504
  const refusal = revolveWithoutExactEdges(shape);
488
505
  if (refusal)
489
506
  throw new ServerCadError(refusal);
490
- return exactRevolveSolidForShape(cad, shape) ?? orientedSolidForShape(cad, shape);
507
+ const revolve = exactRevolveSolidForShape(cad, shape);
508
+ return revolve ? mirroredStoredSolid(cad, revolve, shape) : orientedSolidForShape(cad, shape);
491
509
  }
492
510
  /** Build the analytical full-turn BREP for chamfering a retained plain revolve. */
493
511
  export function isPlainFullTurnSketchRevolve(shape) {
@@ -589,9 +607,11 @@ export function exactPlainSketchRevolveResult(shape) {
589
607
  /**
590
608
  * Apply a prism draft along the shape's vertical extrusion axis.
591
609
  *
592
- * This is intentionally a baked operation: the project does not yet retain
593
- * the source extrusion as a parametric feature. The exact BREP and viewport
594
- * mesh are persisted together, as with shell and edge treatments.
610
+ * The geometry only: the caller records the retained angle and source frame
611
+ * (`retainedPrismDraftFields`) that a sketch edit replays it from. The B-rep
612
+ * is built about the centre of the profile's bounds
613
+ * (`draftPrismProfileOffset`), and the exact BREP and viewport mesh are
614
+ * persisted together, as with shell and edge treatments.
595
615
  */
596
616
  export function applyDraftPrism(shape, request) {
597
617
  if (!Number.isFinite(request.angle) || request.angle === 0 || Math.abs(request.angle) >= 45) {
@@ -609,12 +629,7 @@ export function applyDraftPrism(shape, request) {
609
629
  return Promise.reject(new ServerCadError("Draft prism currently requires one closed polygonal sketch profile made from straight segments.", 400));
610
630
  }
611
631
  return withCadKernel((cad) => {
612
- const minX = Math.min(...points.map(({ x }) => x));
613
- const maxX = Math.max(...points.map(({ x }) => x));
614
- const minZ = Math.min(...points.map(({ z }) => z));
615
- const maxZ = Math.max(...points.map(({ z }) => z));
616
- const centerX = (minX + maxX) / 2;
617
- const centerZ = (minZ + maxZ) / 2;
632
+ const { x: centerX, z: centerZ } = draftPrismProfileOffset(shape.sketchProfile);
618
633
  const edges = points.map((point, index) => {
619
634
  const next = points[(index + 1) % points.length];
620
635
  return cad.makeLineEdge({ x: point.x - centerX, y: 0, z: point.z - centerZ }, { x: next.x - centerX, y: 0, z: next.z - centerZ });
@@ -663,75 +678,15 @@ export function applySketchFaceDraft(shape, request) {
663
678
  const face = faces[selected[0]];
664
679
  if (!face)
665
680
  throw new ServerCadError("The selected source face is no longer available.");
666
- const direction = DRAFT_PULL_AXES[request.pullDirection];
667
- const angle = request.angle * Math.PI / 180;
668
- let drafted;
669
- try {
670
- drafted = cad.draft(solid, face, angle, direction);
671
- }
672
- catch {
673
- const rotation = canonicalDraftRotation(request.pullDirection);
674
- try {
675
- if (!rotation)
676
- throw new Error("No canonical rotation for the selected pull axis.");
677
- const rotatedSolid = cad.rotate(solid, rotation.axis, rotation.angle);
678
- const oldNormal = faceNormal(cad, face);
679
- if (!oldNormal)
680
- throw new Error("The selected face has no usable normal.");
681
- const targetNormal = rotateVector(oldNormal, rotation.axis.direction, rotation.angle);
682
- const targetCenter = rotateVector(cad.getSurfaceCenterOfMass(face), rotation.axis.direction, rotation.angle);
683
- const bounds = cad.getBoundingBox(solid, false);
684
- const scale = Math.max(1, Math.hypot(bounds.xmax - bounds.xmin, bounds.ymax - bounds.ymin, bounds.zmax - bounds.zmin));
685
- const matches = cad.getSubShapes(rotatedSolid, "face").filter((candidate) => {
686
- const normal = faceNormal(cad, candidate);
687
- const center = cad.getSurfaceCenterOfMass(candidate);
688
- return normal && Math.hypot(normal.x - targetNormal.x, normal.y - targetNormal.y, normal.z - targetNormal.z) <= 1e-7
689
- && Math.hypot(center.x - targetCenter.x, center.y - targetCenter.y, center.z - targetCenter.z) <= scale * 1e-8;
690
- });
691
- if (matches.length !== 1)
692
- throw new Error("Could not uniquely identify the selected face after rotating the solid.");
693
- const canonicalDraft = cad.draft(rotatedSolid, matches[0], angle, { x: 0, y: 0, z: 1 });
694
- drafted = cad.rotate(canonicalDraft, rotation.axis, -rotation.angle);
695
- }
696
- catch {
697
- throw new ServerCadError("The selected source face cannot be drafted along that local pull axis and angle.");
698
- }
699
- }
681
+ const drafted = draftSketchFace(cad, solid, face, request);
682
+ if (!drafted)
683
+ throw new ServerCadError("The selected source face cannot be drafted along that local pull axis and angle.");
700
684
  if (!cadResultIsValid(cad, drafted) || !cad.isSolid(drafted)) {
701
685
  throw new ServerCadError("The face draft did not produce a valid solid.");
702
686
  }
703
687
  return meshedCadResult(cad, exactRevolve ? scaleRevolveResult(cad, drafted, shape) : drafted, shape);
704
688
  });
705
689
  }
706
- function canonicalDraftRotation(direction) {
707
- switch (direction) {
708
- case "x": return { axis: { point: { x: 0, y: 0, z: 0 }, direction: { x: 0, y: 1, z: 0 } }, angle: -Math.PI / 2 };
709
- case "-x": return { axis: { point: { x: 0, y: 0, z: 0 }, direction: { x: 0, y: 1, z: 0 } }, angle: Math.PI / 2 };
710
- case "y": return { axis: { point: { x: 0, y: 0, z: 0 }, direction: { x: 1, y: 0, z: 0 } }, angle: Math.PI / 2 };
711
- case "-y": return { axis: { point: { x: 0, y: 0, z: 0 }, direction: { x: 1, y: 0, z: 0 } }, angle: -Math.PI / 2 };
712
- case "z": return null;
713
- case "-z": return { axis: { point: { x: 0, y: 0, z: 0 }, direction: { x: 0, y: 1, z: 0 } }, angle: Math.PI };
714
- }
715
- }
716
- function rotateVector(vector, axis, angle) {
717
- const cosine = Math.cos(angle), sine = Math.sin(angle);
718
- const dot = axis.x * vector.x + axis.y * vector.y + axis.z * vector.z;
719
- const cross = { x: axis.y * vector.z - axis.z * vector.y, y: axis.z * vector.x - axis.x * vector.z, z: axis.x * vector.y - axis.y * vector.x };
720
- return {
721
- x: vector.x * cosine + cross.x * sine + axis.x * dot * (1 - cosine),
722
- y: vector.y * cosine + cross.y * sine + axis.y * dot * (1 - cosine),
723
- z: vector.z * cosine + cross.z * sine + axis.z * dot * (1 - cosine),
724
- };
725
- }
726
- function faceNormal(cad, face) {
727
- try {
728
- const bounds = cad.uvBounds(face);
729
- return cad.surfaceNormal(face, (bounds.uMin + bounds.uMax) / 2, (bounds.vMin + bounds.vMax) / 2);
730
- }
731
- catch {
732
- return null;
733
- }
734
- }
735
690
  /** The exact geometry and a mesh of it, which is what a shape stores after any CAD operation. */
736
691
  export function meshedCadResult(cad, result, sourceShape, lineage, sourceSolid) {
737
692
  const mesh = cad.meshShape(result, { linearDeflection: MESH_DEFLECTION });
@@ -746,12 +701,7 @@ export function meshedCadResult(cad, result, sourceShape, lineage, sourceSolid)
746
701
  }
747
702
  const faces = cad.getSubShapes(result, "face");
748
703
  const faceIndexByHash = new Map(faces.map((face, index) => [cad.hashCode(face, 2_147_483_647), index]));
749
- const faceGroups = [];
750
- for (let group = 0; group + 2 < (mesh.faceGroups?.length ?? 0); group += 3) {
751
- const index = faceIndexByHash.get(mesh.faceGroups[group + 2]);
752
- if (index !== undefined)
753
- faceGroups.push(mesh.faceGroups[group], mesh.faceGroups[group + 1], index);
754
- }
704
+ const faceGroups = triangleFaceGroups(mesh.faceGroups, faceIndexByHash);
755
705
  const faceIds = sourceShape
756
706
  ? lineage
757
707
  ? faceIdsFromEvolution(sourceShape.id, sourceShape.faceIds, lineage.sourceFaceHashes, faces.map((face) => cad.hashCode(face, FACE_HASH_UPPER_BOUND)), lineage.evolution)
@@ -766,56 +716,8 @@ export function meshedCadResult(cad, result, sourceShape, lineage, sourceSolid)
766
716
  ...(faceGroups.length ? { faceGroups } : {}),
767
717
  };
768
718
  }
769
- /**
770
- * Keep an ID only when an exact face BREP or a unique planar support surface
771
- * occurs on each side. OCCT face ordering and hash codes are kernel details,
772
- * so an unmatched or ambiguous face receives a new application ID.
773
- */
774
719
  function faceIdsForResult(cad, source, resultFaces, sourceSolid = orientedSolidForShape(cad, source)) {
775
- const sourceFaces = cad.getSubShapes(sourceSolid, "face");
776
- const fingerprint = (face) => {
777
- const brep = cad.toBREP(face);
778
- try {
779
- if (cad.surfaceType(face) !== "plane")
780
- return `brep:${brep}`;
781
- const bounds = cad.uvBounds(face);
782
- const normal = cad.surfaceNormal(face, (bounds.uMin + bounds.uMax) / 2, (bounds.vMin + bounds.vMax) / 2);
783
- const center = cad.getSurfaceCenterOfMass(face);
784
- const round = (value) => Math.round(value * 1e6) / 1e6;
785
- const n = [round(normal.x), round(normal.y), round(normal.z)];
786
- const offset = round(center.x * normal.x + center.y * normal.y + center.z * normal.z);
787
- return `plane:${n.join(",")}:${offset}`;
788
- }
789
- catch {
790
- return `brep:${brep}`;
791
- }
792
- };
793
- const sourceByBrep = new Map();
794
- sourceFaces.forEach((face, index) => {
795
- const key = fingerprint(face);
796
- sourceByBrep.set(key, [...(sourceByBrep.get(key) ?? []), index]);
797
- });
798
- const resultCounts = new Map();
799
- const resultBreps = resultFaces.map((face) => {
800
- const key = fingerprint(face);
801
- resultCounts.set(key, (resultCounts.get(key) ?? 0) + 1);
802
- return key;
803
- });
804
- const used = new Set();
805
- return resultBreps.map((brep, index) => {
806
- const matches = sourceByBrep.get(brep) ?? [];
807
- const sourceIndex = matches.length === 1 && resultCounts.get(brep) === 1 ? matches[0] : undefined;
808
- const inherited = sourceIndex === undefined
809
- ? undefined
810
- : source.faceIds?.[sourceIndex] ?? `face_${encodeURIComponent(source.id)}_${sourceIndex}`;
811
- if (inherited && !used.has(inherited)) {
812
- used.add(inherited);
813
- return inherited;
814
- }
815
- const fresh = createLocalId(`${source.id}-face-${index}`);
816
- used.add(fresh);
817
- return fresh.startsWith("face_") ? fresh : `face_${fresh}`;
818
- });
720
+ return faceIdsForCadResult(cad, source, resultFaces, sourceSolid);
819
721
  }
820
722
  function freshFaceIds(cad, solid, shapeId) {
821
723
  return cad.getSubShapes(solid, "face").map((_, index) => `face_${createLocalId(`${shapeId}-face-${index}`)}`);