@andespindola/brainlink 0.1.0-beta.108 → 0.1.0-beta.109
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/README.md +1 -0
- package/dist/application/frontend/client-js.js +37 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -603,6 +603,7 @@ The graph UI shows:
|
|
|
603
603
|
- adaptive CPU safeguards for large graphs: idle frame pacing, throttled background physics updates and cached viewport dimensions to reduce redraw/layout overhead while preserving interaction responsiveness
|
|
604
604
|
- hierarchical hot-path optimizations reduce per-frame allocations and repeated scans during layered cluster expansion and edge projection
|
|
605
605
|
- hierarchical edge projection now caches hub membership and node-to-cluster resolution per frame to keep large recursive subgraph rendering smooth during continuous zoom and pan
|
|
606
|
+
- hierarchical projection now uses stronger perspective yaw/pitch and depth-based render ordering so layered subgraphs read as a true 3D field instead of a flat expansion
|
|
606
607
|
- WebGL node and edge acceleration when supported, falling back to Canvas 2D without changing graph behavior
|
|
607
608
|
- compact macro-to-micro density progression so reset keeps the graph mass oriented and zoom-in separates local neighborhoods progressively
|
|
608
609
|
- graph camera treats hub-centered navigation as structural only when the hub is dominant; diffuse stress graphs reset and zoom around the full graph mass
|
|
@@ -35,6 +35,10 @@ const ecosystemDepthNear = 80
|
|
|
35
35
|
const ecosystemDepthFar = 2600
|
|
36
36
|
const ecosystemDepthPerspective = 620
|
|
37
37
|
const ecosystemDepthTiltY = 0.24
|
|
38
|
+
const ecosystemDepthYaw = 0.22
|
|
39
|
+
const ecosystemDepthPitch = 0.16
|
|
40
|
+
const ecosystemDepthRadialGain = 0.09
|
|
41
|
+
const ecosystemDepthOrbitalMaxOffset = 160
|
|
38
42
|
const ecosystemDepthMinScale = 0.24
|
|
39
43
|
const ecosystemDepthOpacityFloor = 0.2
|
|
40
44
|
const zoomRecoveryGuardMs = 4200
|
|
@@ -1207,12 +1211,23 @@ const ecosystemDepthForCluster = (cluster, levelIndexMap) => {
|
|
|
1207
1211
|
|
|
1208
1212
|
const projectEcosystemPoint = (x, y, depth, anchor) => {
|
|
1209
1213
|
const safeDepth = Math.max(0, depth)
|
|
1210
|
-
const
|
|
1211
|
-
const
|
|
1214
|
+
const dx = x - anchor.x
|
|
1215
|
+
const dy = y - anchor.y
|
|
1216
|
+
const yawSin = Math.sin(ecosystemDepthYaw)
|
|
1217
|
+
const yawCos = Math.cos(ecosystemDepthYaw)
|
|
1218
|
+
const pitchSin = Math.sin(ecosystemDepthPitch)
|
|
1219
|
+
const pitchCos = Math.cos(ecosystemDepthPitch)
|
|
1220
|
+
const rotatedX = dx * yawCos + safeDepth * yawSin
|
|
1221
|
+
const rotatedZ = Math.max(0, safeDepth * yawCos - dx * yawSin)
|
|
1222
|
+
const rotatedY = dy * pitchCos - rotatedZ * pitchSin
|
|
1223
|
+
const projectedDepth = Math.max(0, rotatedZ + Math.max(0, dy * pitchSin))
|
|
1224
|
+
const factor = ecosystemDepthPerspective / (ecosystemDepthPerspective + projectedDepth)
|
|
1225
|
+
const verticalTilt = projectedDepth * ecosystemDepthTiltY
|
|
1212
1226
|
return {
|
|
1213
|
-
x: anchor.x +
|
|
1214
|
-
y: anchor.y +
|
|
1215
|
-
factor
|
|
1227
|
+
x: anchor.x + rotatedX * factor,
|
|
1228
|
+
y: anchor.y + rotatedY * factor - verticalTilt,
|
|
1229
|
+
factor,
|
|
1230
|
+
projectedDepth
|
|
1216
1231
|
}
|
|
1217
1232
|
}
|
|
1218
1233
|
|
|
@@ -1223,7 +1238,13 @@ const applyEcosystemDepthProjection = (clusters, edges, anchor) => {
|
|
|
1223
1238
|
|
|
1224
1239
|
for (let index = 0; index < clusters.length; index += 1) {
|
|
1225
1240
|
const cluster = clusters[index]
|
|
1226
|
-
const
|
|
1241
|
+
const baseDepth = ecosystemDepthForCluster(cluster, levelIndexMap)
|
|
1242
|
+
const radialDistance = Math.hypot(cluster.x - anchor.x, cluster.y - anchor.y)
|
|
1243
|
+
const radialOffset = cluster.isHub ? 0 : Math.min(320, radialDistance * ecosystemDepthRadialGain)
|
|
1244
|
+
const orbitalOffset = cluster.isHub
|
|
1245
|
+
? 0
|
|
1246
|
+
: Math.sin(Math.atan2(cluster.y - anchor.y, cluster.x - anchor.x) * 2.2) * ecosystemDepthOrbitalMaxOffset
|
|
1247
|
+
const depth = Math.max(0, baseDepth + radialOffset + orbitalOffset)
|
|
1227
1248
|
const projected = projectEcosystemPoint(cluster.x, cluster.y, depth, anchor)
|
|
1228
1249
|
const baseOpacity = Number.isFinite(cluster.lodOpacity) ? cluster.lodOpacity : 1
|
|
1229
1250
|
const depthScale = ecosystemDepthMinScale + (1 - ecosystemDepthMinScale) * projected.factor
|
|
@@ -1236,7 +1257,7 @@ const applyEcosystemDepthProjection = (clusters, edges, anchor) => {
|
|
|
1236
1257
|
x: projected.x,
|
|
1237
1258
|
y: projected.y,
|
|
1238
1259
|
lodOpacity: baseOpacity * depthOpacity,
|
|
1239
|
-
depth,
|
|
1260
|
+
depth: projected.projectedDepth,
|
|
1240
1261
|
depthScale
|
|
1241
1262
|
}
|
|
1242
1263
|
projectedClusters.push(projectedCluster)
|
|
@@ -2981,6 +3002,9 @@ const clusterRadiusPx = cluster => {
|
|
|
2981
3002
|
const clusterOpacity = cluster =>
|
|
2982
3003
|
Math.max(0, Math.min(1, Number.isFinite(cluster.lodOpacity) ? cluster.lodOpacity : 1))
|
|
2983
3004
|
|
|
3005
|
+
const clusterDepth = cluster => Number.isFinite(cluster.depth) ? cluster.depth : ecosystemDepthNear
|
|
3006
|
+
const clusterDepthScale = cluster => Number.isFinite(cluster.depthScale) ? cluster.depthScale : 1
|
|
3007
|
+
|
|
2984
3008
|
const worldViewportBounds = () => {
|
|
2985
3009
|
const width = Math.max(state.viewport.width, 320)
|
|
2986
3010
|
const height = Math.max(state.viewport.height, 320)
|
|
@@ -3400,6 +3424,8 @@ const render = now => {
|
|
|
3400
3424
|
ctx.save()
|
|
3401
3425
|
ctx.translate(state.transform.x, state.transform.y)
|
|
3402
3426
|
ctx.scale(state.transform.scale, state.transform.scale)
|
|
3427
|
+
const orderedClusters = [...state.renderClusters]
|
|
3428
|
+
.sort((left, right) => clusterDepth(right) - clusterDepth(left))
|
|
3403
3429
|
const safeScale = Math.max(state.transform.scale, 0.0001)
|
|
3404
3430
|
if (state.renderClusterEdges.length > 0) {
|
|
3405
3431
|
for (let index = 0; index < state.renderClusterEdges.length; index += 1) {
|
|
@@ -3408,15 +3434,17 @@ const render = now => {
|
|
|
3408
3434
|
if (edgeOpacity <= 0.01) {
|
|
3409
3435
|
continue
|
|
3410
3436
|
}
|
|
3437
|
+
const depthScale = Math.min(clusterDepthScale(edge.sourceCluster), clusterDepthScale(edge.targetCluster))
|
|
3438
|
+
const widthScale = 0.6 + depthScale * 0.9
|
|
3411
3439
|
ctx.beginPath()
|
|
3412
3440
|
ctx.moveTo(edge.sourceCluster.x, edge.sourceCluster.y)
|
|
3413
3441
|
ctx.lineTo(edge.targetCluster.x, edge.targetCluster.y)
|
|
3414
|
-
ctx.lineWidth = 1.2 / safeScale
|
|
3442
|
+
ctx.lineWidth = (1.2 * widthScale) / safeScale
|
|
3415
3443
|
ctx.strokeStyle = 'rgba(153, 165, 181, ' + (edge.inferred ? 0.14 : 0.22) * edgeOpacity + ')'
|
|
3416
3444
|
ctx.stroke()
|
|
3417
3445
|
}
|
|
3418
3446
|
}
|
|
3419
|
-
|
|
3447
|
+
orderedClusters.forEach(cluster => {
|
|
3420
3448
|
const isMacro = cluster.id === 'macro-galaxy'
|
|
3421
3449
|
const isEcosystem = String(cluster.id).startsWith('ecosystem-')
|
|
3422
3450
|
const isHub = Boolean(cluster.isHub)
|
package/package.json
CHANGED