Natural=peak sin name=*

Abro este hilo¹ debido a las habituales quejas de usuarios referentes al abuso que se hace sobre natural=peak, introduciendo un exceso de picos no acorde con la realidad, por ejemplo en esta entrada del foro: Peaks in the area of Nerja (Costa del Sol) se menciona Sierra Nevada y Málaga. También se han producido quejas en Fuerteventura.

Por tratar de resumir, desde el IGN se pueden descargar diversos productos de la Base Topológica Nacional, que incluyen muchos datos vectoriales sobre elevaciones, los cuales aparecen renderizados en el mapa ráster:

Muestro dos datasets de una hoja del BTN, en el que se muestras las cotas altimétricas y las curvas de nivel. Hay más datos, evidentemente.

El tema es que varios mapeadores están utilizando la información de las cotas altimétricas como si se tratase de picos (o collados), cuando simplemente son mediciones, que se corresponden con puntos rodeados de cotas inferiores, pero lejos del concepto general que tenemos de lo que es una cima.

Es cierto que, como menciono en este post, el renderizador de cartocss no ayuda (el mapa por defecto de OSM) lleva años sin resolver el problema, ni tiene pinta de que lo vaya a hacer próximamente.

Por tanto, debemos acordar qué hacer con este tipo de información geográfica: si merece estar en el mapa de OSM (las curvas de nivel, por ejemplo, no se incluyen), y siendo así qué etiquetado es preferible. O si por el contrario, es más sencillo eliminarlo (picos sin nombre).

Podéis utilizar esta consulta para encontrar picos sueltos que se encuentran cerca de otros picos que sí tienen nombre. Podéis jugar con la distancia node(around.picosnombre:100) cambiando el número 100 (metros).

[out:json][timeout:25];
node[natural=peak]["name"]["ele"]({{bbox}}) -> .picosnombre;
node(around.picosnombre:100)
      ["natural"="peak"]
      [!"name"];
out geom;

¹ Tema también comentado en telegram: Telegram: View @OSMes

1 Like

Hola.

En Málaga ya he empezado a revertir algunos de los cambios. Como comenté en el hilo y en la entrada del diario, opté por usar «natural=peak» porque la discusión sobre si un pico es una montaña o una colina («natural=hill») tampoco parece que se vaya a resolver próximamente. Los colaboradores de OSM no se ponen de acuerdo sobre este punto y se le quitan a uno las ganas de abrir nuevamente la discusión para no llegar a nada.

Hace años mantuve una discusión en la lista de correo internacional sobre la mejor forma de mapear una cordillera. Aunque las cordilleras se pueden añadir al mapa, después de aquella peregrina discusión llegué a la conclusión de que, aunque se puede, en realidad no se puede. Siempre había alguien que encontraba algún problema en la forma de mapear cordilleras, y la conclusión a la que llegué fue que no se pueden mapear cordilleras, aunque se pueda. En fin, entre absurdo y ridículo, pero así fue. Quedó claro que este asunto, como el de mapear puntos singulares del terreno, no está resuelto en OSM.

En cualquier caso, ya se están revertiendo algunos picos que claramente no lo son. Me llevará algún tiempo, estoy en ello. Mejor no discutir sobre el sexo de los ángeles.

Buenas tardes, yo en mi opinion soy partidario de eliminar las cotas que no salgan reflejadas en los mapas del IGN o en los mapas cartográficos de las comunidades autonómicas que dispongan de ellos, como el Institut Cartogràfic Valencià (ICV) sean picos o no, si salen en los mapas las dejaría para mi es una información util.

Otra cosa seria de como representarlas en vez de utilizar “natural”=“peak”, desconozco si se pudiera utilizar otra definición.

Saludos.

Creo que sería mejor no seguir ese criterio. Asumiendo que nos movemos en terreno movedizo y que no está claro lo que es un pico, una montaña o una colina ni que etiquetas le corresponden en cada caso, nada en las directrices del wiki dice que no se pueda mapear un pico sin nombre. Si alguien se queja porque le borran o no le dejan mapear un pico sin nombre, tendría que darle la razón.

Por matizar, realmente es el IGN quien es responsable de que se etiqueten infinitos picos de montaña.
En la siguiente imagen, los marcados en color negro (dos picos y un collado), tienen nombre y no hay discusión sobre ello. Pero los marcados en morado se han introducido como picos, y no son cimas, son simplemente un promontorio, no tiene ni por qué destacar en su entorno, pero para el IGN está catalogado como una cota altimétrica, simplemente porque sabe la altitud en ese punto.

