Modifica la "mano" del poligono per SQL 2008 (ordine vertice poligonale inverso)


11

Ho qualche centinaio di forme ( polygonS e multipolygonI) Ogni composto da decine di migliaia di punti che sto cercando di entrare in SQL 2008.

Sfortunatamente, le forme che ho cercato di importare sono "destrorse" (il perimetro di ognuna è disegnato in senso orario attorno ai punti che contiene). Il server SQL assume forme "mancine" (in senso antiorario all'interno), almeno per i geographytipi. Ciò significa che SQL presuppone che sto cercando di selezionare l'intera terra tranne la mia forma. Alcune persone lo descrivono come forme "dentro e fuori".

Da MSDN , che frustrantemente non dice quale orientamento dell'anello si debba usare:

Se utilizziamo il geographytipo di dati per memorizzare l'istanza spaziale, dobbiamo specificare l'orientamento dell'anello e descrivere accuratamente la posizione dell'istanza.

Se si utilizza l'orientamento dell'anello errato in SQL 2008, si arresta in modo anomalo con il seguente errore (sottolineatura mia):

Si è verificato un errore .NET Framework durante l'esecuzione della routine definita dall'utente o della "geografia" aggregata: Microsoft.SqlServer.Types.GLArgumentException: 24205: l'input specificato non rappresenta un'istanza geografica valida perché supera un singolo emisfero. Ogni istanza geografica deve rientrare in un singolo emisfero. Un motivo comune per questo errore è che un poligono ha l'orientamento dell'anello errato.

Importare le forme come geometryinvece geographyfunziona bene, ma mi piacerebbe usare geographyse posso.

In SQL 2012, sembra abbastanza banale risolvere questo problema, ma sono legato al 2008.

Come devo convertire le forme?


1
+1 ottima domanda ... hai un link in cui si dice che il server SQL assume forme per mancini?
Kirk Kuykendall,

@Kirk Grazie. Ho problemi a trovare la documentazione ufficiale, ma posso collegarmi a MSDN dove dice che "l'orientamento dell'anello" è importante (anche se non dice in che modo utilizzare). Inserirò anche l'errore che si ottiene quando si blocca.
Michael - Dov'è Clay Shirky il

Risposte:


14

Il blog di Spatial Ed aveva una soluzione concisa. Ecco alcuni SQL che dimostrano la trasformazione:

DECLARE @geom GEOMETRY = 'POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))';
DECLARE @geog GEOGRAPHY = @geom.MakeValid().STUnion(@geom.STStartPoint()).STAsText()

E un estratto dal post di Ed:

La chiave di questo comportamento è il STUnion()metodo. Poiché si tratta di un metodo basato su OGC, che lavora sull'intera geometria per una determinata funzione, forza i poligoni nell'orientamento richiesto per il metodo, che risulta essere quello utilizzato per il Geographytipo [...]. Questo metodo illustrato è abbastanza efficiente, mantenendo le spese generali [...] piccole.


2
Su SQL Server 2008 r2, ho dovuto mettere .MakeValid () all'interno di STUnion () e farlo funzionare: .STUnion (@ geom.MakeValid (). STStartPoint ())
Chris Smith

@Smitty Questo ha senso per i casi in cui SQL non può altrimenti determinare il punto di partenza. Forse se la forma raddoppia su se stessa o in altre circostanze strane?
Michael - Dov'è Clay Shirky il

Sì, nelle mie circostanze la forma è bizzarra e si sovrappone.
Chris Smith,

0

In> = SQL Server 2012, il metodo ReorientObject () dovrebbe ottenere questo risultato. Per <SQL Server 2012, di seguito è riportato un metodo alternativo.

Per una geografia SQL esistente @g, il codice seguente estrae i punti e ricrea un poligono con punti (vertici) in ordine inverso:
(NOTA 1: funziona per poligoni semplici, non per multipoligoni o poligoni con anelli / centroidi)
(NOTA 2: utilizzo del sistema di coordinate SRID 4326 (WGS 84))

--For existing geography @g
DECLARE @GeometryText varchar(max), @ReversedPolygon geography
DECLARE @GeometryType varchar(20) = 'POLYGON', @Count int
SET @Count = @g.STNumPoints()
WHILE @Count > 0
BEGIN
    SET @GeometryText = @GeometryText + CONVERT(varchar(30),CONVERT(decimal(12,8),@g.STPointN(@Count).Long)) + ' ' + CONVERT(varchar(30),CONVERT(decimal(12,8),@g.STPointN(@Count).Lat))
    SET @Count = @Count - 1
    IF @Count > 0 SET @GeometryText = @GeometryText + ','
END
SET @GeometryText = @GeometryType +'((' + @GeometryText + '))'
SET @ReversedPolygon = geography::STGeomFromText(@GeometryText, 4326); 

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.