{"slug":"terrain-hydrology","title":"terrain-hydrology","summary":"Always invoke for terrain, drainage, viewshed, or visibility analysis from elevation, even before the DEM or correct surface is chosen. Covers DTM-versus-DSM selection, slope, aspect, curvature, hillshade, conditioning, flow direction/accumulation, streams, watersheds, and catchm","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-09-18T14:08:04.678715Z","repo":{"url":"https://github.com/muend/geoai-skills","stars":27,"forks":3,"license":"MIT","updatedAt":"2026-09-03T23:49:19Z"},"bodyHtml":"<hr>\n<h2>name: terrain-hydrology\ndescription: &gt;-\nAlways invoke for terrain, drainage, viewshed, or visibility analysis from\nelevation, even before the DEM or correct surface is chosen. Covers\nDTM-versus-DSM selection, slope, aspect, curvature, hillshade, conditioning,\nflow direction/accumulation, streams, watersheds, and catchments. Use\npoint-cloud-lidar first only when an elevation surface must be created from\nLiDAR or photogrammetric points.\nlicense: MIT\nmetadata:\nauthor: Muhammed Enes Duran</h2>\n<h1>Terrain &amp; Hydrology</h1>\n<p>Purpose: terrain products whose numbers are physically meaningful. The two\nrecurring failure modes: <strong>unit mismatch</strong> (degree coordinates with meter\nelevations silently corrupts every derivative) and <strong>unconditioned DEMs</strong>\n(flow routed into spurious pits produces fragmented, fictional streams).</p>\n<h2>DEM hygiene first</h2>\n<table>\n<thead>\n<tr>\n<th>Check</th>\n<th>Rule</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Surface type</td>\n<td><strong>DTM</strong> (bare earth) for hydrology/slope; <strong>DSM</strong> (with canopy/buildings) for viewshed/solar. Using a DSM for watersheds routes rivers over treetops.</td>\n</tr>\n<tr>\n<td>Source</td>\n<td>Copernicus GLO-30 &gt; SRTM for most global work; national LiDAR DTMs when available (see <code>point-cloud-lidar</code> to make your own). Record source + acquisition date.</td>\n</tr>\n<tr>\n<td>Nodata</td>\n<td>Identify the nodata value (-9999, -32768, 3.4e38) and mask it — never let it enter statistics or fill algorithms as \"very deep hole\".</td>\n</tr>\n<tr>\n<td>Voids</td>\n<td>Fill data voids (interpolation from edges) BEFORE hydrological conditioning; document filled areas.</td>\n</tr>\n<tr>\n<td><strong>CRS + units</strong></td>\n<td>Reproject to a projected CRS so horizontal units = vertical units (meters). Slope from a 4326 DEM without z-factor correction is the classic silent error. If staying geographic, apply a latitude-dependent z-factor — better: don't.</td>\n</tr>\n</tbody>\n</table>\n<h2>Derivatives</h2>\n<pre><code>import whitebox\nwbt = whitebox.WhiteboxTools()\nwbt.slope(\"dem.tif\", \"slope_deg.tif\", units=\"degrees\")\nwbt.aspect(\"dem.tif\", \"aspect_deg.tif\")\nwbt.plan_curvature(\"dem.tif\", \"plan_curv.tif\")\n</code></pre>\n<ul>\n<li>Slope: state units (degrees vs percent — 45° = 100%); Horn's method\n(3×3) is the standard; steeper terrain → consider resolution effects\n(slope flattens as cell size grows — report cell size with every slope\nstatistic).</li>\n<li>Aspect: circular variable — never average it arithmetically; use vector\n(sin/cos) averaging; flat cells have undefined aspect (mask, don't zero).</li>\n<li>Curvature: plan (flow convergence) vs profile (flow acceleration) —\npick per question.</li>\n<li>Hillshade is for cartography (see <code>cartography-geoviz</code>), never analysis\ninput.</li>\n<li>Ruggedness/position: TRI, TPI (radius-dependent — report the radius),\ngeomorphons for landform classification.</li>\n</ul>\n<h2>Hydrological conditioning — order matters</h2>\n<pre><code>voids filled → breach depressions (preferred) → fill remaining pits\n→ flow direction → flow accumulation → streams → watersheds\n</code></pre>\n<ul>\n<li><strong>Breaching before filling</strong> (WhiteboxTools\n<code>BreachDepressionsLeastCost</code>): carves through barriers (road embankments\nover culverts) instead of flooding upstream areas flat. Pure fill on\nflat/embanked terrain creates large artificial lakes with arbitrary flow\npaths.</li>\n<li>Real depressions exist (karst, prairie potholes, reservoirs). If the\nlandscape genuinely holds water, don't condition it away — model with\nexplicit sink handling and say so.</li>\n<li>Flow direction: <strong>D8</strong> for stream networks/watersheds (discrete,\nstandard); <strong>D-infinity/MFD</strong> for dispersal quantities (wetness index,\nerosion) on hillslopes.</li>\n</ul>\n<h2>Streams and watersheds</h2>\n<ul>\n<li>Stream extraction threshold (min. accumulation) is a MODELING choice:\nderive from a mapped reference network (match total stream length) or\nreport the threshold and show two alternatives — never present one\nthreshold's network as \"the\" rivers.</li>\n<li><strong>Pour point snapping</strong>: outlet coordinates rarely fall on the modeled\nstream cell. Snap to the highest-accumulation cell within a search\nradius (<code>wbt.jenson_snap_pour_points</code>) — an unsnapped pour point yields\na tiny, wrong watershed silently.</li>\n<li>Verify delineation: watershed area vs authoritative basin data (±5-10%),\nand the modeled network overlaid on imagery/topo maps at 3 locations.</li>\n<li>Wetness index (TWI), stream power (SPA): compute from conditioned DEM +\nMFD accumulation; they are relative indices — don't read absolute\nthresholds across regions.</li>\n</ul>\n<h2>Viewshed</h2>\n<ul>\n<li>Use a <strong>DSM</strong> (or DTM + feature heights) — bare-earth viewsheds\noverstate visibility wherever trees/buildings exist; state which surface\nwas used.</li>\n<li>Set observer height (~1.7 m person, tower height for infrastructure) and\ntarget height explicitly; defaults differ across tools.</li>\n<li>Account for earth curvature + refraction beyond ~5 km\n(<code>wbt.viewshed</code> handles it; verify the flag).</li>\n<li>Deliver binary visible/not plus the observer point(s) and parameters in\nthe metadata; for siting problems, cumulative viewsheds from candidate\nsets feed <code>mcda-suitability-analysis</code>.</li>\n</ul>\n<h2>Tooling</h2>\n<p>WhiteboxTools (conditioning, full hydrology suite, fast) · <code>pysheds</code>\n(lightweight Python watersheds) · <code>richdem</code> (derivatives) · GDAL\n(<code>gdaldem</code>) for quick slope/hillshade · GRASS (<code>r.watershed</code>) for very\nlarge DEMs (no explicit fill needed — least-cost routing).</p>\n<h2>Verification protocol</h2>\n<ol>\n<li>Derivative histograms: slope &gt; 60° over large areas or negative\naccumulation = unit/nodata bug.</li>\n<li>Stream network overlay on imagery at 3 locations, including one flat\narea (where artifacts concentrate).</li>\n<li>Watershed area cross-check vs authoritative basin polygons.</li>\n<li>Report: DEM source/date/resolution, conditioning method, flow\nalgorithm, stream threshold, all in the deliverable.</li>\n</ol>\n<h2>Pitfalls checklist</h2>\n<ul>\n<li>Slope from a geographic-CRS DEM without z-factor (values ~100× off).</li>\n<li>DSM used for watershed delineation (rivers over treetops).</li>\n<li>Fill-only conditioning across road embankments → phantom lakes.</li>\n<li>Unsnapped pour point → 3-cell \"watershed\".</li>\n<li>Arithmetic mean of aspect (350° and 10° average to south, not north).</li>\n<li>Nodata treated as elevation in fill/statistics.</li>\n<li>One arbitrary stream threshold presented as the drainage network.</li>\n</ul>\n<h2>Execution contract</h2>\n<ul>\n<li><strong>Workflow:</strong> inspect DEM source, CRS, vertical units, datum, resolution, and nodata; condition terrain; derive gradients and flow; delineate products; test thresholds; validate against imagery and controls.</li>\n<li><strong>Decision rules:</strong> use terrain workflows on raster elevation products, point-cloud workflows before DEM generation, and choose conditioning and flow algorithms from landscape and scale.</li>\n<li><strong>Verification protocol:</strong> inspect derivative distributions, hillshade artifacts, stream overlays, watershed area, pour-point snapping, threshold sensitivity, and elevation-control residuals.</li>\n<li><strong>Failure modes:</strong> reject products from DSM misuse, geographic-unit slope, vertical datum mismatch, unconditioned barriers, nodata contamination, unsnapped outlets, or resolution unsupported by source data.</li>\n<li><strong>Deliverables:</strong> conditioned DEM, derivatives and hydrologic products, parameter and threshold record, CRS and vertical datum, QA maps, validation metrics, and limitations.</li>\n<li><strong>Source freshness:</strong> consult <a href=\"references/authoritative-sources.md\">the authoritative source registry</a> before applying tool algorithms or product rules and record the checked date.</li>\n</ul>\n","files":[{"path":"agents/openai.yaml","sizeBytes":213,"isText":true},{"path":"references/authoritative-sources.md","sizeBytes":784,"isText":true},{"path":"SKILL.md","sizeBytes":7272,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-09-18T14:08:45.295939Z","sha256":"0E0D185F12A2830536606CA2A8CDF8AF8F3B80D3EF6D22BAA503BD0421DBEAF0","sizeBytes":4467},"review":null,"source":{"repositoryUrl":"https://github.com/muend/geoai-skills","path":"skills/terrain-hydrology","license":"MIT","commit":"096e5d4e6825a128e376b017783ee4c8c7323f9b","subtreeSha":"2086C51F8677C466137EDE2AB94897E8D0A410FD258659988D3B37B10FEBA1A6","lastSyncedAt":"2026-09-27T19:46:46.325636Z"},"reviewedAt":"2026-09-18T14:10:29.957706Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/muend/geoai-skills/tree/main/skills/terrain-hydrology"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install muend-geoai-skills@llmmart"},{"target":"git","command":"git clone https://github.com/muend/geoai-skills.git"}]}