SQL Server 2008 Spatial: trova un punto nel poligono

Sto usando i tipi di dati spaziali di SQL Server 2008. Ho una tabella con tutti gli stati (come poligoni) come tipo di dati GEOMETRIA. Ora voglio controllare se le coordinate di un punto (latitudini, longitudini) come tipo di dati GEOGRAFIA, si trovano all’interno di quello stato oppure no.

Non sono riuscito a trovare alcun esempio utilizzando i nuovi tipi di dati spaziali. Attualmente, ho una soluzione alternativa che è stata implementata molti anni fa, ma presenta alcuni inconvenienti.

Ho entrambi SQL Server 2008 e 2012. Se la nuova versione ha alcuni miglioramenti, posso iniziare a lavorarci anche io.

Grazie.

AGGIORNAMENTO 1:

Sto aggiungendo un esempio di codice per un po ‘più di chiarezza.

declare @s geometry --GeomCol is of this type too. declare @z geography --GeogCol is of this type too. select @s = GeomCol from AllStates where STATE_ABBR = 'NY' select @z = GeogCol from AllZipCodes where ZipCode = 10101 

Penso che il metodo geografico STIntersects () farà quello che vuoi:

 DECLARE @g geography; DECLARE @h geography; SET @g = geography::STGeomFromText('POLYGON((-122.358 47.653, -122.348 47.649, -122.348 47.658, -122.358 47.658, -122.358 47.653))', 4326); SET @h = geography::Point(47.653, -122.358, 4326) SELECT @g.STIntersects(@h) 

Se non è ansible modificare il tipo di dati per i poligoni memorizzati su GEOGRAPHY è ansible convertire la latitudine e la longitudine di input in GEOMETRY e utilizzare STContains o STIntersects rispetto al valore convertito.

 DECLARE @PointGeography GEOGRAPHY = geography::Point(43.365267, -80.971974, 4326) DECLARE @PointGeometry GEOMETRY = geometry::STGeomFromWKB(@PointGeography.STAsBinary(), 4326); SELECT @PolygonGeometry.STContains(@PointGeometry); 

Andando nella direzione opposta – provando a convertire i poligoni GEOMETRY in GEOGRPAHY – è sobject a errori e probabilmente fallirà dalla mia esperienza.

E nota che se provi a creare il punto GEOMETRY direttamente dai valori di latitudine e longitudine, allora STContains (o STIntersects ) non funzioneranno (cioè non daranno una corrispondenza quando dovrebbero).

 declare @g geometry set @g=geometry::STGeomFromText('POLYGON((-33.229869 -70.891988, -33.251124 -70.476616, -33.703094 -70.508045, -33.693931 -70.891052,-33.229869 -70.891988))',0) DECLARE @h geometry; SET @h = geometry::STGeomFromText('POINT(-33.3906300 -70.5725020)', 0); SELECT @g.STContains(@h); 
  1. Non dovresti mischiare Geometria e Geografia. La geometria è per gli PIANI PIATTI, la Geografia è per gli SPERIDI (come la Terra).
  2. “Dovresti” riconciliare gli SRID per far fronte a questo. Ogni SRID (ad es. 2913 = NZG2000) descrive una relazione di trasformazione. Ogni SRID può essere usato per mappare a / da una sfera uniforms, che è il modo in cui si ottiene da uno all’altro.
  3. Fino a quando non si arriva a uno “stesso” SRID su entrambi i valori, molti per le funzioni .STxXX restituiranno NULL (in entrambi i casi potrebbe essere il valore predefinito 0)
  4. Se non sono uguali, ma fingi di esserlo, potresti avere degli errori nei casi limite.
  5. Se si trascorre del tempo “precalc”, è ansible determinare i punti superiore / sinistro e inferiore / destro per i limiti di delimitazione coinvolti (e memorizzarli) e utilizzare tali valori negli indici per limitare i record da controllare. A meno che AT / L BT / L non possano sovrapporsi, il che significa che un semplice controllo numerico a 4 E nel tuo WHERE limiterà i tuoi controlli STWithin

Ecco un esempio che ho utilizzato in SRID 2193. Tutte le strade nel raggio di 3 km da un determinato punto e all’interno di una specifica zona scolastica

 DECLARE @g geometry SELECT @g = GEO2193 FROM dbo.schoolzones WHERE schoolID = 319 SELECT DD.full_road_name, MIN(convert(int, dd.address_number)), MAX(convert(int, dd.address_number)) FROM ( select A.* from dbo.[street-address] A WHERE (((A.Shape_X - 1566027.50505) * (A.Shape_X - 1566027.50505)) + ((A.Shape_Y - 5181211.81675) * (A.Shape_Y - 5181211.81675))) < 9250000 and a.shape_y > 5181076.1943481788 and a.shape_y < 5185097.2169968253 and a.shape_x < 1568020.2202472512 and a.shape_x > 1562740.328937705 and a.geo2193.STWithin(@g) = 1 ) DD GROUP BY DD.full_road_name ORDER BY DD.full_road_name