Esta é uma questão de geometria do SQL Server aparentemente simples que eu pensei que teria uma solução pronta para uso, mas não estou tendo sorte em encontrar uma.
Minha intenção é selecionar todos os registros em uma tabela que tenham polígonos aninhados (contidos) em um polígono maior de outra tabela. Eu esperava funções STWithin
e, STContains
como sendo as soluções necessárias, mas, infelizmente, ambas identificam apenas os polígonos internos dentro daqueles aninhados no polígono maior, não aqueles polígonos aninhados que estão tocando o limite do polígono maior. Veja a imagem por exemplo.
Uma opção alternativa que atendeu às minhas necessidades foi STIntersection
. O problema com esta função, no entanto, é que ela retorna apenas a coluna geométrica! Gostaria de obter o ID do registro. Alguém tem alguma sugestão de como isso pode ser feito?
STWithin
:
select a.bg10 from
gis.usa_10_block_group a
join gis.usa_10_mkt_definition b
on a.shape.STWithin(b.shape) = 1
where b.mktname = 'Loop'
STContains
:
select a.bg10 from
gis.usa_10_block_group a
join gis.usa_10_mkt_definition b
on b.shape.STContains(a.shape) = 1
where b.mktname = 'Loop'
STIntersection
:
select a.shape.STIntersection(b.shape)
from gis.usa_10_block_group a
join gis.usa_10_mkt_definition b
on a.shape.STIntersects(b.shape) = 1
where b.mktname = 'Loop'
Editar:
Uma sugestão era omitir STIntersection
e usar apenas STIntersects
o seguinte:
STIntersects
:
select a.bg10
from gis.usa_10_block_group a
join gis.usa_10_mkt_definition b
on a.shape.STIntersects(b.shape) = 1
where b.mktname = 'Loop'
O problema dessa abordagem é que STIntersects
parece selecionar todos os polígonos dentro ou fora e tocando o polígono maior, não apenas aqueles estritamente internos. Veja a imagem por exemplo.
fonte
STContains
ou outroSTWithin
. Não é realmente um truque agradável, mas você obtém os resultados desejados. A outra opção seria fazer as conexões STI com uma comparação da área de interseção e da área de polígonos.Respostas:
Em teoria, as consultas que você fez devem retornar os polígonos que você disse que não foram retornados. Isso me faz suspeitar que você possa estar enfrentando problemas de erro de ponto flutuante que o SQL Server possui com esses tipos de dados espaciais. Daí o meu comentário sobre o buffer do polígono delimitador com uma quantidade mínima.
Portanto, algo como o seguinte deve obter os resultados desejados.
Aqui está um exemplo rápido do comportamento esperado de alguns dos métodos espaciais.
Resultados
fonte
A consulta de interseção deve ficar assim (supondo que você queira que todos os registros retornem de 'a'):
Se você deseja apenas as áreas de a que cruzam b (ou seja, recortar a para b), adicione a seção STIntersection
Mas isso não dá a você os polígonos que estão dentro de b ainda ...
Esse tipo de polígono-em-polígono é muito irritante com os limites e sua conincidência - para serem 'Internos', os limites de a não podem ser compatíveis com os limites de b - o mesmo vale para 'Contém'.
Por essas definições, quantos de seus polígonos em a estão realmente dentro de b ...?
Então, você deseja armazenar em buffer b antes de selecionar polígonos em um que esteja dentro? Ou fazer um buffer negativo em um?
Não tenho certeza qual é a resposta exata aqui ...
fonte