Recentemente tive que implementar uma solução, onde através de um formulário, o usuário informava as coordenadas em graus, minutos e segundos, logo em seguida era mostrado em um mapa, se essa coordenada caía em uma área válida da aplicação.
Acontece que por padrão, o PostGIS armazena as geometrias no formato decimal, logo eu teria que tratar as coordenadas digitadas (no código PHP ou no Banco), transformando-as em graus decimais, foi aí que eu encontrei duas funções muito úteis na lista de discussão do PostGIS. Fiz uma pequena modificação na segunda função, que aumenta a quantidade de casas decimais dos minutos e segundos, caso do resultado seja um número inteiro nesses dois elementos.
Para utilizá-las é necessário carregá-las em um banco com o PostGIS instalado.
Create or Replace Function DMS2DD( dDeg In Float, dMin In Float, dSec In Float ) Returns Float AS $BODY$ Declare dDD Float; BEGIN dDD := ABS(dDeg) + dMin / 60::float + dSec / 3600::float; Return SIGN(dDeg) * dDD; End; $BODY$ LANGUAGE 'plpgsql' IMMUTABLE STRICT COST 100; create or Replace Function DD2DMS( dDecDeg in Float, pDegreeSymbol in VarChar(1), pMinuteSymbol in VarChar(1), pSecondSymbol in VarChar(1) ) Returns varchar(50) AS $BODY$ DECLARE iDeg Int; iMin Int; dSec Float; BEGIN iDeg := Trunc(dDecDeg)::Int; iMin := Trunc( (Abs(dDecDeg) - Abs(iDeg)) * 60)::Int; dSec := Round(((((Abs(dDecDeg) - Abs(iDeg)) * 60) - iMin) * 60)::numeric, 3)::float; Return trim(to_char(iDeg,'9999')) || pDegreeSymbol::text || trim(to_char(iMin,'99.00')) || pMinuteSymbol::text || case when dSec = 0::Float then '00' else replace(trim(to_char(dSec,'99.999')),'.000','') end || pSecondSymbol::text; END; $BODY$ LANGUAGE 'plpgsql' IMMUTABLE STRICT COST 100;
Utilizando as funções:
-- Converter as coordenadas da geometria -- POINT(-38.4969 -6.4026) para graus, minutos e segundos: SELECT DD2DMS(x(geometryFromText('POINT(-38.4969 -6.4026)')), '°','\'','\"' ) as Longitude, DD2DMS(y(geometryFromText('POINT(-38.4969 -6.4026)')), '°','\'','\"' ) as Latitude;
Resultado:
Longitude | Latitude
--------------------------+-----------------------
-38°29.00'48.840" | -6°24.00'9.360"
-- Converter as coordenadas (-34° 10' 50", -7° 33' 30") -- para graus decimais: SELECT DMS2DD(-34,10,50) as longitude, DMS2DD(-7,33,30) as latitude;
Resultado:
Longitude | Latitude
----------------------------+-----------------------
-34.1805555555556 | -7.55833333333333