@lv-x-software-house/x_view 1.4.0 → 1.4.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/index.js +118 -60
- package/dist/index.mjs +118 -60
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20823,6 +20823,7 @@ function XViewScene({
|
|
|
20823
20823
|
let sumY = 0;
|
|
20824
20824
|
let sumZ = 0;
|
|
20825
20825
|
let nodeCount = 0;
|
|
20826
|
+
let networkMaxRadius = 150;
|
|
20826
20827
|
activeNodeIds.forEach((id) => {
|
|
20827
20828
|
const mesh = nodeObjects[id];
|
|
20828
20829
|
if (mesh && mesh.material) {
|
|
@@ -20930,6 +20931,7 @@ function XViewScene({
|
|
|
20930
20931
|
const activeSet = new Set(activeNodeIds.map(String));
|
|
20931
20932
|
const edges = [];
|
|
20932
20933
|
const degreeMap = new Map(activeNodeIds.map((id) => [String(id), 0]));
|
|
20934
|
+
const adjMap = new Map(activeNodeIds.map((id) => [String(id), []]));
|
|
20933
20935
|
const seenPairs = /* @__PURE__ */ new Set();
|
|
20934
20936
|
[...allLinks, ...ancestryLinks].forEach((line) => {
|
|
20935
20937
|
var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2;
|
|
@@ -20946,55 +20948,104 @@ function XViewScene({
|
|
|
20946
20948
|
edges.push([u, v]);
|
|
20947
20949
|
degreeMap.set(u, (degreeMap.get(u) || 0) + 1);
|
|
20948
20950
|
degreeMap.set(v, (degreeMap.get(v) || 0) + 1);
|
|
20951
|
+
adjMap.get(u).push(v);
|
|
20952
|
+
adjMap.get(v).push(u);
|
|
20949
20953
|
}
|
|
20950
20954
|
}
|
|
20951
20955
|
});
|
|
20952
|
-
const
|
|
20953
|
-
|
|
20954
|
-
|
|
20955
|
-
const
|
|
20956
|
-
|
|
20957
|
-
(
|
|
20956
|
+
const hubCount = Array.from(degreeMap.values()).filter(
|
|
20957
|
+
(d) => d >= 3
|
|
20958
|
+
).length;
|
|
20959
|
+
const volumeRadius = Math.max(
|
|
20960
|
+
130,
|
|
20961
|
+
Math.cbrt(N) * 58 + Math.sqrt(N) * 24 + hubCount * 8
|
|
20958
20962
|
);
|
|
20963
|
+
const radiusX = volumeRadius * 1.45;
|
|
20964
|
+
const radiusY = volumeRadius * 1.15;
|
|
20965
|
+
const radiusZ = volumeRadius * 1.15;
|
|
20966
|
+
const connectedIds = activeNodeIds.map(String).filter((id) => (degreeMap.get(id) || 0) > 0).sort((a, b) => (degreeMap.get(b) || 0) - (degreeMap.get(a) || 0));
|
|
20967
|
+
const isolatedIds = activeNodeIds.map(String).filter((id) => (degreeMap.get(id) || 0) === 0);
|
|
20968
|
+
const interleavedIds = [];
|
|
20969
|
+
let cIdx = 0;
|
|
20970
|
+
let iIdx = 0;
|
|
20971
|
+
for (let k = 0; k < N; k++) {
|
|
20972
|
+
const takeConnected = cIdx < connectedIds.length && (iIdx >= isolatedIds.length || cIdx / Math.max(1, connectedIds.length) <= iIdx / Math.max(1, isolatedIds.length));
|
|
20973
|
+
if (takeConnected) {
|
|
20974
|
+
interleavedIds.push(connectedIds[cIdx++]);
|
|
20975
|
+
} else if (iIdx < isolatedIds.length) {
|
|
20976
|
+
interleavedIds.push(isolatedIds[iIdx++]);
|
|
20977
|
+
}
|
|
20978
|
+
}
|
|
20959
20979
|
const posMap = /* @__PURE__ */ new Map();
|
|
20980
|
+
const anchorMap = /* @__PURE__ */ new Map();
|
|
20960
20981
|
const velMap = /* @__PURE__ */ new Map();
|
|
20961
20982
|
const goldenAngle = Math.PI * (3 - Math.sqrt(5));
|
|
20962
|
-
|
|
20963
|
-
const t =
|
|
20964
|
-
const
|
|
20965
|
-
const
|
|
20966
|
-
const
|
|
20967
|
-
|
|
20968
|
-
|
|
20969
|
-
|
|
20970
|
-
|
|
20971
|
-
|
|
20972
|
-
|
|
20983
|
+
interleavedIds.forEach((id, idx) => {
|
|
20984
|
+
const t = (idx + 0.5) / Math.max(1, N);
|
|
20985
|
+
const yDir = 1 - 2 * t;
|
|
20986
|
+
const radiusAtY = Math.sqrt(Math.max(0, 1 - yDir * yDir));
|
|
20987
|
+
const theta = idx * goldenAngle;
|
|
20988
|
+
const xDir = Math.cos(theta) * radiusAtY;
|
|
20989
|
+
const zDir = Math.sin(theta) * radiusAtY;
|
|
20990
|
+
const shell = 0.3 + 0.7 * Math.cbrt(idx * 7 % Math.max(1, N) / Math.max(1, N));
|
|
20991
|
+
const px = xDir * shell * radiusX;
|
|
20992
|
+
const py = yDir * shell * radiusY;
|
|
20993
|
+
const pz = zDir * shell * radiusZ;
|
|
20994
|
+
posMap.set(id, { x: px, y: py, z: pz });
|
|
20995
|
+
anchorMap.set(id, { x: px, y: py, z: pz });
|
|
20996
|
+
velMap.set(id, { x: 0, y: 0, z: 0 });
|
|
20997
|
+
});
|
|
20998
|
+
connectedIds.forEach((id, idx) => {
|
|
20999
|
+
const deg = degreeMap.get(id) || 0;
|
|
21000
|
+
if (deg <= 2) {
|
|
21001
|
+
const neighbors = adjMap.get(id) || [];
|
|
21002
|
+
const hubNeighbor = neighbors.reduce(
|
|
21003
|
+
(best, curr) => (degreeMap.get(curr) || 0) > (degreeMap.get(best) || 0) ? curr : best,
|
|
21004
|
+
neighbors[0]
|
|
21005
|
+
);
|
|
21006
|
+
const hubPos = posMap.get(hubNeighbor);
|
|
21007
|
+
const myPos = posMap.get(id);
|
|
21008
|
+
if (hubPos && myPos && hubNeighbor !== id) {
|
|
21009
|
+
const phi = idx * goldenAngle * 3;
|
|
21010
|
+
const costheta = Math.cos(idx * 1.732);
|
|
21011
|
+
const sintheta = Math.sqrt(Math.max(0, 1 - costheta * costheta));
|
|
21012
|
+
const orbitDist = 62 + idx % 3 * 16;
|
|
21013
|
+
myPos.x = hubPos.x + sintheta * Math.cos(phi) * orbitDist;
|
|
21014
|
+
myPos.y = hubPos.y + sintheta * Math.sin(phi) * orbitDist;
|
|
21015
|
+
myPos.z = hubPos.z + costheta * orbitDist;
|
|
21016
|
+
}
|
|
21017
|
+
}
|
|
20973
21018
|
});
|
|
20974
|
-
const iterations =
|
|
20975
|
-
const minNodeDist =
|
|
20976
|
-
const
|
|
20977
|
-
const
|
|
21019
|
+
const iterations = 130;
|
|
21020
|
+
const minNodeDist = 56;
|
|
21021
|
+
const minHubDist = 140;
|
|
21022
|
+
const idealEdgeDist = 72;
|
|
21023
|
+
const repulsionRadius = 150;
|
|
20978
21024
|
for (let iter = 0; iter < iterations; iter++) {
|
|
20979
|
-
const cooling = 1 - iter / iterations * 0.
|
|
21025
|
+
const cooling = 1 - iter / iterations * 0.78;
|
|
20980
21026
|
for (let i = 0; i < N; i++) {
|
|
20981
|
-
const idA =
|
|
21027
|
+
const idA = interleavedIds[i];
|
|
20982
21028
|
const pA = posMap.get(idA);
|
|
20983
21029
|
const vA = velMap.get(idA);
|
|
21030
|
+
const degA = degreeMap.get(idA) || 0;
|
|
20984
21031
|
for (let j = i + 1; j < N; j++) {
|
|
20985
|
-
const idB =
|
|
21032
|
+
const idB = interleavedIds[j];
|
|
20986
21033
|
const pB = posMap.get(idB);
|
|
20987
21034
|
const vB = velMap.get(idB);
|
|
21035
|
+
const degB = degreeMap.get(idB) || 0;
|
|
20988
21036
|
const dx = pA.x - pB.x;
|
|
20989
21037
|
const dy = pA.y - pB.y;
|
|
20990
|
-
const dz =
|
|
20991
|
-
const
|
|
20992
|
-
const
|
|
20993
|
-
|
|
20994
|
-
|
|
21038
|
+
const dz = pA.z - pB.z;
|
|
21039
|
+
const dist = Math.sqrt(dx * dx + dy * dy + dz * dz + 0.1);
|
|
21040
|
+
const bothHubs = degA >= 3 && degB >= 3;
|
|
21041
|
+
const oneHub = degA >= 3 || degB >= 3;
|
|
21042
|
+
const effectiveMinDist = bothHubs ? minHubDist : oneHub ? minNodeDist * 1.35 : minNodeDist;
|
|
21043
|
+
const effectiveRepRadius = bothHubs ? repulsionRadius * 1.6 : repulsionRadius;
|
|
21044
|
+
if (dist < effectiveRepRadius) {
|
|
21045
|
+
const force = dist < effectiveMinDist ? (effectiveMinDist - dist) / dist * 2.4 : (effectiveRepRadius - dist) / effectiveRepRadius * 0.65 / dist;
|
|
20995
21046
|
const fx = dx * force;
|
|
20996
21047
|
const fy = dy * force;
|
|
20997
|
-
const fz =
|
|
21048
|
+
const fz = dz * force;
|
|
20998
21049
|
vA.x += fx;
|
|
20999
21050
|
vA.y += fy;
|
|
21000
21051
|
vA.z += fz;
|
|
@@ -21010,42 +21061,40 @@ function XViewScene({
|
|
|
21010
21061
|
const pV = posMap.get(v);
|
|
21011
21062
|
const vU = velMap.get(u);
|
|
21012
21063
|
const vV = velMap.get(v);
|
|
21064
|
+
const degU = degreeMap.get(u) || 1;
|
|
21065
|
+
const degV = degreeMap.get(v) || 1;
|
|
21013
21066
|
const dx = pV.x - pU.x;
|
|
21014
21067
|
const dy = pV.y - pU.y;
|
|
21015
21068
|
const dz = pV.z - pU.z;
|
|
21016
21069
|
const dist = Math.sqrt(dx * dx + dy * dy + dz * dz) || 1;
|
|
21017
21070
|
const delta = dist - idealEdgeDist;
|
|
21018
|
-
const
|
|
21071
|
+
const degreeDamping = 1 / Math.sqrt(degU + degV);
|
|
21072
|
+
const springStrength = 0.08 * degreeDamping;
|
|
21019
21073
|
const fx = dx / dist * delta * springStrength;
|
|
21020
21074
|
const fy = dy / dist * delta * springStrength;
|
|
21021
21075
|
const fz = dz / dist * delta * springStrength;
|
|
21022
|
-
|
|
21023
|
-
|
|
21024
|
-
vU.
|
|
21025
|
-
|
|
21026
|
-
|
|
21027
|
-
vV.
|
|
21076
|
+
const weightU = degV / (degU + degV);
|
|
21077
|
+
const weightV = degU / (degU + degV);
|
|
21078
|
+
vU.x += fx * weightU * 1.7;
|
|
21079
|
+
vU.y += fy * weightU * 1.7;
|
|
21080
|
+
vU.z += fz * weightU * 1.7;
|
|
21081
|
+
vV.x -= fx * weightV * 1.7;
|
|
21082
|
+
vV.y -= fy * weightV * 1.7;
|
|
21083
|
+
vV.z -= fz * weightV * 1.7;
|
|
21028
21084
|
}
|
|
21029
21085
|
for (let i = 0; i < N; i++) {
|
|
21030
|
-
const id =
|
|
21086
|
+
const id = interleavedIds[i];
|
|
21031
21087
|
const p = posMap.get(id);
|
|
21032
21088
|
const v = velMap.get(id);
|
|
21033
|
-
const
|
|
21034
|
-
const
|
|
21035
|
-
|
|
21036
|
-
|
|
21037
|
-
|
|
21038
|
-
|
|
21039
|
-
v.
|
|
21040
|
-
v.y -= ny * pull * 8;
|
|
21041
|
-
} else if (radialNorm < 0.2 && N > 12 && (degreeMap.get(id) || 0) === 0) {
|
|
21042
|
-
v.x += (nx || 0.1) * 1.5;
|
|
21043
|
-
v.y += (ny || 0.1) * 1.5;
|
|
21044
|
-
}
|
|
21045
|
-
if (Math.abs(nz) > 0.95) {
|
|
21046
|
-
v.z -= nz * (Math.abs(nz) - 0.95) * 10;
|
|
21089
|
+
const anchor = anchorMap.get(id);
|
|
21090
|
+
const deg = degreeMap.get(id) || 0;
|
|
21091
|
+
if (deg === 0 || deg >= 3) {
|
|
21092
|
+
const anchorPull = deg === 0 ? 0.055 : 0.035;
|
|
21093
|
+
v.x += (anchor.x - p.x) * anchorPull;
|
|
21094
|
+
v.y += (anchor.y - p.y) * anchorPull;
|
|
21095
|
+
v.z += (anchor.z - p.z) * anchorPull;
|
|
21047
21096
|
}
|
|
21048
|
-
const maxStep =
|
|
21097
|
+
const maxStep = 10 * cooling;
|
|
21049
21098
|
const speed = Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z) || 1;
|
|
21050
21099
|
const scale = speed > maxStep ? maxStep / speed : cooling;
|
|
21051
21100
|
p.x += v.x * scale;
|
|
@@ -21077,6 +21126,20 @@ function XViewScene({
|
|
|
21077
21126
|
sumZ += target.z;
|
|
21078
21127
|
nodeCount++;
|
|
21079
21128
|
});
|
|
21129
|
+
if (nodeCount > 0) {
|
|
21130
|
+
const cx = sumX / nodeCount;
|
|
21131
|
+
const cy = sumY / nodeCount;
|
|
21132
|
+
const cz = sumZ / nodeCount;
|
|
21133
|
+
let maxDist = 120;
|
|
21134
|
+
activeNodeIds.forEach((id) => {
|
|
21135
|
+
const p = posMap.get(String(id));
|
|
21136
|
+
if (p) {
|
|
21137
|
+
const d = Math.hypot(p.x - cx, p.y - cy, p.z - cz);
|
|
21138
|
+
if (d > maxDist) maxDist = d;
|
|
21139
|
+
}
|
|
21140
|
+
});
|
|
21141
|
+
networkMaxRadius = maxDist;
|
|
21142
|
+
}
|
|
21080
21143
|
}
|
|
21081
21144
|
if (nodeCount > 0) {
|
|
21082
21145
|
const centerX = sumX / nodeCount;
|
|
@@ -21095,13 +21158,8 @@ function XViewScene({
|
|
|
21095
21158
|
const radius = Math.max(80, nodeCount * 8);
|
|
21096
21159
|
zoomZ = radius * 2.5;
|
|
21097
21160
|
} else if (type === "Network") {
|
|
21098
|
-
|
|
21099
|
-
|
|
21100
|
-
0.52,
|
|
21101
|
-
1.15 - Math.min(nodeCount, 120) * 52e-4
|
|
21102
|
-
);
|
|
21103
|
-
zoomZ = targetFocus.z + Math.max(55, baseSpread * immersionFactor);
|
|
21104
|
-
camOffsetY = -baseSpread * 0.08;
|
|
21161
|
+
zoomZ = targetFocus.z + Math.max(220, networkMaxRadius * 1.85);
|
|
21162
|
+
camOffsetY = networkMaxRadius * 0.12;
|
|
21105
21163
|
}
|
|
21106
21164
|
const camTween = new import_tween2.Tween(camera.position).to(
|
|
21107
21165
|
{
|
package/dist/index.mjs
CHANGED
|
@@ -20925,6 +20925,7 @@ function XViewScene({
|
|
|
20925
20925
|
let sumY = 0;
|
|
20926
20926
|
let sumZ = 0;
|
|
20927
20927
|
let nodeCount = 0;
|
|
20928
|
+
let networkMaxRadius = 150;
|
|
20928
20929
|
activeNodeIds.forEach((id) => {
|
|
20929
20930
|
const mesh = nodeObjects[id];
|
|
20930
20931
|
if (mesh && mesh.material) {
|
|
@@ -21032,6 +21033,7 @@ function XViewScene({
|
|
|
21032
21033
|
const activeSet = new Set(activeNodeIds.map(String));
|
|
21033
21034
|
const edges = [];
|
|
21034
21035
|
const degreeMap = new Map(activeNodeIds.map((id) => [String(id), 0]));
|
|
21036
|
+
const adjMap = new Map(activeNodeIds.map((id) => [String(id), []]));
|
|
21035
21037
|
const seenPairs = /* @__PURE__ */ new Set();
|
|
21036
21038
|
[...allLinks, ...ancestryLinks].forEach((line) => {
|
|
21037
21039
|
var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2;
|
|
@@ -21048,55 +21050,104 @@ function XViewScene({
|
|
|
21048
21050
|
edges.push([u, v]);
|
|
21049
21051
|
degreeMap.set(u, (degreeMap.get(u) || 0) + 1);
|
|
21050
21052
|
degreeMap.set(v, (degreeMap.get(v) || 0) + 1);
|
|
21053
|
+
adjMap.get(u).push(v);
|
|
21054
|
+
adjMap.get(v).push(u);
|
|
21051
21055
|
}
|
|
21052
21056
|
}
|
|
21053
21057
|
});
|
|
21054
|
-
const
|
|
21055
|
-
|
|
21056
|
-
|
|
21057
|
-
const
|
|
21058
|
-
|
|
21059
|
-
(
|
|
21058
|
+
const hubCount = Array.from(degreeMap.values()).filter(
|
|
21059
|
+
(d) => d >= 3
|
|
21060
|
+
).length;
|
|
21061
|
+
const volumeRadius = Math.max(
|
|
21062
|
+
130,
|
|
21063
|
+
Math.cbrt(N) * 58 + Math.sqrt(N) * 24 + hubCount * 8
|
|
21060
21064
|
);
|
|
21065
|
+
const radiusX = volumeRadius * 1.45;
|
|
21066
|
+
const radiusY = volumeRadius * 1.15;
|
|
21067
|
+
const radiusZ = volumeRadius * 1.15;
|
|
21068
|
+
const connectedIds = activeNodeIds.map(String).filter((id) => (degreeMap.get(id) || 0) > 0).sort((a, b) => (degreeMap.get(b) || 0) - (degreeMap.get(a) || 0));
|
|
21069
|
+
const isolatedIds = activeNodeIds.map(String).filter((id) => (degreeMap.get(id) || 0) === 0);
|
|
21070
|
+
const interleavedIds = [];
|
|
21071
|
+
let cIdx = 0;
|
|
21072
|
+
let iIdx = 0;
|
|
21073
|
+
for (let k = 0; k < N; k++) {
|
|
21074
|
+
const takeConnected = cIdx < connectedIds.length && (iIdx >= isolatedIds.length || cIdx / Math.max(1, connectedIds.length) <= iIdx / Math.max(1, isolatedIds.length));
|
|
21075
|
+
if (takeConnected) {
|
|
21076
|
+
interleavedIds.push(connectedIds[cIdx++]);
|
|
21077
|
+
} else if (iIdx < isolatedIds.length) {
|
|
21078
|
+
interleavedIds.push(isolatedIds[iIdx++]);
|
|
21079
|
+
}
|
|
21080
|
+
}
|
|
21061
21081
|
const posMap = /* @__PURE__ */ new Map();
|
|
21082
|
+
const anchorMap = /* @__PURE__ */ new Map();
|
|
21062
21083
|
const velMap = /* @__PURE__ */ new Map();
|
|
21063
21084
|
const goldenAngle = Math.PI * (3 - Math.sqrt(5));
|
|
21064
|
-
|
|
21065
|
-
const t =
|
|
21066
|
-
const
|
|
21067
|
-
const
|
|
21068
|
-
const
|
|
21069
|
-
|
|
21070
|
-
|
|
21071
|
-
|
|
21072
|
-
|
|
21073
|
-
|
|
21074
|
-
|
|
21085
|
+
interleavedIds.forEach((id, idx) => {
|
|
21086
|
+
const t = (idx + 0.5) / Math.max(1, N);
|
|
21087
|
+
const yDir = 1 - 2 * t;
|
|
21088
|
+
const radiusAtY = Math.sqrt(Math.max(0, 1 - yDir * yDir));
|
|
21089
|
+
const theta = idx * goldenAngle;
|
|
21090
|
+
const xDir = Math.cos(theta) * radiusAtY;
|
|
21091
|
+
const zDir = Math.sin(theta) * radiusAtY;
|
|
21092
|
+
const shell = 0.3 + 0.7 * Math.cbrt(idx * 7 % Math.max(1, N) / Math.max(1, N));
|
|
21093
|
+
const px = xDir * shell * radiusX;
|
|
21094
|
+
const py = yDir * shell * radiusY;
|
|
21095
|
+
const pz = zDir * shell * radiusZ;
|
|
21096
|
+
posMap.set(id, { x: px, y: py, z: pz });
|
|
21097
|
+
anchorMap.set(id, { x: px, y: py, z: pz });
|
|
21098
|
+
velMap.set(id, { x: 0, y: 0, z: 0 });
|
|
21099
|
+
});
|
|
21100
|
+
connectedIds.forEach((id, idx) => {
|
|
21101
|
+
const deg = degreeMap.get(id) || 0;
|
|
21102
|
+
if (deg <= 2) {
|
|
21103
|
+
const neighbors = adjMap.get(id) || [];
|
|
21104
|
+
const hubNeighbor = neighbors.reduce(
|
|
21105
|
+
(best, curr) => (degreeMap.get(curr) || 0) > (degreeMap.get(best) || 0) ? curr : best,
|
|
21106
|
+
neighbors[0]
|
|
21107
|
+
);
|
|
21108
|
+
const hubPos = posMap.get(hubNeighbor);
|
|
21109
|
+
const myPos = posMap.get(id);
|
|
21110
|
+
if (hubPos && myPos && hubNeighbor !== id) {
|
|
21111
|
+
const phi = idx * goldenAngle * 3;
|
|
21112
|
+
const costheta = Math.cos(idx * 1.732);
|
|
21113
|
+
const sintheta = Math.sqrt(Math.max(0, 1 - costheta * costheta));
|
|
21114
|
+
const orbitDist = 62 + idx % 3 * 16;
|
|
21115
|
+
myPos.x = hubPos.x + sintheta * Math.cos(phi) * orbitDist;
|
|
21116
|
+
myPos.y = hubPos.y + sintheta * Math.sin(phi) * orbitDist;
|
|
21117
|
+
myPos.z = hubPos.z + costheta * orbitDist;
|
|
21118
|
+
}
|
|
21119
|
+
}
|
|
21075
21120
|
});
|
|
21076
|
-
const iterations =
|
|
21077
|
-
const minNodeDist =
|
|
21078
|
-
const
|
|
21079
|
-
const
|
|
21121
|
+
const iterations = 130;
|
|
21122
|
+
const minNodeDist = 56;
|
|
21123
|
+
const minHubDist = 140;
|
|
21124
|
+
const idealEdgeDist = 72;
|
|
21125
|
+
const repulsionRadius = 150;
|
|
21080
21126
|
for (let iter = 0; iter < iterations; iter++) {
|
|
21081
|
-
const cooling = 1 - iter / iterations * 0.
|
|
21127
|
+
const cooling = 1 - iter / iterations * 0.78;
|
|
21082
21128
|
for (let i = 0; i < N; i++) {
|
|
21083
|
-
const idA =
|
|
21129
|
+
const idA = interleavedIds[i];
|
|
21084
21130
|
const pA = posMap.get(idA);
|
|
21085
21131
|
const vA = velMap.get(idA);
|
|
21132
|
+
const degA = degreeMap.get(idA) || 0;
|
|
21086
21133
|
for (let j = i + 1; j < N; j++) {
|
|
21087
|
-
const idB =
|
|
21134
|
+
const idB = interleavedIds[j];
|
|
21088
21135
|
const pB = posMap.get(idB);
|
|
21089
21136
|
const vB = velMap.get(idB);
|
|
21137
|
+
const degB = degreeMap.get(idB) || 0;
|
|
21090
21138
|
const dx = pA.x - pB.x;
|
|
21091
21139
|
const dy = pA.y - pB.y;
|
|
21092
|
-
const dz =
|
|
21093
|
-
const
|
|
21094
|
-
const
|
|
21095
|
-
|
|
21096
|
-
|
|
21140
|
+
const dz = pA.z - pB.z;
|
|
21141
|
+
const dist = Math.sqrt(dx * dx + dy * dy + dz * dz + 0.1);
|
|
21142
|
+
const bothHubs = degA >= 3 && degB >= 3;
|
|
21143
|
+
const oneHub = degA >= 3 || degB >= 3;
|
|
21144
|
+
const effectiveMinDist = bothHubs ? minHubDist : oneHub ? minNodeDist * 1.35 : minNodeDist;
|
|
21145
|
+
const effectiveRepRadius = bothHubs ? repulsionRadius * 1.6 : repulsionRadius;
|
|
21146
|
+
if (dist < effectiveRepRadius) {
|
|
21147
|
+
const force = dist < effectiveMinDist ? (effectiveMinDist - dist) / dist * 2.4 : (effectiveRepRadius - dist) / effectiveRepRadius * 0.65 / dist;
|
|
21097
21148
|
const fx = dx * force;
|
|
21098
21149
|
const fy = dy * force;
|
|
21099
|
-
const fz =
|
|
21150
|
+
const fz = dz * force;
|
|
21100
21151
|
vA.x += fx;
|
|
21101
21152
|
vA.y += fy;
|
|
21102
21153
|
vA.z += fz;
|
|
@@ -21112,42 +21163,40 @@ function XViewScene({
|
|
|
21112
21163
|
const pV = posMap.get(v);
|
|
21113
21164
|
const vU = velMap.get(u);
|
|
21114
21165
|
const vV = velMap.get(v);
|
|
21166
|
+
const degU = degreeMap.get(u) || 1;
|
|
21167
|
+
const degV = degreeMap.get(v) || 1;
|
|
21115
21168
|
const dx = pV.x - pU.x;
|
|
21116
21169
|
const dy = pV.y - pU.y;
|
|
21117
21170
|
const dz = pV.z - pU.z;
|
|
21118
21171
|
const dist = Math.sqrt(dx * dx + dy * dy + dz * dz) || 1;
|
|
21119
21172
|
const delta = dist - idealEdgeDist;
|
|
21120
|
-
const
|
|
21173
|
+
const degreeDamping = 1 / Math.sqrt(degU + degV);
|
|
21174
|
+
const springStrength = 0.08 * degreeDamping;
|
|
21121
21175
|
const fx = dx / dist * delta * springStrength;
|
|
21122
21176
|
const fy = dy / dist * delta * springStrength;
|
|
21123
21177
|
const fz = dz / dist * delta * springStrength;
|
|
21124
|
-
|
|
21125
|
-
|
|
21126
|
-
vU.
|
|
21127
|
-
|
|
21128
|
-
|
|
21129
|
-
vV.
|
|
21178
|
+
const weightU = degV / (degU + degV);
|
|
21179
|
+
const weightV = degU / (degU + degV);
|
|
21180
|
+
vU.x += fx * weightU * 1.7;
|
|
21181
|
+
vU.y += fy * weightU * 1.7;
|
|
21182
|
+
vU.z += fz * weightU * 1.7;
|
|
21183
|
+
vV.x -= fx * weightV * 1.7;
|
|
21184
|
+
vV.y -= fy * weightV * 1.7;
|
|
21185
|
+
vV.z -= fz * weightV * 1.7;
|
|
21130
21186
|
}
|
|
21131
21187
|
for (let i = 0; i < N; i++) {
|
|
21132
|
-
const id =
|
|
21188
|
+
const id = interleavedIds[i];
|
|
21133
21189
|
const p = posMap.get(id);
|
|
21134
21190
|
const v = velMap.get(id);
|
|
21135
|
-
const
|
|
21136
|
-
const
|
|
21137
|
-
|
|
21138
|
-
|
|
21139
|
-
|
|
21140
|
-
|
|
21141
|
-
v.
|
|
21142
|
-
v.y -= ny * pull * 8;
|
|
21143
|
-
} else if (radialNorm < 0.2 && N > 12 && (degreeMap.get(id) || 0) === 0) {
|
|
21144
|
-
v.x += (nx || 0.1) * 1.5;
|
|
21145
|
-
v.y += (ny || 0.1) * 1.5;
|
|
21146
|
-
}
|
|
21147
|
-
if (Math.abs(nz) > 0.95) {
|
|
21148
|
-
v.z -= nz * (Math.abs(nz) - 0.95) * 10;
|
|
21191
|
+
const anchor = anchorMap.get(id);
|
|
21192
|
+
const deg = degreeMap.get(id) || 0;
|
|
21193
|
+
if (deg === 0 || deg >= 3) {
|
|
21194
|
+
const anchorPull = deg === 0 ? 0.055 : 0.035;
|
|
21195
|
+
v.x += (anchor.x - p.x) * anchorPull;
|
|
21196
|
+
v.y += (anchor.y - p.y) * anchorPull;
|
|
21197
|
+
v.z += (anchor.z - p.z) * anchorPull;
|
|
21149
21198
|
}
|
|
21150
|
-
const maxStep =
|
|
21199
|
+
const maxStep = 10 * cooling;
|
|
21151
21200
|
const speed = Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z) || 1;
|
|
21152
21201
|
const scale = speed > maxStep ? maxStep / speed : cooling;
|
|
21153
21202
|
p.x += v.x * scale;
|
|
@@ -21179,6 +21228,20 @@ function XViewScene({
|
|
|
21179
21228
|
sumZ += target.z;
|
|
21180
21229
|
nodeCount++;
|
|
21181
21230
|
});
|
|
21231
|
+
if (nodeCount > 0) {
|
|
21232
|
+
const cx = sumX / nodeCount;
|
|
21233
|
+
const cy = sumY / nodeCount;
|
|
21234
|
+
const cz = sumZ / nodeCount;
|
|
21235
|
+
let maxDist = 120;
|
|
21236
|
+
activeNodeIds.forEach((id) => {
|
|
21237
|
+
const p = posMap.get(String(id));
|
|
21238
|
+
if (p) {
|
|
21239
|
+
const d = Math.hypot(p.x - cx, p.y - cy, p.z - cz);
|
|
21240
|
+
if (d > maxDist) maxDist = d;
|
|
21241
|
+
}
|
|
21242
|
+
});
|
|
21243
|
+
networkMaxRadius = maxDist;
|
|
21244
|
+
}
|
|
21182
21245
|
}
|
|
21183
21246
|
if (nodeCount > 0) {
|
|
21184
21247
|
const centerX = sumX / nodeCount;
|
|
@@ -21197,13 +21260,8 @@ function XViewScene({
|
|
|
21197
21260
|
const radius = Math.max(80, nodeCount * 8);
|
|
21198
21261
|
zoomZ = radius * 2.5;
|
|
21199
21262
|
} else if (type === "Network") {
|
|
21200
|
-
|
|
21201
|
-
|
|
21202
|
-
0.52,
|
|
21203
|
-
1.15 - Math.min(nodeCount, 120) * 52e-4
|
|
21204
|
-
);
|
|
21205
|
-
zoomZ = targetFocus.z + Math.max(55, baseSpread * immersionFactor);
|
|
21206
|
-
camOffsetY = -baseSpread * 0.08;
|
|
21263
|
+
zoomZ = targetFocus.z + Math.max(220, networkMaxRadius * 1.85);
|
|
21264
|
+
camOffsetY = networkMaxRadius * 0.12;
|
|
21207
21265
|
}
|
|
21208
21266
|
const camTween = new Tween2(camera.position).to(
|
|
21209
21267
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lv-x-software-house/x_view",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "Pacote privado contendo os componentes e lógica de renderização 3D do X View.",
|
|
5
5
|
"author": "iv.x - Engenharia de Software - ivxsoftwarehouse@gmail.com",
|
|
6
6
|
"license": "UNLICENSED",
|