格式化双纬度/经度人类可读的格式 [英] Formatting double to latitude/longitude human readable format

查看:135
本文介绍了格式化双纬度/经度人类可读的格式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果公式转换经纬度翻一番是

((度)+(分钟)/ 60 +(二)/ 3600)*((南||西)-1:1)

再有什么公式解析度,分,秒,从双?

这将会有道理对解析经纬度两个不同的方法,但我不知道如何从双重解析度,分,秒。

  ParseLatitude(double值)
{
    //值是南如果为负,否则就是北方。
}

ParseLongitude(double值)
{
    //值是西如果为负,否则就是东。
}
 

例如坐标:

纬度:43.81234123

经度:-119.8374747

最后code再来回转换,这要归功于彼得和詹姆斯的答案。我不得不转换的的为十进制因为这是正在Silverlight和Math.Truncate(双)采用的是不可用):

 公共类坐标
{
    公共双学位{获得;组; }
    公共双分钟{获得;组; }
    公共双秒{获得;组; }
    公共CoordinatesPosition位置{获得;组; }

    公共坐标(){}
    公共坐标(双精度值,CoordinatesPosition位置)
    {
        //神智
        如果(值小于0安培;&安培;仓位== CoordinatesPosition.N)
            位置= CoordinatesPosition.S;
        //神智
        如果(值小于0安培;&安培;仓位== CoordinatesPosition.E)
            位置= CoordinatesPosition.W;
        //神智
        如果(值大于0和放大器;&安培;仓位== CoordinatesPosition.S)
            位置= CoordinatesPosition.N;
        //神智
        如果(值大于0和放大器;&安培;仓位== CoordinatesPosition.W)
            位置= CoordinatesPosition.E;

        VAR decimalValue = Convert.ToDecimal(值);

        decimalValue = Math.Abs​​(decimalValue);

        VAR度= Decimal.Truncate(decimalValue);
        decimalValue =(decimalValue  - 度)* 60;

        VAR分钟= Decimal.Truncate(decimalValue);
        VAR秒=(decimalValue  - 分钟)* 60;

        度= Convert.ToDouble(度);
        分钟= Convert.ToDouble(分钟);
        秒= Convert.ToDouble(秒);
        位置=地位;
    }
    公共坐标(双学位,双分,双秒,CoordinatesPosition位置)
    {
        度=度;
        分钟=分钟;
        秒=秒;
        位置=地位;
    }
    公共双ToDouble()
    {
        VAR的结果=(度)+(分钟)/ 60 +(秒)/ 3600;
        返回位置== CoordinatesPosition.W ||位置== CoordinatesPosition.S? -result:结果;
    }
    公共重写字符串的ToString()
    {
        返回度+º+分钟+'+秒+''+位置;
    }
}

公共枚举CoordinatesPosition
{
    N,E,S,W
}
 

单元测试(NUnit的)

  [的TestFixture]
公共类CoordinateTests
{
    [测试]
    公共无效ShouldConvertDoubleToCoordinateAndBackToDouble()
    {
        常量双baseLatitude = 43.81234123;
        常量双baseLongitude = -119.8374747;

        VAR latCoordN =新坐标(baseLatitude,CoordinatesPosition.N);
        VAR latCoordS =新坐标(baseLatitude,CoordinatesPosition.S);
        VAR lonCoordE =新坐标(baseLongitude,CoordinatesPosition.E);
        VAR lonCoordW =新坐标(baseLongitude,CoordinatesPosition.W);

        变种convertedLatitudeS = latCoordS.ToDouble();
        变种convertedLatitudeN = latCoordN.ToDouble();
        变种convertedLongitudeW = lonCoordW.ToDouble();
        变种convertedLongitudeE = lonCoordE.ToDouble();

        Assert.AreEqual(convertedLatitudeS,convertedLatitudeN);
        Assert.AreEqual(baseLatitude,convertedLatitudeN);
        Assert.AreEqual(convertedLongitudeE,convertedLongitudeW);
        Assert.AreEqual(baseLongitude,convertedLongitudeE);
    }
}
 

解决方案

  ParseLatitude(double值)
{
    VAR方向=值小于; 0? Direction.South:Direction.North;

    值= Math.Abs​​(值);

    VAR度= Math.Truncate(值);

    值=(值 - 度)* 60; //不是值=(值 - 度)/ 60;

    VAR分钟= Math.Truncate(值);
    VAR秒=(值 - 分钟)* 60; //不是值=(值 - 度)/ 60;
    // ...
}

ParseLongitude(双值)
{
    VAR方向=值小于; 0? Direction.West:Direction.East;

    值= Math.Abs​​(值);

    VAR度= Math.Truncate(值);

    值=(值 - 度)* 60; //不是值=(值 - 度)/ 60;

    VAR分钟= Math.Truncate(值);
    VAR秒=(值 - 分钟)* 60; //不是值=(值 - 度)/ 60;
    // ...
}
 

修改

我来是因为最近一个upvote回本。这里有一个DRY-ER的版本,与参数重新命名,以反映最常用的编码惯例,其中的参数开始与小写字母:

  ParseLatitude(double值)
{
    VAR方向=值小于; 0? Direction.South:Direction.North;
    返回ParseLatituteOrLongitude(价值方向);
}

ParseLongitude(double值)
{
    VAR方向=值小于; 0? Direction.West:Direction.East;
    返回ParseLatituteOrLongitude(价值方向);
}

//这必须是一个私人的方法,因为它要求调用者保证
//该方向的参数是正确的。
ParseLatitudeOrLongitude(双重价值,方向方向)
{
    值= Math.Abs​​(值);

    VAR度= Math.Truncate(值);

    值=(值 - 度)* 60; //不是值=(值 - 度)/ 60;

    VAR分钟= Math.Truncate(值);
    VAR秒=(价值 - 分钟)* 60; //不是值=(值 - 度)/ 60;
    // ...
}
 

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);
    }
}

解决方案

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;
    //...
}

EDIT

I came back to this because of a recent upvote. Here's a DRY-er version, with the Value parameter renamed to reflect the most common coding convention, in which parameters start with lower-case letters:

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;
    //...
}

这篇关于格式化双纬度/经度人类可读的格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