public ArborEdge addEdge(string srcSign, string tgtSign, double len = 1.0) { ArborNode src = this.getNode(srcSign); src = (src != null) ? src : this.addNode(srcSign); ArborNode tgt = this.getNode(tgtSign); tgt = (tgt != null) ? tgt : this.addNode(tgtSign); ArborEdge x = null; if (src != null && tgt != null) { foreach (ArborEdge edge in fEdges) { if (edge.Source == src && edge.Target == tgt) { x = edge; break; } } } if (x == null) { x = new ArborEdge(src, tgt, len, ParamStiffness); fEdges.Add(x); } return(x); }
private static int getQuad(ArborNode i, Branch f) { try { if (i.Pt.exploded()) { return(QNone); } ArborPoint h = i.Pt.sub(f.Origin); ArborPoint g = f.Size.div(2); 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); } }
public ArborNode nearest(int sx, int sy) { ArborPoint x = this.fromScreen(sx, sy); ArborNode resNode = null; double minDist = +1.0; foreach (ArborNode node in this.fNodes) { ArborPoint z = node.Pt; if (z.exploded()) { continue; } double dist = z.sub(x).magnitude(); if (dist < minDist) { resNode = node; minDist = dist; } } //minDist = this.toScreen(resNode.Pt).sub(this.toScreen(x)).magnitude(); return(resNode); }
public ArborViewer() { base.BorderStyle = BorderStyle.Fixed3D; base.TabStop = true; base.BackColor = Color.White; base.DoubleBuffered = true; base.SetStyle(ControlStyles.AllPaintingInWmPaint, true); base.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); // repulsion - отталкивание, stiffness - тугоподвижность, friction - сила трения this.fSys = new ArborSystem(10000, 500 /*1000*/, 0.1, this); this.fSys.setScreenSize(this.Width, this.Height); this.fSys.AutoStop = false; this.fEnergyDebug = false; this.fDrawFont = new Font("Calibri", 9); this.fStrFormat = new StringFormat(); this.fStrFormat.Alignment = StringAlignment.Center; this.fStrFormat.LineAlignment = StringAlignment.Center; this.fBlackBrush = new SolidBrush(Color.Black); this.fWhiteBrush = new SolidBrush(Color.White); this.fDragged = null; this.fNodesDragging = false; }
protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); if (this.fNodesDragging && this.fDragged != null) { this.fDragged.Fixed = false; //this.fDragged.Mass = 1000; this.fDragged = null; } }
public RectangleF getNodeRect(Graphics gfx, ArborNode node) { SizeF tsz = gfx.MeasureString(node.Sign, fDrawFont); float w = tsz.Width + 10; float h = tsz.Height + 4; ArborPoint pt = fSys.toScreen(node.Pt); pt.X = Math.Floor(pt.X); pt.Y = Math.Floor(pt.Y); return(new RectangleF((float)pt.X - w / 2, (float)pt.Y - h / 2, w, h)); }
protected override void OnPaint(PaintEventArgs pe) { Graphics gfx = pe.Graphics; try { gfx.SmoothingMode = SmoothingMode.AntiAlias; foreach (ArborNode node in fSys.Nodes) { node.Box = this.getNodeRect(gfx, node); gfx.FillRectangle(new SolidBrush(node.Color), node.Box); gfx.DrawString(node.Sign, fDrawFont, this.fWhiteBrush, node.Box, this.fStrFormat); } using (Pen grayPen = new Pen(Color.Gray, 1)) { grayPen.StartCap = LineCap.NoAnchor; grayPen.EndCap = LineCap.ArrowAnchor; foreach (ArborEdge edge in fSys.Edges) { ArborNode srcNode = edge.Source; ArborNode tgtNode = edge.Target; ArborPoint pt1 = fSys.toScreen(srcNode.Pt); ArborPoint pt2 = fSys.toScreen(tgtNode.Pt); ArborPoint tail = intersect_line_box(pt1, pt2, srcNode.Box); ArborPoint head = (tail.isNull()) ? ArborPoint.Null : intersect_line_box(tail, pt2, tgtNode.Box); if (!head.isNull() && !tail.isNull()) { gfx.DrawLine(grayPen, (int)tail.X, (int)tail.Y, (int)head.X, (int)head.Y); } } } if (this.fEnergyDebug) { string energy = "max=" + fSys.EnergyMax.ToString("0.00000") + ", mean=" + fSys.EnergyMean.ToString("0.00000"); gfx.DrawString(energy, fDrawFont, this.fBlackBrush, 10, 10); } } catch (Exception ex) { Debug.WriteLine("ArborViewer.OnPaint(): " + ex.Message); } }
public ArborNode addNode(string sign, double x, double y) { ArborNode node = this.getNode(sign); if (node != null) { return(node); } node = new ArborNode(sign); node.Pt = new ArborPoint(x, y); fNames.Add(sign, node); fNodes.Add(node); return(node); }
protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); if (!this.Focused) { base.Focus(); } if (this.fNodesDragging) { this.fDragged = fSys.nearest(e.X, e.Y); if (this.fDragged != null) { this.fDragged.Fixed = true; } } }
public void insert(ArborNode j) { try { Branch f = fRoot; List <ArborNode> gst = new List <ArborNode>(); gst.Add(j); while (gst.Count > 0) { ArborNode h = gst[0]; gst.RemoveAt(0); double m = h.Mass; int qd = getQuad(h, f); object fp = f.Q[qd]; if (fp == null) { f.Q[qd] = h; f.Mass += m; f.Pt = f.Pt.add(h.Pt.mul(m)); } else { if (fp is Branch) { f.Mass += m; f.Pt = f.Pt.add(h.Pt.mul(m)); f = fp as Branch; gst.Insert(0, h); } else { ArborPoint l = f.Size.div(2); ArborPoint n = new ArborPoint(f.Origin.X, f.Origin.Y); if (qd == QSe || qd == QSw) { n.Y += l.Y; } if (qd == QNe || qd == QSe) { n.X += l.X; } ArborNode o = fp as ArborNode; fp = new Branch(n, l); f.Q[qd] = fp; f.Mass = m; f.Pt = h.Pt.mul(m); f = fp as Branch; if (o.Pt.X == h.Pt.X && o.Pt.Y == h.Pt.Y) { double k = l.X * 0.08; double i = l.Y * 0.08; o.Pt.X = Math.Min(n.X + l.X, Math.Max(n.X, o.Pt.X - k / 2 + ArborSystem.NextRndDouble() * k)); o.Pt.Y = Math.Min(n.Y + l.Y, Math.Max(n.Y, o.Pt.Y - i / 2 + ArborSystem.NextRndDouble() * i)); } gst.Add(o); gst.Insert(0, h); } } } } catch (Exception ex) { Debug.WriteLine("BarnesHutTree.insert(): " + ex.Message); } }
public void applyForces(ArborNode m, double g) { try { Queue <object> f = new Queue <object>(); f.Enqueue(fRoot); while (f.Count > 0) { object obj = f.Dequeue(); if (obj == null || obj == m) { continue; } ArborPoint ptx, i, k; double l, kMag, massx; if (obj is ArborNode) { ArborNode node = (obj as ArborNode); massx = node.Mass; ptx = node.Pt; k = m.Pt.sub(ptx); kMag = k.magnitudeSquare(); i = ((kMag > 0) ? k : ArborPoint.newRnd(1)).normalize(); l = Math.Max(1, kMag); m.applyForce(i.mul(g * massx).div(l)); } else { Branch branch = (obj as Branch); massx = branch.Mass; ptx = branch.Pt.div(massx); k = m.Pt.sub(ptx); kMag = k.magnitudeSquare(); double h = branch.Size.X * branch.Size.Y; if (h / kMag > fDist) { f.Enqueue(branch.Q[QNe]); f.Enqueue(branch.Q[QNw]); f.Enqueue(branch.Q[QSe]); f.Enqueue(branch.Q[QSw]); } else { i = ((kMag > 0) ? k : ArborPoint.newRnd(1)).normalize(); l = Math.Max(1, kMag); m.applyForce(i.mul(g * massx).div(l)); } } } } catch (Exception ex) { Debug.WriteLine("BarnesHutTree.applyForces(): " + ex.Message); } }
protected virtual ArborEdge CreateEdge(ArborNode src, ArborNode tgt, double len, double stiffness, bool directed = false) { return(new ArborEdge(src, tgt, len, stiffness, directed)); }