public void Faces_OfEachVertex_ShouldHaveTheSameOrderAsEdgesOfEachVertex
            (IPolyhedron polyhedron)
        {
            // Fixture setup

            // Exercise system
            var faces = VertexIndexedTableFactory.Faces(polyhedron);

            // Verify outcome
            for (int vertex = 0; vertex < polyhedron.Vertices.Count; vertex++)
            {
                var faceList = faces[vertex];
                var edgeList = polyhedron.EdgesOf(polyhedron.Vertices[vertex]);

                var firstFace = polyhedron.Faces[faceList[0]];
                var lastEdge  = edgeList[edgeList.Count - 1];
                var firstEdge = edgeList[0];
                Assert.True(polyhedron.EdgesOf(firstFace).Contains(lastEdge));
                Assert.True(polyhedron.EdgesOf(firstFace).Contains(firstEdge));

                for (int i = 1; i < edgeList.Count; i++)
                {
                    var thisFace     = polyhedron.Faces[faceList[i]];
                    var previousEdge = edgeList[i - 1];
                    var thisEdge     = edgeList[i];

                    Assert.True(polyhedron.EdgesOf(thisFace).Contains(previousEdge));
                    Assert.True(polyhedron.EdgesOf(thisFace).Contains(thisEdge));
                }
            }

            // Teardown
        }
        /// <summary>
        /// Calculates the size of the area that's both in the specified face and closer to the specified vertex than any other vertex.
        /// </summary>
        public static double AreaSharedByVertexAndFace(IPolyhedron surface, Vertex vertex, Face face)
        {
            var vertexPosition = vertex.Position;
            var faces          = surface.FacesOf(vertex);
            var edges          = surface.EdgesOf(vertex);
            var index          = faces.IndexOf(face);

            if (!faces.Contains(face))
            {
                return(0.0);
            }

            var midpointOfFace = face.Center();

            var previousEdge           = edges.AtCyclicIndex(index - 1);
            var midpointOfPreviousEdge = BisectionPoint(surface, previousEdge);

            var nextEdge           = edges.AtCyclicIndex(index);
            var midpointOfNextEdge = BisectionPoint(surface, nextEdge);

            var crossProductOfFirstSegment = Vector.CrossProduct(midpointOfPreviousEdge - vertexPosition, midpointOfFace - vertexPosition);
            var areaOfFirstSegment         = Vector.ScalarProduct(crossProductOfFirstSegment, midpointOfFace.Normalize()) / 2;

            var crossProductOfSecondSegment = Vector.CrossProduct(midpointOfFace - vertexPosition, midpointOfNextEdge - vertexPosition);
            var areaOfSecondSegment         = Vector.ScalarProduct(crossProductOfSecondSegment, midpointOfFace.Normalize()) / 2;

            return(areaOfFirstSegment + areaOfSecondSegment);
        }
        /// <summary>
        /// Returns the neighbours of a vertex in the same order that their connecting edges are listed by the
        /// polyhedron's vertexToEdge lookup.
        /// </summary>
        /// <param name="polyhedron"></param>
        /// <param name="vertex"></param>
        /// <returns></returns>
        public static IEnumerable <Vertex> NeighboursOf(this IPolyhedron polyhedron, Vertex vertex)
        {
            var vertexSingleton = new[] { vertex };

            var edges      = polyhedron.EdgesOf(vertex);
            var neighbours = edges.SelectMany(edge => edge.Vertices().Except(vertexSingleton));

            return(neighbours.Where(neighbour => neighbour != vertex));
        }
        /// <summary>
        /// Returns the neighbours of a face in the same order that the edges they have in common appear.
        /// </summary>
        public static IEnumerable <Face> NeighboursOf(this IPolyhedron polyhedron, Face face)
        {
            var faceSingleton = new[] { face };

            var edges      = polyhedron.EdgesOf(face);
            var neighbours = edges.SelectMany(edge => polyhedron.FacesOf(edge).Except(faceSingleton));

            return(neighbours);
        }
        /// <summary>
        /// Constructs a table of the lengths of edges surrounding each face.
        /// Edges are listed in the same order as the opposing faces are given by surface.NeighboursOf.
        /// </summary>
        public static double[][] EdgeLengths(IPolyhedron surface)
        {
            var edgeLengths = new double[surface.Faces.Count][];

            foreach (var face in surface.Faces)
            {
                var lengths = surface.EdgesOf(face).Select(edge => edge.Length());
                edgeLengths[surface.IndexOf(face)] = lengths.ToArray();
            }

            return(edgeLengths);
        }
        /// <summary>
        /// Constructs a table of the spherical distances from each vertex to its neighbours.
        /// </summary>
        public static double[][] Distances(IPolyhedron surface)
        {
            var distanceTable = new double[surface.Vertices.Count][];

            foreach (var vertex in surface.Vertices)
            {
                var edges     = surface.EdgesOf(vertex);
                var distances = edges.Select(edge => edge.Length()).ToArray();
                distanceTable[surface.IndexOf(vertex)] = distances;
            }

            return(distanceTable);
        }
        private static int[] FacesAroundVertex(Vertex vertex, IPolyhedron surface)
        {
            var edges = surface.EdgesOf(vertex);

            var faces = new List <int>();

            for (int i = 0; i < edges.Count; i++)
            {
                var previousEdge = edges.AtCyclicIndex(i - 1);
                var thisEdge     = edges[i];
                var faceInCommon = surface.FacesOf(previousEdge).Intersect(surface.FacesOf(thisEdge)).First();
                var indexOfFace  = surface.IndexOf(faceInCommon);
                faces.Add(indexOfFace);
            }

            return(faces.ToArray());
        }
