📄 kamada_kawai_spring_layout.hpp
字号:
return true;
}
const Graph& g;
PositionMap position;
WeightMap weight;
EdgeOrSideLength edge_or_side_length;
Done done;
weight_type spring_constant;
VertexIndexMap index;
DistanceMatrix distance;
SpringStrengthMatrix spring_strength;
PartialDerivativeMap partial_derivatives;
};
} } // end namespace detail::graph
/// States that the given quantity is an edge length.
template<typename T>
inline detail::graph::edge_or_side<true, T>
edge_length(T x)
{ return detail::graph::edge_or_side<true, T>(x); }
/// States that the given quantity is a display area side length.
template<typename T>
inline detail::graph::edge_or_side<false, T>
side_length(T x)
{ return detail::graph::edge_or_side<false, T>(x); }
/**
* \brief Determines when to terminate layout of a particular graph based
* on a given relative tolerance.
*/
template<typename T = double>
struct layout_tolerance
{
layout_tolerance(const T& tolerance = T(0.001))
: tolerance(tolerance), last_energy((std::numeric_limits<T>::max)()),
last_local_energy((std::numeric_limits<T>::max)()) { }
template<typename Graph>
bool
operator()(T delta_p,
typename boost::graph_traits<Graph>::vertex_descriptor p,
const Graph& g,
bool global)
{
if (global) {
if (last_energy == (std::numeric_limits<T>::max)()) {
last_energy = delta_p;
return false;
}
T diff = last_energy - delta_p;
if (diff < T(0)) diff = -diff;
bool done = (delta_p == T(0) || diff / last_energy < tolerance);
last_energy = delta_p;
return done;
} else {
if (last_local_energy == (std::numeric_limits<T>::max)()) {
last_local_energy = delta_p;
return delta_p == T(0);
}
T diff = last_local_energy - delta_p;
bool done = (delta_p == T(0) || (diff / last_local_energy) < tolerance);
last_local_energy = delta_p;
return done;
}
}
private:
T tolerance;
T last_energy;
T last_local_energy;
};
/** \brief Kamada-Kawai spring layout for undirected graphs.
*
* This algorithm performs graph layout (in two dimensions) for
* connected, undirected graphs. It operates by relating the layout
* of graphs to a dynamic spring system and minimizing the energy
* within that system. The strength of a spring between two vertices
* is inversely proportional to the square of the shortest distance
* (in graph terms) between those two vertices. Essentially,
* vertices that are closer in the graph-theoretic sense (i.e., by
* following edges) will have stronger springs and will therefore be
* placed closer together.
*
* Prior to invoking this algorithm, it is recommended that the
* vertices be placed along the vertices of a regular n-sided
* polygon.
*
* \param g (IN) must be a model of Vertex List Graph, Edge List
* Graph, and Incidence Graph and must be undirected.
*
* \param position (OUT) must be a model of Lvalue Property Map,
* where the value type is a class containing fields @c x and @c y
* that will be set to the @c x and @c y coordinates of each vertex.
*
* \param weight (IN) must be a model of Readable Property Map,
* which provides the weight of each edge in the graph @p g.
*
* \param edge_or_side_length (IN) provides either the unit length
* @c e of an edge in the layout or the length of a side @c s of the
* display area, and must be either @c boost::edge_length(e) or @c
* boost::side_length(s), respectively.
*
* \param done (IN) is a 4-argument function object that is passed
* the current value of delta_p (i.e., the energy of vertex @p p),
* the vertex @p p, the graph @p g, and a boolean flag indicating
* whether @p delta_p is the maximum energy in the system (when @c
* true) or the energy of the vertex being moved. Defaults to @c
* layout_tolerance instantiated over the value type of the weight
* map.
*
* \param spring_constant (IN) is the constant multiplied by each
* spring's strength. Larger values create systems with more energy
* that can take longer to stabilize; smaller values create systems
* with less energy that stabilize quickly but do not necessarily
* result in pleasing layouts. The default value is 1.
*
* \param index (IN) is a mapping from vertices to index values
* between 0 and @c num_vertices(g). The default is @c
* get(vertex_index,g).
*
* \param distance (UTIL/OUT) will be used to store the distance
* from every vertex to every other vertex, which is computed in the
* first stages of the algorithm. This value's type must be a model
* of BasicMatrix with value type equal to the value type of the
* weight map. The default is a a vector of vectors.
*
* \param spring_strength (UTIL/OUT) will be used to store the
* strength of the spring between every pair of vertices. This
* value's type must be a model of BasicMatrix with value type equal
* to the value type of the weight map. The default is a a vector of
* vectors.
*
* \param partial_derivatives (UTIL) will be used to store the
* partial derivates of each vertex with respect to the @c x and @c
* y coordinates. This must be a Read/Write Property Map whose value
* type is a pair with both types equivalent to the value type of
* the weight map. The default is an iterator property map.
*
* \returns @c true if layout was successful or @c false if a
* negative weight cycle was detected.
*/
template<typename Graph, typename PositionMap, typename WeightMap,
typename T, bool EdgeOrSideLength, typename Done,
typename VertexIndexMap, typename DistanceMatrix,
typename SpringStrengthMatrix, typename PartialDerivativeMap>
bool
kamada_kawai_spring_layout(
const Graph& g,
PositionMap position,
WeightMap weight,
detail::graph::edge_or_side<EdgeOrSideLength, T> edge_or_side_length,
Done done,
typename property_traits<WeightMap>::value_type spring_constant,
VertexIndexMap index,
DistanceMatrix distance,
SpringStrengthMatrix spring_strength,
PartialDerivativeMap partial_derivatives)
{
BOOST_STATIC_ASSERT((is_convertible<
typename graph_traits<Graph>::directed_category*,
undirected_tag*
>::value));
detail::graph::kamada_kawai_spring_layout_impl<
Graph, PositionMap, WeightMap,
detail::graph::edge_or_side<EdgeOrSideLength, T>, Done, VertexIndexMap,
DistanceMatrix, SpringStrengthMatrix, PartialDerivativeMap>
alg(g, position, weight, edge_or_side_length, done, spring_constant,
index, distance, spring_strength, partial_derivatives);
return alg.run();
}
/**
* \overload
*/
template<typename Graph, typename PositionMap, typename WeightMap,
typename T, bool EdgeOrSideLength, typename Done,
typename VertexIndexMap>
bool
kamada_kawai_spring_layout(
const Graph& g,
PositionMap position,
WeightMap weight,
detail::graph::edge_or_side<EdgeOrSideLength, T> edge_or_side_length,
Done done,
typename property_traits<WeightMap>::value_type spring_constant,
VertexIndexMap index)
{
typedef typename property_traits<WeightMap>::value_type weight_type;
typename graph_traits<Graph>::vertices_size_type n = num_vertices(g);
typedef std::vector<weight_type> weight_vec;
std::vector<weight_vec> distance(n, weight_vec(n));
std::vector<weight_vec> spring_strength(n, weight_vec(n));
std::vector<std::pair<weight_type, weight_type> > partial_derivatives(n);
return
kamada_kawai_spring_layout(
g, position, weight, edge_or_side_length, done, spring_constant, index,
distance.begin(),
spring_strength.begin(),
make_iterator_property_map(partial_derivatives.begin(), index,
std::pair<weight_type, weight_type>()));
}
/**
* \overload
*/
template<typename Graph, typename PositionMap, typename WeightMap,
typename T, bool EdgeOrSideLength, typename Done>
bool
kamada_kawai_spring_layout(
const Graph& g,
PositionMap position,
WeightMap weight,
detail::graph::edge_or_side<EdgeOrSideLength, T> edge_or_side_length,
Done done,
typename property_traits<WeightMap>::value_type spring_constant)
{
return kamada_kawai_spring_layout(g, position, weight, edge_or_side_length,
done, spring_constant,
get(vertex_index, g));
}
/**
* \overload
*/
template<typename Graph, typename PositionMap, typename WeightMap,
typename T, bool EdgeOrSideLength, typename Done>
bool
kamada_kawai_spring_layout(
const Graph& g,
PositionMap position,
WeightMap weight,
detail::graph::edge_or_side<EdgeOrSideLength, T> edge_or_side_length,
Done done)
{
typedef typename property_traits<WeightMap>::value_type weight_type;
return kamada_kawai_spring_layout(g, position, weight, edge_or_side_length,
done, weight_type(1));
}
/**
* \overload
*/
template<typename Graph, typename PositionMap, typename WeightMap,
typename T, bool EdgeOrSideLength>
bool
kamada_kawai_spring_layout(
const Graph& g,
PositionMap position,
WeightMap weight,
detail::graph::edge_or_side<EdgeOrSideLength, T> edge_or_side_length)
{
typedef typename property_traits<WeightMap>::value_type weight_type;
return kamada_kawai_spring_layout(g, position, weight, edge_or_side_length,
layout_tolerance<weight_type>(),
weight_type(1.0),
get(vertex_index, g));
}
} // end namespace boost
#endif // BOOST_GRAPH_KAMADA_KAWAI_SPRING_LAYOUT_HPP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -