Hi,
i'm trying to code the fruchterman_reingold algorithm for a graph (basic physics between nodes such that it lays out nicely)
I'm using this old lab as a guide.
I'm having trouble iterating over the vertices of the graph. i think it would be best to use iterator, but it seems to complicate everything.
I now need to have current as a member to remember where i'm iterating for the next() call.
I also have and id for the node. Without iterator i would juste use the index to compare.
Here is the code :
mod graph{
use std::collections::HashMap;
pub struct Graph{
adjancy_list : Vec<Node>,
current : usize,
}
#[derive(Clone,Debug)]
pub struct Node {
links : HashMap<usize,usize>, //node nth, weight
color : String, //property will be needed when drawing
position : (usize,usize),
disp : (usize, usize),
id : u128,
}
impl Node {
fn new() -> Node{
Node{links : HashMap::new(), color:"black".to_string(),position : (0,0),disp : (0,0),id :0 }
}
fn set_position(&mut self, (x,y):( usize, usize)){
self.position = (x,y);
}
}
impl PartialEq for Node{
fn eq(&self, other: &Self) ->bool{
self.id == other.id
}
}
impl Graph{
fn new() -> Graph{
Graph{adjancy_list : Vec::new(), current : 0}
}
pub fn add_new_node(& mut self){
let mut n = Node::new();
n.id = self.adjancy_list.len();
self.adjancy_list.push(n)
}
/*
connect two node : from -> to with a weight of weight
*/
pub fn connect(&mut self, from : usize, to : usize, weight : usize) -> usize{
if let Some(u) = self.adjancy_list[from].links.insert(to,weight){
return u;
}
0
}
pub fn len(&self) -> usize{
self.adjancy_list.len()
}
}
impl Iterator for Graph{
type Item = Node;
fn next(&mut self)->Option<Node>{
if let Some(n) = self.adjancy_list.get(self.current){
self.current+=1;
return Some(n.clone());
}
None
}
}
}
mod force_field{
use crate::graph::Graph;
pub fn fruchterman_reingold(x : usize, y : usize, graph : &mut Graph){
let area = x * y;
let k = ((area as f64) /(graph.len() as f64) as f64).sqrt();
let step = 100;
let attraction = |dst: usize| -> f64 {
(dst as f64) * (dst as f64) / k
};
let repulsion = |dst: usize| -> f64 {
(k as f64) * (k as f64) / dst as f64
};
for node1 in graph{
for node2 in graph{ //graph is moved in the previous iteration
if node1 != node2{
//compute the distance vector
}
}
}
}
}
How can i iterate over the vertices without consuming the graph ?
I thought about borrowing it mutable, but there is two loops so it won't work because i can't mutably borrow 2 times or ?
What would you change in the code, would you still use iterators or change it to indexes ?
All comments are welcome