fruchterman_reingold_force_directed_layout
// named parameter version
template<typename Graph, typename PositionMap, typename Dim, typename Param,
typename Tag, typename Rest>
void
fruchterman_reingold_force_directed_layout
(const Graph& g,
PositionMap position,
Dim width,
Dim height,
const bgl_named_params<Param, Tag, Rest>& params);
// non-named parameter version
template<typename Graph, typename PositionMap, typename Dim,
typename AttractiveForce, typename RepulsiveForce,
typename ForcePairs, typename DisplacementMap, typename Cooling>
void
fruchterman_reingold_force_directed_layout
(const Graph& g,
PositionMap position,
Dim width,
Dim height,
AttractiveForce fa,
RepulsiveForce fr,
ForcePairs fp,
Cooling cool,
DisplacementMap displacement);
template<typename Graph, typename PositionMap, typename Dim>
void
fruchterman_reingold_force_directed_layout(const Graph& g,
PositionMap position,
Dim width,
Dim height);
This algorithm [58] performs layout of unweighted, undirected graphs. Unlike the Kamada-Kawai layout algorithm, this algorithm directly supports the layout of disconnected graphs (but see the force_pairs named parameter). It is a force-directed algorithm, meaning that vertex layout is determined by the forces pulling vertices together and pushing them apart. Attractive forces occur between adjacent vertices only, whereas repulsive forces occur between every pair of vertices. Each iteration computes the sum of the forces on each vertex, then moves the vertices to their new positions. The movement of vertices is mitigated by the temperature of the system for that iteration: as the algorithm progresses through successive iterations, the temperature should decrease so that vertices settle in place. The cooling schedule, attractive forces, and repulsive forces can be provided by the user.
The vertices are often placed randomly prior to execution of this algorithm via random_graph_layout.
The graph object on which the algorithm will be applied. The type Graph must be a model of Vertex And Edge List Graph.IN/OUT: PositionMap position
Python: This parameter is named graph in Python.
The property map that stores the position of each vertex. It should typically be initialized with the vertices at random locations (use random_graph_layout). The type PositionMap must be a model of Lvalue Property Map such that the vertex descriptor type of Graph is convertible to its key type. Its value type must be a structure with fields x and y, representing the coordinates of the vertex.IN: Dim width
Python: The position map must be a vertex_point2d_map for the graph.
Python default: graph.get_vertex_point2d_map("position")
The width of the display area in which layout should occur. On termination of the algorithm, the x coordinates of all vertices will fall in [-width/2, width/2].IN: Dim height
The height of the display area in which layout should occur. On termination of the algorithm, the y coordinates of all vertices will fall in [-height/2, height/2].
Computes the magnitude of the attractive force between two adjacent vertices. The function object fa must accept four parameters: the edge descriptor, k, the distance between the vertices, and the graph. k is the square root of the ratio of the display area to the number of vertices.IN: repulsive_force(RepulsiveForce fr)
Default: square_distance_attractive_force(), which computes the attractive force asdist2/k
.
Python: Any callable Python object that matches the signature will suffice.
Computes the magnitude of the repulsive force between any two vertices. The function object fa must accept five parameters: the two vertex descriptors, k,IN: force_pairs(ForcePairs fp)
Default: square_distance_repsulsive_force(),, which computes the repulsive force ask2/dist Python: Any callable Python object that matches the signature will suffice.
Enumerates the pairs of vertices on which the repulsive force should
be applied. fp is a function object taking two parameters:
the graph g and a binary function object that should be
passed each pair of vertices to be considered. The basic formulation
of the Fruchterman-Reingold algorithm computes repulsive forces between all
pairs of vertices (pass
all_force_pairs()
for
this parameter), which is functional for disconnected graphs but
tends to push the connected components toward the edges of the
display area. The grid variant of the algorithm places a grid over
the display area and only computes repulsive forces among vertices
within each rectangle in the grid. The grid variant can be more
efficient than the basic formulation and tends to produce better
layouts for disconnected graphs, but is not better overall: pass
make_grid_force_pairs(width, height, position, g)
Default:
make_grid_force_pairs(width, height, position, g)
Python: Unsupported parameter.
IN: cooling(Cooling cool)
Default:
linear_cooling<double>(100)
Python: Any callable Python object that matches the signature will suffice.
UTIL: displacement_map(DisplacementMap displacement)
The displacement map is used to compute the amount by which each
vertex will move in each step. The
DisplacementMap
type
carries the same requirements as the
PositionMap
Default: Ann
iterator_property_map
with a value type
of
simple_point<double>
Python: Unsupported parameter.
IN: vertex_index_map(VertexIndexMap i_map)
This maps each vertex to an integer in the range
[0,
num_vertices(g)). This is only necessary when no
displacement map is provided.
The type
VertexIndexMap
must be a model of Readable Property
Map. The value type of the map must be an integer typDefault:
get(vertex_index, g)
Note: if you use this default, make sure your graph has
an internalal
vertex_index property. For example,
adjacenty_list
with
VertexList=listS
does not have an internal
vertex_index property.
Python: Unsupported parameter.
Python IN: bool progressive
When
false, performs a random layout of the graph before
running the Fruchterman-Reingold algorithm. If
true, the
algorithm is executing starting with the vertex configuration in
the
position
Default:
False.
Complexity
The time complexity is O(|V|2 + |E|) for each
iteration of the algorithm in the worse case. The average case for the
grid variant is O(|V| + |E|). The number of iterations is
determined by the cooling schedule.
Example
libs/graph/example/fr_layout.cpp
Copyright © 2004
Doug Gregor, Indiana University