De mantener la información (porque esto es OSM y es inevitable que cualquier mapeador introduzca esos datos) habría que asignarle algúna etiqueta del tipo man_made, aunque no survey_point ya que eso señala a un vértice geodésico, es decir, un elemento construido que existe físicamente, a diferencia de estas cotas, que son valores numéricos que no se apegan a ningún elemento físico, ni natural ni construido.

Que sea un punto singular que destaque sobre su entorno sí me parece un buen criterio para decidir lo que debe etiquetarse como pico, con independencia de que tenga o no tenga nombre.

Los que practiquen orientación o senderismo seguro que saben lo valioso que es conocer dónde están esos puntos singulares del terreno, tengan o no tengan nombre.

Por eso, he incluido la consulta de picos cercanos. Sería un caso muy extraño que algo marcado como pico, carezca de nombre y esté a muy poca distancia de una verdadera cima. En general, en un cordal como el de la imagen (la cañada real de Jerez del Marquesado) no hay más pico que la verdadera cima, y que tampoco destaque lo suficiente como para no tener nombre.

No sabría decir cuán extraño es. Sí puedo decir que conozco algún caso, cimas muy cercanas la una de la otra, una con nombre y otra sin nombre. Desde la distancia, la que parece más prominente es curiosamente la que no tiene nombre, aunque realmente sea más baja.

Sea como sea, no importan tanto los casos particulares como encontrar algún criterio general que podamos seguir al respecto. El criterio del nombre no me convence porque los mapeadores van a seguir añadiendo puntos singulares —aunque no tengan nombre— siempre que les sean útiles tenerlos en un mapa como referencia. Si lo hacen, yo no sabría explicarles por qué no lo pueden hacer. Tendría que dejarlo estar porque las directrices de OSM lo permiten.

1 Like

Entiendo que una de las opciones que podemos abordar es justamente cambiar esas directrices para hacerlas más concretas.

Personalmente creo (y ya mencioné) que se podría seguir un criterio objetivo basado en el concepto topográfico de prominencia que mide “cuánto sobresale” el pico comparado con sus alrededores.


(información de Ⓒ)

Ejemplo: un pico que solamente tiene natural=peak + ele=397, y cuya prominencia es de 5 metros, tiene poco mérito de existir.

Ejemplo: un pico que solamente tiene natural=peak + ele=397 con prominencia de 200 metros es un lugar importante que destaca en el terreno.

Queda por determinar un valor de prominencia útil, y una herramienta tipo Osmose (o incluso un plug-in JOSM o una mejora en iD) que avisen de un pico de poco valor.


En cualquier caso, los picos que tengan otras etiquetas ademàs de natural=peak+ ele=* se dejan como están.

Creo q necesitamos una etiqueta específica para las cotas. Eliminar los datos solo es una solución temporal, hasta q un nuevo usuario voluntarioso decide añadirlas de nuevo como pico…

Ya existe la clave «ele» para indicar la cota (elevación sobre el nivel del mar). Lo que ocurre es que la clave «ele» debe estar acompañada de otras etiquetas. OpenStreetMap no pretende ser una base de datos de elevación general, por lo que debe evitarse añadir nodos exclusivamente con el dato «ele». Tampoco se debe añadir la clave «ele» a objetos cuya elevación no sea una información de interés general (una farola en medio de una calle, por ejemplo, o una parada de bus).

1 Like

Fácil de decir, pero muy difícil de obtener: hasta donde he visto no hay ningún dataset del IGN que aporte ese dato, por lo que hay que calcularlo.

¿Cómo? pues a partir de los ficheros GeoTIFF presentes en el modelo digital de elevaciones, es necesario descargarse todos los relativos a la zona a analizar, y utilizar un script al que se le pase una coordenada y devuelva el cálculo.

Consideraciones:

  • Cuanto más fina sea la malla, mayor precisión: MDT02 es la que da un resultados más adecuados
  • Cada fichero de la malla MDT02 ocupa unos 100Mb.
  • Para analizar una zona es muy probable que se necesiten múltiples hojas, que habría que combinar en una sola. Se puede hacer con QGIS.

