/// <summary>
        /// Constructs a table of the area of intersection between each face and the vertices around it.
        /// </summary>
        public static double[][] AreaInEachVertex(IPolyhedron surface)
        {
            var allAreas = new double[surface.Faces.Count][];

            foreach (var face in surface.Faces)
            {
                var vertices = face.Vertices;
                var areas    = vertices.Select(vertex => PolyhedronUtilities.AreaSharedByVertexAndFace(surface, vertex, face)).ToArray();

                allAreas[surface.IndexOf(face)] = areas;
            }

            return(allAreas);
        }
        public void BisectionPoint_OfTheEdgeOfACube_ShouldBeEquidistantFromBothEnds
            (IPolyhedron polyhedron)
        {
            // Fixture setup

            // Exercise system
            var points = polyhedron.Edges.Select(edge => PolyhedronUtilities.BisectionPoint(polyhedron, edge)).ToList();

            // Verify outcome
            var expected = polyhedron.Edges.Select((edge, i) => (edge.A.Position - points[i]).Norm()).ToList();
            var actual   = polyhedron.Edges.Select((edge, i) => (edge.B.Position - points[i]).Norm()).ToList();

            TestUtilities.WriteExpectedAndActual(expected, actual);
            Assert.True(Enumerable.SequenceEqual(expected, actual));

            // Teardown
        }
        public void AreaSharedByVertexAndFace_OnACube_ShouldProduceTheCorrectValues
            (IPolyhedron polyhedron)
        {
            // Fixture setup
            var vertices = polyhedron.Vertices;
            var faces    = polyhedron.Faces;

            var expected = Enumerable.Repeat(1.0, 24).Concat(Enumerable.Repeat(0.0, 24)).ToList();

            // Exercise system
            var actual = vertices.SelectMany(vertex => faces.Select(face => PolyhedronUtilities.AreaSharedByVertexAndFace(polyhedron, vertex, face))).ToList();

            // Verify outcome
            TestUtilities.WriteExpectedAndActual(expected, actual);
            Assert.True(TestUtilities.UnorderedEquals(expected, actual));

            // Teardown
        }
        /// <summary>
        /// Constructs a table of the distances from each vertex to the bisectors running across each neighbouring edge.
        /// </summary>
        public static double[][] HalfEdgeLengths(IPolyhedron surface)
        {
            var halfLengthsTable = new double[surface.Vertices.Count][];

            foreach (var vertex in surface.Vertices)
            {
                var edges   = surface.EdgesOf(vertex);
                var lengths = new List <double>();
                foreach (var edge in edges)
                {
                    var neighbour      = edge.Vertices().First(v => v != vertex);
                    var bisectionPoint = PolyhedronUtilities.BisectionPoint(surface, edge);
                    var length         = (neighbour.Position - bisectionPoint).Norm();
                    //TODO: This is planar distance, not geodesic.
                    lengths.Add(length);
                }
                halfLengthsTable[surface.IndexOf(vertex)] = lengths.ToArray();
            }

            return(halfLengthsTable);
        }