pub enum Value {
Number(f32, RangeInclusive<f32>),
Bool(bool),
}
Expand description
A value that you can change in a Force
’s dictionary.
Variants§
Implementations§
source§impl Value
impl Value
sourcepub const fn bool(&self) -> Option<bool>
pub const fn bool(&self) -> Option<bool>
Retrieves the bool from a value.
Examples found in repository?
src/force/mod.rs (line 166)
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
fn update<N, E, Ty: EdgeType>(
dict: &LinkedHashMap<String, Value>,
graph: &mut ForceGraph<N, E, Ty>,
_dt: f32,
) {
let distance = dict.get("Distance").unwrap().number().unwrap();
for node in graph.node_weights_mut() {
if dict.get("Up").unwrap().bool().unwrap() {
node.location.y -= distance;
}
if dict.get("Down").unwrap().bool().unwrap() {
node.location.y += distance;
}
if dict.get("Left").unwrap().bool().unwrap() {
node.location.x -= distance;
}
if dict.get("Right").unwrap().bool().unwrap() {
node.location.x += distance;
}
}
}
More examples
src/force/handy.rs (line 28)
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
fn update<N, E, Ty: EdgeType>(
dict: &LinkedHashMap<String, Value>,
graph: &mut ForceGraph<N, E, Ty>,
dt: f32,
) {
// establish current variables from the force's dictionary
let repulsion = dict.get("Repulsive Force").unwrap().bool().unwrap();
let attraction = dict.get("Attractive Force").unwrap().bool().unwrap();
let scale = dict.get("Scale").unwrap().number().unwrap();
let cooloff_factor = dict.get("Cooloff Factor").unwrap().number().unwrap();
let gravity_factor = dict.get("Gravity Factor").unwrap().number().unwrap();
let centering = dict.get("Centering").unwrap().bool().unwrap();
let gravity = dict.get("Gravity").unwrap().bool().unwrap();
// sum of all locations (for centering)
let mut loc_sum = Vec3::ZERO;
// reset all old locations
graph
.node_weights_mut()
.for_each(|n| n.old_location = n.location);
// loop through all nodes
for idx in graph.node_indices().collect::<Vec<NodeIndex>>() {
if centering {
loc_sum += graph[idx].old_location
}
// force that will be applied to the node
let mut force = Vec3::ZERO;
if repulsion {
force += fr_get_repulsion(idx, scale, &graph);
}
if attraction {
force += fr_get_attraction(idx, scale, &graph);
}
if gravity {
let node = &graph[idx];
force += -node.old_location / (1.0 / gravity_factor);
}
// apply new location
let node = &mut graph[idx];
node.velocity += force * dt;
node.velocity *= cooloff_factor;
node.location += node.velocity * dt;
}
if centering {
let avg_vec = loc_sum / graph.node_count() as f32;
for idx in graph.node_indices().collect::<Vec<NodeIndex>>() {
let node = &mut graph[idx];
node.location -= avg_vec;
}
}
}
sourcepub const fn number(&self) -> Option<f32>
pub const fn number(&self) -> Option<f32>
Retrieves the number from a value. If you mess up and call it on a bool it will return 0.0.
Examples found in repository?
src/force/mod.rs (line 128)
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
fn update<N, E, Ty: EdgeType>(
dict: &LinkedHashMap<String, Value>,
graph: &mut ForceGraph<N, E, Ty>,
_dt: f32,
) {
let scale = dict.get("Scale Factor").unwrap().number().unwrap();
let center = Iterator::sum::<Vec3>(
graph
.node_weights()
.map(|x| x.location)
.collect::<Vec<Vec3>>()
.iter(),
) / graph.node_count() as f32;
for node in graph.node_weights_mut() {
node.location = ((node.location - center) * scale) + center;
}
}
let mut dict = LinkedHashMap::new();
dict.insert("Scale Factor".to_string(), Value::Number(1.5, 0.1..=2.0));
Force {
dict: dict.clone(),
dict_default: dict,
name: "Scale",
continuous: false,
info: Some("Scales the graph around its center."),
update,
}
}
/// A force for translating the graph in any direction.
pub fn translate<N, E, Ty: EdgeType>() -> Force<N, E, Ty> {
fn update<N, E, Ty: EdgeType>(
dict: &LinkedHashMap<String, Value>,
graph: &mut ForceGraph<N, E, Ty>,
_dt: f32,
) {
let distance = dict.get("Distance").unwrap().number().unwrap();
for node in graph.node_weights_mut() {
if dict.get("Up").unwrap().bool().unwrap() {
node.location.y -= distance;
}
if dict.get("Down").unwrap().bool().unwrap() {
node.location.y += distance;
}
if dict.get("Left").unwrap().bool().unwrap() {
node.location.x -= distance;
}
if dict.get("Right").unwrap().bool().unwrap() {
node.location.x += distance;
}
}
}
More examples
src/force/fruchterman_reingold.rs (line 20)
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
fn update<N, E, Ty: EdgeType>(
dict: &LinkedHashMap<String, Value>,
graph: &mut ForceGraph<N, E, Ty>,
dt: f32,
) {
// establish current variables from the force's dictionary
let scale = dict.get("Scale").unwrap().number().unwrap();
let cooloff_factor = dict.get("Cooloff Factor").unwrap().number().unwrap();
// reset all old locations
graph
.node_weights_mut()
.for_each(|n| n.old_location = n.location);
// loop through all nodes
for idx in graph.node_indices().collect::<Vec<NodeIndex>>() {
// force that will be applied to the node
let mut force = Vec3::ZERO;
force += fr_get_repulsion(idx, scale, &graph);
force += fr_get_attraction(idx, scale, &graph);
// apply new location
let node = &mut graph[idx];
node.velocity += force * dt;
node.velocity *= cooloff_factor;
node.location += node.velocity * dt;
}
}
let mut dict = LinkedHashMap::new();
dict.insert("Scale".to_string(), Value::Number(scale, 1.0..=200.0));
dict.insert(
"Cooloff Factor".to_string(),
Value::Number(cooloff_factor, 0.0..=1.0),
);
Force {
dict: dict.clone(),
dict_default: dict,
name: "Fruchterman-Reingold (1991)",
continuous: true,
info: Some("The force-directed graph drawing algorithm by Fruchterman-Reingold (1991)."),
update,
}
}
/// A force directed graph drawing algorithm based on Fruchterman-Reingold (1991), though it multiplies attractions by edge weights.
pub fn fruchterman_reingold_weighted<N, E: Clone + Into<f32>, Ty: EdgeType>(
scale: f32,
cooloff_factor: f32,
) -> Force<N, E, Ty> {
fn update<N, E: Clone + Into<f32>, Ty: EdgeType>(
dict: &LinkedHashMap<String, Value>,
graph: &mut ForceGraph<N, E, Ty>,
dt: f32,
) {
// establish current variables from the force's dictionary
let scale = dict.get("Scale").unwrap().number().unwrap();
let cooloff_factor = dict.get("Cooloff Factor").unwrap().number().unwrap();
// reset all old locations
graph
.node_weights_mut()
.for_each(|n| n.old_location = n.location);
// loop through all nodes
for idx in graph.node_indices().collect::<Vec<NodeIndex>>() {
// force that will be applied to the node
let mut force = Vec3::ZERO;
force += fr_get_repulsion(idx, scale, &graph);
force += fr_get_attraction_weighted(idx, scale, &graph);
// apply new location
let node = &mut graph[idx];
node.velocity += force * dt;
node.velocity *= cooloff_factor;
node.location += node.velocity * dt;
}
}
src/force/handy.rs (line 30)
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
fn update<N, E, Ty: EdgeType>(
dict: &LinkedHashMap<String, Value>,
graph: &mut ForceGraph<N, E, Ty>,
dt: f32,
) {
// establish current variables from the force's dictionary
let repulsion = dict.get("Repulsive Force").unwrap().bool().unwrap();
let attraction = dict.get("Attractive Force").unwrap().bool().unwrap();
let scale = dict.get("Scale").unwrap().number().unwrap();
let cooloff_factor = dict.get("Cooloff Factor").unwrap().number().unwrap();
let gravity_factor = dict.get("Gravity Factor").unwrap().number().unwrap();
let centering = dict.get("Centering").unwrap().bool().unwrap();
let gravity = dict.get("Gravity").unwrap().bool().unwrap();
// sum of all locations (for centering)
let mut loc_sum = Vec3::ZERO;
// reset all old locations
graph
.node_weights_mut()
.for_each(|n| n.old_location = n.location);
// loop through all nodes
for idx in graph.node_indices().collect::<Vec<NodeIndex>>() {
if centering {
loc_sum += graph[idx].old_location
}
// force that will be applied to the node
let mut force = Vec3::ZERO;
if repulsion {
force += fr_get_repulsion(idx, scale, &graph);
}
if attraction {
force += fr_get_attraction(idx, scale, &graph);
}
if gravity {
let node = &graph[idx];
force += -node.old_location / (1.0 / gravity_factor);
}
// apply new location
let node = &mut graph[idx];
node.velocity += force * dt;
node.velocity *= cooloff_factor;
node.location += node.velocity * dt;
}
if centering {
let avg_vec = loc_sum / graph.node_count() as f32;
for idx in graph.node_indices().collect::<Vec<NodeIndex>>() {
let node = &mut graph[idx];
node.location -= avg_vec;
}
}
}
sourcepub fn number_mut(&mut self) -> Option<&mut f32>
pub fn number_mut(&mut self) -> Option<&mut f32>
Same as number but returns a mutable version.