public static List <VoronoiCell> GenerateVoronoiDiagram(List <Vector3> sites)
        {
            //First generate the delaunay triangulation
            List <Triangle> triangles = TriangulateByFlippingEdges(sites);


            //Generate the voronoi diagram

            //Step 1. For every delaunay edge, compute a voronoi edge
            //The voronoi edge is the edge connecting the circumcenters of two neighboring delaunay triangles
            List <VoronoiEdge> voronoiEdges = new List <VoronoiEdge>();

            for (int i = 0; i < triangles.Count; i++)
            {
                Triangle t = triangles[i];

                //Each triangle consists of these edges
                HalfEdge e1 = t.halfEdge;
                HalfEdge e2 = e1.nextEdge;
                HalfEdge e3 = e2.nextEdge;

                //Calculate the circumcenter for this triangle
                Vector3 v1 = e1.v.position;
                Vector3 v2 = e2.v.position;
                Vector3 v3 = e3.v.position;

                //The circumcenter is the center of a circle where the triangles corners is on the circumference of that circle
                //The .XZ() is an extension method that removes the y value of a vector3 so it becomes a vector2
                Vector2 center2D = CalculateCircleCenter(new Vector2(v1.x, v1.z), new Vector2(v2.x, v2.z), new Vector2(v3.x, v3.z));

                //The circumcenter is also known as a voronoi vertex, which is a position in the diagram where we are equally
                //close to the surrounding sites
                Vector3 voronoiVertex = new Vector3(center2D.x, 0f, center2D.y);

                TryAddVoronoiEdgeFromTriangleEdge(e1, voronoiVertex, voronoiEdges);
                TryAddVoronoiEdgeFromTriangleEdge(e2, voronoiVertex, voronoiEdges);
                TryAddVoronoiEdgeFromTriangleEdge(e3, voronoiVertex, voronoiEdges);
            }


            //Step 2. Find the voronoi cells where each cell is a list of all edges belonging to a site
            List <VoronoiCell> voronoiCells = new List <VoronoiCell>();

            for (int i = 0; i < voronoiEdges.Count; i++)
            {
                VoronoiEdge e = voronoiEdges[i];

                //Find the position in the list of all cells that includes this site
                int cellPos = TryFindCellPos(e, voronoiCells);

                //No cell was found so we need to create a new cell
                if (cellPos == -1)
                {
                    VoronoiCell newCell = new VoronoiCell(e.sitePos);

                    voronoiCells.Add(newCell);

                    newCell.edges.Add(e);
                }
                else
                {
                    voronoiCells[cellPos].edges.Add(e);
                }
            }


            return(voronoiCells);
        }
        public static List <Triangle> TriangulatePoints(List <Vertex> points)
        {
            List <Triangle> triangles = new List <Triangle>();

            //Sort the points along x-axis
            //OrderBy is always soring in ascending order - use OrderByDescending to get in the other order
            points = points.OrderBy(n => n.position.x).ToList();

            //The first 3 vertices are always forming a triangle
            Triangle newTriangle = new Triangle(points[0].position, points[1].position, points[2].position);

            triangles.Add(newTriangle);

            //All edges that form the triangles, so we have something to test against
            List <Edge> edges = new List <Edge>();

            edges.Add(new Edge(newTriangle.v1, newTriangle.v2));
            edges.Add(new Edge(newTriangle.v2, newTriangle.v3));
            edges.Add(new Edge(newTriangle.v3, newTriangle.v1));

            //Add the other triangles one by one
            //Starts at 3 because we have already added 0,1,2
            for (int i = 3; i < points.Count; i++)
            {
                Vector3 currentPoint = points[i].position;

                //The edges we add this loop or we will get stuck in an endless loop
                List <Edge> newEdges = new List <Edge>();

                //Is this edge visible? We only need to check if the midpoint of the edge is visible
                for (int j = 0; j < edges.Count; j++)
                {
                    Edge currentEdge = edges[j];

                    Vector3 midPoint = (currentEdge.v1.position + currentEdge.v2.position) / 2f;

                    Edge edgeToMidpoint = new Edge(currentPoint, midPoint);

                    //Check if this line is intersecting
                    bool canSeeEdge = true;

                    for (int k = 0; k < edges.Count; k++)
                    {
                        //Dont compare the edge with itself
                        if (k == j)
                        {
                            continue;
                        }

                        if (AreEdgesIntersecting(edgeToMidpoint, edges[k]))
                        {
                            canSeeEdge = false;

                            break;
                        }
                    }

                    //This is a valid triangle
                    if (canSeeEdge)
                    {
                        Edge edgeToPoint1 = new Edge(currentEdge.v1, new Vertex(currentPoint));
                        Edge edgeToPoint2 = new Edge(currentEdge.v2, new Vertex(currentPoint));

                        newEdges.Add(edgeToPoint1);
                        newEdges.Add(edgeToPoint2);

                        Triangle newTri = new Triangle(edgeToPoint1.v1, edgeToPoint1.v2, edgeToPoint2.v1);

                        triangles.Add(newTri);
                    }
                }


                for (int j = 0; j < newEdges.Count; j++)
                {
                    edges.Add(newEdges[j]);
                }
            }


            return(triangles);
        }
        private static void FlipEdge(HalfEdge one)
        {
            //The data we need
            //This edge's triangle
            HalfEdge two   = one.nextEdge;
            HalfEdge three = one.prevEdge;
            //The opposite edge's triangle
            HalfEdge four = one.oppositeEdge;
            HalfEdge five = one.oppositeEdge.nextEdge;
            HalfEdge six  = one.oppositeEdge.prevEdge;
            //The vertices
            Vertex a = one.v;
            Vertex b = one.nextEdge.v;
            Vertex c = one.prevEdge.v;
            Vertex d = one.oppositeEdge.nextEdge.v;



            //Flip

            //Change vertex
            a.halfEdge = one.nextEdge;
            c.halfEdge = one.oppositeEdge.nextEdge;

            //Change half-edge
            //Half-edge - half-edge connections
            one.nextEdge = three;
            one.prevEdge = five;

            two.nextEdge = four;
            two.prevEdge = six;

            three.nextEdge = five;
            three.prevEdge = one;

            four.nextEdge = six;
            four.prevEdge = two;

            five.nextEdge = one;
            five.prevEdge = three;

            six.nextEdge = two;
            six.prevEdge = four;

            //Half-edge - vertex connection
            one.v   = b;
            two.v   = b;
            three.v = c;
            four.v  = d;
            five.v  = d;
            six.v   = a;

            //Half-edge - triangle connection
            Triangle t1 = one.t;
            Triangle t2 = four.t;

            one.t   = t1;
            three.t = t1;
            five.t  = t1;

            two.t  = t2;
            four.t = t2;
            six.t  = t2;

            //Opposite-edges are not changing!

            //Triangle connection
            t1.v1 = b;
            t1.v2 = c;
            t1.v3 = d;

            t2.v1 = b;
            t2.v2 = d;
            t2.v3 = a;

            t1.halfEdge = three;
            t2.halfEdge = four;
        }
        public static List <HalfEdge> TransformFromTriangleToHalfEdge(List <Triangle> triangles)
        {
            //Make sure the triangles have the same orientation
            OrientTrianglesClockwise(triangles);

            //First create a list with all possible half-edges
            List <HalfEdge> halfEdges = new List <HalfEdge>(triangles.Count * 3);

            for (int i = 0; i < triangles.Count; i++)
            {
                Triangle t = triangles[i];

                HalfEdge he1 = new HalfEdge(t.v1);
                HalfEdge he2 = new HalfEdge(t.v2);
                HalfEdge he3 = new HalfEdge(t.v3);

                he1.nextEdge = he2;
                he2.nextEdge = he3;
                he3.nextEdge = he1;

                he1.prevEdge = he3;
                he2.prevEdge = he1;
                he3.prevEdge = he2;

                //The vertex needs to know of an edge going from it
                he1.v.halfEdge = he2;
                he2.v.halfEdge = he3;
                he3.v.halfEdge = he1;

                //The face the half-edge is connected to
                t.halfEdge = he1;

                he1.t = t;
                he2.t = t;
                he3.t = t;

                //Add the half-edges to the list
                halfEdges.Add(he1);
                halfEdges.Add(he2);
                halfEdges.Add(he3);
            }

            //Find the half-edges going in the opposite direction
            for (int i = 0; i < halfEdges.Count; i++)
            {
                HalfEdge he = halfEdges[i];

                Vertex goingToVertex   = he.v;
                Vertex goingFromVertex = he.prevEdge.v;

                for (int j = 0; j < halfEdges.Count; j++)
                {
                    //Dont compare with itself
                    if (i == j)
                    {
                        continue;
                    }

                    HalfEdge heOpposite = halfEdges[j];

                    //Is this edge going between the vertices in the opposite direction
                    if (goingFromVertex.position == heOpposite.v.position && goingToVertex.position == heOpposite.prevEdge.v.position)
                    {
                        he.oppositeEdge = heOpposite;

                        break;
                    }
                }
            }


            return(halfEdges);
        }