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); }
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); }
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); }
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); } }
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); }
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); }
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); } }
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)); }
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); }
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); }
protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); if (fNodesDragging && fDragged != null) { fDragged.Fixed = false; fDragged = null; } }
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); }
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; } } }
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); } }
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; }
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 }
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); }
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); } }
protected override ArborEdge CreateEdge(ArborNode source, ArborNode target, double length, double stiffness, bool directed = false) { return(new ArborEdge(source, target, length, stiffness, directed)); }
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); } }
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; }