using System.Collections.Generic;
namespace Netron.Diagramming.Core.Layout.Force {
///
/// Represents a spring in a force simulation.
///
public class Spring {
#region Fields
private static SpringFactory mFactory = new SpringFactory();
private ForceItem item1;
private ForceItem item2;
private float length;
private float coeff;
#endregion
#region Properties
///
/// Retrieve the SpringFactory instance, which serves as an object pool
/// for Spring instances.
///
/// The spring factory.
public static SpringFactory Factory {
get {
return mFactory;
}
}
///
/// The first ForceItem endpoint
///
public ForceItem Item1 {
get { return item1; }
set { item1 = value; }
}
///
/// The second ForceItem endpoint
///
public ForceItem Item2 {
get { return item2; }
set { item2 = value; }
}
///
/// The spring's resting length
///
public float Length {
get { return length; }
set { length = value; }
}
///
/// The spring tension co-efficient
///
public float Coeff {
get { return coeff; }
set { coeff = value; }
}
#endregion
#region Constructor
///
/// Create a new Spring instance
/// the first ForceItem endpoint
/// the second ForceItem endpoint
/// the spring tension co-efficient
/// the spring's resting length
///
public Spring(ForceItem fi1, ForceItem fi2, float k, float len) {
item1 = fi1;
item2 = fi2;
coeff = k;
length = len;
}
#endregion
#region Classes
///
/// The SpringFactory is responsible for generating Spring instances
/// and maintaining an object pool of Springs to reduce garbage collection
/// overheads while force simulations are running.
///
public sealed class SpringFactory {
public const int Capacity = 5000;
private List springs = new List(Capacity);
///
/// Get a Spring instance and set it to the given parameters.
///
public Spring getSpring(ForceItem f1, ForceItem f2, float k, float length) {
if (springs.Count > 0) {
Spring s = springs[springs.Count - 1];
springs.Remove(s);
s.Item1 = f1;
s.Item2 = f2;
s.Coeff = k;
s.Length = length;
return s;
} else {
return new Spring(f1, f2, k, length);
}
}
///
/// Reclaim a Spring into the object pool.
///
public void reclaim(Spring s) {
s.Item1 = null;
s.Item2 = null;
if (springs.Count < Capacity)
springs.Add(s);
}
}
#endregion
}
}