Reputation: 939
Is there some sample conversion code in C# to go from decimal degrees to Degrees, Minutes, Seconds, Tenth?
Upvotes: 10
Views: 36892
Reputation: 2552
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...
Upvotes: 0
Reputation: 7306
Here is a class I made time ago.
public class SexagesimalAngle
{
public bool IsNegative { get; set; }
public int Degrees { get; set; }
public int Minutes { get; set; }
public int Seconds { get; set; }
public int Milliseconds { get; set; }
public static SexagesimalAngle FromDouble(double angleInDegrees)
{
//ensure the value will fall within the primary range [-180.0..+180.0]
while (angleInDegrees < -180.0)
angleInDegrees += 360.0;
while (angleInDegrees > 180.0)
angleInDegrees -= 360.0;
var result = new SexagesimalAngle();
//switch the value to positive
result.IsNegative = angleInDegrees < 0;
angleInDegrees = Math.Abs(angleInDegrees);
//gets the degree
result.Degrees = (int)Math.Floor(angleInDegrees);
var delta = angleInDegrees - result.Degrees;
//gets minutes and seconds
var seconds = (int)Math.Floor(3600.0 * delta);
result.Seconds = seconds % 60;
result.Minutes = (int)Math.Floor(seconds / 60.0);
delta = delta * 3600.0 - seconds;
//gets fractions
result.Milliseconds = (int)(1000.0 * delta);
return result;
}
public override string ToString()
{
var degrees = this.IsNegative
? -this.Degrees
: this.Degrees;
return string.Format(
"{0}° {1:00}' {2:00}\"",
degrees,
this.Minutes,
this.Seconds);
}
public string ToString(string format)
{
switch (format)
{
case "NS":
return string.Format(
"{0}° {1:00}' {2:00}\".{3:000} {4}",
this.Degrees,
this.Minutes,
this.Seconds,
this.Milliseconds,
this.IsNegative ? 'S' : 'N');
case "WE":
return string.Format(
"{0}° {1:00}' {2:00}\".{3:000} {4}",
this.Degrees,
this.Minutes,
this.Seconds,
this.Milliseconds,
this.IsNegative ? 'W' : 'E');
default:
throw new NotImplementedException();
}
}
}
Upvotes: 38
Reputation: 148744
You can simply use these 2 functions :
public Tuple<int,int,int> DecimalToDegrees(decimal decimalValue)
{
return Tuple.Create(Convert.ToInt32( decimal.Truncate(decimalValue)),Convert.ToInt32( (decimal.Truncate(Math.Abs(decimalValue)*60))%60),Convert.ToInt32( (Math.Abs(decimalValue)*3600)%60));
}
And:
public decimal DecimalToDegrees(int deg , int min , int sec)
{ //~2.3825224324453 Meters error due to accuracy
return deg+(min/60m)+(sec/3600m);
}
Upvotes: 1
Reputation: 2856
The solution here has the conversion both ways.
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;
**From Convert Degrees/Minutes/Seconds to Decimal Coordinates
Upvotes: 4
Reputation: 10107
I think this should do it.
double decimal_degrees;
// set decimal_degrees value here
double minutes = (decimal_degrees - Math.Floor(decimal_degrees)) * 60.0;
double seconds = (minutes - Math.Floor(minutes)) * 60.0;
double tenths = (seconds - Math.Floor(seconds)) * 10.0;
// get rid of fractional part
minutes = Math.Floor(minutes);
seconds = Math.Floor(seconds);
tenths = Math.Floor(tenths);
Upvotes: 12