mirror of
https://github.com/UnickSoft/graphonline.git
synced 2025-07-01 15:26:12 +00:00
176 lines
5.1 KiB
JavaScript
176 lines
5.1 KiB
JavaScript
/**
|
|
* Algorithm for reorder graph.
|
|
*
|
|
*/
|
|
function GraphReorder(graph, app)
|
|
{
|
|
BaseAlgorithm.apply(this, arguments);
|
|
if (graph != null)
|
|
{
|
|
this.edges = graph.edges;
|
|
this.vertices = graph.vertices;
|
|
}
|
|
}
|
|
|
|
|
|
// inheritance.
|
|
GraphReorder.prototype = Object.create(BaseAlgorithm.prototype);
|
|
|
|
|
|
GraphReorder.prototype.getName = function(local)
|
|
{
|
|
return g_GraphReorder; //local == "ru" ? "Упорядочить граф" : "Arrange the graph";
|
|
}
|
|
|
|
GraphReorder.prototype.getId = function()
|
|
{
|
|
return "OlegSh.GraphReorder";
|
|
}
|
|
|
|
// @return message for user.
|
|
GraphReorder.prototype.getMessage = function(local)
|
|
{
|
|
return g_done;
|
|
}
|
|
|
|
GraphReorder.prototype.result = function(resultCallback)
|
|
{
|
|
var result = {};
|
|
result["version"] = 1;
|
|
|
|
if (this.vertices.length == 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
var velocityDamping = 0.85;
|
|
var diameter = (new VertexModel()).diameter;
|
|
var maxDistance = diameter * 3;
|
|
var gravityDistanceSqr = 10 * (maxDistance * maxDistance);
|
|
var edgeGravityKof = 10 / (maxDistance);
|
|
var kCenterForce = 10 / (maxDistance * 10);
|
|
//var centerPoint = viewportSize.multiply(0.5);
|
|
var velocityMax = maxDistance * 10;
|
|
|
|
var centerPoint = new Point();
|
|
for(i = 0; i < this.vertices.length; i++) // loop through vertices
|
|
{
|
|
centerPoint.add(this.vertices[i].position);
|
|
}
|
|
centerPoint.multiply(1.0 / this.vertices.length);
|
|
|
|
var edgesMatrix = {};
|
|
for (var i = 0; i < this.edges.length; i++)
|
|
{
|
|
edgesMatrix[this.edges[i].vertex1.id + this.edges[i].vertex2.id * 1000] = 1;
|
|
edgesMatrix[this.edges[i].vertex2.id + this.edges[i].vertex1.id * 1000] = 1;
|
|
}
|
|
|
|
var k = 0;
|
|
var bChanged = true;
|
|
while (k < 1000 && bChanged)
|
|
{
|
|
var vertexData = [];
|
|
for(i = 0; i < this.vertices.length; i++) // loop through vertices
|
|
{
|
|
// Has no in newVertices.
|
|
var currentVertex = {};
|
|
currentVertex.object = this.vertices[i];
|
|
currentVertex.net_force = new Point (0, 0);
|
|
currentVertex.velocity = new Point (0, 0);
|
|
vertexData.push(currentVertex);
|
|
|
|
for(j = 0; j < this.vertices.length; j++) // loop through other vertices
|
|
{
|
|
otherVertex = this.vertices[j];
|
|
|
|
if (otherVertex == currentVertex.object) continue;
|
|
|
|
// squared distance between "u" and "v" in 2D space
|
|
var rsq = currentVertex.object.position.distanceSqr(otherVertex.position);
|
|
|
|
{
|
|
// counting the repulsion between two vertices
|
|
var force = (currentVertex.object.position.subtract(otherVertex.position)).normalize(gravityDistanceSqr / rsq);
|
|
currentVertex.net_force = currentVertex.net_force.add(force);
|
|
}
|
|
}
|
|
|
|
for(j = 0; j < this.vertices.length; j++) // loop through edges
|
|
{
|
|
otherVertex = this.vertices[j];
|
|
if (edgesMatrix.hasOwnProperty(currentVertex.object.id + 1000 * otherVertex.id))
|
|
{
|
|
var distance = currentVertex.object.position.distance(otherVertex.position);
|
|
|
|
if (distance > maxDistance)
|
|
{
|
|
// countin the attraction
|
|
var force = (otherVertex.position.subtract(currentVertex.object.position)).normalize(edgeGravityKof * (distance - maxDistance));
|
|
currentVertex.net_force = currentVertex.net_force.add(force);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Calculate force to center of world.
|
|
var distanceToCenter = centerPoint.distance(currentVertex.object.position);
|
|
var force = centerPoint.subtract(currentVertex.object.position).normalize(distanceToCenter * kCenterForce);
|
|
currentVertex.net_force = currentVertex.net_force.add(force);
|
|
|
|
// counting the velocity (with damping 0.85)
|
|
currentVertex.velocity = currentVertex.velocity.add(currentVertex.net_force);
|
|
}
|
|
|
|
bChanged = false;
|
|
|
|
for(i = 0; i < vertexData.length; i++) // set new positions
|
|
{
|
|
var v = vertexData[i];
|
|
var velocity = v.velocity;
|
|
if (velocity.length() > velocityMax)
|
|
{
|
|
velocity = velocity.normalize(velocityMax);
|
|
}
|
|
v.object.position = v.object.position.add(velocity);
|
|
if (velocity.length() >= 1)
|
|
{
|
|
bChanged = true;
|
|
}
|
|
}
|
|
k++;
|
|
}
|
|
|
|
|
|
this.app.OnAutoAdjustViewport();
|
|
this.app.SetHandlerMode("default");
|
|
// Looks like somthing going wrong and will use circle algorithm for reposition.
|
|
//var bbox = this.getGraphBBox();
|
|
|
|
return result;
|
|
}
|
|
|
|
GraphReorder.prototype.getObjectSelectedGroup = function(object)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
GraphReorder.prototype.getPriority = function()
|
|
{
|
|
return -8.5;
|
|
}
|
|
|
|
// Algorithm support multi graph
|
|
GraphReorder.prototype.IsSupportMultiGraph = function()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// Factory for connected components.
|
|
function CreateAlgorithmGraphReorder(graph, app)
|
|
{
|
|
return new GraphReorder(graph, app)
|
|
}
|
|
|
|
// Gerister connected component.
|
|
RegisterAlgorithm (CreateAlgorithmGraphReorder);
|