use crate::{edge::*, layout::*, node::*, util::*};
use num_traits::Zero;
pub(crate) fn apply_attraction<
T: Coord,
const N: usize,
E: Edges<T, Id>,
O: Nodes<T, N, Id>,
Id,
>(
layout: &mut Layout<T, N, E, O, Id>,
) {
for ((n1, n2), weight) in layout.edges.iter_edges() {
let (n1, n2) = layout.nodes.get_2_mut(n1, n2);
let f = (n2.pos - n1.pos) * layout.settings.ka * weight;
n1.speed += f;
n2.speed -= f;
}
}
pub(crate) fn apply_attraction_log<
T: Coord,
const N: usize,
E: Edges<T, Id>,
O: Nodes<T, N, Id>,
Id,
>(
layout: &mut Layout<T, N, E, O, Id>,
) {
for ((n1, n2), weight) in layout.edges.iter_edges() {
let (n1, n2) = layout.nodes.get_2_mut(n1, n2);
let mut d = T::zero();
let mut dv = VecN::<T, N>::zero();
for ((n1_pos, n2_pos), dvi) in n1.pos.iter().zip(n2.pos.iter()).zip(dv.iter_mut()) {
*dvi = *n2_pos - *n1_pos;
d += *dvi * *dvi;
}
if d.is_zero() {
continue;
}
d = d.sqrt();
let f = dv * (d.ln_1p() / d * layout.settings.ka * weight);
n1.speed += f;
n2.speed -= f;
}
}
pub(crate) fn apply_attraction_po<
T: Coord,
const N: usize,
E: Edges<T, Id>,
O: Nodes<T, N, Id>,
Id,
>(
layout: &mut Layout<T, N, E, O, Id>,
) {
for ((n1, n2), weight) in layout.edges.iter_edges() {
let (n1, n2) = layout.nodes.get_2_mut(n1, n2);
let mut d = T::zero();
let mut dv = VecN::<T, N>::zero();
for ((n1_pos, n2_pos), dvi) in n1.pos.iter().zip(n2.pos.iter()).zip(dv.iter_mut()) {
*dvi = *n2_pos - *n1_pos;
d += *dvi * *dvi;
}
d = d.sqrt();
let dprime = d - n1.size - n2.size;
if !dprime.is_positive() {
continue;
}
let f = dv * (dprime / d * layout.settings.ka * weight);
n1.speed += f;
n2.speed -= f;
}
}
pub(crate) fn apply_attraction_log_po<
T: Coord,
const N: usize,
E: Edges<T, Id>,
O: Nodes<T, N, Id>,
Id,
>(
layout: &mut Layout<T, N, E, O, Id>,
) {
for ((n1, n2), weight) in layout.edges.iter_edges() {
let (n1, n2) = layout.nodes.get_2_mut(n1, n2);
let mut d = T::zero();
let mut dv = VecN::<T, N>::zero();
for ((n1_pos, n2_pos), dvi) in n1.pos.iter().zip(n2.pos.iter()).zip(dv.iter_mut()) {
*dvi = *n2_pos - *n1_pos;
d += *dvi * *dvi;
}
d = d.sqrt();
let dprime = d - n1.size - n2.size;
if !dprime.is_positive() {
continue;
}
let f = dv * (dprime.ln_1p() / d * layout.settings.ka * weight);
n1.speed += f;
n2.speed -= f;
}
}