自动图形布局弹簧理论

6

我想通过视觉方式来展示实体之间的关系。对于自动图形布局,弹簧算法似乎很适合我的需求。我想使用c#在silverlight中实现这一点,所以我正在寻找代码示例或链接到好的理论解释。非常感谢您的帮助。

2个回答

6

我曾经写过一些代码,使用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()函数,您的图将会收敛到最小能量状态。


只是一个提示: "nodes [i] .Velocity * = .99f;" 是一个阻尼常数,使您的图更容易收敛。 减小该值可减少“弹性”。 - Preetum Nakkiran
我想要源代码... stackoverflow@m.capdes.com - Eric Schoonover
当然,这是一个压缩的项目链接:http://staff.arson-media.com/preetum/uploads/springForceV0.zip请注意,我写这段代码已经有一段时间了,所以有一些不必要的混淆区域(例如在更新循环中标记为“mouseStuff”的区域)。尽管如此,所有重要的组件都存在且可用。(还有一些与鼠标的交互) - Preetum Nakkiran
非常好的帖子!谢谢。如果您不介意,可以将源代码发送到flowunderstack@gmail.com - Jeremy
上面的链接已经失效了 - 是否有其他可用的链接? - g t
抱歉打扰,我想问一下是否有办法在画布中固定节点的位置。我已经按照以下代码编写了程序,但问题是我得到的点不在我的小部件坐标系内。 - user506710

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接