diff --git a/src/raster/r.hydro.flatten/r.hydro.flatten.html b/src/raster/r.hydro.flatten/r.hydro.flatten.html index f43a043c1b..c0c8cc76be 100644 --- a/src/raster/r.hydro.flatten/r.hydro.flatten.html +++ b/src/raster/r.hydro.flatten/r.hydro.flatten.html @@ -15,6 +15,14 @@

DESCRIPTION

output representing the standard deviation of the lidar elevation values along the water body's edge. Higher deviation suggests problematic areas that need to be further inspected. +The optional output filled_elevation is a raster map of the input ground surface +filled with the computed water_elevation raster map. + +

+The breaklines parameter is an optional input that specifies a vector map of lines +that represent e.g., a break between an impoundment and downstream river, allowing +correct elevation computation. +

To keep the intermediate results for inspection, use flag -k. @@ -44,7 +52,7 @@

EXAMPLE

# convert elevation from feet to meters r.mapcalc "ground_m = ground * 0.304800609601219" # derive elevation of water bodies and standard deviation -r.hydro.flatten input=ground_m water_elevation=water_elevation water_elevation_stddev=water_elevation_stddev percentile=10 misize=4000 +r.hydro.flatten input=ground_m water_elevation=water_elevation water_elevation_stddev=water_elevation_stddev filled_elevation=filled percentile=10 misize=4000
diff --git a/src/raster/r.hydro.flatten/r.hydro.flatten.py b/src/raster/r.hydro.flatten/r.hydro.flatten.py index 56d06096e3..8350934a25 100644 --- a/src/raster/r.hydro.flatten/r.hydro.flatten.py +++ b/src/raster/r.hydro.flatten/r.hydro.flatten.py @@ -28,6 +28,11 @@ # % key: input # % description: Raster map of binned lidar point elevation # %end +# %option G_OPT_V_INPUT +# % key: breaklines +# % description: Vector map of breaklines +# % required: no +# %end # %option G_OPT_R_OUTPUT # % key: water_elevation # % description: Represents single elevation value for each water body @@ -37,6 +42,11 @@ # % key: water_elevation_stddev # % description: Raster map of derived water elevation standard deviation # %end +# %option G_OPT_R_OUTPUT +# % key: filled_elevation +# % required: no +# % description: Raster map representing filled digital elevation model +# %end # %option # % key: percentile # % type: double @@ -92,6 +102,7 @@ def get_name(basename): return name ground = options["input"] + breaklines = options["breaklines"] size_threshold = options["min_size"] if size_threshold: size_threshold = int(size_threshold) @@ -107,6 +118,17 @@ def get_name(basename): region_m = gs.parse_command("g.region", flags="gm") resolution_m = (float(region_m["nsres"]) + float(region_m["ewres"])) / 2 tmp_rfillstats = get_name("rfillstats") + + if breaklines: + tmp_breaklines = get_name("breaklines") + gs.run_command( + "v.to.rast", + input=breaklines, + output=tmp_breaklines, + use="val", + flags="d", + value=1000, + ) gs.run_command( "r.fill.stats", flags="k", @@ -125,6 +147,15 @@ def get_name(basename): distances=[x * resolution_m for x in range(1, buffer_last_strip)], units="meters", ) + if breaklines: + tmp_buffer_with_breaklines = get_name("buffer_with_breaklines") + gs.run_command( + "r.patch", + input=[tmp_breaklines, tmp_buffer], + output=tmp_buffer_with_breaklines, + ) + tmp_buffer = tmp_buffer_with_breaklines + tmp_reclass_for_clump = get_name("reclass_for_clump") gs.write_command( "r.reclass", @@ -155,30 +186,53 @@ def get_name(basename): method="stddev", output=tmp_water_stddev, ) - tmp_water_elevation_dist = get_name("water_elevation_dist") + tmp_water_elevation_zonal = get_name("water_elevation_zonal") gs.run_command( - "r.grow.distance", input=tmp_water_elevation, value=tmp_water_elevation_dist + "r.stats.zonal", + base=tmp_clump, + cover=tmp_water_elevation, + method="average", + output=tmp_water_elevation_zonal, ) - tmp_water_stddev_dist = get_name("water_stddev_dist") + tmp_water_elevation_stddev_zonal = get_name("water_elevation_stddev_zonal") gs.run_command( - "r.grow.distance", input=tmp_water_stddev, value=tmp_water_stddev_dist - ) - tmp_water_elevation_dist_res = get_name("water_elevation_dist_res") - gs.mapcalc( - f"{tmp_water_elevation_dist_res} = if ({tmp_buffer} < {buffer_last_strip}, " - f"{tmp_water_elevation_dist}, null())" + "r.stats.zonal", + base=tmp_clump, + cover=tmp_water_stddev, + method="average", + output=tmp_water_elevation_stddev_zonal, ) - tmp_water_stddev_dist_res = get_name("water_stddev_dist_res") + tmp_water_elevation_zonal_res = get_name("water_elevation_zonal_res") + if breaklines: + water_elevation_zonal_res_breaklines = get_name( + "water_elevation_zonal_res_breaklines" + ) + gs.mapcalc( + f"{water_elevation_zonal_res_breaklines} = if (isnull({tmp_strip}), {tmp_water_elevation_zonal}, null())" + ) + # heal the breakline holes + gs.run_command( + "r.neighbors", + input=water_elevation_zonal_res_breaklines, + selection=tmp_breaklines, + output=tmp_water_elevation_zonal_res, + size=5, + ) + else: + gs.mapcalc( + f"{tmp_water_elevation_zonal_res} = if (isnull({tmp_strip}), {tmp_water_elevation_zonal}, null())" + ) + + tmp_water_elevation_stddev_zonal_res = get_name("water_elevation_stddev_zonal_res") gs.mapcalc( - f"{tmp_water_stddev_dist_res} = if ({tmp_buffer} < {buffer_last_strip}, " - f"{tmp_water_stddev_dist}, null())" + f"{tmp_water_elevation_stddev_zonal_res} = if (isnull({tmp_strip}), {tmp_water_elevation_stddev_zonal}, null())" ) if size_threshold: size_threshold /= region["nsres"] * region["ewres"] tmp_reclass = get_name("reclass") gs.write_command( "r.reclass", - input=tmp_water_elevation_dist_res, + input=tmp_water_elevation_zonal_res, output=tmp_reclass, rules="-", stdin="* = 1", @@ -194,18 +248,28 @@ def get_name(basename): output=tmp_size, ) gs.mapcalc( - f"{options['water_elevation']} = if ({tmp_size} > {size_threshold}, {tmp_water_elevation_dist_res}, null())" + f"{options['water_elevation']} = if ({tmp_size} > {size_threshold}, {tmp_water_elevation_zonal_res}, null())" ) gs.mapcalc( - f"{options['water_elevation_stddev']} = if ({tmp_size} > {size_threshold}, {tmp_water_stddev_dist_res}, null())" + f"{options['water_elevation_stddev']} = if ({tmp_size} > {size_threshold}, {tmp_water_elevation_stddev_zonal_res}, null())" ) else: - gs.mapcalc(f"{options['water_elevation']} = {tmp_water_elevation_dist_res}") - gs.mapcalc(f"{options['water_elevation_stddev']} = {tmp_water_stddev_dist_res}") + gs.mapcalc(f"{options['water_elevation']} = {tmp_water_elevation_zonal_res}") + gs.mapcalc( + f"{options['water_elevation_stddev']} = {tmp_water_elevation_stddev_zonal_res}" + ) gs.run_command("r.colors", map=options["water_elevation"], raster=ground) gs.run_command("r.colors", map=options["water_elevation_stddev"], color="reds") gs.raster_history(options["water_elevation"]) gs.raster_history(options["water_elevation_stddev"]) + if options["filled_elevation"]: + gs.run_command( + "r.patch", + input=[tmp_rfillstats, options["water_elevation"]], + output=options["filled_elevation"], + ) + gs.run_command("r.colors", map=options["filled_elevation"], raster=ground) + gs.raster_history(options["filled_elevation"]) if __name__ == "__main__":