@retikz/core 0.3.0-beta.2 → 0.4.0-alpha.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/node.js +1 -1
- package/dist/es/compile/path/anchor.js +1 -1
- package/dist/es/compile/path/index.js +1 -1
- package/dist/es/compile/path/relative.js +1 -1
- package/dist/es/compile/path/shrink.js +1 -1
- package/dist/es/compile/position.js +1 -1
- package/dist/es/geometry/contour.d.ts +1 -1
- package/dist/es/geometry/contour.d.ts.map +1 -1
- package/dist/es/geometry/contour.js +5 -45
- package/dist/es/geometry/edge.d.ts +1 -2
- package/dist/es/geometry/edge.d.ts.map +1 -1
- package/dist/es/geometry/edge.js +2 -3
- package/dist/es/geometry/index.d.ts +0 -1
- package/dist/es/geometry/index.d.ts.map +1 -1
- package/dist/es/geometry/point.d.ts +1 -29
- package/dist/es/geometry/point.d.ts.map +1 -1
- package/dist/es/geometry/point.js +2 -50
- 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 +13 -5
- package/dist/es/geometry/rect.d.ts +1 -1
- package/dist/es/geometry/rect.js +1 -1
- package/dist/es/geometry/transform.d.ts +1 -20
- package/dist/es/geometry/transform.d.ts.map +1 -1
- package/dist/es/geometry/transform.js +1 -26
- package/dist/es/index.js +2 -2
- package/dist/es/shapes/arc.js +1 -1
- package/dist/es/shapes/shared.js +1 -1
- package/dist/lib/compile/node.cjs +2 -2
- package/dist/lib/compile/path/anchor.cjs +4 -5
- package/dist/lib/compile/path/index.cjs +17 -17
- package/dist/lib/compile/path/relative.cjs +2 -2
- package/dist/lib/compile/path/shrink.cjs +3 -3
- package/dist/lib/compile/position.cjs +2 -2
- package/dist/lib/geometry/circle.cjs +6 -6
- package/dist/lib/geometry/contour.cjs +12 -52
- package/dist/lib/geometry/contour.d.ts +1 -1
- package/dist/lib/geometry/contour.d.ts.map +1 -1
- package/dist/lib/geometry/diamond.cjs +5 -5
- package/dist/lib/geometry/edge.cjs +2 -4
- package/dist/lib/geometry/edge.d.ts +1 -2
- package/dist/lib/geometry/edge.d.ts.map +1 -1
- package/dist/lib/geometry/ellipse.cjs +6 -6
- package/dist/lib/geometry/index.d.ts +0 -1
- package/dist/lib/geometry/index.d.ts.map +1 -1
- package/dist/lib/geometry/point.d.ts +1 -29
- package/dist/lib/geometry/point.d.ts.map +1 -1
- package/dist/lib/geometry/polar.cjs +13 -5
- 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 +7 -7
- package/dist/lib/geometry/rect.d.ts +1 -1
- package/dist/lib/geometry/segment.cjs +9 -9
- package/dist/lib/geometry/transform.d.ts +1 -20
- package/dist/lib/geometry/transform.d.ts.map +1 -1
- package/dist/lib/index.cjs +20 -6
- package/dist/lib/shapes/arc.cjs +7 -8
- package/dist/lib/shapes/index.cjs +1 -1
- package/dist/lib/shapes/polygon.cjs +2 -2
- package/dist/lib/shapes/rectangle.cjs +5 -5
- package/dist/lib/shapes/sector.cjs +4 -4
- package/dist/lib/shapes/shared.cjs +4 -4
- package/dist/lib/shapes/star.cjs +2 -2
- package/package.json +3 -2
- package/dist/es/geometry/arc.d.ts +0 -34
- package/dist/es/geometry/arc.d.ts.map +0 -1
- package/dist/es/geometry/arc.js +0 -108
- package/dist/lib/geometry/arc.cjs +0 -113
- package/dist/lib/geometry/arc.d.ts +0 -34
- package/dist/lib/geometry/arc.d.ts.map +0 -1
- package/dist/lib/geometry/point.cjs +0 -50
- package/dist/lib/geometry/transform.cjs +0 -28
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
//#region src/geometry/arc.ts
|
|
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
|
-
};
|
|
20
|
-
/** 圆心、半径、角度(度,与 polar.toPosition 同约定)→ 圆周上对应点 */
|
|
21
|
-
var arcEndPoint = (center, radius, angleDeg) => {
|
|
22
|
-
const rad = angleDeg * DEG_TO_RAD;
|
|
23
|
-
return [center[0] + Math.cos(rad) * radius, center[1] + Math.sin(rad) * radius];
|
|
24
|
-
};
|
|
25
|
-
/**
|
|
26
|
-
* 弧的 bbox 极值候选:起点、终点,加 [startAngle,endAngle] 内所有 90°·k 方向的圆周点
|
|
27
|
-
* @description 弧投影到 x/y 轴的极值只可能在弧端点或圆周轴向四点出现。endAngle < startAngle 时按 min..max 扫描;跨 360°(270→450)按数值区间正确处理;不去重——端角恰在 90°·k 上时调用方处理
|
|
28
|
-
*/
|
|
29
|
-
var arcBoundingPoints = (center, radius, startAngleDeg, endAngleDeg) => {
|
|
30
|
-
const points = [arcEndPoint(center, radius, startAngleDeg), arcEndPoint(center, radius, endAngleDeg)];
|
|
31
|
-
const lo = Math.min(startAngleDeg, endAngleDeg);
|
|
32
|
-
const hi = Math.max(startAngleDeg, endAngleDeg);
|
|
33
|
-
for (const angle of axisAngles(lo, hi)) {
|
|
34
|
-
if (angle === startAngleDeg || angle === endAngleDeg) continue;
|
|
35
|
-
points.push(arcEndPoint(center, radius, angle));
|
|
36
|
-
}
|
|
37
|
-
return points;
|
|
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
|
-
};
|
|
84
|
-
/**
|
|
85
|
-
* 椭圆弧参数点:中心 + 半轴 rx/ry + 参数角(度)→ 椭圆周上点
|
|
86
|
-
* @description 与 arcEndPoint 同角度约定(SVG y-down);endpoint = [cx + rx·cosθ, cy + ry·sinθ]。
|
|
87
|
-
* θ 是参数角(非真实极角,rx≠ry 时两者不等)
|
|
88
|
-
*/
|
|
89
|
-
var ellipseArcPoint = (center, radiusX, radiusY, angleDeg) => {
|
|
90
|
-
const rad = angleDeg * DEG_TO_RAD;
|
|
91
|
-
return [center[0] + Math.cos(rad) * radiusX, center[1] + Math.sin(rad) * radiusY];
|
|
92
|
-
};
|
|
93
|
-
/**
|
|
94
|
-
* 椭圆弧 bbox 极值候选:起点、终点,加 [start,end] 区间内所有 90°·k 参数角处的椭圆周点
|
|
95
|
-
* @description 轴对齐椭圆的 x 极值在 θ=0/180、y 极值在 θ=90/270,与正圆同结构(仅半轴用 rx/ry)
|
|
96
|
-
*/
|
|
97
|
-
var ellipseArcBoundingPoints = (center, radiusX, radiusY, startAngleDeg, endAngleDeg) => {
|
|
98
|
-
const points = [ellipseArcPoint(center, radiusX, radiusY, startAngleDeg), ellipseArcPoint(center, radiusX, radiusY, endAngleDeg)];
|
|
99
|
-
const lo = Math.min(startAngleDeg, endAngleDeg);
|
|
100
|
-
const hi = Math.max(startAngleDeg, endAngleDeg);
|
|
101
|
-
for (const angle of axisAngles(lo, hi)) {
|
|
102
|
-
if (angle === startAngleDeg || angle === endAngleDeg) continue;
|
|
103
|
-
points.push(ellipseArcPoint(center, radiusX, radiusY, angle));
|
|
104
|
-
}
|
|
105
|
-
return points;
|
|
106
|
-
};
|
|
107
|
-
//#endregion
|
|
108
|
-
exports.arcAngleInRange = arcAngleInRange;
|
|
109
|
-
exports.arcBoundingPoints = arcBoundingPoints;
|
|
110
|
-
exports.arcEndPoint = arcEndPoint;
|
|
111
|
-
exports.ellipseArcBoundingPoints = ellipseArcBoundingPoints;
|
|
112
|
-
exports.ellipseArcPoint = ellipseArcPoint;
|
|
113
|
-
exports.rayArc = rayArc;
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { Position } from './point';
|
|
2
|
-
/** 圆心、半径、角度(度,与 polar.toPosition 同约定)→ 圆周上对应点 */
|
|
3
|
-
export declare const arcEndPoint: (center: Position, radius: number, angleDeg: number) => Position;
|
|
4
|
-
/**
|
|
5
|
-
* 弧的 bbox 极值候选:起点、终点,加 [startAngle,endAngle] 内所有 90°·k 方向的圆周点
|
|
6
|
-
* @description 弧投影到 x/y 轴的极值只可能在弧端点或圆周轴向四点出现。endAngle < startAngle 时按 min..max 扫描;跨 360°(270→450)按数值区间正确处理;不去重——端角恰在 90°·k 上时调用方处理
|
|
7
|
-
*/
|
|
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>;
|
|
23
|
-
/**
|
|
24
|
-
* 椭圆弧参数点:中心 + 半轴 rx/ry + 参数角(度)→ 椭圆周上点
|
|
25
|
-
* @description 与 arcEndPoint 同角度约定(SVG y-down);endpoint = [cx + rx·cosθ, cy + ry·sinθ]。
|
|
26
|
-
* θ 是参数角(非真实极角,rx≠ry 时两者不等)
|
|
27
|
-
*/
|
|
28
|
-
export declare const ellipseArcPoint: (center: Position, radiusX: number, radiusY: number, angleDeg: number) => Position;
|
|
29
|
-
/**
|
|
30
|
-
* 椭圆弧 bbox 极值候选:起点、终点,加 [start,end] 区间内所有 90°·k 参数角处的椭圆周点
|
|
31
|
-
* @description 轴对齐椭圆的 x 极值在 θ=0/180、y 极值在 θ=90/270,与正圆同结构(仅半轴用 rx/ry)
|
|
32
|
-
*/
|
|
33
|
-
export declare const ellipseArcBoundingPoints: (center: Position, radiusX: number, radiusY: number, startAngleDeg: number, endAngleDeg: number) => Array<Position>;
|
|
34
|
-
//# sourceMappingURL=arc.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
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"}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
const require_polar = require("./polar.cjs");
|
|
2
|
-
//#region src/geometry/point.ts
|
|
3
|
-
var RAD_TO_DEG = 180 / Math.PI;
|
|
4
|
-
var DEFAULT_EPSILON = 1e-9;
|
|
5
|
-
/** 二维向量 / 坐标的基础运算工具集 */
|
|
6
|
-
var point = {
|
|
7
|
-
/** 向量加 a + b */
|
|
8
|
-
add: (a, b) => [a[0] + b[0], a[1] + b[1]],
|
|
9
|
-
/** 向量减 a - b */
|
|
10
|
-
sub: (a, b) => [a[0] - b[0], a[1] - b[1]],
|
|
11
|
-
/** 等比缩放 a * k */
|
|
12
|
-
scale: (a, k) => [a[0] * k, a[1] * k],
|
|
13
|
-
/** 向量长度 */
|
|
14
|
-
length: (a) => Math.hypot(a[0], a[1]),
|
|
15
|
-
/** 归一化向量;零长度 / 极短向量回退到 fallback */
|
|
16
|
-
normalize: (a, fallback = [1, 0], epsilon = DEFAULT_EPSILON) => {
|
|
17
|
-
const len = Math.hypot(a[0], a[1]);
|
|
18
|
-
if (len < epsilon) return fallback;
|
|
19
|
-
return [a[0] / len, a[1] / len];
|
|
20
|
-
},
|
|
21
|
-
/** 把点 p 沿 target 方向移动 dist */
|
|
22
|
-
shiftToward: (p, target, dist) => {
|
|
23
|
-
if (dist === 0) return p;
|
|
24
|
-
const delta = [target[0] - p[0], target[1] - p[1]];
|
|
25
|
-
const dir = point.normalize(delta, [0, 0]);
|
|
26
|
-
if (point.equal(dir, [0, 0])) return p;
|
|
27
|
-
return [p[0] + dir[0] * dist, p[1] + dir[1] * dist];
|
|
28
|
-
},
|
|
29
|
-
/** 两点精确相等(不带容差) */
|
|
30
|
-
equal: (a, b) => a[0] === b[0] && a[1] === b[1],
|
|
31
|
-
/** 笛卡尔 → 极坐标(angle ∈ (-180,180],origin 默认 [0,0]) */
|
|
32
|
-
toPolar: (p) => ({
|
|
33
|
-
angle: Math.atan2(p[1], p[0]) * RAD_TO_DEG,
|
|
34
|
-
radius: Math.hypot(p[0], p[1])
|
|
35
|
-
}),
|
|
36
|
-
/**
|
|
37
|
-
* 跨坐标系两点相同判断(笛卡尔或 PolarPosition)
|
|
38
|
-
* @description 极坐标先转笛卡尔再按 precision 四舍五入比较;polar.equal 委托到本方法
|
|
39
|
-
* @param precision 小数点后位数;默认 2
|
|
40
|
-
* @throws 当 PolarPosition.origin 是节点 id 字符串时(需 Scene 上下文)
|
|
41
|
-
*/
|
|
42
|
-
equalPolar: (a, b, precision = 2) => {
|
|
43
|
-
const aCart = Array.isArray(a) ? a : require_polar.polar.toPosition(a);
|
|
44
|
-
const bCart = Array.isArray(b) ? b : require_polar.polar.toPosition(b);
|
|
45
|
-
const factor = 10 ** precision;
|
|
46
|
-
return Math.round(aCart[0] * factor) === Math.round(bCart[0] * factor) && Math.round(aCart[1] * factor) === Math.round(bCart[1] * factor);
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
//#endregion
|
|
50
|
-
exports.point = point;
|
|
@@ -1,28 +0,0 @@
|
|
|
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;
|