Complete hidden node logic + unhide clicked nodes

This commit is contained in:
mars 2022-11-03 18:24:35 -06:00
parent 647b6ec59a
commit 6f0be98a11
1 changed files with 93 additions and 50 deletions

View File

@ -241,7 +241,7 @@ impl Spring {
} else {
displacement += self.margin;
}*/
if displacement.abs() < self.margin {
displacement *= displacement.abs() / self.margin;
}
@ -273,33 +273,57 @@ impl ForceGraph {
self.apply_repulsion();
for node in self.nodes.iter_mut() {
node.body.update(dt);
if !node.info.hidden {
node.body.update(dt);
}
}
}
pub fn with_unhidden<R>(
&self,
from: usize,
to: usize,
f: impl FnOnce(&Node, &Node) -> R,
) -> Option<R> {
let from = &self.nodes[from];
let to = &self.nodes[to];
if from.info.hidden || to.info.hidden {
None
} else {
Some(f(from, to))
}
}
pub fn apply_springs(&mut self) {
for spring in self.springs.iter() {
let from = &self.nodes[spring.from].body;
let to = &self.nodes[spring.to].body;
let delta = to.position - from.position;
let force = spring.hookes_law(delta);
self.nodes[spring.from].body.apply_force(force);
self.nodes[spring.to].body.apply_force(-force);
let force = self.with_unhidden(spring.from, spring.to, |from, to| {
let delta = to.body.position - from.body.position;
spring.hookes_law(delta)
});
if let Some(force) = force {
self.nodes[spring.from].body.apply_force(force);
self.nodes[spring.to].body.apply_force(-force);
}
}
}
pub fn apply_repulsion(&mut self) {
for i in 1..self.nodes.len() {
for j in i..self.nodes.len() {
const REPULSION_CONSTANT: f32 = 50.0;
let from = self.nodes[i - 1].body.position;
let to = self.nodes[j].body.position;
let delta = to - from;
let proximity = delta.length().max(0.1);
let force = -(REPULSION_CONSTANT / (proximity * proximity));
let force = delta * force;
self.nodes[i - 1].body.apply_force(force);
self.nodes[j].body.apply_force(-force);
let force = self.with_unhidden(i - 1, j, |from, to| {
const REPULSION_CONSTANT: f32 = 50.0;
let delta = to.body.position - from.body.position;
let proximity = delta.length().max(0.1);
let force = -(REPULSION_CONSTANT / (proximity * proximity));
delta * force
});
if let Some(force) = force {
self.nodes[i - 1].body.apply_force(force);
self.nodes[j].body.apply_force(-force);
}
}
}
}
@ -311,9 +335,10 @@ impl ForceGraph {
let position = node.body.position;
let children = node.info.unhide.to_owned();
for child in children {
let offset = Vec2::from_angle(child as f32) * 10.0;
let child = &mut self.nodes[child];
child.info.hidden = false;
child.body.position = position;
child.body.position = position + offset;
}
}
@ -324,6 +349,10 @@ impl ForceGraph {
let label_color = Color::WHITE;
for node in self.nodes.iter() {
if node.info.hidden {
continue;
}
ctx.draw_ring(node.body.position, radius, thickness, color);
let offset = node.body.position + node.info.label_offset;
@ -331,42 +360,44 @@ impl ForceGraph {
}
for connection in self.connections.iter() {
let from = self.nodes[connection.from].body.position;
let to = self.nodes[connection.to].body.position;
let delta = to - from;
self.with_unhidden(connection.from, connection.to, |from, to| {
let from = from.body.position;
let to = to.body.position;
let delta = to - from;
if delta.length() < radius * 2.0 {
continue;
}
if delta.length() < radius * 2.0 {
return;
}
let delta_norm = delta.normalize();
let from = from + delta_norm * radius;
let to = to - delta_norm * radius;
let delta_cross = Vec2::new(delta_norm.y, -delta_norm.x);
let delta_side = delta_cross * connection.width / 2.0;
let delta_norm = delta.normalize();
let from = from + delta_norm * radius;
let to = to - delta_norm * radius;
let delta_cross = Vec2::new(delta_norm.y, -delta_norm.x);
let delta_side = delta_cross * connection.width / 2.0;
let vertices = [
MeshVertex {
position: from + delta_side,
color,
},
MeshVertex {
position: from - delta_side,
color,
},
MeshVertex {
position: to + delta_side,
color,
},
MeshVertex {
position: to - delta_side,
color,
},
];
let vertices = [
MeshVertex {
position: from + delta_side,
color,
},
MeshVertex {
position: from - delta_side,
color,
},
MeshVertex {
position: to + delta_side,
color,
},
MeshVertex {
position: to - delta_side,
color,
},
];
let indices = [0, 1, 2, 1, 2, 3];
let indices = [0, 1, 2, 1, 2, 3];
ctx.draw_indexed(&vertices, &indices);
ctx.draw_indexed(&vertices, &indices);
});
}
}
}
@ -406,7 +437,19 @@ impl PanelImpl for ForceDirectedGraphPanel {
self.size = new_size;
}
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) {}
fn on_cursor_event(&mut self, kind: CursorEventKind, at: Vec2) {
let at = at - self.size / 2.0;
if let CursorEventKind::Deselect = kind {
let node = self
.graph
.nodes
.iter()
.position(|node| !node.info.hidden && node.body.position.distance(at) < 6.0);
if let Some(node) = node {
self.graph.unhide(node);
}
}
}
fn on_message(&mut self, msg: Message) {}
}