11

I have come up with the following expression to convert 5.1234 to 5°7'24.24"

toint($x) || '° ' || toint((($x) - toint ($x))*60) || '`' || substr((tostring(((($x) - toint($x))*60) - toint((($x) - toint($x))*60))*60), 1, 5) || '"'

Here’s the problem: for some points such as 5.1234, it works. But for others, it doesn’t. I suspect the problem is the integer conversion which round up the decimal figures instead of truncating it.

Is there any other option?

3
  • I can suggest a workaround. Not optimal, but if you are stuck right now, you can get your work done. Right click and Save As a CSV. Open the CSV in Excel or Google Docs, enter your formula (which should be cleaner and easier). Delete all fields except a unique identifier and converted DMS strings. Save it. Do a table join with existing layer and you are set. Commented Jul 2, 2012 at 10:46
  • 2
    Be careful with negative inputs.
    – whuber
    Commented Jul 2, 2012 at 11:37
  • Just to add to spatialthought's answer: rounding down to the nearest degree will work in Excel using the FLOOR() function.
    – Micha
    Commented Jul 3, 2012 at 11:23

4 Answers 4

9

Nowadays there is a native function to_dms() for this intent included in the expression calculator.

Now, you can simply run to_dms(5.1234, 'x', 2). A capture of the current doc can be seen below

enter image description here

4

I like the expression you've put together - probably no solution in QGIS 1.8, but in QGIS 1.9-dev there's a floor() rounding function which rounds down. For D°M'S'':

(CASE WHEN $x < 0 THEN '-' ELSE '' END) || floor (abs($x)) || '° ' || floor(((abs($x)) - floor (abs($x))) * 60) ||'\'' || substr( (tostring((((abs($x)) - floor (abs($x))) * 60) - floor(((abs($x)) - floor (abs($x))) * 60)) * 60),1,5) || '"'

Note the escaped apostrophe (\').

For D°M.MMM':

(CASE WHEN $x < 0 THEN '-' ELSE '' END) || floor (abs($x)) || '° ' || ((abs($x) - floor(abs($x))) * 60) ||'\''

To limit the number of displayed decimal minutes, substitute # in the expression below with the number of digits:

(CASE WHEN $x < 0 THEN '-' ELSE '' END) || floor (abs($x)) || '° ' ||  format_number( (abs($x) - floor(abs($x))) * 60, #) ||'\'
4
  • Just out of curiosity, how would the formula look like for Degrees, Minutes?
    – mace
    Commented Jan 8, 2015 at 13:32
  • Added an example; this works in QGIS 2.6 (and probably anything 2.0 and up) but there may be more elegant formatting functions available now.
    – Simbamangu
    Commented Jan 9, 2015 at 4:46
  • 1
    Just one pitfall: Your formula only works for positive values of Easting and Northing. Negative are one too small. And I wonder how 0.5° E and 0.5° W may be distinguished. floor(+/-0.5) will always be 0, not -0.
    – AndreJ
    Commented Jan 9, 2015 at 6:18
  • Aaargh. The pitfalls of insufficient testing ... and here's me working in the southern (negative) hemisphere, too. Updating shortly.
    – Simbamangu
    Commented Jan 9, 2015 at 7:17
1

The modulo operator can be used to do truncation, but the resulting expression would be very ugly. It is prettier to use string substitution, but unfortunately QGIS doesn't expose any strpos or similar functions. Use regexp_replace($x, '\\..*', '') to get the whole part and regexp_replace($x, '^[0-9]*\\.', '') to get the decimal part. Use toreal instead of toint for calculations with the second expression to make sure there will be no rounding.

4
  • 2
    Didn't have a strpos function but does now ;) github.com/qgis/Quantum-GIS/commit/…
    – Nathan W
    Commented Jul 2, 2012 at 10:04
  • tsk tsk tsk, so much whitespace noise. Commented Jul 2, 2012 at 10:22
  • Yeah ignore that first bit it was just a bit of clean up unrelated to the new function.
    – Nathan W
    Commented Jul 2, 2012 at 10:25
  • Ugly it is... will try to work it out.
    – Obsidianz
    Commented Jul 2, 2012 at 22:39
1

I made some changes to the code to get the coordinates in DMS, if necessary. Only adjustments to the EPSG information are needed.

Latitude

(CASE WHEN $y < 0 THEN '-' ELSE '' END) || floor (abs(Y( transform( $geometry, 'EPSG:31983', 'EPSG:4326'))
)) || '°' || floor(((abs(Y( transform( $geometry, 'EPSG:31983', 'EPSG:4326'))
)) - floor (abs(Y( transform( $geometry, 'EPSG:31983', 'EPSG:4326'))
))) * 60) ||'\'' || substr( (tostring((((abs(Y( transform( $geometry, 'EPSG:31983', 'EPSG:4326'))
)) - floor (abs(Y( transform( $geometry, 'EPSG:31983', 'EPSG:4326'))
))) * 60) - floor(((abs(Y( transform( $geometry, 'EPSG:31983', 'EPSG:4326'))
)) - floor (abs(Y( transform( $geometry, 'EPSG:31983', 'EPSG:4326'))
))) * 60)) * 60),1,5) || '"'

Longitude

(CASE WHEN $x < 0 THEN '-' ELSE '' END) || floor (abs(X( transform( $geometry, 'EPSG:31983', 'EPSG:4326'))
)) || '°' || floor(((abs(X( transform( $geometry, 'EPSG:31983', 'EPSG:4326'))
)) - floor (abs(X( transform( $geometry, 'EPSG:31983', 'EPSG:4326'))
))) * 60) ||'\'' || substr( (tostring((((abs(X( transform( $geometry, 'EPSG:31983', 'EPSG:4326'))
)) - floor (abs(X( transform( $geometry, 'EPSG:31983', 'EPSG:4326'))
))) * 60) - floor(((abs(X( transform( $geometry, 'EPSG:31983', 'EPSG:4326'))
)) - floor (abs(X( transform( $geometry, 'EPSG:31983', 'EPSG:4326'))
))) * 60)) * 60),1,5) || '"'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.