use forceatlas2::*;
use rand::SeedableRng;
use std::io::BufRead;
const DEFAULT_N: usize = 2;
const DEFAULT_ITERATIONS: usize = 10000;
fn main() {
let mut args = std::env::args().skip(1);
let filename = args.next().expect(&format!(
"Usage: csv_import <csv_file> [N (default={})] [iterations (default={})]",
DEFAULT_N, DEFAULT_ITERATIONS
));
let dim = args
.next()
.map_or(DEFAULT_N, |arg| arg.parse().expect("Invalid argument N"));
assert!(dim == 2 || dim == 3, "N must be 2 or 3");
let iterations = args.next().map_or(DEFAULT_ITERATIONS, |arg| {
arg.parse().expect("Invalid argument iterations")
});
let file = std::fs::File::open(filename).expect("Cannot open file");
let mut nodes = Vec::new();
let mut edges = Vec::<((usize, usize), f32)>::new();
for (i, line) in std::io::BufReader::new(file).lines().enumerate() {
let line = line.expect("Error reading CSV");
let mut columns = line.split(&[' ', '\t', ',', ';'][..]);
if let (Some(n1), Some(n2)) = (columns.next(), columns.skip_while(|&c| c.is_empty()).next())
{
if let (Ok(n1), Ok(n2)) = (n1.parse::<usize>(), n2.parse::<usize>()) {
if n1 >= nodes.len() || n2 >= nodes.len() {
nodes.extend((nodes.len()..=n1.max(n2)).map(|_| AbstractNode::default()));
}
if n1 != n2 {
edges.push((if n1 < n2 { (n1, n2) } else { (n2, n1) }, 1.0));
nodes[n1].mass += 1.0;
nodes[n2].mass += 1.0;
}
} else {
eprintln!("Ignored line {} has bad number format", i);
}
} else {
eprintln!("Ignored line {} has <2 columns", i);
}
}
eprintln!("Nodes: {}", nodes.len());
let mut rng = rand::prelude::SmallRng::seed_from_u64(42);
match dim {
2 => {
let mut layout = Layout::<f32, 2>::from_abstract(
Settings {
theta: 0.5,
ka: 0.01,
kg: 0.001,
kr: 0.002,
lin_log: false,
speed: 1.0,
prevent_overlapping: None,
strong_gravity: false,
},
nodes.into_iter().enumerate(),
edges,
&mut rng,
);
let start = std::time::Instant::now();
for _i in 0..iterations {
layout.iteration();
}
let duration = start.elapsed();
for node in layout.nodes {
println!("{}\t{}", node.pos[0], node.pos[1]);
}
println!("Duration: {} ms", duration.as_millis());
}
3 => {
let mut layout = Layout::<f32, 3>::from_abstract(
Settings {
theta: 0.5,
ka: 0.01,
kg: 0.001,
kr: 0.002,
lin_log: false,
speed: 1.0,
prevent_overlapping: None,
strong_gravity: false,
},
nodes.into_iter().enumerate(),
edges,
&mut rng,
);
let start = std::time::Instant::now();
for _i in 0..iterations {
layout.iteration();
}
let duration = start.elapsed();
for node in layout.nodes {
println!("{}\t{}\t{}", node.pos[0], node.pos[1], node.pos[2]);
}
println!("Duration: {} ms", duration.as_millis());
}
_ => unreachable!(),
}
}