summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2024-11-08 04:42:01 +0100
committerMitya Selivanov <automainint@guattari.tech>2024-11-08 04:42:01 +0100
commit23fe91bc8d13c5b1237bffa4293ec0e869378ed2 (patch)
tree2cf999dc03086f2e5cd51a4934b23725c4d5d52a
parentaaa61a3eeb5b1ade783b5a7ec31a6a7fd6b3393e (diff)
downloadreduced_system_layer-23fe91bc8d13c5b1237bffa4293ec0e869378ed2.zip
Update graph example
-rwxr-xr-xexamples/graph.c121
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