Если бы это было о зафиксированных изменениях, то необходимо взглянуть на переоснову мерзавца, но, как указано в комментарии VonC, поскольку Вы говорите о локальных изменениях, притон мерзавца, конечно, был бы хорошим способом сделать это.
Некоторое время назад я написал код для выполнения макетов динамических графиков с использованием C # и XNA (полный исходный код доступен по запросу).
Вот некоторые из критических функций:
public void UpdateNodes()
{
for (int i = 0; i < nodes.Count; i++)
{
Vector2 netForce = Vector2.Zero;
foreach (Node otherNode in nodes)
{
if (otherNode != nodes[i])
{
netForce += CoulombRepulsion(nodes[i], otherNode); //calculate repulsion for all nodes
if (nodes[i].links.Contains(otherNode))
{
netForce += HookeAttraction(nodes[i], otherNode); //only calc attraction for linked nodes
}
}
}
nodes[i].Velocity += netForce;
nodes[i].Velocity *= .99f;
nodes[i].Position += nodes[i].Velocity;
}
}
public Vector2 HookeAttraction(Node node1, Node node2) //ON node1 BY node2
{
Vector2 direction = Vector2.Subtract(node2.Position, node1.Position);
direction.Normalize();
return hookeConst* node2.Mass * Vector2.Distance(node1.Position, node2.Position) * direction;
}
public Vector2 GravAttraction(Node node1, Node node2) //ON node1 BY node2
{
Vector2 direction = Vector2.Subtract(node2.Position, node1.Position);
direction.Normalize();
return gravConst * node2.Mass * Vector2.DistanceSquared(node1.Position, node2.Position) * direction;
}
Выберите две константы в зависимости от того, насколько быстро вы хотите, чтобы график сходился. Я использовал их:
private const float hookeConst = .000005f;
private const float gravConst = .00000001f;
Этот код довольно понятен, но не стесняйтесь спрашивать, нужно ли вам что-нибудь. По сути, вызовите функцию UpdateNodes () в цикле, и ваш график сойдется в своем состоянии с минимальной энергией.
Я не использовал ни один из этих примеров, но уверен, что они будут вам полезны.
Здесь также есть похожий (повторяющийся?) Вопрос: Визуализация графиков в Silverlight