2012-03-16 24 views
6

En mi SQL Server (2008 R2) en Azure, hay una tabla que contiene una gran cantidad de factores geográficos Points (latitud/longitud):Crear polígono de la geografía de puntos en T-SQL

CREATE TABLE MyPoints 
(
    Region uniqueidentifier NOT NULL, 
    Number int NOT NULL, 
    Position geography NOT NULL, 
    CONSTRAINT PK_MyPoints PRIMARY KEY(Region, Number) 
) 

Ahora quiero crear a Polygon a partir de estos puntos para determinar, cuáles de mis tiendas están ubicadas en el área definida por los puntos.

¿Existe una manera nativa y rápida de construir un polígono a partir de los puntos dados en T-SQL? The solutions I found están utilizando los métodos STGeomFromText/STGeomFomWKB para crear un polígono, lo que me parece muy engorroso y lento.

Algo así como:

SET @POLY = geometry::STPolyFromPoints(SELECT Position FROM MyPoints) 

Respuesta

3

Por lo que yo sé, no hay ninguna función nativa que tiene una tabla como parámetro y que convierte a un polígono.

Lo mejor es combinar una función escalar definida por el usuario para concatenar una columna de resultados en una sola secuencia separada por comas con STPolyFromText que ya ha leído.

UDF to Concatenate Column to CSV String

MSDN - STPolyFromText

+1

Estamos utilizando una función que concatena los puntos en su representación binaria y llaman 'STGeomFromWKB' en esa cadena. Es lo suficientemente rápido para nuestro propósito, pero sigue siendo feo. – Gene

+0

Otra sugerencia sería escribir su propia .NET CLR User Defined Function que sí toma un parámetro de tabla (columna de Geo Points reales) y devuelve una Geometría. No he trabajado aún, pero el SqlGeometryBuilder parece prometedor: http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.types.sqlgeometrybuilder.aspx –

+0

AFAIK no admite funciones CLR en SQL Azure Pensé en esa posibilidad, también. – Gene

3

Suponiendo que tenemos una mesa llena de largos y dorsales ordenados en esta tabla:

CREATE TABLE [dbo].[LongAndLats](
    [Longitude] [decimal](9, 6) NULL, 
    [Latitude] [decimal](9, 6) NULL, 
    [SortOrder] [int] NULL 
    ) 

Esto convertirá esos puntos en un polígono:

DECLARE @BuildString NVARCHAR(MAX) 
SELECT @BuildString = COALESCE(@BuildString + ',', '') + CAST([Longitude] AS NVARCHAR(50)) + ' ' + CAST([Latitude] AS NVARCHAR(50)) 
FROM dbo.LongAndLats 
ORDER BY SortOrder 

SET @BuildString = 'POLYGON((' + @BuildString + '))'; 
DECLARE @PolygonFromPoints geography = geography::STPolyFromText(@BuildString, 4326); 
SELECT @PolygonFromPoints 

Algunas notas:

  • El polígono debe cerrarse. es decir. el primero y el último punto deberían ser iguales.
  • Debe tener un mínimo de 4 puntos.
  • El orden de los puntos es importante. Debe seguir la "regla de la mano izquierda/pie" (las áreas que se encuentran a la izquierda de la línea trazada entre los puntos se consideran dentro del Polígono)
+0

Me gustaría saber cómo hacer la parte de clasificación real ya que la solución anterior es excelente. Mi cuelgue es cómo ordenar los puntos en "regla de mano izquierda/pie". Estoy terminando con un polígono que se superpone sobre sí mismo porque mi ordenamiento lat/long no es correcto. –

+0

ejemplo: 'DECLARE @geom GEOMETRY = ' POLYGON (( -116).77953600883484 \t 33,103710174560547 , -117,03299999237061 \t 32,547900199890137 , -117.11846709251404 \t 33,469111442565918 , -117,38499999046326 \t 33,202700138092041 , -117,38700008392334 \t 33,206999778747559 , -117,39700007438660 \t 33,209300041198730 , -116,77953600883484 \t 33,103710174560547 ))' DECLARE @geog GEOGRAFÍA = @ geom.MakeValid(). STUnion (@ geom.MakeValid(). STStartPoint()). STAsText() select @ geog' –

+0

@Smitty, el orden debe ser conocido antes de insertar en la tabla '[dbo]. [LongAndLats]'. No conozco ninguna forma de determinar un orden de clasificación confiable que no se intersecte si los puntos no están ordenados, no creo que sea posible porque podría haber n posibles ordenamientos. – g2server

Cuestiones relacionadas