private void pushGraphEdge( Site leftSite, Site rightSite, double x1, double y1, double x2, double y2 ) { GraphEdge newEdge = new GraphEdge (); allEdges.Add ( newEdge ); newEdge.x1 = x1; newEdge.y1 = y1; newEdge.x2 = x2; newEdge.y2 = y2; newEdge.site1 = leftSite.sitenbr; newEdge.site2 = rightSite.sitenbr; }
/// <summary> /// Calculate cell-mesh from list of edges of Voronoi graph /// </summary> /// <param name="zonesCoords">Coords of center of every cell</param> /// <param name="edges">All edges of Voronoi diagram</param> /// <returns>Mesh of cells</returns> private static Cell[] ProcessVoronoi(Vector2[] zonesCoords, GraphEdge[] edges, Bounds bounds) { var timer = Stopwatch.StartNew(); //Clear duplicate edges (some open cell cases) edges = edges.Distinct(GraphEdgeComparer.Default).ToArray(); //Clear zero length edges (some open cell cases) edges = edges.Where(e => e.x1 != e.x2 && e.y1 != e.y2).ToArray(); //Prepare temp collection for sorting cell edges clockwise var cellsEdges = new List <GraphEdge> [zonesCoords.Length]; for (var i = 0; i < cellsEdges.Length; i++) { cellsEdges[i] = new List <GraphEdge>(); } //Fill edge sort collection foreach (var graphEdge in edges) { cellsEdges[graphEdge.site1].Add(graphEdge); cellsEdges[graphEdge.site2].Add(graphEdge); } var isCellsClosed = new bool[zonesCoords.Length]; //For every cell: rotate edges clockwise, sort edges clockwise, check if cell is closed for (int cellIndex = 0; cellIndex < cellsEdges.Length; cellIndex++) { var cellEdges = cellsEdges[cellIndex]; for (var edgeIndex = 0; edgeIndex < cellEdges.Count; edgeIndex++) { var edge = cellEdges[edgeIndex]; if (ClockWiseComparer(new Vector2((float)edge.x1, (float)edge.y1), new Vector2((float)edge.x2, (float)edge.y2), zonesCoords[cellIndex]) > 0) { //Inverse direction of edge cellEdges[edgeIndex] = new GraphEdge() { site1 = edge.site1, site2 = edge.site2, x1 = edge.x2, y1 = edge.y2, x2 = edge.x1, y2 = edge.y1 }; } } //Sort all edges clockwise var zoneCenter = zonesCoords[cellIndex]; cellEdges.Sort((e1, e2) => ClockWiseComparer(new Vector2((float)e1.x1, (float)e1.y1), new Vector2((float)e2.x1, (float)e2.y1), zoneCenter) ); var isCellClosed = false; //So, we get edges in clockwise order, check if cell is closed if (cellEdges.Count > 2) { isCellClosed = true; for (int i = 0; i < cellEdges.Count; i++) { var edge = cellEdges[i]; var nextEdge = cellEdges[(i + 1) % cellEdges.Count]; if (Math.Abs(edge.x2 - nextEdge.x1) > 0.1 || Math.Abs(edge.y2 - nextEdge.y1) > 0.1) { isCellClosed = false; break; } } } isCellsClosed[cellIndex] = isCellClosed; Assert.IsTrue(!isCellClosed || cellEdges.Count >= 3, "Closed sell with < 3 edges!!"); } //Fill result cellmesh var result = new Cell[zonesCoords.Length]; //Create cells for (int i = 0; i < result.Length; i++) { var vertices = isCellsClosed[i] ? cellsEdges[i].Select(e => new Vector2((float)e.x1, (float)e.y1)).ToArray() : cellsEdges[i].SelectMany(e => new[] { new Vector2((float)e.x1, (float)e.y1), new Vector2((float)e.x2, (float)e.y2) }).Distinct().ToArray(); var cellEdges = (cellsEdges[i].Select(e => new Cell.Edge( new Vector2((float)e.x1, (float)e.y1), new Vector2((float)e.x2, (float)e.y2)))).ToArray(); result[i] = new Cell(i, zonesCoords[i], isCellsClosed[i], vertices, cellEdges, bounds); } //Fill cells references for (int i = 0; i < result.Length; i++) { var cell = result[i]; var cellEdges = cellsEdges[i]; cell.Init(cellEdges.Select(e => e.site1 == cell.Id ? result[e.site2] : result[e.site1]).ToArray()); } timer.Stop(); Debug.Log(string.Format("Cellmesh calculated for {0} msec", timer.ElapsedMilliseconds)); return(result); }