public void AddEdge(VoronoiCellEdge edge, bool isAFirstBSecond) { if (pathNodes == null) { pathNodes = new List <VoronoiEdgePathNode>(); } /** When you add first edge, need to pre-add its first vertex too - but only for first edge! */ if (pathNodes.Count < 1) { if (isAFirstBSecond) { pathNodes.Add(new VoronoiEdgePathNode(edge.edgeVertexA)); } else { pathNodes.Add(new VoronoiEdgePathNode(edge.edgeVertexB)); } } pathNodes.Add(new VoronoiEdgePathNode(edge)); if (isAFirstBSecond) { pathNodes.Add(new VoronoiEdgePathNode(edge.edgeVertexB)); } else { pathNodes.Add(new VoronoiEdgePathNode(edge.edgeVertexA)); } }
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); }
public bool ContainsEdge(VoronoiCellEdge e) { if (e == null) { return(false); } return(e == edge1 || e == edge2 || e == edge3); }
public void AddEdge (VoronoiCellEdge e) { if( edge1 == null ) edge1 = e; else if( edge2 == null ) edge2 = e; else if( edge3 == null ) edge3 = e; }
public void AddEdge(VoronoiCellEdge e) { if (edge1 == null) { edge1 = e; } else if (edge2 == null) { edge2 = e; } else if (edge3 == null) { edge3 = e; } }
public void AddEdge( VoronoiCellEdge edge, bool isAFirstBSecond ) { if( pathNodes == null ) { pathNodes = new List<VoronoiEdgePathNode>(); } /** When you add first edge, need to pre-add its first vertex too - but only for first edge! */ if( pathNodes.Count < 1 ) { if( isAFirstBSecond ) pathNodes.Add ( new VoronoiEdgePathNode(edge.edgeVertexA)); else pathNodes.Add ( new VoronoiEdgePathNode(edge.edgeVertexB)); } pathNodes.Add( new VoronoiEdgePathNode(edge) ); if( isAFirstBSecond ) pathNodes.Add ( new VoronoiEdgePathNode(edge.edgeVertexB)); else pathNodes.Add ( new VoronoiEdgePathNode(edge.edgeVertexA)); }
/** AS3Delaunay library automatically gives us this, and its useless for most things, but great when * trying to make a simple mesh. * * Complex meshes would need to know the original Edge objects, so they can set vertex-colouring, * vertex-texture-blending etc (which this CANNOT provide), but we might as well make the simple * version easy while we can! * * TODO: border cells will randomly miss some of their edges because this * method stops when it hits an outside / infinite edge, and does NOT scan * through the dictionary to try and find a resume point */ //public List<Vector2> orderedPointsOnCircumference; public VoronoiEdgePath CalculateOrderedPathAroundEdges() { VoronoiEdgePath path = new VoronoiEdgePath(); /** pick a random edge */ VoronoiCellEdge firstEdge = neighbours.Keys.ToList().First(); VoronoiCellEdge currentEdge = firstEdge; path.AddEdge(currentEdge, true); // true means nextVertex will be B, false means A; you can choose, just implement next few lines appropriately! /** Trace the edge, and when yuo reach a vertex, find the only OTHER edge from * that vertex that leads to a vertex that is ALSO on this cell */ VoronoiCellVertex nextVertex = currentEdge.edgeVertexB; VoronoiCellEdge nextEdge = nextVertex.GetOtherEdgeContainingCell(currentEdge, this); while (nextEdge != firstEdge) { if (nextEdge == null) { /** We hit the end prematurely; means this Cell is on the outer edge of diagram * and is UNCLOSED. * * So we need to scan through neighbours looking for a vertex that * only has ONE edge in this cell, but is NOT the last edge (which meets that criteria too) */ foreach (KeyValuePair <VoronoiCellEdge, VoronoiCell> item in neighbours) { if (item.Key == currentEdge) { continue; // found the edge we're already on } VoronoiCellVertex newNextVertex = null; if (item.Key.edgeVertexA.GetEdgesBorderingCell(this).Count < 2) { /** we've found the other one. Now need to start from that vertex. */ newNextVertex = item.Key.edgeVertexA; } else if (item.Key.edgeVertexB.GetEdgesBorderingCell(this).Count < 2) { /** we've found the other one. Now need to start from that vertex. */ newNextVertex = item.Key.edgeVertexB; } if (newNextVertex != null) { /** Need to FORCE-ADD that vertex onto the path too, since we're jumping * the gap */ path.AddJumpToVertex(newNextVertex); nextVertex = newNextVertex; nextEdge = item.Key; } } if (nextEdge == firstEdge) // rare, but can happen! { break; // we added the forced jump to vertex, but have no more edges to add, so stop } if (nextEdge == null) { /** Something has gone badly wrong */ Debug.LogError("Major error: was trying to close the loop of an outer Cell, but couldn't find a restart point"); break; } } /** ... normal body of while loop starts here ... */ bool isNextEdgeAToB = (nextVertex == nextEdge.edgeVertexA); path.AddEdge(nextEdge, isNextEdgeAToB); if (isNextEdgeAToB) { nextVertex = nextEdge.edgeVertexB; } else { nextVertex = nextEdge.edgeVertexA; } currentEdge = nextEdge; nextEdge = nextVertex.GetOtherEdgeContainingCell(currentEdge, this); } return(path); }
public VoronoiEdgePathNode( VoronoiCellEdge e ) { nodeType = VoronoiEdgePathNodeType.EDGE; edge = e; }
public VoronoiEdgePathNode(VoronoiCellEdge e) { nodeType = VoronoiEdgePathNodeType.EDGE; edge = e; }
public bool ContainsEdge (VoronoiCellEdge e) { if( e == null ) return false; return (e == edge1 || e == edge2 || e == edge3); }
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); }