dsh-memory-engine 0.5.6 → 0.5.7
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/lib/render/layout.mjs +43 -4
- package/lib/render/render.mjs +8 -2
- package/package.json +1 -1
package/lib/render/layout.mjs
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
const SEED = 20261030;
|
|
2
|
+
|
|
1
3
|
export function layoutMemories(nodes) {
|
|
2
|
-
let seed =
|
|
4
|
+
let seed = SEED;
|
|
3
5
|
const random = () => ((seed = (seed * 16807) % 2147483647) - 1) / 2147483646;
|
|
4
6
|
function brainPoint(radiusScale) {
|
|
5
7
|
const radius = Math.pow(random(), 1 / 3) * radiusScale;
|
|
@@ -11,12 +13,49 @@ export function layoutMemories(nodes) {
|
|
|
11
13
|
z: radius * Math.sin(phi) * Math.sin(theta) * 0.78,
|
|
12
14
|
};
|
|
13
15
|
}
|
|
14
|
-
|
|
16
|
+
|
|
17
|
+
const placed = nodes.map((node) => {
|
|
15
18
|
const inner = ['人格', '印象', '知识'].includes(node.kind) || node.majorEmotion;
|
|
16
|
-
|
|
19
|
+
// 整体半径放大 1.35 倍:原来 298 个节点挤在一起,点谁都容易点错
|
|
20
|
+
const distance = (inner ? 14 + Math.pow(random(), 0.65) * 36 : 48 + Math.min(1, node.ageDays / 30) * 58 + random() * 12) * 1.35;
|
|
17
21
|
const baseRadius = node.majorEmotion ? 3.2 : inner
|
|
18
22
|
? (node.heat === 1 ? 2.4 : node.heat === 2 ? 1.8 : 1.3)
|
|
19
23
|
: (node.heat === 1 ? 2.1 : node.heat === 2 ? 1.5 : 1.0);
|
|
20
|
-
|
|
24
|
+
// 连接数加成收敛得更紧一点,避免枢纽节点长得过大压住邻居
|
|
25
|
+
return { ...node, pos: brainPoint(distance), radius: baseRadius + Math.min(1.1, Math.sqrt(node.degree) * 0.15) };
|
|
21
26
|
});
|
|
27
|
+
|
|
28
|
+
// ── 分离松弛:把互相重叠的节点推开 ──
|
|
29
|
+
// 不做这一步的话,随机落点会让相邻节点的圆重叠,视觉糊成一片,点击也分不清。
|
|
30
|
+
// 只在世界坐标里推开,不改 z 深度关系太多;迭代次数固定,保证同一份数据每次布局一致。
|
|
31
|
+
relax(placed, { iterations: 60, gap: 1.55, strength: 0.5 });
|
|
32
|
+
return placed;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function relax(items, { iterations, gap, strength }) {
|
|
36
|
+
if (items.length < 2) return;
|
|
37
|
+
for (let round = 0; round < iterations; round++) {
|
|
38
|
+
let moved = false;
|
|
39
|
+
for (let i = 0; i < items.length; i++) {
|
|
40
|
+
const a = items[i];
|
|
41
|
+
for (let j = i + 1; j < items.length; j++) {
|
|
42
|
+
const b = items[j];
|
|
43
|
+
const dx = b.pos.x - a.pos.x;
|
|
44
|
+
const dy = b.pos.y - a.pos.y;
|
|
45
|
+
const dz = b.pos.z - a.pos.z;
|
|
46
|
+
const dist = Math.hypot(dx, dy, dz) || 1e-6;
|
|
47
|
+
const minDist = (a.radius + b.radius) * gap;
|
|
48
|
+
if (dist >= minDist) continue;
|
|
49
|
+
// 单位向量;重合时用一个确定的、由索引决定的偏移方向,避免除零和随机抖动
|
|
50
|
+
const ux = dist > 1e-5 ? dx / dist : Math.cos(i * 2.39996);
|
|
51
|
+
const uy = dist > 1e-5 ? dy / dist : Math.sin(i * 2.39996);
|
|
52
|
+
const uz = dist > 1e-5 ? dz / dist : 0.35;
|
|
53
|
+
const push = (minDist - dist) * strength * 0.5;
|
|
54
|
+
a.pos.x -= ux * push; a.pos.y -= uy * push; a.pos.z -= uz * push;
|
|
55
|
+
b.pos.x += ux * push; b.pos.y += uy * push; b.pos.z += uz * push;
|
|
56
|
+
moved = true;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (!moved) break;
|
|
60
|
+
}
|
|
22
61
|
}
|
package/lib/render/render.mjs
CHANGED
|
@@ -121,11 +121,17 @@ function fire(id,now) {
|
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
function select(x,y) {
|
|
124
|
-
|
|
124
|
+
// 命中判定:先按「离光标最近的节点」选,而不是「第一个框住光标的节点」。
|
|
125
|
+
// 原来要求 值<该节点半径,小节点容易被邻居抢走 → 点错。
|
|
126
|
+
// 现在给每个节点一个最小容差,再用距离减去一点半径作为打分(同样近时偏向大的那个)。
|
|
127
|
+
let best=null,bestScore=Infinity;
|
|
125
128
|
for (const star of DATA.stars) {
|
|
126
129
|
if (!star._screen) continue;
|
|
127
130
|
const value=Math.hypot(star._screen.x-x,star._screen.y-y);
|
|
128
|
-
|
|
131
|
+
const tolerance=Math.max(14,star._screen.r*1.15);
|
|
132
|
+
if (value>tolerance) continue;
|
|
133
|
+
const score=value-star._screen.r*0.22;
|
|
134
|
+
if (score<bestScore) {bestScore=score;best=star;}
|
|
129
135
|
}
|
|
130
136
|
if (!best) return;
|
|
131
137
|
fire(best.id,performance.now());
|