public VoronoiGraph StepVoronoi() { _graph.ResetNewItems(); if (!_edgeFixup) { if (!_eventQueue.IsEmpty) { _newIntStar = _eventQueue.Min(); } if (_newSite != null && (_eventQueue.IsEmpty || /*Geometry.CompareByYThenX(_newSite, _newIntStar)*/ _newSite.CompareTo(_newIntStar) < 0)) { _graph.PlotSite(_newSite); var lbnd = _edgeList.LeftBound(_newSite); var rbnd = lbnd.Right; var bot = _edgeList.RightRegion(lbnd); var e = Edge.CreateBisectingEdge(bot, _newSite); _graph.PlotBisector(e); var bisector = new HalfEdge(e, Side.Left); EdgeList.Insert(lbnd, bisector); var p = Site.CreateIntersectingSite(lbnd, bisector); if (p != null) { _eventQueue.Delete(lbnd); if (_graph.Debug) { Console.WriteLine("Inserting {0}", p); } _eventQueue.Insert(lbnd, p, Site.Distance(p, _newSite)); } lbnd = bisector; bisector = new HalfEdge(e, Side.Right); EdgeList.Insert(lbnd, bisector); p = Site.CreateIntersectingSite(bisector, rbnd); if (p != null) { if (_graph.Debug) { Console.WriteLine("Inserting {0}", p); } _eventQueue.Insert(bisector, p, Site.Distance(p, _newSite)); } _newSite = _sites.ExtractMin(); if (_newSite != null && _newSite.Y > _graph.SweepLine) { _graph.SweepLine = _newSite.Y; } else if (_newSite == null) { _graph.SweepLine = _graph.Height; } } else if (!_eventQueue.IsEmpty) // intersection is smallest { var lbnd = _eventQueue.ExtractMin(); var llbnd = lbnd.Left; var rbnd = lbnd.Right; var rrbnd = rbnd.Right; var bot = _edgeList.LeftRegion(lbnd); var top = _edgeList.RightRegion(rbnd); _graph.PlotTriple(bot, top, _edgeList.RightRegion(lbnd)); var v = lbnd.Vertex; _graph.PlotVertex(v); _graph.EndPoint(lbnd.Edge, lbnd.Side, v); _graph.EndPoint(rbnd.Edge, rbnd.Side, v); EdgeList.Delete(lbnd); _eventQueue.Delete(rbnd); EdgeList.Delete(rbnd); var pm = Side.Left; if (bot.Y > top.Y) { var temp = bot; bot = top; top = temp; pm = Side.Right; } var e = Edge.CreateBisectingEdge(bot, top); _graph.PlotBisector(e); var bisector = new HalfEdge(e, pm); EdgeList.Insert(llbnd, bisector); _graph.EndPoint(e, pm == Side.Left ? Side.Right : Side.Left, v); var p = Site.CreateIntersectingSite(llbnd, bisector); if (p != null) { _eventQueue.Delete(llbnd); if (_graph.Debug) { Console.WriteLine("Inserting {0}", p); } _eventQueue.Insert(llbnd, p, Site.Distance(p, bot)); } p = Site.CreateIntersectingSite(bisector, rrbnd); if (p != null) { if (_graph.Debug) { Console.WriteLine("Inserting {0}", p); } _eventQueue.Insert(bisector, p, Site.Distance(p, bot)); } } else { _edgeFixup = true; } StepNumber++; } else { var lbnd = _edgeList.LeftEnd.Right; if (lbnd != _edgeList.RightEnd) { var e = lbnd.Edge; _graph.PlotEndpoint(e); EdgeList.Delete(lbnd); StepNumber++; } else { foreach (var edge in _graph.Edges) { edge.ClipVertices(new Rectangle(0, 0, _graph.Width, _graph.Height)); } if (_graph.Debug) { Console.WriteLine("Done computing graph!"); } } } if (_graph.Debug) { Console.WriteLine("Step: " + StepNumber); } return(_graph); }
public static VoronoiGraph ComputeVoronoiGraph(IEnumerable <PointF> points, int w = 800, int h = 600, bool debug = false) { var sites = new SiteList(points); if (debug) { sites.LogSites(); } var graph = new VoronoiGraph(w, h) { Debug = debug }; try { var edgeList = new EdgeList(sites); var eventQueue = new EventQueue(); sites.BottomSite = sites.ExtractMin(); graph.PlotSite(sites.BottomSite); var newSite = sites.ExtractMin(); var newIntStar = new Site(Single.MaxValue, Single.MaxValue); while (true) { if (!eventQueue.IsEmpty) { newIntStar = eventQueue.Min(); } if (newSite != null && (eventQueue.IsEmpty || newSite.CompareTo(newIntStar) < 0)) { // new site is smallest graph.PlotSite(newSite); var lbnd = edgeList.LeftBound(newSite); var rbnd = lbnd.Right; var bot = edgeList.RightRegion(lbnd); var e = Edge.CreateBisectingEdge(bot, newSite); graph.PlotBisector(e); var bisector = new HalfEdge(e, Side.Left); EdgeList.Insert(lbnd, bisector); var p = Site.CreateIntersectingSite(lbnd, bisector); if (p != null) { eventQueue.Delete(lbnd); if (debug) { Console.WriteLine("Inserting {0}", p); } eventQueue.Insert(lbnd, p, Site.Distance(p, newSite)); } lbnd = bisector; bisector = new HalfEdge(e, Side.Right); EdgeList.Insert(lbnd, bisector); p = Site.CreateIntersectingSite(bisector, rbnd); if (p != null) { if (debug) { Console.WriteLine("Inserting {0}", p); } eventQueue.Insert(bisector, p, Site.Distance(p, newSite)); } newSite = sites.ExtractMin(); } else if (!eventQueue.IsEmpty) { // intersection is smallest var lbnd = eventQueue.ExtractMin(); var llbnd = lbnd.Left; var rbnd = lbnd.Right; var rrbnd = rbnd.Right; var bot = edgeList.LeftRegion(lbnd); var top = edgeList.RightRegion(rbnd); graph.PlotTriple(bot, top, edgeList.RightRegion(lbnd)); var v = lbnd.Vertex; graph.PlotVertex(v); graph.EndPoint(lbnd.Edge, lbnd.Side, v); graph.EndPoint(rbnd.Edge, rbnd.Side, v); EdgeList.Delete(lbnd); eventQueue.Delete(rbnd); EdgeList.Delete(rbnd); var pm = Side.Left; if (bot.Y > top.Y) { var temp = bot; bot = top; top = temp; pm = Side.Right; } var e = Edge.CreateBisectingEdge(bot, top); graph.PlotBisector(e); var bisector = new HalfEdge(e, pm); EdgeList.Insert(llbnd, bisector); graph.EndPoint(e, Side.Other(pm), v); var p = Site.CreateIntersectingSite(llbnd, bisector); if (p != null) { eventQueue.Delete(llbnd); if (debug) { Console.WriteLine("Inserting {0}", p); } eventQueue.Insert(llbnd, p, Site.Distance(p, bot)); } p = Site.CreateIntersectingSite(bisector, rrbnd); if (p != null) { if (debug) { Console.WriteLine("Inserting {0}", p); } eventQueue.Insert(bisector, p, Site.Distance(p, bot)); } } else { break; } } for (var lbnd = edgeList.LeftEnd.Right; lbnd != edgeList.RightEnd; lbnd = lbnd.Right) { var e = lbnd.Edge; graph.PlotEndpoint(e); } } catch (Exception ex) { Console.WriteLine("########################################"); Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } graph.SweepLine = graph.Height; graph.ResetNewItems(); foreach (var edge in graph.Edges) { edge.ClipVertices(new Rectangle(0, 0, w, h)); } return(graph); }