Convert decimal coordinates to Degrees, Minutes & Seconds by c#
Asked Answered
E

5

1

Has anyone know simple short code to convert this without use additional libraries ?

Escrow answered 6/7, 2010 at 15:25 Comment(0)
Y
9

Like this:

double coord = 59.345235;
int sec = (int)Math.Round(coord * 3600);
int deg = sec / 3600;
sec = Math.Abs(sec % 3600);
int min = sec / 60;
sec %= 60;

Edit: Added an Abs call so that it works for negative angles also.

Yuzik answered 6/7, 2010 at 15:29 Comment(0)
G
4

you could use timespan: (tricky but it works)

   double coord = 123.312312;   
   var ts = TimeSpan.FromHours(Math.Abs(coord));
   int degrees = Math.Sign(coord) * Math.Floor(ts.TotalHours);
   int minutes = ts.Minutes;
   int seconds = ts.Seconds;
Greenback answered 6/7, 2010 at 15:43 Comment(2)
Interresting, but it might be a bit confusing as it's not at all a time... And it doesn't work for negative angles...Yuzik
@Guffa, I agree! It's a wtf??!! fer sure.. but curious and illuminating as it illustrates (and capitalizes on ) the parallel between the two data structures. (fixed it to handle negatives)Greenback
E
2

I am infering from your question that you want to convert from cartesian to polar coordinates.

If this is the case, the basic formulae you need are:

r = √ (x2 + y2)

θ = atan( y / x )

Where r is the distance and θ is the angle from x = 0 (about the origin)

Does this help?

Eshman answered 6/7, 2010 at 15:30 Comment(0)
D
2

I came up with the following. It correctly handles negative coordinates (south latitude or west longitude) and returns the remainder (in degrees) that was not evely divided into minutes or seconds.

public static double ConvertDecimalToDegMinSec(double value, out int deg, out int min, out int sec)
{
    deg = (int)value;
    value = Math.Abs(value - deg);
    min = (int)(value * 60);
    value = value - (double)min / 60;
    sec = (int)(value * 3600);
    value = value - (double)sec / 3600;
    return value;
}
Dumbbell answered 6/7, 2010 at 16:11 Comment(0)
B
0

String representation of a location, i.e. 51°09'48.2"N 10°07'28.6"E

public static string ToDMS(this Location location)
{
    var (lat, lon) = (location.Latitude, location.Longitude);
    var latSec = Math.Abs(lat) % 1.0 * 3600.0;
    var lonSec = Math.Abs(lon) % 1.0 * 3600.0;
    return FormattableString.Invariant(
      $@"{Math.Abs((int)lat)}°{(int)latSec / 60}'{latSec % 60:F1}\"{(lat >= 0 ? "N" : "S")
       } {Math.Abs((int)lon)}°{(int)lonSec / 60}'{lonSec % 60:F1}\"{(lon >= 0 ? "E" : "W")}");
}

You might not like this one-liner :)

public static string ToDMS(double lat, double lon) => FormattableString.Invariant($"{Math.Abs((int)lat)}°{(int)(Math.Abs(lat) % 1.0 * 60.0)}'{Math.Abs(lat) * 3600.0 % 60:F1}\"{(lat >= 0 ? "N" : "S")} {Math.Abs((int)lon)}°{(int)(Math.Abs(lon) % 1.0 * 60.0)}'{Math.Abs(lon) * 3600.0 % 60:F1}\"{(lon >= 0 ? "E" : "W")}" );

Suggestions for any improvements welcome...

Biannulate answered 3/3, 2022 at 15:50 Comment(2)
I don't know where the Location class is defined. The answer would be easier to use/test, if the function received doubles as parameters. Also, why is FormattableString.Invariant useful here?Scleroma
@ScottHutchinson, this is just an example, just change the parameters to lat, lon and remove the first line (or use the second example). Invariant makes sure that the decimal point is used, no matter where this is used (in some countries you would get a decimal comma instead).Biannulate

© 2022 - 2024 — McMap. All rights reserved.