Beispiel #8
0
        public void FacesOf_OnEachVertex_IsInCorrectOrderWithRespectToEdgesOf
            (IPolyhedron polyhedron)
        {
            // Fixture setup

            // Exercise system

            // Verify outcome
            foreach (var vertex in polyhedron.Vertices)
            {
                var edges    = polyhedron.EdgesOf(vertex);
                var expected = edges.SelectMany((edge, i) => polyhedron.FacesOf(edge).Intersect(polyhedron.FacesOf(edges.AtCyclicIndex(i - 1)))).ToList();

                var actual = polyhedron.FacesOf(vertex);

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

            // Teardown
        }
Beispiel #9
0
        public void EdgesOf_OverEachFace_IsInCorrectOrderWithRespectToTheVerticesOfTheFace
            (IPolyhedron polyhedron)
        {
            // Fixture setup

            // Exercise system

            // Verify outcome
            foreach (var face in polyhedron.Faces)
            {
                var expected = face.Vertices;

                var edges  = polyhedron.EdgesOf(face);
                var actual = edges.SelectMany((edge, i) => edge.Vertices().Intersect(edges.AtCyclicIndex(i - 1).Vertices())).ToList();

                TestUtilities.WriteExpectedAndActual(expected, actual);
                Assert.True(Enumerable.SequenceEqual(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);
        }
Beispiel #11
0
        public void EdgesOf_OverEachFace_ReturnsEdgesInAnticlockwiseOrder
            (IPolyhedron polyhedron)
        {
            // Fixture setup

            // Exercise system
            var facesAndEdges = polyhedron.Faces.ToDictionary(face => face, face => polyhedron.EdgesOf(face));

            // Verify outcome
            foreach (var faceAndEdges in facesAndEdges)
            {
                var face          = faceAndEdges.Key;
                var center        = face.SphericalCenter();
                var viewDirection = -center;

                var edges   = faceAndEdges.Value;
                var vectors = edges.Select(edge => edge.SphericalCenter()).ToList();
                Assert.True(TestUtilities.AreInAntiClockwiseOrder(vectors, center, viewDirection));
            }

            // Teardown
        }