Supongamos que tengo un área geográfica en forma de polígono compuesta por 5 puntos de latitud / longitud, como: -

51.314869, -0.497125
51.255586, 0.237066
51.684476, 0.244771
51.725210, -0.514339
51.314869, -0.497125

Luego hago una búsqueda de radio desde un solo punto (por ejemplo, 51.728215, -1.209971) de 30 millas. Quiero poder averiguar si esa búsqueda de radio abarca parte o toda esa área de polígono.

Soy consciente de que hay un tipo de datos geográficos disponible en SQL Server y, si es necesario, los datos se pueden cambiar a este si facilita la resolución

0
Matt 16 feb. 2018 a las 16:03

2 respuestas

La mejor respuesta

Lo siguiente debe hacer el truco:

declare @g geography =
    geography::STGeomFromText('POLYGON((
        51.314869 -0.497125 ,
        51.255586 0.237066  ,
        51.684476 0.244771  ,
        51.725210 -0.514339 ,
        51.314869 -0.497125 
    ))', 4326);

set @g=@g.ReorientObject();

declare @p geography =
    --geography::Point(-0.497125, 51.314869, 4326);
    geography::STPointFromText('POINT(51.314869 -0.497125)', 4326);

select @g.STIntersects(@p.STBuffer(48280.3))

A modo de explicación, estoy usando el tipo de datos geográficos como dicen sus intuiciones que debería ser posible. Primero construyo un polígono que representa tu área. La sintaxis del polígono real se llama WKT (es decir, texto conocido) y es un estándar en geoespacial.

El siguiente paso es reorientar su objeto. ¿Por qué? Un problema con los polígonos geográficos es que pueden definir el área interior al límite o exterior al mismo, según el orden en el que se definen los puntos. En este caso, el orden en el que los especificaste definió el exterior del área (es decir, todo el globo menos un cuadrilátero muy pequeño), así que asumí que querías el interior de esa área para su consideración (lo que resulta es necesario como verá a continuación).

A continuación, construyo un punto. Elegí una de las esquinas de su polígono por conveniencia. Tenga en cuenta que he proporcionado dos formas de hacerlo. Yo personalmente prefiero usar el método Point(), ¡pero tú también puedes usar WKT para hacerlo!

Por último, pruebo una intersección entre su polígono (@g) y un disco centrado en el punto que tiene un radio de 30 millas (o 48280,3 metros). La prueba devuelve un booleano. Hablando de la suposición sobre el orden de los puntos en el polígono, si define los puntos en el orden incorrecto, la prueba de intersección devolverá verdadera para las cosas que ni siquiera están cerca de su polígono (ya que define casi todo el mundo). A primera vista, pensaría que podría invertir la prueba (es decir, una negación lógica de la prueba STIntersects()), pero lo dejaré como un ejercicio para el lector por qué no es lo correcto. .

0
Ben Thul 16 feb. 2018 a las 15:58

Puede optimizar la búsqueda calculando un cuadro delimitador tomando el mínimo y el máximo de lat / lon. Luego, puede buscar la base de datos comparándola con la latitud / longitud mín. / Máx. Finalmente, puede filtrar los datos restantes comprobando si la latitud / longitud está dentro del polígono. Esto no es tan difícil de hacer si su polígono es convexo. Tienes que dividirlo en triángulos y comprobar si el lat / lon está dentro de uno de ellos.

0
Adder 16 feb. 2018 a las 13:10