@retikz/core 0.1.0-alpha.5 → 0.1.0-beta.1
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/es/compile/compile.d.ts +17 -0
- package/dist/es/compile/compile.d.ts.map +1 -1
- package/dist/es/compile/compile.js +40 -15
- package/dist/es/compile/index.d.ts +1 -1
- package/dist/es/compile/index.d.ts.map +1 -1
- package/dist/es/compile/node.d.ts +3 -3
- package/dist/es/compile/node.d.ts.map +1 -1
- package/dist/es/compile/node.js +1 -1
- package/dist/es/compile/path/anchor.d.ts +19 -0
- package/dist/es/compile/path/anchor.d.ts.map +1 -0
- package/dist/es/compile/path/anchor.js +54 -0
- package/dist/es/compile/{path.d.ts → path/index.d.ts} +18 -7
- package/dist/es/compile/path/index.d.ts.map +1 -0
- package/dist/es/compile/path/index.js +308 -0
- package/dist/es/compile/path/label.d.ts +18 -0
- package/dist/es/compile/path/label.d.ts.map +1 -0
- package/dist/es/compile/path/label.js +102 -0
- package/dist/es/compile/path/relative.d.ts +8 -0
- package/dist/es/compile/path/relative.d.ts.map +1 -0
- package/dist/es/compile/path/relative.js +48 -0
- package/dist/es/compile/path/shrink.d.ts +24 -0
- package/dist/es/compile/path/shrink.d.ts.map +1 -0
- package/dist/es/compile/path/shrink.js +136 -0
- package/dist/es/compile/path/split.d.ts +15 -0
- package/dist/es/compile/path/split.d.ts.map +1 -0
- package/dist/es/compile/path/split.js +46 -0
- package/dist/es/compile/text-metrics.d.ts +4 -1
- package/dist/es/compile/text-metrics.d.ts.map +1 -1
- package/dist/es/compile/text-metrics.js +11 -5
- package/dist/es/geometry/_transform.d.ts +21 -0
- package/dist/es/geometry/_transform.d.ts.map +1 -0
- package/dist/es/geometry/_transform.js +27 -0
- package/dist/es/geometry/bend.d.ts +1 -1
- package/dist/es/geometry/bend.js +1 -1
- package/dist/es/geometry/circle.d.ts +2 -3
- package/dist/es/geometry/circle.d.ts.map +1 -1
- package/dist/es/geometry/circle.js +1 -16
- package/dist/es/geometry/diamond.d.ts +2 -3
- package/dist/es/geometry/diamond.d.ts.map +1 -1
- package/dist/es/geometry/diamond.js +1 -16
- package/dist/es/geometry/ellipse.d.ts +2 -3
- package/dist/es/geometry/ellipse.d.ts.map +1 -1
- package/dist/es/geometry/ellipse.js +1 -16
- package/dist/es/geometry/polar.d.ts +2 -2
- package/dist/es/geometry/polar.d.ts.map +1 -1
- package/dist/es/geometry/polar.js +2 -6
- package/dist/es/geometry/rect.d.ts.map +1 -1
- package/dist/es/geometry/rect.js +1 -18
- package/dist/es/geometry/segment.d.ts +5 -1
- package/dist/es/geometry/segment.d.ts.map +1 -1
- package/dist/es/index.d.ts +10 -6
- package/dist/es/index.d.ts.map +1 -1
- package/dist/es/index.js +4 -2
- package/dist/es/ir/font.d.ts +21 -0
- package/dist/es/ir/font.d.ts.map +1 -0
- package/dist/es/ir/font.js +15 -0
- package/dist/es/ir/index.d.ts +2 -0
- package/dist/es/ir/index.d.ts.map +1 -1
- package/dist/es/ir/node.d.ts +28 -139
- package/dist/es/ir/node.d.ts.map +1 -1
- package/dist/es/ir/node.js +6 -30
- package/dist/es/ir/path/arrow.d.ts +12 -12
- package/dist/es/ir/path/path.d.ts +16 -16
- package/dist/es/ir/path/path.js +4 -4
- package/dist/es/ir/path/step.d.ts +1 -1
- package/dist/es/ir/path/step.d.ts.map +1 -1
- package/dist/es/ir/path/step.js +8 -8
- package/dist/es/ir/position/offset-position.js +1 -1
- package/dist/es/ir/position/polar-position.d.ts.map +1 -1
- package/dist/es/ir/position/polar-position.js +2 -2
- package/dist/es/ir/position/position.d.ts.map +1 -1
- package/dist/es/ir/position/position.js +1 -1
- package/dist/es/ir/scene.d.ts +112 -112
- package/dist/es/ir/text.d.ts +96 -0
- package/dist/es/ir/text.d.ts.map +1 -0
- package/dist/es/ir/text.js +20 -0
- package/dist/es/parsers/parseTargetSugar.d.ts +4 -0
- package/dist/es/parsers/parseTargetSugar.d.ts.map +1 -1
- package/dist/es/parsers/parseTargetSugar.js +3 -2
- package/dist/es/primitive/ellipse.d.ts +2 -2
- package/dist/es/primitive/group.d.ts +23 -7
- package/dist/es/primitive/group.d.ts.map +1 -1
- package/dist/es/primitive/path.d.ts +51 -11
- package/dist/es/primitive/path.d.ts.map +1 -1
- package/dist/es/primitive/rect.d.ts +2 -2
- package/dist/es/primitive/rect.d.ts.map +1 -1
- package/dist/es/primitive/text.d.ts +10 -3
- package/dist/es/primitive/text.d.ts.map +1 -1
- package/dist/es/primitive/view-box.d.ts +1 -1
- package/dist/es/primitive/view-box.d.ts.map +1 -1
- package/dist/es/types.d.ts +8 -0
- package/dist/es/types.d.ts.map +1 -1
- package/dist/lib/compile/compile.cjs +40 -15
- package/dist/lib/compile/compile.d.ts +17 -0
- package/dist/lib/compile/compile.d.ts.map +1 -1
- package/dist/lib/compile/index.d.ts +1 -1
- package/dist/lib/compile/index.d.ts.map +1 -1
- package/dist/lib/compile/node.cjs +1 -1
- package/dist/lib/compile/node.d.ts +3 -3
- package/dist/lib/compile/node.d.ts.map +1 -1
- package/dist/lib/compile/path/anchor.cjs +58 -0
- package/dist/lib/compile/path/anchor.d.ts +19 -0
- package/dist/lib/compile/path/anchor.d.ts.map +1 -0
- package/dist/lib/compile/path/index.cjs +308 -0
- package/dist/lib/compile/{path.d.ts → path/index.d.ts} +18 -7
- package/dist/lib/compile/path/index.d.ts.map +1 -0
- package/dist/lib/compile/path/label.cjs +103 -0
- package/dist/lib/compile/path/label.d.ts +18 -0
- package/dist/lib/compile/path/label.d.ts.map +1 -0
- package/dist/lib/compile/path/relative.cjs +48 -0
- package/dist/lib/compile/path/relative.d.ts +8 -0
- package/dist/lib/compile/path/relative.d.ts.map +1 -0
- package/dist/lib/compile/path/shrink.cjs +138 -0
- package/dist/lib/compile/path/shrink.d.ts +24 -0
- package/dist/lib/compile/path/shrink.d.ts.map +1 -0
- package/dist/lib/compile/path/split.cjs +46 -0
- package/dist/lib/compile/path/split.d.ts +15 -0
- package/dist/lib/compile/path/split.d.ts.map +1 -0
- package/dist/lib/compile/text-metrics.cjs +11 -5
- package/dist/lib/compile/text-metrics.d.ts +4 -1
- package/dist/lib/compile/text-metrics.d.ts.map +1 -1
- package/dist/lib/geometry/_transform.cjs +28 -0
- package/dist/lib/geometry/_transform.d.ts +21 -0
- package/dist/lib/geometry/_transform.d.ts.map +1 -0
- package/dist/lib/geometry/bend.cjs +1 -1
- package/dist/lib/geometry/bend.d.ts +1 -1
- package/dist/lib/geometry/circle.cjs +5 -20
- package/dist/lib/geometry/circle.d.ts +2 -3
- package/dist/lib/geometry/circle.d.ts.map +1 -1
- package/dist/lib/geometry/diamond.cjs +5 -20
- package/dist/lib/geometry/diamond.d.ts +2 -3
- package/dist/lib/geometry/diamond.d.ts.map +1 -1
- package/dist/lib/geometry/ellipse.cjs +5 -20
- package/dist/lib/geometry/ellipse.d.ts +2 -3
- package/dist/lib/geometry/ellipse.d.ts.map +1 -1
- package/dist/lib/geometry/polar.cjs +2 -6
- package/dist/lib/geometry/polar.d.ts +2 -2
- package/dist/lib/geometry/polar.d.ts.map +1 -1
- package/dist/lib/geometry/rect.cjs +5 -22
- package/dist/lib/geometry/rect.d.ts.map +1 -1
- package/dist/lib/geometry/segment.d.ts +5 -1
- package/dist/lib/geometry/segment.d.ts.map +1 -1
- package/dist/lib/index.cjs +5 -3
- package/dist/lib/index.d.ts +10 -6
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/ir/font.cjs +15 -0
- package/dist/lib/ir/font.d.ts +21 -0
- package/dist/lib/ir/font.d.ts.map +1 -0
- package/dist/lib/ir/index.d.ts +2 -0
- package/dist/lib/ir/index.d.ts.map +1 -1
- package/dist/lib/ir/node.cjs +7 -34
- package/dist/lib/ir/node.d.ts +28 -139
- package/dist/lib/ir/node.d.ts.map +1 -1
- package/dist/lib/ir/path/arrow.d.ts +12 -12
- package/dist/lib/ir/path/path.cjs +4 -4
- package/dist/lib/ir/path/path.d.ts +16 -16
- package/dist/lib/ir/path/step.cjs +8 -8
- package/dist/lib/ir/path/step.d.ts +1 -1
- package/dist/lib/ir/path/step.d.ts.map +1 -1
- package/dist/lib/ir/position/offset-position.cjs +1 -1
- package/dist/lib/ir/position/polar-position.cjs +2 -2
- package/dist/lib/ir/position/polar-position.d.ts.map +1 -1
- package/dist/lib/ir/position/position.cjs +1 -1
- package/dist/lib/ir/position/position.d.ts.map +1 -1
- package/dist/lib/ir/scene.d.ts +112 -112
- package/dist/lib/ir/text.cjs +21 -0
- package/dist/lib/ir/text.d.ts +96 -0
- package/dist/lib/ir/text.d.ts.map +1 -0
- package/dist/lib/parsers/parseTargetSugar.cjs +3 -2
- package/dist/lib/parsers/parseTargetSugar.d.ts +4 -0
- package/dist/lib/parsers/parseTargetSugar.d.ts.map +1 -1
- package/dist/lib/primitive/ellipse.d.ts +2 -2
- package/dist/lib/primitive/group.d.ts +23 -7
- package/dist/lib/primitive/group.d.ts.map +1 -1
- package/dist/lib/primitive/path.d.ts +51 -11
- package/dist/lib/primitive/path.d.ts.map +1 -1
- package/dist/lib/primitive/rect.d.ts +2 -2
- package/dist/lib/primitive/rect.d.ts.map +1 -1
- package/dist/lib/primitive/text.d.ts +10 -3
- package/dist/lib/primitive/text.d.ts.map +1 -1
- package/dist/lib/primitive/view-box.d.ts +1 -1
- package/dist/lib/primitive/view-box.d.ts.map +1 -1
- package/dist/lib/types.d.ts +8 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/package.json +13 -4
- package/dist/es/compile/path.d.ts.map +0 -1
- package/dist/es/compile/path.js +0 -636
- package/dist/lib/compile/path.cjs +0 -636
- package/dist/lib/compile/path.d.ts.map +0 -1
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
const require_arrow = require("../../ir/path/arrow.cjs");
|
|
2
|
+
const require_anchor = require("./anchor.cjs");
|
|
3
|
+
//#region src/compile/path/shrink.ts
|
|
4
|
+
/**
|
|
5
|
+
* 端点级 spec:顶层默认 ⊕ end-side override(逐字段 merge)
|
|
6
|
+
* @description 缺省字段继承顶层(不是"完全替换");空心 shape 上 fill 字段被丢(silent no-op)
|
|
7
|
+
*/
|
|
8
|
+
var resolveArrowEndSpec = (topLevel, endSide) => {
|
|
9
|
+
const baseShape = endSide?.shape ?? topLevel.shape ?? "normal";
|
|
10
|
+
const out = { shape: baseShape };
|
|
11
|
+
const scale = endSide?.scale ?? topLevel.scale;
|
|
12
|
+
if (scale !== void 0) out.scale = scale;
|
|
13
|
+
const length = endSide?.length ?? topLevel.length;
|
|
14
|
+
if (length !== void 0) out.length = length;
|
|
15
|
+
const width = endSide?.width ?? topLevel.width;
|
|
16
|
+
if (width !== void 0) out.width = width;
|
|
17
|
+
const color = endSide?.color ?? topLevel.color;
|
|
18
|
+
if (color !== void 0) out.color = color;
|
|
19
|
+
const opacity = endSide?.opacity ?? topLevel.opacity;
|
|
20
|
+
if (opacity !== void 0) out.opacity = opacity;
|
|
21
|
+
const lineWidth = endSide?.lineWidth ?? topLevel.lineWidth;
|
|
22
|
+
if (lineWidth !== void 0) out.lineWidth = lineWidth;
|
|
23
|
+
if (!require_arrow.HOLLOW_ARROW_SHAPES.has(baseShape)) {
|
|
24
|
+
const fill = endSide?.fill ?? topLevel.fill;
|
|
25
|
+
if (fill !== void 0) out.fill = fill;
|
|
26
|
+
}
|
|
27
|
+
return out;
|
|
28
|
+
};
|
|
29
|
+
/** IR path-level `arrow` + `arrowDetail` → PathPrim 起末视觉规格 */
|
|
30
|
+
var arrowMarkers = (arrow, detail) => {
|
|
31
|
+
if (!arrow || arrow === "none") return {};
|
|
32
|
+
const top = detail ?? {};
|
|
33
|
+
const startSpec = resolveArrowEndSpec(top, top.start);
|
|
34
|
+
const endSpec = resolveArrowEndSpec(top, top.end);
|
|
35
|
+
switch (arrow) {
|
|
36
|
+
case "->": return { arrowEnd: endSpec };
|
|
37
|
+
case "<-": return { arrowStart: startSpec };
|
|
38
|
+
case "<->": return {
|
|
39
|
+
arrowStart: startSpec,
|
|
40
|
+
arrowEnd: endSpec
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* 端点级 shrink(strokeWidth 倍):line 末端朝起点缩这么多,让 marker apex 落回原 target
|
|
46
|
+
* @description 不分实心/空心:所有 shape 都让 line 端点接在箭头尾部、apex 顶端仍贴原 target。低 opacity 下不会再透出 line。viewBox=10,shrink = (apex.x - refX) × length × scale / 10(strokeWidth 倍)。
|
|
47
|
+
*
|
|
48
|
+
* 几何对齐(必须与 react/render/arrowMarkers.tsx 中 renderInner 的 refX 一致):
|
|
49
|
+
* - `normal` / `diamond` / `circle`:apex 在 viewBox x=10、back 外缘 x=0 → refX=0,shrink = length × scale
|
|
50
|
+
* - `stealth`:apex x=10、V tip x=3(line 嵌进 V 凹口)→ refX=3,shrink = 0.7 × length × scale
|
|
51
|
+
* - `open` / `openDiamond`:apex x=9、back stroke 外缘 x = 1 - lineWidth/2 → refX = 1 - lineWidth/2,shrink = (8 + lineWidth/2) × length × scale / 10
|
|
52
|
+
* - `openCircle`:apex 外缘右 x ≈ 10、back 外缘左 x = 0.75 - lineWidth/2 → refX = 0.75 - lineWidth/2,shrink ≈ length × scale
|
|
53
|
+
*/
|
|
54
|
+
var computeShrink = (spec) => {
|
|
55
|
+
const length = (spec.length ?? 6) * (spec.scale ?? 1);
|
|
56
|
+
if (require_arrow.HOLLOW_ARROW_SHAPES.has(spec.shape)) {
|
|
57
|
+
if (spec.shape === "openCircle") return length;
|
|
58
|
+
return (8 + (spec.lineWidth ?? 1.5) / 2) * length / 10;
|
|
59
|
+
}
|
|
60
|
+
if (spec.shape === "stealth") return 7 * length / 10;
|
|
61
|
+
return length;
|
|
62
|
+
};
|
|
63
|
+
/** 取一个 PathCommand 末端 endpoint(move/line/quad/cubic → to;arc/ellipseArc → polar(end);close 无端点) */
|
|
64
|
+
var endpointOf = (cmd) => {
|
|
65
|
+
switch (cmd.kind) {
|
|
66
|
+
case "move":
|
|
67
|
+
case "line":
|
|
68
|
+
case "quad":
|
|
69
|
+
case "cubic": return [cmd.to[0], cmd.to[1]];
|
|
70
|
+
case "arc": {
|
|
71
|
+
const rad = cmd.endAngle * Math.PI / 180;
|
|
72
|
+
return [cmd.center[0] + Math.cos(rad) * cmd.radius, cmd.center[1] + Math.sin(rad) * cmd.radius];
|
|
73
|
+
}
|
|
74
|
+
case "ellipseArc": {
|
|
75
|
+
const rad = cmd.endAngle * Math.PI / 180;
|
|
76
|
+
return [cmd.center[0] + Math.cos(rad) * cmd.radiusX, cmd.center[1] + Math.sin(rad) * cmd.radiusY];
|
|
77
|
+
}
|
|
78
|
+
case "close": return null;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
/** 改写一个 PathCommand 的 endpoint(用于 shrink) */
|
|
82
|
+
var setEndpoint = (commands, idx, newPt, round) => {
|
|
83
|
+
const cmd = commands[idx];
|
|
84
|
+
if (cmd.kind === "close") return;
|
|
85
|
+
const rp = [round(newPt[0]), round(newPt[1])];
|
|
86
|
+
if (cmd.kind === "move" || cmd.kind === "line") commands[idx] = {
|
|
87
|
+
...cmd,
|
|
88
|
+
to: rp
|
|
89
|
+
};
|
|
90
|
+
else if (cmd.kind === "quad") commands[idx] = {
|
|
91
|
+
...cmd,
|
|
92
|
+
to: rp
|
|
93
|
+
};
|
|
94
|
+
else if (cmd.kind === "cubic") commands[idx] = {
|
|
95
|
+
...cmd,
|
|
96
|
+
to: rp
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* 按 shape + spec(length / scale / lineWidth)把首/末段端点向内缩短
|
|
101
|
+
* @description 让 line 端点接在 hollow arrow 尾部外缘、不贯穿 back outline;shrink=0 的实心 shape 跳过。in-place 改写 commands 数组
|
|
102
|
+
*/
|
|
103
|
+
var applyArrowShrinks = (commands, shrinkStart, shrinkEnd, strokeWidth, round) => {
|
|
104
|
+
if (shrinkStart > 0) {
|
|
105
|
+
const firstIdx = commands.findIndex((o) => o.kind === "move");
|
|
106
|
+
if (firstIdx >= 0) {
|
|
107
|
+
const cur = commands[firstIdx];
|
|
108
|
+
const nextIdx = commands.findIndex((o, idx) => idx > firstIdx && o.kind !== "close");
|
|
109
|
+
if (cur.kind === "move" && nextIdx >= 0) {
|
|
110
|
+
const nextPt = endpointOf(commands[nextIdx]);
|
|
111
|
+
if (nextPt) setEndpoint(commands, firstIdx, require_anchor.shiftToward([cur.to[0], cur.to[1]], nextPt, shrinkStart * strokeWidth), round);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (shrinkEnd > 0) {
|
|
116
|
+
let lastIdx = -1;
|
|
117
|
+
for (let i = commands.length - 1; i >= 0; i--) if (commands[i].kind !== "close") {
|
|
118
|
+
lastIdx = i;
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
if (lastIdx > 0) {
|
|
122
|
+
let prevIdx = lastIdx - 1;
|
|
123
|
+
while (prevIdx >= 0 && commands[prevIdx].kind === "close") prevIdx--;
|
|
124
|
+
if (prevIdx >= 0) {
|
|
125
|
+
const curPt = endpointOf(commands[lastIdx]);
|
|
126
|
+
const prevPt = endpointOf(commands[prevIdx]);
|
|
127
|
+
if (curPt && prevPt) {
|
|
128
|
+
const shifted = require_anchor.shiftToward(curPt, prevPt, shrinkEnd * strokeWidth);
|
|
129
|
+
setEndpoint(commands, lastIdx, shifted, round);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
//#endregion
|
|
136
|
+
exports.applyArrowShrinks = applyArrowShrinks;
|
|
137
|
+
exports.arrowMarkers = arrowMarkers;
|
|
138
|
+
exports.computeShrink = computeShrink;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { IRArrowDetail } from '../../ir';
|
|
2
|
+
import { ArrowEndSpec, PathCommand } from '../../primitive';
|
|
3
|
+
/** IR path-level `arrow` + `arrowDetail` → PathPrim 起末视觉规格 */
|
|
4
|
+
export declare const arrowMarkers: (arrow: "none" | "->" | "<-" | "<->" | undefined, detail: IRArrowDetail | undefined) => {
|
|
5
|
+
arrowStart?: ArrowEndSpec;
|
|
6
|
+
arrowEnd?: ArrowEndSpec;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* 端点级 shrink(strokeWidth 倍):line 末端朝起点缩这么多,让 marker apex 落回原 target
|
|
10
|
+
* @description 不分实心/空心:所有 shape 都让 line 端点接在箭头尾部、apex 顶端仍贴原 target。低 opacity 下不会再透出 line。viewBox=10,shrink = (apex.x - refX) × length × scale / 10(strokeWidth 倍)。
|
|
11
|
+
*
|
|
12
|
+
* 几何对齐(必须与 react/render/arrowMarkers.tsx 中 renderInner 的 refX 一致):
|
|
13
|
+
* - `normal` / `diamond` / `circle`:apex 在 viewBox x=10、back 外缘 x=0 → refX=0,shrink = length × scale
|
|
14
|
+
* - `stealth`:apex x=10、V tip x=3(line 嵌进 V 凹口)→ refX=3,shrink = 0.7 × length × scale
|
|
15
|
+
* - `open` / `openDiamond`:apex x=9、back stroke 外缘 x = 1 - lineWidth/2 → refX = 1 - lineWidth/2,shrink = (8 + lineWidth/2) × length × scale / 10
|
|
16
|
+
* - `openCircle`:apex 外缘右 x ≈ 10、back 外缘左 x = 0.75 - lineWidth/2 → refX = 0.75 - lineWidth/2,shrink ≈ length × scale
|
|
17
|
+
*/
|
|
18
|
+
export declare const computeShrink: (spec: ArrowEndSpec) => number;
|
|
19
|
+
/**
|
|
20
|
+
* 按 shape + spec(length / scale / lineWidth)把首/末段端点向内缩短
|
|
21
|
+
* @description 让 line 端点接在 hollow arrow 尾部外缘、不贯穿 back outline;shrink=0 的实心 shape 跳过。in-place 改写 commands 数组
|
|
22
|
+
*/
|
|
23
|
+
export declare const applyArrowShrinks: (commands: Array<PathCommand>, shrinkStart: number, shrinkEnd: number, strokeWidth: number, round: (n: number) => number) => void;
|
|
24
|
+
//# sourceMappingURL=shrink.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shrink.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/shrink.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAgC,MAAM,UAAU,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAkCjE,8DAA8D;AAC9D,eAAO,MAAM,YAAY,GACvB,OAAO,MAAM,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,SAAS,EAC/C,QAAQ,aAAa,GAAG,SAAS,KAChC;IAAE,UAAU,CAAC,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,EAAE,YAAY,CAAA;CAatD,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,GAAI,MAAM,YAAY,KAAG,MAWlD,CAAC;AAiDF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,UAAU,KAAK,CAAC,WAAW,CAAC,EAC5B,aAAa,MAAM,EACnB,WAAW,MAAM,EACjB,aAAa,MAAM,EACnB,OAAO,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,KAC3B,IA4CF,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
//#region src/compile/path/split.ts
|
|
2
|
+
/**
|
|
3
|
+
* 多 sub-path + 有箭头:按 sub-path split 成多个 PathPrim,仅首段挂 arrowStart / 末段挂 arrowEnd,包进 GroupPrim
|
|
4
|
+
* @description SVG marker 按每个 sub-path 单独贴会在中间节点视觉错乱,故仅首末段挂;单 sub-path 或无箭头直接产一个 PathPrim
|
|
5
|
+
*/
|
|
6
|
+
var splitSubPathsForMarkers = (commands, baseProps, markers) => {
|
|
7
|
+
const hasArrows = !!markers.arrowStart || !!markers.arrowEnd;
|
|
8
|
+
const subPathStarts = [];
|
|
9
|
+
commands.forEach((cmd, idx) => {
|
|
10
|
+
if (cmd.kind === "move") subPathStarts.push(idx);
|
|
11
|
+
});
|
|
12
|
+
if (!hasArrows || subPathStarts.length <= 1) return {
|
|
13
|
+
primitive: {
|
|
14
|
+
type: "path",
|
|
15
|
+
commands,
|
|
16
|
+
...baseProps,
|
|
17
|
+
...markers
|
|
18
|
+
},
|
|
19
|
+
isGrouped: false
|
|
20
|
+
};
|
|
21
|
+
const subPathSlices = [];
|
|
22
|
+
for (let s = 0; s < subPathStarts.length; s++) {
|
|
23
|
+
const start = subPathStarts[s];
|
|
24
|
+
const end = s + 1 < subPathStarts.length ? subPathStarts[s + 1] : commands.length;
|
|
25
|
+
subPathSlices.push(commands.slice(start, end));
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
primitive: {
|
|
29
|
+
type: "group",
|
|
30
|
+
children: subPathSlices.map((sub, i) => {
|
|
31
|
+
const isFirst = i === 0;
|
|
32
|
+
const isLast = i === subPathSlices.length - 1;
|
|
33
|
+
return {
|
|
34
|
+
type: "path",
|
|
35
|
+
commands: sub,
|
|
36
|
+
...baseProps,
|
|
37
|
+
...isFirst && markers.arrowStart ? { arrowStart: markers.arrowStart } : {},
|
|
38
|
+
...isLast && markers.arrowEnd ? { arrowEnd: markers.arrowEnd } : {}
|
|
39
|
+
};
|
|
40
|
+
})
|
|
41
|
+
},
|
|
42
|
+
isGrouped: true
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
//#endregion
|
|
46
|
+
exports.splitSubPathsForMarkers = splitSubPathsForMarkers;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ArrowEndSpec, PathCommand, PathPrim, ScenePrimitive } from '../../primitive';
|
|
2
|
+
/** baseProps:除 commands/markers 外 PathPrim 公共属性集合(多 sub-path 复用) */
|
|
3
|
+
export type PathBaseProps = Omit<PathPrim, 'type' | 'commands' | 'arrowStart' | 'arrowEnd'>;
|
|
4
|
+
/**
|
|
5
|
+
* 多 sub-path + 有箭头:按 sub-path split 成多个 PathPrim,仅首段挂 arrowStart / 末段挂 arrowEnd,包进 GroupPrim
|
|
6
|
+
* @description SVG marker 按每个 sub-path 单独贴会在中间节点视觉错乱,故仅首末段挂;单 sub-path 或无箭头直接产一个 PathPrim
|
|
7
|
+
*/
|
|
8
|
+
export declare const splitSubPathsForMarkers: (commands: Array<PathCommand>, baseProps: PathBaseProps, markers: {
|
|
9
|
+
arrowStart?: ArrowEndSpec;
|
|
10
|
+
arrowEnd?: ArrowEndSpec;
|
|
11
|
+
}) => {
|
|
12
|
+
primitive: ScenePrimitive;
|
|
13
|
+
isGrouped: boolean;
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=split.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"split.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/split.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE3F,oEAAoE;AACpE,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,GAAG,YAAY,GAAG,UAAU,CAAC,CAAC;AAE5F;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GAClC,UAAU,KAAK,CAAC,WAAW,CAAC,EAC5B,WAAW,aAAa,EACxB,SAAS;IAAE,UAAU,CAAC,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,EAAE,YAAY,CAAA;CAAE,KAC9D;IAAE,SAAS,EAAE,cAAc,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CA4CjD,CAAC"}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
//#region src/compile/text-metrics.ts
|
|
2
|
-
/**
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
/**
|
|
3
|
+
* 默认 fallback 度量:基于平均字宽估算,不准但保证可运行
|
|
4
|
+
* @description size=0 → 退化返回 (0, 0)(与 text='' 一致);负 size 或 NaN size → throw(非法输入早 fail,避免 NaN 噪音传播到 Scene)
|
|
5
|
+
*/
|
|
6
|
+
var fallbackMeasurer = (text, font) => {
|
|
7
|
+
if (Number.isNaN(font.size) || font.size < 0) throw new Error(`fallbackMeasurer: invalid font.size '${font.size}'; must be a non-negative finite number`);
|
|
8
|
+
return {
|
|
9
|
+
width: text.length * font.size * .55,
|
|
10
|
+
height: font.size * 1.2
|
|
11
|
+
};
|
|
12
|
+
};
|
|
7
13
|
//#endregion
|
|
8
14
|
exports.fallbackMeasurer = fallbackMeasurer;
|
|
@@ -25,6 +25,9 @@ export type TextMetrics = {
|
|
|
25
25
|
* @description @retikz/react: canvas measureText;@retikz/ssr: opentype.js/fontkit;@retikz/canvas: ctx.measureText
|
|
26
26
|
*/
|
|
27
27
|
export type TextMeasurer = (text: string, font: FontSpec) => TextMetrics;
|
|
28
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* 默认 fallback 度量:基于平均字宽估算,不准但保证可运行
|
|
30
|
+
* @description size=0 → 退化返回 (0, 0)(与 text='' 一致);负 size 或 NaN size → throw(非法输入早 fail,避免 NaN 噪音传播到 Scene)
|
|
31
|
+
*/
|
|
29
32
|
export declare const fallbackMeasurer: TextMeasurer;
|
|
30
33
|
//# sourceMappingURL=text-metrics.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text-metrics.d.ts","sourceRoot":"","sources":["../../../src/compile/text-metrics.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,MAAM,MAAM,QAAQ,GAAG;IACrB,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,mCAAmC;IACnC,KAAK,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;CACzC,CAAC;AAEF,uCAAuC;AACvC,MAAM,MAAM,WAAW,GAAG;IACxB,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,KAAK,WAAW,CAAC;AAEzE
|
|
1
|
+
{"version":3,"file":"text-metrics.d.ts","sourceRoot":"","sources":["../../../src/compile/text-metrics.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,MAAM,MAAM,QAAQ,GAAG;IACrB,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,mCAAmC;IACnC,KAAK,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;CACzC,CAAC;AAEF,uCAAuC;AACvC,MAAM,MAAM,WAAW,GAAG;IACxB,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iCAAiC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,KAAK,WAAW,CAAC;AAEzE;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,YAU9B,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/geometry/_transform.ts
|
|
2
|
+
/**
|
|
3
|
+
* 本地坐标(以中心为原点)→ 世界坐标
|
|
4
|
+
* @description rotate=0 / 缺省时退化为平移;非零时按右手系绕中心旋转后再平移
|
|
5
|
+
*/
|
|
6
|
+
var localToWorld = (s, local) => {
|
|
7
|
+
const angle = s.rotate ?? 0;
|
|
8
|
+
if (angle === 0) return [s.x + local[0], s.y + local[1]];
|
|
9
|
+
const cos = Math.cos(angle);
|
|
10
|
+
const sin = Math.sin(angle);
|
|
11
|
+
return [s.x + local[0] * cos - local[1] * sin, s.y + local[0] * sin + local[1] * cos];
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* 世界坐标 → 本地坐标(`localToWorld` 逆变换)
|
|
15
|
+
* @description 先反平移到中心、再反旋转回本地基;旋转矩阵转置即逆
|
|
16
|
+
*/
|
|
17
|
+
var worldToLocal = (s, world) => {
|
|
18
|
+
const tx = world[0] - s.x;
|
|
19
|
+
const ty = world[1] - s.y;
|
|
20
|
+
const angle = s.rotate ?? 0;
|
|
21
|
+
if (angle === 0) return [tx, ty];
|
|
22
|
+
const cos = Math.cos(angle);
|
|
23
|
+
const sin = Math.sin(angle);
|
|
24
|
+
return [tx * cos + ty * sin, -tx * sin + ty * cos];
|
|
25
|
+
};
|
|
26
|
+
//#endregion
|
|
27
|
+
exports.localToWorld = localToWorld;
|
|
28
|
+
exports.worldToLocal = worldToLocal;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Position } from './point';
|
|
2
|
+
/** 任何"中心 + 可选旋转"形状的几何契约(rect / circle / ellipse / diamond 共用) */
|
|
3
|
+
export type CenteredShape = {
|
|
4
|
+
/** 中心横坐标 */
|
|
5
|
+
x: number;
|
|
6
|
+
/** 中心纵坐标 */
|
|
7
|
+
y: number;
|
|
8
|
+
/** 绕中心旋转弧度(可选,0 / 缺省 = 不旋转) */
|
|
9
|
+
rotate?: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* 本地坐标(以中心为原点)→ 世界坐标
|
|
13
|
+
* @description rotate=0 / 缺省时退化为平移;非零时按右手系绕中心旋转后再平移
|
|
14
|
+
*/
|
|
15
|
+
export declare const localToWorld: (s: CenteredShape, local: Position) => Position;
|
|
16
|
+
/**
|
|
17
|
+
* 世界坐标 → 本地坐标(`localToWorld` 逆变换)
|
|
18
|
+
* @description 先反平移到中心、再反旋转回本地基;旋转矩阵转置即逆
|
|
19
|
+
*/
|
|
20
|
+
export declare const worldToLocal: (s: CenteredShape, world: Position) => Position;
|
|
21
|
+
//# sourceMappingURL=_transform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_transform.d.ts","sourceRoot":"","sources":["../../../src/geometry/_transform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,iEAAiE;AACjE,MAAM,MAAM,aAAa,GAAG;IAC1B,YAAY;IACZ,CAAC,EAAE,MAAM,CAAC;IACV,YAAY;IACZ,CAAC,EAAE,MAAM,CAAC;IACV,+BAA+B;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,GAAG,aAAa,EAAE,OAAO,QAAQ,KAAG,QAShE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,GAAG,aAAa,EAAE,OAAO,QAAQ,KAAG,QAQhE,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
//#region src/geometry/bend.ts
|
|
2
2
|
/**
|
|
3
3
|
* cubic Bezier 拟合 from→to 的弧形 bend
|
|
4
|
-
* @description apex offset = chord × tan(bendAngle/2);控制点取 chord 1/3 与 2/3 处沿法向偏移,让 cubic 在 t=0.5 穿过 apex 故 ctlOffset = 4/3 × apexOffset
|
|
4
|
+
* @description apex offset = chord × tan(bendAngle/2);控制点取 chord 1/3 与 2/3 处沿法向偏移,让 cubic 在 t=0.5 穿过 apex 故 ctlOffset = 4/3 × apexOffset。法向(screen y-down):visual-left=(dy,-dx)/|chord|,visual-right=(-dy,dx)/|chord|。chord=0 时两控制点都返回 from
|
|
5
5
|
*/
|
|
6
6
|
var bendControlPoints = (from, to, direction, bendAngle) => {
|
|
7
7
|
const dx = to[0] - from[0];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Position } from './point';
|
|
2
2
|
/**
|
|
3
3
|
* cubic Bezier 拟合 from→to 的弧形 bend
|
|
4
|
-
* @description apex offset = chord × tan(bendAngle/2);控制点取 chord 1/3 与 2/3 处沿法向偏移,让 cubic 在 t=0.5 穿过 apex 故 ctlOffset = 4/3 × apexOffset
|
|
4
|
+
* @description apex offset = chord × tan(bendAngle/2);控制点取 chord 1/3 与 2/3 处沿法向偏移,让 cubic 在 t=0.5 穿过 apex 故 ctlOffset = 4/3 × apexOffset。法向(screen y-down):visual-left=(dy,-dx)/|chord|,visual-right=(-dy,dx)/|chord|。chord=0 时两控制点都返回 from
|
|
5
5
|
*/
|
|
6
6
|
export declare const bendControlPoints: (from: Position, to: Position, direction: "left" | "right", bendAngle: number) => [Position, Position];
|
|
7
7
|
//# sourceMappingURL=bend.d.ts.map
|
|
@@ -1,28 +1,13 @@
|
|
|
1
|
+
const require__transform = require("./_transform.cjs");
|
|
1
2
|
//#region src/geometry/circle.ts
|
|
2
3
|
var SQRT_HALF = Math.SQRT1_2;
|
|
3
|
-
var localToWorld = (c, local) => {
|
|
4
|
-
const angle = c.rotate ?? 0;
|
|
5
|
-
if (angle === 0) return [c.x + local[0], c.y + local[1]];
|
|
6
|
-
const cos = Math.cos(angle);
|
|
7
|
-
const sin = Math.sin(angle);
|
|
8
|
-
return [c.x + local[0] * cos - local[1] * sin, c.y + local[0] * sin + local[1] * cos];
|
|
9
|
-
};
|
|
10
|
-
var worldToLocal = (c, world) => {
|
|
11
|
-
const tx = world[0] - c.x;
|
|
12
|
-
const ty = world[1] - c.y;
|
|
13
|
-
const angle = c.rotate ?? 0;
|
|
14
|
-
if (angle === 0) return [tx, ty];
|
|
15
|
-
const cos = Math.cos(angle);
|
|
16
|
-
const sin = Math.sin(angle);
|
|
17
|
-
return [tx * cos + ty * sin, -tx * sin + ty * cos];
|
|
18
|
-
};
|
|
19
4
|
/** 圆形相关基础工具 */
|
|
20
5
|
var circle = {
|
|
21
6
|
/** 圆心 */
|
|
22
7
|
center: (c) => [c.x, c.y],
|
|
23
8
|
/** 判断点是否在圆内(含边界) */
|
|
24
9
|
contains: (c, p) => {
|
|
25
|
-
const [lx, ly] = worldToLocal(c, p);
|
|
10
|
+
const [lx, ly] = require__transform.worldToLocal(c, p);
|
|
26
11
|
return lx * lx + ly * ly <= c.radius * c.radius;
|
|
27
12
|
},
|
|
28
13
|
/** 9 个标准 anchor 之一的世界坐标 */
|
|
@@ -61,15 +46,15 @@ var circle = {
|
|
|
61
46
|
ly = r * SQRT_HALF;
|
|
62
47
|
break;
|
|
63
48
|
}
|
|
64
|
-
return localToWorld(c, [lx, ly]);
|
|
49
|
+
return require__transform.localToWorld(c, [lx, ly]);
|
|
65
50
|
},
|
|
66
51
|
/** 从圆心向 toward 方向射线与圆周交点(Path 端点贴 Node 边界用) */
|
|
67
52
|
boundaryPoint: (c, toward) => {
|
|
68
|
-
const [lx, ly] = worldToLocal(c, toward);
|
|
53
|
+
const [lx, ly] = require__transform.worldToLocal(c, toward);
|
|
69
54
|
const len = Math.sqrt(lx * lx + ly * ly);
|
|
70
55
|
if (len === 0) return [c.x, c.y];
|
|
71
56
|
const t = c.radius / len;
|
|
72
|
-
return localToWorld(c, [lx * t, ly * t]);
|
|
57
|
+
return require__transform.localToWorld(c, [lx * t, ly * t]);
|
|
73
58
|
}
|
|
74
59
|
};
|
|
75
60
|
//#endregion
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Position } from './point';
|
|
2
|
+
import { RectAnchor } from './rect';
|
|
2
3
|
/** 圆形:几何中心 + 半径,预留旋转字段保持与 Rect 同形 API */
|
|
3
4
|
export type Circle = {
|
|
4
5
|
x: number;
|
|
@@ -8,8 +9,6 @@ export type Circle = {
|
|
|
8
9
|
/** 绕中心旋转弧度(圆视觉不变,与 Rect 同形保留) */
|
|
9
10
|
rotate?: number;
|
|
10
11
|
};
|
|
11
|
-
/** 圆形 9 个标准 anchor(与 RECT_ANCHORS 同名同义,圆周每 45° 等距分布) */
|
|
12
|
-
export type CircleAnchor = 'center' | 'north' | 'south' | 'east' | 'west' | 'north-east' | 'north-west' | 'south-east' | 'south-west';
|
|
13
12
|
/** 圆形相关基础工具 */
|
|
14
13
|
export declare const circle: {
|
|
15
14
|
/** 圆心 */
|
|
@@ -17,7 +16,7 @@ export declare const circle: {
|
|
|
17
16
|
/** 判断点是否在圆内(含边界) */
|
|
18
17
|
contains: (c: Circle, p: Position) => boolean;
|
|
19
18
|
/** 9 个标准 anchor 之一的世界坐标 */
|
|
20
|
-
anchor: (c: Circle, name:
|
|
19
|
+
anchor: (c: Circle, name: RectAnchor) => Position;
|
|
21
20
|
/** 从圆心向 toward 方向射线与圆周交点(Path 端点贴 Node 边界用) */
|
|
22
21
|
boundaryPoint: (c: Circle, toward: Position) => Position;
|
|
23
22
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"circle.d.ts","sourceRoot":"","sources":["../../../src/geometry/circle.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"circle.d.ts","sourceRoot":"","sources":["../../../src/geometry/circle.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEzC,yCAAyC;AACzC,MAAM,MAAM,MAAM,GAAG;IACnB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,SAAS;IACT,MAAM,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAIF,eAAe;AACf,eAAO,MAAM,MAAM;IACjB,SAAS;gBACG,MAAM,KAAG,QAAQ;IAC7B,oBAAoB;kBACN,MAAM,KAAK,QAAQ,KAAG,OAAO;IAI3C,2BAA2B;gBACf,MAAM,QAAQ,UAAU,KAAG,QAAQ;IAsC/C,+CAA+C;uBAC5B,MAAM,UAAU,QAAQ,KAAG,QAAQ;CAOvD,CAAC"}
|
|
@@ -1,27 +1,12 @@
|
|
|
1
|
+
const require__transform = require("./_transform.cjs");
|
|
1
2
|
//#region src/geometry/diamond.ts
|
|
2
|
-
var localToWorld = (d, local) => {
|
|
3
|
-
const angle = d.rotate ?? 0;
|
|
4
|
-
if (angle === 0) return [d.x + local[0], d.y + local[1]];
|
|
5
|
-
const cos = Math.cos(angle);
|
|
6
|
-
const sin = Math.sin(angle);
|
|
7
|
-
return [d.x + local[0] * cos - local[1] * sin, d.y + local[0] * sin + local[1] * cos];
|
|
8
|
-
};
|
|
9
|
-
var worldToLocal = (d, world) => {
|
|
10
|
-
const tx = world[0] - d.x;
|
|
11
|
-
const ty = world[1] - d.y;
|
|
12
|
-
const angle = d.rotate ?? 0;
|
|
13
|
-
if (angle === 0) return [tx, ty];
|
|
14
|
-
const cos = Math.cos(angle);
|
|
15
|
-
const sin = Math.sin(angle);
|
|
16
|
-
return [tx * cos + ty * sin, -tx * sin + ty * cos];
|
|
17
|
-
};
|
|
18
3
|
/** 菱形相关基础工具 */
|
|
19
4
|
var diamond = {
|
|
20
5
|
/** 中心 */
|
|
21
6
|
center: (d) => [d.x, d.y],
|
|
22
7
|
/** 点是否在菱形内(含边界,含旋转);方程 |x|/halfA + |y|/halfB ≤ 1 */
|
|
23
8
|
contains: (d, p) => {
|
|
24
|
-
const [lx, ly] = worldToLocal(d, p);
|
|
9
|
+
const [lx, ly] = require__transform.worldToLocal(d, p);
|
|
25
10
|
return Math.abs(lx) / d.halfA + Math.abs(ly) / d.halfB <= 1.000000001;
|
|
26
11
|
},
|
|
27
12
|
/** 9 个 anchor:N/S/E/W=顶点,NE/NW/SE/SW=边中点,center=中心 */
|
|
@@ -59,18 +44,18 @@ var diamond = {
|
|
|
59
44
|
ly = d.halfB / 2;
|
|
60
45
|
break;
|
|
61
46
|
}
|
|
62
|
-
return localToWorld(d, [lx, ly]);
|
|
47
|
+
return require__transform.localToWorld(d, [lx, ly]);
|
|
63
48
|
},
|
|
64
49
|
/**
|
|
65
50
|
* 从中心向 toward 方向射线与菱形 4 边的交点
|
|
66
51
|
* @description 菱形方程 |x|/halfA + |y|/halfB = 1;沿方向 (lx,ly) 缩放 t 倍命中:t = 1 / (|lx|/halfA + |ly|/halfB)
|
|
67
52
|
*/
|
|
68
53
|
boundaryPoint: (d, toward) => {
|
|
69
|
-
const [lx, ly] = worldToLocal(d, toward);
|
|
54
|
+
const [lx, ly] = require__transform.worldToLocal(d, toward);
|
|
70
55
|
const denom = Math.abs(lx) / d.halfA + Math.abs(ly) / d.halfB;
|
|
71
56
|
if (denom === 0) return [d.x, d.y];
|
|
72
57
|
const t = 1 / denom;
|
|
73
|
-
return localToWorld(d, [lx * t, ly * t]);
|
|
58
|
+
return require__transform.localToWorld(d, [lx * t, ly * t]);
|
|
74
59
|
}
|
|
75
60
|
};
|
|
76
61
|
//#endregion
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Position } from './point';
|
|
2
|
+
import { RectAnchor } from './rect';
|
|
2
3
|
/** 菱形:中心 + halfA/halfB 半轴长 + 可选旋转;顶点在 (±halfA,0) 与 (0,±halfB) */
|
|
3
4
|
export type Diamond = {
|
|
4
5
|
x: number;
|
|
@@ -10,8 +11,6 @@ export type Diamond = {
|
|
|
10
11
|
/** 绕中心旋转弧度 */
|
|
11
12
|
rotate?: number;
|
|
12
13
|
};
|
|
13
|
-
/** 菱形 9 个标准 anchor(4 顶点 + 4 边中点 + 中心) */
|
|
14
|
-
export type DiamondAnchor = 'center' | 'north' | 'south' | 'east' | 'west' | 'north-east' | 'north-west' | 'south-east' | 'south-west';
|
|
15
14
|
/** 菱形相关基础工具 */
|
|
16
15
|
export declare const diamond: {
|
|
17
16
|
/** 中心 */
|
|
@@ -19,7 +18,7 @@ export declare const diamond: {
|
|
|
19
18
|
/** 点是否在菱形内(含边界,含旋转);方程 |x|/halfA + |y|/halfB ≤ 1 */
|
|
20
19
|
contains: (d: Diamond, p: Position) => boolean;
|
|
21
20
|
/** 9 个 anchor:N/S/E/W=顶点,NE/NW/SE/SW=边中点,center=中心 */
|
|
22
|
-
anchor: (d: Diamond, name:
|
|
21
|
+
anchor: (d: Diamond, name: RectAnchor) => Position;
|
|
23
22
|
/**
|
|
24
23
|
* 从中心向 toward 方向射线与菱形 4 边的交点
|
|
25
24
|
* @description 菱形方程 |x|/halfA + |y|/halfB = 1;沿方向 (lx,ly) 缩放 t 倍命中:t = 1 / (|lx|/halfA + |ly|/halfB)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diamond.d.ts","sourceRoot":"","sources":["../../../src/geometry/diamond.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"diamond.d.ts","sourceRoot":"","sources":["../../../src/geometry/diamond.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEzC,iEAAiE;AACjE,MAAM,MAAM,OAAO,GAAG;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,cAAc;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAe;AACf,eAAO,MAAM,OAAO;IAClB,SAAS;gBACG,OAAO,KAAG,QAAQ;IAC9B,oDAAoD;kBACtC,OAAO,KAAK,QAAQ,KAAG,OAAO;IAI5C,sDAAsD;gBAC1C,OAAO,QAAQ,UAAU,KAAG,QAAQ;IAqClD;;;OAGG;uBACkB,OAAO,UAAU,QAAQ,KAAG,QAAQ;CAOxD,CAAC"}
|
|
@@ -1,28 +1,13 @@
|
|
|
1
|
+
const require__transform = require("./_transform.cjs");
|
|
1
2
|
//#region src/geometry/ellipse.ts
|
|
2
3
|
var SQRT_HALF = Math.SQRT1_2;
|
|
3
|
-
var localToWorld = (e, local) => {
|
|
4
|
-
const angle = e.rotate ?? 0;
|
|
5
|
-
if (angle === 0) return [e.x + local[0], e.y + local[1]];
|
|
6
|
-
const cos = Math.cos(angle);
|
|
7
|
-
const sin = Math.sin(angle);
|
|
8
|
-
return [e.x + local[0] * cos - local[1] * sin, e.y + local[0] * sin + local[1] * cos];
|
|
9
|
-
};
|
|
10
|
-
var worldToLocal = (e, world) => {
|
|
11
|
-
const tx = world[0] - e.x;
|
|
12
|
-
const ty = world[1] - e.y;
|
|
13
|
-
const angle = e.rotate ?? 0;
|
|
14
|
-
if (angle === 0) return [tx, ty];
|
|
15
|
-
const cos = Math.cos(angle);
|
|
16
|
-
const sin = Math.sin(angle);
|
|
17
|
-
return [tx * cos + ty * sin, -tx * sin + ty * cos];
|
|
18
|
-
};
|
|
19
4
|
/** 椭圆相关基础工具 */
|
|
20
5
|
var ellipse = {
|
|
21
6
|
/** 中心 */
|
|
22
7
|
center: (e) => [e.x, e.y],
|
|
23
8
|
/** 判断点是否在椭圆内(含边界,考虑旋转) */
|
|
24
9
|
contains: (e, p) => {
|
|
25
|
-
const [lx, ly] = worldToLocal(e, p);
|
|
10
|
+
const [lx, ly] = require__transform.worldToLocal(e, p);
|
|
26
11
|
return lx * lx / (e.rx * e.rx) + ly * ly / (e.ry * e.ry) <= 1;
|
|
27
12
|
},
|
|
28
13
|
/**
|
|
@@ -63,19 +48,19 @@ var ellipse = {
|
|
|
63
48
|
ly = e.ry * SQRT_HALF;
|
|
64
49
|
break;
|
|
65
50
|
}
|
|
66
|
-
return localToWorld(e, [lx, ly]);
|
|
51
|
+
return require__transform.localToWorld(e, [lx, ly]);
|
|
67
52
|
},
|
|
68
53
|
/**
|
|
69
54
|
* 从中心向 toward 方向射线与椭圆交点
|
|
70
55
|
* @description 椭圆方程 (x/rx)² + (y/ry)² = 1;沿 (lx,ly) 缩放 t 倍命中 t = 1 / √((lx/rx)² + (ly/ry)²)
|
|
71
56
|
*/
|
|
72
57
|
boundaryPoint: (e, toward) => {
|
|
73
|
-
const [lx, ly] = worldToLocal(e, toward);
|
|
58
|
+
const [lx, ly] = require__transform.worldToLocal(e, toward);
|
|
74
59
|
if (lx === 0 && ly === 0) return [e.x, e.y];
|
|
75
60
|
const a = lx / e.rx;
|
|
76
61
|
const b = ly / e.ry;
|
|
77
62
|
const t = 1 / Math.sqrt(a * a + b * b);
|
|
78
|
-
return localToWorld(e, [lx * t, ly * t]);
|
|
63
|
+
return require__transform.localToWorld(e, [lx * t, ly * t]);
|
|
79
64
|
}
|
|
80
65
|
};
|
|
81
66
|
//#endregion
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Position } from './point';
|
|
2
|
+
import { RectAnchor } from './rect';
|
|
2
3
|
/** 椭圆:中心 + 半长轴 rx / 半短轴 ry + 可选旋转 */
|
|
3
4
|
export type Ellipse = {
|
|
4
5
|
x: number;
|
|
@@ -10,8 +11,6 @@ export type Ellipse = {
|
|
|
10
11
|
/** 绕中心旋转弧度 */
|
|
11
12
|
rotate?: number;
|
|
12
13
|
};
|
|
13
|
-
/** 椭圆 9 个标准 anchor(与 RECT_ANCHORS 同名同义) */
|
|
14
|
-
export type EllipseAnchor = 'center' | 'north' | 'south' | 'east' | 'west' | 'north-east' | 'north-west' | 'south-east' | 'south-west';
|
|
15
14
|
/** 椭圆相关基础工具 */
|
|
16
15
|
export declare const ellipse: {
|
|
17
16
|
/** 中心 */
|
|
@@ -22,7 +21,7 @@ export declare const ellipse: {
|
|
|
22
21
|
* 9 个 anchor 的世界坐标
|
|
23
22
|
* @description 对角(NE/NW/SE/SW)取参数曲线 t=π/4 处 (rx/√2, ry/√2),与 TikZ 椭圆 anchor 参数等分约定一致
|
|
24
23
|
*/
|
|
25
|
-
anchor: (e: Ellipse, name:
|
|
24
|
+
anchor: (e: Ellipse, name: RectAnchor) => Position;
|
|
26
25
|
/**
|
|
27
26
|
* 从中心向 toward 方向射线与椭圆交点
|
|
28
27
|
* @description 椭圆方程 (x/rx)² + (y/ry)² = 1;沿 (lx,ly) 缩放 t 倍命中 t = 1 / √((lx/rx)² + (ly/ry)²)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ellipse.d.ts","sourceRoot":"","sources":["../../../src/geometry/ellipse.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ellipse.d.ts","sourceRoot":"","sources":["../../../src/geometry/ellipse.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEzC,qCAAqC;AACrC,MAAM,MAAM,OAAO,GAAG;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,aAAa;IACb,EAAE,EAAE,MAAM,CAAC;IACX,aAAa;IACb,EAAE,EAAE,MAAM,CAAC;IACX,cAAc;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAIF,eAAe;AACf,eAAO,MAAM,OAAO;IAClB,SAAS;gBACG,OAAO,KAAG,QAAQ;IAC9B,0BAA0B;kBACZ,OAAO,KAAK,QAAQ,KAAG,OAAO;IAI9C;;;OAGG;gBACW,OAAO,QAAQ,UAAU,KAAG,QAAQ;IAqClD;;;OAGG;uBACkB,OAAO,UAAU,QAAQ,KAAG,QAAQ;CAQxD,CAAC"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const require_point = require("./point.cjs");
|
|
2
2
|
//#region src/geometry/polar.ts
|
|
3
3
|
var DEG_TO_RAD = Math.PI / 180;
|
|
4
|
-
var RAD_TO_DEG = 180 / Math.PI;
|
|
5
4
|
/** 极坐标 ↔ 笛卡尔转换工具集(polar 不参与几何计算,参与时先 toPosition) */
|
|
6
5
|
var polar = {
|
|
7
6
|
/**
|
|
@@ -17,11 +16,8 @@ var polar = {
|
|
|
17
16
|
const rad = p.angle * DEG_TO_RAD;
|
|
18
17
|
return [origin[0] + Math.cos(rad) * p.radius, origin[1] + Math.sin(rad) * p.radius];
|
|
19
18
|
},
|
|
20
|
-
/** 笛卡尔 → 极坐标(angle ∈ (-180,180],origin 默认 [0,0]) */
|
|
21
|
-
fromPosition: (p) => (
|
|
22
|
-
angle: Math.atan2(p[1], p[0]) * RAD_TO_DEG,
|
|
23
|
-
radius: Math.hypot(p[0], p[1])
|
|
24
|
-
}),
|
|
19
|
+
/** 笛卡尔 → 极坐标(point.toPolar 别名,angle ∈ (-180,180],origin 默认 [0,0]) */
|
|
20
|
+
fromPosition: (p) => require_point.point.toPolar(p),
|
|
25
21
|
/** 在原点附近按极坐标偏移,返回结果点的世界笛卡尔坐标 */
|
|
26
22
|
offsetFrom: (origin, offset) => {
|
|
27
23
|
const rad = offset.angle * DEG_TO_RAD;
|
|
@@ -6,7 +6,7 @@ import { Position } from './point';
|
|
|
6
6
|
export type PolarPosition = {
|
|
7
7
|
/** 极坐标原点:节点 id / 笛卡尔 / 嵌套极坐标;省略表示 [0,0] */
|
|
8
8
|
origin?: string | Position | PolarPosition;
|
|
9
|
-
/**
|
|
9
|
+
/** 角度(度数):从 +x 轴量起,90° 朝 +y(屏幕下方),与 ArcStep / Node label 角度约定一致 */
|
|
10
10
|
angle: number;
|
|
11
11
|
/** 半径(非负) */
|
|
12
12
|
radius: number;
|
|
@@ -18,7 +18,7 @@ export declare const polar: {
|
|
|
18
18
|
* @description origin 为字符串(节点 id)时抛错——字符串解析依赖 Scene 编译器 nodeIndex
|
|
19
19
|
*/
|
|
20
20
|
toPosition: (p: PolarPosition) => Position;
|
|
21
|
-
/** 笛卡尔 → 极坐标(angle ∈ (-180,180],origin 默认 [0,0]) */
|
|
21
|
+
/** 笛卡尔 → 极坐标(point.toPolar 别名,angle ∈ (-180,180],origin 默认 [0,0]) */
|
|
22
22
|
fromPosition: (p: Position) => PolarPosition;
|
|
23
23
|
/** 在原点附近按极坐标偏移,返回结果点的世界笛卡尔坐标 */
|
|
24
24
|
offsetFrom: (origin: Position, offset: {
|