示例#1
0
        public void Test_BarnesHutTree_GetQuad()
        {
            var bht = new BarnesHutTree(new ArborPoint(-1, -1), new ArborPoint(+1, +1), 0.5f);

            var node = new ArborNode("x");

            node.Pt = new ArborPoint(0.5f, 0.5f);
            int qd = BarnesHutTree.GetQuad(node, bht.Root);

            Assert.AreEqual(BarnesHutTree.QSe, qd);

            node.Pt = new ArborPoint(-0.5f, 0.5f);
            qd      = BarnesHutTree.GetQuad(node, bht.Root);
            Assert.AreEqual(BarnesHutTree.QSw, qd);

            node.Pt = new ArborPoint(-0.5f, -0.5f);
            qd      = BarnesHutTree.GetQuad(node, bht.Root);
            Assert.AreEqual(BarnesHutTree.QNw, qd);

            node.Pt = new ArborPoint(0.5f, -0.5f);
            qd      = BarnesHutTree.GetQuad(node, bht.Root);
            Assert.AreEqual(BarnesHutTree.QNe, qd);

            node.Pt = ArborPoint.Null;
            qd      = BarnesHutTree.GetQuad(node, bht.Root);
            Assert.AreEqual(BarnesHutTree.QNone, qd);

            qd = BarnesHutTree.GetQuad(null, bht.Root);
            Assert.AreEqual(BarnesHutTree.QNone, qd);
        }
示例#2
0
        public ArborNode GetNearestNode(int viewX, int viewY)
        {
            ArborPoint pt = GetModelCoords(viewX, viewY);

            ArborNode result  = null;
            double    minDist = +1.0f;

            for (int i = 0, nodesCount = fNodes.Count; i < nodesCount; i++)
            {
                ArborNode  node   = fNodes[i];
                ArborPoint nodePt = node.Pt;
                if (nodePt.IsExploded())
                {
                    continue;
                }

                double dist = nodePt.Sub(pt).Magnitude();
                if (dist < minDist)
                {
                    result  = node;
                    minDist = dist;
                }
            }

            return(result);
        }
示例#3
0
        public void Test_Common()
        {
            var node1 = new ArborNode("x1");
            var node2 = new ArborNode("x2");

            var edge = new ArborEdge(node1, node2, 11.0f, 22.0f, true);

            Assert.IsNotNull(edge);

            Assert.Throws(typeof(ArgumentNullException), () => { new ArborEdge(null, node2, 11.0f, 22.0f, true); });
            Assert.Throws(typeof(ArgumentNullException), () => { new ArborEdge(node1, null, 11.0f, 22.0f, true); });

            var vertex1       = new Vertex();
            var vertex2       = new Vertex();
            var extensibleObj = new Edge(vertex1, vertex2, 1, null);

            edge.Attach(extensibleObj);
            edge.Detach(extensibleObj);

            Assert.AreEqual(node1, edge.Source);
            Assert.AreEqual(node2, edge.Target);
            Assert.AreEqual(11.0f, edge.Length);
            Assert.AreEqual(22.0f, edge.Stiffness);
            Assert.AreEqual(true, edge.Directed);
        }
示例#4
0
        private void SyncGraph()
        {
            fEdges.Clear();
            fNodes.Clear();

            var vertices = fGraph.Vertices;

            for (int i = 0, verticesCount = vertices.Count; i < verticesCount; i++)
            {
                Vertex vertex = vertices[i];

                ArborNode node = CreateNode(vertex.Sign);
                node.Pt = NewRandomPoint();

                vertex.Extensions.Add(node);
                fNodes.Add(node);
            }

            var edges = fGraph.Edges;

            for (int i = 0, edgesCount = edges.Count; i < edgesCount; i++)
            {
                Edge edge = edges[i];

                ArborNode anSrc = edge.Source.Extensions.Find <ArborNode>();
                ArborNode anTgt = edge.Target.Extensions.Find <ArborNode>();

                ArborEdge arbEdge = CreateEdge(anSrc, anTgt, 1.0f, fStiffness);
                edge.Extensions.Add(arbEdge);
                fEdges.Add(arbEdge);
            }
        }
