Carga
This commit is contained in:
2025-04-17 00:35:33 -06:00
parent 4977462629
commit 67fc72aed5
1333 changed files with 1077639 additions and 0 deletions

View File

@@ -0,0 +1,193 @@
/* *
*
* Networkgraph series
*
* (c) 2010-2021 Paweł Fus
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* */
'use strict';
/* *
*
* Functions
*
* */
/**
* Attractive force.
*
* In Verlet integration, force is applied on a node immidatelly to it's
* `plotX` and `plotY` position.
*
* @private
* @param {Highcharts.Point} link
* Link that connects two nodes
* @param {number} force
* Force calcualated in `repulsiveForceFunction`
* @param {Highcharts.PositionObject} distance
* Distance between two nodes e.g. `{x, y}`
*/
function attractive(link, force, distanceXY) {
var massFactor = link.getMass(), translatedX = -distanceXY.x * force * this.diffTemperature, translatedY = -distanceXY.y * force * this.diffTemperature;
if (!link.fromNode.fixedPosition) {
link.fromNode.plotX -=
translatedX * massFactor.fromNode / link.fromNode.degree;
link.fromNode.plotY -=
translatedY * massFactor.fromNode / link.fromNode.degree;
}
if (!link.toNode.fixedPosition) {
link.toNode.plotX +=
translatedX * massFactor.toNode / link.toNode.degree;
link.toNode.plotY +=
translatedY * massFactor.toNode / link.toNode.degree;
}
}
/**
* Attractive force funtion. Can be replaced by API's
* `layoutAlgorithm.attractiveForce`
*
* @private
* @param {number} d current distance between two nodes
* @param {number} k expected distance between two nodes
* @return {number} force
*/
function attractiveForceFunction(d, k) {
// Used in API:
return (k - d) / d;
}
/**
* Barycenter force. Calculate and applys barycenter forces on the
* nodes. Making them closer to the center of their barycenter point.
*
* In Verlet integration, force is applied on a node immidatelly to it's
* `plotX` and `plotY` position.
*
* @private
*/
function barycenter() {
var gravitationalConstant = this.options.gravitationalConstant, xFactor = this.barycenter.xFactor, yFactor = this.barycenter.yFactor;
// To consider:
xFactor = (xFactor - (this.box.left + this.box.width) / 2) *
gravitationalConstant;
yFactor = (yFactor - (this.box.top + this.box.height) / 2) *
gravitationalConstant;
this.nodes.forEach(function (node) {
if (!node.fixedPosition) {
node.plotX -=
xFactor / node.mass / node.degree;
node.plotY -=
yFactor / node.mass / node.degree;
}
});
}
/**
* Estiamte the best possible distance between two nodes, making graph
* readable.
* @private
*/
function getK(layout) {
return Math.pow(layout.box.width * layout.box.height / layout.nodes.length, 0.5);
}
/**
* Integration method.
*
* In Verlet integration, forces are applied on node immidatelly to it's
* `plotX` and `plotY` position.
*
* Verlet without velocity:
*
* x(n+1) = 2 * x(n) - x(n-1) + A(T) * deltaT ^ 2
*
* where:
* - x(n+1) - new position
* - x(n) - current position
* - x(n-1) - previous position
*
* Assuming A(t) = 0 (no acceleration) and (deltaT = 1) we get:
*
* x(n+1) = x(n) + (x(n) - x(n-1))
*
* where:
* - (x(n) - x(n-1)) - position change
*
* TO DO:
* Consider Verlet with velocity to support additional
* forces. Or even Time-Corrected Verlet by Jonathan
* "lonesock" Dummer
*
* @private
* @param {Highcharts.NetworkgraphLayout} layout layout object
* @param {Highcharts.Point} node node that should be translated
*/
function integrate(layout, node) {
var friction = -layout.options.friction, maxSpeed = layout.options.maxSpeed, prevX = node.prevX, prevY = node.prevY,
// Apply friciton:
diffX = ((node.plotX + node.dispX -
prevX) * friction), diffY = ((node.plotY + node.dispY -
prevY) * friction), abs = Math.abs, signX = abs(diffX) / (diffX || 1), // need to deal with 0
signY = abs(diffY) / (diffY || 1);
// Apply max speed:
diffX = signX * Math.min(maxSpeed, Math.abs(diffX));
diffY = signY * Math.min(maxSpeed, Math.abs(diffY));
// Store for the next iteration:
node.prevX = node.plotX + node.dispX;
node.prevY = node.plotY + node.dispY;
// Update positions:
node.plotX += diffX;
node.plotY += diffY;
node.temperature = layout.vectorLength({
x: diffX,
y: diffY
});
}
/**
* Repulsive force.
*
* In Verlet integration, force is applied on a node immidatelly to it's
* `plotX` and `plotY` position.
*
* @private
* @param {Highcharts.Point} node
* Node that should be translated by force.
* @param {number} force
* Force calcualated in `repulsiveForceFunction`
* @param {Highcharts.PositionObject} distance
* Distance between two nodes e.g. `{x, y}`
*/
function repulsive(node, force, distanceXY) {
var factor = force * this.diffTemperature / node.mass / node.degree;
if (!node.fixedPosition) {
node.plotX += distanceXY.x * factor;
node.plotY += distanceXY.y * factor;
}
}
/**
* Repulsive force funtion. Can be replaced by API's
* `layoutAlgorithm.repulsiveForce`
*
* @private
* @param {number} d current distance between two nodes
* @param {number} k expected distance between two nodes
* @return {number} force
*/
function repulsiveForceFunction(d, k) {
// Used in API:
return (k - d) / d * (k > d ? 1 : 0); // Force only for close nodes
}
/* *
*
* Default Export
*
* */
var VerletIntegration = {
attractive: attractive,
attractiveForceFunction: attractiveForceFunction,
barycenter: barycenter,
getK: getK,
integrate: integrate,
repulsive: repulsive,
repulsiveForceFunction: repulsiveForceFunction
};
export default VerletIntegration;