/// <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);
        }
        private static int IndexOfFaceInVertex(IPolyhedron surface, Face face, Vertex vertex)
        {
            var facesAroundVertex = surface.FacesOf(vertex);
            var indexOfFace       = facesAroundVertex.IndexOf(face);

            return(indexOfFace);
        }
        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());
        }
        /// <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);
        }
Exemple #5
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
        }
        /// <summary>
        /// Calculates the point at which the specified edge is closest to the line between its neighbouring faces' centers.
        /// </summary>
        public static Vector BisectionPoint(IPolyhedron polyhedron, Edge edge)
        {
            var aFace  = polyhedron.FacesOf(edge).First();
            var origin = edge.A.Position;

            var edgeVector   = edge.B.Position - origin;
            var vectorToFace = aFace.SphericalCenter() - origin;

            var vectorToBisector = Vector.ScalarProduct(vectorToFace, edgeVector.Normalize()) * edgeVector.Normalize();

            return(vectorToBisector + origin);
        }
        /// <summary>
        /// Constructs a table of the area of intersection between each vertex and the faces around it.
        /// </summary>
        public static double[][] AreaInEachFace(IPolyhedron surface)
        {
            var allAreas = new double[surface.Vertices.Count][];

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

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

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

            // Exercise system
            var vertexIndices = FaceIndexedTableFactory.FaceInFacesOfVertices(polyhedron);

            // Verify outcome
            for (int i = 0; i < polyhedron.Faces.Count; i++)
            {
                var face     = polyhedron.Faces[i];
                var expected = Enumerable.Repeat(face, face.Vertices.Count).ToList();

                var indices  = vertexIndices[i];
                var vertices = face.Vertices;
                var actual   = vertices.Select((v, j) => polyhedron.FacesOf(v)[indices[j]]).ToList();

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

            // Teardown
        }