示例#5
0
        public ArborViewer()
        {
            base.BackColor      = Color.White;
            base.BorderStyle    = BorderStyle.Fixed3D;
            base.DoubleBuffered = true;
            base.TabStop        = true;
            base.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            base.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

            // repulsion - отталкивание, stiffness - тугоподвижность, friction - сила трения
            fSystem = new ArborSystemEx(10000.0f, 500.0f /*1000.0f*/, 0.1f, this);
            fSystem.SetViewSize(Width, Height);
            fSystem.AutoStop = true;
            fSystem.Graph    = new Graph();

            fDragged       = null;
            fEnergyDebug   = false;
            fNodesDragging = false;

            fDrawFont = new Font("Calibri", 9);

            fLinePen          = new Pen(Color.Gray, 1);
            fLinePen.StartCap = LineCap.NoAnchor;
            fLinePen.EndCap   = LineCap.ArrowAnchor;

            fStrFormat               = new StringFormat();
            fStrFormat.Alignment     = StringAlignment.Center;
            fStrFormat.LineAlignment = StringAlignment.Center;

            fBlackBrush = new SolidBrush(Color.Black);
            fWhiteBrush = new SolidBrush(Color.White);
        }
示例#6
0
        public ArborEdge AddEdge(string sourceSign, string targetSign, double length = 1.0f)
        {
            ArborNode src = GetNode(sourceSign);

            src = (src != null) ? src : AddNode(sourceSign);

            ArborNode tgt = GetNode(targetSign);

            tgt = (tgt != null) ? tgt : AddNode(targetSign);

            ArborEdge result = null;

            if (src != null && tgt != null)
            {
                for (int i = 0, edgesCount = fEdges.Count; i < edgesCount; i++)
                {
                    ArborEdge edge = fEdges[i];
                    if (edge.Source == src && edge.Target == tgt)
                    {
                        result = edge;
                        break;
                    }
                }
            }

            if (result == null)
            {
                result = CreateEdge(src, tgt, length, fStiffness);
                fEdges.Add(result);
            }

            return(result);
        }
示例#7
0
        public void ApplyForces(ArborNode m, double repulsion)
        {
            try {
                Queue <object> queue = new Queue <object>();

                queue.Enqueue(fRoot);
                while (queue.Count > 0)
                {
                    object obj = queue.Dequeue();
                    if (obj == null || obj == m)
                    {
                        continue;
                    }

                    ArborPoint ptx, k;
                    double     l, kMag, massx;

                    if (obj is ArborNode)
                    {
                        ArborNode node = (ArborNode)obj;
                        massx = node.Mass;
                        ptx   = node.Pt;

                        k    = m.Pt.Sub(ptx);
                        kMag = k.Magnitude();

                        l = Math.Max(1.0f, kMag);
                        m.ApplyForce(k.Normalize().Mul(repulsion * massx).Div(l * l));
                    }
                    else
                    {
                        Branch branch = (Branch)obj;
                        massx = branch.Mass;
                        ptx   = branch.Pt.Div(massx);

                        k    = m.Pt.Sub(ptx);
                        kMag = k.Magnitude();

                        double h = Math.Sqrt(branch.Size.X * branch.Size.Y);
                        if (h / kMag > fDist)
                        {
                            queue.Enqueue(branch.Q[QNe]);
                            queue.Enqueue(branch.Q[QNw]);
                            queue.Enqueue(branch.Q[QSe]);
                            queue.Enqueue(branch.Q[QSw]);
                        }
                        else
                        {
                            l = Math.Max(1.0f, kMag);
                            m.ApplyForce(k.Normalize().Mul(repulsion * massx).Div(l * l));
                        }
                    }
                }
            } catch (Exception ex) {
                Debug.WriteLine("BarnesHutTree.ApplyForces(): " + ex.Message);
            }
        }
示例#8
0
        public RectangleF GetNodeRect(Graphics gfx, ArborNode node)
        {
            SizeF      tsz = gfx.MeasureString(node.Sign, fDrawFont);
            float      w   = tsz.Width + 10.0f;
            float      h   = tsz.Height + 4.0f;
            ArborPoint pt  = fSystem.GetViewCoords(node.Pt);

            return(new RectangleF((float)pt.X - w / 2.0f, (float)pt.Y - h / 2.0f, w, h));
        }
