예제 #1
0
        /// <summary>
        /// Gets the repulsion force.
        /// </summary>
        /// <param name="of">The node under observation.</param>
        /// <param name="from">The other node.</param>
        /// <param name="repulsionForce">The repulsion force.</param>
        /// <returns>The force vector.</returns>
        private static Vector GetRepulsionForce(Location of, Location @from, double repulsionForce = VertexRepulsionForceStrength)
        {
            // get the proximity and the direction
            double currentDistance;
            var direction = (of - @from).Normalized(out currentDistance);

            // strength decrease is proportional to the squared distance;
            // this imitates Coulomb's Law of the repulsion of charged particles (F = k*Q1*Q2/r^2)
            // where we assume the charge to be equal for all particles.
            var strength = repulsionForce / (currentDistance * currentDistance);

            // return the force vector
            return direction*strength;
        }
예제 #2
0
        /// <summary>
        /// Gets the attraction force.
        /// </summary>
        /// <param name="graph">The graph.</param>
        /// <param name="of">The node under observation.</param>
        /// <param name="locationOf">The location of.</param>
        /// <param name="from">The other node.</param>
        /// <param name="locationFrom">The location from.</param>
        /// <param name="attractionStrength">The attraction strength.</param>
        /// <returns>The force vector.</returns>
        private static Vector GetAttractionForce([NotNull] Graph graph, [NotNull] Vertex of, Location locationOf, [NotNull] Vertex from, Location locationFrom, double attractionStrength = VertexAttractionForceStrength)
        {
            // if vertices are unconnected, there is no force that
            // pulls them together.
            Edge edge;
            if (!graph.TryGetEdge(of, from, out edge)) return Vector.Zero;

            // the actual distance between the two vertices is given by the edge weight
            var expectedDistance = edge.Weight;

            // fetch the force direction and the actual distance
            double currentDistance;
            var direction = (locationOf - locationFrom).Normalized(out currentDistance);

            // determine the spring strength by Hooke's law:
            // If the expected distance is larger than the current distance, the spring is
            // too short and should thus expand; hence the attraction force is zero.
            // If the expected distance is smaller than the current distance, the spring needs
            // to contract, hence the strength is positive.
            var strength = attractionStrength * Math.Max(currentDistance - expectedDistance, 0);

            // In order to contract, we reverse the force direction
            return direction*(-strength);
        }
예제 #3
0
 /// <summary>
 /// Calculates the total attraction force.
 /// </summary>
 /// <param name="graph">The graph.</param>
 /// <param name="vertex">The vertex.</param>
 /// <param name="vertexLocation"></param>
 /// <param name="currentLocations">The current locations.</param>
 /// <returns>Vector.</returns>
 private static Vector CalculateTotalAttraction([NotNull] Graph graph, Vertex vertex, Location vertexLocation, [NotNull] IReadOnlyDictionary<Vertex, Location> currentLocations)
 {
     var forces =
         from edges in graph[vertex].AsParallel()
         let other = edges.Other(vertex)
         let otherLocation = currentLocations[other]
         select GetAttractionForce(graph, vertex, vertexLocation, other, otherLocation);
     var force = forces.Aggregate(Vector.Zero, (current, sumOfForces) => sumOfForces + current);
     return force;
 }
예제 #4
0
 /// <summary>
 /// Calculates the total repulsion force.
 /// </summary>
 /// <param name="graph">The graph.</param>
 /// <param name="vertex">The vertex.</param>
 /// <param name="vertexLocation"></param>
 /// <param name="currentLocations">The current locations.</param>
 /// <returns>Vector.</returns>
 private static Vector CalculateTotalRepulsion([NotNull] Graph graph, Vertex vertex, Location vertexLocation, [NotNull] IReadOnlyDictionary<Vertex, Location> currentLocations)
 {
     var forces =
         from other in graph.Vertices.AsParallel()
         where !other.Equals(vertex)
         let otherLocation = currentLocations[other]
         select GetRepulsionForce(vertexLocation, otherLocation);
     var force = forces.Aggregate(Vector.Zero, (current, sumOfForces) => sumOfForces + current);
     return force;
 }
예제 #5
0
 /// <summary>
 /// Determines whether the specified <see cref="Location" /> is equal to this instance.
 /// </summary>
 /// <param name="other">The object to compare with the current instance.</param>
 /// <returns><c>true</c> if the specified <see cref="Location" /> is equal to this instance; otherwise, <c>false</c>.</returns>
 public bool Equals(Location other)
 {
     return X.Equals(other.X) && Y.Equals(other.Y);
 }