/// <summary> /// Constructs a FieldManipulator instance that allows the cursor tracked by cursorTracker to interact with /// fields defined on polyhedron. /// </summary> /// <param name="polyhedron"></param> /// <param name="cursorTracker"></param> /// <param name="options"></param> public FieldManipulator(IPolyhedron polyhedron, CursorTracker cursorTracker, IFieldManipulatorOptions options) { _polyhedron = polyhedron; _cursorTracker = cursorTracker; _settings = new FieldManipulatorSettings(options); _options = options; }
private static Mesh BuildMesh(IPolyhedron surface) { var vertices = CreateVertexArray(surface); var triangles = CreateTriangleArray(surface); return(CreateMesh(vertices, triangles)); }
public static ScalarField <Face> RandomScalarField(IPolyhedron polyhedron, double average, double deviation) { var prng = new Random(); var values = Enumerable.Repeat(deviation, polyhedron.Faces.Count).Select(i => average + (prng.NextDouble() - 0.5) * deviation).ToArray(); return(new ScalarField <Face>(polyhedron.IndexOf, values)); }
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 }
public static VectorField <Vertex> RandomVectorField(IPolyhedron polyhedron, Vector average, double maxDeviation) { var prng = new Random(); var values = polyhedron.Vertices.Select(vertex => RandomLocalVector(prng, vertex.Position, average, maxDeviation)).ToArray(); return(new VectorField <Vertex>(polyhedron.IndexOf, values)); }
public static ScalarField <Face> XDependentScalarField(IPolyhedron polyhedron, double average, double deviation) { var normals = FaceIndexedTableFactory.Normals(polyhedron); var values = polyhedron.Faces.Select(face => average + deviation * normals[polyhedron.IndexOf(face)][0]).ToArray(); return(new ScalarField <Face>(polyhedron.IndexOf, values)); }
/// <summary> /// Construct a color mapper for the given polyhedron and maintain the running averages of the extrema for /// the specified length of time. /// </summary> /// <param name="polyhedron"></param> /// <param name="lengthOfHistory"></param> public FieldColorer(IPolyhedron polyhedron, int lengthOfHistory) { _polyhedron = polyhedron; _faces = VertexIndexedTableFactory.Faces(polyhedron); _maxAndMinTracker = new MaxAndMinTracker(lengthOfHistory); }
private static int IndexOfFaceInVertex(IPolyhedron surface, Face face, Vertex vertex) { var facesAroundVertex = surface.FacesOf(vertex); var indexOfFace = facesAroundVertex.IndexOf(face); return(indexOfFace); }
/// <summary> /// Constructs a table of the spherical areas associated with each vertex. /// /// Only valid for degree-3 vertices. /// </summary> public static double[] Areas(IPolyhedron surface) { var areasInEachFace = AreaInEachFace(surface); var areas = surface.Vertices.Select((vertex, i) => areasInEachFace[i].Sum()).ToArray(); return(areas); }
/// <summary> /// Calculates the Coriolis acceleration field for the given surface rotating at the given frequency. /// </summary> /// <param name="surface"></param> /// <param name="rotationFrequency"></param> /// <returns></returns> public static ScalarField <Face> CoriolisField(IPolyhedron surface, double rotationFrequency) { var angularVelocity = 2 * Math.PI * rotationFrequency; var values = surface.Faces.Select(face => 2 * angularVelocity * face.SphericalCenter().Normalize()[2]).ToArray(); return(new ScalarField <Face>(surface.IndexOf, values)); }
/// <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> /// Constructs a table of the areas of the faces. /// </summary> public static double[] Areas(IPolyhedron surface) { var areasInEachVertex = AreaInEachVertex(surface); var areas = surface.Faces.Select((face, i) => areasInEachVertex[i].Sum()).ToArray(); return(areas); }
//TODO: Fix the dependency on the specific ordering of vertex vectors then face vectors. // Constructs Vector3 for at each Vertex and at the center of each Face. Returns an array which contains // the Vertex vectors followed by the Face vectors. private static Vector3[] CreateVertexArray(IPolyhedron surface) { var vertexVectors = surface.Vertices.Select(vertex => GraphicsUtilities.Vector3(vertex.Position)); var faceVectors = surface.Faces.Select(face => GraphicsUtilities.Vector3(face.SphericalCenter())); return(vertexVectors.Concat(faceVectors).ToArray()); }
/// <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 an updater for the provided geometry. /// </summary> /// <param name="polyhedron"></param> /// <param name="options"></param> public ParticlePositionUpdater(IPolyhedron polyhedron, IParticleMapOptions options) { _scaleFactor = (float)(options.ParticleSpeedScaleFactor * options.Timestep); _tracker = new ParticleNeighbourhoodTracker(polyhedron, options.ParticleCount); _vertexPositions = GetVertexPositions(polyhedron); _vertexVelocities = new Vector3[polyhedron.Vertices.Count]; _particleVelocities = new Vector3[options.ParticleCount]; }
// Creates a new icosahedron by subdividing the provided icosasphere. private static IPolyhedron Subdivide(IPolyhedron icosasphere) { // Map each edge of the old icosasphere to a new vertex var oldEdgesToNewVertices = CreateNewVerticesFrom(icosasphere.Edges); // Create the new faces (each represented by a list of vertices) from the old icosasphere and the new vertices var newFaces = CreateFacesFrom(icosasphere.Faces, icosasphere.EdgesOf, oldEdgesToNewVertices); return(new Polyhedron(newFaces)); }
/// <summary> /// Construct a particle map for the given simulation geometry. /// </summary> /// <param name="polyhedron"></param> /// <param name="options"></param> public ParticleMapView(IPolyhedron polyhedron, IParticleMapOptions options) { _options = options; _radius = (float)_options.Radius; _positions = CreateParticles(options.ParticleCount, _radius); _renewalScheduler = new ParticleRenewalScheduler(options); _positionUpdater = new ParticlePositionUpdater(polyhedron, options); _renderingManager = new ParticleRenderingManager(options); }
/// <summary> /// Constructs a table of the normals to the sphere at the center of each face. /// </summary> public static Vector[] Normals(IPolyhedron surface) { var normals = new Vector[surface.Faces.Count]; foreach (var face in surface.Faces) { normals[surface.IndexOf(face)] = face.SphericalCenter().Normalize(); } return(normals); }
/// <summary> /// Constructs a table of the faces around each vertex. /// /// The ith edge given by surface.EdgesOf is anticlockwise of the ith face. /// </summary> public static int[][] Faces(IPolyhedron surface) { var faceTable = new int[surface.Vertices.Count][]; foreach (var vertex in surface.Vertices) { faceTable[surface.IndexOf(vertex)] = FacesAroundVertex(vertex, surface); } return(faceTable); }
// Constructs the dual of the provided icosasphere, returning a list of lists in which each list represents the // vertices of a face. private static List <List <Vertex> > DualofIcosasphere(IPolyhedron icosasphere) { // Map each icosasphere face to a geodesic sphere vertex var newVertexDict = icosasphere.Faces.ToDictionary(face => face, face => VertexAtCenterOf(face)); // Gather the new vertices into lists that represent the faces of the geodesic sphere. var vertexLists = icosasphere.Vertices. Select(oldVertex => CreateFaceAbout(oldVertex, newVertexDict, icosasphere.FacesOf)).ToList(); return(vertexLists); }
/// <summary> /// Construct a field updated for the given surface. /// </summary> /// <param name="surface"></param> /// <param name="options"></param> public PrognosticFieldsUpdater(IPolyhedron surface, IModelParameters options) { _options = options; _coriolisField = SimulationUtilities.CoriolisField(surface, _options.RotationFrequency); _faceNormalsField = SimulationUtilities.FaceNormalsField(surface); _vertexNormalsField = SimulationUtilities.VertexNormalsField(surface); _operators = new VectorFieldOperators(surface); _gravity = options.Gravity; }
// Project the vertices of the given polyhedron onto a sphere of the specified radius. private static IPolyhedron ProjectOntoSphere(IPolyhedron polyhedron, double radius) { var newVertex = polyhedron.Vertices. ToDictionary(oldVertex => oldVertex, oldVertex => new Vertex(radius * oldVertex.Position.Normalize())); var newFaces = from face in polyhedron.Faces select face.Vertices.Select(oldVertex => newVertex[oldVertex]).ToList(); return(new Polyhedron(newFaces.ToList())); }
/// <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 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> /// 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); }
public static Vector[] Normals(IPolyhedron surface) { var normals = new Vector[surface.Vertices.Count]; foreach (var vertex in surface.Vertices) { var normal = vertex.Position.Normalize(); normals[surface.IndexOf(vertex)] = normal; } return(normals); }
/// <summary> /// Constructs a table of the index of each face in surface.Faces(vertex) for each vertex around that face. /// </summary> public static int[][] FaceInFacesOfVertices(IPolyhedron surface) { var indices = new int[surface.Faces.Count][]; foreach (var face in surface.Faces) { var indicesOfFace = face.Vertices.Select(vertex => IndexOfFaceInVertex(surface, face, vertex)).ToArray(); indices[surface.IndexOf(face)] = indicesOfFace; } return(indices); }
/// <summary> /// Constructs a table of the indices of the vertices around each face. /// </summary> public static int[][] Vertices(IPolyhedron surface) { var indices = new int[surface.Faces.Count][]; foreach (var face in surface.Faces) { var vertexIndices = face.Vertices.Select(vertex => surface.IndexOf(vertex)).ToArray(); indices[surface.IndexOf(face)] = vertexIndices; } return(indices); }
/// <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); }