Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
83df788
Add river-constrained D8 flow direction
kongdd Aug 21, 2026
f2ae8ff
Include constrained flow-direction tools
kongdd Aug 21, 2026
d99c8d6
Test river-constrained D8 flow direction
kongdd Aug 21, 2026
3ae4ff2
Run constrained flow-direction tests
kongdd Aug 21, 2026
42c8b4d
Add junction snapping and DEM river conditioning
kongdd Aug 21, 2026
4924c55
Test confluence repair and river DEM conditioning
kongdd Aug 21, 2026
adf5d8f
Add river-seeded priority flood routing DEM
kongdd Aug 21, 2026
01f3452
Include priority flood routing
kongdd Aug 21, 2026
775bed3
Test river-seeded priority flood
kongdd Aug 21, 2026
19a5a02
Add complete hydro-enforced flow direction pipeline
kongdd Aug 21, 2026
58c5601
Test full hydro-enforcement pipeline
kongdd Aug 21, 2026
5138bb9
Run hydro-enforcement tests
kongdd Aug 21, 2026
44b8c04
Preserve Priority-Flood queue monotonicity
kongdd Aug 21, 2026
84ab2ce
Load ArchGDAL river IO as package extension
kongdd Aug 21, 2026
9ed9d7c
Expose optional river vector reader
kongdd Aug 21, 2026
65eac58
Add ArchGDAL river vector adapter
kongdd Aug 21, 2026
2a1a12c
Test ArchGDAL river vector reader
kongdd Aug 21, 2026
931bbf9
Run ArchGDAL extension tests
kongdd Aug 21, 2026
8013d49
Accept river vector files in hydro enforcement API
kongdd Aug 21, 2026
5b68d72
Test direct vector-file hydro enforcement
kongdd Aug 21, 2026
4015834
Add flow direction quality-control summary
kongdd Aug 21, 2026
2b00a57
Include flow direction QC
kongdd Aug 21, 2026
f0fdc66
Test flow direction QC summary
kongdd Aug 21, 2026
1f61cc9
Add memory-efficient D8 cycle validation
kongdd Aug 21, 2026
1f56655
Include memory-efficient flow validation
kongdd Aug 21, 2026
8fd36f4
Use linear-memory flow validation in hydro pipeline
kongdd Aug 21, 2026
faa910c
Test linear-memory flow direction validation
kongdd Aug 21, 2026
d3cefde
Run flow direction validation tests
kongdd Aug 21, 2026
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
3 changes: 3 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ SpatialRasterLite = "25a4c9b9-c310-4d6e-b9a7-fa79274760a1"
ArchGDAL = "c9ce4bd3-c3d5-55b8-8973-c0e20141b8c3"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[extensions]
RiverGraphsArchGDALExt = "ArchGDAL"

[sources]
SpatialRasterLite = {url = "https://github.com/jl-pkgs/SpatialRasterLite.jl"}

Expand Down
89 changes: 89 additions & 0 deletions ext/RiverGraphsArchGDALExt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
module RiverGraphsArchGDALExt

import ArchGDAL as AG
import RiverGraphs
import RiverGraphs: read_river_lines, hydro_enforced_flowdir

"""
read_river_lines(path::AbstractString; layer=0, strict=true)

Read LineString/MultiLineString features from a GDAL-supported vector file and
return a `Vector{Vector{Tuple{Float64,Float64}}}`. MultiLineString parts are
returned as separate river lines.

Coordinates are not reprojected. The vector data must use the same CRS as the
raster axes passed later to `rasterize_flowpath` / `hydro_enforced_flowdir`.

With `strict=true`, non-line geometries raise an error. With `strict=false`,
unsupported or empty geometries are skipped. GeometryCollection is traversed
recursively, so mixed collections can be handled with `strict=false`.
"""
function read_river_lines(path::AbstractString;
layer::Integer=0, strict::Bool=true)
lines = Vector{Vector{Tuple{Float64,Float64}}}()

AG.read(path) do dataset
nlayers = AG.nlayer(dataset)
0 <= layer < nlayers || throw(ArgumentError(
"layer index $layer is outside 0:$(nlayers - 1) for $path"))

source = AG.getlayer(dataset, layer)
for feature in source
geom = AG.getgeom(feature, 0)
_append_river_geometry!(lines, geom; strict)
end
end

lines
end

"""
hydro_enforced_flowdir(dem, path, lon, lat; layer=0, strict=true, kwargs...)

Read a GIS river vector file with ArchGDAL and run RiverGraphs' complete
hydro-enforcement pipeline on the supplied raster grid.
"""
function hydro_enforced_flowdir(dem::AbstractMatrix, path::AbstractString,
lon::AbstractVector, lat::AbstractVector;
layer::Integer=0, strict::Bool=true, kwargs...)
lines = read_river_lines(path; layer, strict)
RiverGraphs.hydro_enforced_flowdir(dem, lines, lon, lat; kwargs...)
end

function _append_river_geometry!(lines, geom; strict::Bool)
name = AG.geomname(geom)
if ismissing(name)
strict && throw(ArgumentError("river feature has an empty geometry"))
return lines
end

typename = uppercase(String(name))
if typename == "LINESTRING" || typename == "LINEARRING"
n = Int(AG.ngeom(geom))
if n < 2
strict && throw(ArgumentError("river LineString has fewer than two points"))
return lines
end

line = Vector{Tuple{Float64,Float64}}(undef, n)
@inbounds for i in 0:n-1
point = AG.getpoint(geom, i)
line[i+1] = (Float64(point[1]), Float64(point[2]))
end
push!(lines, line)

elseif typename == "MULTILINESTRING" || typename == "GEOMETRYCOLLECTION"
for i in 0:Int(AG.ngeom(geom))-1
part = AG.getgeom(geom, i)
_append_river_geometry!(lines, part; strict)
end

elseif strict
throw(ArgumentError(
"unsupported river geometry $typename; expected LineString or MultiLineString"))
end

lines
end

end # module RiverGraphsArchGDALExt
15 changes: 15 additions & 0 deletions src/RiverGraphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import RTableTools: cbind, fwrite, fread

include("IO.jl")
include("RiverGraph.jl")
include("validate_flowdir.jl")
include("constrained_flowdir.jl")
include("priority_flood.jl")
include("flowdir_qc.jl")
include("fillnodata_upbasin.jl")
include("fillnodata_upriver.jl")

Expand All @@ -22,12 +26,23 @@ include("utils.jl")
include("sf.jl")


"""
read_river_lines(source; kwargs...)

Read river centreline geometries as vectors of `(x, y)` coordinate tuples.
Methods for GIS vector files are provided by the optional ArchGDAL extension;
load ArchGDAL before calling this function on a file path.
"""
function read_river_lines end


export RiverGraph
export active_indices, reverse_index, pcr_dir,
graph_flow,
topological_sort_kahn,
stream_order, stream_link, stream_network,
fillnodata_upbasin, fillnodata_upriver
export read_river_lines

const path_flowdir_GuanShan = abspath("$(@__DIR__)/../data/GuanShan_flwdir.tif")

Expand Down
Loading
Loading