/// <summary> /// Positions the nodes /// </summary> /// <param name="isAnimated">Indicates whether or not the layout should be animated</param> /// <param name="graphComponents">The object containing the graph data</param> /// <param name="rootNode">Root node</param> public void ComputeLayout(bool isAnimated, GraphComponents graphComponents, INode rootNode) { nodeVMs = graphComponents.GetNodeViewModels().Where(node => !node.IsHidden).ToArray(); positions = new Point[nodeVMs.Length]; edgeCounts = new int[nodeVMs.Length]; nodeIDToIndex = new Dictionary <string, int>(); for (int i = 0; i < nodeVMs.Length; i++) { // Save this nodes position positions[i] = nodeVMs[i].Position; if (nodeVMs[i] is PartitionNode) { nodeIDToIndex[(nodeVMs[i] as PartitionNode).ID] = i; } else { nodeIDToIndex[(nodeVMs[i] as NodeViewModelBase).ParentNode.ID] = i; } // Get a count of all the edges for this node //testcount += GraphComponents.GetNumberOfEdges(nodeVMs[i].ParentNode); List <INodeShape> visitedNeighbors = new List <INodeShape>(); Model.INode currentNode = null; if (nodeVMs[i] is PartitionNode) { currentNode = nodeVMs[i] as Model.INode; } else { currentNode = (nodeVMs[i] as NodeViewModelBase).ParentNode; } // Loop over all the edges for this node foreach (Model.IEdge edge in graphComponents.GetEdges(currentNode)) { // Get the node at the opposite end of this edge INodeShape oppositeNode = graphComponents.GetOppositeNode(edge, currentNode); // Ensure that this edge is not a similarity edge and that // the opposite node has not been visited already if (!(edge is Model.SimilarityDataEdge) && !visitedNeighbors.Contains(oppositeNode)) { edgeCounts[i]++; visitedNeighbors.Add(oppositeNode); } } } // Old version is doing this next call asynchronously if (nodeVMs.Length > 1) { CalculatePositions(graphComponents); } }
/// <summary>Converts a RomanticWeb's <see cref="Node"/> into dotNetRDF's <see cref="VDS.RDF.INode"/>.</summary> public static VDS.RDF.INode UnWrapNode(this Model.INode node, INodeFactory nodeFactory) { if (node.IsUri) { return(nodeFactory.CreateUriNode(node.Uri)); } if (node.IsLiteral) { if (node.Language != null) { return(nodeFactory.CreateLiteralNode(node.Literal, node.Language)); } if (node.DataType != null) { return(nodeFactory.CreateLiteralNode(node.Literal, node.DataType)); } return(nodeFactory.CreateLiteralNode(node.Literal)); } return(nodeFactory.CreateBlankNode(node.BlankNode)); }
protected void CalculatePositions(GraphComponents graphComponents) { double deltaNorm; double otherNorm; bool converged = false; double T = K; double tolerance = 0.02; double coolingConstant = 0.99; Point tempDelta = new Point(); Point displacement = new Point(); TimeSpan globalForceTimespan = new TimeSpan(); TimeSpan localForceTimespan = new TimeSpan(); TimeSpan indexOfTime = new TimeSpan(); DateTime start; Model.INode currentNode = null; List <int> listOfAllNodeIndices = new List <int>(); // If we aren't partitioning into grids then use all the nodes every time if (!useGraphPartitioning) { for (int i = 0; i < nodeVMs.Length; i++) { listOfAllNodeIndices.Add(i); } } for (int loop = 0; loop < maxIterations && !converged; loop++) { double max = 200; double min = 65; double R = max - ((loop / maxIterations) * (max - min) + min); if (useGraphPartitioning) { // Put all vertices into appropraite cells CalculateNodeCells(R); } converged = true; // Loop over nodes for (int currentNodeIndex = 0; currentNodeIndex < nodeVMs.Length; currentNodeIndex++) { if (nodeVMs[currentNodeIndex] is PartitionNode) { currentNode = nodeVMs[currentNodeIndex] as Model.INode; } else { currentNode = (nodeVMs[currentNodeIndex] as NodeViewModelBase).ParentNode; } displacement = new Point(0, 0); // global repulsive force (huh??) start = DateTime.Now; IList <int> repulsionNodes = null; if (useGraphPartitioning) { // Find all nodes, within a certain distance, to perform repulstion on. // Get nodes within maxDistance from this node. double maxDistance = 50; //TODO: MAKE THIS CONFIGURABLE repulsionNodes = FindNodesForRepulsion(currentNodeIndex, R, maxDistance); } else { // Just repulse all nodes repulsionNodes = listOfAllNodeIndices; } // Loop over all nodes in repulsion list foreach (int i in repulsionNodes) { // We skip this calculation for the current node if (i != currentNodeIndex) { tempDelta.X = positions[i].X - positions[currentNodeIndex].X; tempDelta.Y = positions[i].Y - positions[currentNodeIndex].Y; if (tempDelta.X == 0) { tempDelta.X = random.NextDouble() * .001 * K; } if (tempDelta.Y == 0) { tempDelta.Y = random.NextDouble() * .001 * K; } deltaNorm = Math.Max(1, Math.Abs(tempDelta.X) + Math.Abs(tempDelta.Y)); otherNorm = Math.Abs(positions[i].X + Math.Abs(positions[i].Y)); double globalForce = GlobalForce(deltaNorm, otherNorm); displacement.X += (tempDelta.X / deltaNorm) * globalForce; displacement.Y += (tempDelta.Y / deltaNorm) * globalForce; } } globalForceTimespan += (DateTime.Now - start); // Local forces start = DateTime.Now; // Loop over all the edges for this node foreach (Model.IEdge edge in graphComponents.GetEdges(currentNode)) { DateTime startIndex = DateTime.Now; int index = -1; string nodeID = string.Empty; INodeShape oppositeNode = graphComponents.GetOppositeNode(edge, currentNode); //NodeViewModelBase oppositeNodeVM = GraphComponents.GetOppositeNode(edgeVM.ParentEdge, nodeVMs[currentNode].ParentNode); // Get the ID for the opposite node. How we do this depends // on the type of node that we are dealing with. if (oppositeNode is PartitionNode) { nodeID = (oppositeNode as PartitionNode).ID; } else { nodeID = (oppositeNode as NodeViewModelBase).ParentNode.ID; } if (!nodeIDToIndex.TryGetValue(nodeID, out index)) { continue; } indexOfTime += DateTime.Now - startIndex; if (index != -1) { tempDelta = new Point(positions[index].X - positions[currentNodeIndex].X, positions[index].Y - positions[currentNodeIndex].Y); if (tempDelta.X == 0) { tempDelta.X = random.NextDouble() * .001 * K; } if (tempDelta.Y == 0) { tempDelta.Y = random.NextDouble() * .001 * K; } deltaNorm = Math.Max(Math.Sqrt((tempDelta.X * tempDelta.X) + (tempDelta.Y * tempDelta.Y)), 1); otherNorm = Math.Max(Math.Sqrt((oppositeNode.Position.X * oppositeNode.Position.X) + (oppositeNode.Position.Y * oppositeNode.Position.Y)), 1); double localForce = LocalForce(deltaNorm, edgeCounts[currentNodeIndex], edge, graphComponents); displacement.X += (tempDelta.X / deltaNorm) * localForce; displacement.Y += (tempDelta.Y / deltaNorm) * localForce; } } localForceTimespan += (DateTime.Now - start); // Reposition node (huh??) if (displacement.X == 0) { displacement.X = 1; } double displacementNorm = Math.Sqrt((displacement.X * displacement.X) + (displacement.Y * displacement.Y)); double newX = positions[currentNodeIndex].X + (displacement.X / displacementNorm) * Math.Min(T, displacementNorm); double newY = positions[currentNodeIndex].Y + (displacement.Y / displacementNorm) * Math.Min(T, displacementNorm); tempDelta = new Point(newX - positions[currentNodeIndex].X, newY - positions[currentNodeIndex].Y); positions[currentNodeIndex].X = newX; positions[currentNodeIndex].Y = newY; // no clue what this is doing if (Math.Sqrt((tempDelta.X * tempDelta.X) + (tempDelta.Y * tempDelta.Y)) > K * tolerance) { converged = false; } } // cool (huh??) T *= coolingConstant; } //System.Diagnostics.Debug.WriteLine(globalForceTimespan); //System.Diagnostics.Debug.WriteLine(localForceTimespan); //System.Diagnostics.Debug.WriteLine(indexOfTime); }