Commit 05eb1d20 authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

sfdp_layout(): implement preferential ordering along y direction

parent 79d8f45b
......@@ -60,6 +60,10 @@ void sfdp_layout(GraphInterface& g, boost::any pos, boost::any vweight,
typedef vprop_map_t<int32_t>::type c_map_t;
c_map_t c_map = boost::any_cast<c_map_t>(python::extract<any&>(spring_parms[8])());
double R = python::extract<double>(spring_parms[9]);
typedef vprop_map_t<double>::type o_map_t;
o_map_t o_map = boost::any_cast<o_map_t>(python::extract<any&>(spring_parms[10])());
if(vweight.empty())
vweight = vweight_map_t();
if(eweight.empty())
......@@ -76,6 +80,7 @@ void sfdp_layout(GraphInterface& g, boost::any pos, boost::any vweight,
pin_map.get_unchecked(num_vertices(g.get_graph())),
groups, C, K, p, theta, gamma, mu, kappa, r,
c_map.get_unchecked(num_vertices(g.get_graph())),
R, o_map.get_unchecked(num_vertices(g.get_graph())),
init_step,
step_schedule, max_level, epsilon, max_iter,
adaptive, verbose, rng);
......
......@@ -251,14 +251,16 @@ static double norm(Pos& x)
template <class Graph, class PosMap, class VertexWeightMap,
class EdgeWeightMap, class PinMap, class GroupMaps, class CMap,
class OrderMap,
class RNG>
void get_sfdp_layout(Graph& g, PosMap pos, VertexWeightMap vweight,
EdgeWeightMap eweight, PinMap pin, GroupMaps& groups,
double C, double K, double p, double theta, double gamma,
double mu, double kappa, double r, CMap c,
double init_step, double step_schedule, size_t max_level,
double epsilon, size_t max_iter, bool simple,
bool verbose, RNG& rng)
void get_sfdp_layout(Graph& g, PosMap pos, VertexWeightMap vweight,
EdgeWeightMap eweight, PinMap pin, GroupMaps& groups,
double C, double K, double p, double theta, double gamma,
double mu, double kappa, double r, CMap c, double R,
OrderMap yorder,
double init_step, double step_schedule, size_t max_level,
double epsilon, size_t max_iter, bool simple,
bool verbose, RNG& rng)
{
typedef typename property_traits<PosMap>::value_type::value_type val_t;
typedef std::array<val_t, 2> pos_t;
......@@ -268,7 +270,12 @@ void get_sfdp_layout(Graph& g, PosMap pos, VertexWeightMap vweight,
vector<size_t> vertices;
idx_map<size_t, size_t> rs;
double ocenter = 0;
double omax = -std::numeric_limits<double>::max();
double omin = std::numeric_limits<double>::max();
int HN = 0;
vweight_t W = 0;
for (auto v : vertices_range(g))
{
if (pin[v] == 0)
......@@ -277,8 +284,16 @@ void get_sfdp_layout(Graph& g, PosMap pos, VertexWeightMap vweight,
HN++;
rs[groups[0][v]]++;
ocenter += yorder[v] * get(vweight, v);
omax = max(yorder[v], omax);
omin = min(yorder[v], omin);
W += get(vweight, v);
}
ocenter /= W;
double o_rg = omax - omin;
val_t delta = epsilon * K + 1, E = 0, E0;
E0 = numeric_limits<val_t>::max();
size_t n_iter = 0;
......@@ -299,6 +314,11 @@ void get_sfdp_layout(Graph& g, PosMap pos, VertexWeightMap vweight,
ccm.clear();
csize.clear();
double ycenter = 0;
val_t ymax = -std::numeric_limits<val_t>::max();
val_t ymin = std::numeric_limits<val_t>::max();
for (auto v : vertices_range(g))
{
for (size_t j = 0; j < 2; ++j)
......@@ -317,7 +337,13 @@ void get_sfdp_layout(Graph& g, PosMap pos, VertexWeightMap vweight,
csize[s] += get(vweight, v);
for (size_t j = 0; j < 2; ++j)
ccm[s][j] += pos[v][j] * get(vweight, v);
ycenter += pos[v][1] * get(vweight, v);
ymin = min(ymin, pos[v][1]);
ymax = max(ymax, pos[v][1]);
}
ycenter /= W;
double y_rg = ymax - ymin;
for (size_t s = 0; s < ccm.size(); ++s)
{
......@@ -482,6 +508,14 @@ void get_sfdp_layout(Graph& g, PosMap pos, VertexWeightMap vweight,
}
}
// yorder repulsive force
if (R > 0)
{
double dz = (yorder[v] - ocenter)/o_rg;
double dp = (pos[v][1] - ycenter)/y_rg;
ftot[1] += R * (dz - dp);
}
E += pow2(norm(ftot));
for (size_t l = 0; l < 2; ++l)
......
......@@ -524,7 +524,7 @@ def coarse_graphs(g, method="hybrid", mivs_thres=0.9, ec_thres=0.75,
def sfdp_layout(g, vweight=None, eweight=None, pin=None, groups=None, C=0.2,
K=None, p=2., theta=0.6, max_level=15, r=1., gamma=.3, mu=2.,
kappa=1., init_step=None, cooling_step=0.95,
kappa=1., rmap=None, R=1, init_step=None, cooling_step=0.95,
adaptive_cooling=True, epsilon=1e-2, max_iter=0, pos=None,
multilevel=None, coarse_method="hybrid", mivs_thres=0.9,
ec_thres=0.75, weighted_coarse=False, verbose=False):
......@@ -563,6 +563,11 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, groups=None, C=0.2,
Typical length of the repulsive force between different groups.
kappa : float (optional, default: ``1.0``)
Multiplicative factor on the attracttive force between nodes of the same group.
rmap : :class:`~graph_tool.VertexPropertyMap` (optional, default: ``None``)
Vertex rank to be used around to order them preferentially in the
:math:`y` direction.
R : float (optional, default: ``1.0``)
Strength of the rank ordering in the :math:`y` direction.
init_step : float (optional, default: ``None``)
Initial update step. If not provided, it will be chosen automatically.
cooling_step : float (optional, default: ``0.95``)
......@@ -632,6 +637,7 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, groups=None, C=0.2,
.. [hu-multilevel-2005] Yifan Hu, "Efficient and High Quality Force-Directed
Graph", Mathematica Journal, vol. 10, Issue 1, pp. 37-71, (2005)
http://www.mathematica-journal.com/issue/v10i1/graph_draw.html
"""
if pos is None:
......@@ -657,6 +663,12 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, groups=None, C=0.2,
mu *= K
if rmap is None:
rmap = g.new_vp("double")
R = 0
elif rmap.value_type() != "double":
rmap = rmap.copy("double")
if init_step is None:
init_step = 2 * max(_avg_edge_distance(g, pos), K)
......@@ -717,7 +729,7 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, groups=None, C=0.2,
_prop("e", g, eweight),
_prop("v", g, pin),
(C, K, p, gamma, mu, kappa, groups, r,
_prop("v", g, c)),
_prop("v", g, c), R, _prop("v", g, rmap)),
theta, init_step, cooling_step, max_level,
epsilon, max_iter, not adaptive_cooling,
verbose, _get_rng())
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment