@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,6 +1,5 @@
|
|
|
1
1
|
const require_json = require("../../ir/json.cjs");
|
|
2
2
|
const require_rect = require("../../geometry/rect.cjs");
|
|
3
|
-
const require_arc = require("../../geometry/arc.cjs");
|
|
4
3
|
const require_index = require("../../arrows/index.cjs");
|
|
5
4
|
const require_constant = require("../constant.cjs");
|
|
6
5
|
const require_scope = require("../scope.cjs");
|
|
@@ -12,6 +11,7 @@ const require_label = require("./label.cjs");
|
|
|
12
11
|
const require_relative = require("./relative.cjs");
|
|
13
12
|
const require_shrink = require("./shrink.cjs");
|
|
14
13
|
const require_split = require("./split.cjs");
|
|
14
|
+
let _retikz_math = require("@retikz/math");
|
|
15
15
|
//#region src/compile/path/index.ts
|
|
16
16
|
/**
|
|
17
17
|
* referent(offset.of / polar.origin 的并集形态:节点 id 字符串 / `[x, y]` 字面量 / 嵌套 PolarPosition)里挖节点 id
|
|
@@ -345,8 +345,8 @@ var emitPathPrimitive = (path, nameStack, round, measureText = require_text_metr
|
|
|
345
345
|
startAngle,
|
|
346
346
|
endAngle
|
|
347
347
|
});
|
|
348
|
-
points.push(
|
|
349
|
-
lastEnd =
|
|
348
|
+
points.push((0, _retikz_math.arcEndPoint)(center, radius, endAngle));
|
|
349
|
+
lastEnd = (0, _retikz_math.arcEndPoint)(center, radius, endAngle);
|
|
350
350
|
};
|
|
351
351
|
const emitEllipseArc = (center, radiusX, radiusY, startAngle, endAngle) => {
|
|
352
352
|
noteEndpointSource(false);
|
|
@@ -517,20 +517,20 @@ var emitPathPrimitive = (path, nameStack, round, measureText = require_text_metr
|
|
|
517
517
|
if (step.radiusX !== void 0 && step.radiusY !== void 0) {
|
|
518
518
|
const rx = step.radiusX;
|
|
519
519
|
const ry = step.radiusY;
|
|
520
|
-
startSegment(
|
|
520
|
+
startSegment((0, _retikz_math.ellipseArcPoint)(center, rx, ry, step.startAngle));
|
|
521
521
|
emitEllipseArc(center, rx, ry, step.startAngle, step.endAngle);
|
|
522
|
-
for (const p of
|
|
522
|
+
for (const p of (0, _retikz_math.ellipseArcBoundingPoints)(center, rx, ry, step.startAngle, step.endAngle)) points.push(p);
|
|
523
523
|
collectLabel(step, (t) => require_segment.ellipseArcSegmentSample(center, rx, ry, step.startAngle, step.endAngle, t));
|
|
524
|
-
penOverride =
|
|
524
|
+
penOverride = (0, _retikz_math.ellipseArcPoint)(center, rx, ry, step.endAngle);
|
|
525
525
|
continue;
|
|
526
526
|
}
|
|
527
527
|
if (step.radius !== void 0) {
|
|
528
528
|
const r = step.radius;
|
|
529
|
-
startSegment(
|
|
529
|
+
startSegment((0, _retikz_math.arcEndPoint)(center, r, step.startAngle));
|
|
530
530
|
emitArc(center, r, step.startAngle, step.endAngle);
|
|
531
|
-
for (const p of
|
|
531
|
+
for (const p of (0, _retikz_math.arcBoundingPoints)(center, r, step.startAngle, step.endAngle)) points.push(p);
|
|
532
532
|
collectLabel(step, (t) => require_segment.arcSegmentSample(center, r, step.startAngle, step.endAngle, t));
|
|
533
|
-
penOverride =
|
|
533
|
+
penOverride = (0, _retikz_math.arcEndPoint)(center, r, step.endAngle);
|
|
534
534
|
continue;
|
|
535
535
|
}
|
|
536
536
|
warn(require_constant.CompileWarningCode.ArcMissingRadius, "Arc step requires radius (circular) or both radiusX and radiusY (elliptical); the entire path is skipped", `children[${i}]`);
|
|
@@ -542,19 +542,19 @@ var emitPathPrimitive = (path, nameStack, round, measureText = require_text_metr
|
|
|
542
542
|
if (step.startAngle !== void 0 && step.endAngle !== void 0) {
|
|
543
543
|
const startA = step.startAngle;
|
|
544
544
|
const endA = step.endAngle;
|
|
545
|
-
startSegment(
|
|
545
|
+
startSegment((0, _retikz_math.ellipseArcPoint)(center, r, r, startA));
|
|
546
546
|
emitEllipseArc(center, r, r, startA, endA);
|
|
547
|
-
for (const p of
|
|
547
|
+
for (const p of (0, _retikz_math.ellipseArcBoundingPoints)(center, r, r, startA, endA)) points.push(p);
|
|
548
548
|
collectLabel(step, (t) => require_segment.ellipseArcSegmentSample(center, r, r, startA, endA, t));
|
|
549
549
|
const closing = resolvePartialClosed(step.closed, i);
|
|
550
550
|
if (closing === "chord") {
|
|
551
551
|
emitClose();
|
|
552
|
-
penOverride =
|
|
552
|
+
penOverride = (0, _retikz_math.ellipseArcPoint)(center, r, r, startA);
|
|
553
553
|
} else if (closing === "sector") {
|
|
554
554
|
emitLine(center);
|
|
555
555
|
emitClose();
|
|
556
556
|
penOverride = center;
|
|
557
|
-
} else penOverride =
|
|
557
|
+
} else penOverride = (0, _retikz_math.ellipseArcPoint)(center, r, r, endA);
|
|
558
558
|
continue;
|
|
559
559
|
}
|
|
560
560
|
if (step.startAngle !== void 0 || step.endAngle !== void 0) warn(require_constant.CompileWarningCode.PartialArcNeedsBothAngles, "circlePath needs both startAngle and endAngle for a partial circle; treated as a full circle", `children[${i}]`);
|
|
@@ -575,19 +575,19 @@ var emitPathPrimitive = (path, nameStack, round, measureText = require_text_metr
|
|
|
575
575
|
if (step.startAngle !== void 0 && step.endAngle !== void 0) {
|
|
576
576
|
const startA = step.startAngle;
|
|
577
577
|
const endA = step.endAngle;
|
|
578
|
-
startSegment(
|
|
578
|
+
startSegment((0, _retikz_math.ellipseArcPoint)(center, rx, ry, startA));
|
|
579
579
|
emitEllipseArc(center, rx, ry, startA, endA);
|
|
580
|
-
for (const p of
|
|
580
|
+
for (const p of (0, _retikz_math.ellipseArcBoundingPoints)(center, rx, ry, startA, endA)) points.push(p);
|
|
581
581
|
collectLabel(step, (t) => require_segment.ellipseArcSegmentSample(center, rx, ry, startA, endA, t));
|
|
582
582
|
const closing = resolvePartialClosed(step.closed, i);
|
|
583
583
|
if (closing === "chord") {
|
|
584
584
|
emitClose();
|
|
585
|
-
penOverride =
|
|
585
|
+
penOverride = (0, _retikz_math.ellipseArcPoint)(center, rx, ry, startA);
|
|
586
586
|
} else if (closing === "sector") {
|
|
587
587
|
emitLine(center);
|
|
588
588
|
emitClose();
|
|
589
589
|
penOverride = center;
|
|
590
|
-
} else penOverride =
|
|
590
|
+
} else penOverride = (0, _retikz_math.ellipseArcPoint)(center, rx, ry, endA);
|
|
591
591
|
continue;
|
|
592
592
|
}
|
|
593
593
|
if (step.startAngle !== void 0 || step.endAngle !== void 0) warn(require_constant.CompileWarningCode.PartialArcNeedsBothAngles, "ellipsePath needs both startAngle and endAngle for a partial ellipse; treated as a full ellipse", `children[${i}]`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const require_arc = require("../../geometry/arc.cjs");
|
|
2
1
|
const require_scope = require("../scope.cjs");
|
|
3
2
|
const require_anchor = require("./anchor.cjs");
|
|
3
|
+
let _retikz_math = require("@retikz/math");
|
|
4
4
|
//#region src/compile/path/relative.ts
|
|
5
5
|
/**
|
|
6
6
|
* relative/relativeAccumulate 目标解析为绝对 Position(step kind 不变,to 为局部坐标 tuple)
|
|
@@ -25,7 +25,7 @@ var normalizeRelativeTargets = (steps, nameStack, scopeChain = []) => {
|
|
|
25
25
|
}
|
|
26
26
|
if (step.kind === "arc") {
|
|
27
27
|
out.push(step);
|
|
28
|
-
if (prevEnd && step.radius !== void 0 && step.center === void 0) prevEnd =
|
|
28
|
+
if (prevEnd && step.radius !== void 0 && step.center === void 0) prevEnd = (0, _retikz_math.arcEndPoint)(prevEnd, step.radius, step.endAngle);
|
|
29
29
|
continue;
|
|
30
30
|
}
|
|
31
31
|
if (step.kind === "rectangle") {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const require_arrow = require("../../ir/path/arrow.cjs");
|
|
2
|
-
const require_arc = require("../../geometry/arc.cjs");
|
|
3
2
|
const require_marker_prim = require("../marker-prim.cjs");
|
|
4
3
|
const require_anchor = require("./anchor.cjs");
|
|
4
|
+
let _retikz_math = require("@retikz/math");
|
|
5
5
|
//#region src/compile/path/shrink.ts
|
|
6
6
|
/** 默认 baseSize(marker 局部基准边长,viewBox `0 0 baseSize baseSize`) */
|
|
7
7
|
var ARROW_GEOMETRY_BASE_SIZE = 10;
|
|
@@ -191,8 +191,8 @@ var endpointOf = (cmd) => {
|
|
|
191
191
|
case "line":
|
|
192
192
|
case "quad":
|
|
193
193
|
case "cubic": return [cmd.to[0], cmd.to[1]];
|
|
194
|
-
case "arc": return
|
|
195
|
-
case "ellipseArc": return
|
|
194
|
+
case "arc": return (0, _retikz_math.arcEndPoint)(cmd.center, cmd.radius, cmd.endAngle);
|
|
195
|
+
case "ellipseArc": return (0, _retikz_math.ellipseArcPoint)(cmd.center, cmd.radiusX, cmd.radiusY, cmd.endAngle);
|
|
196
196
|
case "close": return null;
|
|
197
197
|
}
|
|
198
198
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const require_arc = require("../geometry/arc.cjs");
|
|
2
1
|
const require_direction = require("./direction.cjs");
|
|
3
2
|
const require_scope = require("./scope.cjs");
|
|
3
|
+
let _retikz_math = require("@retikz/math");
|
|
4
4
|
//#region src/compile/position.ts
|
|
5
5
|
/** 默认相对定位距离(CompileOptions.nodeDistance 未配时使用) */
|
|
6
6
|
var DEFAULT_NODE_DISTANCE = 1;
|
|
@@ -58,7 +58,7 @@ var resolvePosition = (pos, nameStack, nodeDistance = DEFAULT_NODE_DISTANCE, sco
|
|
|
58
58
|
if (!resolved) return null;
|
|
59
59
|
origin = resolved;
|
|
60
60
|
}
|
|
61
|
-
return
|
|
61
|
+
return (0, _retikz_math.arcEndPoint)(origin, pos.radius, pos.angle);
|
|
62
62
|
};
|
|
63
63
|
//#endregion
|
|
64
64
|
exports.resolvePosition = resolvePosition;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_edge = require("./edge.cjs");
|
|
2
|
-
|
|
2
|
+
let _retikz_math = require("@retikz/math");
|
|
3
3
|
//#region src/geometry/circle.ts
|
|
4
4
|
var DEG_TO_RAD = Math.PI / 180;
|
|
5
5
|
var SQRT_HALF = Math.SQRT1_2;
|
|
@@ -9,7 +9,7 @@ var circle = {
|
|
|
9
9
|
center: (c) => [c.x, c.y],
|
|
10
10
|
/** 判断点是否在圆内(含边界) */
|
|
11
11
|
contains: (c, p) => {
|
|
12
|
-
const [lx, ly] =
|
|
12
|
+
const [lx, ly] = (0, _retikz_math.worldToLocal)(c, p);
|
|
13
13
|
return lx * lx + ly * ly <= c.radius * c.radius;
|
|
14
14
|
},
|
|
15
15
|
/** 9 个标准方位 anchor 之一的世界坐标 */
|
|
@@ -48,20 +48,20 @@ var circle = {
|
|
|
48
48
|
ly = r * SQRT_HALF;
|
|
49
49
|
break;
|
|
50
50
|
}
|
|
51
|
-
return
|
|
51
|
+
return (0, _retikz_math.localToWorld)(c, [lx, ly]);
|
|
52
52
|
},
|
|
53
53
|
/** 从圆心向 toward 方向射线与圆周交点(Path 端点贴 Node 边界用) */
|
|
54
54
|
boundaryPoint: (c, toward) => {
|
|
55
|
-
const [lx, ly] =
|
|
55
|
+
const [lx, ly] = (0, _retikz_math.worldToLocal)(c, toward);
|
|
56
56
|
const len = Math.sqrt(lx * lx + ly * ly);
|
|
57
57
|
if (len === 0) return [c.x, c.y];
|
|
58
58
|
const t = c.radius / len;
|
|
59
|
-
return
|
|
59
|
+
return (0, _retikz_math.localToWorld)(c, [lx * t, ly * t]);
|
|
60
60
|
},
|
|
61
61
|
/** 边上比例点:side 的 90° 周长弧段 t∈[0,1] 处(等角,落真实圆周;含旋转) */
|
|
62
62
|
edgePoint: (c, side, t) => {
|
|
63
63
|
const rad = require_edge.edgeAngleDeg(side, t) * DEG_TO_RAD;
|
|
64
|
-
return
|
|
64
|
+
return (0, _retikz_math.localToWorld)(c, [c.radius * Math.cos(rad), c.radius * Math.sin(rad)]);
|
|
65
65
|
}
|
|
66
66
|
};
|
|
67
67
|
//#endregion
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
const require_point = require("./point.cjs");
|
|
1
|
+
let _retikz_math = require("@retikz/math");
|
|
3
2
|
//#region src/geometry/contour.ts
|
|
4
3
|
var DEG_TO_RAD = Math.PI / 180;
|
|
5
4
|
var RAD_TO_DEG = 180 / Math.PI;
|
|
@@ -7,19 +6,19 @@ var EPSILON = 1e-9;
|
|
|
7
6
|
/** 二维叉积 a × b */
|
|
8
7
|
var cross = (a, b) => a[0] * b[1] - a[1] * b[0];
|
|
9
8
|
/** 段起点 */
|
|
10
|
-
var segmentStart = (seg) => seg.kind === "line" ? seg.from :
|
|
9
|
+
var segmentStart = (seg) => seg.kind === "line" ? seg.from : (0, _retikz_math.arcEndPoint)(seg.center, seg.radius, seg.startAngle);
|
|
11
10
|
/** 段终点 */
|
|
12
|
-
var segmentEnd = (seg) => seg.kind === "line" ? seg.to :
|
|
11
|
+
var segmentEnd = (seg) => seg.kind === "line" ? seg.to : (0, _retikz_math.arcEndPoint)(seg.center, seg.radius, seg.endAngle);
|
|
13
12
|
/**
|
|
14
13
|
* 段在某端的「行进切线」单位向量
|
|
15
14
|
* @description atStart=true 取起点处沿行进方向的切线,否则取终点处。line 两端切线相同;
|
|
16
15
|
* arc 切线垂直于半径,方向随 counterClockwise 翻转(CW: (-sinθ, cosθ),CCW: (sinθ, -cosθ))。
|
|
17
16
|
*/
|
|
18
17
|
var tangentAt = (seg, atStart) => {
|
|
19
|
-
if (seg.kind === "line") return
|
|
18
|
+
if (seg.kind === "line") return _retikz_math.point.normalize([seg.to[0] - seg.from[0], seg.to[1] - seg.from[1]]);
|
|
20
19
|
const rad = (atStart ? seg.startAngle : seg.endAngle) * DEG_TO_RAD;
|
|
21
20
|
const sign = seg.counterClockwise ? -1 : 1;
|
|
22
|
-
return
|
|
21
|
+
return _retikz_math.point.normalize([-Math.sin(rad) * sign, Math.cos(rad) * sign]);
|
|
23
22
|
};
|
|
24
23
|
/** arc 段的角跨度(带符号:CW 为正递增、CCW 为负),单位度 */
|
|
25
24
|
var arcSpan = (seg) => seg.endAngle - seg.startAngle;
|
|
@@ -76,45 +75,6 @@ var offsetSegmentAlt = (seg, r) => ({
|
|
|
76
75
|
center: seg.center,
|
|
77
76
|
radius: seg.radius + r
|
|
78
77
|
});
|
|
79
|
-
/** 直线 ∩ 直线(各以 point + dir 表示),返回交点或 undefined(平行) */
|
|
80
|
-
var intersectLineLine = (a, b) => {
|
|
81
|
-
const det = cross(a.dir, b.dir);
|
|
82
|
-
if (Math.abs(det) < EPSILON) return void 0;
|
|
83
|
-
const dx = b.point[0] - a.point[0];
|
|
84
|
-
const dy = b.point[1] - a.point[1];
|
|
85
|
-
const t = (dx * b.dir[1] - dy * b.dir[0]) / det;
|
|
86
|
-
return [a.point[0] + a.dir[0] * t, a.point[1] + a.dir[1] * t];
|
|
87
|
-
};
|
|
88
|
-
/** 直线(point+dir)∩ 圆(center,radius),返回交点列(0/1/2 个) */
|
|
89
|
-
var intersectLineCircle = (line, circle) => {
|
|
90
|
-
const ox = line.point[0] - circle.center[0];
|
|
91
|
-
const oy = line.point[1] - circle.center[1];
|
|
92
|
-
const ux = line.dir[0];
|
|
93
|
-
const uy = line.dir[1];
|
|
94
|
-
const b = 2 * (ox * ux + oy * uy);
|
|
95
|
-
const c = ox * ox + oy * oy - circle.radius * circle.radius;
|
|
96
|
-
const disc = b * b - 4 * c;
|
|
97
|
-
if (disc < 0) return [];
|
|
98
|
-
const sq = Math.sqrt(disc);
|
|
99
|
-
const out = [];
|
|
100
|
-
for (const t of [(-b - sq) / 2, (-b + sq) / 2]) out.push([line.point[0] + ux * t, line.point[1] + uy * t]);
|
|
101
|
-
return out;
|
|
102
|
-
};
|
|
103
|
-
/** 圆 ∩ 圆,返回交点列(0/1/2 个) */
|
|
104
|
-
var intersectCircleCircle = (a, b) => {
|
|
105
|
-
const dx = b.center[0] - a.center[0];
|
|
106
|
-
const dy = b.center[1] - a.center[1];
|
|
107
|
-
const d = Math.hypot(dx, dy);
|
|
108
|
-
if (d < EPSILON || d > a.radius + b.radius + EPSILON || d < Math.abs(a.radius - b.radius) - EPSILON) return [];
|
|
109
|
-
const aa = (a.radius * a.radius - b.radius * b.radius + d * d) / (2 * d);
|
|
110
|
-
const h2 = a.radius * a.radius - aa * aa;
|
|
111
|
-
const h = h2 > 0 ? Math.sqrt(h2) : 0;
|
|
112
|
-
const mx = a.center[0] + aa * dx / d;
|
|
113
|
-
const my = a.center[1] + aa * dy / d;
|
|
114
|
-
const rx = -dy * h / d;
|
|
115
|
-
const ry = dx * h / d;
|
|
116
|
-
return [[mx + rx, my + ry], [mx - rx, my - ry]];
|
|
117
|
-
};
|
|
118
78
|
/** 点到直线(无限延长)的有符号垂足点 */
|
|
119
79
|
var footOnLine = (p, base, dir) => {
|
|
120
80
|
const t = (p[0] - base[0]) * dir[0] + (p[1] - base[1]) * dir[1];
|
|
@@ -139,11 +99,11 @@ var solveFillet = (segA, segB, r) => {
|
|
|
139
99
|
const candidates = [];
|
|
140
100
|
const pushIntersections = (oa, ob) => {
|
|
141
101
|
if (oa.kind === "line" && ob.kind === "line") {
|
|
142
|
-
const p =
|
|
102
|
+
const p = _retikz_math.intersect.lineLine(oa.point, [oa.point[0] + oa.dir[0], oa.point[1] + oa.dir[1]], ob.point, [ob.point[0] + ob.dir[0], ob.point[1] + ob.dir[1]]);
|
|
143
103
|
if (p) candidates.push(p);
|
|
144
|
-
} else if (oa.kind === "line" && ob.kind === "circle") candidates.push(...
|
|
145
|
-
else if (oa.kind === "circle" && ob.kind === "line") candidates.push(...
|
|
146
|
-
else if (oa.kind === "circle" && ob.kind === "circle") candidates.push(...
|
|
104
|
+
} else if (oa.kind === "line" && ob.kind === "circle") candidates.push(..._retikz_math.intersect.lineCircle(oa.point, oa.dir, ob.center, ob.radius));
|
|
105
|
+
else if (oa.kind === "circle" && ob.kind === "line") candidates.push(..._retikz_math.intersect.lineCircle(ob.point, ob.dir, oa.center, oa.radius));
|
|
106
|
+
else if (oa.kind === "circle" && ob.kind === "circle") candidates.push(..._retikz_math.intersect.circleCircle(oa.center, oa.radius, ob.center, ob.radius));
|
|
147
107
|
};
|
|
148
108
|
pushIntersections(offA, offB);
|
|
149
109
|
if (segA.kind === "arc") pushIntersections(offsetSegmentAlt(segA, radius), offB);
|
|
@@ -246,7 +206,7 @@ var tangentPointOn = (seg, filletCenter, radius) => {
|
|
|
246
206
|
let bestErr = Infinity;
|
|
247
207
|
for (const cand of candidates) {
|
|
248
208
|
const angle = Math.atan2(cand[1] - seg.center[1], cand[0] - seg.center[0]) * RAD_TO_DEG;
|
|
249
|
-
if (!
|
|
209
|
+
if (!(0, _retikz_math.arcAngleInRange)(seg.startAngle, seg.endAngle, angle, 1e-6)) continue;
|
|
250
210
|
const err = Math.abs(Math.hypot(cand[0] - filletCenter[0], cand[1] - filletCenter[1]) - radius);
|
|
251
211
|
if (err < bestErr) {
|
|
252
212
|
bestErr = err;
|
|
@@ -360,7 +320,7 @@ var alignSweep = (start, end, ccw) => {
|
|
|
360
320
|
*/
|
|
361
321
|
var boundaryFromContour = (segments, cornerRadius, rayOrigin, toward, fillets = filletContour(segments, cornerRadius)) => {
|
|
362
322
|
const dirRaw = [toward[0] - rayOrigin[0], toward[1] - rayOrigin[1]];
|
|
363
|
-
const dl =
|
|
323
|
+
const dl = _retikz_math.point.length(dirRaw);
|
|
364
324
|
if (dl < 1e-12) return void 0;
|
|
365
325
|
const dir = [dirRaw[0] / dl, dirRaw[1] / dl];
|
|
366
326
|
const n = segments.length;
|
|
@@ -379,7 +339,7 @@ var boundaryFromContour = (segments, cornerRadius, rayOrigin, toward, fillets =
|
|
|
379
339
|
};
|
|
380
340
|
const considerArc = (center, radius, startAngle, endAngle, ccw) => {
|
|
381
341
|
const aligned = alignSweep(startAngle, endAngle, ccw);
|
|
382
|
-
const hits =
|
|
342
|
+
const hits = (0, _retikz_math.rayArc)(rayOrigin, dir, center, radius, aligned.start, aligned.end);
|
|
383
343
|
for (const s of hits) if (s > 1e-9 && s < best) best = s;
|
|
384
344
|
};
|
|
385
345
|
if (fillets.length === 0) for (let i = 0; i < n; i++) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contour.d.ts","sourceRoot":"","sources":["../../../src/geometry/contour.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"contour.d.ts","sourceRoot":"","sources":["../../../src/geometry/contour.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAA0D,MAAM,cAAc,CAAC;AAkBrG,4BAA4B;AAC5B,MAAM,MAAM,WAAW,GAAG;IACxB,YAAY;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB;IAChB,IAAI,EAAE,QAAQ,CAAC;IACf,gBAAgB;IAChB,EAAE,EAAE,QAAQ,CAAC;CACd,CAAC;AAEF,oDAAoD;AACpD,MAAM,MAAM,UAAU,GAAG;IACvB,YAAY;IACZ,IAAI,EAAE,KAAK,CAAC;IACZ,gBAAgB;IAChB,MAAM,EAAE,QAAQ,CAAC;IACjB,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,6BAA6B;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,6BAA6B;AAC7B,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,UAAU,CAAC;AAEtD,qFAAqF;AACrF,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,QAAQ,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,QAAQ,CAAA;CAAE,GAC9B;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,MAAM,EAAE,QAAQ,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,GACD;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AA6BtB;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,kBAAkB;IAClB,cAAc,EAAE,QAAQ,CAAC;IACzB,kBAAkB;IAClB,eAAe,EAAE,QAAQ,CAAC;IAC1B,gBAAgB;IAChB,MAAM,EAAE,QAAQ,CAAC;IACjB,gBAAgB;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB;IACpB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,8BAA8B;IAC9B,aAAa,EAAE,OAAO,CAAC;CACxB,CAAC;AA8PF;;;GAGG;AACH,eAAO,MAAM,aAAa,GACxB,UAAU,KAAK,CAAC,cAAc,CAAC,EAC/B,eAAe,MAAM,KACpB,KAAK,CAAC,cAAc,CAUtB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAC1B,UAAU,KAAK,CAAC,cAAc,CAAC,EAC/B,eAAe,MAAM,EACrB,UAAS,KAAK,CAAC,cAAc,CAAyC,KACrE,KAAK,CAAC,cAAc,CAsCtB,CAAC;AA2BF,iEAAiE;AACjE,eAAO,MAAM,UAAU,GAAI,OAAO,MAAM,EAAE,KAAK,MAAM,EAAE,KAAK,OAAO,KAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAUjG,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAC9B,UAAU,KAAK,CAAC,cAAc,CAAC,EAC/B,cAAc,MAAM,GAAG,SAAS,EAChC,WAAW,QAAQ,EACnB,QAAQ,QAAQ,EAChB,UAAS,KAAK,CAAC,cAAc,CAAyC,KACrE,QAAQ,GAAG,SA0Eb,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_edge = require("./edge.cjs");
|
|
2
|
-
|
|
2
|
+
let _retikz_math = require("@retikz/math");
|
|
3
3
|
//#region src/geometry/diamond.ts
|
|
4
4
|
/** 每条 side 的过顶点折线三 anchor:[邻边中点, cardinal 顶点, 邻边中点](方向 north/south=西→东、east/west=北→南) */
|
|
5
5
|
var DIAMOND_EDGE = {
|
|
@@ -37,7 +37,7 @@ var diamond = {
|
|
|
37
37
|
/** 点是否在菱形内(含边界,含旋转);方程 |x|/halfA + |y|/halfB ≤ 1 */
|
|
38
38
|
contains: (d, p) => {
|
|
39
39
|
if (d.halfA === 0 || d.halfB === 0) return false;
|
|
40
|
-
const [lx, ly] =
|
|
40
|
+
const [lx, ly] = (0, _retikz_math.worldToLocal)(d, p);
|
|
41
41
|
return Math.abs(lx) / d.halfA + Math.abs(ly) / d.halfB <= 1.000000001;
|
|
42
42
|
},
|
|
43
43
|
/** 9 个 anchor:N/S/E/W=顶点,NE/NW/SE/SW=边中点,center=中心 */
|
|
@@ -75,7 +75,7 @@ var diamond = {
|
|
|
75
75
|
ly = d.halfB / 2;
|
|
76
76
|
break;
|
|
77
77
|
}
|
|
78
|
-
return
|
|
78
|
+
return (0, _retikz_math.localToWorld)(d, [lx, ly]);
|
|
79
79
|
},
|
|
80
80
|
/**
|
|
81
81
|
* 从中心向 toward 方向射线与菱形 4 边的交点
|
|
@@ -83,11 +83,11 @@ var diamond = {
|
|
|
83
83
|
*/
|
|
84
84
|
boundaryPoint: (d, toward) => {
|
|
85
85
|
if (d.halfA === 0 || d.halfB === 0) return [d.x, d.y];
|
|
86
|
-
const [lx, ly] =
|
|
86
|
+
const [lx, ly] = (0, _retikz_math.worldToLocal)(d, toward);
|
|
87
87
|
const denom = Math.abs(lx) / d.halfA + Math.abs(ly) / d.halfB;
|
|
88
88
|
if (denom === 0) return [d.x, d.y];
|
|
89
89
|
const t = 1 / denom;
|
|
90
|
-
return
|
|
90
|
+
return (0, _retikz_math.localToWorld)(d, [lx * t, ly * t]);
|
|
91
91
|
},
|
|
92
92
|
/** 边上比例点:side 过 cardinal 顶点的两段折线 t∈[0,1] 处(落真实斜边;含旋转) */
|
|
93
93
|
edgePoint: (d, side, t) => {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
let _retikz_math = require("@retikz/math");
|
|
1
2
|
//#region src/geometry/edge.ts
|
|
2
3
|
/**
|
|
3
4
|
* rect 四直边 t=0 / t=1 端点对应的角 anchor
|
|
@@ -10,8 +11,6 @@ var EDGE_ENDS = {
|
|
|
10
11
|
east: ["north-east", "south-east"],
|
|
11
12
|
west: ["north-west", "south-west"]
|
|
12
13
|
};
|
|
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
14
|
/**
|
|
16
15
|
* circle / ellipse 周长弧段:side 的局部参数角 θ(t),单位度
|
|
17
16
|
* @description 约定同 geometry 既有 `(cosθ, sinθ)` + y 轴向下 ⇒ east=0° / south=90° / west=180° / north=270°,
|
|
@@ -30,9 +29,8 @@ var edgeAngleDeg = (side, t) => {
|
|
|
30
29
|
* @description t∈[0,0.5] 走 p0→vertex、t∈[0.5,1] 走 vertex→p1;t=0.5 恰落 vertex。
|
|
31
30
|
* p0/p1 为相邻边中点 anchor、vertex 为 cardinal 顶点 anchor——全落真实斜边
|
|
32
31
|
*/
|
|
33
|
-
var polylineViaVertex = (p0, vertex, p1, t) => t <= .5 ?
|
|
32
|
+
var polylineViaVertex = (p0, vertex, p1, t) => t <= .5 ? (0, _retikz_math.lerp)(p0, vertex, t * 2) : (0, _retikz_math.lerp)(vertex, p1, (t - .5) * 2);
|
|
34
33
|
//#endregion
|
|
35
34
|
exports.EDGE_ENDS = EDGE_ENDS;
|
|
36
35
|
exports.edgeAngleDeg = edgeAngleDeg;
|
|
37
|
-
exports.lerpPoint = lerpPoint;
|
|
38
36
|
exports.polylineViaVertex = polylineViaVertex;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Position } from './point';
|
|
2
|
+
export { lerp as lerpPoint } from '@retikz/math';
|
|
2
3
|
/** 边上比例点 `{ side, t }` 的四个 side(north/south/east/west) */
|
|
3
4
|
export type Side = 'north' | 'south' | 'east' | 'west';
|
|
4
5
|
/**
|
|
@@ -12,8 +13,6 @@ export declare const EDGE_ENDS: {
|
|
|
12
13
|
readonly east: readonly ["north-east", "south-east"];
|
|
13
14
|
readonly west: readonly ["north-west", "south-west"];
|
|
14
15
|
};
|
|
15
|
-
/** 线性插值 a + (b − a)·t */
|
|
16
|
-
export declare const lerpPoint: (a: Position, b: Position, t: number) => Position;
|
|
17
16
|
/**
|
|
18
17
|
* circle / ellipse 周长弧段:side 的局部参数角 θ(t),单位度
|
|
19
18
|
* @description 约定同 geometry 既有 `(cosθ, sinθ)` + y 轴向下 ⇒ east=0° / south=90° / west=180° / north=270°,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edge.d.ts","sourceRoot":"","sources":["../../../src/geometry/edge.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"edge.d.ts","sourceRoot":"","sources":["../../../src/geometry/edge.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAExC,OAAO,EAAE,IAAI,IAAI,SAAS,EAAE,MAAM,cAAc,CAAC;AAEjD,0DAA0D;AAC1D,MAAM,MAAM,IAAI,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEvD;;;;GAIG;AACH,eAAO,MAAM,SAAS;;;;;CAK8D,CAAC;AAErF;;;;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,QAAkF,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_edge = require("./edge.cjs");
|
|
2
|
-
|
|
2
|
+
let _retikz_math = require("@retikz/math");
|
|
3
3
|
//#region src/geometry/ellipse.ts
|
|
4
4
|
var DEG_TO_RAD = Math.PI / 180;
|
|
5
5
|
var SQRT_HALF = Math.SQRT1_2;
|
|
@@ -10,7 +10,7 @@ var ellipse = {
|
|
|
10
10
|
/** 判断点是否在椭圆内(含边界,考虑旋转) */
|
|
11
11
|
contains: (e, p) => {
|
|
12
12
|
if (e.rx === 0 || e.ry === 0) return false;
|
|
13
|
-
const [lx, ly] =
|
|
13
|
+
const [lx, ly] = (0, _retikz_math.worldToLocal)(e, p);
|
|
14
14
|
return lx * lx / (e.rx * e.rx) + ly * ly / (e.ry * e.ry) <= 1;
|
|
15
15
|
},
|
|
16
16
|
/**
|
|
@@ -51,7 +51,7 @@ var ellipse = {
|
|
|
51
51
|
ly = e.ry * SQRT_HALF;
|
|
52
52
|
break;
|
|
53
53
|
}
|
|
54
|
-
return
|
|
54
|
+
return (0, _retikz_math.localToWorld)(e, [lx, ly]);
|
|
55
55
|
},
|
|
56
56
|
/**
|
|
57
57
|
* 从中心向 toward 方向射线与椭圆交点
|
|
@@ -59,17 +59,17 @@ var ellipse = {
|
|
|
59
59
|
*/
|
|
60
60
|
boundaryPoint: (e, toward) => {
|
|
61
61
|
if (e.rx === 0 || e.ry === 0) return [e.x, e.y];
|
|
62
|
-
const [lx, ly] =
|
|
62
|
+
const [lx, ly] = (0, _retikz_math.worldToLocal)(e, toward);
|
|
63
63
|
if (lx === 0 && ly === 0) return [e.x, e.y];
|
|
64
64
|
const a = lx / e.rx;
|
|
65
65
|
const b = ly / e.ry;
|
|
66
66
|
const t = 1 / Math.sqrt(a * a + b * b);
|
|
67
|
-
return
|
|
67
|
+
return (0, _retikz_math.localToWorld)(e, [lx * t, ly * t]);
|
|
68
68
|
},
|
|
69
69
|
/** 边上比例点:side 的 90° 周长弧段 t∈[0,1] 处(等角,落真实椭圆周;含旋转) */
|
|
70
70
|
edgePoint: (e, side, t) => {
|
|
71
71
|
const rad = require_edge.edgeAngleDeg(side, t) * DEG_TO_RAD;
|
|
72
|
-
return
|
|
72
|
+
return (0, _retikz_math.localToWorld)(e, [e.rx * Math.cos(rad), e.ry * Math.sin(rad)]);
|
|
73
73
|
}
|
|
74
74
|
};
|
|
75
75
|
//#endregion
|
|
@@ -6,7 +6,6 @@ export * from './ellipse';
|
|
|
6
6
|
export * from './diamond';
|
|
7
7
|
export * from './polar';
|
|
8
8
|
export * from './bend';
|
|
9
|
-
export * from './arc';
|
|
10
9
|
export * from './segment';
|
|
11
10
|
export * from './contour';
|
|
12
11
|
export { EDGE_ENDS, lerpPoint, edgeAngleDeg, polylineViaVertex } from './edge';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/geometry/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/geometry/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,QAAQ,CAAC;AAC/E,YAAY,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACzD,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -1,30 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
/** 笛卡尔坐标点 [x, y] */
|
|
3
|
-
export type Position = [number, number];
|
|
4
|
-
/** 二维向量 / 坐标的基础运算工具集 */
|
|
5
|
-
export declare const point: {
|
|
6
|
-
/** 向量加 a + b */
|
|
7
|
-
add: (a: Position, b: Position) => Position;
|
|
8
|
-
/** 向量减 a - b */
|
|
9
|
-
sub: (a: Position, b: Position) => Position;
|
|
10
|
-
/** 等比缩放 a * k */
|
|
11
|
-
scale: (a: Position, k: number) => Position;
|
|
12
|
-
/** 向量长度 */
|
|
13
|
-
length: (a: Position) => number;
|
|
14
|
-
/** 归一化向量;零长度 / 极短向量回退到 fallback */
|
|
15
|
-
normalize: (a: Position, fallback?: Position, epsilon?: number) => Position;
|
|
16
|
-
/** 把点 p 沿 target 方向移动 dist */
|
|
17
|
-
shiftToward: (p: Position, target: Position, dist: number) => Position;
|
|
18
|
-
/** 两点精确相等(不带容差) */
|
|
19
|
-
equal: (a: Position, b: Position) => boolean;
|
|
20
|
-
/** 笛卡尔 → 极坐标(angle ∈ (-180,180],origin 默认 [0,0]) */
|
|
21
|
-
toPolar: (p: Position) => PolarPosition;
|
|
22
|
-
/**
|
|
23
|
-
* 跨坐标系两点相同判断(笛卡尔或 PolarPosition)
|
|
24
|
-
* @description 极坐标先转笛卡尔再按 precision 四舍五入比较;polar.equal 委托到本方法
|
|
25
|
-
* @param precision 小数点后位数;默认 2
|
|
26
|
-
* @throws 当 PolarPosition.origin 是节点 id 字符串时(需 Scene 上下文)
|
|
27
|
-
*/
|
|
28
|
-
equalPolar: (a: Position | PolarPosition, b: Position | PolarPosition, precision?: number) => boolean;
|
|
29
|
-
};
|
|
1
|
+
export { type Position, point, DEFAULT_EPSILON } from '@retikz/math';
|
|
30
2
|
//# sourceMappingURL=point.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"point.d.ts","sourceRoot":"","sources":["../../../src/geometry/point.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"point.d.ts","sourceRoot":"","sources":["../../../src/geometry/point.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const require_point = require("./point.cjs");
|
|
2
1
|
//#region src/geometry/polar.ts
|
|
3
2
|
var DEG_TO_RAD = Math.PI / 180;
|
|
3
|
+
var RAD_TO_DEG = 180 / Math.PI;
|
|
4
4
|
/** 极坐标 ↔ 笛卡尔转换工具集(polar 不参与几何计算,参与时先 toPosition) */
|
|
5
5
|
var polar = {
|
|
6
6
|
/**
|
|
@@ -16,19 +16,27 @@ var polar = {
|
|
|
16
16
|
const rad = p.angle * DEG_TO_RAD;
|
|
17
17
|
return [origin[0] + Math.cos(rad) * p.radius, origin[1] + Math.sin(rad) * p.radius];
|
|
18
18
|
},
|
|
19
|
-
/** 笛卡尔 → 极坐标(
|
|
20
|
-
fromPosition: (p) =>
|
|
19
|
+
/** 笛卡尔 → 极坐标(angle ∈ (-180,180],origin 默认 [0,0]) */
|
|
20
|
+
fromPosition: (p) => ({
|
|
21
|
+
angle: Math.atan2(p[1], p[0]) * RAD_TO_DEG,
|
|
22
|
+
radius: Math.hypot(p[0], p[1])
|
|
23
|
+
}),
|
|
21
24
|
/** 在原点附近按极坐标偏移,返回结果点的世界笛卡尔坐标 */
|
|
22
25
|
offsetFrom: (origin, offset) => {
|
|
23
26
|
const rad = offset.angle * DEG_TO_RAD;
|
|
24
27
|
return [origin[0] + Math.cos(rad) * offset.radius, origin[1] + Math.sin(rad) * offset.radius];
|
|
25
28
|
},
|
|
26
29
|
/**
|
|
27
|
-
*
|
|
30
|
+
* 跨坐标系两点相同判断
|
|
28
31
|
* @description 极坐标先转笛卡尔再按 precision 四舍五入比较
|
|
29
32
|
* @param precision 小数点后位数;默认 2
|
|
30
33
|
*/
|
|
31
|
-
equal: (a, b, precision = 2) =>
|
|
34
|
+
equal: (a, b, precision = 2) => {
|
|
35
|
+
const aCart = Array.isArray(a) ? a : polar.toPosition(a);
|
|
36
|
+
const bCart = Array.isArray(b) ? b : polar.toPosition(b);
|
|
37
|
+
const factor = 10 ** precision;
|
|
38
|
+
return Math.round(aCart[0] * factor) === Math.round(bCart[0] * factor) && Math.round(aCart[1] * factor) === Math.round(bCart[1] * factor);
|
|
39
|
+
}
|
|
32
40
|
};
|
|
33
41
|
//#endregion
|
|
34
42
|
exports.polar = polar;
|
|
@@ -18,7 +18,7 @@ export declare const polar: {
|
|
|
18
18
|
* @description origin 为字符串(节点 id)时抛错——字符串解析依赖 Scene 编译器 nodeIndex
|
|
19
19
|
*/
|
|
20
20
|
toPosition: (p: PolarPosition) => Position;
|
|
21
|
-
/** 笛卡尔 → 极坐标(
|
|
21
|
+
/** 笛卡尔 → 极坐标(angle ∈ (-180,180],origin 默认 [0,0]) */
|
|
22
22
|
fromPosition: (p: Position) => PolarPosition;
|
|
23
23
|
/** 在原点附近按极坐标偏移,返回结果点的世界笛卡尔坐标 */
|
|
24
24
|
offsetFrom: (origin: Position, offset: {
|
|
@@ -26,7 +26,7 @@ export declare const polar: {
|
|
|
26
26
|
radius: number;
|
|
27
27
|
}) => Position;
|
|
28
28
|
/**
|
|
29
|
-
*
|
|
29
|
+
* 跨坐标系两点相同判断
|
|
30
30
|
* @description 极坐标先转笛卡尔再按 precision 四舍五入比较
|
|
31
31
|
* @param precision 小数点后位数;默认 2
|
|
32
32
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"polar.d.ts","sourceRoot":"","sources":["../../../src/geometry/polar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"polar.d.ts","sourceRoot":"","sources":["../../../src/geometry/polar.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AASxC;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,aAAa,CAAC;IAC3C,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAC;IACd,aAAa;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAKF,oDAAoD;AACpD,eAAO,MAAM,KAAK;IAChB;;;OAGG;oBACa,aAAa,KAAG,QAAQ;IAmBxC,oDAAoD;sBAClC,QAAQ,KAAG,aAAa;IAI1C,gCAAgC;yBAEtB,QAAQ,UACR;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,KACxC,QAAQ;IAOb;;;;OAIG;eAEI,QAAQ,GAAG,aAAa,KACxB,QAAQ,GAAG,aAAa,yBAE1B,OAAO;CASX,CAAC"}
|