@retikz/core 0.3.0-alpha.3 → 0.3.0-alpha.5
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/README.md +41 -41
- package/dist/es/compile/anchor-cache.d.ts +5 -3
- package/dist/es/compile/anchor-cache.d.ts.map +1 -1
- package/dist/es/compile/anchor-cache.js +14 -10
- package/dist/es/compile/boundary.d.ts +19 -0
- package/dist/es/compile/boundary.d.ts.map +1 -0
- package/dist/es/compile/boundary.js +64 -0
- package/dist/es/compile/compile.d.ts +1 -1
- package/dist/es/compile/compile.d.ts.map +1 -1
- package/dist/es/compile/compile.js +49 -5
- package/dist/es/compile/node.d.ts +26 -8
- package/dist/es/compile/node.d.ts.map +1 -1
- package/dist/es/compile/node.js +103 -16
- package/dist/es/compile/path/anchor.d.ts.map +1 -1
- package/dist/es/compile/path/anchor.js +7 -6
- package/dist/es/compile/path/index.d.ts.map +1 -1
- package/dist/es/compile/path/index.js +7 -3
- package/dist/es/compile/path/relative.js +1 -1
- package/dist/es/compile/scope.d.ts.map +1 -1
- package/dist/es/compile/scope.js +2 -1
- package/dist/es/geometry/arc.d.ts +14 -0
- package/dist/es/geometry/arc.d.ts.map +1 -1
- package/dist/es/geometry/arc.js +65 -9
- package/dist/es/geometry/index.d.ts +1 -0
- package/dist/es/geometry/index.d.ts.map +1 -1
- package/dist/es/geometry/rect.d.ts +2 -2
- package/dist/es/geometry/rect.d.ts.map +1 -1
- package/dist/es/geometry/rect.js +3 -3
- package/dist/es/geometry/roundedContour.d.ts +88 -0
- package/dist/es/geometry/roundedContour.d.ts.map +1 -0
- package/dist/es/geometry/roundedContour.js +417 -0
- package/dist/es/index.d.ts +9 -5
- package/dist/es/index.d.ts.map +1 -1
- package/dist/es/index.js +11 -6
- package/dist/es/ir/animation.d.ts +218 -0
- package/dist/es/ir/animation.d.ts.map +1 -0
- package/dist/es/ir/animation.js +118 -0
- package/dist/es/ir/boundary.d.ts +25 -0
- package/dist/es/ir/boundary.d.ts.map +1 -0
- package/dist/es/ir/boundary.js +14 -0
- package/dist/es/ir/index.d.ts +3 -0
- package/dist/es/ir/index.d.ts.map +1 -1
- package/dist/es/ir/node.d.ts +219 -27
- package/dist/es/ir/node.d.ts.map +1 -1
- package/dist/es/ir/node.js +10 -3
- package/dist/es/ir/path/arrow.d.ts +36 -36
- package/dist/es/ir/path/path.d.ts +702 -203
- package/dist/es/ir/path/path.d.ts.map +1 -1
- package/dist/es/ir/path/path.js +4 -0
- package/dist/es/ir/path/step.d.ts +674 -154
- package/dist/es/ir/path/step.d.ts.map +1 -1
- package/dist/es/ir/path/step.js +2 -2
- package/dist/es/ir/path/target.d.ts +43 -8
- package/dist/es/ir/path/target.d.ts.map +1 -1
- package/dist/es/ir/path/target.js +4 -5
- package/dist/es/ir/scene.d.ts +156 -0
- package/dist/es/ir/scene.d.ts.map +1 -1
- package/dist/es/ir/scene.js +3 -1
- package/dist/es/ir/scope.d.ts +1671 -424
- package/dist/es/ir/scope.d.ts.map +1 -1
- package/dist/es/ir/scope.js +10 -2
- package/dist/es/ir/shape.d.ts +14 -0
- package/dist/es/ir/shape.d.ts.map +1 -0
- package/dist/es/ir/shape.js +9 -0
- package/dist/es/parsers/parseNodeTarget.d.ts.map +1 -1
- package/dist/es/parsers/parseNodeTarget.js +4 -2
- package/dist/es/presets/animation.d.ts +123 -0
- package/dist/es/presets/animation.d.ts.map +1 -0
- package/dist/es/presets/animation.js +272 -0
- package/dist/es/presets/index.d.ts +3 -0
- package/dist/es/presets/index.d.ts.map +1 -0
- package/dist/es/primitive/ellipse.d.ts +6 -0
- package/dist/es/primitive/ellipse.d.ts.map +1 -1
- package/dist/es/primitive/group.d.ts +6 -0
- package/dist/es/primitive/group.d.ts.map +1 -1
- package/dist/es/primitive/path.d.ts +6 -0
- package/dist/es/primitive/path.d.ts.map +1 -1
- package/dist/es/primitive/rect.d.ts +6 -0
- package/dist/es/primitive/rect.d.ts.map +1 -1
- package/dist/es/primitive/scene.d.ts +3 -0
- package/dist/es/primitive/scene.d.ts.map +1 -1
- package/dist/es/primitive/text.d.ts +6 -0
- package/dist/es/primitive/text.d.ts.map +1 -1
- package/dist/es/shapes/_contour.d.ts +19 -0
- package/dist/es/shapes/_contour.d.ts.map +1 -0
- package/dist/es/shapes/_contour.js +60 -0
- package/dist/es/shapes/_shared.d.ts +54 -0
- package/dist/es/shapes/_shared.d.ts.map +1 -1
- package/dist/es/shapes/_shared.js +68 -1
- package/dist/es/shapes/arc.d.ts +8 -0
- package/dist/es/shapes/arc.d.ts.map +1 -0
- package/dist/es/shapes/arc.js +104 -0
- package/dist/es/shapes/define.d.ts +13 -0
- package/dist/es/shapes/define.d.ts.map +1 -0
- package/dist/es/shapes/define.js +13 -0
- package/dist/es/shapes/ellipse.d.ts +5 -4
- package/dist/es/shapes/ellipse.d.ts.map +1 -1
- package/dist/es/shapes/ellipse.js +15 -7
- package/dist/es/shapes/index.d.ts +9 -6
- package/dist/es/shapes/index.d.ts.map +1 -1
- package/dist/es/shapes/index.js +10 -5
- package/dist/es/shapes/polygon.d.ts +13 -0
- package/dist/es/shapes/polygon.d.ts.map +1 -0
- package/dist/es/shapes/polygon.js +104 -0
- package/dist/es/shapes/rectangle.d.ts +7 -5
- package/dist/es/shapes/rectangle.d.ts.map +1 -1
- package/dist/es/shapes/rectangle.js +37 -8
- package/dist/es/shapes/sector.d.ts +9 -0
- package/dist/es/shapes/sector.d.ts.map +1 -0
- package/dist/es/shapes/sector.js +143 -0
- package/dist/es/shapes/star.d.ts +15 -0
- package/dist/es/shapes/star.d.ts.map +1 -0
- package/dist/es/shapes/star.js +113 -0
- package/dist/es/shapes/types.d.ts +47 -14
- package/dist/es/shapes/types.d.ts.map +1 -1
- package/dist/lib/compile/anchor-cache.cjs +14 -10
- package/dist/lib/compile/anchor-cache.d.ts +5 -3
- package/dist/lib/compile/anchor-cache.d.ts.map +1 -1
- package/dist/lib/compile/boundary.cjs +65 -0
- package/dist/lib/compile/boundary.d.ts +19 -0
- package/dist/lib/compile/boundary.d.ts.map +1 -0
- package/dist/lib/compile/compile.cjs +49 -5
- package/dist/lib/compile/compile.d.ts +1 -1
- package/dist/lib/compile/compile.d.ts.map +1 -1
- package/dist/lib/compile/node.cjs +103 -16
- package/dist/lib/compile/node.d.ts +26 -8
- package/dist/lib/compile/node.d.ts.map +1 -1
- package/dist/lib/compile/path/anchor.cjs +7 -6
- package/dist/lib/compile/path/anchor.d.ts.map +1 -1
- package/dist/lib/compile/path/index.cjs +7 -3
- package/dist/lib/compile/path/index.d.ts.map +1 -1
- package/dist/lib/compile/path/relative.cjs +1 -1
- package/dist/lib/compile/scope.cjs +2 -1
- package/dist/lib/compile/scope.d.ts.map +1 -1
- package/dist/lib/geometry/arc.cjs +66 -8
- package/dist/lib/geometry/arc.d.ts +14 -0
- package/dist/lib/geometry/arc.d.ts.map +1 -1
- package/dist/lib/geometry/index.d.ts +1 -0
- package/dist/lib/geometry/index.d.ts.map +1 -1
- package/dist/lib/geometry/rect.cjs +3 -3
- package/dist/lib/geometry/rect.d.ts +2 -2
- package/dist/lib/geometry/rect.d.ts.map +1 -1
- package/dist/lib/geometry/roundedContour.cjs +418 -0
- package/dist/lib/geometry/roundedContour.d.ts +88 -0
- package/dist/lib/geometry/roundedContour.d.ts.map +1 -0
- package/dist/lib/index.cjs +41 -7
- package/dist/lib/index.d.ts +9 -5
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/ir/animation.cjs +127 -0
- package/dist/lib/ir/animation.d.ts +218 -0
- package/dist/lib/ir/animation.d.ts.map +1 -0
- package/dist/lib/ir/boundary.cjs +15 -0
- package/dist/lib/ir/boundary.d.ts +25 -0
- package/dist/lib/ir/boundary.d.ts.map +1 -0
- package/dist/lib/ir/index.d.ts +3 -0
- package/dist/lib/ir/index.d.ts.map +1 -1
- package/dist/lib/ir/node.cjs +10 -3
- package/dist/lib/ir/node.d.ts +219 -27
- package/dist/lib/ir/node.d.ts.map +1 -1
- package/dist/lib/ir/path/arrow.d.ts +36 -36
- package/dist/lib/ir/path/path.cjs +4 -0
- package/dist/lib/ir/path/path.d.ts +702 -203
- package/dist/lib/ir/path/path.d.ts.map +1 -1
- package/dist/lib/ir/path/step.cjs +2 -2
- package/dist/lib/ir/path/step.d.ts +674 -154
- package/dist/lib/ir/path/step.d.ts.map +1 -1
- package/dist/lib/ir/path/target.cjs +4 -5
- package/dist/lib/ir/path/target.d.ts +43 -8
- package/dist/lib/ir/path/target.d.ts.map +1 -1
- package/dist/lib/ir/scene.cjs +3 -1
- package/dist/lib/ir/scene.d.ts +156 -0
- package/dist/lib/ir/scene.d.ts.map +1 -1
- package/dist/lib/ir/scope.cjs +10 -2
- package/dist/lib/ir/scope.d.ts +1671 -424
- package/dist/lib/ir/scope.d.ts.map +1 -1
- package/dist/lib/ir/shape.cjs +9 -0
- package/dist/lib/ir/shape.d.ts +14 -0
- package/dist/lib/ir/shape.d.ts.map +1 -0
- package/dist/lib/parsers/parseNodeTarget.cjs +4 -2
- package/dist/lib/parsers/parseNodeTarget.d.ts.map +1 -1
- package/dist/lib/presets/animation.cjs +286 -0
- package/dist/lib/presets/animation.d.ts +123 -0
- package/dist/lib/presets/animation.d.ts.map +1 -0
- package/dist/lib/presets/index.d.ts +3 -0
- package/dist/lib/presets/index.d.ts.map +1 -0
- package/dist/lib/primitive/ellipse.d.ts +6 -0
- package/dist/lib/primitive/ellipse.d.ts.map +1 -1
- package/dist/lib/primitive/group.d.ts +6 -0
- package/dist/lib/primitive/group.d.ts.map +1 -1
- package/dist/lib/primitive/path.d.ts +6 -0
- package/dist/lib/primitive/path.d.ts.map +1 -1
- package/dist/lib/primitive/rect.d.ts +6 -0
- package/dist/lib/primitive/rect.d.ts.map +1 -1
- package/dist/lib/primitive/scene.d.ts +3 -0
- package/dist/lib/primitive/scene.d.ts.map +1 -1
- package/dist/lib/primitive/text.d.ts +6 -0
- package/dist/lib/primitive/text.d.ts.map +1 -1
- package/dist/lib/shapes/_contour.cjs +61 -0
- package/dist/lib/shapes/_contour.d.ts +19 -0
- package/dist/lib/shapes/_contour.d.ts.map +1 -0
- package/dist/lib/shapes/_shared.cjs +70 -0
- package/dist/lib/shapes/_shared.d.ts +54 -0
- package/dist/lib/shapes/_shared.d.ts.map +1 -1
- package/dist/lib/shapes/arc.cjs +104 -0
- package/dist/lib/shapes/arc.d.ts +8 -0
- package/dist/lib/shapes/arc.d.ts.map +1 -0
- package/dist/lib/shapes/define.cjs +13 -0
- package/dist/lib/shapes/define.d.ts +13 -0
- package/dist/lib/shapes/define.d.ts.map +1 -0
- package/dist/lib/shapes/ellipse.cjs +15 -7
- package/dist/lib/shapes/ellipse.d.ts +5 -4
- package/dist/lib/shapes/ellipse.d.ts.map +1 -1
- package/dist/lib/shapes/index.cjs +12 -6
- package/dist/lib/shapes/index.d.ts +9 -6
- package/dist/lib/shapes/index.d.ts.map +1 -1
- package/dist/lib/shapes/polygon.cjs +104 -0
- package/dist/lib/shapes/polygon.d.ts +13 -0
- package/dist/lib/shapes/polygon.d.ts.map +1 -0
- package/dist/lib/shapes/rectangle.cjs +37 -8
- package/dist/lib/shapes/rectangle.d.ts +7 -5
- package/dist/lib/shapes/rectangle.d.ts.map +1 -1
- package/dist/lib/shapes/sector.cjs +143 -0
- package/dist/lib/shapes/sector.d.ts +9 -0
- package/dist/lib/shapes/sector.d.ts.map +1 -0
- package/dist/lib/shapes/star.cjs +113 -0
- package/dist/lib/shapes/star.d.ts +15 -0
- package/dist/lib/shapes/star.d.ts.map +1 -0
- package/dist/lib/shapes/types.d.ts +47 -14
- package/dist/lib/shapes/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/dist/es/shapes/circle.d.ts +0 -8
- package/dist/es/shapes/circle.d.ts.map +0 -1
- package/dist/es/shapes/circle.js +0 -34
- package/dist/es/shapes/diamond.d.ts +0 -8
- package/dist/es/shapes/diamond.d.ts.map +0 -1
- package/dist/es/shapes/diamond.js +0 -66
- package/dist/lib/shapes/circle.cjs +0 -34
- package/dist/lib/shapes/circle.d.ts +0 -8
- package/dist/lib/shapes/circle.d.ts.map +0 -1
- package/dist/lib/shapes/diamond.cjs +0 -66
- package/dist/lib/shapes/diamond.d.ts +0 -8
- package/dist/lib/shapes/diamond.d.ts.map +0 -1
package/dist/es/compile/node.js
CHANGED
|
@@ -1,9 +1,62 @@
|
|
|
1
|
+
import { JsonObjectSchema } from "../ir/json.js";
|
|
2
|
+
import { asRectAnchor } from "../shapes/_shared.js";
|
|
1
3
|
import { BUILTIN_SHAPES } from "../shapes/index.js";
|
|
2
4
|
import { resolvePosition } from "./position.js";
|
|
3
5
|
import { toAlphabeticBaselineY } from "./text-baseline.js";
|
|
6
|
+
import { resolveBoundary } from "./boundary.js";
|
|
4
7
|
//#region src/compile/node.ts
|
|
5
8
|
var DEFAULT_FONT_SIZE = 14;
|
|
6
9
|
var DEFAULT_PADDING = 8;
|
|
10
|
+
/** 无参 / 合成 layout 的 shape params 兜底(避免每次调用重建空对象) */
|
|
11
|
+
var EMPTY_SHAPE_PARAMS = {};
|
|
12
|
+
/**
|
|
13
|
+
* 规范化 `Node.shape` 为 `{ type, params }`
|
|
14
|
+
* @description 裸 string → `{ type, params: {} }`;`{ type, params? }` → params 缺省补 `{}`;
|
|
15
|
+
* 缺省(undefined)→ `{ type: 'rectangle', params: {} }`。`'circle'`(裸 string)消解为
|
|
16
|
+
* `{ type: 'ellipse', params: { circumscribe: 'equal' } }`——circle 无独立几何,是 ellipse 等轴 preset 别名。
|
|
17
|
+
* `'diamond'`(裸 string)消解为 `{ type: 'polygon', params: { sides: 4, rotate: 45 } }`——diamond 无独立几何,
|
|
18
|
+
* 是 polygon 4 边形(自旋 45°)preset 别名。仅做形态归一,不查表 / 不校验。
|
|
19
|
+
*/
|
|
20
|
+
var normalizeShape = (shape) => {
|
|
21
|
+
if (shape === void 0) return {
|
|
22
|
+
type: "rectangle",
|
|
23
|
+
params: {}
|
|
24
|
+
};
|
|
25
|
+
if (shape === "circle") return {
|
|
26
|
+
type: "ellipse",
|
|
27
|
+
params: { circumscribe: "equal" }
|
|
28
|
+
};
|
|
29
|
+
if (shape === "diamond") return {
|
|
30
|
+
type: "polygon",
|
|
31
|
+
params: {
|
|
32
|
+
sides: 4,
|
|
33
|
+
rotate: 45
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
if (typeof shape === "string") return {
|
|
37
|
+
type: shape,
|
|
38
|
+
params: {}
|
|
39
|
+
};
|
|
40
|
+
const ref = shape;
|
|
41
|
+
return {
|
|
42
|
+
type: ref.type,
|
|
43
|
+
params: ref.params ?? {}
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* 递归把 JSON 值里所有数值叶子乘以 factor(数组 / 对象深入,string / boolean / null 原样)
|
|
48
|
+
* @description 用于 shape params 随 node scale 协同缩放;输入已是 JSON-safe(双护栏过),输出仍 JSON-safe。
|
|
49
|
+
*/
|
|
50
|
+
var scaleJsonNumbers = (value, factor) => {
|
|
51
|
+
if (typeof value === "number") return value * factor;
|
|
52
|
+
if (Array.isArray(value)) return value.map((v) => scaleJsonNumbers(v, factor));
|
|
53
|
+
if (value !== null && typeof value === "object") {
|
|
54
|
+
const out = {};
|
|
55
|
+
for (const [k, v] of Object.entries(value)) out[k] = scaleJsonNumbers(v, factor);
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
return value;
|
|
59
|
+
};
|
|
7
60
|
var DEFAULT_LINE_HEIGHT_FACTOR = 1.2;
|
|
8
61
|
var DEG_TO_RAD = Math.PI / 180;
|
|
9
62
|
/** CJK / fullwidth ranges: break per-character (no whitespace needed) */
|
|
@@ -73,16 +126,28 @@ var inflateRect = (r, m) => m === 0 ? r : {
|
|
|
73
126
|
};
|
|
74
127
|
/**
|
|
75
128
|
* 取节点 shape 在 toward 方向的附着点(path 端点贴边用)
|
|
76
|
-
* @description
|
|
129
|
+
* @description 走连接面(boundary)对应的 def.boundaryPoint;margin > 0 时先膨胀外接 Rect,让 path 在 border 外停 margin。
|
|
130
|
+
* boundary 缺省 = 'shape'(视觉形状自身),与改前行为一致。
|
|
77
131
|
*/
|
|
78
|
-
var boundaryPointOf = (layout, toward
|
|
132
|
+
var boundaryPointOf = (layout, toward, boundary = "shape") => {
|
|
133
|
+
const { def, rect, params } = resolveBoundary(boundary, layout.shapeDef, layout.rect, layout.shapeParams ?? EMPTY_SHAPE_PARAMS, layout.shapes);
|
|
134
|
+
return def.boundaryPoint(inflateRect(rect, layout.margin), toward, params);
|
|
135
|
+
};
|
|
79
136
|
/**
|
|
80
137
|
* 取节点 shape 命名 anchor(center / north / east / north-east 等)
|
|
81
138
|
* @description 不应用 margin——TikZ 语义中 explicit anchor 取视觉边界点不涉及 outer sep;用于 `'A.north'` 落点。
|
|
82
|
-
*
|
|
139
|
+
* compass(9 个 rect 方位名)走连接面 AABB:'shape' 时归一为 'rectangle'(矩形 AABB),其余按 boundary 解析。
|
|
140
|
+
* 形状专属命名 anchor(tip-N / apex 等非 compass 名)恒走视觉形状自身,boundary 不影响。
|
|
141
|
+
* boundary 缺省 = 'shape',与改前 compass 走 AABB 行为一致(原 shapeDef.anchor 内部也走 rect AABB)。
|
|
83
142
|
*/
|
|
84
|
-
var anchorOf = (layout, name) => {
|
|
85
|
-
|
|
143
|
+
var anchorOf = (layout, name, boundary = "shape") => {
|
|
144
|
+
if (asRectAnchor(name) !== void 0) {
|
|
145
|
+
const { def, rect, params } = resolveBoundary(boundary === "shape" ? "rectangle" : boundary, layout.shapeDef, layout.rect, layout.shapeParams ?? EMPTY_SHAPE_PARAMS, layout.shapes);
|
|
146
|
+
const p = def.anchor(rect, name, params);
|
|
147
|
+
if (p === void 0) throw new Error(`Unknown anchor '${name}' for shape '${layout.shapeName}'`);
|
|
148
|
+
return p;
|
|
149
|
+
}
|
|
150
|
+
const p = layout.shapeDef.anchor(layout.rect, name, layout.shapeParams ?? EMPTY_SHAPE_PARAMS);
|
|
86
151
|
if (p === void 0) throw new Error(`Unknown anchor '${name}' for shape '${layout.shapeName}'`);
|
|
87
152
|
return p;
|
|
88
153
|
};
|
|
@@ -187,9 +252,10 @@ var resolveLabelRotateDeg = (label, lx, ly, cx, cy) => {
|
|
|
187
252
|
};
|
|
188
253
|
/**
|
|
189
254
|
* 取节点 shape 在指定角度方向的边界点
|
|
190
|
-
* @description 角度是节点**局部坐标系**下的极角(度数:0°=局部 +x,90°=局部 +y)。layout.rect.rotate 把局部基绕中心旋转,得到世界系下的视觉方向;shape boundaryPoint 内部用 rotate-aware 投影,所以这里把局部 (cos, sin) 经 rect.rotate 旋转后加到中心当作世界系 toward 传入。不应用 margin(同 anchorOf);用于 `'A.30'`
|
|
255
|
+
* @description 角度是节点**局部坐标系**下的极角(度数:0°=局部 +x,90°=局部 +y)。layout.rect.rotate 把局部基绕中心旋转,得到世界系下的视觉方向;shape boundaryPoint 内部用 rotate-aware 投影,所以这里把局部 (cos, sin) 经 rect.rotate 旋转后加到中心当作世界系 toward 传入。不应用 margin(同 anchorOf);用于 `'A.30'` 落点。
|
|
256
|
+
* boundary 缺省 = 'shape'(视觉形状自身),与改前行为一致。
|
|
191
257
|
*/
|
|
192
|
-
var angleBoundaryOf = (layout, angleDeg) => {
|
|
258
|
+
var angleBoundaryOf = (layout, angleDeg, boundary = "shape") => {
|
|
193
259
|
const rad = angleDeg * Math.PI / 180;
|
|
194
260
|
const lx = Math.cos(rad);
|
|
195
261
|
const ly = Math.sin(rad);
|
|
@@ -197,7 +263,8 @@ var angleBoundaryOf = (layout, angleDeg) => {
|
|
|
197
263
|
const cosR = Math.cos(rot);
|
|
198
264
|
const sinR = Math.sin(rot);
|
|
199
265
|
const toward = [layout.rect.x + lx * cosR - ly * sinR, layout.rect.y + lx * sinR + ly * cosR];
|
|
200
|
-
|
|
266
|
+
const { def, rect, params } = resolveBoundary(boundary, layout.shapeDef, layout.rect, layout.shapeParams ?? EMPTY_SHAPE_PARAMS, layout.shapes);
|
|
267
|
+
return def.boundaryPoint(rect, toward, params);
|
|
201
268
|
};
|
|
202
269
|
/**
|
|
203
270
|
* IR Node → 内部 NodeLayout
|
|
@@ -207,12 +274,20 @@ var angleBoundaryOf = (layout, angleDeg) => {
|
|
|
207
274
|
* 笛卡尔字面量 `Position` 已在 scope 局部度量,行为延续 v0.1。
|
|
208
275
|
*/
|
|
209
276
|
var layoutNode = (node, measureText, nameStack, nodeDistance, scopeChain = [], labelDefault, shapes = BUILTIN_SHAPES, resolveBetweenGlobal) => {
|
|
210
|
-
const shapeName = node.shape
|
|
277
|
+
const { type: shapeName, params: rawShapeParams } = normalizeShape(node.shape);
|
|
211
278
|
const shapeDef = Object.prototype.hasOwnProperty.call(shapes, shapeName) ? shapes[shapeName] : void 0;
|
|
212
279
|
if (!shapeDef) throw new Error(`Unknown shape '${shapeName}'; registered shapes: ${Object.keys(shapes).sort().join(", ")}`);
|
|
280
|
+
JsonObjectSchema.parse(rawShapeParams);
|
|
281
|
+
const parsedShapeParams = shapeDef.paramsSchema.parse(rawShapeParams);
|
|
282
|
+
const mergedShapeParams = shapeName === "rectangle" && node.cornerRadius !== void 0 && !("cornerRadius" in parsedShapeParams) ? {
|
|
283
|
+
...parsedShapeParams,
|
|
284
|
+
cornerRadius: node.cornerRadius
|
|
285
|
+
} : parsedShapeParams;
|
|
213
286
|
const sx = node.xScale ?? node.scale ?? 1;
|
|
214
287
|
const sy = node.yScale ?? node.scale ?? 1;
|
|
215
288
|
const fontScale = Math.min(sx, sy);
|
|
289
|
+
const shapeScale = Math.sqrt(sx * sy);
|
|
290
|
+
const shapeParams = sx === 1 && sy === 1 ? mergedShapeParams : shapeDef.scaleParams ? shapeDef.scaleParams(mergedShapeParams, sx, sy) : scaleJsonNumbers(mergedShapeParams, shapeScale);
|
|
216
291
|
const baseFontSize = node.font?.size ?? DEFAULT_FONT_SIZE;
|
|
217
292
|
const fontSize = baseFontSize * fontScale;
|
|
218
293
|
const fontFamily = node.font?.family;
|
|
@@ -262,10 +337,13 @@ var layoutNode = (node, measureText, nameStack, nodeDistance, scopeChain = [], l
|
|
|
262
337
|
const minH = node.minimumHeight ?? node.minimumSize ?? 0;
|
|
263
338
|
const innerHalfW = Math.max(textWidth / 2 + xSep, xSep, minW / 2);
|
|
264
339
|
const innerHalfH = Math.max(textHeight / 2 + ySep, ySep, minH / 2);
|
|
265
|
-
const { halfWidth: boundsHalfW, halfHeight: boundsHalfH } = shapeDef.circumscribe(innerHalfW, innerHalfH);
|
|
340
|
+
const { halfWidth: boundsHalfW, halfHeight: boundsHalfH } = shapeDef.circumscribe(innerHalfW, innerHalfH, shapeParams);
|
|
266
341
|
const rotateDeg = node.rotate ?? 0;
|
|
267
342
|
const center = resolvePosition(node.position, nameStack, nodeDistance, scopeChain, resolveBetweenGlobal);
|
|
268
343
|
if (!center) throw new Error(`Cannot resolve position for node ${node.id ?? "(unnamed)"}; polar.origin / at.of / between endpoint may reference an undefined node`);
|
|
344
|
+
const aabbOffset = shapeDef.circumscribeOffset?.(shapeParams);
|
|
345
|
+
const rectCenterX = center[0] + (aabbOffset?.[0] ?? 0);
|
|
346
|
+
const rectCenterY = center[1] + (aabbOffset?.[1] ?? 0);
|
|
269
347
|
const labels = (node.label === void 0 ? void 0 : Array.isArray(node.label) ? node.label : [node.label])?.map((lab) => {
|
|
270
348
|
const labFont = lab.font;
|
|
271
349
|
const labFontSize = (labFont?.size ?? labelDefault?.font?.size ?? baseFontSize) * fontScale;
|
|
@@ -297,9 +375,10 @@ var layoutNode = (node, measureText, nameStack, nodeDistance, scopeChain = [], l
|
|
|
297
375
|
id: node.id,
|
|
298
376
|
shapeName,
|
|
299
377
|
shapeDef,
|
|
378
|
+
shapeParams,
|
|
300
379
|
rect: {
|
|
301
|
-
x:
|
|
302
|
-
y:
|
|
380
|
+
x: rectCenterX,
|
|
381
|
+
y: rectCenterY,
|
|
303
382
|
width: 2 * boundsHalfW,
|
|
304
383
|
height: 2 * boundsHalfH,
|
|
305
384
|
rotate: rotateDeg * DEG_TO_RAD
|
|
@@ -321,10 +400,14 @@ var layoutNode = (node, measureText, nameStack, nodeDistance, scopeChain = [], l
|
|
|
321
400
|
strokeOpacity: node.drawOpacity,
|
|
322
401
|
strokeWidth: node.strokeWidth,
|
|
323
402
|
dashPattern: resolveDashArray(node.dashArray, node.dashed, node.dotted),
|
|
324
|
-
|
|
403
|
+
cornerRadius: node.cornerRadius,
|
|
325
404
|
textColor: node.textColor,
|
|
326
405
|
opacity: node.opacity,
|
|
327
|
-
labels
|
|
406
|
+
labels,
|
|
407
|
+
boundary: node.boundary,
|
|
408
|
+
meta: node.meta,
|
|
409
|
+
animations: node.animations,
|
|
410
|
+
shapes
|
|
328
411
|
};
|
|
329
412
|
};
|
|
330
413
|
/** 从 NodeLayout 收敛 emit 所需的视觉样式子集(ShapeStyle,不含几何 / 文本);fill 经 resolveFill 转 PaintValue */
|
|
@@ -335,7 +418,7 @@ var toShapeStyle = (layout, resolveFill) => ({
|
|
|
335
418
|
strokeOpacity: layout.strokeOpacity,
|
|
336
419
|
strokeWidth: layout.strokeWidth,
|
|
337
420
|
dashPattern: layout.dashPattern,
|
|
338
|
-
|
|
421
|
+
cornerRadius: layout.cornerRadius,
|
|
339
422
|
opacity: layout.opacity
|
|
340
423
|
});
|
|
341
424
|
/**
|
|
@@ -380,7 +463,7 @@ var emitNodePrimitives = (layout, round, resolveFill) => {
|
|
|
380
463
|
...layout.rect,
|
|
381
464
|
rotate: 0
|
|
382
465
|
};
|
|
383
|
-
const shapePrims = [...layout.shapeDef.emit(axisAlignedRect, toShapeStyle(layout, resolveFill), round)];
|
|
466
|
+
const shapePrims = [...layout.shapeDef.emit(axisAlignedRect, toShapeStyle(layout, resolveFill), round, layout.shapeParams ?? EMPTY_SHAPE_PARAMS)];
|
|
384
467
|
const inner = [...shapePrims];
|
|
385
468
|
if (layout.lines) {
|
|
386
469
|
const halfBlockW = layout.textWidth / 2;
|
|
@@ -463,6 +546,8 @@ var emitNodePrimitives = (layout, round, resolveFill) => {
|
|
|
463
546
|
}
|
|
464
547
|
if (!(layout.rotateDeg !== 0 || layout.lines !== void 0)) {
|
|
465
548
|
if (layout.id !== void 0) for (const prim of shapePrims) prim.id = layout.id;
|
|
549
|
+
if (layout.meta !== void 0) for (const prim of shapePrims) prim.meta = layout.meta;
|
|
550
|
+
if (layout.animations !== void 0) for (const prim of shapePrims) prim.animations = layout.animations;
|
|
466
551
|
return inner;
|
|
467
552
|
}
|
|
468
553
|
const group = {
|
|
@@ -470,6 +555,8 @@ var emitNodePrimitives = (layout, round, resolveFill) => {
|
|
|
470
555
|
children: inner
|
|
471
556
|
};
|
|
472
557
|
if (layout.id !== void 0) group.id = layout.id;
|
|
558
|
+
if (layout.meta !== void 0) group.meta = layout.meta;
|
|
559
|
+
if (layout.animations !== void 0) group.animations = layout.animations;
|
|
473
560
|
if (layout.rotateDeg !== 0) group.transforms = [{
|
|
474
561
|
kind: "rotate",
|
|
475
562
|
degrees: round(layout.rotateDeg),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anchor.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/anchor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmC,UAAU,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"anchor.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/anchor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmC,UAAU,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEtF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAGjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AA6B/C;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,QAAQ,EAChB,WAAW,SAAS,EACpB,aAAY,aAAa,CAAC,SAAS,CAAM,KACxC,UAAU,GAAG,IA8Bf,CAAC;AAEF,4DAA4D;AAC5D,eAAO,MAAM,QAAQ,GACnB,MAAM,UAAU,EAChB,MAAM,UAAU,EAChB,KAAK,IAAI,GAAG,IAAI,KACf,UACqD,CAAC;AAEzD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,QAAQ,QAAQ,EAChB,QAAQ,UAAU,EAClB,WAAW,SAAS,EACpB,aAAY,aAAa,CAAC,SAAS,CAAM,KACxC,UAAU,GAAG,IAuBf,CAAC;AAEF,qCAAqC;AACrC,eAAO,MAAM,SAAS,GAAI,GAAG,UAAU,GAAG,IAAI,EAAE,GAAG,UAAU,GAAG,IAAI,KAAG,OACzB,CAAC;AAE/C,6BAA6B;AAC7B,eAAO,MAAM,WAAW,GAAI,GAAG,UAAU,EAAE,QAAQ,UAAU,EAAE,MAAM,MAAM,KAAG,UAM7E,CAAC"}
|
|
@@ -8,10 +8,10 @@ import { resolveAnchor, resolveEdgePoint } from "../anchor-cache.js";
|
|
|
8
8
|
var isNodeTarget = (t) => typeof t === "object" && !Array.isArray(t) && "id" in t;
|
|
9
9
|
/** target 是否 between 比例点(`{ between, t }`);独有 `between` 字段 */
|
|
10
10
|
var isBetween = (t) => typeof t === "object" && !Array.isArray(t) && "between" in t;
|
|
11
|
-
/** 解析 NodeTarget 的 anchor(非 undefined)到世界坐标:命名 / 角度走 resolveAnchor
|
|
12
|
-
var resolveAnchorRef = (node, anchor) => {
|
|
13
|
-
if (typeof anchor === "number") return resolveAnchor(node, String(anchor));
|
|
14
|
-
if (typeof anchor === "string") return resolveAnchor(node, anchor);
|
|
11
|
+
/** 解析 NodeTarget 的 anchor(非 undefined)到世界坐标:命名 / 角度走 resolveAnchor(可选连接面),`{ side, t }` 恒走视觉形状(不传 boundary) */
|
|
12
|
+
var resolveAnchorRef = (node, anchor, boundary) => {
|
|
13
|
+
if (typeof anchor === "number") return resolveAnchor(node, String(anchor), boundary);
|
|
14
|
+
if (typeof anchor === "string") return resolveAnchor(node, anchor, boundary);
|
|
15
15
|
return resolveEdgePoint(node, anchor.side, anchor.t);
|
|
16
16
|
};
|
|
17
17
|
/** anchor/边点解析后叠加世界系 offset(不随节点 rotate 旋转) */
|
|
@@ -27,7 +27,7 @@ var refPointOfTarget = (target, nameStack, scopeChain = []) => {
|
|
|
27
27
|
if (isNodeTarget(target)) {
|
|
28
28
|
const node = nameStack.lookup(target.id);
|
|
29
29
|
if (!node) return null;
|
|
30
|
-
return addOffset(target.anchor === void 0 ? [node.rect.x, node.rect.y] : resolveAnchorRef(node, target.anchor), target.offset);
|
|
30
|
+
return addOffset(target.anchor === void 0 ? [node.rect.x, node.rect.y] : resolveAnchorRef(node, target.anchor, target.boundary ?? node.boundary), target.offset);
|
|
31
31
|
}
|
|
32
32
|
if (isBetween(target)) {
|
|
33
33
|
const a = refPointOfTarget(target.between[0], nameStack, scopeChain);
|
|
@@ -54,7 +54,8 @@ var clipForTarget = (target, toward, nameStack, scopeChain = []) => {
|
|
|
54
54
|
if (isNodeTarget(target)) {
|
|
55
55
|
const node = nameStack.lookup(target.id);
|
|
56
56
|
if (!node) return null;
|
|
57
|
-
|
|
57
|
+
const boundary = target.boundary ?? node.boundary;
|
|
58
|
+
return addOffset(target.anchor === void 0 ? boundaryPointOf(node, toward, boundary) : resolveAnchorRef(node, target.anchor, boundary), target.offset);
|
|
58
59
|
}
|
|
59
60
|
if (isBetween(target)) return refPointOfTarget(target, nameStack, scopeChain);
|
|
60
61
|
if (typeof target === "object" && !Array.isArray(target) && ("relative" in target || "relativeAccumulate" in target)) return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAY9C,OAAO,KAAK,EACV,MAAM,EAEN,UAAU,EAGX,MAAM,UAAU,CAAC;AAElB,OAAO,KAAK,EAIV,cAAc,EACd,SAAS,EACV,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,KAAK,YAAY,EAAoB,MAAM,iBAAiB,CAAC;AAKtE,OAAO,EAAE,KAAK,eAAe,EAA2D,MAAM,UAAU,CAAC;AA8FzG,mCAAmC;AACnC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,iCAAiC;IACjC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,KAAK,IAAI,CAAC;IACX,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACtC,wEAAwE;IACxE,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5B;;;;OAIG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC;;;;;OAKG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;CACnE,CAAC;AA0EF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,EACZ,WAAW,SAAS,EACpB,OAAO,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAC5B,cAAa,YAA+B,EAC5C,WAAU,gBAAqB,KAC9B;IAAE,UAAU,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;CAAE,GAAG,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAY9C,OAAO,KAAK,EACV,MAAM,EAEN,UAAU,EAGX,MAAM,UAAU,CAAC;AAElB,OAAO,KAAK,EAIV,cAAc,EACd,SAAS,EACV,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,KAAK,YAAY,EAAoB,MAAM,iBAAiB,CAAC;AAKtE,OAAO,EAAE,KAAK,eAAe,EAA2D,MAAM,UAAU,CAAC;AA8FzG,mCAAmC;AACnC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,iCAAiC;IACjC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,KAAK,IAAI,CAAC;IACX,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,UAAU,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACtC,wEAAwE;IACxE,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5B;;;;OAIG;IACH,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC;;;;;OAKG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;CACnE,CAAC;AA0EF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,EACZ,WAAW,SAAS,EACpB,OAAO,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,EAC5B,cAAa,YAA+B,EAC5C,WAAU,gBAAqB,KAC9B;IAAE,UAAU,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC,UAAU,CAAC,CAAA;CAAE,GAAG,IAsvBrE,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { rectOutline } from "../../geometry/rect.js";
|
|
2
1
|
import { JsonObjectSchema } from "../../ir/json.js";
|
|
2
|
+
import { rectOutline } from "../../geometry/rect.js";
|
|
3
|
+
import { arcBoundingPoints, arcEndPoint, ellipseArcBoundingPoints, ellipseArcPoint } from "../../geometry/arc.js";
|
|
3
4
|
import { BUILTIN_ARROWS } from "../../arrows/index.js";
|
|
4
5
|
import { applyTransformChain } from "../scope.js";
|
|
5
|
-
import { arcBoundingPoints, arcEndPoint, ellipseArcBoundingPoints, ellipseArcPoint } from "../../geometry/arc.js";
|
|
6
6
|
import { bendControlPoints, outInControlPoints } from "../../geometry/bend.js";
|
|
7
7
|
import { arcSegmentSample, circleSegmentSample, cubicSegmentSample, ellipseArcSegmentSample, ellipseSegmentSample, foldSegmentSample, lineSegmentSample, quadSegmentSample } from "../../geometry/segment.js";
|
|
8
8
|
import { fallbackMeasurer } from "../text-metrics.js";
|
|
@@ -434,7 +434,7 @@ var emitPathPrimitive = (path, nameStack, round, measureText = fallbackMeasurer,
|
|
|
434
434
|
return null;
|
|
435
435
|
}
|
|
436
436
|
let rectStart = null;
|
|
437
|
-
for (const op of rectOutline(fromPt, toPt, step.
|
|
437
|
+
for (const op of rectOutline(fromPt, toPt, step.cornerRadius)) if (op.kind === "move") {
|
|
438
438
|
emitMove(op.to);
|
|
439
439
|
rectStart = op.to;
|
|
440
440
|
} else if (op.kind === "line") emitLine(op.to);
|
|
@@ -647,6 +647,8 @@ var emitPathPrimitive = (path, nameStack, round, measureText = fallbackMeasurer,
|
|
|
647
647
|
children: bodyPrims
|
|
648
648
|
};
|
|
649
649
|
if (path.id !== void 0) group.id = path.id;
|
|
650
|
+
if (path.meta !== void 0) group.meta = path.meta;
|
|
651
|
+
if (path.animations !== void 0) group.animations = path.animations;
|
|
650
652
|
const transformedPoints = points.map((p) => applyTransformChain(p, transforms));
|
|
651
653
|
if (!transformedPoints.every(isFinitePoint)) throw new Error("Path rotate / scale produced a non-finite coordinate (scale too large); use a smaller scale.");
|
|
652
654
|
return {
|
|
@@ -656,6 +658,8 @@ var emitPathPrimitive = (path, nameStack, round, measureText = fallbackMeasurer,
|
|
|
656
658
|
}
|
|
657
659
|
}
|
|
658
660
|
if (path.id !== void 0) primitive.id = path.id;
|
|
661
|
+
if (path.meta !== void 0) primitive.meta = path.meta;
|
|
662
|
+
if (path.animations !== void 0) primitive.animations = path.animations;
|
|
659
663
|
return {
|
|
660
664
|
primitives: bodyPrims,
|
|
661
665
|
points
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../../src/compile/scope.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGV,UAAU,EACV,WAAW,EAEZ,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGzC;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAC/B,YAAY,aAAa,CAAC,WAAW,CAAC,EACtC,WAAW,SAAS,EACpB,eAAe,MAAM,KACpB,KAAK,CAAC,SAAS,CAAC,GAAG,IAiDrB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAC9B,OAAO,UAAU,EACjB,OAAO,aAAa,CAAC,SAAS,CAAC,KAC9B,UAyBF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,GAChC,QAAQ,UAAU,EAClB,OAAO,aAAa,CAAC,SAAS,CAAC,KAC9B,UAgCF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,GAChC,QAAQ,UAAU,EAClB,OAAO,aAAa,CAAC,SAAS,CAAC,KAC9B,UAuBF,CAAC;AAEF,8EAA8E;AAC9E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,wBAAwB;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,wBAAwB;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,qCAAqC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,GAClC,SAAS,aAAa,CAAC,UAAU,CAAC,KACjC,gBAAgB,GAAG,IA2BrB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAChC,IAAI,MAAM,EACV,MAAM,gBAAgB,GAAG,IAAI,EAC7B,gBAAgB,UAAU,KACzB,
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../../src/compile/scope.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGV,UAAU,EACV,WAAW,EAEZ,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGzC;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAC/B,YAAY,aAAa,CAAC,WAAW,CAAC,EACtC,WAAW,SAAS,EACpB,eAAe,MAAM,KACpB,KAAK,CAAC,SAAS,CAAC,GAAG,IAiDrB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAC9B,OAAO,UAAU,EACjB,OAAO,aAAa,CAAC,SAAS,CAAC,KAC9B,UAyBF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,GAChC,QAAQ,UAAU,EAClB,OAAO,aAAa,CAAC,SAAS,CAAC,KAC9B,UAgCF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,GAChC,QAAQ,UAAU,EAClB,OAAO,aAAa,CAAC,SAAS,CAAC,KAC9B,UAuBF,CAAC;AAEF,8EAA8E;AAC9E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,wBAAwB;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,wBAAwB;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,qCAAqC;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,GAClC,SAAS,aAAa,CAAC,UAAU,CAAC,KACjC,gBAAgB,GAAG,IA2BrB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAChC,IAAI,MAAM,EACV,MAAM,gBAAgB,GAAG,IAAI,EAC7B,gBAAgB,UAAU,KACzB,UAiBF,CAAC"}
|
package/dist/es/compile/scope.js
CHANGED
|
@@ -6,6 +6,20 @@ export declare const arcEndPoint: (center: Position, radius: number, angleDeg: n
|
|
|
6
6
|
* @description 弧投影到 x/y 轴的极值只可能在弧端点或圆周轴向四点出现。endAngle < startAngle 时按 min..max 扫描;跨 360°(270→450)按数值区间正确处理;不去重——端角恰在 90°·k 上时调用方处理
|
|
7
7
|
*/
|
|
8
8
|
export declare const arcBoundingPoints: (center: Position, radius: number, startAngleDeg: number, endAngleDeg: number) => Array<Position>;
|
|
9
|
+
/**
|
|
10
|
+
* 角度 a(度)是否落在弧的角度区间 [startAngle, endAngle] 内(含端点,带容差)
|
|
11
|
+
* @description 与 ir/path arc 同约定:弧从 startAngle 扫到 endAngle,counterClockwise=false(缺省)
|
|
12
|
+
* 时角度递增(屏幕顺时针)、true 时角度递减(逆时针)。统一把扫描量化为「从 start 出发、沿扫描方向
|
|
13
|
+
* 累积的非负 sweep ∈ [0, |span|]」判定,跨 360°、负角、巨型角都正确(不死循环)。
|
|
14
|
+
*/
|
|
15
|
+
export declare const arcAngleInRange: (startAngleDeg: number, endAngleDeg: number, angleDeg: number, toleranceDeg?: number) => boolean;
|
|
16
|
+
/**
|
|
17
|
+
* 射线(origin + 单位方向 dir)∩ 圆弧(center, radius, [startAngle, endAngle])
|
|
18
|
+
* @description 泛化 sector 的内联 rayCircle:先解 |origin + s·dir|² = radius² 得至多两个参数 s,
|
|
19
|
+
* 再用 arcAngleInRange 过滤掉不在弧角度区间内的交点。返回沿射线的正向参数 s(命中点 = origin + s·dir),
|
|
20
|
+
* 按 s 升序、仅含 s > tolerance 的正向交点;不在区间内的根被剔除。dir 必须为单位向量。
|
|
21
|
+
*/
|
|
22
|
+
export declare const rayArc: (origin: Position, dir: Position, center: Position, radius: number, startAngleDeg: number, endAngleDeg: number, tolerance?: number) => Array<number>;
|
|
9
23
|
/**
|
|
10
24
|
* 椭圆弧参数点:中心 + 半轴 rx/ry + 参数角(度)→ 椭圆周上点
|
|
11
25
|
* @description 与 arcEndPoint 同角度约定(SVG y-down);endpoint = [cx + rx·cosθ, cy + ry·sinθ]。
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"arc.d.ts","sourceRoot":"","sources":["../../../src/geometry/arc.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"arc.d.ts","sourceRoot":"","sources":["../../../src/geometry/arc.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AA8BxC,iDAAiD;AACjD,eAAO,MAAM,WAAW,GACtB,QAAQ,QAAQ,EAChB,QAAQ,MAAM,EACd,UAAU,MAAM,KACf,QAMF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,QAAQ,EAChB,QAAQ,MAAM,EACd,eAAe,MAAM,EACrB,aAAa,MAAM,KAClB,KAAK,CAAC,QAAQ,CAchB,CAAC;AAQF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAC1B,eAAe,MAAM,EACrB,aAAa,MAAM,EACnB,UAAU,MAAM,EAChB,qBAAmB,KAClB,OASF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,MAAM,GACjB,QAAQ,QAAQ,EAChB,KAAK,QAAQ,EACb,QAAQ,QAAQ,EAChB,QAAQ,MAAM,EACd,eAAe,MAAM,EACrB,aAAa,MAAM,EACnB,kBAAgB,KACf,KAAK,CAAC,MAAM,CAuBd,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAC1B,QAAQ,QAAQ,EAChB,SAAS,MAAM,EACf,SAAS,MAAM,EACf,UAAU,MAAM,KACf,QAMF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GACnC,QAAQ,QAAQ,EAChB,SAAS,MAAM,EACf,SAAS,MAAM,EACf,eAAe,MAAM,EACrB,aAAa,MAAM,KAClB,KAAK,CAAC,QAAQ,CAYhB,CAAC"}
|
package/dist/es/geometry/arc.js
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
//#region src/geometry/arc.ts
|
|
2
2
|
var DEG_TO_RAD = Math.PI / 180;
|
|
3
|
+
/**
|
|
4
|
+
* 在 [lo, hi] 内枚举所有 90°·k 方向角(弧轴向极值候选)
|
|
5
|
+
* @description 一圈最多 4 个轴向,合法弧 sweep ≤ 360° → 至多 5 个 90°·k;正常区间直接 for 扫。
|
|
6
|
+
* 但 lo/hi 为巨型角度(如 1e308)时 k=ceil(lo/90) 落在浮点无整数分辨率区,`k++` 满足 k+1===k →
|
|
7
|
+
* for 循环永不前进而挂死(DoS)。此时端点投影已覆盖全部 x/y 极值(巨角下弧实际是退化点 / 单端),
|
|
8
|
+
* 轴向点无新增信息 → 直接跳过枚举。守卫:仅当 kEnd−kStart 是 finite 且 ≤ 安全上界(远大于
|
|
9
|
+
* 任何合法弧的轴向点数)时才枚举,否则返回空(端点已足够定界)。
|
|
10
|
+
*/
|
|
11
|
+
var axisAngles = (lo, hi) => {
|
|
12
|
+
const kStart = Math.ceil(lo / 90);
|
|
13
|
+
const kEnd = Math.floor(hi / 90);
|
|
14
|
+
const span = kEnd - kStart;
|
|
15
|
+
if (!Number.isFinite(span) || span < 0 || span > 1e6) return [];
|
|
16
|
+
const angles = [];
|
|
17
|
+
for (let k = kStart; k <= kEnd; k++) angles.push(k * 90);
|
|
18
|
+
return angles;
|
|
19
|
+
};
|
|
3
20
|
/** 圆心、半径、角度(度,与 polar.toPosition 同约定)→ 圆周上对应点 */
|
|
4
21
|
var arcEndPoint = (center, radius, angleDeg) => {
|
|
5
22
|
const rad = angleDeg * DEG_TO_RAD;
|
|
@@ -13,15 +30,57 @@ var arcBoundingPoints = (center, radius, startAngleDeg, endAngleDeg) => {
|
|
|
13
30
|
const points = [arcEndPoint(center, radius, startAngleDeg), arcEndPoint(center, radius, endAngleDeg)];
|
|
14
31
|
const lo = Math.min(startAngleDeg, endAngleDeg);
|
|
15
32
|
const hi = Math.max(startAngleDeg, endAngleDeg);
|
|
16
|
-
const
|
|
17
|
-
const kEnd = Math.floor(hi / 90);
|
|
18
|
-
for (let k = kStart; k <= kEnd; k++) {
|
|
19
|
-
const angle = k * 90;
|
|
33
|
+
for (const angle of axisAngles(lo, hi)) {
|
|
20
34
|
if (angle === startAngleDeg || angle === endAngleDeg) continue;
|
|
21
35
|
points.push(arcEndPoint(center, radius, angle));
|
|
22
36
|
}
|
|
23
37
|
return points;
|
|
24
38
|
};
|
|
39
|
+
/** 角度(度)→ 规范化到 [0, 360) */
|
|
40
|
+
var normalizeDeg = (deg) => {
|
|
41
|
+
const m = deg % 360;
|
|
42
|
+
return m < 0 ? m + 360 : m;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* 角度 a(度)是否落在弧的角度区间 [startAngle, endAngle] 内(含端点,带容差)
|
|
46
|
+
* @description 与 ir/path arc 同约定:弧从 startAngle 扫到 endAngle,counterClockwise=false(缺省)
|
|
47
|
+
* 时角度递增(屏幕顺时针)、true 时角度递减(逆时针)。统一把扫描量化为「从 start 出发、沿扫描方向
|
|
48
|
+
* 累积的非负 sweep ∈ [0, |span|]」判定,跨 360°、负角、巨型角都正确(不死循环)。
|
|
49
|
+
*/
|
|
50
|
+
var arcAngleInRange = (startAngleDeg, endAngleDeg, angleDeg, toleranceDeg = 1e-7) => {
|
|
51
|
+
const span = endAngleDeg - startAngleDeg;
|
|
52
|
+
const total = Math.abs(span);
|
|
53
|
+
if (total >= 360 - toleranceDeg) return true;
|
|
54
|
+
const swept = normalizeDeg(span < 0 ? startAngleDeg - angleDeg : angleDeg - startAngleDeg);
|
|
55
|
+
return swept <= total + toleranceDeg || swept >= 360 - toleranceDeg;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* 射线(origin + 单位方向 dir)∩ 圆弧(center, radius, [startAngle, endAngle])
|
|
59
|
+
* @description 泛化 sector 的内联 rayCircle:先解 |origin + s·dir|² = radius² 得至多两个参数 s,
|
|
60
|
+
* 再用 arcAngleInRange 过滤掉不在弧角度区间内的交点。返回沿射线的正向参数 s(命中点 = origin + s·dir),
|
|
61
|
+
* 按 s 升序、仅含 s > tolerance 的正向交点;不在区间内的根被剔除。dir 必须为单位向量。
|
|
62
|
+
*/
|
|
63
|
+
var rayArc = (origin, dir, center, radius, startAngleDeg, endAngleDeg, tolerance = 1e-9) => {
|
|
64
|
+
const ox = origin[0] - center[0];
|
|
65
|
+
const oy = origin[1] - center[1];
|
|
66
|
+
const ux = dir[0];
|
|
67
|
+
const uy = dir[1];
|
|
68
|
+
const b = 2 * (ox * ux + oy * uy);
|
|
69
|
+
const c = ox * ox + oy * oy - radius * radius;
|
|
70
|
+
const disc = b * b - 4 * c;
|
|
71
|
+
if (disc < 0) return [];
|
|
72
|
+
const sq = Math.sqrt(disc);
|
|
73
|
+
const roots = [(-b - sq) / 2, (-b + sq) / 2];
|
|
74
|
+
const hits = [];
|
|
75
|
+
for (const s of roots) {
|
|
76
|
+
if (s <= tolerance) continue;
|
|
77
|
+
const px = ox + s * ux;
|
|
78
|
+
const py = oy + s * uy;
|
|
79
|
+
if (arcAngleInRange(startAngleDeg, endAngleDeg, Math.atan2(py, px) * (180 / Math.PI))) hits.push(s);
|
|
80
|
+
}
|
|
81
|
+
hits.sort((a, z) => a - z);
|
|
82
|
+
return hits;
|
|
83
|
+
};
|
|
25
84
|
/**
|
|
26
85
|
* 椭圆弧参数点:中心 + 半轴 rx/ry + 参数角(度)→ 椭圆周上点
|
|
27
86
|
* @description 与 arcEndPoint 同角度约定(SVG y-down);endpoint = [cx + rx·cosθ, cy + ry·sinθ]。
|
|
@@ -39,14 +98,11 @@ var ellipseArcBoundingPoints = (center, radiusX, radiusY, startAngleDeg, endAngl
|
|
|
39
98
|
const points = [ellipseArcPoint(center, radiusX, radiusY, startAngleDeg), ellipseArcPoint(center, radiusX, radiusY, endAngleDeg)];
|
|
40
99
|
const lo = Math.min(startAngleDeg, endAngleDeg);
|
|
41
100
|
const hi = Math.max(startAngleDeg, endAngleDeg);
|
|
42
|
-
const
|
|
43
|
-
const kEnd = Math.floor(hi / 90);
|
|
44
|
-
for (let k = kStart; k <= kEnd; k++) {
|
|
45
|
-
const angle = k * 90;
|
|
101
|
+
for (const angle of axisAngles(lo, hi)) {
|
|
46
102
|
if (angle === startAngleDeg || angle === endAngleDeg) continue;
|
|
47
103
|
points.push(ellipseArcPoint(center, radiusX, radiusY, angle));
|
|
48
104
|
}
|
|
49
105
|
return points;
|
|
50
106
|
};
|
|
51
107
|
//#endregion
|
|
52
|
-
export { arcBoundingPoints, arcEndPoint, ellipseArcBoundingPoints, ellipseArcPoint };
|
|
108
|
+
export { arcAngleInRange, arcBoundingPoints, arcEndPoint, ellipseArcBoundingPoints, ellipseArcPoint, rayArc };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/geometry/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,WAAW,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/geometry/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC"}
|
|
@@ -54,8 +54,8 @@ export type RectOutlineOp = {
|
|
|
54
54
|
/**
|
|
55
55
|
* 矩形 outline:两对角 → 顺时针 path 算子序列
|
|
56
56
|
* @description from/to 任意顺序,归一化 (x0,y0)=min、(x1,y1)=max。直角 = 4 line + close(起点左上 (x0,y0));
|
|
57
|
-
* 圆角 = 4 line + 4 quarter-arc + close(起点 (x0+r, y0))。
|
|
57
|
+
* 圆角 = 4 line + 4 quarter-arc + close(起点 (x0+r, y0))。cornerRadius clamp 到 min(w,h)/2。
|
|
58
58
|
* 角度约定同 geometry/arc(y-down:0=+x, 90=+y/下, 180=-x, 270=-y/上)。
|
|
59
59
|
*/
|
|
60
|
-
export declare const rectOutline: (from: Position, to: Position,
|
|
60
|
+
export declare const rectOutline: (from: Position, to: Position, cornerRadius?: number) => Array<RectOutlineOp>;
|
|
61
61
|
//# sourceMappingURL=rect.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rect.d.ts","sourceRoot":"","sources":["../../../src/geometry/rect.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,IAAI,EAAa,MAAM,SAAS,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,gCAAgC;AAChC,MAAM,MAAM,IAAI,GAAG;IACjB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,cAAc;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,YAAY;;;;;;;;;;CAUf,CAAC;AAEX,+BAA+B;AAC/B,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAE1E,eAAO,MAAM,IAAI;IACf,WAAW;gBACC,IAAI,KAAG,QAAQ;IAC3B,uBAAuB;kBACT,IAAI,KAAK,QAAQ,KAAG,OAAO;IAMzC,sCAAsC;gBAC1B,IAAI,QAAQ,UAAU,KAAG,QAAQ;IAuC7C,qDAAqD;uBAClC,IAAI,UAAU,QAAQ,KAAG,QAAQ;IAUpD,gEAAgE;mBACjD,IAAI,QAAQ,IAAI,KAAK,MAAM,KAAG,QAAQ;CAItD,CAAC;AAEF,4FAA4F;AAC5F,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,QAAQ,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,QAAQ,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACvF;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtB;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GACtB,MAAM,QAAQ,EACd,IAAI,QAAQ,EACZ,
|
|
1
|
+
{"version":3,"file":"rect.d.ts","sourceRoot":"","sources":["../../../src/geometry/rect.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,IAAI,EAAa,MAAM,SAAS,CAAC;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,gCAAgC;AAChC,MAAM,MAAM,IAAI,GAAG;IACjB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,cAAc;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,YAAY;;;;;;;;;;CAUf,CAAC;AAEX,+BAA+B;AAC/B,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAE1E,eAAO,MAAM,IAAI;IACf,WAAW;gBACC,IAAI,KAAG,QAAQ;IAC3B,uBAAuB;kBACT,IAAI,KAAK,QAAQ,KAAG,OAAO;IAMzC,sCAAsC;gBAC1B,IAAI,QAAQ,UAAU,KAAG,QAAQ;IAuC7C,qDAAqD;uBAClC,IAAI,UAAU,QAAQ,KAAG,QAAQ;IAUpD,gEAAgE;mBACjD,IAAI,QAAQ,IAAI,KAAK,MAAM,KAAG,QAAQ;CAItD,CAAC;AAEF,4FAA4F;AAC5F,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,QAAQ,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,QAAQ,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACvF;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtB;;;;;GAKG;AACH,eAAO,MAAM,WAAW,GACtB,MAAM,QAAQ,EACd,IAAI,QAAQ,EACZ,eAAe,MAAM,KACpB,KAAK,CAAC,aAAa,CAgCrB,CAAC"}
|
package/dist/es/geometry/rect.js
CHANGED
|
@@ -82,15 +82,15 @@ var rect = {
|
|
|
82
82
|
/**
|
|
83
83
|
* 矩形 outline:两对角 → 顺时针 path 算子序列
|
|
84
84
|
* @description from/to 任意顺序,归一化 (x0,y0)=min、(x1,y1)=max。直角 = 4 line + close(起点左上 (x0,y0));
|
|
85
|
-
* 圆角 = 4 line + 4 quarter-arc + close(起点 (x0+r, y0))。
|
|
85
|
+
* 圆角 = 4 line + 4 quarter-arc + close(起点 (x0+r, y0))。cornerRadius clamp 到 min(w,h)/2。
|
|
86
86
|
* 角度约定同 geometry/arc(y-down:0=+x, 90=+y/下, 180=-x, 270=-y/上)。
|
|
87
87
|
*/
|
|
88
|
-
var rectOutline = (from, to,
|
|
88
|
+
var rectOutline = (from, to, cornerRadius) => {
|
|
89
89
|
const x0 = Math.min(from[0], to[0]);
|
|
90
90
|
const x1 = Math.max(from[0], to[0]);
|
|
91
91
|
const y0 = Math.min(from[1], to[1]);
|
|
92
92
|
const y1 = Math.max(from[1], to[1]);
|
|
93
|
-
const r =
|
|
93
|
+
const r = cornerRadius === void 0 ? 0 : Math.min(cornerRadius, (x1 - x0) / 2, (y1 - y0) / 2);
|
|
94
94
|
if (r <= 0) return [
|
|
95
95
|
{
|
|
96
96
|
kind: "move",
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Position } from './point';
|
|
2
|
+
/** 直线段:从 from 到 to 的有向线段 */
|
|
3
|
+
export type LineSegment = {
|
|
4
|
+
/** 鉴别字面量 */
|
|
5
|
+
kind: 'line';
|
|
6
|
+
/** 起点 [x, y] */
|
|
7
|
+
from: Position;
|
|
8
|
+
/** 终点 [x, y] */
|
|
9
|
+
to: Position;
|
|
10
|
+
};
|
|
11
|
+
/** 圆弧段:圆心 + 半径 + 起末角(度)+ 扫描方向,与 ir/path arc 同参数化 */
|
|
12
|
+
export type ArcSegment = {
|
|
13
|
+
/** 鉴别字面量 */
|
|
14
|
+
kind: 'arc';
|
|
15
|
+
/** 圆心 [x, y] */
|
|
16
|
+
center: Position;
|
|
17
|
+
/** 半径(user units) */
|
|
18
|
+
radius: number;
|
|
19
|
+
/** 起始角度(度,0=+x、90=+y 视觉下) */
|
|
20
|
+
startAngle: number;
|
|
21
|
+
/** 终止角度(度) */
|
|
22
|
+
endAngle: number;
|
|
23
|
+
/** 是否逆时针扫描;缺省 / false = CW(角度递增 / 屏幕顺时针) */
|
|
24
|
+
counterClockwise?: boolean;
|
|
25
|
+
};
|
|
26
|
+
/** 轮廓段:组成闭合轮廓的最小单元(直线或圆弧) */
|
|
27
|
+
export type ContourSegment = LineSegment | ArcSegment;
|
|
28
|
+
/** fillet 后用于 emit 的路径命令(与 primitive/path PathCommand 的 move/line/arc/close 子集对齐) */
|
|
29
|
+
export type ContourCommand = {
|
|
30
|
+
kind: 'move';
|
|
31
|
+
to: Position;
|
|
32
|
+
} | {
|
|
33
|
+
kind: 'line';
|
|
34
|
+
to: Position;
|
|
35
|
+
} | {
|
|
36
|
+
kind: 'arc';
|
|
37
|
+
center: Position;
|
|
38
|
+
radius: number;
|
|
39
|
+
startAngle: number;
|
|
40
|
+
endAngle: number;
|
|
41
|
+
counterClockwise?: boolean;
|
|
42
|
+
} | {
|
|
43
|
+
kind: 'close';
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* 一个接缝处 fillet 的解算结果
|
|
47
|
+
* @description tangentInPoint = 前段被裁短到此点(前段新终点);tangentOutPoint = 后段从此点起(后段新起点);
|
|
48
|
+
* filletArc 描述连接两切点的圆弧。clampedToZero=true 表示该角夹紧后 r→0,不倒角(保持尖角)。
|
|
49
|
+
*/
|
|
50
|
+
type FilletSolution = {
|
|
51
|
+
/** 前段切点(前段新终点) */
|
|
52
|
+
tangentInPoint: Position;
|
|
53
|
+
/** 后段切点(后段新起点) */
|
|
54
|
+
tangentOutPoint: Position;
|
|
55
|
+
/** fillet 圆心 */
|
|
56
|
+
center: Position;
|
|
57
|
+
/** fillet 半径 */
|
|
58
|
+
radius: number;
|
|
59
|
+
/** fillet 弧起始角(度,从 center 看 tangentInPoint) */
|
|
60
|
+
startAngle: number;
|
|
61
|
+
/** fillet 弧终止角(度,从 center 看 tangentOutPoint) */
|
|
62
|
+
endAngle: number;
|
|
63
|
+
/** fillet 弧是否逆时针 */
|
|
64
|
+
counterClockwise: boolean;
|
|
65
|
+
/** 夹紧后 r→0,本角不倒(emit 走原尖角) */
|
|
66
|
+
clampedToZero: boolean;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* 对闭合轮廓的每个接缝做 fillet,返回 fillet 解算列表(与接缝一一对应,下标 i = 段 i 终点接段 (i+1)%n 起点)
|
|
70
|
+
* @description cornerRadius 省略 / ≤0 → 返回空数组(调用方据此 passthrough 原段序列)。arc-arc 接缝抛错。
|
|
71
|
+
*/
|
|
72
|
+
export declare const filletContour: (segments: Array<ContourSegment>, cornerRadius?: number) => Array<FilletSolution>;
|
|
73
|
+
/**
|
|
74
|
+
* 把闭合轮廓 + cornerRadius emit 成路径命令(move + 缩短 line + 裁剪原 arc + fillet arc + close)
|
|
75
|
+
* @description cornerRadius 省略 / ≤0 → 直接 emit 原始尖角轮廓(passthrough)。否则每段从「上一接缝的
|
|
76
|
+
* fillet 出点」走到「本接缝的 fillet 入点」(line 缩短 / arc 裁剪角度),接缝处插 fillet 弧。
|
|
77
|
+
* 夹紧到 0 的角不插弧、按原尖角连接。
|
|
78
|
+
*/
|
|
79
|
+
export declare const contourCommands: (segments: Array<ContourSegment>, cornerRadius?: number) => Array<ContourCommand>;
|
|
80
|
+
/**
|
|
81
|
+
* 从 rayOrigin 朝 toward 射线 ∩ fillet 后轮廓全部段,返回最近正向交点
|
|
82
|
+
* @description rayOrigin 显式传(不假设中心);toward 是射线指向的目标点(方向 = toward − rayOrigin)。
|
|
83
|
+
* 遍历 fillet 后的有效段(缩短 line / 裁剪 arc / fillet arc),对每段求 ray∩段、取最小正参数命中点。
|
|
84
|
+
* cornerRadius 省略 / ≤0 → 走原尖角轮廓。无命中返回 undefined(调用方兜底)。
|
|
85
|
+
*/
|
|
86
|
+
export declare const boundaryFromContour: (segments: Array<ContourSegment>, cornerRadius: number | undefined, rayOrigin: Position, toward: Position) => Position | undefined;
|
|
87
|
+
export {};
|
|
88
|
+
//# sourceMappingURL=roundedContour.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roundedContour.d.ts","sourceRoot":"","sources":["../../../src/geometry/roundedContour.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAkBxC,4BAA4B;AAC5B,MAAM,MAAM,WAAW,GAAG;IACxB,YAAY;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB;IAChB,IAAI,EAAE,QAAQ,CAAC;IACf,gBAAgB;IAChB,EAAE,EAAE,QAAQ,CAAC;CACd,CAAC;AAEF,oDAAoD;AACpD,MAAM,MAAM,UAAU,GAAG;IACvB,YAAY;IACZ,IAAI,EAAE,KAAK,CAAC;IACZ,gBAAgB;IAChB,MAAM,EAAE,QAAQ,CAAC;IACjB,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,6BAA6B;AAC7B,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,UAAU,CAAC;AAEtD,qFAAqF;AACrF,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,QAAQ,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,QAAQ,CAAA;CAAE,GAC9B;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,MAAM,EAAE,QAAQ,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,GACD;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AA6CtB;;;;GAIG;AACH,KAAK,cAAc,GAAG;IACpB,kBAAkB;IAClB,cAAc,EAAE,QAAQ,CAAC;IACzB,kBAAkB;IAClB,eAAe,EAAE,QAAQ,CAAC;IAC1B,gBAAgB;IAChB,MAAM,EAAE,QAAQ,CAAC;IACjB,gBAAgB;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB;IACpB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,8BAA8B;IAC9B,aAAa,EAAE,OAAO,CAAC;CACxB,CAAC;AAgTF;;;GAGG;AACH,eAAO,MAAM,aAAa,GACxB,UAAU,KAAK,CAAC,cAAc,CAAC,EAC/B,eAAe,MAAM,KACpB,KAAK,CAAC,cAAc,CAUtB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAC1B,UAAU,KAAK,CAAC,cAAc,CAAC,EAC/B,eAAe,MAAM,KACpB,KAAK,CAAC,cAAc,CAuCtB,CAAC;AAwCF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAC9B,UAAU,KAAK,CAAC,cAAc,CAAC,EAC/B,cAAc,MAAM,GAAG,SAAS,EAChC,WAAW,QAAQ,EACnB,QAAQ,QAAQ,KACf,QAAQ,GAAG,SA2Eb,CAAC"}
|