/// <summary>
        /// Returns the area of the given halfedge as per V in https://www.cs.cmu.edu/~kmcrane/Projects/Other/TriangleAreasCheatSheet.pdf
        /// Assumes the halfedge is in a triangular face.
        /// </summary>
        public static double GetArea <V, E, F>(this HeStructure <V, E, F> .Halfedge hedge, Func <V, Vector3d> getPosition)
            where V : HeStructure <V, E, F> .Vertex
            where E : HeStructure <V, E, F> .Halfedge
            where F : HeStructure <V, E, F> .Face
        {
            var p0 = getPosition(hedge.Start);
            var p1 = getPosition(hedge.Next.Start);
            var p2 = getPosition(hedge.Previous.Start);

            return(p0.SquareDistanceTo(p1) * Vector3d.Cotangent(p0 - p2, p1 - p2) * 0.25);
        }
        /// <summary>
        /// Calculates the cotangent of the angle opposite this halfedge.
        /// Assumes the halfedge is in a triangular face.
        /// </summary>
        public static double GetCotangent <V, E, F>(this HeStructure <V, E, F> .Halfedge hedge, Func <V, Vector3d> getPosition)
            where V : HeStructure <V, E, F> .Vertex
            where E : HeStructure <V, E, F> .Halfedge
            where F : HeStructure <V, E, F> .Face
        {
            Vector3d p = getPosition(hedge.Previous.Start);

            return(Vector3d.Cotangent(
                       getPosition(hedge.Start) - p,
                       getPosition(hedge.End) - p
                       ));
        }
        /// <summary>
        /// Returns the area of the given halfedge as per D in https://www.cs.cmu.edu/~kmcrane/Projects/Other/TriangleAreasCheatSheet.pdf
        /// Assumes adjacent faces are triangular.
        /// </summary>
        public static double GetEdgeArea <V, E, F>(this HeStructure <V, E, F> .Halfedge hedge, Func <V, Vector3d> getPosition)
            where V : HeStructure <V, E, F> .Vertex
            where E : HeStructure <V, E, F> .Halfedge
            where F : HeStructure <V, E, F> .Face
        {
            var twin = hedge.Twin;
            var p0   = getPosition(hedge.Start);
            var p1   = getPosition(twin.Start);
            var w    = 0.0;

            if (hedge.Face != null)
            {
                var p2 = getPosition(hedge.Previous.Start);
                w += Vector3d.Cotangent(p0 - p2, p1 - p2);
            }

            if (twin.Face != null)
            {
                var p3 = getPosition(twin.Previous.Start);
                w += Vector3d.Cotangent(p0 - p3, p1 - p3);
            }

            return(p0.SquareDistanceTo(p1) * w * 0.25);
        }