public static double CalculateAngle (MutableVector a, MutableVector b) { a.Normalize(); b.Normalize(); var theta = Math.Acos(a.X * b.X + a.Y * b.Y + a.Z * b.Z); return theta * 180 / Math.PI; }
public static double CalculateAngle (MutableVector a, MutableVector b) { a.Normalize(); b.Normalize(); var theta = Math.Acos(a.X * b.X + a.Y * b.Y + a.Z * b.Z); return(theta * 180 / Math.PI); }
public static MutableVector <int> GetNeighbor(IList <int> coordinate, int side) { var neighbor = MutableVector <int> .CopyOf(coordinate); if (side < coordinate.Count) { --neighbor[side]; } else { ++neighbor[side - coordinate.Count]; } return(neighbor); }
/// <summary> /// Performs one step in the layout process. Most uses will want to call this in a loop /// until there is little energy left in the system, or some amount of time has elapsed. /// </summary> /// <param name="handle_constraints">Whether to enforce constraints on this step of not.</param> /// <returns>An approximation of the total acceleration of the system...?</returns> public double Step() { // every thread must perform thread-safe operations only Parallel.For(0, nodes.Length, (i) => { FDLNode node = nodes[i]; MutableVector force = new MutableVector(Vector.ZERO_VECTOR); //sum forces for (int j = 0; j < nodes.Length; j++) { if (j == i) continue; FDLNode other_node = nodes[j]; force.Add(NodeNodeForce(node, other_node)); } //sum forces foreach (FDLEdge edge in node.InEdges) { force.Add(EdgeForce(edge)); force.Add(EdgeTorque(edge)); } //derive acceleration Vector acceleration = (Vector)force / node.Mass; accels[i] = acceleration.Magnitude; //derive position if (first_step) { //eulers integration - assume old velocity was zero for first step new_positions[i] = new MutablePoint(node.Position); new_positions[i].Add(1.5 * acceleration * TIMESTEP_SQUARED); } else { //verlet integration - requires constant timestep new_positions[i].X = 0; new_positions[i].Y = 0; new_positions[i].Add((1 + DAMPING) * node.Position); new_positions[i].Subtract(DAMPING * node.PreviousPosition); new_positions[i].Add(acceleration * TIMESTEP_SQUARED); } } ); // update node positions and sum accelerations double totalAccel = 0; for (int i = 0; i < nodes.Length; i++) { nodes[i].Position = (Point)new_positions[i]; totalAccel += accels[i]; } first_step = false; // i'm not sure what to call this measure... // but it isn't time or mass biased, which seems to make it a good indicator of a // local minima of... some measure of energy? My best guess is that it's a // really terrible and inaccurate approximation of the total acceleration of // the system. Approximation, since it sums forces only on a per node rather system // basis. return totalAccel; }