Comment empêcher gdalwarp de créer des sorties de portée mondiale près de la ligne de données?

11

J'utilise gdalwarp pour manipuler des tuiles SRTM près de la ligne de données (c'est-à-dire 180 °, alias l'antiméridien). Les carreaux SRTM ont un très léger chevauchement (1/2 pixel) avec le méridien. Vous pouvez le voir en utilisant gdalinfo:

gdalinfo S16W180.hgt
Driver: SRTMHGT/SRTMHGT File Format
Files: S16W180.hgt
Size is 1201, 1201
[...]
Lower Left  (-180.0004167, -16.0004167) (180d 0' 1.50"W, 16d 0' 1.50"S)
Upper Right (-178.9995833, -14.9995833) (178d59'58.50"W, 14d59'58.50"S)
[...]

La source s'étend donc sur une petite quantité de la ligne de données.

Cela provoque des problèmes avec gdalwarp, qui finit par créer d'énormes sorties couvrant l'ensemble du globe.

gdalwarp -t_srs "epsg:900913" S16W180.hgt test.tif
gdalinfo test.tif
Driver: GTiff/GeoTIFF
Files: test.tif
Size is 1703, 5
[...]
Lower Left  (-20037508.330,-1806798.473) (180d 0' 0.00"W, 16d 7'13.00"S)
Upper Right (20032839.451,-1689152.120) (179d57'29.01"E, 15d 5'45.84"S)

Notez que les longitudes couvrent (presque) le globe entier, et aussi le nombre de lignes est étonnamment petit (5)

Est-ce un bug dans gdalwarp? Sinon, quelles sont les bonnes options à passer à gdalwarp pour obtenir une sortie sensible?

gravité
la source
dds.cr.usgs.gov/srtm/version2_1/SRTM3/Australia/S16W180.hgt.zip au cas où vous voudriez expérimenter.
gravitystorm
ajoutez le paramètre SOURCE_EXTRA voir code.google.com/p/maptiler/issues/detail?id=6 - essayez gdalwarp -t_srs epsg: 900913 -wo SOURCE_EXTRA = 120 S16W180.hgt test.tif
Mapperz
utilisez peut-être l'argument -te pour les "extensions cibles", ou réparez d'abord les extensions en utilisant gdal_translate avec a_ullr pour écraser l'existant, ou -projwin pour couper le bit que vous voulez dans les limites
mdsumner

Réponses:

2

Une solution de contournement simple consisterait à spécifier le système de coordonnées "manuellement" en tant que chaîne PROJ. Cela vous permet d'utiliser le +overcommutateur qui désactive l'habillage sur l'antiméridien:

gdalwarp -t_srs \
    "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0 \
        +over +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null \
        +wktext +lon_wrap=-180 +no_defs" \
    S16W180.hgt test.tif

Quand je fais ça et que je fais gdalinfole résultat, j'obtiens ceci:

Corner Coordinates:
Upper Left  (-20037554.726,-1689152.120) (179d59'58.50"E, 14d59'58.50"S)
Lower Left  (-20037554.726,-1804766.925) (179d59'58.50"E, 16d 0' 1.37"S)
Upper Right (-19926099.407,-1689152.120) (178d59'57.11"W, 14d59'58.50"S)
Lower Right (-19926099.407,-1804766.925) (178d59'57.11"W, 16d 0' 1.37"S)
Center      (-19981827.066,-1746959.523) (179d29'59.30"W, 15d30' 2.12"S)

J'ai obtenu la chaîne PROJ (sans +over) en regardant la sortie d'origine de gdalinfo. Il a été inclus dans un EXTENSION[...]bloc du système de coordonnées.

csd
la source
1

Cela fonctionne en deux étapes:

gdalwarp -te -180 -16 -179 -15 s16W180.hgt test.tif
gdalwarp -t_srs "epsg:3857" test.tif out.tif

La première commande lance le demi-pixel supplémentaire du mauvais côté du méridien à 180 °. Vous obtenez un fichier de sortie de 1178P x 1222L.

Alternativement, avec gdal_translate:

gdal_translate -a_ullr -180 -15 -179 -16 S16W180.hgt test2.tif
gdalwarp -t_srs "epsg:3857" test2.tif out2.tif

Création d'un fichier de sortie de 1179P x 1223L.

AndreJ
la source
1

Comme j'étais confronté au même problème, j'ai écrit un petit script shell qui découvre si le fichier raster traverse la ligne de données. Si vrai, l'option suivante est ajoutée à gdalwarp:

--config CENTER_LONG 180

Voici comment le script fonctionne pas à pas:

  1. Obtenez les extensions WGS84 de gdalinfo
  2. Si les valeurs ulx et lrx transformées OU llx et urx sont inversées par rapport au CRS d'origine, le raster transformé traversera la ligne de données.
  3. Si la ligne de données doit être franchie, --config CENTER_LONG 180 est ajouté à gdalwarp.

MISE À JOUR Meilleure version du script, nécessite GDAL 2.0+ et Python: ancienne version ci-dessous.

#!/bin/bash
#
# Small Script to check if input raster will
# cross dateline when converting to EPSG:4326
# 
# USAGE: ./crosses_dateline.sh infile [outfile]
# 
# if no outfile is given, the script returns "true" or "false"
# if an outfile is given, gdalwarp is executed
# 
# Needs gdal 2.0+ and Python
# 


if [ -z "${1}" ]; then
    echo -e "Error: No input rasterfile given.\n> USAGE: ./crosses_dateline.sh infile [outfile]"
    exit
fi

# Get information, save it to variable as we need it several times
gdalinfo=$(gdalinfo "${1}" -json)

# If -json switch is not available exit!
if [ ! -z $(echo $gdalinfo | grep "^Usage:") ]; then
    echo -e "Error: GDAL command failed, Version 2.0+ is needed"
    exit
fi

function jsonq {
    echo "${1}" | python -c "import json,sys; jdata = sys.stdin.read(); data = json.loads(jdata); print(data${2});"
}

ulx=$(jsonq "$gdalinfo" "['wgs84Extent']['coordinates'][0][0][0]")
llx=$(jsonq "$gdalinfo" "['wgs84Extent']['coordinates'][0][1][0]")
lrx=$(jsonq "$gdalinfo" "['wgs84Extent']['coordinates'][0][3][0]")
urx=$(jsonq "$gdalinfo" "['wgs84Extent']['coordinates'][0][2][0]")

crossing_dateline=false
test $(echo "${ulx}>${lrx}" | bc) -eq 1 && crossing_dateline=true
test $(echo "${llx}>${urx}" | bc) -eq 1 && crossing_dateline=true

if [ -z "$2" ]; then
    echo "${crossing_dateline}"
elif [ "${crossing_dateline}" == "true" ]; then
    gdalwarp -t_srs "EPSG:4326" --config CENTER_LONG 180 "${1}" "${2}"
else
    gdalwarp -t_srs "EPSG:4326" "${1}" "${2}"
fi

#!/bin/bash
#
# Check if input raster crosses dateline when converting to EPSG:4326
# 
# if no outfile is given, the script returns "true" or "false"
# if an outfile is given, gdalwarp is executed
# 

if [ -z "${1}" ]; then
    echo -e "Error: No input rasterfile given.\n> USAGE: ./crosses_dateline.sh infile [outfile]"
    exit
fi

# Get information, save it to variable as we need it several times
gdalinfo=$(gdalinfo "${1}")
# Read Source CRS
s_srs="EPSG:"$(echo "${gdalinfo}" | grep -Eo "^\s{4}AUTHORITY\[.*\]" | grep -Eo "[0-9]+")

# Transform corners to Target SRS and test if crossing dateline
t_srs="EPSG:4326"
crossing_dateline=false

if [ "${s_srs}" == "${t_srs}" ]; then
    xmin=$(echo "${gdalinfo}" | grep "Upper Left" | grep -Eo "[-0-9\.]+, +[-0-9\.]+" | grep -Eo "^[-0-9\.]*")
    xmax=$(echo "${gdalinfo}" | grep "Lower Right" | grep -Eo "[-0-9\.]+, +[-0-9\.]+" | grep -Eo "^[-0-9\.]*")
    test $(echo "(${xmax}-(${xmin})) / 1" | bc) -gt 180 && crossing_dateline=true
else
    # We need to check both diagonal lines for intersection with the dateline
    xmin=$(echo "${gdalinfo}" | grep "Upper Left" | grep -Eo "[-0-9\.]+, +[-0-9\.]+" | gdaltransform -s_srs "${s_srs}" -t_srs "${t_srs}" -output_xy | grep -Eo "^[-0-9\.]*")
    xmax=$(echo "${gdalinfo}" | grep "Lower Right" | grep -Eo "[-0-9\.]+, +[-0-9\.]+" | gdaltransform -s_srs "${s_srs}" -t_srs "${t_srs}" -output_xy | grep -Eo "^[-0-9\.]*")
    test $(echo "${xmin}>${xmax}" | bc) -eq 1 && crossing_dateline=true

    xmin=$(echo "${gdalinfo}" | grep "Lower Left" | grep -Eo "[-0-9\.]+, +[-0-9\.]+" | gdaltransform -s_srs "${s_srs}" -t_srs "${t_srs}" -output_xy | grep -Eo "^[-0-9\.]*")
    xmax=$(echo "${gdalinfo}" | grep "Upper Right" | grep -Eo "[-0-9\.]+, +[-0-9\.]+" | gdaltransform -s_srs "${s_srs}" -t_srs "${t_srs}" -output_xy | grep -Eo "^[-0-9\.]*")
    test $(echo "${xmin}>${xmax}" | bc) -eq 1 && crossing_dateline=true
fi


if [ -z "$2" ]; then
    echo "${crossing_dateline}"
elif [ "${crossing_dateline}" == "true" ]; then
    gdalwarp -t_srs "${t_srs}" --config CENTER_LONG 180 "${1}" "${2}"
else
    gdalwarp -t_srs "${t_srs}" "${1}" "${2}"
fi
pLumo
la source
-1

C'est un problème dans la bibliothèque GDAL. Il semble que GDALSuggestedWarpOutput () donne une sortie étrange pour la largeur et la hauteur du fichier de sortie.

Je n'ai pas encore trouvé de moyen de contourner ce problème.

Man Vs Code
la source