quarta-feira, 26 de agosto de 2009

Sql Server 2008 e o sistema de uma projeção só.

Boa noite pessoal,
Estava trabalhando em alguns assuntos no Sql Server 2008 e até aí tudo bem. Tinha alguns dados em outro banco de dados, representativos de pontos. Tudo UTM SAD69. O banco do GIS em Lat/Long SAD69.


As tabelas, eram mais ou menos assim:
ID
X
Y
Z
Sistema_coordenada


Sempre com diversos pontos e diversos sistemas de coordenadas "misturados". Até aí tudo bem.


Bem, a idéia era montar uma visão no banco de dados, registar a parada com o ArcSDE, e disponibilizar os dados que eu queria em tempo real para os usuários do GIS, inclusive eu.


Liguei em uma certa empresa que comercializa um certo software, no suporte. Expliquei a situação, perguntei se o rapaz ou alguém lá saberia de uma solução para realizar o idealizado. De forma alguma (eu) estava viajando na maionese, pela minha experiência (que não é muita) com o PostGIS, sabia que era fazível.


O certo indivíduo que me atendeu, deve ter feito uma cara do outro lado de "What the hell?" sugeriu que eu jogasse minha tabela no ArcMap e rodasse um XY para plotar os dados. Valeu pela super dica amigão. Se você ler isto e lembrar de mim sabe que existe uma forma!


Mas vamos lá. O PostGIS, que é um tanto mais avançado que o Sql Server 2008 nesses quesitos, bastaria o seguinte para criar uma visão espacial (com um ponto de verdade, e não um par de coordenadas) e transformar a parada para o datum que eu queria:

CREATE OR REPLACE VIEW view_foo AS
SELECT ST_Transform(ST_Point(X,Y),4618), coluna1, coluna2 from foo;


Bem, simples né? Acontece que o SQL Server 2008 NÃO POSSUI funções nativas para conversão de coordenadas/projeção de um sistema para outro.


Um camarada do trabalho, Danilo, me falou que já havia visto no CodePlex, um site com um repositório de código da Microsoft, um projeto que realizava o serviço. Bem, o projeto, Sql Spatial Tools, tem muita utilidade e outras funções, como agregador de geometrias, mas as funções de conversão de coordenadas estava furada. Pelo menos a que nós precisávamos usar.


Lembrei que o PostGIS, que também não tem esta capacidade nativa, mas é fornecida pela Proj4, e talvez poderíamos utilizar a Proj4. Mais uma busca no Codeplex e achamos a ProjNET, uma adaptação da Proj4 (acho que é escrita em C) para .NET, em C#.


Utilizamos o modelo da Sql Spatial Tools para registrar bibliotecas externas (muito top, parabéns Sql Server, muito tetinha de fazer) e para expor uma única função que criamos para o Sql Server. A ProjNET, ao contrário da Sql Spatial Tools, realmente converte as coordenadas.


Dicas
  1. Sempre olhe no Codeplex.
  2. Para registrar uma dll externa (dentro do Sql Server) utilize (isto é código SQL): CREATE ASSEMBLY ProjNet 'caminhoParaDll'
  3. Para registrar uma função: CREATE FUNCTION nomeFuncao (parametros) returns tipoRetorno AS external ProjNet.Namespace.Funcao
  4. É só.
No final nossa idéia ficou similar a do PostGIS, and it works. Resultado: utilizamos os dados que temos, sem a necessidade de administrar/atualizar FeatureClasses e realizar tarefas tediosas de Add XY data-Project Data e propensas à erros. E o melhor de tudo, é tudo em tempo real. Se o outro sistema for atualizado às 10:01:01:0001, nós iremos ver os dados atualizados às 10:01:01:0002.


Lições aprendidas
  • Novamente, sempre olhe no CodePlex.
  • É muito fácil desenvolver/linkar APIs e outros frameworks ao Sql Server 2008.
  • Nunca, nunca confie no suporte técnico oferecido.


Thank you notes/Agradecimentos
Danilão! Pelo tempo gasto nisso e paciência.
Onald McDonald e Ogerio McDonald, pela torcida.
Ed Katibah, lead developer at Microsoft, who exchanged several emails with me and noticed that their implementation of Sql Spatial Tools is not correct (for UTM projections), and opened a ticket for fixing. Soon Sql Spatial Tools will be ready to handle all conversions.

6 comentários:

  1. Olá George,

    Você tem mais algum comentário sobre este tópico? O ProjNET está realmente funcionando?

    Abs,

    JMaior

    ResponderExcluir
  2. Sim está 100%.

    Só lembrando que ele não está imediatamente disponível para o SQL SERVER. É necessário registrar as dependências e criar uma função SQL para chamar a função C#.

    George

    ResponderExcluir
  3. Então, George... talvez não seria mais simples criar a função no sql com a conversão de SAD para o Datum que vc precisa? pois, (posso estar enganado), mas o seu problema é fornecer dados espaciais atraves de um banco de dados organizando-os de maneira que saiam em um único parametro, não?
    (criando uma string com o parâmetro de conversão de datum)...
    Será?

    ResponderExcluir
  4. Na verdade, seria. O que acontece por trás dos panos é um JOIN com uma tabela que me fornece os parametros de conversao.

    A função criada em C# foi registrada no SQL (falei criação no comentário acima, mas o único procedimento necessário é o registro), portanto utiliza-se ela da mesma maneira que qualquer função TSQL (ou plpgsql no PostGIS).

    No fim a query é algo como (nao lembro direito da sintaxe do SQL SERVER, me desculpem)

    @ponto SqlGeography
    SELECT ST_TRANSFORM(@ponto(campoX,campoY),campoPROJECAO) FROM tabela1 JOIN projecao ON (tabela1.projecaoID = projecao.projecaoID)

    ResponderExcluir
  5. Que chique, hein, Georgette! :P

    ResponderExcluir
  6. Tem um exemplo prático do código sql com a criação da função e a chamada da mesma?

    ResponderExcluir