/** BORDER means "edges from this vertex that run along the perimeter of that cell" Useful when trying to draw a path around the perimeter of a cell, in several different ways (especially: when trying to auto-close that path if it is on boundary of Diagram and has a pair of infinite / unterminated, but disconnected, edges) */ public List<VoronoiCellEdge> GetEdgesBorderingCell( VoronoiCell c ) { List<VoronoiCellEdge> result = new List<VoronoiCellEdge>(); if( !ConnectsToCell(c)) // This vertex may have an edge that touches that cell, but not border return result; foreach ( VoronoiCellEdge e in new VoronoiCellEdge[] { edge1, edge2, edge3}) { if( e == null ) continue; if( (e.edgeVertexA == this && e.edgeVertexB.ConnectsToCell(c)) || (e.edgeVertexB == this && e.edgeVertexA.ConnectsToCell(c)) ) result.Add( e ); } return result; }
public void AddCellWithSideEffects (VoronoiCell c) { /** Debug check / error checking */ if (cell1 == c || cell2 == c || cell3 == c) { Debug.LogError ("Major error: you re-added a cell ("+c.name+") to a vertex ("+this.name+") that already had that cell; this suggests you've run a cel/vertex generation algorithm twice on the same VoronoiDiagram object (should never happen!)"); } if (cell1 == null) cell1 = c; else if (cell2 == null) cell2 = c; else if (cell3 == null) cell3 = c; else { Debug.LogError ("Cannot add a fourth cell ("+c.name+") to a vertex ("+this.name+") !"); return; } Debug.Log (" vertex ("+this.name+") + cell = ("+(cell1==null?"":cell1.name)+", "+(cell2==null?"":cell2.name)+", "+(cell3==null?"":cell3.name)+") to "); }
/** The side-effects you must be aware of: 1. The cell is added to the two Vertex's on the Edge 2. If this is the 2nd Cell added, the two Cells are explicitly connected to each other internally */ public void AddCellWithSideEffects( VoronoiCell c ) { /** Add the cell or crash */ if( cell1 == null ) cell1 = c; else if( cell2 == null ) cell2 = c; else { Debug.LogError("Cannot add a third cell to an edge!"); return; } /** Add the cell to both vertices on this edge */ if( edgeVertexA == null || edgeVertexB == null ) { Debug.LogError("Fail: this edge has one or both edgeVertex nodes missing; cannot continue"); return; } else { if( ! edgeVertexA.ConnectsToCell( c ) ) // might have been added by a previous edge edgeVertexA.AddCellWithSideEffects( c ); if( ! edgeVertexB.ConnectsToCell( c ) ) // might have been added by a previous edge edgeVertexB.AddCellWithSideEffects( c ); } /** If both cells present, connect them together via this edge */ if( cell1 != null && cell2 != null ) { /* now we can join the two cells via this edge */ if( cell1.neighbours == null ) cell1.neighbours = new Dictionary<VoronoiCellEdge, VoronoiCell>(); cell1.neighbours.Add( this, cell2 ); if( cell2.neighbours == null ) cell2.neighbours = new Dictionary<VoronoiCellEdge, VoronoiCell>(); cell2.neighbours.Add( this, cell1 ); } }
public bool ConnectsToCell( VoronoiCell c ) { if( c == null ) return false; return (c == cell1 || c == cell2 || c == cell3 ); }
public VoronoiCellEdge GetOtherEdgeContainingCell (VoronoiCellEdge currentEdge, VoronoiCell targetCell) { foreach ( VoronoiCellEdge e in new VoronoiCellEdge[] { edge1, edge2, edge3}) { if( e == null ) continue; if (e == currentEdge) continue; if (e.cell1 == targetCell || e.cell2 == targetCell) return e; } if( edge3 != null ) { /** this is ONLY an error if all 3 edges existed; otherwise its an expected outcome */ Debug.LogError ("Cannot find another edge from this vertex (" + this + ") that borders cell: " + targetCell); } return null; }
/** * Stupidly, Unity in 2D mode uses co-ords incompatible with Unity in 3D mode (xy instead of xz). * * So we have to provide a boolean to switch between the two modes! */ public static VoronoiDiagram CreateDiagramFromVoronoiOutput(Voronoi voronoiGenerator, bool useUnity2DCoordsNot3D) { GameObject go = new GameObject("New VoronoiMap"); GameObject goCellHolder = new GameObject(_cellHolderName); goCellHolder.transform.parent = go.transform; GameObject goEdgeHolder = new GameObject(_edgeHolderName); goEdgeHolder.transform.parent = go.transform; GameObject goVertexHolder = new GameObject(_vertexHolderName); goVertexHolder.transform.parent = go.transform; VoronoiDiagram map = go.AddComponent <VoronoiDiagram>(); System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Reset(); watch.Start(); Dictionary <Site, VoronoiCell> generatedCells = new Dictionary <Site, VoronoiCell>(); Dictionary <Vector2, VoronoiCellVertex> generatedVertices = new Dictionary <Vector2, VoronoiCellVertex>(); int numEdgesCreated = 0; foreach (Edge edge in voronoiGenerator.Edges()) { GameObject goEdge = new GameObject("Edge-#" + (numEdgesCreated++)); goEdge.transform.parent = goEdgeHolder.transform; VoronoiCellEdge vEdge = goEdge.AddComponent <VoronoiCellEdge>(); Debug.Log("Processing edge = " + edge + " with clippedEnds = " + (edge.clippedEnds == null ? "null" : "" + edge.clippedEnds.Count)); if (!edge.visible) { Debug.Log("...Voronoi algorithm generated a non-existent edge, skipping it..."); continue; } Vector2 clippedEndLeft = (Vector2)edge.clippedEnds[Side.LEFT]; Vector2 clippedEndRight = (Vector2)edge.clippedEnds[Side.RIGHT]; vEdge.AddVertex(FetchVertexOrAddToObject(clippedEndLeft, generatedVertices, goVertexHolder, useUnity2DCoordsNot3D)); vEdge.AddVertex(FetchVertexOrAddToObject(clippedEndRight, generatedVertices, goVertexHolder, useUnity2DCoordsNot3D)); goEdge.transform.localPosition = (vEdge.edgeVertexA.transform.localPosition + vEdge.edgeVertexB.transform.localPosition) / 2.0f; Site[] bothSites = new Site[] { edge.leftSite, edge.rightSite }; foreach (Site site in bothSites) { /** Re-use or create the Cell */ VoronoiCell newCell = null; // C# is rubbish. Crashes if Dictionary lacks the key. Very bad design. if (generatedCells.ContainsKey(site)) { newCell = generatedCells[site]; } GameObject goCell; if (newCell == null) { goCell = new GameObject("Cell-#" + generatedCells.Count); goCell.transform.parent = goCellHolder.transform; goCell.transform.localPosition = new Vector3(site.Coord.x, useUnity2DCoordsNot3D ? site.Coord.y : 0, useUnity2DCoordsNot3D ? 0 : site.Coord.y); newCell = goCell.AddComponent <VoronoiCell>(); generatedCells.Add(site, newCell); } else { goCell = newCell.gameObject; } /** Now that cell is created, attach it to BOTH Vertex's on the new Edge * (so that later its easy for us to to find Cells-for-this-Vertex, and also: * for a Cell to "trace" around its edges, picking "next edge" from each Vertex * by looking at which edges from the vertex border this cell (by checking * that BOTH Vertex-ends of the edge are attached to this cell) * * Also add the edge itself to the cell, and the cell to the edge. */ vEdge.AddCellWithSideEffects(newCell); } } watch.Stop(); return(map); }