格式化为纬度/经度的人类可读格式

Car*_*urt 7 .net c# reverse-geocoding

如果将纬度或经度转换为double的公式为

((Degree) + (Minute) / 60 + (Second) / 3600) * ((South || West) ? -1 : 1)

那么从双精度解析度,分,秒的公式是什么?

有两个单独的方法来解析纬度和经度是有道理的,但我不知道如何解析双精度的度数,分钟,秒.

ParseLatitude(double value)
{
    //value is South if negative, else is North.
}

ParseLongitude(double value)
{
    //value is West if negative, else is East.
}
Run Code Online (Sandbox Code Playgroud)

示例坐标:

纬度:43.81234123

经度:-119.8374747

最后的代码来回转换,再次感谢Peter和James的回答.我不得不将转换为Decimal,因为这是在Silverlight中使用而Math.Truncate(double)不可用):

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
}
Run Code Online (Sandbox Code Playgroud)

单元测试(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);
    }
}
Run Code Online (Sandbox Code Playgroud)

pho*_*oog 9

ParseLatitude(double Value)
{
    var direction = Value < 0 ? Direction.South : Direction.North;

    Value = Math.Abs(Value);

    var degrees = Math.Truncate(Value);

    Value = (Value - degrees) * 60;       //not Value = (Value - degrees) / 60;

    var minutes = Math.Truncate(Value);
    var seconds = (Value - minutes) * 60; //not Value = (Value - degrees) / 60;
    //...
}

ParseLongitude(double Value)
{
    var direction = Value < 0 ? Direction.West : Direction.East;

    Value = Math.Abs(Value);

    var degrees = Math.Truncate(Value);

    Value = (Value - degrees) * 60;       //not Value = (Value - degrees) / 60;

    var minutes = Math.Truncate(Value);
    var seconds = (Value - minutes) * 60; //not Value = (Value - degrees) / 60;
    //...
}
Run Code Online (Sandbox Code Playgroud)

编辑

由于最近的投票,我回到了这里.这是一个DRY-er版本,Value重命名参数以反映最常见的编码约定,其中参数以小写字母开头:

ParseLatitude(double value)
{
    var direction = value < 0 ? Direction.South : Direction.North;
    return ParseLatituteOrLongitude(value, direction);
}

ParseLongitude(double value)
{
    var direction = value < 0 ? Direction.West : Direction.East;
    return ParseLatituteOrLongitude(value, direction);
}

//This must be a private method because it requires the caller to ensure
//that the direction parameter is correct.
ParseLatitudeOrLongitude(double value, Direction direction)
{
    value = Math.Abs(value);

    var degrees = Math.Truncate(value);

    value = (value - degrees) * 60;       //not Value = (Value - degrees) / 60;

    var minutes = Math.Truncate(value);
    var seconds = (value - minutes) * 60; //not Value = (Value - degrees) / 60;
    //...
}
Run Code Online (Sandbox Code Playgroud)

  • 对不起,phoog,值需要乘以,而不是分. (2认同)