If the formula for converting latitude or longitude to double is
((Degree) + (Minute) / 60 + (Second) / 3600) * ((South || West) ? -1 : 1)
then what's the formula for parsing degrees, minutes, seconds from a double?
It'd make sense to have two separate methods for parsing latitude and longitude, but I'm not sure how to parse the degrees, minutes, seconds from the double.
ParseLatitude(double value)
{
//value is South if negative, else is North.
}
ParseLongitude(double value)
{
//value is West if negative, else is East.
}
Example coordinates:
latitude: 43.81234123
longitude: -119.8374747
The final code to convert back and forth, thanks again to Peter and James for the answer. I had to convert value to Decimal because this is being used in Silverlight and Math.Truncate(double) is not available):
public class Coordinate
{
public double Degrees { get; set; }
public double Minutes { get; set; }
public double Seconds { get; set; }
public CoordinatesPosition Position { get; set; }
public Coordinate() { }
public Coordinate(double value, CoordinatesPosition position)
{
//sanity
if (value < 0 && position == CoordinatesPosition.N)
position = CoordinatesPosition.S;
//sanity
if (value < 0 && position == CoordinatesPosition.E)
position = CoordinatesPosition.W;
//sanity
if (value > 0 && position == CoordinatesPosition.S)
position = CoordinatesPosition.N;
//sanity
if (value > 0 && position == CoordinatesPosition.W)
position = CoordinatesPosition.E;
var decimalValue = Convert.ToDecimal(value);
decimalValue = Math.Abs(decimalValue);
var degrees = Decimal.Truncate(decimalValue);
decimalValue = (decimalValue - degrees) * 60;
var minutes = Decimal.Truncate(decimalValue);
var seconds = (decimalValue - minutes) * 60;
Degrees = Convert.ToDouble(degrees);
Minutes = Convert.ToDouble(minutes);
Seconds = Convert.ToDouble(seconds);
Position = position;
}
public Coordinate(double degrees, double minutes, double seconds, CoordinatesPosition position)
{
Degrees = degrees;
Minutes = minutes;
Seconds = seconds;
Position = position;
}
public double ToDouble()
{
var result = (Degrees) + (Minutes) / 60 + (Seconds) / 3600;
return Position == CoordinatesPosition.W || Position == CoordinatesPosition.S ? -result : result;
}
public override string ToString()
{
return Degrees + "º " + Minutes + "' " + Seconds + "'' " + Position;
}
}
public enum CoordinatesPosition
{
N, E, S, W
}
Unit Test (nUnit)
[TestFixture]
public class CoordinateTests
{
[Test]
public void ShouldConvertDoubleToCoordinateAndBackToDouble()
{
const double baseLatitude = 43.81234123;
const double baseLongitude = -119.8374747;
var latCoordN = new Coordinate(baseLatitude, CoordinatesPosition.N);
var latCoordS = new Coordinate(baseLatitude, CoordinatesPosition.S);
var lonCoordE = new Coordinate(baseLongitude, CoordinatesPosition.E);
var lonCoordW = new Coordinate(baseLongitude, CoordinatesPosition.W);
var convertedLatitudeS = latCoordS.ToDouble();
var convertedLatitudeN = latCoordN.ToDouble();
var convertedLongitudeW = lonCoordW.ToDouble();
var convertedLongitudeE = lonCoordE.ToDouble();
Assert.AreEqual(convertedLatitudeS, convertedLatitudeN);
Assert.AreEqual(baseLatitude, convertedLatitudeN);
Assert.AreEqual(convertedLongitudeE, convertedLongitudeW);
Assert.AreEqual(baseLongitude, convertedLongitudeE);
}
}