¿Cómo insertar un polígono GeoJSON en una tabla PostGIS?

34

Necesito insertar un polígono de GeoJSON en mi tabla PostGIS. Así es como se ve la consulta SQL.

INSERT INTO tablename (name, polygon)
VALUES (
    'Name',
    ST_GeomFromGeoJSON(
        '{
            "type": "Polygon",
            "coordinates": [
                [7.734375,51.835777520452],
                [3.8671875,48.341646172375],
                [7.20703125,43.580390855608],
                [18.6328125,43.834526782237],
                [17.9296875,50.289339253292],
                [13.7109375,54.059387886624],
                [7.734375,51.835777520452]
            ]
        }'
    )
)

Lamentablemente, recibo un mensaje de error.

ERROR:  Geometry SRID (0) does not match column SRID (3857)

GeoJSON ya está en el sistema de referencia correcto. Pero esto no está especificado. ¿Cómo especifico el SRID en GeoJSON? ¿Cómo debe ser el GeoJSON?

Actualización: Cuando envuelvo la geometría creada por ST_GeomFromGeoJSONla ST_SetSRID(..., 3857)lanza otro error. En mi opinión, no parece que la geometría tenga una dimensión Z.

ERROR:  Geometry has Z dimension but column does not
danijar
fuente
Creo que debe especificar que la tabla tiene srid: 4326, parece que su tabla tiene srid: 3857 pero su geojson tiene largo / latitud (es decir, srid: 4326 o WGS84)
Gery
Quiero usar 3857. ¿Cómo debe verse entonces GeoJSON?
danijar

Respuestas:

33

Echando un vistazo al código fuente de PostGIS, descubrí cómo analiza los SRID. Aquí está la forma correcta de especificar el SRID en GeoJSON.

La especificación GeoJSON dice que las coordenadas de un polígono son una matriz de cadenas de líneas. Por lo tanto, tuve que envolverlos con corchetes adicionales.

{
    "type":"Polygon",
    "coordinates":
    [
        [
            [-91.23046875,45.460130637921],
            [-79.8046875,49.837982453085],
            [-69.08203125,43.452918893555],
            [-88.2421875,32.694865977875],
            [-91.23046875,45.460130637921]
        ]
    ],
    "crs":{"type":"name","properties":{"name":"EPSG:3857"}}
}
danijar
fuente
16

Hay un par de problemas con su JSON.

  1. En primer lugar, las coordenadas deben ser una matriz de matrices.
  2. En segundo lugar, mirando las coordenadas, parece que los valores son Latlong en un sistema de coordenadas geográficas, muy probablemente EPSG: 4326. Eso luego necesita ser transformado a EPSG: 3857.

Una vez que corrija estas dos cosas, puede insertar la fila, utilizando la siguiente consulta SQL:

INSERT INTO "Parcels"("Name", the_geom)
    VALUES ('Corrected_Shape', 
    ST_TRANSFORM(ST_GeomFromGeoJSON('{
    "type":"Polygon",
    "coordinates":[[
        [-91.23046875,45.460130637921],
        [-79.8046875,49.837982453085],
        [-69.08203125,43.452918893555],
        [-88.2421875,32.694865977875],
        [-91.23046875,45.460130637921]
    ]],
    "crs":{"type":"name","properties":{"name":"EPSG:4326"}}
}'),3857));

Si esto no funciona (es decir, aún recibe el error con Z diemsnion), actualice la pregunta con la versión PostGis y la Declaración de creación de su tabla.

Devdatta Tengshe
fuente
¿Por qué crees que las coordenadas no están en EPSG: 3857?
danijar
3
Porque las unidades de EPSG: 3857 son (pseudo) metros, y el origen está en el Océano Atlántico. No tendría una precisión de 6 decimales con los medidores, y estos datos estarían en el Océano Atlántico cerca de la costa de África.
Devdatta Tengshe
Las coordenadas son de entrada en un mapa y tienen muchos decimales. Para las pruebas dibujé un área en el Océano Atlántico cerca de África. Pero gracias a ti puedo mejorar el mapa para redondear las coordenadas a metros enteros.
danijar
@danijar: Entonces está bien. Si estas coordenadas estuvieran en EPSG: 4326, se ubicaría sobre los estados orientales de los EE. UU.
Devdatta Tengshe
5

su geojson debe tener valores UTM en su lugar, puede transformar eso con Proj u otras herramientas en línea, pero puede hacerlo fácil y directamente con postgis antes de insertarlo en su tabla, intente esto (sin probar):

SELECT ST_AsText(ST_Transform(ST_GeomFromGeoJSON
    (
        {
            "type":"Polygon",
            "coordinates":[
                [7.734375,51.835777520452],
                [3.8671875,48.341646172375],
                [7.20703125,43.580390855608],
                [18.6328125,43.834526782237],
                [17.9296875,50.289339253292],
                [13.7109375,54.059387886624],
                [7.734375,51.835777520452]
            ]
        }
    ),4326),3857));
Gery
fuente
¿Entonces sugiere convertir el SRID sobre 4326 a 3857? Entonces podría probar directamente ST_Transform (ST_SetSRID (..., 4326), 3857), ¿no? ¿Por qué sería necesario este paso de transformación adicional?
danijar
Creo que deberías probar lo que estás preguntando, probablemente lo que sugieres es el único paso que necesitas, pruébalo y publica lo que tienes
Gery
Esto es lo que obtengo. ERROR: transform: couldn't project point (9.25253e-302 6.08985e+159 1.18576e-322): latitude or longitude exceeded limits (-14)
danijar
3
INSERT INTO tablename (name, polygon)
VALUES
(
    'Name',
    ST_GeomFromGeoJSON
    (
        '{
            "type":"Polygon",
            "coordinates":[
                [7.734375,51.835777520452],
                [3.8671875,48.341646172375],
                [7.20703125,43.580390855608],
                [18.6328125,43.834526782237],
                [17.9296875,50.289339253292],
                [13.7109375,54.059387886624],
                [7.734375,51.835777520452]
            ]
        }'
    )
)

desaparecido "'"

Zakaria Jaddy
fuente
44
¿Podría agregar más contexto a esta respuesta y explicar cómo responde la pregunta de OP y es diferente de las respuestas existentes
Devdatta Tengshe
Honestamente, el JSON no tiene por qué ser una cadena, no es una cadena en la pregunta y no es una cadena en al menos una de las respuestas. Esta respuesta puede señalar lo obvio, pero no es necesariamente obvio para todos, por lo que merece algo de crédito.
Forbesmyester