private void ShiftNode(GraphNode node, ShiftTo shiftType, bool opposite) { float sign = 1.0f; if (opposite) sign = -1.0f; switch (shiftType) { case ShiftTo.Up: node.Bounds = new RectangleF( node.Bounds.X, node.Bounds.Y - sign * _moveValue, node.Bounds.Width, node.Bounds.Height); break; case ShiftTo.Down: node.Bounds = new RectangleF( node.Bounds.X, node.Bounds.Y + sign * _moveValue, node.Bounds.Width, node.Bounds.Height); break; case ShiftTo.Left: node.Bounds = new RectangleF( node.Bounds.X - sign * _moveValue, node.Bounds.Y, node.Bounds.Width, node.Bounds.Height); break; case ShiftTo.Right: node.Bounds = new RectangleF( node.Bounds.X + sign * _moveValue, node.Bounds.Y, node.Bounds.Width, node.Bounds.Height); break; case ShiftTo.UpLeft: node.Bounds = new RectangleF( node.Bounds.X - sign * _moveValue, node.Bounds.Y - sign * _moveValue, node.Bounds.Width, node.Bounds.Height); break; case ShiftTo.UpRight: node.Bounds = new RectangleF( node.Bounds.X + sign * _moveValue, node.Bounds.Y - sign * _moveValue, node.Bounds.Width, node.Bounds.Height); break; case ShiftTo.DownLeft: node.Bounds = new RectangleF( node.Bounds.X - sign * _moveValue, node.Bounds.Y + sign * _moveValue, node.Bounds.Width, node.Bounds.Height); break; case ShiftTo.DownRight: node.Bounds = new RectangleF( node.Bounds.X + sign * _moveValue, node.Bounds.Y + sign * _moveValue, node.Bounds.Width, node.Bounds.Height); break; } }
private float EvaluateGrid(GraphNode[,] grid, int maxShift) { ApplyGrid(grid); float eval = 0; // Total arrow length; shorter arrow mean nodes are closer // so we would like that sum to be minimal foreach (GraphLink link in _graph.Links) { Point gridPos1 = (Point)link.Origin.GetData(_GridPos); Point gridPos2 = (Point)link.Destination.GetData(_GridPos); int dx = Math.Abs(gridPos1.X - gridPos2.X); int dy = Math.Abs(gridPos1.Y - gridPos2.Y); if (dx + dy > 1) eval += (dx * dx + dy * dy); } // Nodeta koito ne sa svurzani da im davame poveche tochki ako // sa blizki (znachi ne ni kefjat; zelta e da sa po-malko tochkite) foreach (GraphNode node in _graph.Nodes) { Point gridPos = (Point)node.GetData(_GridPos); int col = gridPos.X; int row = gridPos.Y; float toadd = 0; for (int k = -1; k <= +1; k++) { for (int l = -1; l <= +1; l++) { if (k == 0 && l == 0) continue; if ((k + l) % 2 == 0) continue; int neighborCol = col + k; int neighborRow = row + l; GraphNode neighbor = grid[1 + neighborCol, 1 + neighborRow]; if (neighbor == null) continue; if (!NodesLinked(node, neighbor)) toadd += 1.0f; } } eval += toadd; } return eval; }
private void ApplyGrid(GraphNode[,] grid) { for (int i = 0; i < _gridWidth; ++i) { for (int j = 0; j < _gridHeight; ++j) { GraphNode node = grid[1 + i, 1 + j]; if (node != null) node.SetData(_GridPos, new Point(i, j)); } } }
private GraphNode[,] InitGrid() { int nodeCount = _graph.Nodes.Count; _gridWidth = _gridHeight = (int)Math.Ceiling(Math.Sqrt(nodeCount)) + 2; GraphNode[,] grid = new GraphNode[_gridWidth + 2, _gridHeight + 2]; GraphNode node0 = _backbone[0] as GraphNode; node0.SetData(_GridPos, new Point(0, 0)); grid[1, 1] = node0; int perRow = Math.Max(1, _backbone.Count / _gridHeight + 1); int curRow = 0; float curCol = 0; int c = 0; for (int i = 0; i < _backbone.Count - 1; i++) { int nodeCol = (int)curCol + c; int nodeRow = curRow; GraphNode node = _backbone[i] as GraphNode; node.SetData(_GridPos, new Point(nodeCol, nodeRow)); grid[1 + nodeCol, 1 + nodeRow] = node; c++; if (c == perRow) { c = 0; curCol += ((float)_gridWidth - perRow) / _gridHeight; curRow++; } } c = 0; for (int i = 0; i < nodeCount; i++) { int nodeCol = i % _gridHeight; int nodeRow = i / _gridHeight; if (grid[1 + nodeCol, 1 + nodeRow] != null) continue; while (c < nodeCount && _backbone.Contains(_graph.Nodes[c])) c++; if (c == nodeCount) break; GraphNode node = _graph.Nodes[c] as GraphNode; node.SetData(_GridPos, new Point(nodeCol, nodeRow)); grid[1 + nodeCol, 1 + nodeRow] = node; if (c == nodeCount - 1) break; c++; } GraphNode nodeN = _backbone[_backbone.Count - 1] as GraphNode; nodeN.SetData(_GridPos, new Point(_gridWidth - 1, _gridHeight - 1)); grid[1 + _gridWidth - 1, 1 + _gridHeight - 1] = nodeN; return grid; }
Size CalcLinkDir(GraphNode node) { int xEval = 0, yEval = 0; Point gridPos1 = (Point)node.GetData(_GridPos); foreach (GraphLink link in node.OutLinks) { Point gridPos2 = (Point)link.Destination.GetData(_GridPos); xEval += gridPos2.X - gridPos1.X; yEval += gridPos2.Y - gridPos1.Y; } foreach (GraphLink link in node.InLinks) { Point gridPos2 = (Point)link.Origin.GetData(_GridPos); xEval += gridPos2.X - gridPos1.X; yEval += gridPos2.Y - gridPos1.Y; } if (xEval > 0) xEval = 1; if (xEval < 0) xEval = -1; if (yEval > 0) yEval = 1; if (yEval < 0) yEval = -1; return new Size(xEval, yEval); }
private bool MoveLeft(GraphNode node, ArrayList layer, double priority) { int index = layer.IndexOf(node); if (index == 0) { // This is the last node in the layer - // so we can move to the left without troubles node.SetData(_GridPosition, (double)node.GetData(_GridPosition) - 0.5); return true; } GraphNode leftNode = layer[index - 1] as GraphNode; double leftNodePriority = ((double)leftNode.GetData(_UPriority) + (double)leftNode.GetData(_DPriority)) / 2; // Check if there is space // between the left and the current node if ((double)leftNode.GetData(_GridPosition) < (double)node.GetData(_GridPosition) - 1) { node.SetData(_GridPosition, (double)node.GetData(_GridPosition) - 0.5); return true; } // We have reached a node with higher priority - // no movement is allowed if (leftNodePriority > priority || Math.Abs(leftNodePriority - priority) < double.Epsilon) return false; // The left node has lower priority - try to move it if (MoveLeft(leftNode, layer, priority)) { node.SetData(_GridPosition, (double)node.GetData(_GridPosition) - 0.5); return true; } return false; }
private void Dummify() { ArrayList links = new ArrayList(_graph.Links); foreach (GraphLink link in links) { GraphNode o = link.Origin; GraphNode d = link.Destination; int oLayer = (int)o.GetData(_Layer); int dLayer = (int)d.GetData(_Layer); double oPos = (double)o.GetData(_GridPosition); double dPos = (double)d.GetData(_GridPosition); double step = (dPos - oPos) / Math.Abs(dLayer - oLayer); GraphNode p = o; if (oLayer - dLayer > 1) { for (int i = oLayer - 1; i > dLayer; i--) { GraphNode newNode = new GraphNode(o.Bounds); ArrayList layer = _layers[i] as ArrayList; double pos = (i - dLayer) * step + oPos; if (pos > layer.Count) pos = layer.Count; // Check if origin and dest are both last if (oPos >= (_layers[oLayer] as ArrayList).Count - 1 && dPos >= (_layers[dLayer] as ArrayList).Count - 1) pos = layer.Count; // Check if origin and destination are both first else if (oPos == 0 && dPos == 0) pos = 0; newNode.SetData(_Layer, i); newNode.SetData(_UBaryCenter, 0.0); newNode.SetData(_DBaryCenter, 0.0); newNode.SetData(_ULinkCount, 0); newNode.SetData(_DLinkCount, 0); newNode.SetData(_GridPosition, pos); newNode.SetData(_Dummy, true); layer.Insert((int)pos, newNode); // Translate rightwards nodes' positions for (int r = (int)pos + 1; r < layer.Count; r++) { GraphNode node = layer[r] as GraphNode; node.SetData(_GridPosition, (double)node.GetData(_GridPosition) + 1); } GraphLink newLink = new GraphLink(p, newNode); newLink.SetData(_DummificationLevel, 0); p = newNode; // Add the new node and the new link to the graph _graph.Nodes.Add(newNode); _graph.Links.Add(newLink); } // Set the origin of the real arrow to the last dummy link.Origin = p; link.SetData(_DummificationLevel, oLayer - dLayer - 1); } if (oLayer - dLayer < -1) { for (int i = oLayer + 1; i < dLayer; i++) { GraphNode newNode = new GraphNode(o.Bounds); ArrayList layer = _layers[i] as ArrayList; double pos = (i - oLayer) * step + oPos; if (pos > layer.Count) pos = layer.Count; // Check if origin and dest are both last if (oPos >= (_layers[oLayer] as ArrayList).Count - 1 && dPos >= (_layers[dLayer] as ArrayList).Count - 1) pos = layer.Count; // Check if origin and destination are both first else if (oPos == 0 && dPos == 0) pos = 0; newNode.SetData(_Layer, i); newNode.SetData(_UBaryCenter, 0.0); newNode.SetData(_DBaryCenter, 0.0); newNode.SetData(_ULinkCount, 0); newNode.SetData(_DLinkCount, 0); newNode.SetData(_GridPosition, pos); newNode.SetData(_Dummy, true); layer.Insert((int)pos, newNode); // Translate rightwards nodes' positions for (int r = (int)pos + 1; r < layer.Count; r++) { GraphNode node = layer[r] as GraphNode; node.SetData(_GridPosition, (double)node.GetData(_GridPosition) + 1); } GraphLink newLink = new GraphLink(p, newNode); newLink.SetData(_DummificationLevel, 0); p = newNode; // Add the new node and the new link to the graph _graph.Nodes.Add(newNode); _graph.Links.Add(newLink); } // Set the origin of the real arrow to the last dummy link.Origin = p; link.SetData(_DummificationLevel, dLayer - oLayer - 1); } } }
private double evalEdgeCrossingsCost(GraphNode node) { int crossingCount = 0; foreach (GraphLink link in node.InLinks) if (link.Origin != link.Destination) crossingCount += countCrossings(link); foreach (GraphLink link in node.OutLinks) if (link.Origin != link.Destination) crossingCount += countCrossings(link); return _info.CrossingEdgesCost * crossingCount; }
private double evalCost(GraphNode node) { return evalDistributionCost(node) + evalBoundaryCost(node) + evalEdgeLengthsCost(node) + evalEdgeCrossingsCost(node); }
private double evalBoundaryCost(GraphNode node) { double l, t, r, b; l = node.Center.X - _drawingArea.Left; t = node.Center.Y - _drawingArea.Top; r = _drawingArea.Right - node.Center.X; b = _drawingArea.Bottom - node.Center.Y; return _info.BoundaryFactor * (1 / (r * r) + 1 / (l * l) + 1 / (t * t) + 1 / (b * b)); }
private double evalEdgeLengthsCost(GraphNode node) { double sum = 0.0f; foreach (GraphLink link in node.InLinks) if (link.Origin != link.Destination) sum += squareDistance(link.Origin, link.Destination); foreach (GraphLink link in node.OutLinks) if (link.Origin != link.Destination) sum += squareDistance(link.Origin, link.Destination); return _info.EdgeLengthFactor * sum; }
private double evalDistributionCost(GraphNode node) { double sum = 0.0f; for (int i = 0; i < _nodes.Length; i++) { if (node == _nodes[i]) continue; double distance = squareDistance(_nodes[i], node); if (distance == 0) distance = 0.00001f; sum += _info.DistributionFactor / distance; } return sum; }
private bool nodeInBounds(GraphNode node) { double l, t, r, b; l = node.Center.X - _drawingArea.Left; t = node.Center.Y - _drawingArea.Top; r = _drawingArea.Right - node.Center.X; b = _drawingArea.Bottom - node.Center.Y; return !(r < 0 || t < 0 || l < 0 || b < 0); }
private double squareDistance(GraphNode node1, GraphNode node2) { PointF p1 = node1.Center; PointF p2 = node2.Center; return Math.Max(0, (p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y) - Math.Pow(lengthFix(node1, node2), 2)); }
private void RollbackMove(GraphNode node) { _glBordLinesCost = _glBordLinesCost + (double)node.GetData(BordLines) - _bordNewLocalValue; }
private double evalTuningCost(GraphNode node) { return evalCost(node) + nodeEdgeDistance(); }
/// <summary> /// Calculates the barycenter of a node. /// </summary> internal static double CalcBaryCenter(GraphNode node) { int uLinkCount = (int)node.GetData(_ULinkCount); int dLinkCount = (int)node.GetData(_DLinkCount); double uBaryCenter = (double)node.GetData(_UBaryCenter); double dBaryCenter = (double)node.GetData(_DBaryCenter); if (uLinkCount > 0 && dLinkCount > 0) return (uBaryCenter + dBaryCenter) / 2; if (uLinkCount > 0) return uBaryCenter; if (dLinkCount > 0) return dBaryCenter; return 0; }
private double CostFunction(GraphNode node) { CalcNewGlobalCost(node); return NodeDistribution() + _glBordLinesCost + EdgeLengths() + EdgeCrossings(); }
private void AddChildren(GraphNode node) { ArrayList next = new ArrayList(); foreach (GraphLink link in node.OutLinks) { GraphNode child = link.Destination; int nodeLayer = (int)node.GetData(_Layer); int childLayer = (int)child.GetData(_Layer); if (childLayer == -1 && nodeLayer < _layers.Count - 1) { child.SetData(_Layer, nodeLayer + 1); (_layers[nodeLayer + 1] as ArrayList).Add(child); next.Add(child); } else if (childLayer == -1) { _layers.Add(new ArrayList()); child.SetData(_Layer, nodeLayer + 1); (_layers[nodeLayer] as ArrayList).Add(child); next.Add(child); } } foreach (GraphLink link in node.InLinks) { GraphNode child = link.Origin; int nodeLayer = (int)node.GetData(_Layer); int childLayer = (int)child.GetData(_Layer); if (childLayer == -1 && nodeLayer > 0) { child.SetData(_Layer, nodeLayer - 1); (_layers[nodeLayer - 1] as ArrayList).Add(child); next.Add(child); } else if (childLayer == -1) { child.SetData(_Layer, 0); (_layers[0] as ArrayList).Add(child); next.Add(child); } } foreach (GraphNode child in next) AddChildren(child); }
private double RichCostFunction(GraphNode node) { return CostFunction(node) + NodeEdgeDistance2(); }
public GraphLink(GraphNode origin, GraphNode destination) { _data = new SortedList(); _link = null; _origin = origin; _destination = destination; _origin.OutLinks.Add(this); _destination.InLinks.Add(this); }
private float lengthFix(GraphNode node1, GraphNode node2) { return (node1.Bounds.Width + node1.Bounds.Height) / 4 + (node2.Bounds.Width + node2.Bounds.Height) / 4; }
private GraphNode[,] ScrambleGrid(GraphNode[,] grid, int maxShift, int iter) { // Da ne e savsem random ami da gleda poveche da murda boxovete s // poveche linkove - i v posoka na linkovete ? GraphNode[,] newGrid = (GraphNode[,])grid.Clone(); if (maxShift > 2) { for (int i = 0; i < _gridWidth; i++) for (int j = 0; j < _gridHeight; ++j) ScrambleGridStep(newGrid, maxShift, iter, i, j); } else { int c = iter % _graph.Nodes.Count; Point pt = (Point)(_graph.Nodes[c] as GraphNode).GetData(_GridPos); ScrambleGridStep(newGrid, maxShift, iter, pt.X, pt.Y); } return newGrid; }
private float lengthFix(GraphNode node) { return (node.Bounds.Width + node.Bounds.Height) / 4; }
private void ScrambleGridStep(GraphNode[,] newGrid, int maxShift, int iter, int i, int j) { GraphNode node1 = newGrid[1 + i, 1 + j]; if (node1 == null) return; int col = i; int row = j; // Choose a new position Size dir = CalcLinkDir(node1); int newCol = maxShift > 1 ? col + dir.Width * _random.Next(0, maxShift + 1) + _random.Next(-1, 1 + 1) : col + dir.Width * _random.Next(0, 1 + 1); int newRow = maxShift > 1 ? row + dir.Height * _random.Next(0, maxShift + 1) + _random.Next(-1, 1 + 1) : row + dir.Height * _random.Next(0, 1 + 1); if (newCol < 0) newCol = 0; if (newCol >= _gridWidth) newCol = _gridWidth - 1; if (newRow < 0) newRow = 0; if (newRow >= _gridHeight) newRow = _gridHeight - 1; // Swap node1 with what's at the new pos GraphNode node2 = newGrid[1 + newCol, 1 + newRow]; // Start & end nodes are static INode startNode = _info.StartNode; INode endNode = _info.EndNode; if (startNode != null) { if (node1.Node == startNode || (node2 != null && node2.Node == startNode)) return; } if (endNode != null) { if (node1.Node == endNode || (node2 != null && node2.Node == endNode)) return; } newGrid[1 + newCol, 1 + newRow] = node1; newGrid[1 + i, 1 + j] = node2; node1.SetData(_GridPos, new Point(newCol, newRow)); if (node2 != null) node2.SetData(_GridPos, new Point(i, j)); }
private void CalcNewGlobalCost(GraphNode node) { _bordNewLocalValue = evalBoundaryCost(node); _glBordLinesCost = _glBordLinesCost - (double)node.GetData(BordLines) + _bordNewLocalValue; }
private bool NodesLinked(GraphNode n1, GraphNode n2) { foreach (GraphLink link in n1.OutLinks) if (link.Destination == n2) return true; return false; }
private void CommitMove(GraphNode node) { node.SetData(BordLines, _bordNewLocalValue); }
private void PlaceObjects(GraphNode[,] grid) { for (int i = 0; i < _gridWidth; ++i) { for (int j = 0; j < _gridHeight; ++j) { GraphNode node = grid[1 + i, 1 + j]; if (node != null) { node.Node.Bounds = new RectangleF(_info.XGap + i * _info.GridSize + _info.GridSize / 2 - node.Node.Bounds.Width / 2, _info.YGap + j * _info.GridSize + _info.GridSize / 2 - node.Node.Bounds.Height / 2, node.Node.Bounds.Width, node.Node.Bounds.Height); } } } }
private void SetGraphElements() { _nodes = new GraphNode[_tempGraph.Nodes.Count]; _links = new GraphLink[_tempGraph.Links.Count]; for (int i = 0; i < _tempGraph.Nodes.Count; i++) _nodes[i] = _tempGraph.Nodes[i] as GraphNode; for (int i = 0; i < _tempGraph.Links.Count; i++) _links[i] = _tempGraph.Links[i] as GraphLink; _sharedNode = new bool[_links.Length, _links.Length]; for (int i = 0; i < _links.Length; i++) { for (int j = 0; j < _links.Length; j++) { _sharedNode[i, j] = (i == j) || _links[i].Origin == _links[j].Origin || _links[i].Origin == _links[j].Destination || _links[i].Destination == _links[j].Destination || _links[i].Destination == _links[j].Origin; } } _nodeLink = new bool[_nodes.Length, _links.Length]; for (int i = 0; i < _nodes.Length; i++) { for (int j = 0; j < _links.Length; j++) { _nodeLink[i,j] = _nodes[i].InLinks.Contains(_links[j]) || _nodes[i].OutLinks.Contains(_links[j]); } } }