PostGIS Geometry Query restituisce "Errore: operazione su geometrie SRID miste" solo per determinati valori


17

Ho una tabella PostGIS con due colonne geometriche, entrambe definite con SRID 4326. Posso inserirla nella tabella senza problemi, usando la seguente INSERTistruzione (dove lnge latsono i valori passati a livello di programmazione):

INSERT INTO pad_meta (
    uuid, created, updated, name, origin, radius, area, expiry, creator
) VALUES (
    $1, now(), now(), $2, ST_GeomFromText('POINT(lng, lat)', 4326), $3, 
    ST_Buffer(ST_GeomFromText('POINT(lng, lat)', 4326), $4), $5, $6
)

Ma quando chiedo un'intersezione usando ST_Intersects, a seconda del valore del punto che ottengo ERROR: Operation on mixed SRID geometries.

Ad esempio, questa query funziona:

SELECT * FROM pad_meta where ST_Intersects(
    'POINT(-122.334172173172 46.602634395263560)'::geometry, area::geometry 
) ORDER BY created DESC;

E questo errore fuori:

SELECT * FROM pad_meta where ST_Intersects(
    'POINT(-122.334172173172 47.602634395263560)'::geometry, area::geometry 
) ORDER BY created DESC;

Si noti che sono query identiche ad eccezione del valore della longitudine. Ho sperimentato valori diversi, ma non ho identificato un chiaro punto di transizione tra le query che funzionano e non lo fanno.

Penso di aver sostanzialmente frainteso qualcosa. Per il momento, ho risolto / corretto / risolto il problema riformattando la query da utilizzare ST_GeomFromTexte specificando esplicitamente l'SRID:

SELECT * FROM pad_meta where ST_Intersects(
    ST_GeomFromText('POINT(-122.334172173172 47.602634395263560)', 4326), area
) ORDER BY created DESC;

Ma sinceramente non capisco davvero quale sia la differenza, o se questa sia veramente la "soluzione".

La mia domanda è: perché visualizzo un errore solo per valori specifici e qual è il modo corretto di formattare questa query?

Ecco la mia definizione di tabella per riferimento:

CREATE TABLE IF NOT EXISTS pad_meta (
  uuid CHAR(32),
  created TIMESTAMP,
  updated TIMESTAMP,
  name VARCHAR(128),
  origin GEOMETRY(Point, 4326),
  radius INTEGER,
  area GEOMETRY(Polygon, 4326),
  expiry TIMESTAMP,
  creator CHAR(32),
  PRIMARY KEY (uuid)
);

Ho anche verificato che esiste un solo tipo di SRID nelle geometrie_colonne:

SELECT f_table_name, f_geometry_column, srid FROM geometry_columns;
f_table_name | f_geometry_column | srid
--------------+-------------------+------
 pad_meta     | origin            | 4326
 pad_meta     | area              | 4326

Aiuto / consiglio apprezzato. Grazie! (Nota: ho anche visto questa domanda , ma poiché sto già definendo esplicitamente i miei SRID geometrici durante l'inserimento nella tabella, sembra che non sia ciò che sta accadendo.)

Risposte:


24

Quando si specifica una geometria senza SRID, in realtà è 0(o -1per la versione <2):

SELECT ST_SRID('POINT(-122.334172173172 46.602634395263560)'::geometry);
 st_srid
---------
       0

Quindi quando usi questa geometria con un'altra con SRID = 4326, sta mescolando 0e 4326. Questo di solito è un errore utile, se i riferimenti spaziali sono veramente diversi. Nel tuo caso, gli SRID sono gli stessi, ma non hai codificato l'SRID nel punto di query. Pertanto, per correggere la query, specificare sempre lo stesso SRID per il punto di query e non verranno più mescolati.

Come nota a margine, il geographytipo ha un SRID predefinito di 4326 (WGS 84), come mostrato qui:

SELECT ST_SRID('POINT(-122.334172173172 46.602634395263560)'::geography::geometry);
 st_srid
---------
    4326

Pertanto, se si utilizzano geographytipi anziché geometrytipi, non è necessario specificare l'SRID (a meno che non si desideri un SRID diverso per un ellissoide alternativo per Marte o altro).


Per quanto riguarda il motivo per cui una query ha un errore e l'altra no, per ST_Intersectsprima cosa esegue una &&ricerca nel riquadro di delimitazione, che è veloce e non si preoccupa degli SRID. Non verranno generati messaggi di errore SRID misti se i rettangoli non si intersecano. Ma se si intersecano, il secondo filtro è _ST_Intersects, che è più preciso e controlla i due SRID per assicurarsi che corrispondano e genera un errore se vengono mescolati. Per esempio:

WITH pad_meta AS (
    SELECT 'SRID=4326;POLYGON((-124 50, -124 47, -121 50, -124 50))'::geometry AS area)

SELECT * FROM pad_meta where ST_Intersects(
    'POINT(-122.334172173172 46.602634395263560)'::geometry, area::geometry 
);

non ha alcun riquadro di delimitazione intersecante e bypass _ST_Intersects. Ma POINT(-122.334172173172 47.602634395263560)genererà l'errore perché le finestre di delimitazione si sovrappongono (anche se le geometrie non si intersecano effettivamente).

Tuttavia, con le stesse geometrie e filtro diverso:

WITH pad_meta AS (
    SELECT 'SRID=4326;POLYGON((-124 50, -124 47, -121 50, -124 50))'::geometry AS area)

SELECT * FROM pad_meta where _ST_Intersects(
    'POINT(-122.334172173172 46.602634395263560)'::geometry, area::geometry 
);

genera un errore SRID misto, poiché i box di delimitazione non vengono considerati.


Wow grazie. ha senso. prefissare una query con SRID=4326(come hai fatto sopra) il modo giusto di impostare l'SRID per il resto dell'istruzione? (al contrario di usare ST_GeomFromTextsemplicemente perché non sapevo come specificare il SRID ...?) esiste un modo per impostare un SRID predefinito per le query? sembra piuttosto prolisso impostarlo esplicitamente ogni volta. ancora grazie!
jessykate,

1
Ho aggiornato la mia risposta per suggerire di utilizzare geographytipi, che sono sempre 4326. Inoltre, ci sono diversi modi per specificare l'SRID.
Mike T,

0

Un paio di osservazioni che possono essere d'aiuto: una, Point(Double, Double)è una funzione PostgreSQL nativa che stai costringendo a un tipo di dati PostGIS. ST_MakePoint(double x, double y)creerà la geometria corretta. Inoltre, nella tua domanda sembri riferirti al secondo argomento come longitudine. L'ordine corretto è x, y, che corrisponde a Longitude, Latitude. Ottenere quelli invertiti può restituire risultati imprevisti senza generare eccezioni.

Niente di tutto ciò spiega davvero perché il tuo primo esempio funzioni a volte e non altri, ma spero che questo ti aiuti a creare buone domande.

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.