示例#9
0
        public void Test_BarnesHutTree_ApplyForces()
        {
            var bht = new BarnesHutTree(new ArborPoint(-1, -1), new ArborPoint(+1, +1), 0.5f);

            var node = new ArborNode("x");

            node.Pt = new ArborPoint(0.5f, 0.5f);
            bht.ApplyForces(node, 10000.0f);
        }
示例#10
0
        public void Test_BarnesHutTree_Insert()
        {
            var bht = new BarnesHutTree(new ArborPoint(-1, -1), new ArborPoint(+1, +1), 0.5f);

            var node = new ArborNode("x");

            node.Pt = new ArborPoint(0.5f, 0.5f);
            bht.Insert(node);
        }
示例#11
0
        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);

            if (fNodesDragging && fDragged != null)
            {
                fDragged.Fixed = false;
                fDragged       = null;
            }
        }
示例#12
0
        public ArborNode AddNode(string sign, ArborPoint pt)
        {
            ArborNode node = GetNode(sign);

            if (node != null)
            {
                return(node);
            }

            node    = CreateNode(sign);
            node.Pt = pt;

            fNames.Add(sign, node);
            fNodes.Add(node);

            return(node);
        }
示例#13
0
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (!Focused)
            {
                base.Focus();
            }

            if (fNodesDragging)
            {
                fDragged = fSystem.GetNearestNode(e.X, e.Y);

                if (fDragged != null)
                {
                    fDragged.Fixed = true;
                }
            }
        }
示例#14
0
        private void ApplyBarnesHutRepulsion()
        {
            fBHTree.Reset();

            int nodesCount = fNodes.Count;

            for (int i = 0; i < nodesCount; i++)
            {
                ArborNode node = fNodes[i];
                fBHTree.Insert(node);
            }

            for (int i = 0; i < nodesCount; i++)
            {
                ArborNode node = fNodes[i];
                fBHTree.ApplyForces(node, fRepulsion);
            }
        }
示例#15
0
        public ArborEdge(ArborNode source, ArborNode target, double length, double stiffness, bool directed = false)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (target == null)
            {
                throw new ArgumentNullException("target");
            }

            Source    = source;
            Target    = target;
            Length    = length;
            Stiffness = stiffness;
            Directed  = directed;
        }
示例#16
0
        public void Test_ApplyForce()
        {
            var node = new ArborNode("x");

            Assert.IsNotNull(node);

            #if DEBUG
            node.V = new ArborPoint(1.0f, 1.0f);
            node.F = new ArborPoint(3.0f, 4.0f);

            node.Mass = 2.0f;
            node.ApplyForce(new ArborPoint(3.0f, 3.0f));
            Assert.AreEqual(new ArborPoint(4.5f, 5.5f), node.F);

            node.Mass = 0.0d;
            node.ApplyForce(new ArborPoint(3.0f, 3.0f));
            Assert.AreEqual(new ArborPoint(double.PositiveInfinity, double.PositiveInfinity), node.F);
            #endif
        }
示例#17
0
        public void Test_Common()
        {
            var node = new ArborNode("x");

            Assert.IsNotNull(node);

            var extensibleObj = new Vertex();

            node.Attach(extensibleObj);
            node.Detach(extensibleObj);

            Assert.AreEqual("x", node.Sign);
            Assert.AreEqual(null, node.Data);
            Assert.AreEqual(false, node.Fixed);
            Assert.AreEqual(1.0f, node.Mass);

            node.Pt = ArborPoint.Zero;
            Assert.AreEqual(ArborPoint.Zero, node.Pt);
        }
示例#18
0
 internal static int GetQuad(ArborNode node, Branch branch)
 {
     try {
         if (node.Pt.IsExploded())
         {
             return(QNone);
         }
         ArborPoint h = node.Pt.Sub(branch.Origin);
         ArborPoint g = branch.Size.Div(2.0f);
         if (h.Y < g.Y)
         {
             return((h.X < g.X) ? QNw : QNe);
         }
         else
         {
             return((h.X < g.X) ? QSw : QSe);
         }
     } catch (Exception ex) {
         Debug.WriteLine("BarnesHutTree.GetQuad(): " + ex.Message);
         return(QNone);
     }
 }
