void FinishEdge(BeachNode node) { if (node.GetType() == typeof(BeachArc)) { return; } BeachEdge n = (BeachEdge)node; float mx; if (n.edge.direction.x > 0) { mx = Mathf.Max(width, n.edge.start.pos.x + 10); } else { mx = Mathf.Max(0, n.edge.start.pos.x - 10); } Vertex end = new Vertex(new Vector2(mx, mx * n.edge.f + n.edge.g)); n.edge.end = end; diagram.vertices.Add(end); diagram.edges.Add(n.edge); FinishEdge(n.left); FinishEdge(n.right); }
public void CheckCircle(BeachArc mid) { BeachEdge leftParent = BeachNode.GetLeftParent(mid); BeachEdge rightParent = BeachNode.GetRightParent(mid); BeachArc left = BeachNode.GetLeftChild(leftParent); BeachArc right = BeachNode.GetRightChild(rightParent); if (left == null || right == null || left.site == right.site) { return; } Vector2 s = GetEdgeIntersection(leftParent.edge, rightParent.edge); if (float.IsNaN(s.x) || float.IsNaN(s.y)) { return; } float dx = left.site.pos.x - s.x; float dy = left.site.pos.y - s.y; float d = Mathf.Sqrt((dx * dx) + (dy * dy)); if (s.y - d >= sweep) { return; } VertexEvent ev = new VertexEvent(left, mid, right); mid.ev = ev; events.Add(ev); }
public float GetXOfEdge(BeachEdge n, float y) { BeachArc left = BeachNode.GetLeftChild(n); BeachArc right = BeachNode.GetRightChild(n); Vector2 p = left.site.pos; Vector2 r = right.site.pos; float dp = 2f * (p.y - y); float a1 = 1f / dp; float b1 = -2f * p.x / dp; float c1 = y + dp / 4 + p.x * p.x / dp; dp = 2f * (r.y - y); float a2 = 1f / dp; float b2 = -2f * r.x / dp; float c2 = sweep + dp / 4 + r.x * r.x / dp; float a = a1 - a2; float b = b1 - b2; float c = c1 - c2; float disc = b * b - 4 * a * c; float x1 = (-b + Mathf.Sqrt(disc)) / (2 * a); float x2 = (-b - Mathf.Sqrt(disc)) / (2 * a); float xl = Mathf.Min(x1, x2); float xr = Mathf.Max(x1, x2); float ry; if (p.y < r.y) { ry = Mathf.Max(x1, x2); } else { ry = Mathf.Min(x1, x2); } return(ry); /* * if(p.x < r.x) //going L to R * { * if (r.y < p.y) * return xl; * else * return xr; * } * else * { * if (p.y < r.y) * return xr; * else * return xl; * }*/ }
public static BeachArc GetRightChild(BeachNode n) { if (n == null) { return(null); } BeachNode child = n.right; while (child.GetType() != typeof(BeachArc)) { child = child.left; } return((BeachArc)child); }
public static BeachEdge GetRightParent(BeachNode n) { BeachNode p = n.parent; BeachNode last = n; while (p.right == last) { if (p.parent == null) { return(null); } last = p; p = p.parent; } return((BeachEdge)p); }
string PrintNode(BeachNode n) { if (n.GetType() == typeof(BeachArc)) { return(((BeachArc)n).site.name + " "); } else { BeachEdge edgeNode = (BeachEdge)n; string left = PrintNode(n.left); string right = PrintNode(n.right); float x = GetXOfEdge(edgeNode, sweep); float y = edgeNode.edge.f * x + edgeNode.edge.g; return(left + "[" + x.ToString("0.0") + ", " + y.ToString("0.0") + "] " + right); } }
List <Vector2> GetBreaks(BeachNode n) { if (n.GetType() == typeof(BeachArc)) { return(new List <Vector2>()); } BeachEdge edgeNode = (BeachEdge)n; List <Vector2> left = GetBreaks(n.left); float x = GetXOfEdge(edgeNode, sweep); float y = edgeNode.edge.f * x + edgeNode.edge.g; left.Add(new Vector2(x, y)); List <Vector2> right = GetBreaks(n.right); left.AddRange(right); return(left); }
public BeachArc GetParabolaByX(float x) { BeachNode par = root; float cur = 0; while (par.GetType() != typeof(BeachArc)) { cur = GetXOfEdge((BeachEdge)par, sweep); if (cur > x) { par = par.left; } else { par = par.right; } } return((BeachArc)par); }
public BeachNode GetRight(BeachNode n) { return(GetRightChild(GetRightParent(n))); }
public BeachNode GetLeft(BeachNode n) { return(GetLeftChild(GetLeftParent(n))); }
public void Insert(Cell c) { Vertex start; Edge edge; if (root == null) { root = new BeachArc(c); return; } if (root.GetType() == typeof(BeachArc) && ((BeachArc)root).site.pos.y - c.pos.y < 1) { BeachArc temp = (BeachArc)root; root = new BeachEdge(); if (c.pos.x < temp.site.pos.x) { root.left = new BeachArc(c); root.right = temp; } else { root.left = temp; root.right = new BeachArc(c); } start = new Vertex(new Vector2(c.pos.x, GetY(temp.site.pos, c.pos.x))); diagram.vertices.Add(start); if (c.pos.x > temp.site.pos.x) { edge = new Edge(start, temp.site, c); ((BeachEdge)root).edge = edge; } else { edge = new Edge(start, c, temp.site); ((BeachEdge)root).edge = edge; } diagram.edges.Add(edge); return; } BeachArc par = GetParabolaByX(c.pos.x); if (par.ev != null) //If hit arc is the center of a triplet, remove it { events.Remove(par.ev); par.ev = null; } start = new Vertex(new Vector2(c.pos.x, GetY(par.site.pos, c.pos.x))); diagram.vertices.Add(start); Edge left = new Edge(start, par.site, c); Edge right = new Edge(start, c, par.site); left.section = right; diagram.edges.Add(left); BeachArc p0 = new BeachArc(par.site); BeachArc p1 = new BeachArc(c); BeachArc p2 = new BeachArc(par.site); BeachEdge subroot = new BeachEdge(); subroot.edge = right; if (par == par.parent.left) { par.parent.left = subroot; } else { par.parent.right = subroot; } subroot.right = p2; subroot.left = new BeachEdge(left); subroot.left.left = p0; subroot.left.right = p1; CheckCircle(p0); CheckCircle(p2); }
public void Remove(VertexEvent e) { BeachArc mid = e.arcs[1]; BeachEdge leftEdge = BeachNode.GetLeftParent(mid); BeachEdge rightEdge = BeachNode.GetRightParent(mid); BeachArc left = BeachNode.GetLeftChild(leftEdge); BeachArc right = BeachNode.GetRightChild(rightEdge); if (left.ev != null) { events.Remove(left.ev); left.ev = null; } if (right.ev != null) { events.Remove(right.ev); right.ev = null; } Vertex end = new Vertex(e.center); diagram.vertices.Add(end); leftEdge.edge.end = end; rightEdge.edge.end = end; diagram.edges.Add(leftEdge.edge); diagram.edges.Add(rightEdge.edge); BeachEdge higher = null; BeachNode par = mid; while (par != root) { par = par.parent; if (par == leftEdge) { higher = leftEdge; } if (par == rightEdge) { higher = rightEdge; } } higher.edge = new Edge(end, left.site, right.site); diagram.edges.Add(higher.edge); BeachEdge gparent = (BeachEdge)mid.parent.parent; if (mid.parent.left == mid) { if (gparent.left == mid.parent) { gparent.left = mid.parent.right; } if (gparent.right == mid.parent) { gparent.right = mid.parent.right; } } else { if (gparent.left == mid.parent) { gparent.left = mid.parent.left; } if (gparent.right == mid.parent) { gparent.right = mid.parent.left; } } CheckCircle(left); CheckCircle(right); }