Se me ha ocurrido pedir un script en python a chatGPT :crossed_fingers: para que me calcule si una coordenada es prominente o no. Tal vez en QGIS exista algún plugin más acertado pero lo desconozco:

SCRIPT ACTUALIZADO

import argparse
import rasterio
import numpy as np
from pyproj import Transformer

def estimar_pixel_metros(src):
    px_x = abs(src.transform[0])
    px_y = abs(src.transform[4])
    px_m = (px_x + px_y) / 2
    if px_m < 0.1:
        px_m = 2  # Forzamos 2m si sale ridículamente pequeño
    return px_m

def destacar_punto(tif_path, lon, lat, ele, osm_id):
    radios_peque = [1, 3, 5]
    radios_grande = [10, 20, 50, 100, 200, 500]
    pesos_grande = [1, 2, 3, 4, 5, 6, 7]  # len=7, 500 incluido
    total_peso = sum(pesos_grande)

    with rasterio.open(tif_path) as src:
        px_m = estimar_pixel_metros(src)

        transformer = Transformer.from_crs("EPSG:4326", src.crs, always_xy=True)
        x, y = transformer.transform(lon, lat)

        row, col = src.index(x, y)
        elev_data = src.read(1)

        # Aplicar offset del DEM con la elevación oficial (ele)
        delta_ele = ele - elev_data[row, col]
        elev_data_adj = elev_data + delta_ele

        # Función interna para evaluar criterio p95 (radios grandes)
        def criterio_p95(r):
            r_pix = r
            row_start = max(row - r_pix, 0)
            row_end = min(row + r_pix + 1, elev_data_adj.shape[0])
            col_start = max(col - r_pix, 0)
            col_end = min(col + r_pix + 1, elev_data_adj.shape[1])

            ventana = elev_data_adj[row_start:row_end, col_start:col_end].flatten()
            ventana = ventana[ventana > -10000]
            if ventana.size == 0:
                return False, 0
            p95 = np.percentile(ventana, 95)
            cumple = ele >= p95
            return cumple, p95 * px_m

        # Función interna para criterio local (radios pequeños)
        def criterio_local(r):
            r_pix = r
            row_start = max(row - r_pix, 0)
            row_end = min(row + r_pix + 1, elev_data_adj.shape[0])
            col_start = max(col - r_pix, 0)
            col_end = min(col + r_pix + 1, elev_data_adj.shape[1])

            ventana = elev_data_adj[row_start:row_end, col_start:col_end]
            ventana_val = ventana[ventana > -10000]
            if ventana_val.size == 0:
                return False, 0
            media_vecinos = np.mean(ventana_val)
            cumple = ele > media_vecinos
            return cumple, media_vecinos * px_m

        # Evaluamos radios grandes con pesos
        resultados_p95 = []
        suma_pesos = 0
        for i, r in enumerate(radios_grande):
            cumple, val = criterio_p95(r)
            resultados_p95.append((cumple, val))
            if cumple:
                suma_pesos += pesos_grande[i]

        cumple_p95 = suma_pesos >= total_peso / 2

        # Evaluamos radios pequeños sin pesos
        resultados_local = []
        for r in radios_peque:
            cumple, val = criterio_local(r)
            resultados_local.append((cumple, val))

        cumple_local = sum([1 for c, _ in resultados_local if c]) >= len(radios_peque) / 2

        cumple_total = cumple_p95 and cumple_local

        icono_final = "✅" if cumple_total else "❌"
        alerta = ""
        delta_dem = ele - elev_data[row, col]
        if abs(delta_dem) > 10:
            alerta = "❗"

        # Formateo ticks para p95 y local
        def ticks(resultados):
            return "".join("✔" if r else "✘" for r, _ in resultados)

        rango_p95 = f"{radios_grande[0]*px_m:.1f}m -> {radios_grande[-1]*px_m:.1f}m"
        rango_local = f"{radios_peque[0]*px_m:.1f}m -> {radios_peque[-1]*px_m:.1f}m"

        print(f"{icono_final} | criteria: {ticks(resultados_p95)} (p95: {rango_p95}) {ticks(resultados_local)} (local: {rango_local}) | ΔDEM: {delta_dem:+.2f}m {alerta} | https://www.openstreetmap.org/node/{osm_id}")

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Estimación simple de prominencia local en un DEM.")
    parser.add_argument("tif_path", help="Archivo GeoTIFF")
    parser.add_argument("lon", type=float, help="Longitud")
    parser.add_argument("lat", type=float, help="Latitud")
    parser.add_argument("ele", type=float, help="Elevación oficial a comprobar")
    parser.add_argument("osm_id", help="ID nodo OSM")
    args = parser.parse_args()

    destacar_punto(args.tif_path, args.lon, args.lat, args.ele, args.osm_id)

Para probar el script podéis obtener un CSV así, y luego guardarlo en un fichero:

[out:csv(::lon, ::lat, "ele", ::id)][timeout:25];
node[natural=peak][!"name"]["ele"]({{bbox}});
out geom;

y luego ejecutarlo en bucle:

while IFS=$'\t' read -r lon lat ele id;
 do python prominencia.py <fichero>.tif $lon $lat $ele $id;
done < prominencias

Se necesita un fichero GeoTIFF

En Australia (principalmente, y solo en una zona específica) se ha utilizado natural=spot_elevation, aunque no tenga excesivos usos, parece que es muy parecido a este caso.

Mi idea era calcularlo a partir de los datos ya inscritos en OpenStreetMap, imaginando que solo require un mínimo de pos-procesado a partir de la consulta Overpass que proponías en el primer mensaje.

Serviría no ya como una fuente de “picos prominentes” sino como una mera criba de los picos no prominentes que ya están en el mapa.

La prominencia no se puede calcular así, no es restar altitudes. Se necesitan modelos de elevaciones para determinar si un punto destaca en su entorno o no.

Como ya he explicado en el comentario anterior, es bastante enrevesado, y solo obtendríamos un valor estimado, aunque suficiente para ir cribando algunos.

No sé por qué seguir esta politica. A mi me parece útil de añadir lo que en ingles llamamos “spot heights”, si estas cotas tienen una provenencia de tan alta calidad como el IGN.

ele=* sín más puede communicar la existencia de una “cimacita”, y esto sería útil para los montañeros y otros. Más importante, permite averiguar las elevaciones approximada por radar, o otra manera no muy precisa (lo cual supongo se usa para Tracetrack Topo).

Estoy de acuerdo que “peak” debería significar cima culturalmente entendida como tal (y pues probablemente tiene nombre), o al menos una cima prominente. No sé cómo las identificar, pero espería que las cotas mismas puedan quedar.

Porque son las directrices de OSM. Puede verlas en el wiki:

OpenStreetMap does not try to be a general elevation database, so do not tag elevation of nodes with no other tags, as well as for objects whose elevation is not an information of general interest.

Es justo al revés. La clave prominence está pensada para añadir información adicional a un pico con el fin de que sirva de fuente para saber cuándo un pico es más prominente que otro. No sirve ni se usa para determinar lo que es un pico de lo que no lo es. Todos lo son.

P. D.: La prominencia está bien para usarla en mapas personalizados en los que solo queramos ver los picos y cimas más prominentes. También es útil como fuente para que el renderizador solo muestre los picos más prominentes y oculte los menos prominentes en pantalla a distintos niveles de zum. Pero los picos siguen siendo picos aunque no aparezcan en nuestro mapa o no se muestren en pantalla. Cribarlos por su prominencia no desvirtúa su naturaleza: un pico es un pico tenga la prominencia que tenga, tenga o no tenga nombre, y no sabría cómo explicarle a un mapeador que no puede añadirlo al mapa cuando las directrices de OSM efectivamente lo permiten.

1 Like

He actualizado el script (está más depurado), y las consideraciones. Si alguien quiere probar en su zona, a ver qué tal son los resultados, se lo agradecería.

Al respecto del tema que se trata en este hilo y en el que se abrió sobre el entorno de Nerja y tal y como se trató en hilos pasados creo que hay un problema del render que bajo mi punto de vista no debería tener presentes las cotas sin nombre y otro problema en que sin duda muchas de esas cotas no son picos o elevaciones propias de natural=peak.

Por otro lado, y aunque se recoja en la wiki que OSM no es un lugar para recoger todas estas cotas del terreno entiendo que hay gente que hace uso de ellas y las ha incluido en la base de datos espacial para ello por lo que no termin ode ver que debamos acabar con ellas pues no deja de ser una información relevante.

El uso de otra etiqueta sería lo propio, dejar solo la elevación sin más no termino de verlo.

Lo de pasar un script que depende de una información ráster me parece que se sale de la filosofía de OSM.

Saludos