Skip to main content

symbios_tensor/
lib.rs

1//! Tensor-field-driven procedural urban layout generator.
2//!
3//! This crate generates realistic road networks and building lots on terrain
4//! defined by a [`symbios_ground::HeightMap`]. Roads follow the natural
5//! topography: **major** roads trace elevation contours while **minor** roads
6//! run along the gradient, producing organic street grids that adapt to hills
7//! and valleys. On flat terrain the field falls back to an axis-aligned
8//! Manhattan grid.
9//!
10//! # Pipeline
11//!
12//! 1. **Road generation** — [`generate_roads`] seeds streamlines on a jittered
13//!    grid and traces them through a [`TensorField`] using RK2 integration,
14//!    snapping and splitting edges to form a planar [`RoadGraph`].
15//! 2. **Graph rationalization** — [`rationalize_graph`] rewrites the raw tracer
16//!    output into clean geometry: RDP decimation removes unnecessary points,
17//!    quadratic Bézier fillets smooth sharp bends, and elevation profiles are
18//!    Laplacian-smoothed and grade-clamped. Arteries are traced through
19//!    intersections for global straightening; severed side-streets are
20//!    reconnected.
21//! 3. **Block extraction** — [`extract_blocks`] walks the planar graph with a
22//!    minimum-angle (left-most turn) algorithm, producing closed [`CityBlock`]
23//!    polygons for every bounded interior face.
24//! 4. **Lot subdivision** — [`extract_lots`] recursively splits each block
25//!    perpendicular to its longest edge (through the centroid) until pieces
26//!    are below a configurable area threshold, then computes a street-aligned
27//!    [`BuildingLot`] rectangle with front/side/rear setbacks.
28//! 5. **Terrain carving** — [`carve_roads`] and [`carve_lots`] flatten the
29//!    heightmap under roads and building foundations with smooth embankment
30//!    blending at the edges. Both accept a configurable `blend_radius` that
31//!    controls how far the embankment zone extends — larger values produce
32//!    wider, gentler slopes on steep terrain. `carve_roads` returns a boolean
33//!    road-surface mask so that `carve_lots` can avoid overwriting
34//!    already-flattened pavement. Road elevations use the rationalized
35//!    (smoothed) node heights.
36//! 6. **Road pruning** — [`prune_unused_roads`] optionally removes roads that
37//!    do not serve any building lot, keeping only the minimal connected
38//!    sub-network via Dijkstra-based Steiner tree construction.
39//! 7. **3D mesh generation** — [`generate_road_meshes`] produces engine-agnostic
40//!    [`ProceduralMesh`] vertex buffers for intersection hubs (flat N-gon
41//!    polygons with embankment skirts) and street ribbons (extruded strips
42//!    with flanking skirt meshes).
43//!
44//! # Quick start
45//!
46//! ```ignore
47//! use symbios_ground::HeightMap;
48//! use symbios_tensor::*;
49//!
50//! let heightmap = HeightMap::new(128, 128, 4.0);
51//! let config = TensorConfig::default();
52//!
53//! // 1. Generate road network
54//! let mut graph = generate_roads(&heightmap, &config).expect("invalid config");
55//!
56//! // 2. Rationalize: straighten, fillet, and smooth elevations
57//! rationalize_graph(&mut graph, &heightmap, &RationalizeConfig::default());
58//!
59//! // 3. Extract city blocks
60//! extract_blocks(&mut graph);
61//!
62//! // 4. Subdivide blocks into building lots
63//! let mut hm = heightmap;
64//! let lots = extract_lots(&graph, &mut hm, &LotConfig::default());
65//!
66//! // 5. Carve roads and lots into terrain
67//! let road_mask = carve_roads(&graph, &mut hm, &RoadMeshConfig::default(), 4.0);
68//! carve_lots(&lots, &mut hm, 2.0, Some(&road_mask));
69//!
70//! // 6. (Optional) Prune roads that don't serve any lot
71//! prune_unused_roads(&mut graph, &lots);
72//!
73//! // 7. Generate 3D road meshes
74//! let meshes = generate_road_meshes(&graph, &hm, &RoadMeshConfig::default());
75//! // meshes.hubs    — intersection polygons
76//! // meshes.ribbons — street ribbon strips
77//! // meshes.skirts  — embankment skirt meshes
78//! ```
79
80pub mod carve;
81pub mod geometry;
82pub mod graph;
83pub mod lots;
84pub mod polygons;
85pub mod prune;
86pub mod rationalize;
87pub mod roads_3d;
88pub mod spatial;
89pub mod streaming;
90pub mod tensor;
91pub mod topology;
92pub mod tracer;
93
94pub use carve::{carve_lots, carve_roads};
95pub use graph::{BlockId, CityBlock, EdgeId, NodeId, RoadEdge, RoadGraph, RoadNode, RoadType};
96pub use lots::{BuildingLot, LotConfig, WaterPolicy, extract_lots};
97pub use polygons::{block_centroid, extract_blocks};
98pub use prune::prune_unused_roads;
99pub use rationalize::{RationalizeConfig, rationalize_graph, unify_road_types};
100pub use roads_3d::{ProceduralMesh, RoadMeshConfig, RoadMeshes, SkirtConfig, generate_road_meshes};
101pub use streaming::{CityStreamer, CityStreamerConfig, CityTile};
102pub use tensor::{TensorField, TensorFieldConfig};
103pub use tracer::{GenerationError, GenerationStage, TensorConfig, generate_roads};