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 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; } }