From 2a3064b0fed0cdbdf67c3f32dbe0c6fec4d50115 Mon Sep 17 00:00:00 2001 From: Marto Date: Fri, 1 May 2026 14:46:30 +0200 Subject: [PATCH] Improvement to intersection data calculation --- src/common/utils.zig | 9 +++++ src/infrastructure/node.zig | 9 +++++ src/infrastructure/road.zig | 2 +- src/infrastructure/road_manager.zig | 2 +- src/simulator.zig | 59 ++++++++++++++++++++++++----- 5 files changed, 70 insertions(+), 11 deletions(-) diff --git a/src/common/utils.zig b/src/common/utils.zig index eac874a..12acd8e 100644 --- a/src/common/utils.zig +++ b/src/common/utils.zig @@ -21,4 +21,13 @@ pub fn compareIntersections(ctx: *const Node, inter_a: st.IntersectionData, inte const distance_b = ctx.getRelativeInterDistance(inter_b); return distance_a < distance_b; +} + +// felt cute, might delete it later idk +pub fn listContains(comptime T: type, element: *T, list: *[]*T) bool { + for (0..list.len) |i| { + if (list[i] == element) return true; + } + + return false; } \ No newline at end of file diff --git a/src/infrastructure/node.zig b/src/infrastructure/node.zig index a26f78c..7130840 100644 --- a/src/infrastructure/node.zig +++ b/src/infrastructure/node.zig @@ -83,6 +83,15 @@ pub const Node = struct { pub fn getRelativeInterDistance(self: *const Node, intersection: st.IntersectionData) f32 { return ut.calculate_length(intersection.pos, self.pos); } + + /// Searches for the road pointer within roads list + pub fn roadsContains(self: *const Node, road_to_search: *const Road) bool { + for (self.roads.items) |road| { + if (road == road_to_search) return true; + } + + return false; + } }; // TODO tests diff --git a/src/infrastructure/road.zig b/src/infrastructure/road.zig index 9969b98..0220eca 100644 --- a/src/infrastructure/road.zig +++ b/src/infrastructure/road.zig @@ -60,7 +60,7 @@ pub const Road = struct { } /// Checks whether pos coordinate is on the referenced road - pub fn isHighlighted(self: *const Road, pos: rl.Vector2) bool { + pub fn collides(self: *const Road, pos: rl.Vector2) bool { return rl.checkCollisionPointLine(pos, self.nodes[0].pos, self.nodes[1].pos, c.ROAD_SIZE); } }; diff --git a/src/infrastructure/road_manager.zig b/src/infrastructure/road_manager.zig index 026b1e8..9ba88c3 100644 --- a/src/infrastructure/road_manager.zig +++ b/src/infrastructure/road_manager.zig @@ -89,7 +89,7 @@ pub const RoadManager = struct { /// Returns if pos is pointing at a road, or null if it isn't at any pub fn getHighlightedRoad(self: *const RoadManager, pos: Vector2) ?*Road { for (self.roads.items) |road| { - if (road.isHighlighted(pos)) return road; + if (road.collides(pos)) return road; } return null; diff --git a/src/simulator.zig b/src/simulator.zig index 5c556ac..631637a 100644 --- a/src/simulator.zig +++ b/src/simulator.zig @@ -156,6 +156,8 @@ pub const Simulator = struct { const intersections = self.getIntersectingRoads(self.allocator, temp, cur_node) catch |err| { std.debug.panic("Intersection selection failure: {}\n", .{err}); }; + defer self.allocator.free(intersections); + // DEBUG TODO REMOVE std.debug.print("Displaying intersection position and the intersected road:\n", .{}); for (0..intersections.len) |i| { @@ -163,7 +165,6 @@ pub const Simulator = struct { std.debug.print("Road ID={d} Pos: ({d}, {d})\n", .{int.road.id, int.pos.x, int.pos.y}); } - self.node_man.temp_node = if (self.auto_continue) cur_node else null; return; } @@ -217,8 +218,32 @@ pub const Simulator = struct { var intersections: std.ArrayList(st.IntersectionData) = .empty; var collision_point: rl.Vector2 = undefined; + var start_node_collision: ?*Road = null; + var end_node_collision: ?*Road = null; + + // Here we will check if any road collides with start and end node + for (self.road_man.roads.items) |road| { + if (start_node_collision == null and road.collides(start.pos) and !start.roadsContains(road)) + start_node_collision = road; + if (end_node_collision == null and road.collides(end.pos) and !end.roadsContains(road)) + end_node_collision = road; + + if (start_node_collision != null and end_node_collision != null) break; + } + + // if road node is placed on the road it is added as a collision with said road + if (start_node_collision) |road| { + try intersections.append(self.allocator, .{ + .road = road, + .pos = start.pos, + }); + } + outer: for (self.road_man.roads.items) |road| { - if (!rl.checkCollisionLines(start.pos, end.pos, road.nodes[0].pos, road.nodes[1].pos, &collision_point)) + if (!rl.checkCollisionLines( + start.pos,end.pos, + road.nodes[0].pos, road.nodes[1].pos, + &collision_point)) continue; const intersection = st.IntersectionData { @@ -226,7 +251,8 @@ pub const Simulator = struct { .pos = collision_point, }; - // We put a 0 here, just to satisfy the constructor function + // We put a 0 here, just to satisfy the constructor function, + // it is not getting appended to the node list anyways const node: Node = .init(0, intersection.pos); // If the newly acquired intersection node is within the snapping radius of already existing nodes, // we don't add it to the list @@ -236,22 +262,37 @@ pub const Simulator = struct { // If there is an existing node that covers our position within its snapping radius, // then such position will not be saved as intersection - if (self.node_man.getNodeIfExists(node.pos) != null) continue :outer; + if (self.node_man.getNodeIfExists(node.pos) != null) continue; try intersections.append(allocator, intersection); } + // if end node is placed on the road it is added as a collision with said road + if (end_node_collision) |road| { + try intersections.append(self.allocator, .{ + .road = road, + .pos = end.pos, + }); + } + const sorted_intersection = try intersections.toOwnedSlice(allocator); std.sort.block(st.IntersectionData, sorted_intersection, start, ut.compareIntersections); return sorted_intersection; } - fn splitRoadsByIntersections(self: *Simulator, intersections: st.IntersectionData, start: *Node, end: *Node) void { - _ = intersections; // autofix - _ = end; // autofix - _ = start; // autofix - _ = self; // autofix + fn splitRoadsByIntersections(self: *Simulator, intersections: []st.IntersectionData, start: *Node, end: *Node) void { + if (intersections.len == 0) { + self.road_man.addRoad(self.allocator, start, end) catch |err| { + std.debug.panic("Failed to create a road connecting the origin nodes: {}\n", .{err}); + }; + return; + } + + for (0..intersections.len) |i| { + _ = i; // autofix + + } } }; \ No newline at end of file