diff options
author | Mitya Selivanov <automainint@guattari.tech> | 2024-11-08 04:42:01 +0100 |
---|---|---|
committer | Mitya Selivanov <automainint@guattari.tech> | 2024-11-08 04:42:01 +0100 |
commit | 23fe91bc8d13c5b1237bffa4293ec0e869378ed2 (patch) | |
tree | 2cf999dc03086f2e5cd51a4934b23725c4d5d52a | |
parent | aaa61a3eeb5b1ade783b5a7ec31a6a7fd6b3393e (diff) | |
download | reduced_system_layer-23fe91bc8d13c5b1237bffa4293ec0e869378ed2.zip |
Update graph example
-rwxr-xr-x | examples/graph.c | 121 |
1 files changed, 89 insertions, 32 deletions
diff --git a/examples/graph.c b/examples/graph.c index 36c110f..a224a5b 100755 --- a/examples/graph.c +++ b/examples/graph.c @@ -180,7 +180,22 @@ void remove_node(i64 node_index) { world.nodes[node_index].enabled = 0; } +f64 distance_between(f64 x0, f64 y0, f64 x1, f64 y1) { + f64 dx = x1 - x0; + f64 dy = y1 - y0; + + return sqrt(dx * dx + dy * dy); +} + void add_node(f64 x, f64 y) { + f64 radius = 50; + + for (i64 i = 0; i < MAX_NUM_NODES; ++i) { + Node n = world.nodes[i]; + if (n.enabled && distance_between(n.x, n.y, x, y) < radius + n.radius) + return; + } + i64 node_index = 0; while (node_index < MAX_NUM_NODES && world.nodes[node_index].enabled) @@ -192,7 +207,7 @@ void add_node(f64 x, f64 y) { .enabled = 1, .x = x, .y = y, - .radius = 50, + .radius = radius, }; } @@ -203,9 +218,12 @@ void add_edge(i64 src, i64 dst) { if (src == dst) return; - for (i64 i = 0; i < MAX_NUM_EDGES; ++i) - if (world.edges[i].enabled && world.edges[i].src == src && world.edges[i].dst == dst) - return; + for (i64 i = 0; i < MAX_NUM_EDGES; ++i) { + Edge e = world.edges[i]; + if (!e.enabled) continue; + if (e.src == src && e.dst == dst) return; + if (e.dst == src && e.src == dst) return; + } i64 edge_index = 0; @@ -222,17 +240,7 @@ void add_edge(i64 src, i64 dst) { }; } -f64 distance_between(f64 x0, f64 y0, f64 x1, f64 y1) { - f64 dx = x1 - x0; - f64 dy = y1 - y0; - - return sqrt(dx * dx + dy * dy); -} - void highlight_path(i64 src, i64 dst) { - if (!check_node_index(src)) return; - if (!check_node_index(dst)) return; - for (i64 i = 0; i < MAX_NUM_NODES; ++i) { world.nodes[i].highlight = 0; world.nodes[i].distance = -1; @@ -241,6 +249,9 @@ void highlight_path(i64 src, i64 dst) { for (i64 i = 0; i < MAX_NUM_EDGES; ++i) world.edges[i].highlight = 0; + if (!check_node_index(src)) return; + if (!check_node_index(dst)) return; + world.nodes[src].highlight = 1; world.nodes[dst].highlight = 1; @@ -290,11 +301,8 @@ void highlight_path(i64 src, i64 dst) { world.nodes[min_index].distance = min_distance; - // Repeat until we got the destination node + // Repeat until there's no connected nodes left // - - if (min_index == dst) - break; } // If path not found, stop @@ -308,14 +316,13 @@ void highlight_path(i64 src, i64 dst) { // Reconstruct the path // - f64 min_distance = world.nodes[dst].distance; - for (i64 node_index = dst; node_index != src;) { // Repeat until we got the source node // Find neighbor node with minimal path distance // + f64 min_distance = -1; i64 min_node_index = -1; i64 min_edge_index = -1; @@ -325,19 +332,23 @@ void highlight_path(i64 src, i64 dst) { Node n0 = world.nodes[e.src]; Node n1 = world.nodes[e.dst]; + f64 l = distance_between(n0.x, n0.y, n1.x, n1.y); + // Assume bi-directional graph - if (e.src == node_index && n1.distance >= 0 && n1.distance < min_distance) { - min_node_index = e.dst; - min_edge_index = i; - min_distance = n1.distance; - } + if (e.src == node_index && n1.distance >= 0) + if (min_distance < 0 || l + n1.distance < min_distance) { + min_node_index = e.dst; + min_edge_index = i; + min_distance = l + n1.distance; + } - if (e.dst == node_index && n0.distance >= 0 && n0.distance < min_distance) { - min_node_index = e.src; - min_edge_index = i; - min_distance = n0.distance; - } + if (e.dst == node_index && n0.distance >= 0) + if (min_distance < 0 || l + n0.distance < min_distance) { + min_node_index = e.src; + min_edge_index = i; + min_distance = l + n0.distance; + } } // If not found, stop @@ -369,6 +380,11 @@ b8 path_changed = 0; i64 path_src = -1; i64 path_dst = -1; +b8 drag_on = 0; +i64 drag_node = -1; +i64 drag_x0 = 0; +i64 drag_y0 = 0; + void update_and_render_frame(void) { p_wait_events(); @@ -399,6 +415,8 @@ void update_and_render_frame(void) { for (i64 i = 0; i < MAX_NUM_NODES; ++i) if (world.nodes[i].enabled && world.nodes[i].hover) remove_node(i); + + path_changed = 1; } if (platform.key_pressed['1']) { @@ -423,8 +441,19 @@ void update_and_render_frame(void) { path_changed = 0; } - if (platform.key_pressed[BUTTON_LEFT]) - add_node(platform.cursor_x, platform.cursor_y); + if (platform.key_pressed[BUTTON_LEFT]) { + for (i64 i = 0; i < MAX_NUM_NODES; ++i) + if (world.nodes[i].enabled && world.nodes[i].hover) { + drag_on = 1; + drag_node = i; + drag_x0 = world.nodes[i].x - platform.cursor_x; + drag_y0 = world.nodes[i].y - platform.cursor_y; + break; + } + + if (!drag_on) + add_node(platform.cursor_x, platform.cursor_y); + } if (platform.key_pressed[BUTTON_RIGHT]) for (i64 i = 0; i < MAX_NUM_NODES; ++i) @@ -445,6 +474,34 @@ void update_and_render_frame(void) { if (adding_edge && !platform.key_down[BUTTON_RIGHT]) { adding_edge = 0; add_edge(adding_src, adding_dst); + path_changed = 1; + } + + if (drag_on) { + if (check_node_index(drag_node)) { + f64 r = world.nodes[drag_node].radius; + f64 x = drag_x0 + platform.cursor_x; + f64 y = drag_y0 + platform.cursor_y; + + b8 collision = 0; + + for (i64 i = 0; i < MAX_NUM_NODES; ++i) { + Node n = world.nodes[i]; + if (i != drag_node && n.enabled && distance_between(n.x, n.y, x, y) < n.radius + r) { + collision = 1; + break; + } + } + + if (!collision) { + world.nodes[drag_node].x = x; + world.nodes[drag_node].y = y; + path_changed = 1; + } + } + + if (!platform.key_down[BUTTON_LEFT]) + drag_on = 0; } // Render |