Alterar a “mão” do polígono para o SQL 2008 (ordem do vértice do polígono reverso)


11

Eu tenho algumas centenas de formas ( polygons e multipolygons) cada uma composta por dezenas de milhares de pontos que eu estou tentando entrar em SQL Server 2008.

Infelizmente, as formas que tentei importar são "destras" (o perímetro de cada uma é desenhado no sentido horário em torno dos pontos que ela contém). O servidor SQL assume formas "canhotas" (anti-horário no interior), pelo menos para os geographytipos. Isso significa que o SQL assume que estou tentando selecionar a terra inteira, exceto a minha forma. Algumas pessoas descrevem isso como formas "de dentro para fora".

Do MSDN , que frustrantemente não diz qual orientação de toque usar:

Se usarmos o geographytipo de dados para armazenar a instância espacial, devemos especificar a orientação do anel e descrever com precisão o local da instância.

Se você usar a orientação de toque incorreta no SQL 2008, ela trava com o seguinte erro (ênfase minha):

Ocorreu um erro do .NET Framework durante a execução da rotina definida pelo usuário ou da "geografia" agregada: Microsoft.SqlServer.Types.GLArgumentException: 24205: A entrada especificada não representa uma instância geográfica válida porque excede um único hemisfério. Cada instância geográfica deve caber dentro de um único hemisfério. Um motivo comum para esse erro é que um polígono tem a orientação incorreta do toque.

Importar as formas como em geometryvez de geographyfuncionar bem, mas eu gostaria de usar geographyse puder.

No SQL 2012, parece bastante trivial corrigir esse problema, mas estou vinculado a 2008.

Como devo converter as formas?


1
+1 ótima pergunta ... você tem um link onde diz que o servidor SQL assume formas canhotas?
22413 Kirk Kuykendall

@Kirk Obrigado. Estou com problemas para encontrar a documentação oficial, mas posso vincular ao MSDN onde diz que a "orientação de toque" é importante (embora não diga qual caminho usar). Também colocarei o erro que ocorre quando falha.
Michael - Onde está Clay Shirky

Respostas:


14

O blog do Spatial Ed tinha uma solução concisa. Aqui está algum SQL demonstrando a transformação:

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

E um trecho do post de Ed:

A chave para esse comportamento é o STUnion()método Como este é um método baseado em OGC, trabalhando em toda a geometria de um determinado recurso, força os polígonos na orientação necessária para o método - que é o que é usado para o Geographytipo [...]. Este método ilustrado é bastante eficiente, mantendo a sobrecarga pequena [...].


2
No SQL Server 2008 r2, tive que colocar .MakeValid () na parte interna do STUnion () para que isso funcionasse: .STUnion (@ geom.MakeValid (). STStartPoint ())
Chris Smith

@ Smitty Isso faz sentido para casos em que o SQL não pode determinar o ponto de partida. Talvez se a forma dobrar sobre si mesma ou outras circunstâncias estranhas?
Michael - Onde está Clay Shirky

Sim, na minha circunstância, a forma é esquisita e se sobrepõe.
21716 Chris Smith

0

Em> = SQL Server 2012, o método ReorientObject () deve fazer isso. Para <SQL Server 2012, abaixo está um método alternativo.

Para uma geografia SQL existente @g, o código abaixo extrai os pontos e recria um polígono com pontos (vértices) na ordem inversa:
(NOTA 1: funciona para polígonos simples, não para multipolígonos ou polígonos com anéis / centróides)
(NOTA 2: usando o sistema de coordenadas 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); 

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.