public VoronoiMap CreateVoronoiMap(int height, int width, IEnumerable <Site> sites) { if (sites == null) { throw new ArgumentNullException("sites"); } if (sites.GroupBy(s => s.Point).Count() != sites.Count()) { throw new ArgumentException("Multiple sites with the same coordinates passed!"); } var siteList = string.Join(", ", sites.Select(s => s.Point.ToString()).ToArray()); _logger.Log($"Create Voronoi map with sites: {siteList}"); _eventQueue = new EventQueue(); _beachLine = new BeachLine(height); var map = new VoronoiMap(); _eventQueue.Initialize(sites.Select(s => s.Point)); map.AddRange(sites.Cast <IGeometry>()); while (_eventQueue.HasEvents) { var sweepEvent = _eventQueue.GetNextEvent(); var siteEvent = sweepEvent as SiteEvent; if (siteEvent != null) { _logger.Log($"Sweepline SiteEvent: {siteEvent.Point}"); var halfEdges = _siteEventHandler.HandleEvent(siteEvent, _eventQueue, _beachLine); map.AddRange(halfEdges); foreach (var geo in halfEdges) { _logger.Log($"Add {geo}"); } continue; } var circleEvent = sweepEvent as CircleEvent; if (circleEvent == null) { throw new InvalidOperationException("SweepEvent is neither SiteEvent nor CircleEvent"); } //_logger.Log($"Sweepline CircleEvent: {circleEvent.Point} for arc {circleEvent.Arc.Site}"); var circleEventResult = _circleEventHandler.HandleEvent(circleEvent, _eventQueue, _beachLine); foreach (var geo in circleEventResult) { _logger.Log($"Add {geo}"); } // Add vertex and new half edge map.AddRange(circleEventResult); } _beachLine.FinishEdge(_beachLine.Root, width); //map.FinishEdges(width); map.ConnectEdges(); _logger.Log("Finished Voronoi map creation"); foreach (var edge in map.Where(g => g is HalfEdge).Cast <HalfEdge>()) { _logger.Log(edge.ToString()); } return(map); }