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); } }
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); } }
public BarnesHutTree(ArborPoint lt, ArborPoint rb, double dist) { fDist = dist; fRoot = new Branch(lt, rb.Sub(lt)); }
public static ArborPoint IntersectLineLine(ArborPoint p1, ArborPoint p2, ArborPoint p3, ArborPoint p4) { double denom = ((p4.Y - p3.Y) * (p2.X - p1.X) - (p4.X - p3.X) * (p2.Y - p1.Y)); if (denom == 0.0f) { return(ArborPoint.Null); // lines are parallel } double ua = ((p4.X - p3.X) * (p1.Y - p3.Y) - (p4.Y - p3.Y) * (p1.X - p3.X)) / denom; double ub = ((p2.X - p1.X) * (p1.Y - p3.Y) - (p2.Y - p1.Y) * (p1.X - p3.X)) / denom; if (ua < 0.0f || ua > 1.0f || ub < 0.0f || ub > 1.0f) { return(ArborPoint.Null); } return(new ArborPoint(p1.X + ua * (p2.X - p1.X), p1.Y + ua * (p2.Y - p1.Y))); }
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; }
public ArborNode AddNode(string sign) { ArborPoint pt = NewRandomPoint(); return(AddNode(sign, pt)); }
public PSBounds(ArborPoint leftTop, ArborPoint rightBottom) { LeftTop = leftTop; RightBottom = rightBottom; }
internal void ApplyForce(ArborPoint a) { F = F.Add(a.Div(Mass)); }