【问题标题】:Automatic graph layout spring theory自动图形布局弹簧理论
【发布时间】:2009-08-25 04:06:29
【问题描述】:

我正在尝试直观地定位实体以显示它们之间的关系。看起来对于自​​动图形布局,弹簧算法将适合我的需要。我想在 Silverlight 中使用 c# 来实现它,所以我正在寻找代码示例,或者链接到该理论的良好解释。任何帮助表示赞赏

【问题讨论】:

    标签: silverlight graph graph-theory


    【解决方案1】:

    我不久前编写了一些代码来使用 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;”是一个阻尼常数,使您的图形更容易收敛。降低该值以减少“弹性”。
    • 我想要来源... *@m.capdes.com
    • 当然,这里是(作为一个压缩项目):staff.arson-media.com/preetum/uploads/springForceV0.zip 请注意,这段代码我相当之前写的,所以有一些不必要的混淆区域(比如在更新循环中标记为“mouseStuff”的区域)。尽管如此,所有重要的组件都存在并且可以正常工作。 (还有一些与鼠标的交互)
    • 好帖子!谢谢。如果您不介意,可以将源代码发送到 gmail.com 上的 flowunderstack
    • 上面的链接失效了——哪里有live版本?
    【解决方案2】:

    我没有使用任何这些示例,但我相信它们会对您有用。

    这里也有一个类似(重复?)的问题:Graph visualisation in Silverlight

    【讨论】: