¿Cómo detener a gdalwarp creando productos que abarcan todo el mundo cerca de la línea de fecha?

11

Estoy usando gdalwarp para manipular mosaicos SRTM cerca de la línea de fecha (es decir, 180 °, también conocido como el antimeridiano). Las baldosas SRTM tienen una superposición muy leve (1/2 píxel) con el meridiano. Puedes ver esto usando 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)
[...]

Entonces, la fuente abarca la fecha en una pequeña cantidad.

Esto causa problemas con gdalwarp, que termina creando enormes resultados que abarcan todo el mundo.

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)

Tenga en cuenta que las longitudes abarcan (casi) todo el globo, y también el número de líneas es inesperadamente pequeño (5)

¿Es esto un error en gdalwarp? Si no, ¿cuáles son las opciones correctas para pasar a gdalwarp para obtener un resultado razonable?

tormenta de gravedad
fuente
dds.cr.usgs.gov/srtm/version2_1/SRTM3/Australia/S16W180.hgt.zip en caso de que desee experimentar.
tormenta de gravedad
agregue el parámetro SOURCE_EXTRA ver code.google.com/p/maptiler/issues/detail?id=6 - pruebe gdalwarp -t_srs epsg: 900913 -wo SOURCE_EXTRA = 120 S16W180.hgt test.tif
Mapperz
tal vez use el argumento -te para "extensiones de destino", o arregle las extensiones primero usando gdal_translate con a_ullr para sobrescribir lo existente, o -projwin para cortar el bit que desee dentro de los límites
mdsumner

Respuestas:

2

Una solución fácil sería especificar el sistema de coordenadas "manualmente" como una cadena PROJ. Esto le permite usar el +overinterruptor que deshabilita el ajuste en el antimeridiano:

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

Cuando hago eso y luego hago gdalinfoel resultado, obtengo esto:

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)

Obtuve la cadena PROJ (sin +over) mirando la salida original de gdalinfo. Se incluyó en un EXTENSION[...]bloque del sistema de coordenadas.

csd
fuente
1

Funciona en dos pasos:

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

El primer comando inicia el medio píxel extra en el lado equivocado del meridiano de 180 °. Obtiene un archivo de salida que es 1178P x 1222L.

Alternativamente, con gdal_translate:

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

Crear un archivo de salida que sea 1179P x 1223L.

AndreJ
fuente
1

Como estaba enfrentando el mismo problema, escribí un pequeño script de shell que descubre si el archivo ráster cruza la línea de fecha. Si es verdadero, la siguiente opción se agrega a gdalwarp:

--config CENTER_LONG 180

Así es como funciona el script paso a paso:

  1. Obtenga extensiones WGS84 de gdalinfo
  2. Si las transformadas ULX y LRX O LLX y URX valores se da la vuelta en comparación con los CRS originales, el raster transformado cruzará la fecha límite.
  3. Si se cruza la línea de fecha, se agrega --config CENTER_LONG 180 a gdalwarp.

ACTUALIZACIÓN Mejor versión del script, requiere GDAL 2.0+ y Python: versión anterior a continuación.

#!/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
fuente
-1

Este es un problema en la biblioteca GDAL. Parece que GDALSuggestedWarpOutput () está dando una salida extraña para el ancho y la altura del archivo de salida.

Todavía no he encontrado una manera de solucionar esto.

Man Vs Code
fuente