Convert Degrees/Minutes/Seconds to Decimal Coordinates

前端 未结 7 1156
青春惊慌失措
青春惊慌失措 2020-12-01 12:31

In one part of my code I convert from decimal coordinates to degrees/minutes/seconds and I use this:

double coord = 59.345235;
int sec = (int)Math.Round(coor         


        
相关标签:
7条回答
  • 2020-12-01 13:10

    The accepted answer to date is inaccurate and doesn't take into account what happens when you add negative numbers to positive numbers. The below code addresses the issue and will correctly convert.

        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;
        }
    
    0 讨论(0)
  • 2020-12-01 13:12

    Since degrees are each worth 1 coordinate total, and minutes are worth 1/60 of a coordinate total, and seconds are worth 1/3600 of a coordinate total, you should be able to put them back together with:

    new_coord = deg + min/60 + sec/3600
    

    Beware that it won't be the exact same as the original, though, due to floating-point rounding.

    0 讨论(0)
  • 2020-12-01 13:14

    Just to save others time, I wanted to add on to Byron's answer. If you have the point in string form (e.g. "17.21.18S"), you can use this method:

    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;
    }
    
    0 讨论(0)
  • 2020-12-01 13:15

    Often the western and southern hemispheres are expressed as negative degrees, and seconds contain decimals for accuracy: -86:44:52.892 Remember longitude is the X-coordinate and latitude is the Y-coordinate. This often gets mixed up because people often refer to them lat/lon and X/Y. I modified the code below for the above format.

    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;
    }
    
    0 讨论(0)
  • 2020-12-01 13:17

    CoordinateSharp is available as a Nuget package and can handle Coordinate conversions for you. It even does UTM/MGRS conversion and provides solar/lunar times relative to the input location. It's really easy to use!

    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
    

    Coordinate properties are iObservable as as well. So if you change a latitude minute value for example, everything else will update.

    0 讨论(0)
  • 2020-12-01 13:20

    For those who prefer regular expression and to handle format like DDMMSS.ffffdS This function could easily be updated to handle other format.

    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;
    
                }
    
    0 讨论(0)
提交回复
热议问题