/// <summary>
        /// Constructs a table of the neighbours of each face.
        /// Neighbours are listed in the same order as given by surface.NeighboursOf.
        /// </summary>
        public static int[][] Neighbours(IPolyhedron surface)
        {
            var neighbours = new int[surface.Faces.Count][];

            foreach (var face in surface.Faces)
            {
                var indicesOfNeighbours = surface.NeighboursOf(face).Select(neighbour => surface.IndexOf(neighbour));
                neighbours[surface.IndexOf(face)] = indicesOfNeighbours.ToArray();
            }

            return(neighbours);
        }
        /// <summary>
        /// Constructs a table of the directions towards the faces neighbours in the face's tangent space.
        /// </summary>
        public static Vector[][] Directions(IPolyhedron surface)
        {
            var directions = new Vector[surface.Faces.Count][];

            foreach (var face in surface.Faces)
            {
                var neighboursOfFace = surface.NeighboursOf(face);
                var localDirections  = neighboursOfFace.Select(neighbour => Direction(face, neighbour));
                directions[surface.IndexOf(face)] = localDirections.ToArray();
            }

            return(directions);
        }
        // Gets the neighbours of a face which are within radius steps of it.
        private IEnumerable <Face> GetNearbyFaces(Face center, int radius)
        {
            var faces = new HashSet <Face> {
                center
            };

            for (int i = 1; i < radius; i++)
            {
                var neighbours = faces.SelectMany(face => _polyhedron.NeighboursOf(face)).ToList();
                faces.UnionWith(neighbours);
            }

            return(faces);
        }
        /// <summary>
        /// Constructs a table of the vectors perpendicular to a vertex and normal to each adjoining edge.
        ///
        /// Normals point anticlockwise around the vertex.
        /// </summary>
        public static Vector[][] EdgeNormals(IPolyhedron surface)
        {
            var edgeNormalsTable = new Vector[surface.Vertices.Count][];

            foreach (var vertex in surface.Vertices)
            {
                var vertexVector = vertex.Position;
                var edgeVectors  = surface.NeighboursOf(vertex).Select(neighbour => (neighbour.Position - vertexVector));
                var edgeNormals  = edgeVectors.Select(edgeVector => Vector.CrossProduct(vertexVector, edgeVector).Normalize()).ToArray();
                edgeNormalsTable[surface.IndexOf(vertex)] = edgeNormals;
            }

            return(edgeNormalsTable);
        }
        /// <summary>
        /// Constructs a table of the distances from each face's center to it's neighbour's centers.
        /// Neighbours are listed in the same order as given by surface.NeighboursOf.
        /// </summary>
        public static double[][] Distances(IPolyhedron surface)
        {
            var edgeLengths = new double[surface.Faces.Count][];

            foreach (var face in surface.Faces)
            {
                var distances =
                    surface.
                    NeighboursOf(face).
                    Select(neighbour => VectorUtilities.GeodesicDistance(face.SphericalCenter(), neighbour.SphericalCenter()));
                edgeLengths[surface.IndexOf(face)] = distances.ToArray();
            }

            //TODO: Work out how to turn this into spherical area.

            return(edgeLengths);
        }