Go to content Go to navigation and search

Home

Current PostGIS Blog Articles


Search

Browse

RSS / Atom

Email me

textpattern

Creative Commons License
All Blog Articles, Data Models and Free Source Code by Simon Greener, The SpatialDB Advisor is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

COGO: Converting Decimal Degrees to Degrees Minutes and Seconds - and back again (PostGIS)

Thursday March 01 2012 at 00:54

KeywordsDD2MS DMS2DD Decimal Degrees Degrees Minutes Seconds
Summary

This article shows how to implement conversion functions for decimal degrees to degrees minutes and seconds and the reverse: plpgsql functions are presented called Dms2Dd Dd2Dms.

It is useful to have functions for converting from individual degrees, minutes and seconds to a single decimal degree value and back again.

Here are some useful plPgSql functions.

DMS2DD

Firstly, a function to convert individual degrees, minutes and seconds values to a single decimal degree value.

  1. CREATE FUNCTION DMS2DD( p_dDeg IN FLOAT,
  2.                         p_dMin IN FLOAT,
  3.                         p_dSec IN FLOAT)
  4. RETURNS FLOAT
  5. AS
  6. $BODY$
  7. DECLARE
  8.    v_dDD FLOAT;
  9. BEGIN
  10.    v_dDD := ABS(p_dDeg) + p_dMin / 60::FLOAT + p_dSec / 3600::FLOAT;
  11.    RETURN SIGN(p_dDeg) * v_dDD;
  12. END;
  13. $BODY$
  14.   LANGUAGE 'plpgsql' IMMUTABLE STRICT
  15.   COST 100;

Now for some examples….

  1. SELECT DMS2DD(-44,10,50);

Result:

dms2dd
-44.1805555555556
  1. SELECT DMS2DD(-44,00,00);

Result:

dms2dd
-44

There is also a function, DMS2DD that takes a string input (cf Google Earth/Maps) and returns its decimal equivalent.

DD2DMS

Secondly, a function to convert a single decimal degree value to individual degrees, minutes and seconds values as a string.

  1. CREATE OR REPLACE FUNCTION DD2DMS( p_dDecDeg       IN FLOAT,
  2.                                    p_sDegreeSymbol IN VARCHAR(1),
  3.                                    p_sMinuteSymbol IN VARCHAR(1),
  4.                                    p_sSecondSymbol IN VARCHAR(1) )
  5. RETURNS VARCHAR(50)
  6. AS
  7. $BODY$
  8. DECLARE
  9.    v_iDeg INT;
  10.    v_iMin INT;
  11.    v_dSec FLOAT;
  12. BEGIN
  13.    v_iDeg := Trunc(p_dDecDeg)::INT;
  14.    v_iMin := Trunc(   (Abs(p_dDecDeg) - Abs(v_iDeg)) * 60)::INT;
  15.    v_dSec := Round(((((Abs(p_dDecDeg) - Abs(v_iDeg)) * 60) - v_iMin) * 60)::NUMERIC, 3)::FLOAT;
  16.    RETURN TRIM(to_char(v_iDeg,'9999')) || p_sDegreeSymbol::text || TRIM(to_char(v_iMin,'99')) || p_sMinuteSymbol::text ||
  17.           CASE WHEN v_dSec = 0::FLOAT THEN '0' ELSE REPLACE(TRIM(to_char(v_dSec,'99.999')),'.000','') END || p_sSecondSymbol::text;
  18. END;
  19. $BODY$
  20.   LANGUAGE 'plpgsql' IMMUTABLE STRICT
  21.   COST 100;

Some examples.

  1. SELECT DD2DMS(-44,'d','m','s');

Result:

dd2dms
-44d0m0s
  1. SELECT DD2DMS(-44.5,'d','m','s');

Result:

dd2dms
-44d30m0s
  1. SELECT DD2DMS(-44.577,'d','m','s');

Result:

dd2dms
-44d34m37.200s
  1. SELECT DD2DMS(gis.DMS2DD(-44,10,50),'d','s','"');

Result:

dd2dms
-44d10s50”

DD2DMST

But what if I only want the individual degrees, minutes and seconds values from a decimal degree value?

This can be done in a number of ways eg writing three functions to extract each individual value. But the way I will do it is via a TYPE and a single function.

  1. CREATE TYPE DMS AS (
  2.    degree INT,
  3.    MINUTE INT,
  4.    SECOND FLOAT
  5. );
  6. -- Function
  7. --
  8. CREATE OR REPLACE FUNCTION DD2DMST( p_dDecDeg IN FLOAT )
  9. RETURNS DMS
  10. AS
  11. $BODY$
  12. DECLARE
  13.    v_dms  DMS;
  14. BEGIN
  15.    v_dms.degree := Trunc(p_dDecDeg)::INT;
  16.    v_dms.MINUTE := Trunc(   (Abs(p_dDecDeg) - Abs(v_dms.degree)) * 60)::INT;
  17.    v_dms.SECOND := Round(((((Abs(p_dDecDeg) - Abs(v_dms.degree)) * 60) - v_dms.MINUTE) * 60)::NUMERIC, 3)::FLOAT;
  18.    RETURN v_dms;
  19. END;
  20. $BODY$
  21.   LANGUAGE 'plpgsql' IMMUTABLE STRICT
  22.   COST 100;

Some examples.

  1. SELECT DD2DMST(-44);

Result:

dd2dmst
(-44,0,0)
  1. SELECT (DD2DMST(-44.5)).*;

Result:

degree minute second
-44 30 0
  1. SELECT degree,MINUTE,SECOND FROM (SELECT (DD2DMST(-44.577)).* ) AS a;

Result:

degree minute second
-44 34 37.2
  1. SELECT DD2DMST(DMS2DD(-44,10,50));

Result:

dd2dmst
(-44,10,50)

I hope these are useful to someone.

Creative Commons License

post this at del.icio.uspost this at Diggpost this at Technoratipost this at Redditpost this at Farkpost this at Yahoo! my webpost this at Windows Livepost this at Google Bookmarkspost this to Twitter

Comment