Example #1
0
		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);
        }