示例#19
0
 protected override ArborEdge CreateEdge(ArborNode source, ArborNode target, double length, double stiffness,
                                         bool directed = false)
 {
     return(new ArborEdge(source, target, length, stiffness, directed));
 }
示例#20
0
        public void Insert(ArborNode node)
        {
            try {
                Branch           branch = fRoot;
                List <ArborNode> gst    = new List <ArborNode>();
                gst.Add(node);
                while (gst.Count > 0)
                {
                    ArborNode h = gst[0];
                    gst.RemoveAt(0);

                    double m  = h.Mass;
                    int    qd = GetQuad(h, branch);
                    object fp = branch.Q[qd];

                    if (fp == null)
                    {
                        branch.Q[qd] = h;

                        branch.Mass += m;
                        branch.Pt    = branch.Pt.Add(h.Pt.Mul(m));
                    }
                    else
                    {
                        if (fp is Branch)
                        {
                            branch.Mass += m;
                            branch.Pt    = branch.Pt.Add(h.Pt.Mul(m));

                            branch = (Branch)fp;

                            gst.Insert(0, h);
                        }
                        else
                        {
                            ArborPoint l = branch.Size.Div(2);
                            ArborPoint n = branch.Origin;

                            if (qd == QSe || qd == QSw)
                            {
                                n.Y += l.Y;
                            }
                            if (qd == QNe || qd == QSe)
                            {
                                n.X += l.X;
                            }

                            ArborNode o = (ArborNode)fp;
                            fp           = new Branch(n, l);
                            branch.Q[qd] = fp;

                            branch.Mass = m;
                            branch.Pt   = h.Pt.Mul(m);

                            branch = (Branch)fp;

                            ArborPoint oPt = o.Pt;
                            if (oPt.X == h.Pt.X && oPt.Y == h.Pt.Y)
                            {
                                double lX = l.X * 0.08f;
                                double lY = l.Y * 0.08f;
                                oPt.X = Math.Min(n.X + l.X, Math.Max(n.X, oPt.X - lX / 2 + ArborSystem.GetRandom() * lX));
                                oPt.Y = Math.Min(n.Y + l.Y, Math.Max(n.Y, oPt.Y - lY / 2 + ArborSystem.GetRandom() * lY));
                                o.Pt  = oPt;
                            }

                            gst.Add(o);
                            gst.Insert(0, h);
                        }
                    }
                }
            } catch (Exception ex) {
                Debug.WriteLine("BarnesHutTree.Insert(): " + ex.Message);
            }
        }
示例#21
0
        private void UpdateVelocityAndPosition(double dt)
        {
            int nodesCount = fNodes.Count;

            if (nodesCount == 0)
            {
                fEnergyMax  = 0.0f;
                fEnergyMean = 0.0f;
                fEnergySum  = 0.0f;
                return;
            }

            double eMax = 0.0f;
            double eSum = 0.0f;

            // calc center drift
            ArborPoint rr = ArborPoint.Zero;

            for (int i = 0; i < nodesCount; i++)
            {
                ArborNode node = fNodes[i];
                rr = rr.Sub(node.Pt);
            }
            ArborPoint drift = rr.Div(nodesCount);

            // main updates loop
            for (int i = 0; i < nodesCount; i++)
            {
                ArborNode node = fNodes[i];

                // apply center drift
                node.ApplyForce(drift);

                // apply center gravity
                if (fGravity)
                {
                    ArborPoint q = node.Pt.Mul(-1.0f);
                    node.ApplyForce(q.Mul(fRepulsion / 100.0f));
                }

                // update velocities
                if (node.Fixed)
                {
                    node.V = ArborPoint.Zero;
                }
                else
                {
                    node.V = node.V.Add(node.F.Mul(dt));
                    node.V = node.V.Mul(1.0f - fFriction);

                    double r = node.V.MagnitudeSquare();
                    if (r > 1000000.0f)
                    {
                        node.V = node.V.Div(r);
                    }
                }

                node.F = ArborPoint.Zero;

                // update positions
                node.Pt = node.Pt.Add(node.V.Mul(dt));

                // update energy
                double energy = node.V.MagnitudeSquare();
                eSum += energy;
                eMax  = Math.Max(energy, eMax);
            }

            fEnergyMax  = eMax;
            fEnergyMean = eSum / nodesCount;
            fEnergySum  = eSum;
        }