将度/分/秒转换为十进制坐标

21
在我的代码的某个部分,我将十进制坐标转换为度/分/秒,我使用以下代码:
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;

如何将度/分/秒转换回十进制坐标?


快速问题,将sec / 3600分配给deg不就相当于将coord分配给它吗? - Jeff LaFay
2
谢谢!大多数人在这里都很友善,但MVP们成为MVP是有原因的,他们整天泡在论坛上而不是工作,并且过于认真地对待他们的头衔... - Justin
你关于 sec / 3600 和 coord 相同是正确的,我实际上是从这个网站上得到了这个公式,但没有仔细检查过。现在我正在尝试反向计算它,但思路不够清晰,无法完成。 - Justin
@Justin:也许John在对待你方面有点粗鲁,但他是正确的。该站点的常见问题解答要求您省略诸如“嗨”和“谢谢”之类的内容(基本上与问题无关的任何内容)。这不是失礼的问题,而是因为该站点被设计成可以被搜索,大多数人不感兴趣阅读那些东西。话虽如此,这并不是什么大不了的事情。但我还是建议您将"C#"之类的内容放在标签中而非标题。也许减少一下关于MVP的修辞?我们中的一些人有激情,而不仅仅是大量的空闲时间。 - Adam Robinson
1
@Justin:StackOverflow之所以如此出色,其中一个原因是社区致力于将你在其他所有编程形式中看到的废话排除在外。因此,请不要在标题中放置标签,使用问候语和标语,或对他人粗鲁无礼。如果您对我们在这里做事的原因有任何疑问,请前往[meta]。 - user1228
1
@Will - Stack Overflow有时候会让人感到不爽的原因之一就是因为有太多像“不要使用问候语”这样愚蠢规则的保安执法。我们都是人,而不是机器人(当然除了机器人)。我认为让人们表达一点礼貌和感激之情值得花费额外的一秒钟来回答问题。我不想听人们的生活故事,但简单的“你好”就足够了,甚至受欢迎。Stack Overflow是一个很棒的资源,我希望能保持这种状态,所以让我们不要让摆动过度。 - d512
7个回答

41

试一下这个:

public double ConvertDegreeAngleToDouble( double degrees, double minutes, double seconds )
{
    //Decimal degrees = 
    //   whole number of degrees, 
    //   plus minutes divided by 60, 
    //   plus seconds divided by 3600

    return degrees + (minutes/60) + (seconds/3600);
}

11
这并未考虑半球因素。 - Duncan_m
2
在使用谷歌地图时让我困惑的一件事是,当我试图将MinDec转换为WGS84基准十进制值时。现在很明显,它只有度和分。我的公式类似于:返回度数+(分钟/60)+(秒/6000)。 - Dessus

12

仅为了节省其他人的时间,我想补充一下Byron的答案。如果您有字符串形式的点(例如“17.21.18S”),可以使用此方法:

public double ConvertDegreeAngleToDouble(string point)
{
    //Example: 17.21.18S

    var multiplier = (point.Contains("S") || point.Contains("W")) ? -1 : 1; //handle south and west

    point = Regex.Replace(point, "[^0-9.]", ""); //remove the characters

    var pointArray = point.Split('.'); //split the string.

    //Decimal degrees = 
    //   whole number of degrees, 
    //   plus minutes divided by 60, 
    //   plus seconds divided by 3600

    var degrees = Double.Parse(pointArray[0]);
    var minutes = Double.Parse(pointArray[1]) / 60;
    var seconds = Double.Parse(pointArray[2]) / 3600;

    return (degrees + minutes + seconds) * multiplier;
}

4

由于每个度数总共值1个坐标,每个分钟值1/60个坐标,每个秒钟值1/3600个坐标,您应该能够使用以下方法将它们重新组合:

new_coord = deg + min/60 + sec/3600

请注意,由于浮点数舍入的原因,它不会与原始数据完全相同。


4

