Come inserire un poligono GeoJSON in una tabella PostGIS?


34

Devo inserire un poligono da GeoJSON alla mia tabella PostGIS. Ecco come appare la query 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]
            ]
        }'
    )
)

Sfortunatamente, ricevo un messaggio di errore.

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

GeoJSON è già nel giusto sistema di riferimento. Ma questo non è specificato. Come posso specificare SRID in GeoJSON? Che aspetto deve avere GeoJSON?

Aggiornamento: Quando ho avvolgere la geometria creato da ST_GeomFromGeoJSONcon ST_SetSRID(..., 3857)che getta un altro errore. A mio avviso, non sembra che la geometria abbia una dimensione Z.

ERROR:  Geometry has Z dimension but column does not

Penso che devi specificare che la tabella ha srid: 4326, sembra che la tua tabella abbia srid: 3857 ma il tuo geojson ha long / latitude (cioè srid: 4326 o WGS84)
Gery

Voglio usare 3857. Come deve essere allora il GeoJSON?
danijar,

Risposte:


33

Dando un'occhiata al codice sorgente di PostGIS ho scoperto come analizza gli SRID. Ecco il modo corretto di specificare l'SRID in GeoJSON.

La specifica GeoJSON afferma che le coordinate di un poligono sono una matrice di stringhe di linea. Pertanto ho dovuto avvolgerli con staffe aggiuntive.

{
    "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"}}
}

16

Ci sono un paio di problemi con il tuo JSON.

  1. Innanzitutto, le coordinate dovrebbero essere una matrice di matrici.
  2. In secondo luogo, guardando le coordinate, sembra che i valori siano Latlong in un sistema di coordinate geografiche, molto probabilmente EPSG: 4326. Che quindi deve essere trasformato in EPSG: 3857.

Dopo aver corretto queste due cose, è possibile inserire la riga utilizzando la seguente query 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));

Se il problema persiste (ovvero se stai ancora riscontrando l'errore con Z diemsnion), aggiorna la domanda con la versione PostGis e la dichiarazione Crea della tabella.


Perché pensi che le coordinate non siano in EPSG: 3857?
danijar,

3
Perché le unità di EPSG: 3857 sono (pseudo) metri e l'origine è nell'Oceano Atlantico. Non avresti 6 precisione decimale con i contatori e questi dati si troverebbero nell'Oceano Atlantico vicino alla costa dell'Africa.
Devdatta Tengshe,

Le coordinate provengono dall'input su una mappa e hanno molti decimali. Per i test ho disegnato un'area nell'Oceano Atlantico vicino all'Africa. Ma grazie a te posso migliorare la mappa per arrotondare le coordinate a metri interi.
danijar,

@danijar: allora va tutto bene. Se queste coordinate fossero in EPSG: 4326, si troverebbero sugli stati orientali degli Stati Uniti.
Devdatta Tengshe,

5

il tuo geojson deve invece avere valori UTM, puoi trasformarlo con Proj o altri strumenti online, ma puoi farlo facilmente e direttamente con PostGis prima di inserirlo nella tua tabella, prova questo (non testato):

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));

Quindi suggerisci di convertire l'SRID su 4326 in 3857? Quindi ho potuto provare direttamente ST_Transform (ST_SetSRID (..., 4326), 3857), no? Perché questo passaggio di trasformazione aggiuntivo sarebbe necessario?
danijar,

Penso che dovresti testare quello che stai chiedendo, probabilmente quello che suggerisci è l'unico passo di cui hai bisogno, provalo e pubblica quello che hai
Gery

Questo è quello che ottengo. 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]
            ]
        }'
    )
)

"" "mancante


4
Potresti aggiungere più contesto a questa risposta e spiegare come risponde alla domanda di OP, ed è diverso dalle risposte esistenti
Devdatta Tengshe

Onestamente, il JSON non deve essere una stringa, non è una stringa nella questione e non è una stringa in almeno una delle risposte. Questa risposta potrebbe indicare l'ovvio, ma non è necessariamente ovvio per tutti, quindi merita un po 'di credito.
Forbesmyester,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.