private NodeHalfEdge addEdge(Dictionary <Vector3, List <NodeHalfEdge> > edgesByStartPosition, NodeHalfEdge previous, Vector3 start, Vector3 end, Node node)
    {
        var currentEdge = new NodeHalfEdge {
            node = node
        };

        if (!points.Contains(start))
        {
            points.Add(start);
        }
        if (!points.Contains(end))
        {
            points.Add(end);
        }

        currentEdge.destination = end;

        if (!edgesByStartPosition.ContainsKey(start))
        {
            edgesByStartPosition.Add(start, new List <NodeHalfEdge>());
        }
        edgesByStartPosition[start].Add(currentEdge);

        edges.Add(currentEdge);

        if (previous != null)
        {
            previous.next        = currentEdge;
            currentEdge.previous = previous;
        }
        return(currentEdge);
    }
    private void generateGraph(Voronoi voronoi)
    {
        points = new HashSet <Vector3>();
        nodes  = new HashSet <Node>();
        edges  = new List <NodeHalfEdge>();

        var edgesByStartPosition = new Dictionary <Vector3, List <NodeHalfEdge> >();
        var siteEdges            = new Dictionary <Vector2, List <LineSegment> >();

        foreach (var edge in voronoi.Edges())
        {
            if (edge.visible)
            {
                var p1      = edge.clippedEnds[Delaunay.LR.Side.LEFT];
                var p2      = edge.clippedEnds[Delaunay.LR.Side.RIGHT];
                var segment = new LineSegment(p1, p2);

                if (Vector2.Distance(p1.Value, p2.Value) < 0.001f)
                {
                    continue;
                }

                if (edge.leftSite != null)
                {
                    if (!siteEdges.ContainsKey(edge.leftSite.Coord))
                    {
                        siteEdges.Add(edge.leftSite.Coord, new List <LineSegment>());
                    }
                    siteEdges[edge.leftSite.Coord].Add(segment);
                }
                if (edge.rightSite != null)
                {
                    if (!siteEdges.ContainsKey(edge.rightSite.Coord))
                    {
                        siteEdges.Add(edge.rightSite.Coord, new List <LineSegment>());
                    }
                    siteEdges[edge.rightSite.Coord].Add(segment);
                }
            }
        }

        foreach (var site in voronoi.SiteCoords())
        {
            var boundries   = getBoundriesForSite(siteEdges, site);
            var center      = getPointWithElevation(site);
            var currentNode = new Node {
                centerPoint = center
            };
            nodes.Add(currentNode);

            NodeHalfEdge firstEdge    = null;
            NodeHalfEdge previousEdge = null;

            for (var i = 0; i < boundries.Count; i++)
            {
                var edge = boundries[i];

                var start = getPointWithElevation(edge.p0.Value);
                var end   = getPointWithElevation(edge.p1.Value);
                if (start == end)
                {
                    continue;
                }

                previousEdge = addEdge(edgesByStartPosition, previousEdge, start, end, currentNode);
                if (firstEdge == null)
                {
                    firstEdge = previousEdge;
                }
                if (currentNode.startEdge == null)
                {
                    currentNode.startEdge = previousEdge;
                }

                // figure out if the two edges meet, and if not then insert some more edges to close the polygon
                if (i < boundries.Count - 1)
                {
                    start = getPointWithElevation(edge.p1.Value);
                    end   = getPointWithElevation(boundries[i + 1].p0.Value);
                }
                else if (i == boundries.Count - 1)
                {
                    start = getPointWithElevation(edge.p1.Value);
                    end   = getPointWithElevation(boundries[0].p0.Value);
                }
                if (start != end)
                {
                    previousEdge = addEdge(edgesByStartPosition, previousEdge, previousEdge.destination, end, currentNode);
                }
            }
            // Connect up the end of the loop
            previousEdge.next  = firstEdge;
            firstEdge.previous = previousEdge;
        }

        connectOpposites(edgesByStartPosition);
    }