Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/data_processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ pub fn generate_world(
waterways::generate_waterways(&mut editor, way);
} else if way.tags.contains_key("bridge") {
//bridges::generate_bridges(&mut editor, way, ground_level); // TODO FIX
} else if way.tags.contains_key("railway") {
} else if way.tags.contains_key("railway") || way.tags.contains_key("subway") {
railways::generate_railways(&mut editor, way);
} else if way.tags.contains_key("aeroway") || way.tags.contains_key("area:aeroway")
{
Expand Down
142 changes: 131 additions & 11 deletions src/element_processing/railways.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,26 @@ use crate::world_editor::WorldEditor;

pub fn generate_railways(editor: &mut WorldEditor, element: &ProcessedWay) {
if let Some(railway_type) = element.tags.get("railway") {
// Check for underground railways (negative level or layer)
let is_underground = element
.tags
.get("level")
.map_or(false, |level| level.parse::<i32>().map_or(false, |l| l < 0))
|| element
.tags
.get("layer")
.map_or(false, |layer| layer.parse::<i32>().map_or(false, |l| l < 0));

// Also check for tunnel=yes tag
let is_tunnel = element
.tags
.get("tunnel")
.map_or(false, |tunnel| tunnel == "yes");

// Skip certain railway types
if [
"proposed",
"abandoned",
"subway",
"construction",
"razed",
"turntable",
Expand All @@ -18,18 +34,13 @@ pub fn generate_railways(editor: &mut WorldEditor, element: &ProcessedWay) {
return;
}

if let Some(subway) = element.tags.get("subway") {
if subway == "yes" {
return;
}
}

if let Some(tunnel) = element.tags.get("tunnel") {
if tunnel == "yes" {
return;
}
// Process as subway if it's a subway, underground by level/layer tag, or a tunnel
if element.tags.get("subway").map_or(false, |v| v == "yes") || is_underground || is_tunnel {
generate_subway(editor, element);
return;
}

// Regular surface railways
for i in 1..element.nodes.len() {
let prev_node = element.nodes[i - 1].xz();
let cur_node = element.nodes[i].xz();
Expand Down Expand Up @@ -69,6 +80,115 @@ pub fn generate_railways(editor: &mut WorldEditor, element: &ProcessedWay) {
}
}

fn generate_subway(editor: &mut WorldEditor, element: &ProcessedWay) {
for i in 1..element.nodes.len() {
let prev_node = element.nodes[i - 1].xz();
let cur_node = element.nodes[i].xz();

let points = bresenham_line(prev_node.x, 0, prev_node.z, cur_node.x, 0, cur_node.z);
let smoothed_points = smooth_diagonal_rails(&points);

for j in 0..smoothed_points.len() {
let (bx, _, bz) = smoothed_points[j];

// Create a 4-block wide floor
for dx in -2..=1 {
for dz in -2..=1 {
editor.set_block(SMOOTH_STONE, bx + dx, -9, bz + dz, None, None);
}
}

// Create a 4-block wide ceiling 3 blocks above the floor
for dx in -2..=1 {
for dz in -2..=1 {
// Add occasional glowstone for lighting
if dx == 0 && dz == 0 && j % 4 == 0 {
editor.set_block(GLOWSTONE, bx, -4, bz, None, None);
} else {
editor.set_block(
SMOOTH_STONE,
bx + dx,
-4,
bz + dz,
None,
Some(&[GLOWSTONE]),
);
}
}
}

// Get previous and next points for direction
let prev = if j > 0 {
Some(smoothed_points[j - 1])
} else {
None
};
let next = if j < smoothed_points.len() - 1 {
Some(smoothed_points[j + 1])
} else {
None
};

let rail_block = determine_rail_direction(
(bx, bz),
prev.map(|(x, _, z)| (x, z)),
next.map(|(x, _, z)| (x, z)),
);

// Place the rail on top of the floor
editor.set_block(rail_block, bx, -8, bz, None, None);

// Helper function to place wall only if block below is not SMOOTH_STONE
let mut place_wall = |x: i32, y: i32, z: i32| {
if !editor.check_for_block(x, y - 1, z, Some(&[SMOOTH_STONE])) {
editor.set_block(POLISHED_ANDESITE, x, y, z, None, None);
editor.set_block(POLISHED_ANDESITE, x, y + 1, z, None, None);
editor.set_block(POLISHED_ANDESITE, x, y + 2, z, None, None);
editor.set_block(POLISHED_ANDESITE, x, y + 3, z, None, None);
editor.set_block(POLISHED_ANDESITE, x, y + 4, z, None, None);
}
};

// Place dirt blocks two blocks away from the rail
// Determine orientation based on rail block
match rail_block {
RAIL_NORTH_SOUTH => {
// For north-south rails, place dirt two blocks east and west
place_wall(bx + 3, -8, bz);
place_wall(bx - 3, -8, bz);
}
RAIL_EAST_WEST => {
// For east-west rails, place dirt two blocks north and south
place_wall(bx, -8, bz + 3);
place_wall(bx, -8, bz - 3);
}
RAIL_NORTH_EAST => {
// For curves, place dirt two blocks away at appropriate positions
place_wall(bx - 3, -8, bz);
place_wall(bx, -8, bz + 3);
}
RAIL_NORTH_WEST => {
place_wall(bx + 3, -8, bz);
place_wall(bx, -8, bz + 3);
}
RAIL_SOUTH_EAST => {
place_wall(bx - 3, -8, bz);
place_wall(bx, -8, bz - 3);
}
RAIL_SOUTH_WEST => {
place_wall(bx + 3, -8, bz);
place_wall(bx, -8, bz - 3);
}
_ => {
// Default for any other rail blocks
place_wall(bx + 3, -8, bz);
place_wall(bx - 3, -8, bz);
}
}
}
}
}

fn smooth_diagonal_rails(points: &[(i32, i32, i32)]) -> Vec<(i32, i32, i32)> {
let mut smoothed = Vec::new();

Expand Down
3 changes: 3 additions & 0 deletions src/retrieve_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ pub fn fetch_data(
nwr["tourism"];
nwr["bridge"];
nwr["railway"];
nwr["subway"="yes"];
nwr["tunnel"="yes"];
nwr["public_transport"="station"];
nwr["barrier"];
nwr["entrance"];
nwr["door"];
Expand Down
Loading