CoordinateSharp 是一个可用的 Nuget 包,它可以为您处理坐标转换。它甚至可以进行 UTM/MGRS 转换并提供相对于输入位置的太阳/月亮时间。它非常易于使用!

Coordinate c = new Coordinate(40.465, -75.089);

//Display DMS Format
c.FormatOptions.Format = CoordinateFormatType.Degree_Minutes_Seconds;
c.ToString();//N 40º 27' 54" W 75º 5' 20.4"
c.Latitude.ToString();//N 40º 27' 54"
c.Latitude.ToDouble();//40.465

坐标属性也是可观察的。因此,如果您更改了纬度分钟值,其他所有内容都会更新。


注意,这是AGPL许可证! - Maulik Modi
它是分割许可。如果您不符合AGPL要求,您可以购买经济实惠的终身许可证,用于无限使用和分发。 - Tronald

4

通常,西半球和南半球用负度数表示,秒数带有小数以增加精度:-86:44:52.892。请记住,经度是X坐标,纬度是Y坐标。由于人们经常将它们称为lat/lon和X/Y,因此这经常会混淆。我修改了以下代码来适应上述格式。

private double ConvertDegreesToDecimal(string coordinate)
{
    double decimalCoordinate;
    string[] coordinateArray = coordinate.Split(':');
    if (3 == coordinateArray.Length)
    {
        double degrees = Double.Parse(coordinateArray[0]);
        double minutes = Double.Parse(coordinateArray[1]) / 60;
        double seconds = Double.Parse(coordinateArray[2]) / 3600;

        if (degrees > 0)
        {
            decimalCoordinate = (degrees + minutes + seconds);
        }
        else
        {
            decimalCoordinate = (degrees - minutes - seconds);
        }
    }
    return decimalCoordinate;
}

1

对于那些喜欢使用正则表达式并处理像DDMMSS.dddS这样的格式的人来说,这个函数可以很容易地更新以处理其他格式。

C#

Regex reg = new Regex(@"^((?<D>\d{1,2}(\.\d+)?)(?<W>[SN])|(?<D>\d{2})(?<M>\d{2}(\.\d+)?)(?<W>[SN])|(?<D>\d{2})(?<M>\d{2})(?<S>\d{2}(\.\d+)?)(?<W>[SN])|(?<D>\d{1,3}(\.\d+)?)(?<W>[WE])|(?<D>\d{3})(?<M>\d{2}(\.\d+)?)(?<W>[WE])|(?<D>\d{3})(?<M>\d{2})(?<S>\d{2}(\.\d+)?)(?<W>[WE]))$");

private double DMS2Decimal(string dms)
            {
                double result = double.NaN;            

                var match = reg.Match(dms);

                if (match.Success)
                {
                    var degrees = double.Parse("0" + match.Groups["D"]);
                    var minutes = double.Parse("0" + match.Groups["M"]);
                    var seconds = double.Parse("0" + match.Groups["S"]);
                    var direction = match.Groups["W"].ToString();
                    var dec = (Math.Abs(degrees) + minutes / 60d + seconds / 3600d) * (direction == "S" || direction == "W" ? -1 : 1);
                    var absDec = Math.Abs(dec);

                    if ((((direction == "W" || direction == "E") && degrees <= 180 & absDec <= 180) || (degrees <= 90 && absDec <= 90)) && minutes < 60 && seconds < 60)
                    {
                        result = dec;
                    }

                }

                return result;

            }

1
迄今为止被接受的答案是不准确的,没有考虑到将负数加到正数时会发生什么。下面的代码解决了这个问题,并且可以正确地进行转换。
    public double ConvertDegreeAngleToDouble(double degrees, double minutes, double seconds)
    {
        var multiplier = (degrees < 0 ? -1 : 1);
        var _deg = (double)Math.Abs(degrees);
        var result = _deg + (minutes / 60) + (seconds / 3600);
        return result * multiplier;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接