/**
   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;
				}
Beispiel #6
0
        /**
         * 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);
        }