/// <summary>
        /// Retourne une liste de sommets correspondant aux sommets de la face
        /// les sommets sont retournés dans le sens trigo
        /// </summary>
        public List <VertexWE> GetFaceVertices(FaceWE f)
        {
            List <VertexWE> vertices  = new List <VertexWE>();
            EdgeWE          firstEdge = f.Edges[0];

            for (int i = 0; i < f.Edges.Count; i++)
            {
                VertexWE v1 = f.Edges[i].Vertex1;
                VertexWE v2 = f.Edges[i].Vertex2;

                if (f.Edges[i].LeftFace == f)
                {
                    v1 = f.Edges[i].Vertex2;
                    v2 = f.Edges[i].Vertex1;
                }

                if (!vertices.Contains(v1))
                {
                    vertices.Add(v1);
                }
                if (!vertices.Contains(v2))
                {
                    vertices.Add(v2);
                }
            }

            return(vertices);
        }
        /// <summary>
        /// Cette méthode ce charge de rajouter un sommet à l'intérieur du triangle f,
        /// et divise donc la face en 3 nouvelles faces
        /// </summary>
        public List <FaceWE> AddVertex(FaceWE f, float x, float y, float z)
        {
            List <FaceWE>   faces    = new List <FaceWE>();
            List <VertexWE> vertices = GetFaceVertices(f);

            RemoveFace(f);
            VertexWE v = AddVertex(x, y, z);

            faces.Add(AddFace(vertices[0], v, vertices[1]));
            faces.Add(AddFace(vertices[1], v, vertices[2]));
            faces.Add(AddFace(vertices[2], v, vertices[0]));
            return(faces);
        }
        /// <summary>
        /// Cette opération consiste à "flip" une edge, utilisé dans la triangulation de deulaunay
        /// L'opération de flip consiste à détruire 2 triangles reliés par une arrête, et construire
        /// 2 nouveau triangle en utilisant les 2 sommets non utilisé comme arrête de séparation
        ///   /|\          /\
        ///  / | \   -->  /__\
        ///  \ | /        \  /
        ///   \|/          \/
        /// </summary>
        public List <FaceWE> FlipEdge(EdgeWE e)
        {
            List <FaceWE> newfaces = new List <FaceWE>();

            FaceWE f1 = e.LeftFace;
            FaceWE f2 = e.RightFace;

            // On enregistre les 2 sommets de l'arrêtes
            VertexWE v1 = e.Vertex1;
            VertexWE v2 = e.Vertex2;

            // On cherche les deux sommets inconnus qui serviront pour créer l'arrête commune
            //entre les 2 faces

            VertexWE v3 = null;
            VertexWE v4 = null;

            List <VertexWE> f1vertices = GetFaceVertices(f1);
            List <VertexWE> f2vertices = GetFaceVertices(f2);

            for (int i = 0; i < f1vertices.Count; i++)
            {
                if (f1vertices[i] != v1 && f1vertices[i] != v2)
                {
                    v3 = f1vertices[i];
                }
            }

            for (int i = 0; i < f2vertices.Count; i++)
            {
                if (f2vertices[i] != v1 && f2vertices[i] != v2)
                {
                    v4 = f2vertices[i];
                }
            }

            RemoveFace(f1);
            RemoveFace(f2);

            newfaces.Add(AddFace(v3, v4, v1));
            newfaces.Add(AddFace(v3, v4, v2));

            return(newfaces);
        }
        /// <summary>
        /// Supprime la face
        /// </summary>
        /// <param name="f"></param>
        public void RemoveFace(FaceWE f)
        {
            foreach (EdgeWE e in f.Edges)
            {
                if (e.RightFace == f)
                {
                    e.RightFace = null;
                }

                if (e.LeftFace == f)
                {
                    e.LeftFace = null;
                }

                if (e.LeftFace == null && e.RightFace == null)
                {
                    Edges.Remove(e);
                    e.Vertex1.Edges.Remove(e);
                    e.Vertex2.Edges.Remove(e);
                }
            }
            Faces.Remove(f);
        }
        /// <summary>
        /// Retourne une liste de face voisines à la face passé en paramètre
        /// </summary>
        /// <param name="f"></param>
        /// <returns></returns>
        public List <FaceWE> GetFaceNeighbours(FaceWE f)
        {
            List <FaceWE> faces = new List <FaceWE>();

            for (int i = 0; i < f.Edges.Count; i++)
            {
                if (f.Edges[i].LeftFace != null && f.Edges[i].LeftFace != f)
                {
                    if (!faces.Contains(f.Edges[i].LeftFace))
                    {
                        faces.Add(f.Edges[i].LeftFace);
                    }
                }
                if (f.Edges[i].RightFace != null && f.Edges[i].RightFace != f)
                {
                    if (!faces.Contains(f.Edges[i].RightFace))
                    {
                        faces.Add(f.Edges[i].RightFace);
                    }
                }
            }

            return(faces);
        }
        /// <summary>
        /// Vérifie si une des arrêtes de la face est un "bord", c'est à dire que l'arrête
        /// n'a qu'une seule face d'enregistré
        /// </summary>
        /// <param name="f"></param>
        /// <returns></returns>
        public bool IsFaceBorder(FaceWE f)
        {
            foreach (EdgeWE e in f.Edges)
            {
                if (e.LeftFace == null || e.RightFace == null)
                {
                    return(true);
                }
            }

            List <VertexWE> v = GetFaceVertices(f);

            foreach (VertexWE vertex in v)
            {
                foreach (EdgeWE e in vertex.Edges)
                {
                    if (e.LeftFace == null || e.RightFace == null)
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
        /// <summary>
        /// Ajoute une nouvelle face à la structure à partir des sommets spécifiés
        /// </summary>
        public FaceWE AddFace(VertexWE v1, VertexWE v2, VertexWE v3)
        {
            // On commence par vérifier si la face n'a pas déjà été crée
            if (FaceAlreadyExist(v1, v2, v3) == null)
            {
                // On vérifie si les sommets sont dans le bon ordre

                if (!IsTriangleClockwise(v1, v2, v3))
                {
                    // Si ce n'est pas le cas, j'inverse v2 et v3 pour avoir un triangle clockwise

                    VertexWE temp = v2;
                    v2 = v3;
                    v3 = temp;
                }

                // On crée un nouvelle face

                FaceWE f = new FaceWE();

                EdgeWE e1 = EdgeAlreadyExist(v1, v2);
                EdgeWE e2 = EdgeAlreadyExist(v2, v3);
                EdgeWE e3 = EdgeAlreadyExist(v3, v1);

                // On commence par crée les arrêtes si elles n'existent pas
                if (e1 == null)
                {
                    e1 = new EdgeWE(v1, v2);
                    v1.Edges.Add(e1);
                    v2.Edges.Add(e1);
                    Edges.Add(e1);
                    e1.LeftFace = f;
                }
                else
                {
                    if (e1.LeftFace == null)
                    {
                        e1.LeftFace = f;
                    }
                    else
                    {
                        e1.RightFace = f;
                    }
                }

                if (e2 == null)
                {
                    e2 = new EdgeWE(v2, v3);

                    v2.Edges.Add(e2);
                    v3.Edges.Add(e2);

                    Edges.Add(e2);
                    e2.LeftFace = f;
                }
                else
                {
                    if (e2.LeftFace == null)
                    {
                        e2.LeftFace = f;
                    }
                    else
                    {
                        e2.RightFace = f;
                    }
                }

                if (e3 == null)
                {
                    e3 = new EdgeWE(v3, v1);
                    v3.Edges.Add(e3);
                    v1.Edges.Add(e3);
                    e3.LeftFace = f;
                    Edges.Add(e3);
                }
                else
                {
                    if (e3.LeftFace == null)
                    {
                        e3.LeftFace = f;
                    }
                    else
                    {
                        e3.RightFace = f;
                    }
                }

                // On se charge ensuite de connecter les arrêtes entre elles

                //if ( e1.RightFace == null )
                //{
                //    e1.NextLeft = e2;
                //    e1.PreviousLeft = e3;
                //}
                //else
                //{
                //    e1.NextRight    = e2;
                //    e1.PreviousRight= e3;
                //}

                //if ( e2.RightFace == null )
                //{
                //    e2.NextLeft     = e3;
                //    e2.PreviousLeft = e1;
                //}
                //else
                //{
                //    e2.NextRight        = e3;
                //    e2.PreviousRight    = e1;
                //}

                //if ( e3.RightFace == null )
                //{
                //    e3.NextLeft     = e1;
                //    e3.PreviousLeft = e2;
                //}
                //else
                //{
                //    e3.NextRight        = e1;
                //    e3.PreviousRight    = e2;
                //}

                f.Edges.Add(e1);
                f.Edges.Add(e2);
                f.Edges.Add(e3);

                Faces.Add(f);
                return(f);
            }
            return(null);
        }