Neste post irei mostrar uma maneira de calcular uma coordenada(ponto qualquer) está contido dentro de um quadrado, dado sua metragem desde o ponto inicial, usando SQL.

Vamos supor a seguinte tabela com os registros abaixo.

Lat Lng
1.0 -1.25
2.3526 -3
4 5.98

A tabela acima mostra coordenadas que podemos chama-las de latitude e longitude. Passaremos para a função um valor correspondente em metros para a mesma realizar um cálculo quadrado da latitude com longitude. Podemos realizar esse calculo para um circulo, porém o calculo exige saber o raio e incrementar o PI dentro da função, porém vamos ao quadrado mesmo.

Veja a função abaixo, ela realiza todo o calculo. Podemos utiliza-la para realizar cálculos direto no banco de dados o que aumenta muito o poder de processamento ao invés de buscar os dados e depois fazer o calculo de 1 por 1.

Fiz um teste com um total de 11.816.250 (mais de 11 milhões de registros) passando por cada um deles, sem usar filtros e me retornou em um tempo de 8.5 SEGUNDOS.

Imagina agora buscar todos esses 11 milhões de registros e depois fazer para cada ponto 1 calculo que verifica se o ponto está dentro ou fora, acredite, em qualquer linguagem de programação demora demais e pode até causar pane no sistema caso várias pessoas esteja realizando o mesmo processo. Chega de papo e veja o código abaixo.

create or replace 
FUNCTION 
  CHECK_COORDS(LAT VARCHAR2, LNG VARCHAR2, METROS NUMBER) RETURN VARCHAR2 IS
  coords  Varchar2(37000):='';
  latitude Varchar2(1);
  longitude Varchar2(1);
  CALC_METERS Number := (0.001 * METROS) / 100;
  
  cursor resultado is select 
    tb.latitude, tb.longitude into latitude, longitude
  from 
    TABELA tb
  where 
    (
      (abs(replace(LAT, '.', ','))  between (abs(tb.latitude) -CALC_METERS) and (abs(tb.latitude) +CALC_METERS))
      and 
      (abs(replace(LNG, '.', ','))  between (abs(tb.longitude)-CALC_METERS) and (abs(tb.longitude)+CALC_METERS))
    );
    
BEGIN
  FOR i IN resultado LOOP
      coords := i.latitude || ', ' || i.longitude || ' - ' ||;    
  END LOOP;
  
  RETURN coords;;
END CHECK_COORDS;

Muito simples mas funcional. Veja o Between do próprio SQL, ele faz toda a mágica. Se quisesse fazer em um circulo, poderiamos alterar este cálculo passando o raio e acrescentando o PI(3.14) assim você verificaria se o ponto estaria dentro deste circulo.

Vamos chamar a função então?

select CHECK_COORDS('1', '3', 200) from dual;

Veja que 1 é a latitude, 3 é a longitude e 200 é o valor em metros. Cuidado, se retornar muitos valores concatenados a função poderá precisar de um Clob. Você pode também simplesmente retornar o primeiro registro que achar, use a imaginação.

Lembre-se que este cálculo pode ser usado em um plano cartesiano 2D genérico.

Ate a próxima.

Quero CompartilharShare on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn

Comentários

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *