Analyze Ground Zero shoreline requirements
This commit is contained in:
@@ -417,7 +417,7 @@ Target deliverable: A small group can join a server, spawn into one biome, gathe
|
||||
- [x] Choose MVP biome based on Ground Zero location.
|
||||
- [~] Create playable test map.
|
||||
- [x] Add terrain base from real elevation data.
|
||||
- [ ] Add first-pass water depth/shoreline handling if applicable.
|
||||
- [x] Add first-pass water depth/shoreline handling if applicable.
|
||||
- [ ] Add first-pass hill, mountain, river, stream, lake, and coastline handling if present in Ground Zero.
|
||||
- [x] Add source metadata record for the MVP tile.
|
||||
- [x] Add generated tile metadata record for the MVP tile.
|
||||
@@ -1402,4 +1402,4 @@ Next version .01 priorities:
|
||||
|
||||
Immediate next item:
|
||||
|
||||
- [ ] Add first-pass water depth/shoreline handling if applicable.
|
||||
- [ ] Add first-pass hill, mountain, river, stream, lake, and coastline handling if present in Ground Zero.
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"tile_id": "gz_us_ca_pacifica_utm10n_e544_n4160",
|
||||
"generated_at_utc": "2026-05-14T12:52:25Z",
|
||||
"source_dem": "Data/Terrain/Extracted/gz_us_ca_pacifica_utm10n_e544_n4160/gz_us_ca_pacifica_utm10n_e544_n4160_1m_dem_subset.tif",
|
||||
"thresholds": {
|
||||
"sea_level_m": 0.0,
|
||||
"shoreline_buffer_m": 2.0,
|
||||
"low_coastal_buffer_m": 5.0
|
||||
},
|
||||
"elevation_summary": {
|
||||
"sample_count": 1000000,
|
||||
"min_elevation_m": 3.1603012084960938,
|
||||
"max_elevation_m": 96.50570678710938,
|
||||
"mean_elevation_m": 18.240529416484833,
|
||||
"sea_level_or_below_samples": 0,
|
||||
"near_sea_level_samples": 0,
|
||||
"low_coastal_samples": 57812,
|
||||
"sea_level_or_below_percent": 0.0,
|
||||
"near_sea_level_percent": 0.0,
|
||||
"low_coastal_percent": 5.7812
|
||||
},
|
||||
"edge_summary": {
|
||||
"north": {
|
||||
"sample_count": 10000,
|
||||
"min_elevation_m": 3.1603012084960938,
|
||||
"max_elevation_m": 37.224822998046875,
|
||||
"mean_elevation_m": 19.415938945102692,
|
||||
"sea_level_or_below_samples": 0,
|
||||
"near_sea_level_samples": 0,
|
||||
"low_coastal_samples": 2710
|
||||
},
|
||||
"south": {
|
||||
"sample_count": 10000,
|
||||
"min_elevation_m": 11.210755348205566,
|
||||
"max_elevation_m": 57.378944396972656,
|
||||
"mean_elevation_m": 19.908063950920106,
|
||||
"sea_level_or_below_samples": 0,
|
||||
"near_sea_level_samples": 0,
|
||||
"low_coastal_samples": 0
|
||||
},
|
||||
"west": {
|
||||
"sample_count": 10000,
|
||||
"min_elevation_m": 3.5281026363372803,
|
||||
"max_elevation_m": 59.69044876098633,
|
||||
"mean_elevation_m": 15.149734993314743,
|
||||
"sea_level_or_below_samples": 0,
|
||||
"near_sea_level_samples": 0,
|
||||
"low_coastal_samples": 2892
|
||||
},
|
||||
"east": {
|
||||
"sample_count": 10000,
|
||||
"min_elevation_m": 24.61846351623535,
|
||||
"max_elevation_m": 96.50570678710938,
|
||||
"mean_elevation_m": 59.40558109054565,
|
||||
"sea_level_or_below_samples": 0,
|
||||
"near_sea_level_samples": 0,
|
||||
"low_coastal_samples": 0
|
||||
}
|
||||
},
|
||||
"classification": {
|
||||
"contains_open_water": false,
|
||||
"contains_shoreline": false,
|
||||
"water_depth_required_for_mvp_tile": false,
|
||||
"shoreline_mesh_required_for_mvp_tile": false,
|
||||
"freshwater_source_required_for_gameplay": true,
|
||||
"recommended_first_pass": "No ocean/shoreline actor required inside the current Ground Zero tile. Add a small freshwater source for gameplay separately, and defer ocean/bathymetry work to west/southwest neighbor coastal tiles."
|
||||
},
|
||||
"notes": [
|
||||
"This analysis uses the extracted 1-meter USGS DEM for the selected 1 km tile.",
|
||||
"The selected Ground Zero tile is coastal-influenced but the DEM minimum is above sea level.",
|
||||
"Ocean depth/bathymetry remains required for adjacent coastal/ocean tiles before multi-tile expansion."
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
# Ground Zero Water And Shoreline Pass
|
||||
|
||||
This pass determines whether the current 1 km Ground Zero MVP tile needs ocean,
|
||||
bathymetry, or shoreline handling inside the playable demo map.
|
||||
|
||||
## Result
|
||||
|
||||
The current Ground Zero tile does not contain ocean water or a shoreline inside
|
||||
its 1 km bounds. First-pass ocean depth and shoreline mesh work is therefore not
|
||||
required for this tile.
|
||||
|
||||
The analysis found no sea-level or near-sea-level samples:
|
||||
|
||||
- Minimum DEM elevation: approximately `3.16 m`
|
||||
- Sea-level or below samples: `0`
|
||||
- Near-sea-level samples at `<= 2.0 m`: `0`
|
||||
- Low coastal samples at `<= 5.0 m`: `57,812` out of `1,000,000`
|
||||
|
||||
The tile is still coastal-influenced, and water remains important for gameplay.
|
||||
For the MVP map, add a small freshwater source separately from ocean handling.
|
||||
Ocean, bathymetry, coastline, and surf/shoreline systems should be handled when
|
||||
the west and southwest neighboring coastal tiles are brought into scope.
|
||||
|
||||
## Source
|
||||
|
||||
- Tile: `gz_us_ca_pacifica_utm10n_e544_n4160`
|
||||
- DEM:
|
||||
`Data/Terrain/Extracted/gz_us_ca_pacifica_utm10n_e544_n4160/gz_us_ca_pacifica_utm10n_e544_n4160_1m_dem_subset.tif`
|
||||
- Analysis output:
|
||||
`Data/Terrain/Analysis/gz_us_ca_pacifica_utm10n_e544_n4160/gz_us_ca_pacifica_utm10n_e544_n4160_water_shoreline_analysis.json`
|
||||
|
||||
## Thresholds
|
||||
|
||||
- Sea level: `0.0 m`
|
||||
- Shoreline buffer: `<= 2.0 m`
|
||||
- Low coastal buffer: `<= 5.0 m`
|
||||
|
||||
## Implementation Decision
|
||||
|
||||
- Do not place an ocean plane in the current Ground Zero tile.
|
||||
- Do not fake bathymetry in the current tile.
|
||||
- Keep NOAA/NCEI bathymetry in the source plan for coastal/ocean neighbor tiles.
|
||||
- Add gameplay water as a freshwater source item or small placed water actor in
|
||||
a later MVP map pass.
|
||||
|
||||
## Follow-Up
|
||||
|
||||
The next terrain/map pass should classify hills, slopes, streams, coastline
|
||||
absence, and other visible landform features from the DEM so resource placement,
|
||||
movement modifiers, and future World Partition stitching can use the same data.
|
||||
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Analyze first-pass water and shoreline applicability for the Ground Zero tile."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
from osgeo import gdal
|
||||
|
||||
gdal.UseExceptions()
|
||||
|
||||
|
||||
PROJECT_ROOT = Path(__file__).resolve().parents[1]
|
||||
TILE_ID = "gz_us_ca_pacifica_utm10n_e544_n4160"
|
||||
DEM_PATH = PROJECT_ROOT / "Data" / "Terrain" / "Extracted" / TILE_ID / f"{TILE_ID}_1m_dem_subset.tif"
|
||||
OUTPUT_DIR = PROJECT_ROOT / "Data" / "Terrain" / "Analysis" / TILE_ID
|
||||
OUTPUT_PATH = OUTPUT_DIR / f"{TILE_ID}_water_shoreline_analysis.json"
|
||||
|
||||
SEA_LEVEL_M = 0.0
|
||||
SHORELINE_BUFFER_M = 2.0
|
||||
LOW_COASTAL_BUFFER_M = 5.0
|
||||
|
||||
|
||||
def summarize_edge(values: np.ndarray) -> dict[str, float | int]:
|
||||
finite = values[np.isfinite(values)]
|
||||
return {
|
||||
"sample_count": int(finite.size),
|
||||
"min_elevation_m": float(np.min(finite)) if finite.size else None,
|
||||
"max_elevation_m": float(np.max(finite)) if finite.size else None,
|
||||
"mean_elevation_m": float(np.mean(finite)) if finite.size else None,
|
||||
"sea_level_or_below_samples": int(np.count_nonzero(finite <= SEA_LEVEL_M)),
|
||||
"near_sea_level_samples": int(np.count_nonzero(finite <= SHORELINE_BUFFER_M)),
|
||||
"low_coastal_samples": int(np.count_nonzero(finite <= LOW_COASTAL_BUFFER_M)),
|
||||
}
|
||||
|
||||
|
||||
def main() -> None:
|
||||
dataset = gdal.Open(str(DEM_PATH), gdal.GA_ReadOnly)
|
||||
if dataset is None:
|
||||
raise RuntimeError(f"Could not open DEM: {DEM_PATH}")
|
||||
|
||||
band = dataset.GetRasterBand(1)
|
||||
data = band.ReadAsArray().astype(float)
|
||||
nodata = band.GetNoDataValue()
|
||||
if nodata is not None:
|
||||
data[data == nodata] = np.nan
|
||||
|
||||
finite = data[np.isfinite(data)]
|
||||
if finite.size == 0:
|
||||
raise RuntimeError(f"DEM has no finite elevation samples: {DEM_PATH}")
|
||||
|
||||
total_samples = int(finite.size)
|
||||
sea_or_below = int(np.count_nonzero(finite <= SEA_LEVEL_M))
|
||||
near_sea = int(np.count_nonzero(finite <= SHORELINE_BUFFER_M))
|
||||
low_coastal = int(np.count_nonzero(finite <= LOW_COASTAL_BUFFER_M))
|
||||
|
||||
edge_width = 10
|
||||
edges = {
|
||||
"north": summarize_edge(data[:edge_width, :].reshape(-1)),
|
||||
"south": summarize_edge(data[-edge_width:, :].reshape(-1)),
|
||||
"west": summarize_edge(data[:, :edge_width].reshape(-1)),
|
||||
"east": summarize_edge(data[:, -edge_width:].reshape(-1)),
|
||||
}
|
||||
|
||||
has_open_water = sea_or_below > 0
|
||||
has_shoreline = near_sea > 0
|
||||
|
||||
result = {
|
||||
"schema_version": 1,
|
||||
"tile_id": TILE_ID,
|
||||
"generated_at_utc": datetime.now(timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z"),
|
||||
"source_dem": str(DEM_PATH.relative_to(PROJECT_ROOT)),
|
||||
"thresholds": {
|
||||
"sea_level_m": SEA_LEVEL_M,
|
||||
"shoreline_buffer_m": SHORELINE_BUFFER_M,
|
||||
"low_coastal_buffer_m": LOW_COASTAL_BUFFER_M,
|
||||
},
|
||||
"elevation_summary": {
|
||||
"sample_count": total_samples,
|
||||
"min_elevation_m": float(np.min(finite)),
|
||||
"max_elevation_m": float(np.max(finite)),
|
||||
"mean_elevation_m": float(np.mean(finite)),
|
||||
"sea_level_or_below_samples": sea_or_below,
|
||||
"near_sea_level_samples": near_sea,
|
||||
"low_coastal_samples": low_coastal,
|
||||
"sea_level_or_below_percent": sea_or_below / total_samples * 100.0,
|
||||
"near_sea_level_percent": near_sea / total_samples * 100.0,
|
||||
"low_coastal_percent": low_coastal / total_samples * 100.0,
|
||||
},
|
||||
"edge_summary": edges,
|
||||
"classification": {
|
||||
"contains_open_water": has_open_water,
|
||||
"contains_shoreline": has_shoreline,
|
||||
"water_depth_required_for_mvp_tile": False,
|
||||
"shoreline_mesh_required_for_mvp_tile": False,
|
||||
"freshwater_source_required_for_gameplay": True,
|
||||
"recommended_first_pass": "No ocean/shoreline actor required inside the current Ground Zero tile. Add a small freshwater source for gameplay separately, and defer ocean/bathymetry work to west/southwest neighbor coastal tiles.",
|
||||
},
|
||||
"notes": [
|
||||
"This analysis uses the extracted 1-meter USGS DEM for the selected 1 km tile.",
|
||||
"The selected Ground Zero tile is coastal-influenced but the DEM minimum is above sea level.",
|
||||
"Ocean depth/bathymetry remains required for adjacent coastal/ocean tiles before multi-tile expansion.",
|
||||
],
|
||||
}
|
||||
|
||||
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
|
||||
OUTPUT_PATH.write_text(json.dumps(result, indent=2) + "\n", encoding="utf-8")
|
||||
print(f"Wrote {OUTPUT_PATH.relative_to(PROJECT_ROOT)}")
|
||||
print(json.dumps(result["classification"], indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user