Chris@16
|
1 // Copyright 2004, 2005 The Trustees of Indiana University.
|
Chris@16
|
2
|
Chris@16
|
3 // Distributed under the Boost Software License, Version 1.0.
|
Chris@16
|
4 // (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
5 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6
|
Chris@16
|
7 // Authors: Douglas Gregor
|
Chris@16
|
8 // Andrew Lumsdaine
|
Chris@16
|
9 #ifndef BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP
|
Chris@16
|
10 #define BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP
|
Chris@16
|
11
|
Chris@16
|
12 #include <boost/config/no_tr1/cmath.hpp>
|
Chris@16
|
13 #include <boost/graph/graph_traits.hpp>
|
Chris@16
|
14 #include <boost/graph/named_function_params.hpp>
|
Chris@16
|
15 #include <boost/graph/iteration_macros.hpp>
|
Chris@16
|
16 #include <boost/graph/topology.hpp> // For topology concepts
|
Chris@16
|
17 #include <vector>
|
Chris@16
|
18 #include <list>
|
Chris@16
|
19 #include <algorithm> // for std::min and std::max
|
Chris@16
|
20 #include <numeric> // for std::accumulate
|
Chris@16
|
21 #include <cmath> // for std::sqrt and std::fabs
|
Chris@16
|
22 #include <functional>
|
Chris@16
|
23
|
Chris@16
|
24 namespace boost {
|
Chris@16
|
25
|
Chris@16
|
26 struct square_distance_attractive_force {
|
Chris@16
|
27 template<typename Graph, typename T>
|
Chris@16
|
28 T
|
Chris@16
|
29 operator()(typename graph_traits<Graph>::edge_descriptor,
|
Chris@16
|
30 T k,
|
Chris@16
|
31 T d,
|
Chris@16
|
32 const Graph&) const
|
Chris@16
|
33 {
|
Chris@16
|
34 return d * d / k;
|
Chris@16
|
35 }
|
Chris@16
|
36 };
|
Chris@16
|
37
|
Chris@16
|
38 struct square_distance_repulsive_force {
|
Chris@16
|
39 template<typename Graph, typename T>
|
Chris@16
|
40 T
|
Chris@16
|
41 operator()(typename graph_traits<Graph>::vertex_descriptor,
|
Chris@16
|
42 typename graph_traits<Graph>::vertex_descriptor,
|
Chris@16
|
43 T k,
|
Chris@16
|
44 T d,
|
Chris@16
|
45 const Graph&) const
|
Chris@16
|
46 {
|
Chris@16
|
47 return k * k / d;
|
Chris@16
|
48 }
|
Chris@16
|
49 };
|
Chris@16
|
50
|
Chris@16
|
51 template<typename T>
|
Chris@16
|
52 struct linear_cooling {
|
Chris@16
|
53 typedef T result_type;
|
Chris@16
|
54
|
Chris@16
|
55 linear_cooling(std::size_t iterations)
|
Chris@16
|
56 : temp(T(iterations) / T(10)), step(0.1) { }
|
Chris@16
|
57
|
Chris@16
|
58 linear_cooling(std::size_t iterations, T temp)
|
Chris@16
|
59 : temp(temp), step(temp / T(iterations)) { }
|
Chris@16
|
60
|
Chris@16
|
61 T operator()()
|
Chris@16
|
62 {
|
Chris@16
|
63 T old_temp = temp;
|
Chris@16
|
64 temp -= step;
|
Chris@16
|
65 if (temp < T(0)) temp = T(0);
|
Chris@16
|
66 return old_temp;
|
Chris@16
|
67 }
|
Chris@16
|
68
|
Chris@16
|
69 private:
|
Chris@16
|
70 T temp;
|
Chris@16
|
71 T step;
|
Chris@16
|
72 };
|
Chris@16
|
73
|
Chris@16
|
74 struct all_force_pairs
|
Chris@16
|
75 {
|
Chris@16
|
76 template<typename Graph, typename ApplyForce >
|
Chris@16
|
77 void operator()(const Graph& g, ApplyForce apply_force)
|
Chris@16
|
78 {
|
Chris@16
|
79 typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
|
Chris@16
|
80 vertex_iterator v, end;
|
Chris@16
|
81 for (boost::tie(v, end) = vertices(g); v != end; ++v) {
|
Chris@16
|
82 vertex_iterator u = v;
|
Chris@16
|
83 for (++u; u != end; ++u) {
|
Chris@16
|
84 apply_force(*u, *v);
|
Chris@16
|
85 apply_force(*v, *u);
|
Chris@16
|
86 }
|
Chris@16
|
87 }
|
Chris@16
|
88 }
|
Chris@16
|
89 };
|
Chris@16
|
90
|
Chris@16
|
91 template<typename Topology, typename PositionMap>
|
Chris@16
|
92 struct grid_force_pairs
|
Chris@16
|
93 {
|
Chris@16
|
94 typedef typename property_traits<PositionMap>::value_type Point;
|
Chris@16
|
95 BOOST_STATIC_ASSERT (Point::dimensions == 2);
|
Chris@16
|
96 typedef typename Topology::point_difference_type point_difference_type;
|
Chris@16
|
97
|
Chris@16
|
98 template<typename Graph>
|
Chris@16
|
99 explicit
|
Chris@16
|
100 grid_force_pairs(const Topology& topology,
|
Chris@16
|
101 PositionMap position, const Graph& g)
|
Chris@16
|
102 : topology(topology), position(position)
|
Chris@16
|
103 {
|
Chris@16
|
104 two_k = 2. * this->topology.volume(this->topology.extent()) / std::sqrt((double)num_vertices(g));
|
Chris@16
|
105 }
|
Chris@16
|
106
|
Chris@16
|
107 template<typename Graph, typename ApplyForce >
|
Chris@16
|
108 void operator()(const Graph& g, ApplyForce apply_force)
|
Chris@16
|
109 {
|
Chris@16
|
110 typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
|
Chris@16
|
111 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
Chris@16
|
112 typedef std::list<vertex_descriptor> bucket_t;
|
Chris@16
|
113 typedef std::vector<bucket_t> buckets_t;
|
Chris@16
|
114
|
Chris@16
|
115 std::size_t columns = std::size_t(topology.extent()[0] / two_k + 1.);
|
Chris@16
|
116 std::size_t rows = std::size_t(topology.extent()[1] / two_k + 1.);
|
Chris@16
|
117 buckets_t buckets(rows * columns);
|
Chris@16
|
118 vertex_iterator v, v_end;
|
Chris@16
|
119 for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v) {
|
Chris@16
|
120 std::size_t column =
|
Chris@16
|
121 std::size_t((get(position, *v)[0] + topology.extent()[0] / 2) / two_k);
|
Chris@16
|
122 std::size_t row =
|
Chris@16
|
123 std::size_t((get(position, *v)[1] + topology.extent()[1] / 2) / two_k);
|
Chris@16
|
124
|
Chris@16
|
125 if (column >= columns) column = columns - 1;
|
Chris@16
|
126 if (row >= rows) row = rows - 1;
|
Chris@16
|
127 buckets[row * columns + column].push_back(*v);
|
Chris@16
|
128 }
|
Chris@16
|
129
|
Chris@16
|
130 for (std::size_t row = 0; row < rows; ++row)
|
Chris@16
|
131 for (std::size_t column = 0; column < columns; ++column) {
|
Chris@16
|
132 bucket_t& bucket = buckets[row * columns + column];
|
Chris@16
|
133 typedef typename bucket_t::iterator bucket_iterator;
|
Chris@16
|
134 for (bucket_iterator u = bucket.begin(); u != bucket.end(); ++u) {
|
Chris@16
|
135 // Repulse vertices in this bucket
|
Chris@16
|
136 bucket_iterator v = u;
|
Chris@16
|
137 for (++v; v != bucket.end(); ++v) {
|
Chris@16
|
138 apply_force(*u, *v);
|
Chris@16
|
139 apply_force(*v, *u);
|
Chris@16
|
140 }
|
Chris@16
|
141
|
Chris@16
|
142 std::size_t adj_start_row = row == 0? 0 : row - 1;
|
Chris@16
|
143 std::size_t adj_end_row = row == rows - 1? row : row + 1;
|
Chris@16
|
144 std::size_t adj_start_column = column == 0? 0 : column - 1;
|
Chris@16
|
145 std::size_t adj_end_column = column == columns - 1? column : column + 1;
|
Chris@16
|
146 for (std::size_t other_row = adj_start_row; other_row <= adj_end_row;
|
Chris@16
|
147 ++other_row)
|
Chris@16
|
148 for (std::size_t other_column = adj_start_column;
|
Chris@16
|
149 other_column <= adj_end_column; ++other_column)
|
Chris@16
|
150 if (other_row != row || other_column != column) {
|
Chris@16
|
151 // Repulse vertices in this bucket
|
Chris@16
|
152 bucket_t& other_bucket
|
Chris@16
|
153 = buckets[other_row * columns + other_column];
|
Chris@16
|
154 for (v = other_bucket.begin(); v != other_bucket.end(); ++v) {
|
Chris@16
|
155 double dist =
|
Chris@16
|
156 topology.distance(get(position, *u), get(position, *v));
|
Chris@16
|
157 if (dist < two_k) apply_force(*u, *v);
|
Chris@16
|
158 }
|
Chris@16
|
159 }
|
Chris@16
|
160 }
|
Chris@16
|
161 }
|
Chris@16
|
162 }
|
Chris@16
|
163
|
Chris@16
|
164 private:
|
Chris@16
|
165 const Topology& topology;
|
Chris@16
|
166 PositionMap position;
|
Chris@16
|
167 double two_k;
|
Chris@16
|
168 };
|
Chris@16
|
169
|
Chris@16
|
170 template<typename PositionMap, typename Topology, typename Graph>
|
Chris@16
|
171 inline grid_force_pairs<Topology, PositionMap>
|
Chris@16
|
172 make_grid_force_pairs
|
Chris@16
|
173 (const Topology& topology,
|
Chris@16
|
174 const PositionMap& position, const Graph& g)
|
Chris@16
|
175 { return grid_force_pairs<Topology, PositionMap>(topology, position, g); }
|
Chris@16
|
176
|
Chris@16
|
177 template<typename Graph, typename PositionMap, typename Topology>
|
Chris@16
|
178 void
|
Chris@16
|
179 scale_graph(const Graph& g, PositionMap position, const Topology& topology,
|
Chris@16
|
180 typename Topology::point_type upper_left, typename Topology::point_type lower_right)
|
Chris@16
|
181 {
|
Chris@16
|
182 if (num_vertices(g) == 0) return;
|
Chris@16
|
183
|
Chris@16
|
184 typedef typename Topology::point_type Point;
|
Chris@16
|
185 typedef typename Topology::point_difference_type point_difference_type;
|
Chris@16
|
186
|
Chris@16
|
187 // Find min/max ranges
|
Chris@16
|
188 Point min_point = get(position, *vertices(g).first), max_point = min_point;
|
Chris@16
|
189 BGL_FORALL_VERTICES_T(v, g, Graph) {
|
Chris@16
|
190 min_point = topology.pointwise_min(min_point, get(position, v));
|
Chris@16
|
191 max_point = topology.pointwise_max(max_point, get(position, v));
|
Chris@16
|
192 }
|
Chris@16
|
193
|
Chris@16
|
194 Point old_origin = topology.move_position_toward(min_point, 0.5, max_point);
|
Chris@16
|
195 Point new_origin = topology.move_position_toward(upper_left, 0.5, lower_right);
|
Chris@16
|
196 point_difference_type old_size = topology.difference(max_point, min_point);
|
Chris@16
|
197 point_difference_type new_size = topology.difference(lower_right, upper_left);
|
Chris@16
|
198
|
Chris@16
|
199 // Scale to bounding box provided
|
Chris@16
|
200 BGL_FORALL_VERTICES_T(v, g, Graph) {
|
Chris@16
|
201 point_difference_type relative_loc = topology.difference(get(position, v), old_origin);
|
Chris@16
|
202 relative_loc = (relative_loc / old_size) * new_size;
|
Chris@16
|
203 put(position, v, topology.adjust(new_origin, relative_loc));
|
Chris@16
|
204 }
|
Chris@16
|
205 }
|
Chris@16
|
206
|
Chris@16
|
207 namespace detail {
|
Chris@16
|
208 template<typename Topology, typename PropMap, typename Vertex>
|
Chris@16
|
209 void
|
Chris@16
|
210 maybe_jitter_point(const Topology& topology,
|
Chris@16
|
211 const PropMap& pm, Vertex v,
|
Chris@16
|
212 const typename Topology::point_type& p2)
|
Chris@16
|
213 {
|
Chris@16
|
214 double too_close = topology.norm(topology.extent()) / 10000.;
|
Chris@16
|
215 if (topology.distance(get(pm, v), p2) < too_close) {
|
Chris@16
|
216 put(pm, v,
|
Chris@16
|
217 topology.move_position_toward(get(pm, v), 1./200,
|
Chris@16
|
218 topology.random_point()));
|
Chris@16
|
219 }
|
Chris@16
|
220 }
|
Chris@16
|
221
|
Chris@16
|
222 template<typename Topology, typename PositionMap, typename DisplacementMap,
|
Chris@16
|
223 typename RepulsiveForce, typename Graph>
|
Chris@16
|
224 struct fr_apply_force
|
Chris@16
|
225 {
|
Chris@16
|
226 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
Chris@16
|
227 typedef typename Topology::point_type Point;
|
Chris@16
|
228 typedef typename Topology::point_difference_type PointDiff;
|
Chris@16
|
229
|
Chris@16
|
230 fr_apply_force(const Topology& topology,
|
Chris@16
|
231 const PositionMap& position,
|
Chris@16
|
232 const DisplacementMap& displacement,
|
Chris@16
|
233 RepulsiveForce repulsive_force, double k, const Graph& g)
|
Chris@16
|
234 : topology(topology), position(position), displacement(displacement),
|
Chris@16
|
235 repulsive_force(repulsive_force), k(k), g(g)
|
Chris@16
|
236 { }
|
Chris@16
|
237
|
Chris@16
|
238 void operator()(vertex_descriptor u, vertex_descriptor v)
|
Chris@16
|
239 {
|
Chris@16
|
240 if (u != v) {
|
Chris@16
|
241 // When the vertices land on top of each other, move the
|
Chris@16
|
242 // first vertex away from the boundaries.
|
Chris@16
|
243 maybe_jitter_point(topology, position, u, get(position, v));
|
Chris@16
|
244
|
Chris@16
|
245 double dist = topology.distance(get(position, u), get(position, v));
|
Chris@16
|
246 typename Topology::point_difference_type dispv = get(displacement, v);
|
Chris@16
|
247 if (dist == 0.) {
|
Chris@16
|
248 for (std::size_t i = 0; i < Point::dimensions; ++i) {
|
Chris@16
|
249 dispv[i] += 0.01;
|
Chris@16
|
250 }
|
Chris@16
|
251 } else {
|
Chris@16
|
252 double fr = repulsive_force(u, v, k, dist, g);
|
Chris@16
|
253 dispv += (fr / dist) *
|
Chris@16
|
254 topology.difference(get(position, v), get(position, u));
|
Chris@16
|
255 }
|
Chris@16
|
256 put(displacement, v, dispv);
|
Chris@16
|
257 }
|
Chris@16
|
258 }
|
Chris@16
|
259
|
Chris@16
|
260 private:
|
Chris@16
|
261 const Topology& topology;
|
Chris@16
|
262 PositionMap position;
|
Chris@16
|
263 DisplacementMap displacement;
|
Chris@16
|
264 RepulsiveForce repulsive_force;
|
Chris@16
|
265 double k;
|
Chris@16
|
266 const Graph& g;
|
Chris@16
|
267 };
|
Chris@16
|
268
|
Chris@16
|
269 } // end namespace detail
|
Chris@16
|
270
|
Chris@16
|
271 template<typename Topology, typename Graph, typename PositionMap,
|
Chris@16
|
272 typename AttractiveForce, typename RepulsiveForce,
|
Chris@16
|
273 typename ForcePairs, typename Cooling, typename DisplacementMap>
|
Chris@16
|
274 void
|
Chris@16
|
275 fruchterman_reingold_force_directed_layout
|
Chris@16
|
276 (const Graph& g,
|
Chris@16
|
277 PositionMap position,
|
Chris@16
|
278 const Topology& topology,
|
Chris@16
|
279 AttractiveForce attractive_force,
|
Chris@16
|
280 RepulsiveForce repulsive_force,
|
Chris@16
|
281 ForcePairs force_pairs,
|
Chris@16
|
282 Cooling cool,
|
Chris@16
|
283 DisplacementMap displacement)
|
Chris@16
|
284 {
|
Chris@16
|
285 typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
|
Chris@16
|
286 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
Chris@16
|
287 typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
|
Chris@16
|
288
|
Chris@16
|
289 double volume = topology.volume(topology.extent());
|
Chris@16
|
290
|
Chris@16
|
291 // assume positions are initialized randomly
|
Chris@16
|
292 double k = pow(volume / num_vertices(g), 1. / (double)(Topology::point_difference_type::dimensions));
|
Chris@16
|
293
|
Chris@16
|
294 detail::fr_apply_force<Topology, PositionMap, DisplacementMap,
|
Chris@16
|
295 RepulsiveForce, Graph>
|
Chris@16
|
296 apply_force(topology, position, displacement, repulsive_force, k, g);
|
Chris@16
|
297
|
Chris@16
|
298 do {
|
Chris@16
|
299 // Calculate repulsive forces
|
Chris@16
|
300 vertex_iterator v, v_end;
|
Chris@16
|
301 for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v)
|
Chris@16
|
302 put(displacement, *v, typename Topology::point_difference_type());
|
Chris@16
|
303 force_pairs(g, apply_force);
|
Chris@16
|
304
|
Chris@16
|
305 // Calculate attractive forces
|
Chris@16
|
306 edge_iterator e, e_end;
|
Chris@16
|
307 for (boost::tie(e, e_end) = edges(g); e != e_end; ++e) {
|
Chris@16
|
308 vertex_descriptor v = source(*e, g);
|
Chris@16
|
309 vertex_descriptor u = target(*e, g);
|
Chris@16
|
310
|
Chris@16
|
311 // When the vertices land on top of each other, move the
|
Chris@16
|
312 // first vertex away from the boundaries.
|
Chris@16
|
313 ::boost::detail::maybe_jitter_point(topology, position, u, get(position, v));
|
Chris@16
|
314
|
Chris@16
|
315 typename Topology::point_difference_type delta =
|
Chris@16
|
316 topology.difference(get(position, v), get(position, u));
|
Chris@16
|
317 double dist = topology.distance(get(position, u), get(position, v));
|
Chris@16
|
318 double fa = attractive_force(*e, k, dist, g);
|
Chris@16
|
319
|
Chris@16
|
320 put(displacement, v, get(displacement, v) - (fa / dist) * delta);
|
Chris@16
|
321 put(displacement, u, get(displacement, u) + (fa / dist) * delta);
|
Chris@16
|
322 }
|
Chris@16
|
323
|
Chris@16
|
324 if (double temp = cool()) {
|
Chris@16
|
325 // Update positions
|
Chris@16
|
326 BGL_FORALL_VERTICES_T (v, g, Graph) {
|
Chris@16
|
327 BOOST_USING_STD_MIN();
|
Chris@16
|
328 BOOST_USING_STD_MAX();
|
Chris@16
|
329 double disp_size = topology.norm(get(displacement, v));
|
Chris@16
|
330 put(position, v, topology.adjust(get(position, v), get(displacement, v) * (min BOOST_PREVENT_MACRO_SUBSTITUTION (disp_size, temp) / disp_size)));
|
Chris@16
|
331 put(position, v, topology.bound(get(position, v)));
|
Chris@16
|
332 }
|
Chris@16
|
333 } else {
|
Chris@16
|
334 break;
|
Chris@16
|
335 }
|
Chris@16
|
336 } while (true);
|
Chris@16
|
337 }
|
Chris@16
|
338
|
Chris@16
|
339 namespace detail {
|
Chris@16
|
340 template<typename DisplacementMap>
|
Chris@16
|
341 struct fr_force_directed_layout
|
Chris@16
|
342 {
|
Chris@16
|
343 template<typename Topology, typename Graph, typename PositionMap,
|
Chris@16
|
344 typename AttractiveForce, typename RepulsiveForce,
|
Chris@16
|
345 typename ForcePairs, typename Cooling,
|
Chris@16
|
346 typename Param, typename Tag, typename Rest>
|
Chris@16
|
347 static void
|
Chris@16
|
348 run(const Graph& g,
|
Chris@16
|
349 PositionMap position,
|
Chris@16
|
350 const Topology& topology,
|
Chris@16
|
351 AttractiveForce attractive_force,
|
Chris@16
|
352 RepulsiveForce repulsive_force,
|
Chris@16
|
353 ForcePairs force_pairs,
|
Chris@16
|
354 Cooling cool,
|
Chris@16
|
355 DisplacementMap displacement,
|
Chris@16
|
356 const bgl_named_params<Param, Tag, Rest>&)
|
Chris@16
|
357 {
|
Chris@16
|
358 fruchterman_reingold_force_directed_layout
|
Chris@16
|
359 (g, position, topology, attractive_force, repulsive_force,
|
Chris@16
|
360 force_pairs, cool, displacement);
|
Chris@16
|
361 }
|
Chris@16
|
362 };
|
Chris@16
|
363
|
Chris@16
|
364 template<>
|
Chris@16
|
365 struct fr_force_directed_layout<param_not_found>
|
Chris@16
|
366 {
|
Chris@16
|
367 template<typename Topology, typename Graph, typename PositionMap,
|
Chris@16
|
368 typename AttractiveForce, typename RepulsiveForce,
|
Chris@16
|
369 typename ForcePairs, typename Cooling,
|
Chris@16
|
370 typename Param, typename Tag, typename Rest>
|
Chris@16
|
371 static void
|
Chris@16
|
372 run(const Graph& g,
|
Chris@16
|
373 PositionMap position,
|
Chris@16
|
374 const Topology& topology,
|
Chris@16
|
375 AttractiveForce attractive_force,
|
Chris@16
|
376 RepulsiveForce repulsive_force,
|
Chris@16
|
377 ForcePairs force_pairs,
|
Chris@16
|
378 Cooling cool,
|
Chris@16
|
379 param_not_found,
|
Chris@16
|
380 const bgl_named_params<Param, Tag, Rest>& params)
|
Chris@16
|
381 {
|
Chris@16
|
382 typedef typename Topology::point_difference_type PointDiff;
|
Chris@16
|
383 std::vector<PointDiff> displacements(num_vertices(g));
|
Chris@16
|
384 fruchterman_reingold_force_directed_layout
|
Chris@16
|
385 (g, position, topology, attractive_force, repulsive_force,
|
Chris@16
|
386 force_pairs, cool,
|
Chris@16
|
387 make_iterator_property_map
|
Chris@16
|
388 (displacements.begin(),
|
Chris@16
|
389 choose_const_pmap(get_param(params, vertex_index), g,
|
Chris@16
|
390 vertex_index),
|
Chris@16
|
391 PointDiff()));
|
Chris@16
|
392 }
|
Chris@16
|
393 };
|
Chris@16
|
394
|
Chris@16
|
395 } // end namespace detail
|
Chris@16
|
396
|
Chris@16
|
397 template<typename Topology, typename Graph, typename PositionMap, typename Param,
|
Chris@16
|
398 typename Tag, typename Rest>
|
Chris@16
|
399 void
|
Chris@16
|
400 fruchterman_reingold_force_directed_layout
|
Chris@16
|
401 (const Graph& g,
|
Chris@16
|
402 PositionMap position,
|
Chris@16
|
403 const Topology& topology,
|
Chris@16
|
404 const bgl_named_params<Param, Tag, Rest>& params)
|
Chris@16
|
405 {
|
Chris@16
|
406 typedef typename get_param_type<vertex_displacement_t, bgl_named_params<Param,Tag,Rest> >::type D;
|
Chris@16
|
407
|
Chris@16
|
408 detail::fr_force_directed_layout<D>::run
|
Chris@16
|
409 (g, position, topology,
|
Chris@16
|
410 choose_param(get_param(params, attractive_force_t()),
|
Chris@16
|
411 square_distance_attractive_force()),
|
Chris@16
|
412 choose_param(get_param(params, repulsive_force_t()),
|
Chris@16
|
413 square_distance_repulsive_force()),
|
Chris@16
|
414 choose_param(get_param(params, force_pairs_t()),
|
Chris@16
|
415 make_grid_force_pairs(topology, position, g)),
|
Chris@16
|
416 choose_param(get_param(params, cooling_t()),
|
Chris@16
|
417 linear_cooling<double>(100)),
|
Chris@16
|
418 get_param(params, vertex_displacement_t()),
|
Chris@16
|
419 params);
|
Chris@16
|
420 }
|
Chris@16
|
421
|
Chris@16
|
422 template<typename Topology, typename Graph, typename PositionMap>
|
Chris@16
|
423 void
|
Chris@16
|
424 fruchterman_reingold_force_directed_layout
|
Chris@16
|
425 (const Graph& g,
|
Chris@16
|
426 PositionMap position,
|
Chris@16
|
427 const Topology& topology)
|
Chris@16
|
428 {
|
Chris@16
|
429 fruchterman_reingold_force_directed_layout
|
Chris@16
|
430 (g, position, topology,
|
Chris@16
|
431 attractive_force(square_distance_attractive_force()));
|
Chris@16
|
432 }
|
Chris@16
|
433
|
Chris@16
|
434 } // end namespace boost
|
Chris@16
|
435
|
Chris@16
|
436 #ifdef BOOST_GRAPH_USE_MPI
|
Chris@16
|
437 # include <boost/graph/distributed/fruchterman_reingold.hpp>
|
Chris@16
|
438 #endif
|
Chris@16
|
439
|
Chris@16
|
440 #endif // BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP
|