public static double LeftBreakPoint(RedBlackTree arc, double directrix) { var site = arc.Site; var rfocx = site.X; var rfocy = site.Y; var pby2 = rfocy - directrix; if (pby2 == 0) { return(rfocx); } var lArc = arc.P; if (lArc == null) { return(double.MinValue); } site = lArc.Site; var lfocx = site.X; var lfocy = site.Y; var plby2 = lfocy - directrix; if (plby2 == 0) { return(lfocx); } var hl = lfocx - rfocx; var aby2 = 1 / pby2 - 1 / plby2; var b = hl / plby2; if (aby2 != 0) { return((-b + Math.Sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx); } return((rfocx + lfocx) / 2); }
public static void AddBeach(ref Dictionary <int, Cell> cells, ref RedBlackTree circles, ref RedBlackTree beaches, ref List <Edge> edges, Point site) { var x = site.X; var directrix = site.Y; RedBlackTree lArc = null; RedBlackTree rArc = null; var dxl = 0d; var dxr = 0d; var node = beaches._; while (node != null) { dxl = LeftBreakPoint(node, directrix) - x; if (dxl > Diagram.Epsilon) { node = node.L; } else { dxr = x - RightBreakPoint(node, directrix); if (dxr > Diagram.Epsilon) { if (node.R == null) { lArc = node; break; } node = node.R; } else { if (dxl > -Diagram.Epsilon) { lArc = node.P; rArc = node; } else if (dxr > -Diagram.Epsilon) { lArc = node; rArc = node.N; } else { lArc = rArc = node; } break; } } } Cell.CreateCell(ref cells, site); var newArc = CreateBeach(site); beaches.Insert(lArc, newArc); if (lArc == null && rArc == null) { return; } if (lArc == rArc) { Circle.DetachCircle(ref circles, lArc); rArc = CreateBeach(lArc.Site); beaches.Insert(newArc, rArc); newArc.Edge = rArc.Edge = Edge.CreateEdge(ref cells, ref edges, lArc.Site, newArc.Site); Circle.AttachCircle(ref circles, lArc); Circle.AttachCircle(ref circles, rArc); return; } if (rArc == null) { // && lArc newArc.Edge = Edge.CreateEdge(ref cells, ref edges, lArc.Site, newArc.Site); return; } // else lArc !== rArc Circle.DetachCircle(ref circles, lArc); Circle.DetachCircle(ref circles, rArc); var lSite = lArc.Site; var ax = lSite.X; var ay = lSite.Y; var bx = site.X - ax; var by = site.Y - ay; var rSite = rArc.Site; var cx = rSite.X - ax; var cy = rSite.Y - ay; var d = 2 * (bx * cy - by * cx); var hb = bx * bx + by * by; var hc = cx * cx + cy * cy; var vertex = new Point((cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay); rArc.Edge = Edge.SetEdgeEnd(rArc.Edge, lSite, rSite, vertex); newArc.Edge = Edge.CreateEdge(ref cells, ref edges, lSite, site, null, vertex); rArc.Edge = Edge.CreateEdge(ref cells, ref edges, site, rSite, null, vertex); Circle.AttachCircle(ref circles, lArc); Circle.AttachCircle(ref circles, rArc); }
public static void RemoveBeach(ref Dictionary <int, Cell> cells, ref List <Edge> edges, ref RedBlackTree beaches, ref RedBlackTree circles, RedBlackTree beach) { var circle = beach.Circle; var x = circle.X; var y = circle.CY; var vertex = new Point(x, y); var previous = beach.P; var next = beach.N; var disappearing = new List <RedBlackTree>() { beach }; DetachBeach(ref circles, ref beaches, beach); var lArc = previous; while (lArc.Circle != null && Math.Abs(x - lArc.Circle.X) < Diagram.Epsilon && Math.Abs(y - lArc.Circle.CY) < Diagram.Epsilon) { previous = lArc.P; disappearing.Insert(0, lArc); DetachBeach(ref circles, ref beaches, lArc); lArc = previous; } disappearing.Insert(0, lArc); Circle.DetachCircle(ref circles, lArc); var rArc = next; while (rArc.Circle != null && Math.Abs(x - rArc.Circle.X) < Diagram.Epsilon && Math.Abs(y - rArc.Circle.CY) < Diagram.Epsilon) { next = rArc.N; disappearing.Add(rArc); DetachBeach(ref circles, ref beaches, rArc); rArc = next; } disappearing.Add(rArc); Circle.DetachCircle(ref circles, rArc); int nArcs = disappearing.Count; int iArc; for (iArc = 1; iArc < nArcs; ++iArc) { rArc = disappearing[iArc]; lArc = disappearing[iArc - 1]; rArc.Edge = Edge.SetEdgeEnd(rArc.Edge, lArc.Site, rArc.Site, vertex); } lArc = disappearing[0]; rArc = disappearing[nArcs - 1]; rArc.Edge = Edge.CreateEdge(ref cells, ref edges, lArc.Site, rArc.Site, null, vertex); Circle.AttachCircle(ref circles, lArc); Circle.AttachCircle(ref circles, rArc); }
public static void DetachBeach(ref RedBlackTree circles, ref RedBlackTree beaches, RedBlackTree beach) { Circle.DetachCircle(ref circles, beach); beaches.Remove(beach); Beach.BeachPool.Add(beach); beach.Reset(); }
public void Insert(RedBlackTree after, RedBlackTree node) { RedBlackTree parent = null; RedBlackTree grandpa = null; RedBlackTree uncle = null; if (after != null) { node.P = after; node.N = after.N; if (after.N != null) { after.N.P = node; } after.N = node; if (after.R != null) { after = after.R; while (after.L != null) { after = after.L; } after.L = node; } else { after.R = node; } parent = after; } else if (this._ != null) { after = RedBlackFirst(this._); node.P = null; node.N = after; after.P = after.L = node; parent = after; } else { node.P = node.N = null; this._ = node; parent = null; } node.L = node.R = null; node.U = parent; node.C = true; after = node; while (parent != null && parent.C) { grandpa = parent.U; if (parent == grandpa.L) { uncle = grandpa.R; if (uncle != null && uncle.C) { parent.C = uncle.C = false; grandpa.C = true; after = grandpa; } else { if (after == parent.R) { RedBlackRotateLeft(this, parent); after = parent; parent = after.U; } parent.C = false; grandpa.C = true; RedBlackRotateRight(this, grandpa); } } else { uncle = grandpa.L; if (uncle != null && uncle.C) { parent.C = uncle.C = false; grandpa.C = true; after = grandpa; } else { if (after == parent.L) { RedBlackRotateRight(this, parent); after = parent; parent = after.U; } parent.C = false; grandpa.C = true; RedBlackRotateLeft(this, grandpa); } } parent = after.U; } this._.C = false; }
public void Reset() { U = L = R = P = N = null; C = false; }
public void Remove(RedBlackTree node) { if (node.N != null) { node.N.P = node.P; } if (node.P != null) { node.P.N = node.N; } node.N = node.P = null; RedBlackTree parent = node.U; RedBlackTree sibling = null; RedBlackTree left = node.L; RedBlackTree right = node.R; RedBlackTree next = null; bool red = false; if (left == null) { next = right; } else if (right == null) { next = left; } else { next = RedBlackFirst(right); } if (parent != null) { if (parent.L == node) { parent.L = next; } else { parent.R = next; } } else { this._ = next; } if (left != null && right != null) { red = next.C; next.C = node.C; next.L = left; left.U = next; if (next != right) { parent = next.U; next.U = node.U; node = next.R; parent.L = node; next.R = right; right.U = next; } else { next.U = parent; parent = next; node = next.R; } } else { red = node.C; node = next; } if (node != null) { node.U = parent; } if (red) { return; } if (node != null && node.C) { node.C = false; return; } do { if (node == this._) { break; } if (node == parent.L) { sibling = parent.R; if (sibling.C) { sibling.C = false; parent.C = true; RedBlackRotateLeft(this, parent); sibling = parent.R; } if ((sibling.L != null && sibling.L.C) || (sibling.R != null && sibling.R.C)) { if (sibling.R == null || !sibling.R.C) { sibling.L.C = false; sibling.C = true; RedBlackRotateRight(this, sibling); sibling = parent.R; } sibling.C = parent.C; parent.C = sibling.R.C = false; RedBlackRotateLeft(this, parent); node = this._; break; } } else { sibling = parent.L; if (sibling.C) { sibling.C = false; parent.C = true; RedBlackRotateRight(this, parent); sibling = parent.L; } if ((sibling.L != null && sibling.L.C) || (sibling.R != null && sibling.R.C)) { if (sibling.L == null || !sibling.L.C) { sibling.R.C = false; sibling.C = true; RedBlackRotateLeft(this, sibling); sibling = parent.L; } sibling.C = parent.C; parent.C = sibling.L.C = false; RedBlackRotateRight(this, parent); node = this._; break; } } sibling.C = true; node = parent; parent = parent.U; } while (!node.C); if (node != null) { node.C = false; } }
public static void AttachCircle(ref RedBlackTree circles, RedBlackTree arc) { var lArc = arc.P; var rArc = arc.N; if (lArc == null || rArc == null) { return; } var lSite = lArc.Site; var cSite = arc.Site; var rSite = rArc.Site; if (lSite == rSite) { return; } var bx = cSite.X; var by = cSite.Y; var ax = lSite.X - bx; var ay = lSite.Y - by; var cx = rSite.X - bx; var cy = rSite.Y - by; var d = 2 * (ax * cy - ay * cx); if (d >= -Diagram.Epsilon2) { return; } var ha = ax * ax + ay * ay; var hc = cx * cx + cy * cy; var x = (cy * ha - ay * hc) / d; var y = (ax * hc - cx * ha) / d; RedBlackTree circle = null; if (Circle.CirclePool.Any()) { circle = Circle.CirclePool.Last(); Circle.CirclePool.Remove(circle); } else { circle = new RedBlackTree(); } circle.Arc = arc; circle.Site = cSite; circle.X = x + bx; circle.Y = (circle.CY = y + by) + Math.Sqrt(x * x + y * y); // y bottom arc.Circle = circle; RedBlackTree before = null; var node = circles._; while (node != null) { if (circle.Y < node.Y || (circle.Y == node.Y && circle.X <= node.X)) { if (node.L != null) { node = node.L; } else { before = node.P; break; } } else { if (node.R != null) { node = node.R; } else { before = node; break; } } } circles.Insert(before, circle); if (before == null) { FirstCircle = circle; } }