//using System; //using System.Collections.Generic; //using System.Linq; //using System.Windows; //using AIStudio.Wpf.DiagramDesigner.Geometrys; //namespace AIStudio.Wpf.DiagramDesigner.Layout //{ // internal class Engine // { // internal void ApplyRandomShift(DiagramViewModel network) // { // Random random = new Random(); // foreach (var node in network.Items.OfType()) // { // node.Position = node.Position + new VectorBase(random.NextDouble(), random.NextDouble()); // } // } // internal void Update(int deltaTMillis, IState state, Configuration config) // { // // Calculate forces // int nodeCount = config.Network.Items.Count; // IList<(DesignerItemViewModelBase, VectorBase)> nodeForces = new List<(DesignerItemViewModelBase, VectorBase)>(nodeCount); // foreach (var node in config.Network.Items.OfType()) // { // if (!config.IsFixedNode(node)) // { // nodeForces.Add((node, CalculateNodeForce(node, state, config))); // } // } // // Apply forces // foreach (var (node, force) in nodeForces) // { // VectorBase speed = state.GetNodeSpeed(node); // VectorBase pos = state.GetNodePosition(node); // double deltaT = deltaTMillis / 1000.0; // state.SetNodePosition(node, pos + ((speed * deltaT) + (force * deltaT * deltaT / 2))); // state.SetNodeSpeed(node, speed + ((force / config.NodeMass(node)) * deltaT)); // } // } // private VectorBase CalculateNodeForce(DesignerItemViewModelBase node, IState state, Configuration config) // { // VectorBase force = new VectorBase(); // // Calculate total force on node from endpoints // if (node.InputConnectors.Count > 0 || node.OutputConnectors.Count > 0) // { // force += node.InputConnectors.Concat(node.OutputConnectors) // .Select(e => CalculateEndpointForce(e, state, config)) // .Aggregate((v1, v2) => v1 + v2); // } // // Apply node repulsion force so nodes don't overlap // var nodeCenter = state.GetNodePosition(node) + (new VectorBase(node.Size.Width, node.Size.Height) / 2.0); // foreach (var otherNode in config.Network.Items.OfType()) // { // if (node == otherNode) // { // continue; // } // var otherNodeCenter = state.GetNodePosition(otherNode) + (new VectorBase(otherNode.Size.Width, otherNode.Size.Height) / 2.0); // var thisToOther = otherNodeCenter - nodeCenter; // var dist = thisToOther.Length; // thisToOther.Normalize(); // var repulsionX = thisToOther.X * (-1 * ((node.Size.Width + otherNode.Size.Width) / 2) / dist); // var repulsionY = thisToOther.Y * (-1 * ((node.Size.Height + otherNode.Size.Height) / 2) / dist); // force += new VectorBase(repulsionX, repulsionY) * config.NodeRepulsionForce; // } // // Apply friction to make the movement converge to a stable state. // float gravity = 9.8f; // float normalForce = gravity * config.NodeMass(node); // float kineticFriction = normalForce * config.FrictionCoefficient(node); // VectorBase frictionVector = new VectorBase(); // var nodeSpeed = state.GetNodeSpeed(node); // if (nodeSpeed.Length > 0) // { // frictionVector = new VectorBase(nodeSpeed.X, nodeSpeed.Y); // frictionVector.Normalize(); // frictionVector *= -1.0 * kineticFriction; // } // force += frictionVector; // return force; // } // private VectorBase CalculateEndpointForce(ConnectorInfoBase endpoint, IState state, Configuration config) // { // var pos = state.GetEndpointPosition(endpoint); // VectorBase force = new VectorBase(); // foreach (var conn in endpoint.Connections.Items) // { // var otherSide = conn.Input == endpoint ? (ConnectorInfoBase)conn.Output : conn.Input; // var otherSidePos = state.GetEndpointPosition(otherSide); // var dist = (otherSidePos - pos).Length; // var angle = Math.Acos((otherSidePos.X - pos.X) / dist); // if (otherSidePos.Y < pos.Y) // { // angle *= -1.0; // } // // Put a spring between connected endpoints. // var hookForce = (dist - config.EquilibriumDistance(conn)) * config.SpringConstant(conn); // force += new VectorBase(Math.Cos(angle), Math.Sin(angle)) * hookForce; // // Try to 'straighten' out the graph horizontally. // var isLeftSide = endpoint.Orientation == ConnectorOrientation.Left; // var rowForce = (isLeftSide ? 1 : -1) * config.RowForce(conn); // force.X += rowForce; // } // return force; // } // } //}