/// <summary> /// Initialize the simulation with the provided enclosing simulation. After /// this call has been made, the simulation can be queried for the /// n-body force acting on a given item. /// </summary> /// <param name="fsim">the encompassing ForceSimulator</param> public override void Init(ForceSimulator fsim) { clear(); // clear internal state // compute and squarify bounds of quadtree float x1 = float.MaxValue, y1 = float.MaxValue; float x2 = float.MinValue, y2 = float.MinValue; foreach (ForceItem item in fsim.Items) { float x = item.Location[0]; float y = item.Location[1]; if (x < x1) { x1 = x; } if (y < y1) { y1 = y; } if (x > x2) { x2 = x; } if (y > y2) { y2 = y; } } float dx = x2 - x1, dy = y2 - y1; if (dx > dy) { y2 = y1 + dx; } else { x2 = x1 + dy; } setBounds(x1, y1, x2, y2); // Insert items into quadtree foreach (ForceItem item in fsim.Items) { Insert(item); } // calculate magnitudes and centers of mass CalculateMass(root); }
/// <summary> /// Initialize this force function. This default implementation does nothing. /// Subclasses should override this method with any needed initialization. /// </summary> /// <param name="fsim">the encompassing ForceSimulator</param> public virtual void Init(ForceSimulator fsim) { // do nothing. }
/// <summary> /// Integrates the specified simulation. /// </summary> /// <param name="sim">The sim.</param> /// <param name="timestep">The timestep.</param> public void Integrate(ForceSimulator sim, long timestep) { float speedLimit = sim.SpeedLimit; float vx, vy, v, coeff; float[,] k, l; foreach (ForceItem item in sim.Items) { coeff = timestep / item.Mass; k = item.RungeKuttaTemp1; l = item.RungeKuttaTemp2; item.PreviousLocation[0] = item.Location[0]; item.PreviousLocation[1] = item.Location[1]; k[0, 0] = timestep * item.Velocity[0]; k[0, 1] = timestep * item.Velocity[1]; l[0, 0] = coeff * item.Force[0]; l[0, 1] = coeff * item.Force[1]; // Set the position to the new predicted position item.Location[0] += 0.5f * k[0, 0]; item.Location[1] += 0.5f * k[0, 1]; } // recalculate forces sim.Accumulate(); foreach (ForceItem item in sim.Items) { coeff = timestep / item.Mass; k = item.RungeKuttaTemp1; l = item.RungeKuttaTemp2; vx = item.Velocity[0] + .5f * l[0, 0]; vy = item.Velocity[1] + .5f * l[0, 1]; v = (float)Math.Sqrt(vx * vx + vy * vy); if (v > speedLimit) { vx = speedLimit * vx / v; vy = speedLimit * vy / v; } k[1, 0] = timestep * vx; k[1, 1] = timestep * vy; l[1, 0] = coeff * item.Force[0]; l[1, 1] = coeff * item.Force[1]; // Set the position to the new predicted position item.Location[0] = item.PreviousLocation[0] + 0.5f * k[1, 0]; item.Location[1] = item.PreviousLocation[1] + 0.5f * k[1, 1]; } // recalculate forces sim.Accumulate(); foreach (ForceItem item in sim.Items) { coeff = timestep / item.Mass; k = item.RungeKuttaTemp1; l = item.RungeKuttaTemp2; vx = item.Velocity[0] + .5f * l[1, 0]; vy = item.Velocity[1] + .5f * l[1, 1]; v = (float)Math.Sqrt(vx * vx + vy * vy); if (v > speedLimit) { vx = speedLimit * vx / v; vy = speedLimit * vy / v; } k[2, 0] = timestep * vx; k[2, 1] = timestep * vy; l[2, 0] = coeff * item.Force[0]; l[2, 1] = coeff * item.Force[1]; // Set the position to the new predicted position item.Location[0] = item.PreviousLocation[0] + 0.5f * k[2, 0]; item.Location[1] = item.PreviousLocation[1] + 0.5f * k[2, 1]; } // recalculate forces sim.Accumulate(); foreach (ForceItem item in sim.Items) { coeff = timestep / item.Mass; k = item.RungeKuttaTemp1; l = item.RungeKuttaTemp2; float[] p = item.PreviousLocation; vx = item.Velocity[0] + l[2, 0]; vy = item.Velocity[1] + l[2, 1]; v = (float)Math.Sqrt(vx * vx + vy * vy); if (v > speedLimit) { vx = speedLimit * vx / v; vy = speedLimit * vy / v; } k[3, 0] = timestep * vx; k[3, 1] = timestep * vy; l[3, 0] = coeff * item.Force[0]; l[3, 1] = coeff * item.Force[1]; item.Location[0] = p[0] + (k[0, 0] + k[3, 0]) / 6.0f + (k[1, 0] + k[2, 0]) / 3.0f; item.Location[1] = p[1] + (k[0, 1] + k[3, 1]) / 6.0f + (k[1, 1] + k[2, 1]) / 3.0f; vx = (l[0, 0] + l[3, 0]) / 6.0f + (l[1, 0] + l[2, 0]) / 3.0f; vy = (l[0, 1] + l[3, 1]) / 6.0f + (l[1, 1] + l[2, 1]) / 3.0f; v = (float)Math.Sqrt(vx * vx + vy * vy); if (v > speedLimit) { vx = speedLimit * vx / v; vy = speedLimit * vy / v; } item.Velocity[0] += vx; item.Velocity[1] += vy; } }
/// <summary> /// Initialize the simulation with the provided enclosing simulation. After /// this call has been made, the simulation can be queried for the /// n-body force acting on a given item. /// </summary> /// <param name="fsim">the encompassing ForceSimulator</param> public override void Init(ForceSimulator fsim) { clear(); // clear internal state // compute and squarify bounds of quadtree float x1 = float.MaxValue, y1 = float.MaxValue; float x2 = float.MinValue, y2 = float.MinValue; foreach (ForceItem item in fsim.Items) { float x = item.Location[0]; float y = item.Location[1]; if (x < x1) x1 = x; if (y < y1) y1 = y; if (x > x2) x2 = x; if (y > y2) y2 = y; } float dx = x2 - x1, dy = y2 - y1; if (dx > dy) { y2 = y1 + dx; } else { x2 = x1 + dy; } setBounds(x1, y1, x2, y2); // Insert items into quadtree foreach (ForceItem item in fsim.Items) { Insert(item); } // calculate magnitudes and centers of mass CalculateMass(root); }
/// <summary> /// Initialize this force function. This default implementation does nothing. /// Subclasses should override this method with any needed initialization. /// </summary> /// <param name="fsim">the encompassing ForceSimulator</param> public virtual void Init(ForceSimulator fsim) { // do nothing. }
/// <summary> /// Integrates the specified simulation. /// </summary> /// <param name="sim">The sim.</param> /// <param name="timestep">The timestep.</param> public void Integrate(ForceSimulator sim, long timestep) { float speedLimit = sim.SpeedLimit; float vx, vy, v, coeff; float[,] k, l; foreach (ForceItem item in sim.Items) { coeff = timestep / item.Mass; k = item.RungeKuttaTemp1; l = item.RungeKuttaTemp2; item.PreviousLocation[0] = item.Location[0]; item.PreviousLocation[1] = item.Location[1]; k[0, 0] = timestep * item.Velocity[0]; k[0, 1] = timestep * item.Velocity[1]; l[0, 0] = coeff * item.Force[0]; l[0, 1] = coeff * item.Force[1]; // Set the position to the new predicted position item.Location[0] += 0.5f * k[0, 0]; item.Location[1] += 0.5f * k[0, 1]; } // recalculate forces sim.Accumulate(); foreach (ForceItem item in sim.Items) { coeff = timestep / item.Mass; k = item.RungeKuttaTemp1; l = item.RungeKuttaTemp2; vx = item.Velocity[0] + .5f * l[0, 0]; vy = item.Velocity[1] + .5f * l[0, 1]; v = (float)Math.Sqrt(vx * vx + vy * vy); if (v > speedLimit) { vx = speedLimit * vx / v; vy = speedLimit * vy / v; } k[1, 0] = timestep * vx; k[1, 1] = timestep * vy; l[1, 0] = coeff * item.Force[0]; l[1, 1] = coeff * item.Force[1]; // Set the position to the new predicted position item.Location[0] = item.PreviousLocation[0] + 0.5f * k[1, 0]; item.Location[1] = item.PreviousLocation[1] + 0.5f * k[1, 1]; } // recalculate forces sim.Accumulate(); foreach (ForceItem item in sim.Items) { coeff = timestep / item.Mass; k = item.RungeKuttaTemp1; l = item.RungeKuttaTemp2; vx = item.Velocity[0] + .5f * l[1, 0]; vy = item.Velocity[1] + .5f * l[1, 1]; v = (float)Math.Sqrt(vx * vx + vy * vy); if (v > speedLimit) { vx = speedLimit * vx / v; vy = speedLimit * vy / v; } k[2, 0] = timestep * vx; k[2, 1] = timestep * vy; l[2, 0] = coeff * item.Force[0]; l[2, 1] = coeff * item.Force[1]; // Set the position to the new predicted position item.Location[0] = item.PreviousLocation[0] + 0.5f * k[2, 0]; item.Location[1] = item.PreviousLocation[1] + 0.5f * k[2, 1]; } // recalculate forces sim.Accumulate(); foreach (ForceItem item in sim.Items) { coeff = timestep / item.Mass; k = item.RungeKuttaTemp1; l = item.RungeKuttaTemp2; float[] p = item.PreviousLocation; vx = item.Velocity[0] + l[2, 0]; vy = item.Velocity[1] + l[2, 1]; v = (float)Math.Sqrt(vx * vx + vy * vy); if (v > speedLimit) { vx = speedLimit * vx / v; vy = speedLimit * vy / v; } k[3, 0] = timestep * vx; k[3, 1] = timestep * vy; l[3, 0] = coeff * item.Force[0]; l[3, 1] = coeff * item.Force[1]; item.Location[0] = p[0] + (k[0, 0] + k[3, 0]) / 6.0f + (k[1, 0] + k[2, 0]) / 3.0f; item.Location[1] = p[1] + (k[0, 1] + k[3, 1]) / 6.0f + (k[1, 1] + k[2, 1]) / 3.0f; vx = (l[0, 0] + l[3, 0]) / 6.0f + (l[1, 0] + l[2, 0]) / 3.0f; vy = (l[0, 1] + l[3, 1]) / 6.0f + (l[1, 1] + l[2, 1]) / 3.0f; v = (float)Math.Sqrt(vx * vx + vy * vy); if (v > speedLimit) { vx = speedLimit * vx / v; vy = speedLimit * vy / v; } item.Velocity[0] += vx; item.Velocity[1] += vy; } }
/// <summary> /// Loads the simulator with all relevant force items and springs. /// </summary> /// <param name="fsim"> the force simulator driving this layout.</param> protected void InitializeSimulator(ForceSimulator fsim) { //TODO: some checks here...? float startX = (referrer == null ? 0f : (float)referrer.X); float startY = (referrer == null ? 0f : (float)referrer.Y); startX = float.IsNaN(startX) ? 0f : startX; startY = float.IsNaN(startY) ? 0f : startY; if (Nodes != null && Nodes.Count > 0) { foreach (INode item in Nodes) { ForceItem fitem = Pars[item.Uid.ToString()]; fitem.Mass = getMassValue(item); double x = item.X; double y = item.Y; fitem.Location[0] = (Double.IsNaN(x) ? startX : (float)x); fitem.Location[1] = (Double.IsNaN(y) ? startY : (float)y); fsim.addItem(fitem); } } if (Edges != null && Edges.Count > 0) { foreach (IEdge e in Edges) { INode n1 = e.SourceNode; if (n1 == null) continue; ForceItem f1 = Pars[n1.Uid.ToString()]; INode n2 = e.TargetNode; if (n2 == null) continue; ForceItem f2 = Pars[n2.Uid.ToString()]; float coeff = getSpringCoefficient(e); float slen = getSpringLength(e); fsim.addSpring(f1, f2, (coeff >= 0 ? coeff : -1.0F), (slen >= 0 ? slen : -1.0F)); } } }
private bool Init() { mEnforceBounds = false; m_runonce = true; m_fsim = new ForceSimulator(); m_fsim.AddForce(new NBodyForce()); m_fsim.AddForce(new SpringForce()); m_fsim.AddForce(new DragForce()); this.Graph = this.Model as IGraph; if (Graph == null) throw new InconsistencyException("The model has not been set and the Graph property is hence 'null'"); //Graph.ClearSpanningTree(); //Graph.MakeSpanningTree(LayoutRoot as INode); if (Graph.Nodes.Count == 0) return false; if (Graph.Edges.Count == 0) //this layout is base on embedded springs in the connections return false; Pars = new Dictionary<string, ForceItem>(); foreach (INode node in Nodes) { Pars.Add(node.Uid.ToString(), new ForceItem()); } return true; }