Skip to content

Commit aff7e2d

Browse files
authored
Merge pull request OSGeo#13103 from rouault/fix_13100
gdaldem: fix wrong results on non north-up src ds wih aspect/tpi/tri (and…
2 parents 8e39cf9 + 6013324 commit aff7e2d

File tree

2 files changed

+68
-4
lines changed

2 files changed

+68
-4
lines changed

apps/gdaldem_lib.cpp

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3634,6 +3634,39 @@ GDALDatasetH GDALDEMProcessing(const char *pszDest, GDALDatasetH hSrcDataset,
36343634

36353635
GDALDEMProcessingOptions *psOptions = psOptionsToFree.get();
36363636

3637+
double adfGeoTransform[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
3638+
3639+
// Keep that variable in that scope.
3640+
// A reference on that dataset will be taken by GDALGeneric3x3Dataset
3641+
// (and released at its destruction) if we go to that code path, and
3642+
// GDALWarp() (actually the VRTWarpedDataset) will itself take a reference
3643+
// on hSrcDataset.
3644+
std::unique_ptr<GDALDataset, GDALDatasetUniquePtrReleaser> poTmpSrcDS;
3645+
3646+
if (GDALGetGeoTransform(hSrcDataset, adfGeoTransform) == CE_None &&
3647+
// For following modes, detect non north-up datasets and autowarp
3648+
// them so they are north-up oriented.
3649+
(((eUtilityMode == ASPECT || eUtilityMode == TRI ||
3650+
eUtilityMode == TPI) &&
3651+
(adfGeoTransform[2] != 0 || adfGeoTransform[4] != 0 ||
3652+
adfGeoTransform[5] > 0)) ||
3653+
// For following modes, detect rotated datasets and autowarp
3654+
// them so they are north-up oriented. (south-up are fine for those)
3655+
((eUtilityMode == SLOPE || eUtilityMode == HILL_SHADE) &&
3656+
(adfGeoTransform[2] != 0 || adfGeoTransform[4] != 0))))
3657+
{
3658+
const char *const apszWarpOptions[] = {"-of", "VRT", nullptr};
3659+
GDALWarpAppOptions *psWarpOptions = GDALWarpAppOptionsNew(
3660+
const_cast<char **>(apszWarpOptions), nullptr);
3661+
poTmpSrcDS.reset(GDALDataset::FromHandle(
3662+
GDALWarp("", nullptr, 1, &hSrcDataset, psWarpOptions, nullptr)));
3663+
GDALWarpAppOptionsFree(psWarpOptions);
3664+
if (!poTmpSrcDS)
3665+
return nullptr;
3666+
hSrcDataset = GDALDataset::ToHandle(poTmpSrcDS.get());
3667+
GDALGetGeoTransform(hSrcDataset, adfGeoTransform);
3668+
}
3669+
36373670
const int nXSize = GDALGetRasterXSize(hSrcDataset);
36383671
const int nYSize = GDALGetRasterYSize(hSrcDataset);
36393672

@@ -3730,12 +3763,8 @@ GDALDatasetH GDALDEMProcessing(const char *pszDest, GDALDatasetH hSrcDataset,
37303763
return nullptr;
37313764
}
37323765

3733-
double adfGeoTransform[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
3734-
37353766
GDALRasterBandH hSrcBand = GDALGetRasterBand(hSrcDataset, psOptions->nBand);
37363767

3737-
GDALGetGeoTransform(hSrcDataset, adfGeoTransform);
3738-
37393768
CPLString osFormat;
37403769
if (psOptions->osFormat.empty())
37413770
{

autotest/utilities/test_gdaldem_lib.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,3 +910,38 @@ def test_gdaldem_lib_dict_arguments():
910910
ind = opt.index("-co")
911911

912912
assert opt[ind : ind + 4] == ["-co", "COMPRESS=DEFLATE", "-co", "LEVEL=4"]
913+
914+
915+
###############################################################################
916+
917+
918+
def flipped_ds():
919+
920+
src_ds = gdal.Open("../gdrivers/data/n43.tif")
921+
gt = src_ds.GetGeoTransform()
922+
ulx = "%.17g" % gt[0]
923+
uly = "%.17g" % gt[3]
924+
lrx = "%.17g" % (gt[0] + src_ds.RasterXSize * gt[1])
925+
lry = "%.17g" % (gt[3] + src_ds.RasterYSize * gt[5])
926+
return gdal.Warp("", src_ds, options=f"-of VRT -te {ulx} {uly} {lrx} {lry}")
927+
928+
929+
@pytest.mark.parametrize("alg", ["aspect", "TPI", "TRI"])
930+
def test_gdaldem_lib_flipped_aspect_tpi_tri(alg):
931+
932+
src_ds = gdal.Open("../gdrivers/data/n43.tif")
933+
ref_ds = gdal.DEMProcessing("", src_ds, alg, format="MEM", computeEdges=True)
934+
out_ds = gdal.DEMProcessing("", flipped_ds(), alg, format="MEM", computeEdges=True)
935+
assert ref_ds.GetGeoTransform() == pytest.approx(out_ds.GetGeoTransform())
936+
assert ref_ds.ReadRaster() == out_ds.ReadRaster()
937+
938+
939+
@pytest.mark.parametrize("alg", ["hillshade", "slope", "roughness"])
940+
def test_gdaldem_lib_flipped_hillshade_slope_roughness(alg):
941+
942+
src_ds = gdal.Open("../gdrivers/data/n43.tif")
943+
ref_ds = gdal.DEMProcessing("", src_ds, alg, format="MEM", computeEdges=True)
944+
out_ds = gdal.DEMProcessing("", flipped_ds(), alg, format="MEM", computeEdges=True)
945+
out_ds = gdal.Warp("", out_ds, format="MEM")
946+
assert ref_ds.GetGeoTransform() == pytest.approx(out_ds.GetGeoTransform())
947+
assert ref_ds.ReadRaster() == out_ds.ReadRaster()

0 commit comments

Comments
 (0)