void FruchtermanReingold::make_initialisations(double bl, DPoint d_l_c, int grid_quot) { grid_quotient(grid_quot); down_left_corner = d_l_c; //export this two values from FMMM boxlength = bl; }
FruchtermanReingold:: FruchtermanReingold() { grid_quotient(2); }
void FruchtermanReingold::calculate_approx_repulsive_forces( const Graph &G, NodeArray<NodeAttributes> &A, NodeArray<DPoint>& F_rep) { //GRID algorithm by Fruchterman & Reingold numexcept N; List<IPoint> neighbour_boxes; List<node> neighbour_box; IPoint act_neighbour_box; IPoint neighbour; DPoint f_rep_u_on_v; DPoint vector_v_minus_u; DPoint nullpoint(0, 0); DPoint pos_u, pos_v; double norm_v_minus_u; double scalar; int i, j, act_i, act_j, k, l, length; double gridboxlength;//length of a box in the GRID //init F_rep for (node v : G.nodes) F_rep[v] = nullpoint; //init max_gridindex and set contained_nodes; max_gridindex = static_cast<int> (sqrt(double(G.numberOfNodes())) / grid_quotient()) - 1; max_gridindex = ((max_gridindex > 0) ? max_gridindex : 0); Array2D<List<node> > contained_nodes(0, max_gridindex, 0, max_gridindex); for (i = 0; i <= max_gridindex; i++) for (j = 0; j <= max_gridindex; j++) { contained_nodes(i, j).clear(); } gridboxlength = boxlength / (max_gridindex + 1); for (node v : G.nodes) { double x = A[v].get_x() - down_left_corner.m_x;//shift comput. box to nullpoint double y = A[v].get_y() - down_left_corner.m_y; int x_index = static_cast<int>(x / gridboxlength); int y_index = static_cast<int>(y / gridboxlength); contained_nodes(x_index, y_index).pushBack(v); } //force calculation for (i = 0; i <= max_gridindex; i++) for (j = 0; j <= max_gridindex; j++) { //step1: calculate forces inside contained_nodes(i,j) length = contained_nodes(i, j).size(); Array<node> nodearray_i_j(length + 1); k = 1; for (node v : contained_nodes(i, j)) { nodearray_i_j[k] = v; k++; } for (k = 1; k < length; k++) for (l = k + 1; l <= length; l++) { node u = nodearray_i_j[k]; node v = nodearray_i_j[l]; pos_u = A[u].get_position(); pos_v = A[v].get_position(); if (pos_u == pos_v) {//if2 (Exception handling if two nodes have the same position) pos_u = N.choose_distinct_random_point_in_radius_epsilon(pos_u); }//if2 vector_v_minus_u = pos_v - pos_u; norm_v_minus_u = vector_v_minus_u.norm(); if (!N.f_rep_near_machine_precision(norm_v_minus_u, f_rep_u_on_v)) { scalar = f_rep_scalar(norm_v_minus_u) / norm_v_minus_u; f_rep_u_on_v.m_x = scalar * vector_v_minus_u.m_x; f_rep_u_on_v.m_y = scalar * vector_v_minus_u.m_y; } F_rep[v] = F_rep[v] + f_rep_u_on_v; F_rep[u] = F_rep[u] - f_rep_u_on_v; } //step 2: calculated forces to nodes in neighbour boxes //find_neighbour_boxes neighbour_boxes.clear(); for (k = i - 1; k <= i + 1; k++) for (l = j - 1; l <= j + 1; l++) if ((k >= 0) && (l >= 0) && (k <= max_gridindex) && (l <= max_gridindex)) { neighbour.m_x = k; neighbour.m_y = l; if ((k != i) || (l != j)) neighbour_boxes.pushBack(neighbour); } //forget neighbour_boxes that already had access to this box for (const IPoint &act_neighbour_box : neighbour_boxes) { act_i = act_neighbour_box.m_x; act_j = act_neighbour_box.m_y; if ((act_j == j + 1) || ((act_j == j) && (act_i == i + 1))) { for (node v : contained_nodes(i, j)) { for (node u : contained_nodes(act_i, act_j)) { pos_u = A[u].get_position(); pos_v = A[v].get_position(); if (pos_u == pos_v) {// (Exception handling if two nodes have the same position) pos_u = N.choose_distinct_random_point_in_radius_epsilon(pos_u); } vector_v_minus_u = pos_v - pos_u; norm_v_minus_u = vector_v_minus_u.norm(); if (!N.f_rep_near_machine_precision(norm_v_minus_u, f_rep_u_on_v)) { scalar = f_rep_scalar(norm_v_minus_u) / norm_v_minus_u; f_rep_u_on_v.m_x = scalar * vector_v_minus_u.m_x; f_rep_u_on_v.m_y = scalar * vector_v_minus_u.m_y; } F_rep[v] = F_rep[v] + f_rep_u_on_v; F_rep[u] = F_rep[u] - f_rep_u_on_v; } } } } } }