Geometría SQL encuentra todos los puntos en un radio

Soy fluido en SQL pero nuevo en el uso de las características de SQL Geometry. Tengo lo que probablemente sea un problema muy básico para resolver, pero no he encontrado ningún recurso bueno en línea que explique cómo usar objects de geometry. (Technet es una manera pésima de aprender cosas nuevas …)

Tengo una colección de 2d puntos en un plano cartesiano, y estoy tratando de encontrar todos los puntos que están dentro de una colección de radios.

Creé y llené una tabla usando syntax como:

Actualizar [Cosas] establecer [Ubicación] = geometry :: Punto (@X, @Y, 0)

(@ X, @ Y son solo los valores xey, 0 es un número arbitrario compartido por todos los objects que permite establecer el filtrado si entiendo correctamente)

Aquí es donde me salgo de los Rails … ¿Trato de build algún tipo de colección de polígonos y consultas usando eso, o hay alguna manera simple de verificar la intersección de radios múltiples sin build un montón de polígonos circulares?

Adición: Si nadie tiene la respuesta a la pregunta de múltiples radios, ¿cuál es la solución de radio único?

ACTUALIZAR

Aquí hay algunos ejemplos que he trabajado, usando una database de estrellas imaginarias donde las estrellas se almacenan en una cuadrícula xy como puntos:

Selecciona todos los puntos en una caja:

DECLARE @polygon geometry = geometry::STGeomFromText('POLYGON((' + CAST(@MinX AS VARCHAR(10)) + ' ' + CAST(@MinY AS VARCHAR(10)) + ',' + CAST(@MaxX AS VARCHAR(10)) + ' ' + CAST(@MinY AS VARCHAR(10)) + ', ' + CAST(@MaxX AS VARCHAR(10)) + ' ' + CAST(@MaxY AS VARCHAR(10)) + ',' + CAST(@MinX AS VARCHAR(10)) + ' ' + CAST(@MaxY AS VARCHAR(10)) + ',' + CAST(@MinX AS VARCHAR(10)) + ' ' + CAST(@MinY AS VARCHAR(10)) + '))', 0); SELECT [Star].[Name] AS [StarName], [Star].[StarTypeId] AS [StarTypeId], FROM [Star] WHERE @polygon.STContains([Star].[Location]) = 1 

Usando esto como un patrón, puedes hacer todo tipo de cosas interesantes, como definir múltiples polígonos:

 WHERE @polygon1.STContains([Star].[Location]) = 1 OR @polygon2.STContains([Star].[Location]) = 1 OR @polygon3.STContains([Star].[Location]) = 1 

O verificando la distancia:

 WHERE [Star].[Location].STDistance(@polygon1) < @SomeDistance 

Declaración de inserción de muestra

 INSERT [Star] ( [Name], [StarTypeId], [Location], ) VALUES ( @GameId, @Name, @StarTypeId, GEOMETRY::Point(@LocationX, @LocationY, 0), ) 

Esta es una respuesta increíblemente tardía, pero quizás pueda arrojar algo de luz sobre una solución. El número de "ajuste" al que se refiere es un identificador de reference espacial o SRID. Para los cálculos lat / long, debería considerar establecer esto en 4326, lo que asegurará que los medidores se usen como una unidad de medida. También debería considerar cambiar a SqlGeography en lugar de SqlGeometry, pero continuaremos con SqlGeometry por el momento. Para configurar de forma masiva el SRID, puede actualizar su tabla de la siguiente manera:

 UPDATE [YourTable] SET [SpatialColumn] = GEOMETRY.STPointFromText([SpatialColumn].STAsText(), 4326); 

Para un solo radio, necesita crear un radio como un object espacial. Por ejemplo:

 DECLARE @radiusInMeters FLOAT = 1000; -- Set to a number in meters DECLARE @radius GEOMETRY = GEOMETRY::Point(@x, @y, 4326).STBuffer(@radiusInMeters); 

STBuffer () toma el punto espacial y crea un círculo (ahora un tipo de Polígono) a partir de él. A continuación, puede consultar su set de datos de la siguiente manera:

 SELECT * FROM [YourTable] WHERE [SpatialColumn].STIntersects(@radius); 

Lo anterior ahora usará cualquier índice espacial que haya creado en [SpatialColumn] en su plan de consulta.

También hay una opción más simple que funcionará (y aún usará un índice espacial). El método STDistance le permite hacer lo siguiente:

 DECLARE @radius GEOMETRY = GEOMETRY::Point(@x, @y, 4326); DECLARE @distance FLOAT = 1000; -- A distance in metres SELECT * FROM [YourTable] WHERE [SpatialColumn].STDistance(@radius) <= @distance; 

Por último, trabajando con una colección de radios. Tienes pocas opciones. El primero es ejecutar lo anterior para cada radio por turno, pero consideraría lo siguiente para hacerlo como uno:

 DECLARE #radiiCollection TABLE ( [RadiusInMetres] FLOAT, [Radius] GEOMETRY ) INSERT INTO #radiiCollection ([RadiusInMetres], [Radius]) VALUES (1000, GEOMETRY::Point(@xValue, @yValue, 4326).STBuffer(1000)); -- Repeat for other radii SELECT X.[Id], MIN(R.[RadiusInMetres]) AS [WithinRadiusDistance] FROM [YourTable] X JOIN #radiiCollection RC ON RC.[Radius].STIntersects(X.[SpatialColumn]) GROUP BY X.[IdColumn], R.[RadiusInMetres] DROP TABLE @radiiCollection; 

La final anterior no ha sido probada, pero estoy 99% seguro de que está por allí con una pequeña cantidad de ajustes como posibilidad. El ideal de tomar la distancia de radio mínimo en la selección es que si los radios múltiples provienen de una sola location, si un punto está dentro del primer radio, naturalmente estará dentro de todos los demás. Por lo tanto, duplicará el logging, pero al agrupar y luego seleccionar el mínimo, obtendrá solo uno (y el más cercano).

Espero que ayude, aunque 4 semanas después de haber hecho la pregunta. ¡Lo siento, no lo vi antes, si hubiera solo una label espacial para preguntas!

Claro, esto es posible. La cláusula individual where debería ser algo así como:

 DIM @Center AS Location -- Initialize the location here, you probably know better how to do that than I. Dim @Radius AS Decimal(10, 2) SELECT * from pointTable WHERE sqrt(square(@Center.STX-Location.STX)+square(@Center.STX-Location.STX)) > @Radius 

A continuación, puede acumular un montón de radios y puntos xy en una variable de tabla que se parece a:

 Dim @MyCircleTable AS Table(Geometry Circle) INSERT INTO @MyCircleTable (.........) 

Nota: No he expuesto esto a través de un comstackdor, pero esto es lo básico de una solución funcional.

La otra opción parece estar aquí: http://technet.microsoft.com/en-us/library/bb933904.aspx

Y hay una demostración de syntax aparentemente funcional aquí: http://social.msdn.microsoft.com/Forums/sqlserver/en-US/6e1d7af4-ecc2-4d82-b069-f2517c3276c2/slow-spatial-pnetworkingicates-stcontains-stintersects- stwithin-? forum = sqlspatial

La segunda publicación implica la syntax:

 SELECT Distinct pointTable.* from pointTable pt, circletable crcs WHERE crcs.geom.STContains(b.Location) = 1 
    Intereting Posts