@faicad/faijs 0.18.3 → 0.22.2
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/api/api-namespace.d.ts.map +1 -1
- package/dist/api/api-namespace.js +4 -1
- package/dist/api/api-namespace.js.map +1 -1
- package/dist/api/brep-mirror/joinery-brep.d.ts +1 -1
- package/dist/api/brep-mirror/joinery-brep.d.ts.map +1 -1
- package/dist/api/brep-mirror/joinery-brep.js +22 -20
- package/dist/api/brep-mirror/joinery-brep.js.map +1 -1
- package/dist/api/generated/script-face-manifest.d.ts +4 -0
- package/dist/api/generated/script-face-manifest.d.ts.map +1 -1
- package/dist/api/generated/script-face-manifest.js.map +1 -1
- package/dist/api/index.d.ts +4 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +3 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/knurl.d.ts.map +1 -1
- package/dist/api/knurl.js +1 -0
- package/dist/api/knurl.js.map +1 -1
- package/dist/api/primitives.d.ts +4 -3
- package/dist/api/primitives.d.ts.map +1 -1
- package/dist/api/primitives.js +9 -3
- package/dist/api/primitives.js.map +1 -1
- package/dist/api/profile.d.ts +34 -5
- package/dist/api/profile.d.ts.map +1 -1
- package/dist/api/profile.js +168 -186
- package/dist/api/profile.js.map +1 -1
- package/dist/api/punch-hole.d.ts +77 -0
- package/dist/api/punch-hole.d.ts.map +1 -0
- package/dist/api/punch-hole.js +207 -0
- package/dist/api/punch-hole.js.map +1 -0
- package/dist/api/sketch-on-face.d.ts +85 -0
- package/dist/api/sketch-on-face.d.ts.map +1 -0
- package/dist/api/sketch-on-face.js +136 -0
- package/dist/api/sketch-on-face.js.map +1 -0
- package/dist/api/sketch-on-plane.d.ts +87 -0
- package/dist/api/sketch-on-plane.d.ts.map +1 -0
- package/dist/api/sketch-on-plane.js +106 -0
- package/dist/api/sketch-on-plane.js.map +1 -0
- package/dist/api/surface/arg-spec.d.ts +8 -0
- package/dist/api/surface/arg-spec.d.ts.map +1 -1
- package/dist/api/surface/arg-spec.js.map +1 -1
- package/dist/api/transform.d.ts +5 -5
- package/dist/api/transform.d.ts.map +1 -1
- package/dist/api/transform.js +12 -10
- package/dist/api/transform.js.map +1 -1
- package/dist/api/xml-dom.d.ts +27 -0
- package/dist/api/xml-dom.d.ts.map +1 -0
- package/dist/api/xml-dom.js +45 -0
- package/dist/api/xml-dom.js.map +1 -0
- package/dist/boolean/csg-backend.d.ts +6 -6
- package/dist/boolean/csg-backend.d.ts.map +1 -1
- package/dist/boolean/csg-backend.js +9 -9
- package/dist/boolean/csg-backend.js.map +1 -1
- package/dist/boolean/csg-core.d.ts +10 -10
- package/dist/boolean/csg-core.d.ts.map +1 -1
- package/dist/boolean/csg-core.js +24 -24
- package/dist/boolean/csg-core.js.map +1 -1
- package/dist/boolean/extrude-helpers.d.ts +8 -8
- package/dist/boolean/extrude-helpers.d.ts.map +1 -1
- package/dist/boolean/extrude-helpers.js +13 -13
- package/dist/boolean/extrude-helpers.js.map +1 -1
- package/dist/brep/brep-ops.d.ts +24 -10
- package/dist/brep/brep-ops.d.ts.map +1 -1
- package/dist/brep/brep-ops.js +46 -18
- package/dist/brep/brep-ops.js.map +1 -1
- package/dist/brep/brep-topology.d.ts.map +1 -1
- package/dist/brep/brep-topology.js +3 -1
- package/dist/brep/brep-topology.js.map +1 -1
- package/dist/brep/export/export-model.d.ts +79 -0
- package/dist/brep/export/export-model.d.ts.map +1 -0
- package/dist/brep/export/export-model.js +335 -0
- package/dist/brep/export/export-model.js.map +1 -0
- package/dist/brep/primitives-brep.d.ts.map +1 -1
- package/dist/brep/primitives-brep.js +3 -1
- package/dist/brep/primitives-brep.js.map +1 -1
- package/dist/brepkit-kernel/brepkitKernel.d.ts.map +1 -1
- package/dist/brepkit-kernel/brepkitKernel.js +4 -2
- package/dist/brepkit-kernel/brepkitKernel.js.map +1 -1
- package/dist/browser-host/csg-worker-protocol.d.ts +3 -3
- package/dist/browser-host/csg-worker-protocol.d.ts.map +1 -1
- package/dist/browser-host/csg-worker-protocol.js.map +1 -1
- package/dist/browser-host/csg-worker.js +3 -3
- package/dist/browser-host/csg-worker.js.map +1 -1
- package/dist/browser-host/inline-csg-backend.d.ts +3 -3
- package/dist/browser-host/inline-csg-backend.d.ts.map +1 -1
- package/dist/browser-host/inline-csg-backend.js +3 -3
- package/dist/browser-host/inline-csg-backend.js.map +1 -1
- package/dist/browser-host/worker-csg-backend.d.ts +3 -3
- package/dist/browser-host/worker-csg-backend.d.ts.map +1 -1
- package/dist/browser-host/worker-csg-backend.js.map +1 -1
- package/dist/cad-runtime/direct-executor.d.ts +4 -0
- package/dist/cad-runtime/direct-executor.d.ts.map +1 -1
- package/dist/cad-runtime/direct-executor.js +17 -1
- package/dist/cad-runtime/direct-executor.js.map +1 -1
- package/dist/cad-runtime/ports.d.ts +3 -3
- package/dist/cad-runtime/ports.d.ts.map +1 -1
- package/dist/cad-runtime/ports.js.map +1 -1
- package/dist/cad-runtime/runtime.d.ts +24 -1
- package/dist/cad-runtime/runtime.d.ts.map +1 -1
- package/dist/cad-runtime/runtime.js +53 -3
- package/dist/cad-runtime/runtime.js.map +1 -1
- package/dist/define-op.d.ts +22 -0
- package/dist/define-op.d.ts.map +1 -1
- package/dist/define-op.js +15 -0
- package/dist/define-op.js.map +1 -1
- package/dist/env-agnostic.d.ts +7 -7
- package/dist/env-agnostic.d.ts.map +1 -1
- package/dist/env-agnostic.js +3 -3
- package/dist/env-agnostic.js.map +1 -1
- package/dist/geometry2d/adapt.d.ts +46 -0
- package/dist/geometry2d/adapt.d.ts.map +1 -0
- package/dist/geometry2d/adapt.js +41 -0
- package/dist/geometry2d/adapt.js.map +1 -0
- package/dist/geometry2d/bbox2d.d.ts +82 -0
- package/dist/geometry2d/bbox2d.d.ts.map +1 -0
- package/dist/geometry2d/bbox2d.js +123 -0
- package/dist/geometry2d/bbox2d.js.map +1 -0
- package/dist/geometry2d/blueprint-sketcher.d.ts +27 -0
- package/dist/geometry2d/blueprint-sketcher.d.ts.map +1 -0
- package/dist/geometry2d/blueprint-sketcher.js +29 -0
- package/dist/geometry2d/blueprint-sketcher.js.map +1 -0
- package/dist/geometry2d/blueprint.d.ts +102 -0
- package/dist/geometry2d/blueprint.d.ts.map +1 -0
- package/dist/geometry2d/blueprint.js +225 -0
- package/dist/geometry2d/blueprint.js.map +1 -0
- package/dist/geometry2d/blueprints.d.ts +58 -0
- package/dist/geometry2d/blueprints.d.ts.map +1 -0
- package/dist/geometry2d/blueprints.js +72 -0
- package/dist/geometry2d/blueprints.js.map +1 -0
- package/dist/geometry2d/bridge/lift-on-plane.d.ts +50 -0
- package/dist/geometry2d/bridge/lift-on-plane.d.ts.map +1 -0
- package/dist/geometry2d/bridge/lift-on-plane.js +78 -0
- package/dist/geometry2d/bridge/lift-on-plane.js.map +1 -0
- package/dist/geometry2d/bridge/on-surface.d.ts +98 -0
- package/dist/geometry2d/bridge/on-surface.d.ts.map +1 -0
- package/dist/geometry2d/bridge/on-surface.js +94 -0
- package/dist/geometry2d/bridge/on-surface.js.map +1 -0
- package/dist/geometry2d/bridge/plane.d.ts +69 -0
- package/dist/geometry2d/bridge/plane.d.ts.map +1 -0
- package/dist/geometry2d/bridge/plane.js +96 -0
- package/dist/geometry2d/bridge/plane.js.map +1 -0
- package/dist/geometry2d/canned-blueprints.d.ts +44 -0
- package/dist/geometry2d/canned-blueprints.d.ts.map +1 -0
- package/dist/geometry2d/canned-blueprints.js +94 -0
- package/dist/geometry2d/canned-blueprints.js.map +1 -0
- package/dist/geometry2d/compound-blueprint.d.ts +72 -0
- package/dist/geometry2d/compound-blueprint.d.ts.map +1 -0
- package/dist/geometry2d/compound-blueprint.js +95 -0
- package/dist/geometry2d/compound-blueprint.js.map +1 -0
- package/dist/geometry2d/curve2d.d.ts +298 -0
- package/dist/geometry2d/curve2d.d.ts.map +1 -0
- package/dist/geometry2d/curve2d.js +1110 -0
- package/dist/geometry2d/curve2d.js.map +1 -0
- package/dist/geometry2d/index.d.ts +22 -0
- package/dist/geometry2d/index.d.ts.map +1 -0
- package/dist/geometry2d/index.js +21 -0
- package/dist/geometry2d/index.js.map +1 -0
- package/dist/geometry2d/organise.d.ts +28 -0
- package/dist/geometry2d/organise.d.ts.map +1 -0
- package/dist/geometry2d/organise.js +108 -0
- package/dist/geometry2d/organise.js.map +1 -0
- package/dist/geometry2d/pen-sketcher.d.ts +365 -0
- package/dist/geometry2d/pen-sketcher.d.ts.map +1 -0
- package/dist/geometry2d/pen-sketcher.js +520 -0
- package/dist/geometry2d/pen-sketcher.js.map +1 -0
- package/dist/geometry2d/point.d.ts +44 -0
- package/dist/geometry2d/point.d.ts.map +1 -0
- package/dist/geometry2d/point.js +57 -0
- package/dist/geometry2d/point.js.map +1 -0
- package/dist/geometry2d/svg-ellipse.d.ts +74 -0
- package/dist/geometry2d/svg-ellipse.d.ts.map +1 -0
- package/dist/geometry2d/svg-ellipse.js +163 -0
- package/dist/geometry2d/svg-ellipse.js.map +1 -0
- package/dist/lang/code-to-args.d.ts +29 -3
- package/dist/lang/code-to-args.d.ts.map +1 -1
- package/dist/lang/code-to-args.js +41 -2
- package/dist/lang/code-to-args.js.map +1 -1
- package/dist/lang/codegen.d.ts +45 -1
- package/dist/lang/codegen.d.ts.map +1 -1
- package/dist/lang/codegen.js +135 -6
- package/dist/lang/codegen.js.map +1 -1
- package/dist/lang/host-arg.d.ts +6 -0
- package/dist/lang/host-arg.d.ts.map +1 -1
- package/dist/lang/host-arg.js.map +1 -1
- package/dist/lang/metadata-extractor.d.ts +25 -0
- package/dist/lang/metadata-extractor.d.ts.map +1 -1
- package/dist/lang/metadata-extractor.js +289 -25
- package/dist/lang/metadata-extractor.js.map +1 -1
- package/dist/lang/parse-error.d.ts +7 -1
- package/dist/lang/parse-error.d.ts.map +1 -1
- package/dist/lang/parse-error.js.map +1 -1
- package/dist/lang/security-scanner.d.ts +9 -1
- package/dist/lang/security-scanner.d.ts.map +1 -1
- package/dist/lang/security-scanner.js +38 -1
- package/dist/lang/security-scanner.js.map +1 -1
- package/dist/lang/symbol-table.generated.d.ts +3 -0
- package/dist/lang/symbol-table.generated.d.ts.map +1 -1
- package/dist/lang/symbol-table.generated.js +3 -0
- package/dist/lang/symbol-table.generated.js.map +1 -1
- package/dist/mesh/io.d.ts +62 -9
- package/dist/mesh/io.d.ts.map +1 -1
- package/dist/mesh/io.js +124 -17
- package/dist/mesh/io.js.map +1 -1
- package/dist/mesh/threemf-loader.d.ts +15 -0
- package/dist/mesh/threemf-loader.d.ts.map +1 -0
- package/dist/mesh/threemf-loader.js +163 -0
- package/dist/mesh/threemf-loader.js.map +1 -0
- package/dist/mesh/transform.d.ts +2 -2
- package/dist/mesh/transform.d.ts.map +1 -1
- package/dist/mesh/transform.js +3 -3
- package/dist/mesh/transform.js.map +1 -1
- package/dist/mesh/types.d.ts +2 -2
- package/dist/mesh/types.d.ts.map +1 -1
- package/dist/mesh/types.js.map +1 -1
- package/dist/node-host/cli.d.ts.map +1 -1
- package/dist/node-host/cli.js +53 -26
- package/dist/node-host/cli.js.map +1 -1
- package/dist/occt-kernel/occtKernel.d.ts.map +1 -1
- package/dist/occt-kernel/occtKernel.js +4 -2
- package/dist/occt-kernel/occtKernel.js.map +1 -1
- package/dist/occt-kernel/topologyExt.d.ts.map +1 -1
- package/dist/occt-kernel/topologyExt.js +4 -1
- package/dist/occt-kernel/topologyExt.js.map +1 -1
- package/dist/runtime-state.d.ts +18 -0
- package/dist/runtime-state.d.ts.map +1 -1
- package/dist/runtime-state.js +23 -0
- package/dist/runtime-state.js.map +1 -1
- package/dist/sdk.d.ts +1 -1
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +1 -1
- package/dist/sdk.js.map +1 -1
- package/dist/tolerance.d.ts +38 -0
- package/dist/tolerance.d.ts.map +1 -0
- package/dist/tolerance.js +40 -0
- package/dist/tolerance.js.map +1 -0
- package/dist/topology/naming/score.js +3 -3
- package/dist/topology/naming/score.js.map +1 -1
- package/dist/units.d.ts +248 -0
- package/dist/units.d.ts.map +1 -0
- package/dist/units.js +397 -0
- package/dist/units.js.map +1 -0
- package/package.json +19 -2
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { centerOf, createBBox2d, mergeBBox } from './bbox2d.js';
|
|
2
|
+
/**
|
|
3
|
+
* Blueprints — collection of disjoint 2D profiles.
|
|
4
|
+
* Typical result of boolean operations producing multiple independent regions.
|
|
5
|
+
*/
|
|
6
|
+
export class Blueprints {
|
|
7
|
+
/** The independent profiles in this collection. */
|
|
8
|
+
blueprints;
|
|
9
|
+
_bbox = null;
|
|
10
|
+
constructor(blueprints) {
|
|
11
|
+
this.blueprints = blueprints;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Return a copy of this collection.
|
|
15
|
+
* @returns a new Blueprints whose profiles are clones of the originals.
|
|
16
|
+
*/
|
|
17
|
+
clone() {
|
|
18
|
+
return new Blueprints(this.blueprints.map((b) => b.clone()));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Bounding box (cached). The box spanning all contained profiles.
|
|
22
|
+
* @returns a BBox2d enclosing every profile in this collection.
|
|
23
|
+
*/
|
|
24
|
+
get boundingBox() {
|
|
25
|
+
if (!this._bbox) {
|
|
26
|
+
const bb = createBBox2d();
|
|
27
|
+
for (const b of this.blueprints)
|
|
28
|
+
mergeBBox(bb, b.boundingBox);
|
|
29
|
+
this._bbox = bb;
|
|
30
|
+
}
|
|
31
|
+
return this._bbox;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Scale every profile about a center point.
|
|
35
|
+
* @param factor - the scale factor to apply.
|
|
36
|
+
* @param center - the scaling center `[x, y]` (defaults to the bounding-box center).
|
|
37
|
+
* @returns a new Blueprints with every profile scaled.
|
|
38
|
+
*/
|
|
39
|
+
scale(factor, center) {
|
|
40
|
+
const ctr = center ?? centerOf(this.boundingBox);
|
|
41
|
+
return new Blueprints(this.blueprints.map((b) => b.scale(factor, ctr)));
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Translate every profile by a delta.
|
|
45
|
+
* @param dxOrPoint - the x delta, or a full `[dx, dy]` offset point.
|
|
46
|
+
* @param dy - the y delta (default 0, ignored when `dxOrPoint` is a point).
|
|
47
|
+
* @returns a new Blueprints with every profile translated.
|
|
48
|
+
*/
|
|
49
|
+
translate(dxOrPoint, dy) {
|
|
50
|
+
return new Blueprints(this.blueprints.map((b) => b.translate(dxOrPoint, dy ?? 0)));
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Rotate every profile about a center point.
|
|
54
|
+
* @param angleDeg - the rotation angle in degrees.
|
|
55
|
+
* @param center - the rotation center `[x, y]` (defaults to the origin).
|
|
56
|
+
* @returns a new Blueprints with every profile rotated.
|
|
57
|
+
*/
|
|
58
|
+
rotate(angleDeg, center) {
|
|
59
|
+
return new Blueprints(this.blueprints.map((b) => b.rotate(angleDeg, center)));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Mirror every profile.
|
|
63
|
+
* @param centerOrDirection - the mirror center (mode `center`) or the mirror axis direction.
|
|
64
|
+
* @param origin - the axis origin `[x, y]` when mirroring across a plane (defaults to the origin).
|
|
65
|
+
* @param mode - `center` mirrors about a point; `plane` mirrors across an axis.
|
|
66
|
+
* @returns a new Blueprints with every profile mirrored.
|
|
67
|
+
*/
|
|
68
|
+
mirror(centerOrDirection, origin, mode = 'center') {
|
|
69
|
+
return new Blueprints(this.blueprints.map((b) => b.mirror(centerOrDirection, origin, mode)));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=blueprints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blueprints.js","sourceRoot":"","sources":["../../src/geometry2d/blueprints.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAe,MAAM,UAAU,CAAA;AAEzE;;;GAGG;AACH,MAAM,OAAO,UAAU;IACrB,mDAAmD;IAC1C,UAAU,CAAsC;IAEjD,KAAK,GAAkB,IAAI,CAAA;IAEnC,YAAY,UAAgD;QAC1D,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;IAED;;;OAGG;IACH,KAAK;QACH,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IAC9D,CAAC;IAED;;;OAGG;IACH,IAAI,WAAW;QACb,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,MAAM,EAAE,GAAG,YAAY,EAAE,CAAA;YACzB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,UAAU;gBAAE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,CAAA;YAC7D,IAAI,CAAC,KAAK,GAAG,EAAE,CAAA;QACjB,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAA;IACnB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,MAAc,EAAE,MAAe;QACnC,MAAM,GAAG,GAAG,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QAChD,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;IACzE,CAAC;IAED;;;;;OAKG;IACH,SAAS,CAAC,SAA0B,EAAE,EAAW;QAC/C,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;IACpF,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,QAAgB,EAAE,MAAe;QACtC,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;IAC/E,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,iBAAyB,EAAE,MAAe,EAAE,OAA2B,QAAQ;QACpF,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;IAC9F,CAAC;CACF","sourcesContent":["/**\n * Blueprints — collection of disjoint 2D profiles (pure-data port of brepjs,\n * Apache-2.0). Typical result of boolean operations producing multiple regions.\n * @module\n */\nimport { Blueprint, type Point2 } from './blueprint'\nimport { CompoundBlueprint } from './compound-blueprint'\nimport { centerOf, createBBox2d, mergeBBox, type BBox2d } from './bbox2d'\n\n/**\n * Blueprints — collection of disjoint 2D profiles.\n * Typical result of boolean operations producing multiple independent regions.\n */\nexport class Blueprints {\n /** The independent profiles in this collection. */\n readonly blueprints: Array<Blueprint | CompoundBlueprint>\n\n private _bbox: BBox2d | null = null\n\n constructor(blueprints: Array<Blueprint | CompoundBlueprint>) {\n this.blueprints = blueprints\n }\n\n /**\n * Return a copy of this collection.\n * @returns a new Blueprints whose profiles are clones of the originals.\n */\n clone(): Blueprints {\n return new Blueprints(this.blueprints.map((b) => b.clone()))\n }\n\n /**\n * Bounding box (cached). The box spanning all contained profiles.\n * @returns a BBox2d enclosing every profile in this collection.\n */\n get boundingBox(): BBox2d {\n if (!this._bbox) {\n const bb = createBBox2d()\n for (const b of this.blueprints) mergeBBox(bb, b.boundingBox)\n this._bbox = bb\n }\n return this._bbox\n }\n\n /**\n * Scale every profile about a center point.\n * @param factor - the scale factor to apply.\n * @param center - the scaling center `[x, y]` (defaults to the bounding-box center).\n * @returns a new Blueprints with every profile scaled.\n */\n scale(factor: number, center?: Point2): Blueprints {\n const ctr = center ?? centerOf(this.boundingBox)\n return new Blueprints(this.blueprints.map((b) => b.scale(factor, ctr)))\n }\n\n /**\n * Translate every profile by a delta.\n * @param dxOrPoint - the x delta, or a full `[dx, dy]` offset point.\n * @param dy - the y delta (default 0, ignored when `dxOrPoint` is a point).\n * @returns a new Blueprints with every profile translated.\n */\n translate(dxOrPoint: number | Point2, dy?: number): Blueprints {\n return new Blueprints(this.blueprints.map((b) => b.translate(dxOrPoint, dy ?? 0)))\n }\n\n /**\n * Rotate every profile about a center point.\n * @param angleDeg - the rotation angle in degrees.\n * @param center - the rotation center `[x, y]` (defaults to the origin).\n * @returns a new Blueprints with every profile rotated.\n */\n rotate(angleDeg: number, center?: Point2): Blueprints {\n return new Blueprints(this.blueprints.map((b) => b.rotate(angleDeg, center)))\n }\n\n /**\n * Mirror every profile.\n * @param centerOrDirection - the mirror center (mode `center`) or the mirror axis direction.\n * @param origin - the axis origin `[x, y]` when mirroring across a plane (defaults to the origin).\n * @param mode - `center` mirrors about a point; `plane` mirrors across an axis.\n * @returns a new Blueprints with every profile mirrored.\n */\n mirror(centerOrDirection: Point2, origin?: Point2, mode: 'center' | 'plane' = 'center'): Blueprints {\n return new Blueprints(this.blueprints.map((b) => b.mirror(centerOrDirection, origin, mode)))\n }\n}"]}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 2D curve → 3D plane placement primitives (E2, occt-only bridge layer).
|
|
3
|
+
*
|
|
4
|
+
* This is the "lift" half of `sketchOnPlane`: it maps a pure-2D `Curve2dObj[]`
|
|
5
|
+
* (or `Blueprint`) onto an arbitrary plane and assembles the resulting 3D edges
|
|
6
|
+
* into a wire. `curvesAsEdgesOnPlane` / `assembleWire` mirror the plan's E2 work
|
|
7
|
+
* items. The kernel edge/wire primitives are accepted as `Pick<BrepEngineApi, …>`
|
|
8
|
+
* (the bridge may import the kernel contract, only `api/` is off-limits) so
|
|
9
|
+
* callers pass `getBrepApi()` directly with no casts.
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
import type { BrepEngineApi } from '../../brep/engine/primitives.js';
|
|
13
|
+
import type { BrepHandle } from '../../brep/engine/types.js';
|
|
14
|
+
import type { Curve2dObj } from '../curve2d.js';
|
|
15
|
+
import type { Blueprint } from '../blueprint.js';
|
|
16
|
+
import { type Plane } from './plane.js';
|
|
17
|
+
/** Minimal kernel edge/wire surface needed for planar placement. */
|
|
18
|
+
export type PlaneWireKernel = Pick<BrepEngineApi, 'makeLineEdge' | 'makeArcEdge' | 'makeBezierEdge' | 'makeWire'>;
|
|
19
|
+
/**
|
|
20
|
+
* Build the 3D edge(s) for a single 2D curve lifted onto a plane. Line and
|
|
21
|
+
* bezier build exact analytic edges; circle / trimmed-circle build a true arc
|
|
22
|
+
* edge from three on-plane lift points (a full circle is split into two arcs to
|
|
23
|
+
* keep `makeArcEdge` well-formed); ellipse / bspline fall back to a dense
|
|
24
|
+
* sampled polyline.
|
|
25
|
+
* @param kernel - the kernel edge primitives.
|
|
26
|
+
* @param plane - the target plane frame.
|
|
27
|
+
* @param c - the ordered 2D curve to lift.
|
|
28
|
+
* @returns the lifted 3D edge handle(s), in curve order.
|
|
29
|
+
*/
|
|
30
|
+
export declare function liftCurve2dToPlane(kernel: PlaneWireKernel, plane: Plane, c: Curve2dObj): BrepHandle[];
|
|
31
|
+
/**
|
|
32
|
+
* Lift an ordered list of 2D curves to edges on a plane frame.
|
|
33
|
+
* @param kernel - the kernel edge/wire primitives.
|
|
34
|
+
* @param plane - the target plane.
|
|
35
|
+
* @param curves - the ordered 2D curves (a closed loop stays closed).
|
|
36
|
+
* @returns the lifted 3D edge handles in the same order.
|
|
37
|
+
*/
|
|
38
|
+
export declare function curvesAsEdgesOnPlane(kernel: PlaneWireKernel, plane: Plane, curves: readonly Curve2dObj[]): BrepHandle[];
|
|
39
|
+
/**
|
|
40
|
+
* Assemble a Blueprint's curves into a 3D wire on a plane — the shared placement
|
|
41
|
+
* step for all of the profile / draw / sketch sources.
|
|
42
|
+
* @param kernel - the curve kernel/wire primitives.
|
|
43
|
+
* @param planeOrName - a plane frame or a named plane string (`'XY'` / `'XZ'` / …).
|
|
44
|
+
* @param bp - the blueprint whose ordered curves become the wire.
|
|
45
|
+
* @returns the assembled 3D wire.
|
|
46
|
+
*/
|
|
47
|
+
export declare function assembleWire(kernel: PlaneWireKernel, planeOrName: Plane | string, bp: Blueprint): BrepHandle;
|
|
48
|
+
export { liftPointToPlane, namedPlane, makePlane, toVec3 } from './plane.js';
|
|
49
|
+
export type { Plane, Vec3, Vec3Input } from './plane.js';
|
|
50
|
+
//# sourceMappingURL=lift-on-plane.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lift-on-plane.d.ts","sourceRoot":"","sources":["../../../src/geometry2d/bridge/lift-on-plane.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AACjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAAgC,KAAK,KAAK,EAAa,MAAM,SAAS,CAAA;AAE7E,oEAAoE;AACpE,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,aAAa,EAAE,cAAc,GAAG,aAAa,GAAG,gBAAgB,GAAG,UAAU,CAAC,CAAA;AAEjH;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,GAAG,UAAU,EAAE,CA4BrG;AAaD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,UAAU,EAAE,GAAG,UAAU,EAAE,CAIvH;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,KAAK,GAAG,MAAM,EAAE,EAAE,EAAE,SAAS,GAAG,UAAU,CAG5G;AAED,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AACzE,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { evaluateCurve2d } from '../curve2d.js';
|
|
2
|
+
import { namedPlane, liftPointToPlane } from './plane.js';
|
|
3
|
+
/**
|
|
4
|
+
* Build the 3D edge(s) for a single 2D curve lifted onto a plane. Line and
|
|
5
|
+
* bezier build exact analytic edges; circle / trimmed-circle build a true arc
|
|
6
|
+
* edge from three on-plane lift points (a full circle is split into two arcs to
|
|
7
|
+
* keep `makeArcEdge` well-formed); ellipse / bspline fall back to a dense
|
|
8
|
+
* sampled polyline.
|
|
9
|
+
* @param kernel - the kernel edge primitives.
|
|
10
|
+
* @param plane - the target plane frame.
|
|
11
|
+
* @param c - the ordered 2D curve to lift.
|
|
12
|
+
* @returns the lifted 3D edge handle(s), in curve order.
|
|
13
|
+
*/
|
|
14
|
+
export function liftCurve2dToPlane(kernel, plane, c) {
|
|
15
|
+
const on = (c2, t) => liftPointToPlane(plane, ...evaluateCurve2d(c2, t));
|
|
16
|
+
switch (c.kind2d) {
|
|
17
|
+
case 'line':
|
|
18
|
+
// P2 (2026-09-28, ArchDetail class): a fully-trimmed sketch can carry a
|
|
19
|
+
// ZERO-LENGTH line; makeLineEdge(start, start) is rejected by the OCCT
|
|
20
|
+
// kernel and killed the whole sketchOnPlane call. A zero-length segment
|
|
21
|
+
// contributes nothing to the wire — skip it.
|
|
22
|
+
if (c.len === 0)
|
|
23
|
+
return [];
|
|
24
|
+
return [
|
|
25
|
+
kernel.makeLineEdge(liftPointToPlane(plane, c.ox, c.oy), liftPointToPlane(plane, c.ox + c.dx * c.len, c.oy + c.dy * c.len)),
|
|
26
|
+
];
|
|
27
|
+
case 'bezier':
|
|
28
|
+
return [kernel.makeBezierEdge(c.poles.map(([x, y]) => liftPointToPlane(plane, x, y)))];
|
|
29
|
+
case 'circle':
|
|
30
|
+
return [
|
|
31
|
+
kernel.makeArcEdge(on(c, 0), on(c, Math.PI / 2), on(c, Math.PI)),
|
|
32
|
+
kernel.makeArcEdge(on(c, Math.PI), on(c, (3 * Math.PI) / 2), on(c, 2 * Math.PI)),
|
|
33
|
+
];
|
|
34
|
+
case 'trimmed':
|
|
35
|
+
if (c.basis.kind2d === 'circle')
|
|
36
|
+
return [kernel.makeArcEdge(on(c, 0), on(c, 0.5), on(c, 1))];
|
|
37
|
+
return sampledEdges(kernel, plane, c);
|
|
38
|
+
default:
|
|
39
|
+
return sampledEdges(kernel, plane, c);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/** Sample a non-analytic curve into a polyline of `makeLineEdge`s on the plane. */
|
|
43
|
+
function sampledEdges(kernel, plane, c) {
|
|
44
|
+
const out = [];
|
|
45
|
+
for (let k = 0; k < 32; k++) {
|
|
46
|
+
const t0 = k / 32;
|
|
47
|
+
const t1 = (k + 1) / 32;
|
|
48
|
+
out.push(kernel.makeLineEdge(liftPointToPlane(plane, ...evaluateCurve2d(c, t0)), liftPointToPlane(plane, ...evaluateCurve2d(c, t1))));
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Lift an ordered list of 2D curves to edges on a plane frame.
|
|
54
|
+
* @param kernel - the kernel edge/wire primitives.
|
|
55
|
+
* @param plane - the target plane.
|
|
56
|
+
* @param curves - the ordered 2D curves (a closed loop stays closed).
|
|
57
|
+
* @returns the lifted 3D edge handles in the same order.
|
|
58
|
+
*/
|
|
59
|
+
export function curvesAsEdgesOnPlane(kernel, plane, curves) {
|
|
60
|
+
const out = [];
|
|
61
|
+
for (const c of curves)
|
|
62
|
+
out.push(...liftCurve2dToPlane(kernel, plane, c));
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Assemble a Blueprint's curves into a 3D wire on a plane — the shared placement
|
|
67
|
+
* step for all of the profile / draw / sketch sources.
|
|
68
|
+
* @param kernel - the curve kernel/wire primitives.
|
|
69
|
+
* @param planeOrName - a plane frame or a named plane string (`'XY'` / `'XZ'` / …).
|
|
70
|
+
* @param bp - the blueprint whose ordered curves become the wire.
|
|
71
|
+
* @returns the assembled 3D wire.
|
|
72
|
+
*/
|
|
73
|
+
export function assembleWire(kernel, planeOrName, bp) {
|
|
74
|
+
const plane = typeof planeOrName === 'string' ? namedPlane(planeOrName) : planeOrName;
|
|
75
|
+
return kernel.makeWire(curvesAsEdgesOnPlane(kernel, plane, bp.curves));
|
|
76
|
+
}
|
|
77
|
+
export { liftPointToPlane, namedPlane, makePlane, toVec3 } from './plane.js';
|
|
78
|
+
//# sourceMappingURL=lift-on-plane.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lift-on-plane.js","sourceRoot":"","sources":["../../../src/geometry2d/bridge/lift-on-plane.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 2D curve → 3D plane placement primitives (E2, occt-only bridge layer).\n *\n * This is the \"lift\" half of `sketchOnPlane`: it maps a pure-2D `Curve2dObj[]`\n * (or `Blueprint`) onto an arbitrary plane and assembles the resulting 3D edges\n * into a wire. `curvesAsEdgesOnPlane` / `assembleWire` mirror the plan's E2 work\n * items. The kernel edge/wire primitives are accepted as `Pick<BrepEngineApi, …>`\n * (the bridge may import the kernel contract, only `api/` is off-limits) so\n * callers pass `getBrepApi()` directly with no casts.\n * @module\n */\nimport type { BrepEngineApi } from '../../brep/engine/primitives'\nimport type { BrepHandle } from '../../brep/engine/types'\nimport type { Curve2dObj } from '../curve2d'\nimport { evaluateCurve2d } from '../curve2d'\nimport type { Blueprint } from '../blueprint'\nimport { namedPlane, liftPointToPlane, type Plane, type Vec3 } from './plane'\n\n/** Minimal kernel edge/wire surface needed for planar placement. */\nexport type PlaneWireKernel = Pick<BrepEngineApi, 'makeLineEdge' | 'makeArcEdge' | 'makeBezierEdge' | 'makeWire'>\n\n/**\n * Build the 3D edge(s) for a single 2D curve lifted onto a plane. Line and\n * bezier build exact analytic edges; circle / trimmed-circle build a true arc\n * edge from three on-plane lift points (a full circle is split into two arcs to\n * keep `makeArcEdge` well-formed); ellipse / bspline fall back to a dense\n * sampled polyline.\n * @param kernel - the kernel edge primitives.\n * @param plane - the target plane frame.\n * @param c - the ordered 2D curve to lift.\n * @returns the lifted 3D edge handle(s), in curve order.\n */\nexport function liftCurve2dToPlane(kernel: PlaneWireKernel, plane: Plane, c: Curve2dObj): BrepHandle[] {\n const on = (c2: Curve2dObj, t: number): Vec3 => liftPointToPlane(plane, ...evaluateCurve2d(c2, t))\n switch (c.kind2d) {\n case 'line':\n // P2 (2026-09-28, ArchDetail class): a fully-trimmed sketch can carry a\n // ZERO-LENGTH line; makeLineEdge(start, start) is rejected by the OCCT\n // kernel and killed the whole sketchOnPlane call. A zero-length segment\n // contributes nothing to the wire — skip it.\n if (c.len === 0) return []\n return [\n kernel.makeLineEdge(\n liftPointToPlane(plane, c.ox, c.oy),\n liftPointToPlane(plane, c.ox + c.dx * c.len, c.oy + c.dy * c.len),\n ),\n ]\n case 'bezier':\n return [kernel.makeBezierEdge(c.poles.map(([x, y]) => liftPointToPlane(plane, x, y)))]\n case 'circle':\n return [\n kernel.makeArcEdge(on(c, 0), on(c, Math.PI / 2), on(c, Math.PI)),\n kernel.makeArcEdge(on(c, Math.PI), on(c, (3 * Math.PI) / 2), on(c, 2 * Math.PI)),\n ]\n case 'trimmed':\n if (c.basis.kind2d === 'circle') return [kernel.makeArcEdge(on(c, 0), on(c, 0.5), on(c, 1))]\n return sampledEdges(kernel, plane, c)\n default:\n return sampledEdges(kernel, plane, c)\n }\n}\n\n/** Sample a non-analytic curve into a polyline of `makeLineEdge`s on the plane. */\nfunction sampledEdges(kernel: PlaneWireKernel, plane: Plane, c: Curve2dObj): BrepHandle[] {\n const out: BrepHandle[] = []\n for (let k = 0; k < 32; k++) {\n const t0 = k / 32\n const t1 = (k + 1) / 32\n out.push(kernel.makeLineEdge(liftPointToPlane(plane, ...evaluateCurve2d(c, t0)), liftPointToPlane(plane, ...evaluateCurve2d(c, t1))))\n }\n return out\n}\n\n/**\n * Lift an ordered list of 2D curves to edges on a plane frame.\n * @param kernel - the kernel edge/wire primitives.\n * @param plane - the target plane.\n * @param curves - the ordered 2D curves (a closed loop stays closed).\n * @returns the lifted 3D edge handles in the same order.\n */\nexport function curvesAsEdgesOnPlane(kernel: PlaneWireKernel, plane: Plane, curves: readonly Curve2dObj[]): BrepHandle[] {\n const out: BrepHandle[] = []\n for (const c of curves) out.push(...liftCurve2dToPlane(kernel, plane, c))\n return out\n}\n\n/**\n * Assemble a Blueprint's curves into a 3D wire on a plane — the shared placement\n * step for all of the profile / draw / sketch sources.\n * @param kernel - the curve kernel/wire primitives.\n * @param planeOrName - a plane frame or a named plane string (`'XY'` / `'XZ'` / …).\n * @param bp - the blueprint whose ordered curves become the wire.\n * @returns the assembled 3D wire.\n */\nexport function assembleWire(kernel: PlaneWireKernel, planeOrName: Plane | string, bp: Blueprint): BrepHandle {\n const plane = typeof planeOrName === 'string' ? namedPlane(planeOrName) : planeOrName\n return kernel.makeWire(curvesAsEdgesOnPlane(kernel, plane, bp.curves))\n}\n\nexport { liftPointToPlane, namedPlane, makePlane, toVec3 } from './plane'\nexport type { Plane, Vec3, Vec3Input } from './plane'"]}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 2D curve → face UV-surface placement primitives (E3, occt-only bridge layer).
|
|
3
|
+
*
|
|
4
|
+
* This is the "on-surface" half of `sketchOnFace`: it places a pure-2D
|
|
5
|
+
* `Curve2dObj[]` contour onto the UV parameter domain of an existing face and
|
|
6
|
+
* assembles 3D edges living on that surface. Unlike `liftCurve2dToPlane` (which
|
|
7
|
+
* maps 2D onto a plane *frame*), `buildEdgeOnSurface` samples each 2D curve,
|
|
8
|
+
* maps the samples into the face's UV space under a scale mode, evaluates the
|
|
9
|
+
* surface at those UVs via `pointOnSurface(face,u,v)`, and interpolates a
|
|
10
|
+
* B-spline edge through the resulting 3D points — the plan's §164 composite
|
|
11
|
+
* approach (engine-method-map marks `buildEdgeOnSurface` as "occt 适配器组合实现").
|
|
12
|
+
* It is surface-type-independent (plane / cylinder / any parametric surface).
|
|
13
|
+
*
|
|
14
|
+
* The three scale modes (plan §164):
|
|
15
|
+
* - `original`: `u=x, v=y` — reads 2D coordinates as face UVs directly.
|
|
16
|
+
* - `bounds` / `native`: affine-fit the 2D contour's bounding box onto the
|
|
17
|
+
* face's UV bounds, ratio-preserving — the generic mode for any face.
|
|
18
|
+
*
|
|
19
|
+
* The UV-mapping functions are pure and the bridge takes an injected
|
|
20
|
+
* `Pick<BrepEngineApi, …>` kernel plus the target face handle, so the math is
|
|
21
|
+
* unit-testable with a recording kernel exactly like `lift-on-plane.ts` (no
|
|
22
|
+
* occt-wasm needed). The bridge imports the kernel contract and `geometry2d`
|
|
23
|
+
* only — `api/` is off-limits.
|
|
24
|
+
*
|
|
25
|
+
* @module
|
|
26
|
+
*/
|
|
27
|
+
import type { BrepEngineApi } from '../../brep/engine/primitives.js';
|
|
28
|
+
import type { BrepUvBounds, BrepHandle } from '../../brep/engine/types.js';
|
|
29
|
+
import type { Curve2dObj } from '../curve2d.js';
|
|
30
|
+
import type { Blueprint } from '../blueprint.js';
|
|
31
|
+
/** How a 2D contour's coordinates map onto a face's UV space (`cad.sketchOnFace`). */
|
|
32
|
+
export type FaceScaleMode = 'original' | 'bounds' | 'native';
|
|
33
|
+
/** An axis-aligned 2D box (the contour's coordinate span). */
|
|
34
|
+
export interface Rect2d {
|
|
35
|
+
x0: number;
|
|
36
|
+
x1: number;
|
|
37
|
+
y0: number;
|
|
38
|
+
y1: number;
|
|
39
|
+
}
|
|
40
|
+
/** A 3D surface point (the `pointOnSurface` result). */
|
|
41
|
+
export interface SurfacePoint {
|
|
42
|
+
x: number;
|
|
43
|
+
y: number;
|
|
44
|
+
z: number;
|
|
45
|
+
}
|
|
46
|
+
/** `(x,y)` → `(u,v)` face parameter-space mapping (pure). */
|
|
47
|
+
export type UvMap = (x: number, y: number) => [number, number];
|
|
48
|
+
/** Kernel surface needed for curve-on-face placement (wider than the plane-lift Pick). */
|
|
49
|
+
export type SurfaceEdgesKernel = Pick<BrepEngineApi, 'pointOnSurface' | 'uvBounds' | 'interpolatePoints' | 'makeLineEdge' | 'makeWire'>;
|
|
50
|
+
/** BrepVec3 element type handed to `interpolatePoints` / returned by `pointOnSurface`. */
|
|
51
|
+
export type SurfaceVec3 = SurfacePoint;
|
|
52
|
+
/**
|
|
53
|
+
* Sample the tight axis-aligned 2D bounding box of an ordered curve set, used
|
|
54
|
+
* to affine-fit a contour onto a face's UV bounds under `bounds`/`native`.
|
|
55
|
+
* @param curves - the ordered 2D curves of a single contour.
|
|
56
|
+
* @returns the sampled bounding rect; an empty set becomes the origin rect.
|
|
57
|
+
*/
|
|
58
|
+
export declare function curves2dBounds(curves: readonly Curve2dObj[]): Rect2d;
|
|
59
|
+
/**
|
|
60
|
+
* Build a `(x,y)` → `(u,v)` mapping for a scale mode against a face's UV bounds.
|
|
61
|
+
* `original` returns the identity (2D coords are read as UVs). `bounds`/`native`
|
|
62
|
+
* affine-scale the contour's 2D box onto the full UV bounds, preserving aspect.
|
|
63
|
+
* @param mode - the face-scale mode.
|
|
64
|
+
* @param rect - the 2D bounding box of the contour (sampled; ignored by `original`).
|
|
65
|
+
* @param bounds - the face UV bounds from `uvBounds`.
|
|
66
|
+
* @returns an `(x,y)` → `(u,v)` function (pure; assertable in unit tests).
|
|
67
|
+
*/
|
|
68
|
+
export declare function makeUvMap(mode: FaceScaleMode, rect: Rect2d, bounds: BrepUvBounds): UvMap;
|
|
69
|
+
/**
|
|
70
|
+
* Build the 3D edge for a single 2D curve laid on a face: sample the curve, map
|
|
71
|
+
* samples to UV under the given mapping, evaluate the face surface there, and
|
|
72
|
+
* interpolate a curve edge through the resulting 3D points. A curve that
|
|
73
|
+
* evaluates to 2 or fewer distinct points is emitted as an exact `makeLineEdge`
|
|
74
|
+
* (the planar fast path).
|
|
75
|
+
* @param kernel - the surface kernel (`pointOnSurface` + `interpolatePoints`).
|
|
76
|
+
* @param face - the target face handle (for `pointOnSurface(face,u,v)`).
|
|
77
|
+
* @param uv - the UV mapping for this curve (see `makeUvMap`).
|
|
78
|
+
* @param c - the ordered 2D curve to place on the face.
|
|
79
|
+
* @param samples - the sample count per curve (>= 3 for smooth edges).
|
|
80
|
+
* @returns the placed 3D edge handle (one per curve).
|
|
81
|
+
*/
|
|
82
|
+
export declare function buildEdgeOnSurface(kernel: Pick<SurfaceEdgesKernel, 'pointOnSurface' | 'interpolatePoints' | 'makeLineEdge'>, face: BrepHandle, uv: UvMap, c: Curve2dObj, samples?: number): BrepHandle;
|
|
83
|
+
/**
|
|
84
|
+
* Place every curve of a contour onto a face's UV space and assemble a wire.
|
|
85
|
+
* Computes the face UV bounds and the contour's 2D box, derives the UV map for
|
|
86
|
+
* the chosen scale mode, and buildings edges + a `makeWire` on the surface.
|
|
87
|
+
* @param kernel - the surface kernel.
|
|
88
|
+
* @param face - the target face handle.
|
|
89
|
+
* @param mode - the face-scale mode (`original`/`bounds`/`native`).
|
|
90
|
+
* @param bp - the blueprint whose ordered curves become on-face edges.
|
|
91
|
+
* @param samples - samples per curve (default 12).
|
|
92
|
+
* @returns `{ wire, uv }`: the assembled 3D wire and the UV map used.
|
|
93
|
+
*/
|
|
94
|
+
export declare function assembleWireOnFace(kernel: Pick<SurfaceEdgesKernel, 'pointOnSurface' | 'uvBounds' | 'interpolatePoints' | 'makeLineEdge' | 'makeWire'>, face: BrepHandle, mode: FaceScaleMode, bp: Blueprint, samples?: number): {
|
|
95
|
+
wire: BrepHandle;
|
|
96
|
+
uv: UvMap;
|
|
97
|
+
};
|
|
98
|
+
//# sourceMappingURL=on-surface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"on-surface.d.ts","sourceRoot":"","sources":["../../../src/geometry2d/bridge/on-surface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACvE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,sFAAsF;AACtF,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAE5D,8DAA8D;AAC9D,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;IACV,EAAE,EAAE,MAAM,CAAA;CACX;AAED,wDAAwD;AACxD,MAAM,WAAW,YAAY;IAC3B,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED,6DAA6D;AAC7D,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAE9D,0FAA0F;AAC1F,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACnC,aAAa,EACb,gBAAgB,GAAG,UAAU,GAAG,mBAAmB,GAAG,cAAc,GAAG,UAAU,CAClF,CAAA;AAED,0FAA0F;AAC1F,MAAM,MAAM,WAAW,GAAG,YAAY,CAAA;AAEtC;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,GAAG,MAAM,CAqBpE;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,GAAG,KAAK,CAKxF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,GAAG,mBAAmB,GAAG,cAAc,CAAC,EACzF,IAAI,EAAE,UAAU,EAChB,EAAE,EAAE,KAAK,EACT,CAAC,EAAE,UAAU,EACb,OAAO,SAAK,GACX,UAAU,CAYZ;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,IAAI,CAAC,kBAAkB,EAAE,gBAAgB,GAAG,UAAU,GAAG,mBAAmB,GAAG,cAAc,GAAG,UAAU,CAAC,EACnH,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,aAAa,EACnB,EAAE,EAAE,SAAS,EACb,OAAO,SAAK,GACX;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,EAAE,EAAE,KAAK,CAAA;CAAE,CAKjC"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { evaluateCurve2d, curveBounds } from '../curve2d.js';
|
|
2
|
+
/**
|
|
3
|
+
* Sample the tight axis-aligned 2D bounding box of an ordered curve set, used
|
|
4
|
+
* to affine-fit a contour onto a face's UV bounds under `bounds`/`native`.
|
|
5
|
+
* @param curves - the ordered 2D curves of a single contour.
|
|
6
|
+
* @returns the sampled bounding rect; an empty set becomes the origin rect.
|
|
7
|
+
*/
|
|
8
|
+
export function curves2dBounds(curves) {
|
|
9
|
+
const segments = 100;
|
|
10
|
+
let x0 = Infinity;
|
|
11
|
+
let x1 = -Infinity;
|
|
12
|
+
let y0 = Infinity;
|
|
13
|
+
let y1 = -Infinity;
|
|
14
|
+
for (const c of curves) {
|
|
15
|
+
// Sample across the curve's actual domain (a line spans [0,len] arc length, a
|
|
16
|
+
// full circle [0,2π]); the naive [0,1] interval would under-measure both.
|
|
17
|
+
const { first, last } = curveBounds(c);
|
|
18
|
+
for (let k = 0; k <= segments; k++) {
|
|
19
|
+
const t = first + ((last - first) * k) / segments;
|
|
20
|
+
const [x, y] = evaluateCurve2d(c, t);
|
|
21
|
+
if (x < x0)
|
|
22
|
+
x0 = x;
|
|
23
|
+
if (x > x1)
|
|
24
|
+
x1 = x;
|
|
25
|
+
if (y < y0)
|
|
26
|
+
y0 = y;
|
|
27
|
+
if (y > y1)
|
|
28
|
+
y1 = y;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (x0 === Infinity)
|
|
32
|
+
return { x0: 0, x1: 0, y0: 0, y1: 0 };
|
|
33
|
+
return { x0, x1, y0, y1 };
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Build a `(x,y)` → `(u,v)` mapping for a scale mode against a face's UV bounds.
|
|
37
|
+
* `original` returns the identity (2D coords are read as UVs). `bounds`/`native`
|
|
38
|
+
* affine-scale the contour's 2D box onto the full UV bounds, preserving aspect.
|
|
39
|
+
* @param mode - the face-scale mode.
|
|
40
|
+
* @param rect - the 2D bounding box of the contour (sampled; ignored by `original`).
|
|
41
|
+
* @param bounds - the face UV bounds from `uvBounds`.
|
|
42
|
+
* @returns an `(x,y)` → `(u,v)` function (pure; assertable in unit tests).
|
|
43
|
+
*/
|
|
44
|
+
export function makeUvMap(mode, rect, bounds) {
|
|
45
|
+
if (mode === 'original')
|
|
46
|
+
return (x, y) => [x, y];
|
|
47
|
+
const su = rect.x1 > rect.x0 ? (bounds.uMax - bounds.uMin) / (rect.x1 - rect.x0) : 0;
|
|
48
|
+
const sv = rect.y1 > rect.y0 ? (bounds.vMax - bounds.vMin) / (rect.y1 - rect.y0) : 0;
|
|
49
|
+
return (x, y) => [bounds.uMin + (x - rect.x0) * su, bounds.vMin + (y - rect.y0) * sv];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build the 3D edge for a single 2D curve laid on a face: sample the curve, map
|
|
53
|
+
* samples to UV under the given mapping, evaluate the face surface there, and
|
|
54
|
+
* interpolate a curve edge through the resulting 3D points. A curve that
|
|
55
|
+
* evaluates to 2 or fewer distinct points is emitted as an exact `makeLineEdge`
|
|
56
|
+
* (the planar fast path).
|
|
57
|
+
* @param kernel - the surface kernel (`pointOnSurface` + `interpolatePoints`).
|
|
58
|
+
* @param face - the target face handle (for `pointOnSurface(face,u,v)`).
|
|
59
|
+
* @param uv - the UV mapping for this curve (see `makeUvMap`).
|
|
60
|
+
* @param c - the ordered 2D curve to place on the face.
|
|
61
|
+
* @param samples - the sample count per curve (>= 3 for smooth edges).
|
|
62
|
+
* @returns the placed 3D edge handle (one per curve).
|
|
63
|
+
*/
|
|
64
|
+
export function buildEdgeOnSurface(kernel, face, uv, c, samples = 12) {
|
|
65
|
+
const raw = [];
|
|
66
|
+
for (let k = 0; k <= samples; k++) {
|
|
67
|
+
const [x, y] = evaluateCurve2d(c, k / samples);
|
|
68
|
+
const [u, v] = uv(x, y);
|
|
69
|
+
raw.push(kernel.pointOnSurface(face, u, v));
|
|
70
|
+
}
|
|
71
|
+
const unique = Array.from(new Map(raw.map((p) => [`${p.x},${p.y},${p.z}`, p])).values());
|
|
72
|
+
if (unique.length <= 2) {
|
|
73
|
+
return kernel.makeLineEdge(unique[0], unique[unique.length - 1]);
|
|
74
|
+
}
|
|
75
|
+
return kernel.interpolatePoints(unique, 3);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Place every curve of a contour onto a face's UV space and assemble a wire.
|
|
79
|
+
* Computes the face UV bounds and the contour's 2D box, derives the UV map for
|
|
80
|
+
* the chosen scale mode, and buildings edges + a `makeWire` on the surface.
|
|
81
|
+
* @param kernel - the surface kernel.
|
|
82
|
+
* @param face - the target face handle.
|
|
83
|
+
* @param mode - the face-scale mode (`original`/`bounds`/`native`).
|
|
84
|
+
* @param bp - the blueprint whose ordered curves become on-face edges.
|
|
85
|
+
* @param samples - samples per curve (default 12).
|
|
86
|
+
* @returns `{ wire, uv }`: the assembled 3D wire and the UV map used.
|
|
87
|
+
*/
|
|
88
|
+
export function assembleWireOnFace(kernel, face, mode, bp, samples = 12) {
|
|
89
|
+
const bounds = kernel.uvBounds(face);
|
|
90
|
+
const uv = makeUvMap(mode, curves2dBounds(bp.curves), bounds);
|
|
91
|
+
const edges = bp.curves.map((c) => buildEdgeOnSurface(kernel, face, uv, c, samples));
|
|
92
|
+
return { wire: kernel.makeWire(edges), uv };
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=on-surface.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"on-surface.js","sourceRoot":"","sources":["../../../src/geometry2d/bridge/on-surface.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 2D curve → face UV-surface placement primitives (E3, occt-only bridge layer).\n *\n * This is the \"on-surface\" half of `sketchOnFace`: it places a pure-2D\n * `Curve2dObj[]` contour onto the UV parameter domain of an existing face and\n * assembles 3D edges living on that surface. Unlike `liftCurve2dToPlane` (which\n * maps 2D onto a plane *frame*), `buildEdgeOnSurface` samples each 2D curve,\n * maps the samples into the face's UV space under a scale mode, evaluates the\n * surface at those UVs via `pointOnSurface(face,u,v)`, and interpolates a\n * B-spline edge through the resulting 3D points — the plan's §164 composite\n * approach (engine-method-map marks `buildEdgeOnSurface` as \"occt 适配器组合实现\").\n * It is surface-type-independent (plane / cylinder / any parametric surface).\n *\n * The three scale modes (plan §164):\n * - `original`: `u=x, v=y` — reads 2D coordinates as face UVs directly.\n * - `bounds` / `native`: affine-fit the 2D contour's bounding box onto the\n * face's UV bounds, ratio-preserving — the generic mode for any face.\n *\n * The UV-mapping functions are pure and the bridge takes an injected\n * `Pick<BrepEngineApi, …>` kernel plus the target face handle, so the math is\n * unit-testable with a recording kernel exactly like `lift-on-plane.ts` (no\n * occt-wasm needed). The bridge imports the kernel contract and `geometry2d`\n * only — `api/` is off-limits.\n *\n * @module\n */\nimport type { BrepEngineApi } from '../../brep/engine/primitives'\nimport type { BrepUvBounds, BrepHandle } from '../../brep/engine/types'\nimport type { Curve2dObj } from '../curve2d'\nimport { evaluateCurve2d, curveBounds } from '../curve2d'\nimport type { Blueprint } from '../blueprint'\n\n/** How a 2D contour's coordinates map onto a face's UV space (`cad.sketchOnFace`). */\nexport type FaceScaleMode = 'original' | 'bounds' | 'native'\n\n/** An axis-aligned 2D box (the contour's coordinate span). */\nexport interface Rect2d {\n x0: number\n x1: number\n y0: number\n y1: number\n}\n\n/** A 3D surface point (the `pointOnSurface` result). */\nexport interface SurfacePoint {\n x: number\n y: number\n z: number\n}\n\n/** `(x,y)` → `(u,v)` face parameter-space mapping (pure). */\nexport type UvMap = (x: number, y: number) => [number, number]\n\n/** Kernel surface needed for curve-on-face placement (wider than the plane-lift Pick). */\nexport type SurfaceEdgesKernel = Pick<\n BrepEngineApi,\n 'pointOnSurface' | 'uvBounds' | 'interpolatePoints' | 'makeLineEdge' | 'makeWire'\n>\n\n/** BrepVec3 element type handed to `interpolatePoints` / returned by `pointOnSurface`. */\nexport type SurfaceVec3 = SurfacePoint\n\n/**\n * Sample the tight axis-aligned 2D bounding box of an ordered curve set, used\n * to affine-fit a contour onto a face's UV bounds under `bounds`/`native`.\n * @param curves - the ordered 2D curves of a single contour.\n * @returns the sampled bounding rect; an empty set becomes the origin rect.\n */\nexport function curves2dBounds(curves: readonly Curve2dObj[]): Rect2d {\n const segments = 100\n let x0 = Infinity\n let x1 = -Infinity\n let y0 = Infinity\n let y1 = -Infinity\n for (const c of curves) {\n // Sample across the curve's actual domain (a line spans [0,len] arc length, a\n // full circle [0,2π]); the naive [0,1] interval would under-measure both.\n const { first, last } = curveBounds(c)\n for (let k = 0; k <= segments; k++) {\n const t = first + ((last - first) * k) / segments\n const [x, y] = evaluateCurve2d(c, t)\n if (x < x0) x0 = x\n if (x > x1) x1 = x\n if (y < y0) y0 = y\n if (y > y1) y1 = y\n }\n }\n if (x0 === Infinity) return { x0: 0, x1: 0, y0: 0, y1: 0 }\n return { x0, x1, y0, y1 }\n}\n\n/**\n * Build a `(x,y)` → `(u,v)` mapping for a scale mode against a face's UV bounds.\n * `original` returns the identity (2D coords are read as UVs). `bounds`/`native`\n * affine-scale the contour's 2D box onto the full UV bounds, preserving aspect.\n * @param mode - the face-scale mode.\n * @param rect - the 2D bounding box of the contour (sampled; ignored by `original`).\n * @param bounds - the face UV bounds from `uvBounds`.\n * @returns an `(x,y)` → `(u,v)` function (pure; assertable in unit tests).\n */\nexport function makeUvMap(mode: FaceScaleMode, rect: Rect2d, bounds: BrepUvBounds): UvMap {\n if (mode === 'original') return (x, y) => [x, y]\n const su = rect.x1 > rect.x0 ? (bounds.uMax - bounds.uMin) / (rect.x1 - rect.x0) : 0\n const sv = rect.y1 > rect.y0 ? (bounds.vMax - bounds.vMin) / (rect.y1 - rect.y0) : 0\n return (x, y) => [bounds.uMin + (x - rect.x0) * su, bounds.vMin + (y - rect.y0) * sv]\n}\n\n/**\n * Build the 3D edge for a single 2D curve laid on a face: sample the curve, map\n * samples to UV under the given mapping, evaluate the face surface there, and\n * interpolate a curve edge through the resulting 3D points. A curve that\n * evaluates to 2 or fewer distinct points is emitted as an exact `makeLineEdge`\n * (the planar fast path).\n * @param kernel - the surface kernel (`pointOnSurface` + `interpolatePoints`).\n * @param face - the target face handle (for `pointOnSurface(face,u,v)`).\n * @param uv - the UV mapping for this curve (see `makeUvMap`).\n * @param c - the ordered 2D curve to place on the face.\n * @param samples - the sample count per curve (>= 3 for smooth edges).\n * @returns the placed 3D edge handle (one per curve).\n */\nexport function buildEdgeOnSurface(\n kernel: Pick<SurfaceEdgesKernel, 'pointOnSurface' | 'interpolatePoints' | 'makeLineEdge'>,\n face: BrepHandle,\n uv: UvMap,\n c: Curve2dObj,\n samples = 12,\n): BrepHandle {\n const raw: SurfacePoint[] = []\n for (let k = 0; k <= samples; k++) {\n const [x, y] = evaluateCurve2d(c, k / samples)\n const [u, v] = uv(x, y)\n raw.push(kernel.pointOnSurface(face, u, v))\n }\n const unique = Array.from(new Map(raw.map((p) => [`${p.x},${p.y},${p.z}`, p])).values())\n if (unique.length <= 2) {\n return kernel.makeLineEdge(unique[0]!, unique[unique.length - 1]!)\n }\n return kernel.interpolatePoints(unique, 3)\n}\n\n/**\n * Place every curve of a contour onto a face's UV space and assemble a wire.\n * Computes the face UV bounds and the contour's 2D box, derives the UV map for\n * the chosen scale mode, and buildings edges + a `makeWire` on the surface.\n * @param kernel - the surface kernel.\n * @param face - the target face handle.\n * @param mode - the face-scale mode (`original`/`bounds`/`native`).\n * @param bp - the blueprint whose ordered curves become on-face edges.\n * @param samples - samples per curve (default 12).\n * @returns `{ wire, uv }`: the assembled 3D wire and the UV map used.\n */\nexport function assembleWireOnFace(\n kernel: Pick<SurfaceEdgesKernel, 'pointOnSurface' | 'uvBounds' | 'interpolatePoints' | 'makeLineEdge' | 'makeWire'>,\n face: BrepHandle,\n mode: FaceScaleMode,\n bp: Blueprint,\n samples = 12,\n): { wire: BrepHandle; uv: UvMap } {\n const bounds = kernel.uvBounds(face)\n const uv = makeUvMap(mode, curves2dBounds(bp.curves), bounds)\n const edges = bp.curves.map((c) => buildEdgeOnSurface(kernel, face, uv, c, samples) as never)\n return { wire: kernel.makeWire(edges), uv }\n}"]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plane frame helpers for 2D→3D placement (pure TS, no kernel, no `api/` import).
|
|
3
|
+
*
|
|
4
|
+
* A {@link Plane} carries an origin plus a right-handed, orthonormal frame
|
|
5
|
+
* `xDir / yDir / zDir` where `zDir` is the plane normal — the same semantic as
|
|
6
|
+
* the kernel `gp_Ax3` frame and the `createPlane` helper in `api/brepjs-compat`.
|
|
7
|
+
* The bridge may **not** import `api/` (plan rule against a cycle), so this
|
|
8
|
+
* module re-derives the framing math self-containedly. Points use the
|
|
9
|
+
* `{ x, y, z }` shape compatible with the BREP engine's neutral `BrepVec3`.
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
/** A 3D point / vector (neutral {x,y,z} shape, kernel-compatible). */
|
|
13
|
+
export interface Vec3 {
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
z: number;
|
|
17
|
+
}
|
|
18
|
+
/** User-facing 3D input: `{x,y,z}` object or `[x,y,z]` array (the script form). */
|
|
19
|
+
export type Vec3Input = Vec3 | readonly [number, number, number];
|
|
20
|
+
/**
|
|
21
|
+
* Normalize a raw script- or API-facing 3D input to the canonical `{x,y,z}`.
|
|
22
|
+
* Accepts both the array form (`[1,0,0]`, as produced by `.fai.js` literals)
|
|
23
|
+
* and the object form (`{x,y,z}`, used by the bridge internals).
|
|
24
|
+
* @param v - the input 3D value.
|
|
25
|
+
* @returns the canonical vector.
|
|
26
|
+
*/
|
|
27
|
+
export declare function toVec3(v: Vec3Input): Vec3;
|
|
28
|
+
/**
|
|
29
|
+
* A right-handed, orthonormal plane frame: an origin plus `xDir`/`yDir` (in-plane
|
|
30
|
+
* axes) and `zDir` (the normal). 2D `(x, y)` maps to `origin + x*xDir + y*yDir`.
|
|
31
|
+
*/
|
|
32
|
+
export interface Plane {
|
|
33
|
+
/** The plane's anchor point (the 2D origin maps here). */
|
|
34
|
+
readonly origin: Vec3;
|
|
35
|
+
/** The in-plane X axis (maps the 2D +X). */
|
|
36
|
+
readonly xDir: Vec3;
|
|
37
|
+
/** The in-plane Y axis (maps the 2D +Y). */
|
|
38
|
+
readonly yDir: Vec3;
|
|
39
|
+
/** The plane normal (2D +Z after placement). */
|
|
40
|
+
readonly zDir: Vec3;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Build a right-handed plane frame from an origin, a normal, and an optional
|
|
44
|
+
* in-plane X direction. The X direction is auto-derived (least-aligned-axis
|
|
45
|
+
* cross product) when omitted, mirroring the kernel `gp_Ax3` convention.
|
|
46
|
+
* @param origin - the plane origin (2D origin maps here).
|
|
47
|
+
* @param normal - the plane normal (becomes the zDir); must be non-zero.
|
|
48
|
+
* @param xDir - optional explicit in-plane X; auto-derived when omitted.
|
|
49
|
+
* @returns the orthonormal plane frame.
|
|
50
|
+
*/
|
|
51
|
+
export declare function makePlane(origin: Vec3Input, normal: Vec3Input, xDir?: Vec3Input): Plane;
|
|
52
|
+
/**
|
|
53
|
+
* Resolve a named plane (e.g. `'XY'` / `'XZ'` / `'top'`) to a frame at a given
|
|
54
|
+
* origin. Unknown names throw.
|
|
55
|
+
* @param name - the canonical plane name.
|
|
56
|
+
* @param origin - the plane origin (default [0,0,0]).
|
|
57
|
+
* @returns the plane frame.
|
|
58
|
+
*/
|
|
59
|
+
export declare function namedPlane(name: string, origin?: Vec3Input): Plane;
|
|
60
|
+
/**
|
|
61
|
+
* Map a 2D point `(x, y)` into 3D on a plane frame:
|
|
62
|
+
* `origin + x*xDir + y*yDir`. This is the per-point lift used by curve lifting.
|
|
63
|
+
* @param plane - the target plane.
|
|
64
|
+
* @param x - the 2D `x` coordinate.
|
|
65
|
+
* @param y - the 2D `y` coordinate.
|
|
66
|
+
* @returns the 3D point on the plane.
|
|
67
|
+
*/
|
|
68
|
+
export declare function liftPointToPlane(plane: Plane, x: number, y: number): Vec3;
|
|
69
|
+
//# sourceMappingURL=plane.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plane.d.ts","sourceRoot":"","sources":["../../../src/geometry2d/bridge/plane.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,sEAAsE;AACtE,MAAM,WAAW,IAAI;IACnB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;CACV;AAED,mFAAmF;AACnF,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAEhE;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,SAAS,GAAG,IAAI,CAIzC;AAED;;;GAGG;AACH,MAAM,WAAW,KAAK;IACpB,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAA;IACrB,4CAA4C;IAC5C,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;IACnB,4CAA4C;IAC5C,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;IACnB,gDAAgD;IAChD,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;CACpB;AAeD;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,KAAK,CAcvF;AAeD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,SAAgC,GAAG,KAAK,CAIxF;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAGzE"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plane frame helpers for 2D→3D placement (pure TS, no kernel, no `api/` import).
|
|
3
|
+
*
|
|
4
|
+
* A {@link Plane} carries an origin plus a right-handed, orthonormal frame
|
|
5
|
+
* `xDir / yDir / zDir` where `zDir` is the plane normal — the same semantic as
|
|
6
|
+
* the kernel `gp_Ax3` frame and the `createPlane` helper in `api/brepjs-compat`.
|
|
7
|
+
* The bridge may **not** import `api/` (plan rule against a cycle), so this
|
|
8
|
+
* module re-derives the framing math self-containedly. Points use the
|
|
9
|
+
* `{ x, y, z }` shape compatible with the BREP engine's neutral `BrepVec3`.
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Normalize a raw script- or API-facing 3D input to the canonical `{x,y,z}`.
|
|
14
|
+
* Accepts both the array form (`[1,0,0]`, as produced by `.fai.js` literals)
|
|
15
|
+
* and the object form (`{x,y,z}`, used by the bridge internals).
|
|
16
|
+
* @param v - the input 3D value.
|
|
17
|
+
* @returns the canonical vector.
|
|
18
|
+
*/
|
|
19
|
+
export function toVec3(v) {
|
|
20
|
+
if (Array.isArray(v))
|
|
21
|
+
return { x: v[0], y: v[1], z: v[2] };
|
|
22
|
+
const o = v;
|
|
23
|
+
return { x: o.x, y: o.y, z: o.z };
|
|
24
|
+
}
|
|
25
|
+
function cross(a, b) {
|
|
26
|
+
return { x: a.y * b.z - a.z * b.y, y: a.z * b.x - a.x * b.z, z: a.x * b.y - a.y * b.x };
|
|
27
|
+
}
|
|
28
|
+
function norm(v) {
|
|
29
|
+
return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
|
|
30
|
+
}
|
|
31
|
+
function normalize(v) {
|
|
32
|
+
const len = norm(v);
|
|
33
|
+
return len > 1e-14 ? { x: v.x / len, y: v.y / len, z: v.z / len } : { x: 1, y: 0, z: 0 };
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Build a right-handed plane frame from an origin, a normal, and an optional
|
|
37
|
+
* in-plane X direction. The X direction is auto-derived (least-aligned-axis
|
|
38
|
+
* cross product) when omitted, mirroring the kernel `gp_Ax3` convention.
|
|
39
|
+
* @param origin - the plane origin (2D origin maps here).
|
|
40
|
+
* @param normal - the plane normal (becomes the zDir); must be non-zero.
|
|
41
|
+
* @param xDir - optional explicit in-plane X; auto-derived when omitted.
|
|
42
|
+
* @returns the orthonormal plane frame.
|
|
43
|
+
*/
|
|
44
|
+
export function makePlane(origin, normal, xDir) {
|
|
45
|
+
const o = toVec3(origin);
|
|
46
|
+
const z = normalize(toVec3(normal));
|
|
47
|
+
let x;
|
|
48
|
+
if (xDir) {
|
|
49
|
+
x = normalize(toVec3(xDir));
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const ax = Math.abs(z.x), ay = Math.abs(z.y), az = Math.abs(z.z);
|
|
53
|
+
const cand = ax <= ay && ax <= az ? { x: 1, y: 0, z: 0 } : ay <= az ? { x: 0, y: 1, z: 0 } : { x: 0, y: 0, z: 1 };
|
|
54
|
+
x = normalize(cross(cand, z));
|
|
55
|
+
}
|
|
56
|
+
const y = normalize(cross(z, x));
|
|
57
|
+
return { origin: o, xDir: x, yDir: y, zDir: z };
|
|
58
|
+
}
|
|
59
|
+
/** Named CAD planes with their canonical frames (origin defaults to [0,0,0]). */
|
|
60
|
+
const NAMED_PLANES = {
|
|
61
|
+
XY: { xDir: { x: 1, y: 0, z: 0 }, zDir: { x: 0, y: 0, z: 1 } },
|
|
62
|
+
XZ: { xDir: { x: 1, y: 0, z: 0 }, zDir: { x: 0, y: -1, z: 0 } },
|
|
63
|
+
YZ: { xDir: { x: 0, y: 1, z: 0 }, zDir: { x: 1, y: 0, z: 0 } },
|
|
64
|
+
front: { xDir: { x: 1, y: 0, z: 0 }, zDir: { x: 0, y: 0, z: 1 } },
|
|
65
|
+
back: { xDir: { x: -1, y: 0, z: 0 }, zDir: { x: 0, y: 0, z: -1 } },
|
|
66
|
+
left: { xDir: { x: 0, y: 0, z: 1 }, zDir: { x: -1, y: 0, z: 0 } },
|
|
67
|
+
right: { xDir: { x: 0, y: 0, z: -1 }, zDir: { x: 1, y: 0, z: 0 } },
|
|
68
|
+
top: { xDir: { x: 1, y: 0, z: 0 }, zDir: { x: 0, y: 1, z: 0 } },
|
|
69
|
+
bottom: { xDir: { x: 1, y: 0, z: 0 }, zDir: { x: 0, y: -1, z: 0 } },
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Resolve a named plane (e.g. `'XY'` / `'XZ'` / `'top'`) to a frame at a given
|
|
73
|
+
* origin. Unknown names throw.
|
|
74
|
+
* @param name - the canonical plane name.
|
|
75
|
+
* @param origin - the plane origin (default [0,0,0]).
|
|
76
|
+
* @returns the plane frame.
|
|
77
|
+
*/
|
|
78
|
+
export function namedPlane(name, origin = { x: 0, y: 0, z: 0 }) {
|
|
79
|
+
const cfg = NAMED_PLANES[name];
|
|
80
|
+
if (!cfg)
|
|
81
|
+
throw new Error(`unknown plane '${name}' (expected XY | XZ | YZ | front/back/left/right/top/bottom)`);
|
|
82
|
+
return makePlane(toVec3(origin), cfg.zDir, cfg.xDir);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Map a 2D point `(x, y)` into 3D on a plane frame:
|
|
86
|
+
* `origin + x*xDir + y*yDir`. This is the per-point lift used by curve lifting.
|
|
87
|
+
* @param plane - the target plane.
|
|
88
|
+
* @param x - the 2D `x` coordinate.
|
|
89
|
+
* @param y - the 2D `y` coordinate.
|
|
90
|
+
* @returns the 3D point on the plane.
|
|
91
|
+
*/
|
|
92
|
+
export function liftPointToPlane(plane, x, y) {
|
|
93
|
+
const { origin: o, xDir: u, yDir: v } = plane;
|
|
94
|
+
return { x: o.x + x * u.x + y * v.x, y: o.y + x * u.y + y * v.y, z: o.z + x * u.z + y * v.z };
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=plane.js.map
|