@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,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Axis-aligned 2D bounding box (pure-data; faijs port of brepjs `BoundingBox2d`).
|
|
3
|
+
* brepjs backs this with a kernel `Bnd_Box2d`; here it's plain numbers.
|
|
4
|
+
*
|
|
5
|
+
* License: adapted from brepjs (Apache-2.0).
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Create an empty (inverted) bounding box.
|
|
10
|
+
* @returns a fresh BBox2d whose mins are +Infinity and maxes are -Infinity.
|
|
11
|
+
*/
|
|
12
|
+
export function createBBox2d() {
|
|
13
|
+
return { xMin: Infinity, yMin: Infinity, xMax: -Infinity, yMax: -Infinity };
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* True when the box holds no finite extent yet.
|
|
17
|
+
* @param bb - the bounding box to test.
|
|
18
|
+
* @returns true when any corner is non-finite or the box is inverted.
|
|
19
|
+
*/
|
|
20
|
+
export function isEmpty(bb) {
|
|
21
|
+
return (!isFinite(bb.xMin) || !isFinite(bb.yMin) || !isFinite(bb.xMax) || !isFinite(bb.yMax) ||
|
|
22
|
+
bb.xMax < bb.xMin || bb.yMax < bb.yMin);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Expand `bb` to include the given corner points.
|
|
26
|
+
* @param bb - the bounding box to expand in place.
|
|
27
|
+
* @param pts - the corner points to include.
|
|
28
|
+
*/
|
|
29
|
+
export function addPoints(bb, pts) {
|
|
30
|
+
for (const [x, y] of pts) {
|
|
31
|
+
if (x < bb.xMin)
|
|
32
|
+
bb.xMin = x;
|
|
33
|
+
if (y < bb.yMin)
|
|
34
|
+
bb.yMin = y;
|
|
35
|
+
if (x > bb.xMax)
|
|
36
|
+
bb.xMax = x;
|
|
37
|
+
if (y > bb.yMax)
|
|
38
|
+
bb.yMax = y;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Expand `bb` to include all points of `other`.
|
|
43
|
+
* @param bb - the box to expand in place.
|
|
44
|
+
* @param other - the box whose extent is folded into `bb`.
|
|
45
|
+
*/
|
|
46
|
+
export function mergeBBox(bb, other) {
|
|
47
|
+
if (other.xMin < bb.xMin)
|
|
48
|
+
bb.xMin = other.xMin;
|
|
49
|
+
if (other.yMin < bb.yMin)
|
|
50
|
+
bb.yMin = other.yMin;
|
|
51
|
+
if (other.xMax > bb.xMax)
|
|
52
|
+
bb.xMax = other.xMax;
|
|
53
|
+
if (other.yMax > bb.yMax)
|
|
54
|
+
bb.yMax = other.yMax;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Return `[min, max]` corner points.
|
|
58
|
+
* @param bb - the bounding box to read from.
|
|
59
|
+
* @returns the lower-left and upper-right corners as `[[xMin,yMin],[xMax,yMax]]`.
|
|
60
|
+
*/
|
|
61
|
+
export function boundsOf(bb) {
|
|
62
|
+
return [
|
|
63
|
+
[bb.xMin, bb.yMin],
|
|
64
|
+
[bb.xMax, bb.yMax],
|
|
65
|
+
];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Compute the center point of the box.
|
|
69
|
+
* @param bb - the bounding box to read from.
|
|
70
|
+
* @returns the midpoint `[x, y]` between the min and max corners.
|
|
71
|
+
*/
|
|
72
|
+
export function centerOf(bb) {
|
|
73
|
+
return [(bb.xMin + bb.xMax) / 2, (bb.yMin + bb.yMax) / 2];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Compute the width of the box.
|
|
77
|
+
* @param bb - the bounding box to read from.
|
|
78
|
+
* @returns the absolute horizontal extent.
|
|
79
|
+
*/
|
|
80
|
+
export function widthOf(bb) {
|
|
81
|
+
return Math.abs(bb.xMax - bb.xMin);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Compute the height of the box.
|
|
85
|
+
* @param bb - the bounding box to read from.
|
|
86
|
+
* @returns the absolute vertical extent.
|
|
87
|
+
*/
|
|
88
|
+
export function heightOf(bb) {
|
|
89
|
+
return Math.abs(bb.yMax - bb.yMin);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Point guaranteed outside (to the upper-right of) the box.
|
|
93
|
+
* @param bb - the bounding box to read from.
|
|
94
|
+
* @param paddingPercent - the padding as a percent of the box extent (default 1).
|
|
95
|
+
* @returns a point offset to the upper-right of `bb`.
|
|
96
|
+
*/
|
|
97
|
+
export function outsidePointOf(bb, paddingPercent = 1) {
|
|
98
|
+
const width = bb.xMax - bb.xMin;
|
|
99
|
+
const height = bb.yMax - bb.yMin;
|
|
100
|
+
return [bb.xMax + (width / 100) * paddingPercent, bb.yMax + (height / 100) * paddingPercent * 0.9];
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* True if `bb` and `other` are completely disjoint.
|
|
104
|
+
* @param bb - the first bounding box.
|
|
105
|
+
* @param other - the second bounding box.
|
|
106
|
+
* @returns true when the two boxes do not overlap (empty boxes count as disjoint).
|
|
107
|
+
*/
|
|
108
|
+
export function isBBoxOut(bb, other) {
|
|
109
|
+
// Handles degenerate (empty) boxes by treating them as disjoint.
|
|
110
|
+
if (isEmpty(bb) || isEmpty(other))
|
|
111
|
+
return true;
|
|
112
|
+
return other.xMax < bb.xMin || other.xMin > bb.xMax || other.yMax < bb.yMin || other.yMin > bb.yMax;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* True if the point lies inside (or on the boundary of) the box.
|
|
116
|
+
* @param bb - the bounding box to test against.
|
|
117
|
+
* @param pt - the 2D point to test, `[x, y]`.
|
|
118
|
+
* @returns true when `pt` is within (or on) the box.
|
|
119
|
+
*/
|
|
120
|
+
export function containsPoint(bb, pt) {
|
|
121
|
+
return (pt[0] >= bb.xMin && pt[0] <= bb.xMax && pt[1] >= bb.yMin && pt[1] <= bb.yMax);
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=bbox2d.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bbox2d.js","sourceRoot":"","sources":["../../src/geometry2d/bbox2d.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Axis-aligned 2D bounding box (pure-data; faijs port of brepjs `BoundingBox2d`).\n * brepjs backs this with a kernel `Bnd_Box2d`; here it's plain numbers.\n *\n * License: adapted from brepjs (Apache-2.0).\n * @module\n */\n\nexport interface BBox2d {\n xMin: number\n yMin: number\n xMax: number\n yMax: number\n}\n\n/**\n * Create an empty (inverted) bounding box.\n * @returns a fresh BBox2d whose mins are +Infinity and maxes are -Infinity.\n */\nexport function createBBox2d(): BBox2d {\n return { xMin: Infinity, yMin: Infinity, xMax: -Infinity, yMax: -Infinity }\n}\n\n/**\n * True when the box holds no finite extent yet.\n * @param bb - the bounding box to test.\n * @returns true when any corner is non-finite or the box is inverted.\n */\nexport function isEmpty(bb: BBox2d): boolean {\n return (\n !isFinite(bb.xMin) || !isFinite(bb.yMin) || !isFinite(bb.xMax) || !isFinite(bb.yMax) ||\n bb.xMax < bb.xMin || bb.yMax < bb.yMin\n )\n}\n\n/**\n * Expand `bb` to include the given corner points.\n * @param bb - the bounding box to expand in place.\n * @param pts - the corner points to include.\n */\nexport function addPoints(bb: BBox2d, pts: ReadonlyArray<readonly [number, number]>): void {\n for (const [x, y] of pts) {\n if (x < bb.xMin) bb.xMin = x\n if (y < bb.yMin) bb.yMin = y\n if (x > bb.xMax) bb.xMax = x\n if (y > bb.yMax) bb.yMax = y\n }\n}\n\n/**\n * Expand `bb` to include all points of `other`.\n * @param bb - the box to expand in place.\n * @param other - the box whose extent is folded into `bb`.\n */\nexport function mergeBBox(bb: BBox2d, other: BBox2d): void {\n if (other.xMin < bb.xMin) bb.xMin = other.xMin\n if (other.yMin < bb.yMin) bb.yMin = other.yMin\n if (other.xMax > bb.xMax) bb.xMax = other.xMax\n if (other.yMax > bb.yMax) bb.yMax = other.yMax\n}\n\n/**\n * Return `[min, max]` corner points.\n * @param bb - the bounding box to read from.\n * @returns the lower-left and upper-right corners as `[[xMin,yMin],[xMax,yMax]]`.\n */\nexport function boundsOf(bb: BBox2d): [[number, number], [number, number]] {\n return [\n [bb.xMin, bb.yMin],\n [bb.xMax, bb.yMax],\n ]\n}\n\n/**\n * Compute the center point of the box.\n * @param bb - the bounding box to read from.\n * @returns the midpoint `[x, y]` between the min and max corners.\n */\nexport function centerOf(bb: BBox2d): [number, number] {\n return [(bb.xMin + bb.xMax) / 2, (bb.yMin + bb.yMax) / 2]\n}\n\n/**\n * Compute the width of the box.\n * @param bb - the bounding box to read from.\n * @returns the absolute horizontal extent.\n */\nexport function widthOf(bb: BBox2d): number {\n return Math.abs(bb.xMax - bb.xMin)\n}\n\n/**\n * Compute the height of the box.\n * @param bb - the bounding box to read from.\n * @returns the absolute vertical extent.\n */\nexport function heightOf(bb: BBox2d): number {\n return Math.abs(bb.yMax - bb.yMin)\n}\n\n/**\n * Point guaranteed outside (to the upper-right of) the box.\n * @param bb - the bounding box to read from.\n * @param paddingPercent - the padding as a percent of the box extent (default 1).\n * @returns a point offset to the upper-right of `bb`.\n */\nexport function outsidePointOf(bb: BBox2d, paddingPercent = 1): [number, number] {\n const width = bb.xMax - bb.xMin\n const height = bb.yMax - bb.yMin\n return [bb.xMax + (width / 100) * paddingPercent, bb.yMax + (height / 100) * paddingPercent * 0.9]\n}\n\n/**\n * True if `bb` and `other` are completely disjoint.\n * @param bb - the first bounding box.\n * @param other - the second bounding box.\n * @returns true when the two boxes do not overlap (empty boxes count as disjoint).\n */\nexport function isBBoxOut(bb: BBox2d, other: BBox2d): boolean {\n // Handles degenerate (empty) boxes by treating them as disjoint.\n if (isEmpty(bb) || isEmpty(other)) return true\n return other.xMax < bb.xMin || other.xMin > bb.xMax || other.yMax < bb.yMin || other.yMin > bb.yMax\n}\n\n/**\n * True if the point lies inside (or on the boundary of) the box.\n * @param bb - the bounding box to test against.\n * @param pt - the 2D point to test, `[x, y]`.\n * @returns true when `pt` is within (or on) the box.\n */\nexport function containsPoint(bb: BBox2d, pt: readonly [number, number]): boolean {\n return (\n pt[0] >= bb.xMin && pt[0] <= bb.xMax && pt[1] >= bb.yMin && pt[1] <= bb.yMax\n )\n}"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* geometry2d — `BlueprintSketcher` (C2): a pen that packages its curves as a
|
|
3
|
+
* `Blueprint`.
|
|
4
|
+
*
|
|
5
|
+
* Ported from brepjs `2d/blueprints/blueprintSketcher.ts` (Apache-2.0). Built
|
|
6
|
+
* on the pure `BaseSketcher2d`. `done()` returns the still-open contour as a
|
|
7
|
+
* `Blueprint`; callers that want a closed contour draw the closing segment
|
|
8
|
+
* (the base `close()` does this) and wrap the result.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
import { Blueprint } from './blueprint.js';
|
|
13
|
+
import { BaseSketcher2d } from './pen-sketcher.js';
|
|
14
|
+
/**
|
|
15
|
+
* A `BaseSketcher2d` that packages the drawn contour as a `Blueprint`.
|
|
16
|
+
*
|
|
17
|
+
* Extends the pen with a `done()` result owner; closes still go through:
|
|
18
|
+
* `new Blueprint(pen.close())` yields the closed contour as a `Blueprint`.
|
|
19
|
+
*/
|
|
20
|
+
export declare class BlueprintSketcher extends BaseSketcher2d {
|
|
21
|
+
/**
|
|
22
|
+
* Package the accumulated curves as a `Blueprint` without closing.
|
|
23
|
+
* @returns the open Blueprint of the drawn contour.
|
|
24
|
+
*/
|
|
25
|
+
done(): Blueprint;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=blueprint-sketcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blueprint-sketcher.d.ts","sourceRoot":"","sources":["../../src/geometry2d/blueprint-sketcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAE/C;;;;;GAKG;AACH,qBAAa,iBAAkB,SAAQ,cAAc;IACnD;;;OAGG;IACH,IAAI,IAAI,SAAS;CAGlB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* geometry2d — `BlueprintSketcher` (C2): a pen that packages its curves as a
|
|
3
|
+
* `Blueprint`.
|
|
4
|
+
*
|
|
5
|
+
* Ported from brepjs `2d/blueprints/blueprintSketcher.ts` (Apache-2.0). Built
|
|
6
|
+
* on the pure `BaseSketcher2d`. `done()` returns the still-open contour as a
|
|
7
|
+
* `Blueprint`; callers that want a closed contour draw the closing segment
|
|
8
|
+
* (the base `close()` does this) and wrap the result.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
import { Blueprint } from './blueprint.js';
|
|
13
|
+
import { BaseSketcher2d } from './pen-sketcher.js';
|
|
14
|
+
/**
|
|
15
|
+
* A `BaseSketcher2d` that packages the drawn contour as a `Blueprint`.
|
|
16
|
+
*
|
|
17
|
+
* Extends the pen with a `done()` result owner; closes still go through:
|
|
18
|
+
* `new Blueprint(pen.close())` yields the closed contour as a `Blueprint`.
|
|
19
|
+
*/
|
|
20
|
+
export class BlueprintSketcher extends BaseSketcher2d {
|
|
21
|
+
/**
|
|
22
|
+
* Package the accumulated curves as a `Blueprint` without closing.
|
|
23
|
+
* @returns the open Blueprint of the drawn contour.
|
|
24
|
+
*/
|
|
25
|
+
done() {
|
|
26
|
+
return new Blueprint([...this.pendingCurves]);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=blueprint-sketcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blueprint-sketcher.js","sourceRoot":"","sources":["../../src/geometry2d/blueprint-sketcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAE/C;;;;;GAKG;AACH,MAAM,OAAO,iBAAkB,SAAQ,cAAc;IACnD;;;OAGG;IACH,IAAI;QACF,OAAO,IAAI,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAA;IAC/C,CAAC;CACF","sourcesContent":["/**\n * geometry2d — `BlueprintSketcher` (C2): a pen that packages its curves as a\n * `Blueprint`.\n *\n * Ported from brepjs `2d/blueprints/blueprintSketcher.ts` (Apache-2.0). Built\n * on the pure `BaseSketcher2d`. `done()` returns the still-open contour as a\n * `Blueprint`; callers that want a closed contour draw the closing segment\n * (the base `close()` does this) and wrap the result.\n *\n * @module\n */\n\nimport { Blueprint } from './blueprint'\nimport { BaseSketcher2d } from './pen-sketcher'\n\n/**\n * A `BaseSketcher2d` that packages the drawn contour as a `Blueprint`.\n *\n * Extends the pen with a `done()` result owner; closes still go through:\n * `new Blueprint(pen.close())` yields the closed contour as a `Blueprint`.\n */\nexport class BlueprintSketcher extends BaseSketcher2d {\n /**\n * Package the accumulated curves as a `Blueprint` without closing.\n * @returns the open Blueprint of the drawn contour.\n */\n done(): Blueprint {\n return new Blueprint([...this.pendingCurves])\n }\n}"]}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Blueprint — ordered 2D profile of `Curve2dObj` segments (pure-data port of
|
|
3
|
+
* brepjs `Blueprint`, Apache-2.0).
|
|
4
|
+
*
|
|
5
|
+
* Key adaptation: brepjs stores kernel-backed `Curve2D` handles that must be
|
|
6
|
+
* disposed; faijs stores plain `Curve2dObj` objects (no handles, no dispose).
|
|
7
|
+
* Kernel-coupling methods (sketchOnPlane / sketchOnFace / subFace / punchHole)
|
|
8
|
+
* intentionally live in `geometry2d/bridge`, not here.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
import type { Curve2dObj } from './curve2d.js';
|
|
13
|
+
import { type BBox2d } from './bbox2d.js';
|
|
14
|
+
/** 2D point. */
|
|
15
|
+
export type Point2 = [number, number];
|
|
16
|
+
/**
|
|
17
|
+
* True when `(x,y)` is within `tol` of curve `c`.
|
|
18
|
+
* @param c - the curve to test against.
|
|
19
|
+
* @param pt - the 2D point to test, `[x, y]`.
|
|
20
|
+
* @param tol - the distance tolerance (default 1e-9).
|
|
21
|
+
* @returns true when the point lies within `tol` of the curve.
|
|
22
|
+
*/
|
|
23
|
+
export declare function isOnCurve(c: Curve2dObj, pt: readonly [number, number], tol?: number): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* A planar 2D profile = an ordered sequence of 2D curves.
|
|
26
|
+
* Shared base for `cad.profile`, `cad.draw` and (solved) `cad.sketch` outputs on
|
|
27
|
+
* their way to `sketchOnPlane`/`sketchOnFace`.
|
|
28
|
+
*/
|
|
29
|
+
export declare class Blueprint {
|
|
30
|
+
/** Ordered 2D curve segments composing this blueprint. */
|
|
31
|
+
readonly curves: Curve2dObj[];
|
|
32
|
+
private _bbox;
|
|
33
|
+
private _orientation;
|
|
34
|
+
private _guessedOrientation;
|
|
35
|
+
constructor(curves: Curve2dObj[]);
|
|
36
|
+
/**
|
|
37
|
+
* Return a shallow copy of this blueprint (new container, same curve objects).
|
|
38
|
+
* @returns a new Blueprint with the same curves.
|
|
39
|
+
*/
|
|
40
|
+
clone(): Blueprint;
|
|
41
|
+
/** Bounding box (cached). */
|
|
42
|
+
get boundingBox(): BBox2d;
|
|
43
|
+
/** Winding orientation via shoelace (curve midpoints for non-lines). */
|
|
44
|
+
get orientation(): 'clockwise' | 'counterClockwise';
|
|
45
|
+
/**
|
|
46
|
+
* Scale the blueprint about a center point.
|
|
47
|
+
* @param factor - the scale factor to apply.
|
|
48
|
+
* @param center - the scaling center `[x, y]` (defaults to the bounding-box center).
|
|
49
|
+
* @returns a new Blueprint with every curve scaled about the center.
|
|
50
|
+
*/
|
|
51
|
+
scale(factor: number, center?: Point2): Blueprint;
|
|
52
|
+
/**
|
|
53
|
+
* Translate the whole blueprint by a delta.
|
|
54
|
+
* @param dxOrPoint - the x delta, or a full `[dx, dy]` offset point.
|
|
55
|
+
* @param dy - the y delta (default 0, ignored when `dxOrPoint` is a point).
|
|
56
|
+
* @returns a new Blueprint with every curve translated.
|
|
57
|
+
*/
|
|
58
|
+
translate(dxOrPoint: number | Point2, dy?: number): Blueprint;
|
|
59
|
+
/**
|
|
60
|
+
* Rotate the whole blueprint about a center point.
|
|
61
|
+
* @param angleDeg - the rotation angle in degrees.
|
|
62
|
+
* @param center - the rotation center `[x, y]` (defaults to the origin).
|
|
63
|
+
* @returns a new Blueprint with every curve rotated.
|
|
64
|
+
*/
|
|
65
|
+
rotate(angleDeg: number, center?: Point2): Blueprint;
|
|
66
|
+
/**
|
|
67
|
+
* Mirror the whole blueprint.
|
|
68
|
+
* @param centerOrDirection - the mirror center (mode `center`) or the mirror axis direction.
|
|
69
|
+
* @param origin - the axis origin `[x, y]` when mirroring across a plane (defaults to the origin).
|
|
70
|
+
* @param mode - `center` mirrors about a point; `plane` mirrors across an axis.
|
|
71
|
+
* @returns a new Blueprint with every curve mirrored.
|
|
72
|
+
*/
|
|
73
|
+
mirror(centerOrDirection: Point2, origin?: Point2, mode?: 'center' | 'plane'): Blueprint;
|
|
74
|
+
/**
|
|
75
|
+
* The starting point of the first curve.
|
|
76
|
+
* @returns the 2D point where this blueprint begins.
|
|
77
|
+
*/
|
|
78
|
+
get firstPoint(): Point2;
|
|
79
|
+
/**
|
|
80
|
+
* The ending point of the last curve.
|
|
81
|
+
* @returns the 2D point where this blueprint ends.
|
|
82
|
+
*/
|
|
83
|
+
get lastPoint(): Point2;
|
|
84
|
+
/**
|
|
85
|
+
* True when the profile closes back on itself.
|
|
86
|
+
* @returns true when the first and last points coincide.
|
|
87
|
+
*/
|
|
88
|
+
isClosed(): boolean;
|
|
89
|
+
/**
|
|
90
|
+
* True when a point is strictly inside (ray-cast); false on the boundary.
|
|
91
|
+
* @param point - the 2D point to test, `[x, y]`.
|
|
92
|
+
* @returns true when the point is strictly inside, false on/outside the boundary.
|
|
93
|
+
*/
|
|
94
|
+
isInside(point: readonly [number, number]): boolean;
|
|
95
|
+
/**
|
|
96
|
+
* True when any curve of `this` intersects any curve of `other`.
|
|
97
|
+
* @param other - the blueprint to test for intersections against.
|
|
98
|
+
* @returns true when any pair of curves intersects.
|
|
99
|
+
*/
|
|
100
|
+
intersects(other: Blueprint): boolean;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=blueprint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blueprint.d.ts","sourceRoot":"","sources":["../../src/geometry2d/blueprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAE3C,OAAO,EAAgE,KAAK,MAAM,EAAE,MAAM,UAAU,CAAA;AAEpG,gBAAgB;AAChB,MAAM,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAcrC;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,SAAO,GAAG,OAAO,CAa3F;AAED;;;;GAIG;AACH,qBAAa,SAAS;IACpB,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,CAAA;IAE7B,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,YAAY,CAAgD;IACpE,OAAO,CAAC,mBAAmB,CAAgD;gBAE/D,MAAM,EAAE,UAAU,EAAE;IAKhC;;;OAGG;IACH,KAAK,IAAI,SAAS;IAIlB,6BAA6B;IAC7B,IAAI,WAAW,IAAI,MAAM,CAOxB;IAED,wEAAwE;IACxE,IAAI,WAAW,IAAI,WAAW,GAAG,kBAAkB,CAiBlD;IAED;;;;;OAKG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS;IAKjD;;;;;OAKG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS;IAK7D;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS;IAMpD;;;;;;OAMG;IACH,MAAM,CAAC,iBAAiB,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,GAAE,QAAQ,GAAG,OAAkB,GAAG,SAAS;IAUlG;;;OAGG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;;OAGG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED;;;OAGG;IACH,QAAQ,IAAI,OAAO;IAMnB;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO;IAsBnD;;;;OAIG;IACH,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO;CAWtC"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
import { addCurveToBBox, evaluateCurve2d, curveBounds, intersectCurves2dFn, makeLine2d, mirrorAcrossAxis, mirrorAtPoint, rotateCurve2d, scaleCurve2d, translateCurve2d } from './curve2d.js';
|
|
2
|
+
import { centerOf, createBBox2d, isBBoxOut, mergeBBox, outsidePointOf } from './bbox2d.js';
|
|
3
|
+
// `addCurveToBBox` writes xMin/yMin/xMax/yMax — same fields as BBox2d, so the
|
|
4
|
+
// structural subtype is satisfied by passing a plain BBox2d.
|
|
5
|
+
function curveBBox(c) {
|
|
6
|
+
const bb = createBBox2d();
|
|
7
|
+
addCurveToBBox(bb, c, 1e-9);
|
|
8
|
+
return bb;
|
|
9
|
+
}
|
|
10
|
+
function containsBoxPoint(bb, pt) {
|
|
11
|
+
return pt[0] >= bb.xMin && pt[0] <= bb.xMax && pt[1] >= bb.yMin && pt[1] <= bb.yMax;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* True when `(x,y)` is within `tol` of curve `c`.
|
|
15
|
+
* @param c - the curve to test against.
|
|
16
|
+
* @param pt - the 2D point to test, `[x, y]`.
|
|
17
|
+
* @param tol - the distance tolerance (default 1e-9).
|
|
18
|
+
* @returns true when the point lies within `tol` of the curve.
|
|
19
|
+
*/
|
|
20
|
+
export function isOnCurve(c, pt, tol = 1e-9) {
|
|
21
|
+
const bb = curveBBox(c);
|
|
22
|
+
if (!containsBoxPoint(bb, pt))
|
|
23
|
+
return false;
|
|
24
|
+
const b = curveBounds(c);
|
|
25
|
+
const N = 32;
|
|
26
|
+
let best = Infinity;
|
|
27
|
+
for (let i = 0; i <= N; i++) {
|
|
28
|
+
const t = b.first + ((b.last - b.first) * i) / N;
|
|
29
|
+
const [px, py] = evaluateCurve2d(c, t);
|
|
30
|
+
const d2 = (px - pt[0]) ** 2 + (py - pt[1]) ** 2;
|
|
31
|
+
if (d2 < best)
|
|
32
|
+
best = d2;
|
|
33
|
+
}
|
|
34
|
+
return best <= tol * tol;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A planar 2D profile = an ordered sequence of 2D curves.
|
|
38
|
+
* Shared base for `cad.profile`, `cad.draw` and (solved) `cad.sketch` outputs on
|
|
39
|
+
* their way to `sketchOnPlane`/`sketchOnFace`.
|
|
40
|
+
*/
|
|
41
|
+
export class Blueprint {
|
|
42
|
+
/** Ordered 2D curve segments composing this blueprint. */
|
|
43
|
+
curves;
|
|
44
|
+
_bbox = null;
|
|
45
|
+
_orientation = null;
|
|
46
|
+
_guessedOrientation = null;
|
|
47
|
+
constructor(curves) {
|
|
48
|
+
if (curves.length === 0)
|
|
49
|
+
throw new Error('Blueprint requires at least one curve');
|
|
50
|
+
this.curves = curves;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Return a shallow copy of this blueprint (new container, same curve objects).
|
|
54
|
+
* @returns a new Blueprint with the same curves.
|
|
55
|
+
*/
|
|
56
|
+
clone() {
|
|
57
|
+
return new Blueprint([...this.curves]);
|
|
58
|
+
}
|
|
59
|
+
/** Bounding box (cached). */
|
|
60
|
+
get boundingBox() {
|
|
61
|
+
if (!this._bbox) {
|
|
62
|
+
const bb = createBBox2d();
|
|
63
|
+
for (const c of this.curves)
|
|
64
|
+
mergeBBox(bb, curveBBox(c));
|
|
65
|
+
this._bbox = bb;
|
|
66
|
+
}
|
|
67
|
+
return this._bbox;
|
|
68
|
+
}
|
|
69
|
+
/** Winding orientation via shoelace (curve midpoints for non-lines). */
|
|
70
|
+
get orientation() {
|
|
71
|
+
if (this._orientation)
|
|
72
|
+
return this._orientation;
|
|
73
|
+
if (this._guessedOrientation)
|
|
74
|
+
return this._guessedOrientation;
|
|
75
|
+
const vertices = [];
|
|
76
|
+
for (const c of this.curves) {
|
|
77
|
+
const b = curveBounds(c);
|
|
78
|
+
vertices.push(firstPointOf(c));
|
|
79
|
+
if (c.kind2d !== 'line')
|
|
80
|
+
vertices.push(evaluate(c, (b.first + b.last) / 2));
|
|
81
|
+
}
|
|
82
|
+
let area = 0;
|
|
83
|
+
for (let i = 0; i < vertices.length; i++) {
|
|
84
|
+
const v1 = vertices[i];
|
|
85
|
+
const v2 = vertices[(i + 1) % vertices.length];
|
|
86
|
+
area += (v2[0] - v1[0]) * (v2[1] + v1[1]);
|
|
87
|
+
}
|
|
88
|
+
this._guessedOrientation = area > 0 ? 'clockwise' : 'counterClockwise';
|
|
89
|
+
return this._guessedOrientation;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Scale the blueprint about a center point.
|
|
93
|
+
* @param factor - the scale factor to apply.
|
|
94
|
+
* @param center - the scaling center `[x, y]` (defaults to the bounding-box center).
|
|
95
|
+
* @returns a new Blueprint with every curve scaled about the center.
|
|
96
|
+
*/
|
|
97
|
+
scale(factor, center) {
|
|
98
|
+
const [cx, cy] = center ?? centerOf(this.boundingBox);
|
|
99
|
+
return new Blueprint(this.curves.map((c) => scaleCurve2d(c, factor, cx, cy)));
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Translate the whole blueprint by a delta.
|
|
103
|
+
* @param dxOrPoint - the x delta, or a full `[dx, dy]` offset point.
|
|
104
|
+
* @param dy - the y delta (default 0, ignored when `dxOrPoint` is a point).
|
|
105
|
+
* @returns a new Blueprint with every curve translated.
|
|
106
|
+
*/
|
|
107
|
+
translate(dxOrPoint, dy) {
|
|
108
|
+
const [dx, yy] = typeof dxOrPoint === 'number' ? [dxOrPoint, dy ?? 0] : [dxOrPoint[0], dxOrPoint[1]];
|
|
109
|
+
return new Blueprint(this.curves.map((c) => translateCurve2d(c, dx, yy)));
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Rotate the whole blueprint about a center point.
|
|
113
|
+
* @param angleDeg - the rotation angle in degrees.
|
|
114
|
+
* @param center - the rotation center `[x, y]` (defaults to the origin).
|
|
115
|
+
* @returns a new Blueprint with every curve rotated.
|
|
116
|
+
*/
|
|
117
|
+
rotate(angleDeg, center) {
|
|
118
|
+
const a = (angleDeg * Math.PI) / 180;
|
|
119
|
+
const [cx, cy] = center ?? [0, 0];
|
|
120
|
+
return new Blueprint(this.curves.map((c) => rotateCurve2d(c, a, cx, cy)));
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Mirror the whole blueprint.
|
|
124
|
+
* @param centerOrDirection - the mirror center (mode `center`) or the mirror axis direction.
|
|
125
|
+
* @param origin - the axis origin `[x, y]` when mirroring across a plane (defaults to the origin).
|
|
126
|
+
* @param mode - `center` mirrors about a point; `plane` mirrors across an axis.
|
|
127
|
+
* @returns a new Blueprint with every curve mirrored.
|
|
128
|
+
*/
|
|
129
|
+
mirror(centerOrDirection, origin, mode = 'center') {
|
|
130
|
+
if (mode === 'plane') {
|
|
131
|
+
const [ox, oy] = origin ?? [0, 0];
|
|
132
|
+
const [dx, dy] = centerOrDirection;
|
|
133
|
+
return new Blueprint(this.curves.map((c) => mirrorAcrossAxis(c, ox, oy, dx, dy)));
|
|
134
|
+
}
|
|
135
|
+
const [cx, cy] = centerOrDirection;
|
|
136
|
+
return new Blueprint(this.curves.map((c) => mirrorAtPoint(c, cx, cy)));
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* The starting point of the first curve.
|
|
140
|
+
* @returns the 2D point where this blueprint begins.
|
|
141
|
+
*/
|
|
142
|
+
get firstPoint() {
|
|
143
|
+
return firstPointOf(this.curves[0]);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The ending point of the last curve.
|
|
147
|
+
* @returns the 2D point where this blueprint ends.
|
|
148
|
+
*/
|
|
149
|
+
get lastPoint() {
|
|
150
|
+
return lastPointOf(this.curves[this.curves.length - 1]);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* True when the profile closes back on itself.
|
|
154
|
+
* @returns true when the first and last points coincide.
|
|
155
|
+
*/
|
|
156
|
+
isClosed() {
|
|
157
|
+
const fp = this.firstPoint;
|
|
158
|
+
const lp = this.lastPoint;
|
|
159
|
+
return Math.abs(fp[0] - lp[0]) < 1e-9 && Math.abs(fp[1] - lp[1]) < 1e-9;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* True when a point is strictly inside (ray-cast); false on the boundary.
|
|
163
|
+
* @param point - the 2D point to test, `[x, y]`.
|
|
164
|
+
* @returns true when the point is strictly inside, false on/outside the boundary.
|
|
165
|
+
*/
|
|
166
|
+
isInside(point) {
|
|
167
|
+
const bbox = this.boundingBox;
|
|
168
|
+
const p = [point[0], point[1]];
|
|
169
|
+
if (!containsBoxPoint(bbox, p))
|
|
170
|
+
return false;
|
|
171
|
+
if (this.curves.some((c) => isOnCurve(c, p)))
|
|
172
|
+
return false;
|
|
173
|
+
const outside = outsidePointOf(bbox);
|
|
174
|
+
const segment = makeLine2d(p[0], p[1], outside[0], outside[1]);
|
|
175
|
+
const seen = [];
|
|
176
|
+
let crossCount = 0;
|
|
177
|
+
for (const c of this.curves) {
|
|
178
|
+
if (isBBoxOut(curveBBox(segment), curveBBox(c)))
|
|
179
|
+
continue;
|
|
180
|
+
const r = intersectCurves2dFn(segment, c, 1e-9);
|
|
181
|
+
for (const pt of r.points) {
|
|
182
|
+
if (!seen.some((s) => samePoint(s, pt))) {
|
|
183
|
+
seen.push(pt);
|
|
184
|
+
crossCount++;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return crossCount % 2 === 1;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* True when any curve of `this` intersects any curve of `other`.
|
|
192
|
+
* @param other - the blueprint to test for intersections against.
|
|
193
|
+
* @returns true when any pair of curves intersects.
|
|
194
|
+
*/
|
|
195
|
+
intersects(other) {
|
|
196
|
+
if (isBBoxOut(this.boundingBox, other.boundingBox))
|
|
197
|
+
return false;
|
|
198
|
+
for (const a of this.curves) {
|
|
199
|
+
for (const b of other.curves) {
|
|
200
|
+
if (isBBoxOut(curveBBox(a), curveBBox(b)))
|
|
201
|
+
continue;
|
|
202
|
+
const r = intersectCurves2dFn(a, b, 1e-9);
|
|
203
|
+
if (r.points.length || r.segments.length)
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// ---------------------------------------------------------------------------
|
|
211
|
+
// Pure helpers
|
|
212
|
+
// ---------------------------------------------------------------------------
|
|
213
|
+
function evaluate(c, t) {
|
|
214
|
+
return evaluateCurve2d(c, t);
|
|
215
|
+
}
|
|
216
|
+
function firstPointOf(c) {
|
|
217
|
+
return evaluateCurve2d(c, curveBounds(c).first);
|
|
218
|
+
}
|
|
219
|
+
function lastPointOf(c) {
|
|
220
|
+
return evaluateCurve2d(c, curveBounds(c).last);
|
|
221
|
+
}
|
|
222
|
+
function samePoint(a, b, tol = 1e-9) {
|
|
223
|
+
return Math.abs(a[0] - b[0]) < tol && Math.abs(a[1] - b[1]) < tol;
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=blueprint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blueprint.js","sourceRoot":"","sources":["../../src/geometry2d/blueprint.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Blueprint — ordered 2D profile of `Curve2dObj` segments (pure-data port of\n * brepjs `Blueprint`, Apache-2.0).\n *\n * Key adaptation: brepjs stores kernel-backed `Curve2D` handles that must be\n * disposed; faijs stores plain `Curve2dObj` objects (no handles, no dispose).\n * Kernel-coupling methods (sketchOnPlane / sketchOnFace / subFace / punchHole)\n * intentionally live in `geometry2d/bridge`, not here.\n *\n * @module\n */\nimport type { Curve2dObj } from './curve2d'\nimport { addCurveToBBox, evaluateCurve2d, curveBounds, intersectCurves2dFn, makeLine2d, mirrorAcrossAxis, mirrorAtPoint, rotateCurve2d, scaleCurve2d, translateCurve2d } from './curve2d'\nimport { centerOf, createBBox2d, isBBoxOut, mergeBBox, outsidePointOf, type BBox2d } from './bbox2d'\n\n/** 2D point. */\nexport type Point2 = [number, number]\n\n// `addCurveToBBox` writes xMin/yMin/xMax/yMax — same fields as BBox2d, so the\n// structural subtype is satisfied by passing a plain BBox2d.\nfunction curveBBox(c: Curve2dObj): BBox2d {\n const bb = createBBox2d()\n addCurveToBBox(bb as never, c, 1e-9)\n return bb\n}\n\nfunction containsBoxPoint(bb: BBox2d, pt: readonly [number, number]): boolean {\n return pt[0] >= bb.xMin && pt[0] <= bb.xMax && pt[1] >= bb.yMin && pt[1] <= bb.yMax\n}\n\n/**\n * True when `(x,y)` is within `tol` of curve `c`.\n * @param c - the curve to test against.\n * @param pt - the 2D point to test, `[x, y]`.\n * @param tol - the distance tolerance (default 1e-9).\n * @returns true when the point lies within `tol` of the curve.\n */\nexport function isOnCurve(c: Curve2dObj, pt: readonly [number, number], tol = 1e-9): boolean {\n const bb = curveBBox(c)\n if (!containsBoxPoint(bb, pt)) return false\n const b = curveBounds(c)\n const N = 32\n let best = Infinity\n for (let i = 0; i <= N; i++) {\n const t = b.first + ((b.last - b.first) * i) / N\n const [px, py] = evaluateCurve2d(c, t)\n const d2 = (px - pt[0]) ** 2 + (py - pt[1]) ** 2\n if (d2 < best) best = d2\n }\n return best <= tol * tol\n}\n\n/**\n * A planar 2D profile = an ordered sequence of 2D curves.\n * Shared base for `cad.profile`, `cad.draw` and (solved) `cad.sketch` outputs on\n * their way to `sketchOnPlane`/`sketchOnFace`.\n */\nexport class Blueprint {\n /** Ordered 2D curve segments composing this blueprint. */\n readonly curves: Curve2dObj[]\n\n private _bbox: BBox2d | null = null\n private _orientation: 'clockwise' | 'counterClockwise' | null = null\n private _guessedOrientation: 'clockwise' | 'counterClockwise' | null = null\n\n constructor(curves: Curve2dObj[]) {\n if (curves.length === 0) throw new Error('Blueprint requires at least one curve')\n this.curves = curves\n }\n\n /**\n * Return a shallow copy of this blueprint (new container, same curve objects).\n * @returns a new Blueprint with the same curves.\n */\n clone(): Blueprint {\n return new Blueprint([...this.curves])\n }\n\n /** Bounding box (cached). */\n get boundingBox(): BBox2d {\n if (!this._bbox) {\n const bb = createBBox2d()\n for (const c of this.curves) mergeBBox(bb, curveBBox(c))\n this._bbox = bb\n }\n return this._bbox\n }\n\n /** Winding orientation via shoelace (curve midpoints for non-lines). */\n get orientation(): 'clockwise' | 'counterClockwise' {\n if (this._orientation) return this._orientation\n if (this._guessedOrientation) return this._guessedOrientation\n const vertices: Point2[] = []\n for (const c of this.curves) {\n const b = curveBounds(c)\n vertices.push(firstPointOf(c))\n if (c.kind2d !== 'line') vertices.push(evaluate(c, (b.first + b.last) / 2) as Point2)\n }\n let area = 0\n for (let i = 0; i < vertices.length; i++) {\n const v1 = vertices[i]!\n const v2 = vertices[(i + 1) % vertices.length]!\n area += (v2[0] - v1[0]) * (v2[1] + v1[1])\n }\n this._guessedOrientation = area > 0 ? 'clockwise' : 'counterClockwise'\n return this._guessedOrientation\n }\n\n /**\n * Scale the blueprint 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 Blueprint with every curve scaled about the center.\n */\n scale(factor: number, center?: Point2): Blueprint {\n const [cx, cy] = center ?? centerOf(this.boundingBox)\n return new Blueprint(this.curves.map((c) => scaleCurve2d(c, factor, cx, cy)))\n }\n\n /**\n * Translate the whole blueprint 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 Blueprint with every curve translated.\n */\n translate(dxOrPoint: number | Point2, dy?: number): Blueprint {\n const [dx, yy] = typeof dxOrPoint === 'number' ? [dxOrPoint, dy ?? 0] : [dxOrPoint[0], dxOrPoint[1]]\n return new Blueprint(this.curves.map((c) => translateCurve2d(c, dx, yy)))\n }\n\n /**\n * Rotate the whole blueprint 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 Blueprint with every curve rotated.\n */\n rotate(angleDeg: number, center?: Point2): Blueprint {\n const a = (angleDeg * Math.PI) / 180\n const [cx, cy] = center ?? [0, 0]\n return new Blueprint(this.curves.map((c) => rotateCurve2d(c, a, cx, cy)))\n }\n\n /**\n * Mirror the whole blueprint.\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 Blueprint with every curve mirrored.\n */\n mirror(centerOrDirection: Point2, origin?: Point2, mode: 'center' | 'plane' = 'center'): Blueprint {\n if (mode === 'plane') {\n const [ox, oy] = origin ?? [0, 0]\n const [dx, dy] = centerOrDirection\n return new Blueprint(this.curves.map((c) => mirrorAcrossAxis(c, ox, oy, dx, dy)))\n }\n const [cx, cy] = centerOrDirection\n return new Blueprint(this.curves.map((c) => mirrorAtPoint(c, cx, cy)))\n }\n\n /**\n * The starting point of the first curve.\n * @returns the 2D point where this blueprint begins.\n */\n get firstPoint(): Point2 {\n return firstPointOf(this.curves[0]!)\n }\n\n /**\n * The ending point of the last curve.\n * @returns the 2D point where this blueprint ends.\n */\n get lastPoint(): Point2 {\n return lastPointOf(this.curves[this.curves.length - 1]!)\n }\n\n /**\n * True when the profile closes back on itself.\n * @returns true when the first and last points coincide.\n */\n isClosed(): boolean {\n const fp = this.firstPoint\n const lp = this.lastPoint\n return Math.abs(fp[0] - lp[0]) < 1e-9 && Math.abs(fp[1] - lp[1]) < 1e-9\n }\n\n /**\n * True when a point is strictly inside (ray-cast); false on the boundary.\n * @param point - the 2D point to test, `[x, y]`.\n * @returns true when the point is strictly inside, false on/outside the boundary.\n */\n isInside(point: readonly [number, number]): boolean {\n const bbox = this.boundingBox\n const p: Point2 = [point[0], point[1]]\n if (!containsBoxPoint(bbox, p)) return false\n if (this.curves.some((c) => isOnCurve(c, p))) return false\n const outside = outsidePointOf(bbox)\n const segment = makeLine2d(p[0], p[1], outside[0], outside[1])\n const seen: Point2[] = []\n let crossCount = 0\n for (const c of this.curves) {\n if (isBBoxOut(curveBBox(segment), curveBBox(c))) continue\n const r = intersectCurves2dFn(segment, c, 1e-9)\n for (const pt of r.points) {\n if (!seen.some((s) => samePoint(s, pt))) {\n seen.push(pt)\n crossCount++\n }\n }\n }\n return crossCount % 2 === 1\n }\n\n /**\n * True when any curve of `this` intersects any curve of `other`.\n * @param other - the blueprint to test for intersections against.\n * @returns true when any pair of curves intersects.\n */\n intersects(other: Blueprint): boolean {\n if (isBBoxOut(this.boundingBox, other.boundingBox)) return false\n for (const a of this.curves) {\n for (const b of other.curves) {\n if (isBBoxOut(curveBBox(a), curveBBox(b))) continue\n const r = intersectCurves2dFn(a, b, 1e-9)\n if (r.points.length || r.segments.length) return true\n }\n }\n return false\n }\n}\n\n// ---------------------------------------------------------------------------\n// Pure helpers\n// ---------------------------------------------------------------------------\n\nfunction evaluate(c: Curve2dObj, t: number): [number, number] {\n return evaluateCurve2d(c, t)\n}\n\nfunction firstPointOf(c: Curve2dObj): Point2 {\n return evaluateCurve2d(c, curveBounds(c).first)\n}\n\nfunction lastPointOf(c: Curve2dObj): Point2 {\n return evaluateCurve2d(c, curveBounds(c).last)\n}\n\nfunction samePoint(a: readonly [number, number], b: readonly [number, number], tol = 1e-9): boolean {\n return Math.abs(a[0] - b[0]) < tol && Math.abs(a[1] - b[1]) < tol\n}"]}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Blueprints — collection of disjoint 2D profiles (pure-data port of brepjs,
|
|
3
|
+
* Apache-2.0). Typical result of boolean operations producing multiple regions.
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { Blueprint, type Point2 } from './blueprint.js';
|
|
7
|
+
import { CompoundBlueprint } from './compound-blueprint.js';
|
|
8
|
+
import { type BBox2d } from './bbox2d.js';
|
|
9
|
+
/**
|
|
10
|
+
* Blueprints — collection of disjoint 2D profiles.
|
|
11
|
+
* Typical result of boolean operations producing multiple independent regions.
|
|
12
|
+
*/
|
|
13
|
+
export declare class Blueprints {
|
|
14
|
+
/** The independent profiles in this collection. */
|
|
15
|
+
readonly blueprints: Array<Blueprint | CompoundBlueprint>;
|
|
16
|
+
private _bbox;
|
|
17
|
+
constructor(blueprints: Array<Blueprint | CompoundBlueprint>);
|
|
18
|
+
/**
|
|
19
|
+
* Return a copy of this collection.
|
|
20
|
+
* @returns a new Blueprints whose profiles are clones of the originals.
|
|
21
|
+
*/
|
|
22
|
+
clone(): Blueprints;
|
|
23
|
+
/**
|
|
24
|
+
* Bounding box (cached). The box spanning all contained profiles.
|
|
25
|
+
* @returns a BBox2d enclosing every profile in this collection.
|
|
26
|
+
*/
|
|
27
|
+
get boundingBox(): BBox2d;
|
|
28
|
+
/**
|
|
29
|
+
* Scale every profile about a center point.
|
|
30
|
+
* @param factor - the scale factor to apply.
|
|
31
|
+
* @param center - the scaling center `[x, y]` (defaults to the bounding-box center).
|
|
32
|
+
* @returns a new Blueprints with every profile scaled.
|
|
33
|
+
*/
|
|
34
|
+
scale(factor: number, center?: Point2): Blueprints;
|
|
35
|
+
/**
|
|
36
|
+
* Translate every profile by a delta.
|
|
37
|
+
* @param dxOrPoint - the x delta, or a full `[dx, dy]` offset point.
|
|
38
|
+
* @param dy - the y delta (default 0, ignored when `dxOrPoint` is a point).
|
|
39
|
+
* @returns a new Blueprints with every profile translated.
|
|
40
|
+
*/
|
|
41
|
+
translate(dxOrPoint: number | Point2, dy?: number): Blueprints;
|
|
42
|
+
/**
|
|
43
|
+
* Rotate every profile about a center point.
|
|
44
|
+
* @param angleDeg - the rotation angle in degrees.
|
|
45
|
+
* @param center - the rotation center `[x, y]` (defaults to the origin).
|
|
46
|
+
* @returns a new Blueprints with every profile rotated.
|
|
47
|
+
*/
|
|
48
|
+
rotate(angleDeg: number, center?: Point2): Blueprints;
|
|
49
|
+
/**
|
|
50
|
+
* Mirror every profile.
|
|
51
|
+
* @param centerOrDirection - the mirror center (mode `center`) or the mirror axis direction.
|
|
52
|
+
* @param origin - the axis origin `[x, y]` when mirroring across a plane (defaults to the origin).
|
|
53
|
+
* @param mode - `center` mirrors about a point; `plane` mirrors across an axis.
|
|
54
|
+
* @returns a new Blueprints with every profile mirrored.
|
|
55
|
+
*/
|
|
56
|
+
mirror(centerOrDirection: Point2, origin?: Point2, mode?: 'center' | 'plane'): Blueprints;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=blueprints.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blueprints.d.ts","sourceRoot":"","sources":["../../src/geometry2d/blueprints.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,KAAK,MAAM,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,EAAqC,KAAK,MAAM,EAAE,MAAM,UAAU,CAAA;AAEzE;;;GAGG;AACH,qBAAa,UAAU;IACrB,mDAAmD;IACnD,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC,SAAS,GAAG,iBAAiB,CAAC,CAAA;IAEzD,OAAO,CAAC,KAAK,CAAsB;gBAEvB,UAAU,EAAE,KAAK,CAAC,SAAS,GAAG,iBAAiB,CAAC;IAI5D;;;OAGG;IACH,KAAK,IAAI,UAAU;IAInB;;;OAGG;IACH,IAAI,WAAW,IAAI,MAAM,CAOxB;IAED;;;;;OAKG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,UAAU;IAKlD;;;;;OAKG;IACH,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU;IAI9D;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,UAAU;IAIrD;;;;;;OAMG;IACH,MAAM,CAAC,iBAAiB,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,GAAE,QAAQ,GAAG,OAAkB,GAAG,UAAU;CAGpG"}
|