@retikz/core 0.2.0-alpha.4 → 0.2.0-alpha.6
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/anchor-cache.d.ts +10 -0
- package/dist/es/compile/anchor-cache.d.ts.map +1 -1
- package/dist/es/compile/anchor-cache.js +25 -1
- package/dist/es/compile/index.d.ts +0 -1
- package/dist/es/compile/index.d.ts.map +1 -1
- package/dist/es/compile/path/anchor.d.ts.map +1 -1
- package/dist/es/compile/path/anchor.js +17 -18
- package/dist/es/compile/path/index.d.ts.map +1 -1
- package/dist/es/compile/path/index.js +98 -13
- package/dist/es/compile/path/relative.d.ts.map +1 -1
- package/dist/es/compile/path/relative.js +5 -1
- package/dist/es/geometry/_edge.d.ts +29 -0
- package/dist/es/geometry/_edge.d.ts.map +1 -0
- package/dist/es/geometry/_edge.js +35 -0
- package/dist/es/geometry/arc.d.ts +11 -0
- package/dist/es/geometry/arc.d.ts.map +1 -1
- package/dist/es/geometry/arc.js +27 -1
- package/dist/es/geometry/circle.d.ts +3 -0
- package/dist/es/geometry/circle.d.ts.map +1 -1
- package/dist/es/geometry/circle.js +7 -0
- package/dist/es/geometry/diamond.d.ts +3 -0
- package/dist/es/geometry/diamond.d.ts.map +1 -1
- package/dist/es/geometry/diamond.js +29 -0
- package/dist/es/geometry/ellipse.d.ts +3 -0
- package/dist/es/geometry/ellipse.d.ts.map +1 -1
- package/dist/es/geometry/ellipse.js +7 -0
- package/dist/es/geometry/rect.d.ts +26 -0
- package/dist/es/geometry/rect.d.ts.map +1 -1
- package/dist/es/geometry/rect.js +90 -1
- package/dist/es/geometry/segment.d.ts +2 -0
- package/dist/es/geometry/segment.d.ts.map +1 -1
- package/dist/es/geometry/segment.js +12 -1
- package/dist/es/index.d.ts +3 -3
- package/dist/es/index.d.ts.map +1 -1
- package/dist/es/index.js +6 -5
- package/dist/es/ir/coordinate.d.ts +2 -2
- package/dist/es/ir/node.d.ts +4 -4
- package/dist/es/ir/path/path.d.ts +828 -111
- package/dist/es/ir/path/path.d.ts.map +1 -1
- package/dist/es/ir/path/step.d.ts +1209 -168
- package/dist/es/ir/path/step.d.ts.map +1 -1
- package/dist/es/ir/path/step.js +36 -11
- package/dist/es/ir/path/target.d.ts +71 -1
- package/dist/es/ir/path/target.d.ts.map +1 -1
- package/dist/es/ir/path/target.js +24 -3
- package/dist/es/ir/scope.d.ts +1228 -190
- package/dist/es/ir/scope.d.ts.map +1 -1
- package/dist/es/parsers/index.d.ts +1 -0
- package/dist/es/parsers/index.d.ts.map +1 -1
- package/dist/es/parsers/parseNodeTarget.d.ts +4 -0
- package/dist/es/parsers/parseNodeTarget.d.ts.map +1 -0
- package/dist/es/parsers/parseNodeTarget.js +33 -0
- package/dist/es/parsers/parseTargetSugar.d.ts +4 -2
- package/dist/es/parsers/parseTargetSugar.d.ts.map +1 -1
- package/dist/es/parsers/parseTargetSugar.js +6 -3
- package/dist/es/parsers/parseWay.d.ts +1 -1
- package/dist/es/parsers/parseWay.d.ts.map +1 -1
- package/dist/es/shapes/circle.d.ts.map +1 -1
- package/dist/es/shapes/circle.js +1 -0
- package/dist/es/shapes/diamond.d.ts.map +1 -1
- package/dist/es/shapes/diamond.js +1 -0
- package/dist/es/shapes/ellipse.d.ts.map +1 -1
- package/dist/es/shapes/ellipse.js +1 -0
- package/dist/es/shapes/rectangle.d.ts.map +1 -1
- package/dist/es/shapes/rectangle.js +1 -0
- package/dist/es/shapes/types.d.ts +6 -0
- package/dist/es/shapes/types.d.ts.map +1 -1
- package/dist/lib/compile/anchor-cache.cjs +25 -0
- package/dist/lib/compile/anchor-cache.d.ts +10 -0
- package/dist/lib/compile/anchor-cache.d.ts.map +1 -1
- package/dist/lib/compile/index.d.ts +0 -1
- package/dist/lib/compile/index.d.ts.map +1 -1
- package/dist/lib/compile/path/anchor.cjs +16 -17
- package/dist/lib/compile/path/anchor.d.ts.map +1 -1
- package/dist/lib/compile/path/index.cjs +96 -11
- package/dist/lib/compile/path/index.d.ts.map +1 -1
- package/dist/lib/compile/path/relative.cjs +5 -1
- package/dist/lib/compile/path/relative.d.ts.map +1 -1
- package/dist/lib/geometry/_edge.cjs +38 -0
- package/dist/lib/geometry/_edge.d.ts +29 -0
- package/dist/lib/geometry/_edge.d.ts.map +1 -0
- package/dist/lib/geometry/arc.cjs +28 -0
- package/dist/lib/geometry/arc.d.ts +11 -0
- package/dist/lib/geometry/arc.d.ts.map +1 -1
- package/dist/lib/geometry/circle.cjs +7 -0
- package/dist/lib/geometry/circle.d.ts +3 -0
- package/dist/lib/geometry/circle.d.ts.map +1 -1
- package/dist/lib/geometry/diamond.cjs +29 -0
- package/dist/lib/geometry/diamond.d.ts +3 -0
- package/dist/lib/geometry/diamond.d.ts.map +1 -1
- package/dist/lib/geometry/ellipse.cjs +7 -0
- package/dist/lib/geometry/ellipse.d.ts +3 -0
- package/dist/lib/geometry/ellipse.d.ts.map +1 -1
- package/dist/lib/geometry/rect.cjs +90 -0
- package/dist/lib/geometry/rect.d.ts +26 -0
- package/dist/lib/geometry/rect.d.ts.map +1 -1
- package/dist/lib/geometry/segment.cjs +12 -0
- package/dist/lib/geometry/segment.d.ts +2 -0
- package/dist/lib/geometry/segment.d.ts.map +1 -1
- package/dist/lib/index.cjs +7 -2
- package/dist/lib/index.d.ts +3 -3
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/ir/coordinate.d.ts +2 -2
- package/dist/lib/ir/node.d.ts +4 -4
- package/dist/lib/ir/path/path.d.ts +828 -111
- package/dist/lib/ir/path/path.d.ts.map +1 -1
- package/dist/lib/ir/path/step.cjs +36 -10
- package/dist/lib/ir/path/step.d.ts +1209 -168
- package/dist/lib/ir/path/step.d.ts.map +1 -1
- package/dist/lib/ir/path/target.cjs +25 -2
- package/dist/lib/ir/path/target.d.ts +71 -1
- package/dist/lib/ir/path/target.d.ts.map +1 -1
- package/dist/lib/ir/scope.d.ts +1228 -190
- package/dist/lib/ir/scope.d.ts.map +1 -1
- package/dist/lib/parsers/index.d.ts +1 -0
- package/dist/lib/parsers/index.d.ts.map +1 -1
- package/dist/lib/parsers/parseNodeTarget.cjs +33 -0
- package/dist/lib/parsers/parseNodeTarget.d.ts +4 -0
- package/dist/lib/parsers/parseNodeTarget.d.ts.map +1 -0
- package/dist/lib/parsers/parseTargetSugar.cjs +6 -3
- package/dist/lib/parsers/parseTargetSugar.d.ts +4 -2
- package/dist/lib/parsers/parseTargetSugar.d.ts.map +1 -1
- package/dist/lib/parsers/parseWay.d.ts +1 -1
- package/dist/lib/parsers/parseWay.d.ts.map +1 -1
- package/dist/lib/shapes/circle.cjs +1 -0
- package/dist/lib/shapes/circle.d.ts.map +1 -1
- package/dist/lib/shapes/diamond.cjs +1 -0
- package/dist/lib/shapes/diamond.d.ts.map +1 -1
- package/dist/lib/shapes/ellipse.cjs +1 -0
- package/dist/lib/shapes/ellipse.d.ts.map +1 -1
- package/dist/lib/shapes/rectangle.cjs +1 -0
- package/dist/lib/shapes/rectangle.d.ts.map +1 -1
- package/dist/lib/shapes/types.d.ts +6 -0
- package/dist/lib/shapes/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/es/compile/parseTarget.d.ts +0 -20
- package/dist/es/compile/parseTarget.d.ts.map +0 -1
- package/dist/es/compile/parseTarget.js +0 -36
- package/dist/lib/compile/parseTarget.cjs +0 -36
- package/dist/lib/compile/parseTarget.d.ts +0 -20
- package/dist/lib/compile/parseTarget.d.ts.map +0 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Side } from '../geometry/_edge';
|
|
1
2
|
import { IRPosition } from '../ir';
|
|
2
3
|
import { NodeLayout } from './node';
|
|
3
4
|
/**
|
|
@@ -9,4 +10,13 @@ import { NodeLayout } from './node';
|
|
|
9
10
|
* @returns 全局坐标系下的 IRPosition `[x, y]`
|
|
10
11
|
*/
|
|
11
12
|
export declare const resolveAnchor: (layout: NodeLayout, anchorName: string) => IRPosition;
|
|
13
|
+
/**
|
|
14
|
+
* 取节点边上比例点 `{ side, t }` 的全局坐标,带 per-layout 缓存
|
|
15
|
+
* @description 走 `layout.shapeDef.edgePoint`——shape 未实现(如自定义 shape)抛"does not support side anchors";
|
|
16
|
+
* 零尺寸 layout(Coordinate)抛错(边上比例点对一个点无意义,报错比退化中心更可诊断,见 alpha.6 ADR-01 决策细节 #10)。
|
|
17
|
+
* 缓存 key = `${side}:${t}`,与命名 anchor(`'north'` / `'30'`)共用 layout 的 Map——key 含 `:` 故命名空间不冲突。
|
|
18
|
+
* @param layout 已 Pass 1 完成的 NodeLayout(rect 已是全局坐标)
|
|
19
|
+
* @returns 全局坐标系下的 IRPosition `[x, y]`
|
|
20
|
+
*/
|
|
21
|
+
export declare const resolveEdgePoint: (layout: NodeLayout, side: Side, t: number) => IRPosition;
|
|
12
22
|
//# sourceMappingURL=anchor-cache.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anchor-cache.d.ts","sourceRoot":"","sources":["../../../src/compile/anchor-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"anchor-cache.d.ts","sourceRoot":"","sources":["../../../src/compile/anchor-cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAE9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAExC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AA4BzC;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GACxB,QAAQ,UAAU,EAClB,YAAY,MAAM,KACjB,UAWF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,UAAU,EAClB,MAAM,IAAI,EACV,GAAG,MAAM,KACR,UAuBF,CAAC"}
|
|
@@ -37,5 +37,29 @@ var resolveAnchor = (layout, anchorName) => {
|
|
|
37
37
|
layoutCache.set(anchorName, result);
|
|
38
38
|
return result;
|
|
39
39
|
};
|
|
40
|
+
/**
|
|
41
|
+
* 取节点边上比例点 `{ side, t }` 的全局坐标,带 per-layout 缓存
|
|
42
|
+
* @description 走 `layout.shapeDef.edgePoint`——shape 未实现(如自定义 shape)抛"does not support side anchors";
|
|
43
|
+
* 零尺寸 layout(Coordinate)抛错(边上比例点对一个点无意义,报错比退化中心更可诊断,见 alpha.6 ADR-01 决策细节 #10)。
|
|
44
|
+
* 缓存 key = `${side}:${t}`,与命名 anchor(`'north'` / `'30'`)共用 layout 的 Map——key 含 `:` 故命名空间不冲突。
|
|
45
|
+
* @param layout 已 Pass 1 完成的 NodeLayout(rect 已是全局坐标)
|
|
46
|
+
* @returns 全局坐标系下的 IRPosition `[x, y]`
|
|
47
|
+
*/
|
|
48
|
+
var resolveEdgePoint = (layout, side, t) => {
|
|
49
|
+
const { edgePoint } = layout.shapeDef;
|
|
50
|
+
if (!edgePoint) throw new Error(`shape '${layout.shapeName}' does not support side anchors ({ side, t })`);
|
|
51
|
+
if (layout.rect.width === 0 && layout.rect.height === 0) throw new Error(`{ side, t } is not meaningful on a zero-size Coordinate (shape '${layout.shapeName}')`);
|
|
52
|
+
let layoutCache = cache.get(layout);
|
|
53
|
+
if (!layoutCache) {
|
|
54
|
+
layoutCache = /* @__PURE__ */ new Map();
|
|
55
|
+
cache.set(layout, layoutCache);
|
|
56
|
+
}
|
|
57
|
+
const key = `${side}:${t}`;
|
|
58
|
+
const cached = layoutCache.get(key);
|
|
59
|
+
if (cached !== void 0) return cached;
|
|
60
|
+
const result = positionToIR(edgePoint(layout.rect, side, t));
|
|
61
|
+
layoutCache.set(key, result);
|
|
62
|
+
return result;
|
|
63
|
+
};
|
|
40
64
|
//#endregion
|
|
41
|
-
export { resolveAnchor };
|
|
65
|
+
export { resolveAnchor, resolveEdgePoint };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/compile/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/compile/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,QAAQ,CAAC;AACvB,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anchor.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/anchor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"anchor.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/anchor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgB,UAAU,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAqB/C;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,QAAQ,EAChB,WAAW,SAAS,EACpB,aAAY,aAAa,CAAC,SAAS,CAAM,KACxC,UAAU,GAAG,IAkBf,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,IAkBf,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"}
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { applyTransformChain } from "../scope.js";
|
|
2
2
|
import { resolvePosition } from "../position.js";
|
|
3
3
|
import { boundaryPointOf } from "../node.js";
|
|
4
|
-
import { resolveAnchor } from "../anchor-cache.js";
|
|
5
|
-
import { parseNodeRef } from "../parseTarget.js";
|
|
4
|
+
import { resolveAnchor, resolveEdgePoint } from "../anchor-cache.js";
|
|
6
5
|
//#region src/compile/path/anchor.ts
|
|
6
|
+
/** target 是否对象形态 NodeTarget(`{ id, anchor?, offset? }`);与 Position(array) / Polar / Offset(of) / Relative 区分(独有 `id`) */
|
|
7
|
+
var isNodeTarget = (t) => typeof t === "object" && !Array.isArray(t) && "id" in t;
|
|
8
|
+
/** 解析 NodeTarget 的 anchor(非 undefined)到世界坐标:命名 / 角度走 resolveAnchor,`{ side, t }` 走 resolveEdgePoint */
|
|
9
|
+
var resolveAnchorRef = (node, anchor) => {
|
|
10
|
+
if (typeof anchor === "number") return resolveAnchor(node, String(anchor));
|
|
11
|
+
if (typeof anchor === "string") return resolveAnchor(node, anchor);
|
|
12
|
+
return resolveEdgePoint(node, anchor.side, anchor.t);
|
|
13
|
+
};
|
|
14
|
+
/** anchor/边点解析后叠加世界系 offset(不随节点 rotate 旋转) */
|
|
15
|
+
var addOffset = (base, offset) => offset ? [base[0] + offset[0], base[1] + offset[1]] : base;
|
|
7
16
|
/**
|
|
8
17
|
* 求 step.to 的参考点(给 boundary clip 算方向 / 折角 corner 用)
|
|
9
18
|
* @description 三态:`'A'`(auto) 节点中心;`'A.<anchor>'`/`'A.<deg>'` 显式锚点 refPoint=endpoint 位置不随邻居变。直接坐标/极坐标解析为笛卡尔。
|
|
@@ -12,15 +21,10 @@ import { parseNodeRef } from "../parseTarget.js";
|
|
|
12
21
|
* `applyTransformChain` 投回全局。`scopeChain=[]` 等价 v0.1(恒等)。
|
|
13
22
|
*/
|
|
14
23
|
var refPointOfTarget = (target, nameStack, scopeChain = []) => {
|
|
15
|
-
if (
|
|
16
|
-
const
|
|
17
|
-
const node = nameStack.lookup(ref.id);
|
|
24
|
+
if (isNodeTarget(target)) {
|
|
25
|
+
const node = nameStack.lookup(target.id);
|
|
18
26
|
if (!node) return null;
|
|
19
|
-
|
|
20
|
-
case "node": return [node.rect.x, node.rect.y];
|
|
21
|
-
case "anchor": return resolveAnchor(node, ref.anchor);
|
|
22
|
-
case "angle": return resolveAnchor(node, String(ref.angle));
|
|
23
|
-
}
|
|
27
|
+
return addOffset(target.anchor === void 0 ? [node.rect.x, node.rect.y] : resolveAnchorRef(node, target.anchor), target.offset);
|
|
24
28
|
}
|
|
25
29
|
if (typeof target === "object" && !Array.isArray(target) && ("relative" in target || "relativeAccumulate" in target)) return null;
|
|
26
30
|
const local = resolvePosition(target, nameStack, void 0, scopeChain);
|
|
@@ -36,15 +40,10 @@ var cornerOf = (prev, curr, via) => via === "-|" ? [curr[0], prev[1]] : [prev[0]
|
|
|
36
40
|
* `resolvePosition(..., scopeChain)` 拿到当前 scope 局部坐标后 `applyTransformChain` 投回全局。
|
|
37
41
|
*/
|
|
38
42
|
var clipForTarget = (target, toward, nameStack, scopeChain = []) => {
|
|
39
|
-
if (
|
|
40
|
-
const
|
|
41
|
-
const node = nameStack.lookup(ref.id);
|
|
43
|
+
if (isNodeTarget(target)) {
|
|
44
|
+
const node = nameStack.lookup(target.id);
|
|
42
45
|
if (!node) return null;
|
|
43
|
-
|
|
44
|
-
case "node": return boundaryPointOf(node, toward);
|
|
45
|
-
case "anchor": return resolveAnchor(node, ref.anchor);
|
|
46
|
-
case "angle": return resolveAnchor(node, String(ref.angle));
|
|
47
|
-
}
|
|
46
|
+
return addOffset(target.anchor === void 0 ? boundaryPointOf(node, toward) : resolveAnchorRef(node, target.anchor), target.offset);
|
|
48
47
|
}
|
|
49
48
|
if (typeof target === "object" && !Array.isArray(target) && ("relative" in target || "relativeAccumulate" in target)) return null;
|
|
50
49
|
const local = resolvePosition(target, nameStack, void 0, scopeChain);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/index.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EACV,MAAM,EACN,UAAU,EAGX,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAEV,cAAc,EACd,SAAS,EACV,MAAM,iBAAiB,CAAC;AAEzB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,KAAK,YAAY,EAAoB,MAAM,iBAAiB,CAAC;AAkCtE,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;CACvC,CAAC;AAEF;;;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,IAkhBrE,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { rectOutline } from "../../geometry/rect.js";
|
|
2
|
+
import { arcBoundingPoints, arcEndPoint, ellipseArcBoundingPoints, ellipseArcPoint } from "../../geometry/arc.js";
|
|
2
3
|
import { bendControlPoints } from "../../geometry/bend.js";
|
|
3
|
-
import { arcSegmentSample, circleSegmentSample, cubicSegmentSample, ellipseSegmentSample, foldSegmentSample, lineSegmentSample, quadSegmentSample } from "../../geometry/segment.js";
|
|
4
|
+
import { arcSegmentSample, circleSegmentSample, cubicSegmentSample, ellipseArcSegmentSample, ellipseSegmentSample, foldSegmentSample, lineSegmentSample, quadSegmentSample } from "../../geometry/segment.js";
|
|
4
5
|
import { fallbackMeasurer } from "../text-metrics.js";
|
|
5
6
|
import { clipForTarget, cornerOf, refPointOfTarget, samePoint } from "./anchor.js";
|
|
6
7
|
import { emitLabelPrimitive, tForLabelPosition } from "./label.js";
|
|
@@ -8,6 +9,8 @@ import { normalizeRelativeTargets } from "./relative.js";
|
|
|
8
9
|
import { applyArrowShrinks, computeShrink, endpointArrows } from "./shrink.js";
|
|
9
10
|
import { splitSubPathsForEndpointArrows } from "./split.js";
|
|
10
11
|
//#region src/compile/path/index.ts
|
|
12
|
+
/** 目标若是对象 NodeTarget(`{ id, ... }`)返回其 id,否则 undefined——给 UNRESOLVED_NODE_REFERENCE 诊断用 */
|
|
13
|
+
var nodeRefId = (t) => typeof t === "object" && !Array.isArray(t) && "id" in t ? t.id : void 0;
|
|
11
14
|
/**
|
|
12
15
|
* 语义 stroke 档位 → 数值(user units)
|
|
13
16
|
* @description 对齐 TikZ 比例(thin=0.4pt→1=默认 strokeWidth):ultraThin 0.25、veryThin 0.5、thin 1、semithick 1.5、thick 2、veryThick 3、ultraThick 4。显式 strokeWidth 覆盖 thickness。
|
|
@@ -51,11 +54,12 @@ var emitPathPrimitive = (path, nameStack, round, measureText = fallbackMeasurer,
|
|
|
51
54
|
labelPrims.push(r.primitive);
|
|
52
55
|
for (const p of r.points) points.push(p);
|
|
53
56
|
};
|
|
54
|
-
const hasTo = (s) => s.kind !== "cycle" && s.kind !== "arc" && s.kind !== "circlePath" && s.kind !== "ellipsePath";
|
|
57
|
+
const hasTo = (s) => s.kind !== "cycle" && s.kind !== "arc" && s.kind !== "circlePath" && s.kind !== "ellipsePath" && s.kind !== "rectangle";
|
|
55
58
|
const anchors = steps.map((s, idx) => {
|
|
56
59
|
if (!hasTo(s)) return null;
|
|
57
60
|
const ref = refPointOfTarget(s.to, nameStack, scopeChain);
|
|
58
|
-
|
|
61
|
+
const toId = nodeRefId(s.to);
|
|
62
|
+
if (!ref && toId !== void 0) warn("UNRESOLVED_NODE_REFERENCE", `Step.to references undefined node id '${toId}'; the entire path is skipped`, `children[${idx}].to`);
|
|
59
63
|
return ref;
|
|
60
64
|
});
|
|
61
65
|
/**
|
|
@@ -168,6 +172,12 @@ var emitPathPrimitive = (path, nameStack, round, measureText = fallbackMeasurer,
|
|
|
168
172
|
if (samePoint(p, lastEnd)) return;
|
|
169
173
|
emitMove(p);
|
|
170
174
|
};
|
|
175
|
+
/** 部分圆/椭圆的闭合模式:'open' 直接返回;缺省 / 误给 'closed' 回退 'chord' */
|
|
176
|
+
const resolvePartialClosed = (closed, idx) => {
|
|
177
|
+
if (closed === "open") return "open";
|
|
178
|
+
if (closed === "closed") warn("PARTIAL_ARC_CLOSED_INVALID", "Partial circle/ellipse (with angles) cannot use closed:'closed'; falling back to 'chord'", `children[${idx}]`);
|
|
179
|
+
return "chord";
|
|
180
|
+
};
|
|
171
181
|
for (let i = 0; i < steps.length; i++) {
|
|
172
182
|
if (i > 0) {
|
|
173
183
|
const prevStep = steps[i - 1];
|
|
@@ -193,22 +203,83 @@ var emitPathPrimitive = (path, nameStack, round, measureText = fallbackMeasurer,
|
|
|
193
203
|
emitLine(toClip);
|
|
194
204
|
continue;
|
|
195
205
|
}
|
|
206
|
+
if (step.kind === "rectangle") {
|
|
207
|
+
const fromPt = refPointOfTarget(step.from, nameStack, scopeChain);
|
|
208
|
+
const toPt = refPointOfTarget(step.to, nameStack, scopeChain);
|
|
209
|
+
if (!fromPt || !toPt) {
|
|
210
|
+
const fromId = nodeRefId(step.from);
|
|
211
|
+
const rectToId = nodeRefId(step.to);
|
|
212
|
+
if (!fromPt && fromId !== void 0) warn("UNRESOLVED_NODE_REFERENCE", `Rectangle from references undefined node id '${fromId}'; the entire path is skipped`, `children[${i}].from`);
|
|
213
|
+
if (!toPt && rectToId !== void 0) warn("UNRESOLVED_NODE_REFERENCE", `Rectangle to references undefined node id '${rectToId}'; the entire path is skipped`, `children[${i}].to`);
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
let rectStart = null;
|
|
217
|
+
for (const op of rectOutline(fromPt, toPt, step.roundedCorners)) if (op.kind === "move") {
|
|
218
|
+
emitMove(op.to);
|
|
219
|
+
rectStart = op.to;
|
|
220
|
+
} else if (op.kind === "line") emitLine(op.to);
|
|
221
|
+
else if (op.kind === "arc") emitArc(op.center, op.radius, op.startAngle, op.endAngle);
|
|
222
|
+
else emitClose();
|
|
223
|
+
const rx0 = Math.min(fromPt[0], toPt[0]);
|
|
224
|
+
const rx1 = Math.max(fromPt[0], toPt[0]);
|
|
225
|
+
const ry0 = Math.min(fromPt[1], toPt[1]);
|
|
226
|
+
const ry1 = Math.max(fromPt[1], toPt[1]);
|
|
227
|
+
points.push([rx0, ry0], [rx1, ry0], [rx1, ry1], [rx0, ry1]);
|
|
228
|
+
if (rectStart) penOverride = rectStart;
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
196
231
|
const prev = findPrev();
|
|
197
232
|
if (!prev) return null;
|
|
198
233
|
if (step.kind === "arc") {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
234
|
+
let center;
|
|
235
|
+
if (step.center !== void 0) {
|
|
236
|
+
const c = refPointOfTarget(step.center, nameStack, scopeChain);
|
|
237
|
+
if (!c) {
|
|
238
|
+
const centerId = nodeRefId(step.center);
|
|
239
|
+
if (centerId !== void 0) warn("UNRESOLVED_NODE_REFERENCE", `Arc step center references undefined node id '${centerId}'; the entire path is skipped`, `children[${i}].center`);
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
center = c;
|
|
243
|
+
} else center = prev.anchor;
|
|
244
|
+
if (step.radiusX !== void 0 && step.radiusY !== void 0) {
|
|
245
|
+
const rx = step.radiusX;
|
|
246
|
+
const ry = step.radiusY;
|
|
247
|
+
startSegment(ellipseArcPoint(center, rx, ry, step.startAngle));
|
|
248
|
+
emitEllipseArc(center, rx, ry, step.startAngle, step.endAngle);
|
|
249
|
+
for (const p of ellipseArcBoundingPoints(center, rx, ry, step.startAngle, step.endAngle)) points.push(p);
|
|
250
|
+
collectLabel(step, (t) => ellipseArcSegmentSample(center, rx, ry, step.startAngle, step.endAngle, t));
|
|
251
|
+
penOverride = ellipseArcPoint(center, rx, ry, step.endAngle);
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
if (step.radius !== void 0) {
|
|
255
|
+
const r = step.radius;
|
|
256
|
+
startSegment(arcEndPoint(center, r, step.startAngle));
|
|
257
|
+
emitArc(center, r, step.startAngle, step.endAngle);
|
|
258
|
+
for (const p of arcBoundingPoints(center, r, step.startAngle, step.endAngle)) points.push(p);
|
|
259
|
+
collectLabel(step, (t) => arcSegmentSample(center, r, step.startAngle, step.endAngle, t));
|
|
260
|
+
penOverride = arcEndPoint(center, r, step.endAngle);
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
warn("ARC_MISSING_RADIUS", "Arc step requires radius (circular) or both radiusX and radiusY (elliptical); the entire path is skipped", `children[${i}]`);
|
|
264
|
+
return null;
|
|
208
265
|
}
|
|
209
266
|
if (step.kind === "circlePath") {
|
|
210
267
|
const center = prev.anchor;
|
|
211
268
|
const r = step.radius;
|
|
269
|
+
if (step.startAngle !== void 0 && step.endAngle !== void 0) {
|
|
270
|
+
const startA = step.startAngle;
|
|
271
|
+
const endA = step.endAngle;
|
|
272
|
+
startSegment(ellipseArcPoint(center, r, r, startA));
|
|
273
|
+
emitEllipseArc(center, r, r, startA, endA);
|
|
274
|
+
for (const p of ellipseArcBoundingPoints(center, r, r, startA, endA)) points.push(p);
|
|
275
|
+
collectLabel(step, (t) => ellipseArcSegmentSample(center, r, r, startA, endA, t));
|
|
276
|
+
if (resolvePartialClosed(step.closed, i) === "chord") {
|
|
277
|
+
emitClose();
|
|
278
|
+
penOverride = ellipseArcPoint(center, r, r, startA);
|
|
279
|
+
} else penOverride = ellipseArcPoint(center, r, r, endA);
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (step.startAngle !== void 0 || step.endAngle !== void 0) warn("PARTIAL_ARC_NEEDS_BOTH_ANGLES", "circlePath needs both startAngle and endAngle for a partial circle; treated as a full circle", `children[${i}]`);
|
|
212
283
|
startSegment([center[0] + r, center[1]]);
|
|
213
284
|
emitEllipseArc(center, r, r, 0, 360);
|
|
214
285
|
points.push([center[0] + r, center[1]]);
|
|
@@ -223,6 +294,20 @@ var emitPathPrimitive = (path, nameStack, round, measureText = fallbackMeasurer,
|
|
|
223
294
|
const center = prev.anchor;
|
|
224
295
|
const rx = step.radiusX;
|
|
225
296
|
const ry = step.radiusY;
|
|
297
|
+
if (step.startAngle !== void 0 && step.endAngle !== void 0) {
|
|
298
|
+
const startA = step.startAngle;
|
|
299
|
+
const endA = step.endAngle;
|
|
300
|
+
startSegment(ellipseArcPoint(center, rx, ry, startA));
|
|
301
|
+
emitEllipseArc(center, rx, ry, startA, endA);
|
|
302
|
+
for (const p of ellipseArcBoundingPoints(center, rx, ry, startA, endA)) points.push(p);
|
|
303
|
+
collectLabel(step, (t) => ellipseArcSegmentSample(center, rx, ry, startA, endA, t));
|
|
304
|
+
if (resolvePartialClosed(step.closed, i) === "chord") {
|
|
305
|
+
emitClose();
|
|
306
|
+
penOverride = ellipseArcPoint(center, rx, ry, startA);
|
|
307
|
+
} else penOverride = ellipseArcPoint(center, rx, ry, endA);
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
if (step.startAngle !== void 0 || step.endAngle !== void 0) warn("PARTIAL_ARC_NEEDS_BOTH_ANGLES", "ellipsePath needs both startAngle and endAngle for a partial ellipse; treated as a full ellipse", `children[${i}]`);
|
|
226
311
|
startSegment([center[0] + rx, center[1]]);
|
|
227
312
|
emitEllipseArc(center, rx, ry, 0, 360);
|
|
228
313
|
points.push([center[0] + rx, center[1]]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"relative.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/relative.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,MAAM,EAAY,MAAM,UAAU,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI/C;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,GACnC,OAAO,aAAa,CAAC,MAAM,CAAC,EAC5B,WAAW,SAAS,EACpB,aAAY,aAAa,CAAC,SAAS,CAAM,KACxC,KAAK,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"relative.d.ts","sourceRoot":"","sources":["../../../../src/compile/path/relative.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAc,MAAM,EAAY,MAAM,UAAU,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI/C;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,GACnC,OAAO,aAAa,CAAC,MAAM,CAAC,EAC5B,WAAW,SAAS,EACpB,aAAY,aAAa,CAAC,SAAS,CAAM,KACxC,KAAK,CAAC,MAAM,CA6Ed,CAAC"}
|
|
@@ -25,7 +25,11 @@ var normalizeRelativeTargets = (steps, nameStack, scopeChain = []) => {
|
|
|
25
25
|
}
|
|
26
26
|
if (step.kind === "arc") {
|
|
27
27
|
out.push(step);
|
|
28
|
-
if (prevEnd) prevEnd = arcEndPoint(prevEnd, step.radius, step.endAngle);
|
|
28
|
+
if (prevEnd && step.radius !== void 0 && step.center === void 0) prevEnd = arcEndPoint(prevEnd, step.radius, step.endAngle);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (step.kind === "rectangle") {
|
|
32
|
+
out.push(step);
|
|
29
33
|
continue;
|
|
30
34
|
}
|
|
31
35
|
const original = step.to;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Position } from './point';
|
|
2
|
+
/** 边上比例点 `{ side, t }` 的四个 side(north/south/east/west) */
|
|
3
|
+
export type Side = 'north' | 'south' | 'east' | 'west';
|
|
4
|
+
/**
|
|
5
|
+
* rect 四直边 t=0 / t=1 端点对应的角 anchor
|
|
6
|
+
* @description 方向约定单一真源:north/south = 西→东(t=0 在 west 端),east/west = 北→南(t=0 在 north 端)。
|
|
7
|
+
* 仅 rect 直边用两角端点;circle/ellipse 用 `edgeAngleDeg` 角度表、diamond 用过顶点折线。
|
|
8
|
+
*/
|
|
9
|
+
export declare const EDGE_ENDS: {
|
|
10
|
+
readonly north: readonly ["north-west", "north-east"];
|
|
11
|
+
readonly south: readonly ["south-west", "south-east"];
|
|
12
|
+
readonly east: readonly ["north-east", "south-east"];
|
|
13
|
+
readonly west: readonly ["north-west", "south-west"];
|
|
14
|
+
};
|
|
15
|
+
/** 线性插值 a + (b − a)·t */
|
|
16
|
+
export declare const lerpPoint: (a: Position, b: Position, t: number) => Position;
|
|
17
|
+
/**
|
|
18
|
+
* circle / ellipse 周长弧段:side 的局部参数角 θ(t),单位度
|
|
19
|
+
* @description 约定同 geometry 既有 `(cosθ, sinθ)` + y 轴向下 ⇒ east=0° / south=90° / west=180° / north=270°,
|
|
20
|
+
* 顺时针为正。每条 side 是一段 90° 弧(等角插值);三点(t=0/0.5/1)与 9-anchor 重合。
|
|
21
|
+
*/
|
|
22
|
+
export declare const edgeAngleDeg: (side: Side, t: number) => number;
|
|
23
|
+
/**
|
|
24
|
+
* diamond 过 cardinal 顶点的两段折线
|
|
25
|
+
* @description t∈[0,0.5] 走 p0→vertex、t∈[0.5,1] 走 vertex→p1;t=0.5 恰落 vertex。
|
|
26
|
+
* p0/p1 为相邻边中点 anchor、vertex 为 cardinal 顶点 anchor——全落真实斜边
|
|
27
|
+
*/
|
|
28
|
+
export declare const polylineViaVertex: (p0: Position, vertex: Position, p1: Position, t: number) => Position;
|
|
29
|
+
//# sourceMappingURL=_edge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_edge.d.ts","sourceRoot":"","sources":["../../../src/geometry/_edge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAGxC,0DAA0D;AAC1D,MAAM,MAAM,IAAI,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEvD;;;;GAIG;AACH,eAAO,MAAM,SAAS;;;;;CAK8C,CAAC;AAErE,yBAAyB;AACzB,eAAO,MAAM,SAAS,GAAI,GAAG,QAAQ,EAAE,GAAG,QAAQ,EAAE,GAAG,MAAM,KAAG,QAG/D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,IAAI,EAAE,GAAG,MAAM,KAAG,MAWpD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAC5B,IAAI,QAAQ,EACZ,QAAQ,QAAQ,EAChB,IAAI,QAAQ,EACZ,GAAG,MAAM,KACR,QAA4F,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
//#region src/geometry/_edge.ts
|
|
2
|
+
/**
|
|
3
|
+
* rect 四直边 t=0 / t=1 端点对应的角 anchor
|
|
4
|
+
* @description 方向约定单一真源:north/south = 西→东(t=0 在 west 端),east/west = 北→南(t=0 在 north 端)。
|
|
5
|
+
* 仅 rect 直边用两角端点;circle/ellipse 用 `edgeAngleDeg` 角度表、diamond 用过顶点折线。
|
|
6
|
+
*/
|
|
7
|
+
var EDGE_ENDS = {
|
|
8
|
+
north: ["north-west", "north-east"],
|
|
9
|
+
south: ["south-west", "south-east"],
|
|
10
|
+
east: ["north-east", "south-east"],
|
|
11
|
+
west: ["north-west", "south-west"]
|
|
12
|
+
};
|
|
13
|
+
/** 线性插值 a + (b − a)·t */
|
|
14
|
+
var lerpPoint = (a, b, t) => [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
|
|
15
|
+
/**
|
|
16
|
+
* circle / ellipse 周长弧段:side 的局部参数角 θ(t),单位度
|
|
17
|
+
* @description 约定同 geometry 既有 `(cosθ, sinθ)` + y 轴向下 ⇒ east=0° / south=90° / west=180° / north=270°,
|
|
18
|
+
* 顺时针为正。每条 side 是一段 90° 弧(等角插值);三点(t=0/0.5/1)与 9-anchor 重合。
|
|
19
|
+
*/
|
|
20
|
+
var edgeAngleDeg = (side, t) => {
|
|
21
|
+
switch (side) {
|
|
22
|
+
case "north": return 225 + 90 * t;
|
|
23
|
+
case "south": return 135 - 90 * t;
|
|
24
|
+
case "east": return -45 + 90 * t;
|
|
25
|
+
case "west": return 225 - 90 * t;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* diamond 过 cardinal 顶点的两段折线
|
|
30
|
+
* @description t∈[0,0.5] 走 p0→vertex、t∈[0.5,1] 走 vertex→p1;t=0.5 恰落 vertex。
|
|
31
|
+
* p0/p1 为相邻边中点 anchor、vertex 为 cardinal 顶点 anchor——全落真实斜边
|
|
32
|
+
*/
|
|
33
|
+
var polylineViaVertex = (p0, vertex, p1, t) => t <= .5 ? lerpPoint(p0, vertex, t * 2) : lerpPoint(vertex, p1, (t - .5) * 2);
|
|
34
|
+
//#endregion
|
|
35
|
+
export { EDGE_ENDS, edgeAngleDeg, lerpPoint, polylineViaVertex };
|
|
@@ -6,4 +6,15 @@ 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
|
+
* 椭圆弧参数点:中心 + 半轴 rx/ry + 参数角(度)→ 椭圆周上点
|
|
11
|
+
* @description 与 arcEndPoint 同角度约定(SVG y-down);endpoint = [cx + rx·cosθ, cy + ry·sinθ]。
|
|
12
|
+
* θ 是参数角(非真实极角,rx≠ry 时两者不等)
|
|
13
|
+
*/
|
|
14
|
+
export declare const ellipseArcPoint: (center: Position, radiusX: number, radiusY: number, angleDeg: number) => Position;
|
|
15
|
+
/**
|
|
16
|
+
* 椭圆弧 bbox 极值候选:起点、终点,加 [start,end] 区间内所有 90°·k 参数角处的椭圆周点
|
|
17
|
+
* @description 轴对齐椭圆的 x 极值在 θ=0/180、y 极值在 θ=90/270,与正圆同结构(仅半轴用 rx/ry)
|
|
18
|
+
*/
|
|
19
|
+
export declare const ellipseArcBoundingPoints: (center: Position, radiusX: number, radiusY: number, startAngleDeg: number, endAngleDeg: number) => Array<Position>;
|
|
9
20
|
//# sourceMappingURL=arc.d.ts.map
|
|
@@ -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;AAWxC,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,CAiBhB,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;AAWxC,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,CAiBhB,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,CAehB,CAAC"}
|
package/dist/es/geometry/arc.js
CHANGED
|
@@ -22,5 +22,31 @@ var arcBoundingPoints = (center, radius, startAngleDeg, endAngleDeg) => {
|
|
|
22
22
|
}
|
|
23
23
|
return points;
|
|
24
24
|
};
|
|
25
|
+
/**
|
|
26
|
+
* 椭圆弧参数点:中心 + 半轴 rx/ry + 参数角(度)→ 椭圆周上点
|
|
27
|
+
* @description 与 arcEndPoint 同角度约定(SVG y-down);endpoint = [cx + rx·cosθ, cy + ry·sinθ]。
|
|
28
|
+
* θ 是参数角(非真实极角,rx≠ry 时两者不等)
|
|
29
|
+
*/
|
|
30
|
+
var ellipseArcPoint = (center, radiusX, radiusY, angleDeg) => {
|
|
31
|
+
const rad = angleDeg * DEG_TO_RAD;
|
|
32
|
+
return [center[0] + Math.cos(rad) * radiusX, center[1] + Math.sin(rad) * radiusY];
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* 椭圆弧 bbox 极值候选:起点、终点,加 [start,end] 区间内所有 90°·k 参数角处的椭圆周点
|
|
36
|
+
* @description 轴对齐椭圆的 x 极值在 θ=0/180、y 极值在 θ=90/270,与正圆同结构(仅半轴用 rx/ry)
|
|
37
|
+
*/
|
|
38
|
+
var ellipseArcBoundingPoints = (center, radiusX, radiusY, startAngleDeg, endAngleDeg) => {
|
|
39
|
+
const points = [ellipseArcPoint(center, radiusX, radiusY, startAngleDeg), ellipseArcPoint(center, radiusX, radiusY, endAngleDeg)];
|
|
40
|
+
const lo = Math.min(startAngleDeg, endAngleDeg);
|
|
41
|
+
const hi = Math.max(startAngleDeg, endAngleDeg);
|
|
42
|
+
const kStart = Math.ceil(lo / 90);
|
|
43
|
+
const kEnd = Math.floor(hi / 90);
|
|
44
|
+
for (let k = kStart; k <= kEnd; k++) {
|
|
45
|
+
const angle = k * 90;
|
|
46
|
+
if (angle === startAngleDeg || angle === endAngleDeg) continue;
|
|
47
|
+
points.push(ellipseArcPoint(center, radiusX, radiusY, angle));
|
|
48
|
+
}
|
|
49
|
+
return points;
|
|
50
|
+
};
|
|
25
51
|
//#endregion
|
|
26
|
-
export { arcBoundingPoints, arcEndPoint };
|
|
52
|
+
export { arcBoundingPoints, arcEndPoint, ellipseArcBoundingPoints, ellipseArcPoint };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Side } from './_edge';
|
|
1
2
|
import { Position } from './point';
|
|
2
3
|
import { RectAnchor } from './rect';
|
|
3
4
|
/** 圆形:几何中心 + 半径,预留旋转字段保持与 Rect 同形 API */
|
|
@@ -19,5 +20,7 @@ export declare const circle: {
|
|
|
19
20
|
anchor: (c: Circle, name: RectAnchor) => Position;
|
|
20
21
|
/** 从圆心向 toward 方向射线与圆周交点(Path 端点贴 Node 边界用) */
|
|
21
22
|
boundaryPoint: (c: Circle, toward: Position) => Position;
|
|
23
|
+
/** 边上比例点:side 的 90° 周长弧段 t∈[0,1] 处(等角,落真实圆周;含旋转) */
|
|
24
|
+
edgePoint: (c: Circle, side: Side, t: number) => Position;
|
|
22
25
|
};
|
|
23
26
|
//# sourceMappingURL=circle.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
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;
|
|
1
|
+
{"version":3,"file":"circle.d.ts","sourceRoot":"","sources":["../../../src/geometry/circle.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,IAAI,EAAgB,MAAM,SAAS,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAIzC,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;IAOtD,oDAAoD;mBACrC,MAAM,QAAQ,IAAI,KAAK,MAAM,KAAG,QAAQ;CAIxD,CAAC"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { localToWorld, worldToLocal } from "./_transform.js";
|
|
2
|
+
import { edgeAngleDeg } from "./_edge.js";
|
|
2
3
|
//#region src/geometry/circle.ts
|
|
4
|
+
var DEG_TO_RAD = Math.PI / 180;
|
|
3
5
|
var SQRT_HALF = Math.SQRT1_2;
|
|
4
6
|
/** 圆形相关基础工具 */
|
|
5
7
|
var circle = {
|
|
@@ -55,6 +57,11 @@ var circle = {
|
|
|
55
57
|
if (len === 0) return [c.x, c.y];
|
|
56
58
|
const t = c.radius / len;
|
|
57
59
|
return localToWorld(c, [lx * t, ly * t]);
|
|
60
|
+
},
|
|
61
|
+
/** 边上比例点:side 的 90° 周长弧段 t∈[0,1] 处(等角,落真实圆周;含旋转) */
|
|
62
|
+
edgePoint: (c, side, t) => {
|
|
63
|
+
const rad = edgeAngleDeg(side, t) * DEG_TO_RAD;
|
|
64
|
+
return localToWorld(c, [c.radius * Math.cos(rad), c.radius * Math.sin(rad)]);
|
|
58
65
|
}
|
|
59
66
|
};
|
|
60
67
|
//#endregion
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Side } from './_edge';
|
|
1
2
|
import { Position } from './point';
|
|
2
3
|
import { RectAnchor } from './rect';
|
|
3
4
|
/** 菱形:中心 + halfA/halfB 半轴长 + 可选旋转;顶点在 (±halfA,0) 与 (0,±halfB) */
|
|
@@ -24,5 +25,7 @@ export declare const diamond: {
|
|
|
24
25
|
* @description 菱形方程 |x|/halfA + |y|/halfB = 1;沿方向 (lx,ly) 缩放 t 倍命中:t = 1 / (|lx|/halfA + |ly|/halfB)
|
|
25
26
|
*/
|
|
26
27
|
boundaryPoint: (d: Diamond, toward: Position) => Position;
|
|
28
|
+
/** 边上比例点:side 过 cardinal 顶点的两段折线 t∈[0,1] 处(落真实斜边;含旋转) */
|
|
29
|
+
edgePoint: (d: Diamond, side: Side, t: number) => Position;
|
|
27
30
|
};
|
|
28
31
|
//# sourceMappingURL=diamond.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
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;
|
|
1
|
+
{"version":3,"file":"diamond.d.ts","sourceRoot":"","sources":["../../../src/geometry/diamond.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,IAAI,EAAqB,MAAM,SAAS,CAAC;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAUzC,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;IAOvD,yDAAyD;mBAC1C,OAAO,QAAQ,IAAI,KAAK,MAAM,KAAG,QAAQ;CASzD,CAAC"}
|
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
import { localToWorld, worldToLocal } from "./_transform.js";
|
|
2
|
+
import { polylineViaVertex } from "./_edge.js";
|
|
2
3
|
//#region src/geometry/diamond.ts
|
|
4
|
+
/** 每条 side 的过顶点折线三 anchor:[邻边中点, cardinal 顶点, 邻边中点](方向 north/south=西→东、east/west=北→南) */
|
|
5
|
+
var DIAMOND_EDGE = {
|
|
6
|
+
north: [
|
|
7
|
+
"north-west",
|
|
8
|
+
"north",
|
|
9
|
+
"north-east"
|
|
10
|
+
],
|
|
11
|
+
south: [
|
|
12
|
+
"south-west",
|
|
13
|
+
"south",
|
|
14
|
+
"south-east"
|
|
15
|
+
],
|
|
16
|
+
east: [
|
|
17
|
+
"north-east",
|
|
18
|
+
"east",
|
|
19
|
+
"south-east"
|
|
20
|
+
],
|
|
21
|
+
west: [
|
|
22
|
+
"north-west",
|
|
23
|
+
"west",
|
|
24
|
+
"south-west"
|
|
25
|
+
]
|
|
26
|
+
};
|
|
3
27
|
/** 菱形相关基础工具 */
|
|
4
28
|
var diamond = {
|
|
5
29
|
/** 中心 */
|
|
@@ -56,6 +80,11 @@ var diamond = {
|
|
|
56
80
|
if (denom === 0) return [d.x, d.y];
|
|
57
81
|
const t = 1 / denom;
|
|
58
82
|
return localToWorld(d, [lx * t, ly * t]);
|
|
83
|
+
},
|
|
84
|
+
/** 边上比例点:side 过 cardinal 顶点的两段折线 t∈[0,1] 处(落真实斜边;含旋转) */
|
|
85
|
+
edgePoint: (d, side, t) => {
|
|
86
|
+
const [mid0, vertex, mid1] = DIAMOND_EDGE[side];
|
|
87
|
+
return polylineViaVertex(diamond.anchor(d, mid0), diamond.anchor(d, vertex), diamond.anchor(d, mid1), t);
|
|
59
88
|
}
|
|
60
89
|
};
|
|
61
90
|
//#endregion
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Side } from './_edge';
|
|
1
2
|
import { Position } from './point';
|
|
2
3
|
import { RectAnchor } from './rect';
|
|
3
4
|
/** 椭圆:中心 + 半长轴 rx / 半短轴 ry + 可选旋转 */
|
|
@@ -27,5 +28,7 @@ export declare const ellipse: {
|
|
|
27
28
|
* @description 椭圆方程 (x/rx)² + (y/ry)² = 1;沿 (lx,ly) 缩放 t 倍命中 t = 1 / √((lx/rx)² + (ly/ry)²)
|
|
28
29
|
*/
|
|
29
30
|
boundaryPoint: (e: Ellipse, toward: Position) => Position;
|
|
31
|
+
/** 边上比例点:side 的 90° 周长弧段 t∈[0,1] 处(等角,落真实椭圆周;含旋转) */
|
|
32
|
+
edgePoint: (e: Ellipse, side: Side, t: number) => Position;
|
|
30
33
|
};
|
|
31
34
|
//# sourceMappingURL=ellipse.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
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;
|
|
1
|
+
{"version":3,"file":"ellipse.d.ts","sourceRoot":"","sources":["../../../src/geometry/ellipse.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,IAAI,EAAgB,MAAM,SAAS,CAAC;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAIzC,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;IAQvD,qDAAqD;mBACtC,OAAO,QAAQ,IAAI,KAAK,MAAM,KAAG,QAAQ;CAIzD,CAAC"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { localToWorld, worldToLocal } from "./_transform.js";
|
|
2
|
+
import { edgeAngleDeg } from "./_edge.js";
|
|
2
3
|
//#region src/geometry/ellipse.ts
|
|
4
|
+
var DEG_TO_RAD = Math.PI / 180;
|
|
3
5
|
var SQRT_HALF = Math.SQRT1_2;
|
|
4
6
|
/** 椭圆相关基础工具 */
|
|
5
7
|
var ellipse = {
|
|
@@ -61,6 +63,11 @@ var ellipse = {
|
|
|
61
63
|
const b = ly / e.ry;
|
|
62
64
|
const t = 1 / Math.sqrt(a * a + b * b);
|
|
63
65
|
return localToWorld(e, [lx * t, ly * t]);
|
|
66
|
+
},
|
|
67
|
+
/** 边上比例点:side 的 90° 周长弧段 t∈[0,1] 处(等角,落真实椭圆周;含旋转) */
|
|
68
|
+
edgePoint: (e, side, t) => {
|
|
69
|
+
const rad = edgeAngleDeg(side, t) * DEG_TO_RAD;
|
|
70
|
+
return localToWorld(e, [e.rx * Math.cos(rad), e.ry * Math.sin(rad)]);
|
|
64
71
|
}
|
|
65
72
|
};
|
|
66
73
|
//#endregion
|