/// <summary> /// Calculate the attractive force between nodes /// </summary> /// <param name="first">the first node</param> /// <param name="second">the second node</param> /// <returns>attractive force between nodes</returns> private Vector CalculateAttractiveForceBetweenNodes(NodeLayoutData first, NodeLayoutData second) { double springConstant = _defaultSpringConstant; double amplifier = _defaultSpringAmplifier; double springStableDistance = _defaultSpringStableDistance; double dx = first.Coordinates.X - second.Coordinates.X; double dy = first.Coordinates.Y - second.Coordinates.Y; double distance = Math.Sqrt((Math.Pow(dx, 2) + Math.Pow(dy, 2))); double springMultiplier = 0; if (!double.IsNaN(distance)) { double distanceFromStablePoint = Math.Abs(distance - springStableDistance); int directionModifier = -1; if (distance < springStableDistance) { directionModifier = 1; } springMultiplier = (distanceFromStablePoint / springConstant); if (springMultiplier > _defaultSpringMultiplierCap) { springMultiplier = _defaultSpringMultiplierCap; } springMultiplier = springMultiplier * directionModifier * amplifier; } return new Vector(springMultiplier * dx, springMultiplier * dy); }
/// <summary> /// Calculate the repulsive force between nodes /// </summary> /// <param name="first">the first node</param> /// <param name="second">the second node</param> /// <returns>A vector representing a repulsive first</returns> private Vector CalculateRepulsiveForceBetweeNodes(NodeLayoutData first, NodeLayoutData second) { double repulseConstant = _defaultRepulseConstant; double dx = first.Coordinates.X - second.Coordinates.X; double dy = first.Coordinates.Y - second.Coordinates.Y; double distance = Math.Sqrt((Math.Pow(dx, 2) + Math.Pow(dy, 2))); double repulseMultiplier = 0; if (!double.IsNaN(distance)) { repulseMultiplier = repulseConstant / distance; } return new Vector(repulseMultiplier * dx, repulseMultiplier * dy); }
/// <summary> /// Increment the sort score of a nodes destinations /// </summary> /// <param name="nodeData">the current node</param> /// <param name="visitedNodes">a list of nodes already visited, important to prevent circular processing</param> private void AddSortScoreToDestinations(NodeLayoutData nodeData, List<NodeLayoutData> visitedNodes) { visitedNodes.Add(nodeData); if (nodeData.NextNodesLayoutData != null) { foreach (NodeLayoutData nextNode in nodeData.NextNodesLayoutData) { nextNode.SortScore = nextNode.SortScore + 1; if (!visitedNodes.Contains(nextNode)) { AddSortScoreToDestinations(nextNode, visitedNodes); } } } }