6 * $Date: 2012-07-05 16:45:20 +0200 (Do, 05. Jul 2012) $
7 ***************************************************************/
10 * \brief Implementation of class Multlevel (used by FMMMLayout).
12 * \author Stefan Hachul
15 * This file is part of the Open Graph Drawing Framework (OGDF).
19 * See README.txt in the root directory of the OGDF installation for details.
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * Version 2 or 3 as published by the Free Software Foundation;
25 * see the file LICENSE.txt included in the packaging of this file
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
35 * You should have received a copy of the GNU General Public
36 * License along with this program; if not, write to the Free
37 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
38 * Boston, MA 02110-1301, USA.
40 * \see http://www.gnu.org/copyleft/gpl.html
41 ***************************************************************/
44 #include "Multilevel.h"
47 #include <ogdf/basic/Array.h>
48 #include <ogdf/basic/Math.h>
49 #include <ogdf/basic/simple_graph_alg.h>
50 #include <ogdf/energybased/FMMMLayout.h>
55 void Multilevel::create_multilevel_representations(
57 NodeArray
<NodeAttributes
>& A
,
58 EdgeArray
<EdgeAttributes
>& E
,
63 Array
<Graph
*> &G_mult_ptr
,
64 Array
<NodeArray
<NodeAttributes
>*> &A_mult_ptr
,
65 Array
<EdgeArray
<EdgeAttributes
>*> &E_mult_ptr
,
68 //make initialisations;
70 G_mult_ptr
[0] = &G
; //init graph at level 0 to the original undirected simple
71 A_mult_ptr
[0] = &A
; //and loopfree connected graph G/A/E
74 int bad_edgenr_counter
= 0;
76 Graph
* act_Graph_ptr
= G_mult_ptr
[0];
78 while( (act_Graph_ptr
->numberOfNodes() > min_Graph_size
) &&
79 edgenumbersum_of_all_levels_is_linear(G_mult_ptr
,act_level
,bad_edgenr_counter
) )
81 Graph
* G_new
= new (Graph
);
82 NodeArray
<NodeAttributes
>* A_new
= OGDF_NEW NodeArray
<NodeAttributes
>;
83 EdgeArray
<EdgeAttributes
>* E_new
= OGDF_NEW EdgeArray
<EdgeAttributes
>;
84 G_mult_ptr
[act_level
+1] = G_new
;
85 A_mult_ptr
[act_level
+1] = A_new
;
86 E_mult_ptr
[act_level
+1] = E_new
;
88 init_multilevel_values(G_mult_ptr
,A_mult_ptr
,E_mult_ptr
,act_level
);
89 partition_galaxy_into_solar_systems(G_mult_ptr
,A_mult_ptr
,E_mult_ptr
,rand_seed
,
90 galaxy_choice
,random_tries
,act_level
);
91 collaps_solar_systems(G_mult_ptr
,A_mult_ptr
,E_mult_ptr
,act_level
);
94 act_Graph_ptr
= G_mult_ptr
[act_level
];
96 max_level
= act_level
;
100 bool Multilevel::edgenumbersum_of_all_levels_is_linear(
101 Array
<Graph
*> &G_mult_ptr
,
103 int& bad_edgenr_counter
)
109 if(G_mult_ptr
[act_level
]->numberOfEdges()<=
110 0.8 * double (G_mult_ptr
[act_level
-1]->numberOfEdges()))
112 else if(bad_edgenr_counter
< 5)
114 bad_edgenr_counter
++;
123 inline void Multilevel::init_multilevel_values(
124 Array
<Graph
*> &G_mult_ptr
,
125 Array
<NodeArray
<NodeAttributes
>*> &A_mult_ptr
,
126 Array
<EdgeArray
<EdgeAttributes
>*> &E_mult_ptr
,
130 forall_nodes(v
,*G_mult_ptr
[level
])
131 (*A_mult_ptr
[level
])[v
].init_mult_values();
134 forall_edges(e
,*G_mult_ptr
[level
])
135 (*E_mult_ptr
[level
])[e
].init_mult_values();
139 inline void Multilevel::partition_galaxy_into_solar_systems(
140 Array
<Graph
*> &G_mult_ptr
,
141 Array
<NodeArray
<NodeAttributes
>*> &A_mult_ptr
,
142 Array
<EdgeArray
<EdgeAttributes
>*> &E_mult_ptr
,
148 create_suns_and_planets(G_mult_ptr
, A_mult_ptr
, E_mult_ptr
, rand_seed
, galaxy_choice
,
149 random_tries
, act_level
);
150 create_moon_nodes_and_pm_nodes(G_mult_ptr
, A_mult_ptr
, E_mult_ptr
, act_level
);
154 void Multilevel::create_suns_and_planets(
155 Array
<Graph
*> &G_mult_ptr
,
156 Array
<NodeArray
<NodeAttributes
>*> &A_mult_ptr
,
157 Array
<EdgeArray
<EdgeAttributes
>*> &E_mult_ptr
,
164 node v
, sun_node
, planet_node
, newNode
, pos_moon_node
;
167 List
<node
> planet_nodes
;
168 List
<node
> sun_nodes
;
170 //make initialisations
172 Node_Set
.set_seed(rand_seed
); //set seed for random number generator
173 forall_nodes(v
,*G_mult_ptr
[act_level
])
174 if(act_level
== 0) (*A_mult_ptr
[act_level
])[v
].set_mass(1);
175 if(galaxy_choice
== FMMMLayout::gcUniformProb
)
176 Node_Set
.init_node_set(*G_mult_ptr
[act_level
]);
177 else //galaxy_choice != gcUniformProb in FMMMLayout
178 Node_Set
.init_node_set(*G_mult_ptr
[act_level
],*A_mult_ptr
[act_level
]);
181 while (!Node_Set
.empty_node_set())
183 //randomly select a sun node
184 planet_nodes
.clear();
185 if(galaxy_choice
== FMMMLayout::gcUniformProb
)
186 sun_node
= Node_Set
.get_random_node();
187 else if (galaxy_choice
== FMMMLayout::gcNonUniformProbLowerMass
)
188 sun_node
= Node_Set
.get_random_node_with_lowest_star_mass(random_tries
);
189 else //galaxy_choice == FMMMLayout::gcNonUniformProbHigherMass
190 sun_node
= Node_Set
.get_random_node_with_highest_star_mass(random_tries
);
191 sun_nodes
.pushBack(sun_node
);
193 //create new node at higher level that represents the collapsed solar_system
194 newNode
= G_mult_ptr
[act_level
+1]->newNode();
196 //update information for sun_node
197 (*A_mult_ptr
[act_level
])[sun_node
].set_higher_level_node(newNode
);
198 (*A_mult_ptr
[act_level
])[sun_node
].set_type(1);
199 (*A_mult_ptr
[act_level
])[sun_node
].set_dedicated_sun_node(sun_node
);
200 (*A_mult_ptr
[act_level
])[sun_node
].set_dedicated_sun_distance(0);
202 //update information for planet_nodes
203 forall_adj_edges(sun_edge
,sun_node
)
205 dist_to_sun
= (*E_mult_ptr
[act_level
])[sun_edge
].get_length();
206 if (sun_edge
->source() != sun_node
)
207 planet_node
= sun_edge
->source();
209 planet_node
= sun_edge
->target();
210 (*A_mult_ptr
[act_level
])[planet_node
].set_type(2);
211 (*A_mult_ptr
[act_level
])[planet_node
].set_dedicated_sun_node(sun_node
);
212 (*A_mult_ptr
[act_level
])[planet_node
].set_dedicated_sun_distance(dist_to_sun
);
213 planet_nodes
.pushBack(planet_node
);
216 //delete all planet_nodes and possible_moon_nodes from Node_Set
218 ListConstIterator
<node
> planet_node_ptr
;
219 //forall_listiterators(node,planet_node_ptr,planet_nodes)
220 for(planet_node_ptr
= planet_nodes
.begin(); planet_node_ptr
.valid(); ++planet_node_ptr
)
221 if(!Node_Set
.is_deleted(*planet_node_ptr
))
222 Node_Set
.delete_node(*planet_node_ptr
);
224 for(planet_node_ptr
= planet_nodes
.begin(); planet_node_ptr
.valid(); ++planet_node_ptr
)
225 //forall_listiterators(node,planet_node_ptr,planet_nodes)
227 forall_adj_edges(e
,*planet_node_ptr
)
229 if(e
->source() == *planet_node_ptr
)
230 pos_moon_node
= e
->target();
232 pos_moon_node
= e
->source();
233 if(!Node_Set
.is_deleted(pos_moon_node
))
234 Node_Set
.delete_node(pos_moon_node
);
239 //init *A_mult_ptr[act_level+1] and set NodeAttributes information for new nodes
240 A_mult_ptr
[act_level
+1]->init(*G_mult_ptr
[act_level
+1]);
241 forall_listiterators(node
, sun_node_ptr
, sun_nodes
)
243 newNode
= (*A_mult_ptr
[act_level
])[*sun_node_ptr
].get_higher_level_node();
244 (*A_mult_ptr
[act_level
+1])[newNode
].set_NodeAttributes((*A_mult_ptr
[act_level
])
245 [*sun_node_ptr
].get_width(),
246 (*A_mult_ptr
[act_level
])
247 [*sun_node_ptr
].get_height(),
248 (*A_mult_ptr
[act_level
])
249 [*sun_node_ptr
].get_position(),
251 (*A_mult_ptr
[act_level
+1])[newNode
].set_mass(0);
256 void Multilevel::create_moon_nodes_and_pm_nodes(
257 Array
<Graph
*> &G_mult_ptr
,
258 Array
<NodeArray
<NodeAttributes
>*> &A_mult_ptr
,
259 Array
<EdgeArray
<EdgeAttributes
>*> &E_mult_ptr
,
263 node v
, nearest_neighbour_node
, neighbour_node
, dedicated_sun_node
;
264 double dist_to_nearest_neighbour
, dedicated_sun_distance
;
269 forall_nodes(v
,*G_mult_ptr
[act_level
])
270 if((*A_mult_ptr
[act_level
])[v
].get_type() == 0) //a moon node
272 //find nearest neighbour node
273 first_adj_edge
= true;
274 forall_adj_edges(e
,v
)
277 neighbour_node
= e
->target();
279 neighbour_node
= e
->source();
280 neighbour_type
= (*A_mult_ptr
[act_level
])[neighbour_node
].get_type();
281 if( (neighbour_type
== 2) || (neighbour_type
== 3) )
285 first_adj_edge
= false;
287 dist_to_nearest_neighbour
= (*E_mult_ptr
[act_level
])[e
].get_length();
288 nearest_neighbour_node
= neighbour_node
;
290 else if(dist_to_nearest_neighbour
>(*E_mult_ptr
[act_level
])[e
].get_length())
293 dist_to_nearest_neighbour
= (*E_mult_ptr
[act_level
])[e
].get_length();
294 nearest_neighbour_node
= neighbour_node
;
298 //find dedic. solar system for v and update information in *A_mult_ptr[act_level]
299 //and *E_mult_ptr[act_level]
301 (*E_mult_ptr
[act_level
])[moon_edge
].make_moon_edge(); //mark this edge
302 dedicated_sun_node
= (*A_mult_ptr
[act_level
])[nearest_neighbour_node
].
303 get_dedicated_sun_node();
304 dedicated_sun_distance
= dist_to_nearest_neighbour
+ (*A_mult_ptr
[act_level
])
305 [nearest_neighbour_node
].get_dedicated_sun_distance();
306 (*A_mult_ptr
[act_level
])[v
].set_type(4);
307 (*A_mult_ptr
[act_level
])[v
].set_dedicated_sun_node(dedicated_sun_node
);
308 (*A_mult_ptr
[act_level
])[v
].set_dedicated_sun_distance(dedicated_sun_distance
);
309 (*A_mult_ptr
[act_level
])[v
].set_dedicated_pm_node(nearest_neighbour_node
);
311 //identify nearest_neighbour_node as a pm_node and update its information
313 (*A_mult_ptr
[act_level
])[nearest_neighbour_node
].set_type(3);
314 (*A_mult_ptr
[act_level
])[nearest_neighbour_node
].
315 get_dedicated_moon_node_List_ptr()->pushBack(v
);
320 inline void Multilevel::collaps_solar_systems(
321 Array
<Graph
*> &G_mult_ptr
,
322 Array
<NodeArray
<NodeAttributes
>*> &A_mult_ptr
,
323 Array
<EdgeArray
<EdgeAttributes
>*> &E_mult_ptr
,
326 EdgeArray
<double> new_edgelength
;
327 calculate_mass_of_collapsed_nodes(G_mult_ptr
, A_mult_ptr
, act_level
);
328 create_edges_edgedistances_and_lambda_Lists(G_mult_ptr
, A_mult_ptr
, E_mult_ptr
,
329 new_edgelength
, act_level
);
330 delete_parallel_edges_and_update_edgelength(G_mult_ptr
, E_mult_ptr
, new_edgelength
,
335 inline void Multilevel::calculate_mass_of_collapsed_nodes(
336 Array
<Graph
*> &G_mult_ptr
,
337 Array
<NodeArray
<NodeAttributes
>*> &A_mult_ptr
,
341 node dedicated_sun
,high_level_node
;
343 forall_nodes(v
,*G_mult_ptr
[act_level
])
345 dedicated_sun
= (*A_mult_ptr
[act_level
])[v
].get_dedicated_sun_node();
346 high_level_node
= (*A_mult_ptr
[act_level
])[dedicated_sun
].get_higher_level_node();
347 (*A_mult_ptr
[act_level
+1])[high_level_node
].set_mass((*A_mult_ptr
[act_level
+1])
348 [high_level_node
].get_mass()+1);
353 void Multilevel::create_edges_edgedistances_and_lambda_Lists(
354 Array
<Graph
*> &G_mult_ptr
,
355 Array
<NodeArray
<NodeAttributes
>*> &A_mult_ptr
,
356 Array
<EdgeArray
<EdgeAttributes
>*> &E_mult_ptr
,
357 EdgeArray
<double>& new_edgelength
,int
362 node s_sun_node
, t_sun_node
;
363 node high_level_sun_s
, high_level_sun_t
;
364 double length_e
, length_s_edge
, length_t_edge
, newlength
;
365 double lambda_s
, lambda_t
;
366 List
<edge
> inter_solar_system_edges
;
368 //create new edges at act_level+1 and create for each inter solar system edge at
369 //act_level a link to its corresponding edge
371 forall_edges(e
,*G_mult_ptr
[act_level
])
373 s_node
= e
->source();
374 t_node
= e
->target();
375 s_sun_node
= (*A_mult_ptr
[act_level
])[s_node
].get_dedicated_sun_node();
376 t_sun_node
= (*A_mult_ptr
[act_level
])[t_node
].get_dedicated_sun_node();
377 if( s_sun_node
!= t_sun_node
) //a inter solar system edge
379 high_level_sun_s
= (*A_mult_ptr
[act_level
])[s_sun_node
].get_higher_level_node();
380 high_level_sun_t
= (*A_mult_ptr
[act_level
])[t_sun_node
].get_higher_level_node();
382 //create new edge in *G_mult_ptr[act_level+1]
383 e_new
= G_mult_ptr
[act_level
+1]->newEdge(high_level_sun_s
,high_level_sun_t
);
384 (*E_mult_ptr
[act_level
])[e
].set_higher_level_edge(e_new
);
385 inter_solar_system_edges
.pushBack(e
);
389 //init new_edgelength calculate the values of new_edgelength and the lambda Lists
391 new_edgelength
.init(*G_mult_ptr
[act_level
+1]);
392 forall_listiterators(edge
, e_ptr
, inter_solar_system_edges
)
394 s_node
= (*e_ptr
)->source();
395 t_node
= (*e_ptr
)->target();
396 s_sun_node
= (*A_mult_ptr
[act_level
])[s_node
].get_dedicated_sun_node();
397 t_sun_node
= (*A_mult_ptr
[act_level
])[t_node
].get_dedicated_sun_node();
398 length_e
= (*E_mult_ptr
[act_level
])[*e_ptr
].get_length();
399 length_s_edge
=(*A_mult_ptr
[act_level
])[s_node
].get_dedicated_sun_distance();
400 length_t_edge
=(*A_mult_ptr
[act_level
])[t_node
].get_dedicated_sun_distance();
401 newlength
= length_s_edge
+ length_e
+ length_t_edge
;
403 //set new edge_length in *G_mult_ptr[act_level+1]
404 e_new
= (*E_mult_ptr
[act_level
])[*e_ptr
].get_higher_level_edge();
405 new_edgelength
[e_new
] = newlength
;
407 //create entries in lambda Lists
408 lambda_s
= length_s_edge
/newlength
;
409 lambda_t
= length_t_edge
/newlength
;
410 (*A_mult_ptr
[act_level
])[s_node
].get_lambda_List_ptr()->pushBack(lambda_s
);
411 (*A_mult_ptr
[act_level
])[t_node
].get_lambda_List_ptr()->pushBack(lambda_t
);
412 (*A_mult_ptr
[act_level
])[s_node
].get_neighbour_sun_node_List_ptr()->pushBack(
414 (*A_mult_ptr
[act_level
])[t_node
].get_neighbour_sun_node_List_ptr()->pushBack(
420 void Multilevel::delete_parallel_edges_and_update_edgelength(
421 Array
<Graph
*> &G_mult_ptr
,
422 Array
<EdgeArray
<EdgeAttributes
>*> &E_mult_ptr
,
423 EdgeArray
<double>& new_edgelength
,int
426 EdgeMaxBucketFunc get_max_index
;
427 EdgeMinBucketFunc get_min_index
;
430 List
<Edge
> sorted_edges
;
431 Graph
* Graph_ptr
= G_mult_ptr
[act_level
+1];
432 int save_s_index
,save_t_index
,act_s_index
,act_t_index
;
435 //make *G_mult_ptr[act_level+1] undirected
436 makeSimpleUndirected(*G_mult_ptr
[act_level
+1]);
438 //sort the List sorted_edges
439 forall_edges(e_act
,*Graph_ptr
)
441 f_act
.set_Edge(e_act
,Graph_ptr
);
442 sorted_edges
.pushBack(f_act
);
445 sorted_edges
.bucketSort(0,Graph_ptr
->numberOfNodes()-1,get_max_index
);
446 sorted_edges
.bucketSort(0,Graph_ptr
->numberOfNodes()-1,get_min_index
);
448 //now parallel edges are consecutive in sorted_edges
449 forall_listiterators(Edge
, EdgeIterator
,sorted_edges
)
451 e_act
= (*EdgeIterator
).get_edge();
452 act_s_index
= e_act
->source()->index();
453 act_t_index
= e_act
->target()->index();
455 if(EdgeIterator
!= sorted_edges
.begin())
457 if( (act_s_index
== save_s_index
&& act_t_index
== save_t_index
) ||
458 (act_s_index
== save_t_index
&& act_t_index
== save_s_index
) )
460 new_edgelength
[e_save
] += new_edgelength
[e_act
];
461 Graph_ptr
->delEdge(e_act
);
468 new_edgelength
[e_save
] /= counter
;
471 save_s_index
= act_s_index
;
472 save_t_index
= act_t_index
;
478 save_s_index
= act_s_index
;
479 save_t_index
= act_t_index
;
484 //treat special case (last edges were multiple edges)
486 new_edgelength
[e_save
] /= counter
;
488 //init *E_mult_ptr[act_level+1] and import EdgeAttributes
489 E_mult_ptr
[act_level
+1]->init(*G_mult_ptr
[act_level
+1]);
490 forall_edges(e_act
,*Graph_ptr
)
491 (*E_mult_ptr
[act_level
+1])[e_act
].set_length(new_edgelength
[e_act
]);
495 void Multilevel::find_initial_placement_for_level(
497 int init_placement_way
,
498 Array
<Graph
*> &G_mult_ptr
,
499 Array
<NodeArray
<NodeAttributes
>*> &A_mult_ptr
,
500 Array
<EdgeArray
<EdgeAttributes
>*> &E_mult_ptr
)
503 set_initial_positions_of_sun_nodes(level
, G_mult_ptr
, A_mult_ptr
);
504 set_initial_positions_of_planet_and_moon_nodes(level
, init_placement_way
, G_mult_ptr
,
505 A_mult_ptr
, E_mult_ptr
, pm_nodes
);
506 set_initial_positions_of_pm_nodes(level
, init_placement_way
, A_mult_ptr
,
507 E_mult_ptr
, pm_nodes
);
511 void Multilevel::set_initial_positions_of_sun_nodes(
513 Array
<Graph
*> &G_mult_ptr
,
514 Array
<NodeArray
<NodeAttributes
>*> &A_mult_ptr
)
518 forall_nodes(v_high
,*G_mult_ptr
[level
+1])
520 v_act
= (*A_mult_ptr
[level
+1])[v_high
].get_lower_level_node();
521 new_pos
= (*A_mult_ptr
[level
+1])[v_high
].get_position();
522 (*A_mult_ptr
[level
])[v_act
].set_position(new_pos
);
523 (*A_mult_ptr
[level
])[v_act
].place();
528 void Multilevel::set_initial_positions_of_planet_and_moon_nodes(
530 int init_placement_way
,
531 Array
<Graph
*> &G_mult_ptr
,
532 Array
<NodeArray
<NodeAttributes
>*> &A_mult_ptr
,
533 Array
<EdgeArray
<EdgeAttributes
>*> &E_mult_ptr
,
534 List
<node
>& pm_nodes
)
536 double lambda
, dedicated_sun_distance
;
538 node v
, v_adj
, dedicated_sun
;
540 DPoint new_pos
,dedicated_sun_pos
, adj_sun_pos
;
542 ListIterator
<double> lambdaIterator
;
544 create_all_placement_sectors(G_mult_ptr
,A_mult_ptr
,E_mult_ptr
,level
);
545 forall_nodes(v
,*G_mult_ptr
[level
])
547 node_type
= (*A_mult_ptr
[level
])[v
].get_type();
549 pm_nodes
.pushBack(v
);
550 else if(node_type
== 2 || node_type
== 4) //a planet_node or moon_node
553 dedicated_sun
= (*A_mult_ptr
[level
])[v
].get_dedicated_sun_node();
554 dedicated_sun_pos
= (*A_mult_ptr
[level
])[dedicated_sun
].get_position();
555 dedicated_sun_distance
= (*A_mult_ptr
[level
])[v
].get_dedicated_sun_distance();
557 if(init_placement_way
== FMMMLayout::ipmAdvanced
)
559 forall_adj_edges(e
,v
)
565 if( ( (*A_mult_ptr
[level
])[v
].get_dedicated_sun_node() ==
566 (*A_mult_ptr
[level
])[v_adj
].get_dedicated_sun_node() ) &&
567 ( (*A_mult_ptr
[level
])[v_adj
].get_type() != 1 ) &&
568 ( (*A_mult_ptr
[level
])[v_adj
].is_placed() ) )
570 new_pos
= calculate_position(dedicated_sun_pos
,(*A_mult_ptr
[level
])
571 [v_adj
].get_position(),dedicated_sun_distance
,
572 (*E_mult_ptr
[level
])[e
].get_length());
577 if ((*A_mult_ptr
[level
])[v
].get_lambda_List_ptr()->empty())
581 new_pos
= create_random_pos(dedicated_sun_pos
,(*A_mult_ptr
[level
])
582 [v
].get_dedicated_sun_distance(),
583 (*A_mult_ptr
[level
])[v
].get_angle_1(),
584 (*A_mult_ptr
[level
])[v
].get_angle_2());
590 lambdaIterator
= (*A_mult_ptr
[level
])[v
].get_lambda_List_ptr()->begin();
592 forall_listiterators(node
, adj_sun_ptr
,*(*A_mult_ptr
[level
])[v
].
593 get_neighbour_sun_node_List_ptr())
595 lambda
= *lambdaIterator
;
596 adj_sun_pos
= (*A_mult_ptr
[level
])[*adj_sun_ptr
].get_position();
597 new_pos
= get_waggled_inbetween_position(dedicated_sun_pos
,adj_sun_pos
,
600 if(lambdaIterator
!= (*A_mult_ptr
[level
])[v
].get_lambda_List_ptr()
602 lambdaIterator
= (*A_mult_ptr
[level
])[v
].get_lambda_List_ptr()
603 ->cyclicSucc(lambdaIterator
);
607 (*A_mult_ptr
[level
])[v
].set_position(get_barycenter_position(L
));
608 (*A_mult_ptr
[level
])[v
].place();
614 void Multilevel::create_all_placement_sectors(
615 Array
<Graph
*> &G_mult_ptr
,
616 Array
<NodeArray
<NodeAttributes
>*> &A_mult_ptr
,
617 Array
<EdgeArray
<EdgeAttributes
>*> &E_mult_ptr
,
620 node v_high
, w_high
, sun_node
, v
, ded_sun
;
622 List
<DPoint
> adj_pos
;
623 double angle_1
, angle_2
, act_angle_1
, act_angle_2
, next_angle
, min_next_angle
;
624 DPoint start_pos
, end_pos
;
625 int MAX
= 10; //the biggest of at most MAX random selected sectors is choosen
627 ListIterator
<DPoint
> it
, next_pos_ptr
;
631 forall_nodes(v_high
,(*G_mult_ptr
[level
+1]))
633 //find pos of adjacent nodes
635 DPoint
v_high_pos ((*A_mult_ptr
[level
+1])[v_high
].get_x(),
636 (*A_mult_ptr
[level
+1])[v_high
].get_y());
637 forall_adj_edges(e_high
,v_high
)
638 if(!(*E_mult_ptr
[level
+1])[e_high
].is_extra_edge())
640 if(v_high
== e_high
->source())
641 w_high
= e_high
->target();
643 w_high
= e_high
->source();
645 DPoint
w_high_pos ((*A_mult_ptr
[level
+1])[w_high
].get_x(),
646 (*A_mult_ptr
[level
+1])[w_high
].get_y());
647 adj_pos
.pushBack(w_high_pos
);
649 if(adj_pos
.empty()) //easy case
654 else if(adj_pos
.size() == 1) //special case
657 start_pos
= *adj_pos
.begin();
658 DPoint
x_parallel_pos (v_high_pos
.m_x
+ 1, v_high_pos
.m_y
);
659 angle_1
= angle(v_high_pos
,x_parallel_pos
,start_pos
);
661 angle_2
= angle_1
+ Math::pi
;
666 it
= adj_pos
.begin();
671 DPoint
x_parallel_pos (v_high_pos
.m_x
+ 1, v_high_pos
.m_y
);
672 act_angle_1
= angle(v_high_pos
,x_parallel_pos
,start_pos
);
676 for(next_pos_ptr
= adj_pos
.begin();next_pos_ptr
.valid();++next_pos_ptr
)
678 next_angle
= angle(v_high_pos
,start_pos
,*next_pos_ptr
);
680 if(start_pos
!= *next_pos_ptr
&& (first_angle
|| next_angle
<
683 min_next_angle
= next_angle
;
687 act_angle_2
= act_angle_1
+ min_next_angle
;
688 if((it
== adj_pos
.begin())||((act_angle_2
-act_angle_1
)>(angle_2
-angle_1
)))
690 angle_1
= act_angle_1
;
691 angle_2
= act_angle_2
;
693 if(it
!= adj_pos
.rbegin())
694 it
= adj_pos
.cyclicSucc(it
);
697 while((steps
<= MAX
) && (it
!= adj_pos
.rbegin()));
699 if(angle_1
== angle_2
)
700 angle_2
= angle_1
+ Math::pi
;
703 //import angle_1 and angle_2 to the dedicated suns at level level
704 sun_node
= (*A_mult_ptr
[level
+1])[v_high
].get_lower_level_node();
705 (*A_mult_ptr
[level
])[sun_node
].set_angle_1(angle_1
);
706 (*A_mult_ptr
[level
])[sun_node
].set_angle_2(angle_2
);
709 //import the angle values from the values of the dedicated sun nodes
710 forall_nodes(v
,*G_mult_ptr
[level
])
712 ded_sun
= (*A_mult_ptr
[level
])[v
].get_dedicated_sun_node();
713 (*A_mult_ptr
[level
])[v
].set_angle_1((*A_mult_ptr
[level
])[ded_sun
].get_angle_1());
714 (*A_mult_ptr
[level
])[v
].set_angle_2((*A_mult_ptr
[level
])[ded_sun
].get_angle_2());
719 void Multilevel::set_initial_positions_of_pm_nodes(
721 int init_placement_way
,
722 Array
<NodeArray
<NodeAttributes
>*> &A_mult_ptr
,
723 Array
<EdgeArray
<EdgeAttributes
>*> &E_mult_ptr
,
724 List
<node
>& pm_nodes
)
726 double moon_dist
, sun_dist
, lambda
;
727 node v_adj
, sun_node
;
729 DPoint sun_pos
, moon_pos
, new_pos
, adj_sun_pos
;
731 ListIterator
<double> lambdaIterator
;
733 forall_listiterators(node
,v_ptr
,pm_nodes
)
736 sun_node
= (*A_mult_ptr
[level
])[*v_ptr
].get_dedicated_sun_node();
737 sun_pos
= (*A_mult_ptr
[level
])[sun_node
].get_position();
738 sun_dist
= (*A_mult_ptr
[level
])[*v_ptr
].get_dedicated_sun_distance();
740 if(init_placement_way
== FMMMLayout::ipmAdvanced
)
742 forall_adj_edges(e
,*v_ptr
)
744 if(e
->source() != *v_ptr
)
748 if( (!(*E_mult_ptr
[level
])[e
].is_moon_edge()) &&
749 ( (*A_mult_ptr
[level
])[*v_ptr
].get_dedicated_sun_node() ==
750 (*A_mult_ptr
[level
])[v_adj
].get_dedicated_sun_node() ) &&
751 ( (*A_mult_ptr
[level
])[v_adj
].get_type() != 1 ) &&
752 ( (*A_mult_ptr
[level
])[v_adj
].is_placed() ) )
754 new_pos
= calculate_position(sun_pos
,(*A_mult_ptr
[level
])[v_adj
].
755 get_position(),sun_dist
,(*E_mult_ptr
[level
])
761 forall_listiterators(node
, moon_node_ptr
,*(*A_mult_ptr
[level
])[*v_ptr
].
762 get_dedicated_moon_node_List_ptr())
764 moon_pos
= (*A_mult_ptr
[level
])[*moon_node_ptr
].get_position();
765 moon_dist
= (*A_mult_ptr
[level
])[*moon_node_ptr
].get_dedicated_sun_distance();
766 lambda
= sun_dist
/moon_dist
;
767 new_pos
= get_waggled_inbetween_position(sun_pos
,moon_pos
,lambda
);
771 if (!(*A_mult_ptr
[level
])[*v_ptr
].get_lambda_List_ptr()->empty())
773 lambdaIterator
= (*A_mult_ptr
[level
])[*v_ptr
].get_lambda_List_ptr()->begin();
775 forall_listiterators(node
,adj_sun_ptr
,*(*A_mult_ptr
[level
])[*v_ptr
].
776 get_neighbour_sun_node_List_ptr())
778 lambda
= *lambdaIterator
;
779 adj_sun_pos
= (*A_mult_ptr
[level
])[*adj_sun_ptr
].get_position();
780 new_pos
= get_waggled_inbetween_position(sun_pos
,adj_sun_pos
,lambda
);
782 if(lambdaIterator
!= (*A_mult_ptr
[level
])[*v_ptr
].get_lambda_List_ptr()
784 lambdaIterator
= (*A_mult_ptr
[level
])[*v_ptr
].get_lambda_List_ptr()
785 ->cyclicSucc(lambdaIterator
);
789 (*A_mult_ptr
[level
])[*v_ptr
].set_position(get_barycenter_position(L
));
790 (*A_mult_ptr
[level
])[*v_ptr
].place();
795 inline DPoint
Multilevel::create_random_pos(DPoint center
,double radius
,double angle_1
,
798 const int BILLION
= 1000000000;
800 double rnd
= double(randomNumber(1,BILLION
)+1)/(BILLION
+2);//rand number in (0,1)
801 double rnd_angle
= angle_1
+(angle_2
-angle_1
)*rnd
;
802 double dx
= cos(rnd_angle
) * radius
;
803 double dy
= sin(rnd_angle
) * radius
;
804 new_point
.m_x
= center
.m_x
+ dx
;
805 new_point
.m_y
= center
.m_y
+ dy
;
810 inline DPoint
Multilevel::get_waggled_inbetween_position(DPoint s
, DPoint t
, double lambda
)
812 const double WAGGLEFACTOR
= 0.05;
813 const int BILLION
= 1000000000;
814 DPoint inbetween_point
;
815 inbetween_point
.m_x
= s
.m_x
+ lambda
*(t
.m_x
- s
.m_x
);
816 inbetween_point
.m_y
= s
.m_y
+ lambda
*(t
.m_y
- s
.m_y
);
817 double radius
= WAGGLEFACTOR
* (t
-s
).norm();
818 double rnd
= double(randomNumber(1,BILLION
)+1)/(BILLION
+2);//rand number in (0,1)
819 double rand_radius
= radius
* rnd
;
820 return create_random_pos(inbetween_point
,rand_radius
,0,6.2831853);
824 inline DPoint
Multilevel::get_barycenter_position(List
<DPoint
>& L
)
829 forall_listiterators(DPoint
, act_point_ptr
,L
)
830 sum
= sum
+ (*act_point_ptr
);
831 barycenter
.m_x
= sum
.m_x
/L
.size();
832 barycenter
.m_y
= sum
.m_y
/L
.size();
837 inline DPoint
Multilevel::calculate_position(DPoint P
, DPoint Q
, double dist_P
, double dist_Q
)
839 double dist_PQ
= (P
-Q
).norm();
840 double lambda
= (dist_P
+ (dist_PQ
- dist_P
- dist_Q
)/2)/dist_PQ
;
841 return get_waggled_inbetween_position(P
,Q
,lambda
);
845 void Multilevel::delete_multilevel_representations(
846 Array
<Graph
*> &G_mult_ptr
,
847 Array
<NodeArray
<NodeAttributes
>*> &A_mult_ptr
,
848 Array
<EdgeArray
<EdgeAttributes
>*> &E_mult_ptr
,
851 for(int i
=1; i
<= max_level
; i
++)
853 delete G_mult_ptr
[i
];
854 delete A_mult_ptr
[i
];
855 delete E_mult_ptr
[i
];
860 double Multilevel::angle(DPoint
& P
, DPoint
& Q
, DPoint
& R
)
862 double dx1
= Q
.m_x
- P
.m_x
;
863 double dy1
= Q
.m_y
- P
.m_y
;
864 double dx2
= R
.m_x
- P
.m_x
;
865 double dy2
= R
.m_y
- P
.m_y
;
866 double fi
;//the angle
868 if ((dx1
== 0 && dy1
== 0) || (dx2
== 0 && dy2
== 0))
869 cout
<<"Multilevel::angle()"<<endl
;
871 double norm
= (dx1
*dx1
+dy1
*dy1
)*(dx2
*dx2
+dy2
*dy2
);
872 double cosfi
= (dx1
*dx2
+dy1
*dy2
) / sqrt(norm
);
874 if (cosfi
>= 1.0 ) fi
= 0;
875 if (cosfi
<= -1.0 ) fi
= Math::pi
;
879 if (dx1
*dy2
< dy1
*dx2
) fi
= -fi
;
880 if (fi
< 0) fi
+= 2*Math::pi
;