DEV Community

TaroFortune
TaroFortune

Posted on

Building a nationwide flood-risk map for Korea with SRTM DEM + OpenStreetMap

I build ZipScope, a Korean web app that scores the living environment around 38,000+ residential complexes (apartments, officetels, and row/multi-family housing) nationwide. It is deliberately not a real-estate listing site — no prices to chase, no agents. Just analysis: seven living-quality dimensions, commute isochrones, winter sunlight, water-view lines of sight, and the piece I want to walk through here — an estimated flood-risk layer built entirely from open data.

Among free Korean services, flood, sunlight, and view analysis are close to unique. But "estimated" is the operative word, and I will be blunt about where the estimate breaks down. If you are doing anything similar with terrain data, the tradeoffs below are the interesting part.

Why not just use the official flood map?

Korea has an official inundation hazard map at floodmap.go.kr. It is authoritative — and I link to it directly from every result. But it does not exist as a clean, queryable layer for arbitrary points across every one of 38k complexes at the resolution and cadence I wanted. So I built a complementary approximation from two open sources:

  • SRTM 30m DEM — NASA's Shuttle Radar Topography Mission elevation grid.
  • OSM waterways — river and stream geometry pulled from OpenStreetMap via the Overpass API.

The goal is not to replace the official map. It is to give a fast, consistent, nationwide relative signal — "is this complex low and near water, or high and dry?" — with the honest caveat attached.

Extracting rivers from OSM Overpass

The drainage network comes from OSM. An Overpass query for waterway features (rivers, streams, canals) inside a bounding box returns the linework I treat as the local drainage baseline. OSM's water coverage in Korea is good for named rivers and major streams; it thins out for tiny ditches and culverted channels, which matters for the limitations section below.

The practical trick is batching the Overpass calls by region rather than per-complex — you do not want 38,000 separate HTTP round-trips to a shared public endpoint. Pull the waterways for an administrative area once, cache the geometry, and reuse it for every complex inside it.

The core: a HAND approximation

The risk signal is a HAND (Height Above Nearest Drainage) approximation. HAND is a well-known terrain descriptor: for any point, you ask how far above the nearest drainage channel is it, vertically? A house 2 m above the local stream is far more exposed than one 40 m above it, regardless of absolute elevation.

The pipeline, conceptually:

  1. Sample the SRTM DEM at the complex location and along the nearby OSM drainage lines.
  2. Find the nearest drainage segment.
  3. Compute the vertical drop from the complex to that drainage baseline.

Small HAND values (the point sits barely above nearby water) push the risk estimate up; large HAND values push it down. It is a coarse proxy for hydrological connectivity, but on 30 m terrain it captures the first-order intuition that low points near channels flood first.

Slope attenuation

Raw HAND on its own over-flags flat riverside land and under-weights how quickly water actually reaches — or drains away from — a point. So I add a slope-based attenuation term derived from the DEM gradient around the complex.

Steeper local terrain sheds water and attenuates the pooling signal; flatter terrain retains it. Concretely, the slope factor dampens or amplifies the HAND-derived score so that a flat floodplain and a hillside that happen to share the same height-above-drainage do not get scored identically. It is a heuristic weighting, not a hydraulic model — no Manning's equation, no rainfall-runoff simulation.

Batch performance: recomputing the whole country at once

The whole nationwide layer recomputes as a single batch over all 38,000+ complexes — fast enough to rerun on demand rather than as an overnight job. What makes that possible is not clever math — it is avoiding per-point I/O:

  • DEM tiles stay in memory during the batch instead of being re-opened per query.
  • OSM drainage geometry is cached per region, so nearest-drainage lookups are local array math, not network calls.
  • Vectorized sampling — elevation and slope for many points at once rather than a Python loop per complex.

The stack itself is intentionally boring and cheap to host: Flask + React + Leaflet on the front, SQLite for storage, SRTM DEM + OSM Overpass as the geodata sources, all running on PythonAnywhere. No PostGIS cluster, no cloud GIS bill. That constraint — keep it runnable on modest shared hosting — shaped every decision above.

Honest limitations (this is the important part)

I show all of these caveats in the product, next to the number, and I will repeat them here because a flood estimate you trust blindly is worse than none:

  • This is an estimate, not an official inundation map. For decisions that matter, check floodmap.go.kr. ZipScope says so on every result.
  • 30 m DEM is coarse. SRTM resolution smooths out embankments, levees, small berms, and sub-30 m features that decisively change local flood behavior. A protective wall thinner than a pixel is invisible.
  • HAND ignores drainage capacity and rainfall. It is a static terrain descriptor. It knows nothing about storm-sewer sizing, pump stations, tides, dam releases, or how much rain fell. Urban flooding is often a drainage-capacity problem, not a topography problem — and this method cannot see that.
  • OSM waterways are incomplete. Culverted or unmapped channels do not appear, so a point can look "far from drainage" when a buried stream runs right under it.
  • Slope attenuation is a heuristic, tuned by inspection, not calibrated against observed flood events.

Because of all that, I present the output as a relative signal for comparing complexes, always paired with its source and its limits. That honesty is also, frankly, the marketing: every estimate in ZipScope — flood, winter sunlight, view openness — ships with its provenance and its weaknesses stated plainly. In a category full of confident numbers, showing your error bars is the differentiator.

Takeaways if you are building similar

  • HAND + open DEM + OSM waterways gets you a surprisingly useful first-order flood proxy with zero paid data.
  • Batch by region and keep tiles in RAM — that is the difference between a batch that finishes while you wait and one that crawls for minutes.
  • State your limitations louder than your results. A terrain approximation dressed up as ground truth is a liability; the same number, honestly framed, is a genuinely helpful feature.

Live here: https://tarofortune.pythonanywhere.com/analyze/

— austriano

Top comments (0)