Cambiar la "entrega" del polígono para SQL 2008 (orden de vértice de polígono inverso)


11

Tengo unos cientos de formas ( polygons y multipolygons), cada una de las cuales consta de decenas de miles de puntos que intento ingresar a SQL 2008.

Desafortunadamente, las formas que he tratado de importar son "diestras" (el perímetro de cada una se dibuja en el sentido de las agujas del reloj alrededor de los puntos que contiene). El servidor SQL asume formas "zurdas" (en sentido antihorario alrededor del interior), al menos para los geographytipos. Esto significa que SQL asume que estoy tratando de seleccionar toda la tierra, excepto mi forma. Algunas personas describen esto como formas "de adentro hacia afuera".

De MSDN , que frustrantemente no dice qué orientación de anillo se debe usar:

Si usamos el geographytipo de datos para almacenar la instancia espacial, debemos especificar la orientación del anillo y describir con precisión la ubicación de la instancia.

Si usa la orientación de anillo incorrecta en SQL 2008, se bloquea con el siguiente error (el énfasis es mío):

Se produjo un error de .NET Framework durante la ejecución de la rutina o geografía agregada definida por el usuario: Microsoft.SqlServer.Types.GLArgumentException: 24205: La entrada especificada no representa una instancia de geografía válida porque excede un solo hemisferio. Cada instancia de geografía debe caber dentro de un solo hemisferio. Una razón común para este error es que un polígono tiene una orientación de anillo incorrecta.

Importar las formas como en geometrylugar de geographyfunciona bien, pero me gustaría usar geographysi puedo.

En SQL 2012, parece bastante trivial solucionar este problema, pero estoy vinculado a 2008.

¿Cómo debo convertir las formas?


1
+1 gran pregunta ... ¿tiene un enlace donde dice que el servidor SQL asume formas zurdas?
Kirk Kuykendall

@ Kirk Gracias. Tengo problemas para encontrar la documentación oficial, pero puedo vincularme al MSDN donde dice que la "orientación del anillo" es importante (aunque no dice qué forma de usar). También pondré el error que se obtiene cuando se bloquea.
Michael - ¿Dónde está Clay Shirky?

Respuestas:


14

El blog de Spatial Ed tuvo una solución concisa. Aquí hay algunos SQL que demuestran la transformación:

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

Y un extracto de la publicación de Ed:

La clave de este comportamiento es el STUnion()método. Dado que este es un método basado en OGC, que trabaja en toda la geometría para una característica dada, obliga a los polígonos a la orientación requerida para el método, que resulta ser el que se usa para el Geographytipo [...]. Este método ilustrado es bastante eficiente, manteniendo una sobrecarga pequeña [...].


2
En SQL Server 2008 r2, también tuve que poner .MakeValid () en el interior de STUnion () para que esto funcione: .STUnion (@ geom.MakeValid (). STStartPoint ())
Chris Smith

@Smitty Eso tiene sentido para los casos en que SQL no puede determinar el punto de partida. ¿Tal vez si la forma se dobla sobre sí misma u otras circunstancias extrañas?
Michael - ¿Dónde está Clay Shirky?

Sí, en mi caso, la forma es extraña y se superpone.
Chris Smith

0

En> = SQL Server 2012, el método ReorientObject () debería lograr esto. Para <SQL Server 2012, a continuación hay un método alternativo.

Para una geografía SQL existente @g, el código siguiente extraerá los puntos y volverá a crear un polígono con puntos (vértices) en orden inverso:
(NOTA 1: funciona para polígonos simples, no para multipolígonos o polígonos con anillos / centroides)
(NOTA 2: utilizando el 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); 

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.