use crate::graph::Node;
use crate::{AnnotationGraph, Measurement, Variable};
use forceatlas2::Layout;
fn layout<'graph>(
annotations: &'graph AnnotationGraph,
) -> impl Iterator<Item = (&'graph Node<'graph>, forceatlas2::Node<f64, 2>)> {
let edges = annotations
.edges()
.map(|(source, target)| (source.index(), target.index()))
.map(|(source, target)| (source.index(), target.index()))
.map(|edge| (edge, 1.0))
.collect();
let sizes = annotations.edges().map(|(source, _target)| {
annotations.variable(source, Variable::UnitDuration, Measurement::Exact)
});
let mut layout =
Layout::from_graph_with_degree_mass(edges, sizes, forceatlas2::Settings::default());
for _step in 0..1_000 {
layout.iteration();
}
annotations.packages().zip(layout.nodes.into_iter())
}
pub fn data(annotations: &AnnotationGraph) -> charming::series::GraphData {
let categories = vec![charming::series::GraphCategory {
name: String::from("default"),
}];
let layout = layout(annotations);
let nodes = layout
.map(|(graph_node, layout_node)| {
let unit_time =
annotations.variable(graph_node, Variable::UnitDuration, Measurement::Exact);
charming::series::GraphNode {
id: graph_node.id().repr.clone(),
name: graph_node.name().to_string(),
x: layout_node.pos.x(),
y: layout_node.pos.y(),
value: unit_time,
category: 0,
symbol_size: unit_time,
label: None,
}
})
.collect();
let links = annotations
.edges()
.map(|(source, target)| charming::series::GraphLink {
source: source.id().repr.to_string(),
target: target.id().repr.to_string(),
value: None,
})
.collect();
charming::series::GraphData {
nodes,
links,
categories,
}
}