tags:

views:

2941

answers:

3

I've got a CSV file containing latitude and longitude values, such as:

"25°36'55.57""E","45°39'12.52""N"

Anyone have a quick and simple piece of C# code to convert this to double values?

Thanks

+7  A: 

If you mean C# code to do this:

result = 25 + (36 / 60) + (55.57 / 3600)

First you'll need to parse the expression with Regex or some other mechanism and split it into the individual parts. Then:

String hour = "25";
String minute = "36";
String second = "55.57";
Double result = (hour) + (minute) / 60 + (second) / 3600;

And of course a switch to flip sign depending on N/S or E/S. Wikipedia has a little on that:

For calculations, the West/East suffix is replaced by a negative sign in the western hemisphere. Confusingly, the convention of negative for East is also sometimes seen. The preferred convention -- that East be positive -- is consistent with a right-handed Cartesian coordinate system with the North Pole up. A specific longitude may then be combined with a specific latitude (usually positive in the northern hemisphere) to give a precise position on the Earth's surface. (http://en.wikipedia.org/wiki/Longitude)

amdfan
You have minor error in code - second division (of seconds) should be by 3600.
Jakub Kotrla
The correct formula is: result = deg + (min / 60) + (sec / 3600);
holiveira
isn't that what I have? order of operations dictates that division will be done before addition.
amdfan
Might want to change your Strings to doubles.
Ron Warholic
A: 

What are you wanting to represent it as? Arc seconds? Then 60 min in every degree, 60 seconds in every minute. You would then have to keep E and N by yourself.

This is not how it's done generally though.

The easiest representation I've seen to work with is a point plotted on the globe on a grid system that has its origin through the center of the earth.[Thus a nice position vector.] The problem with this is that while it's easy to use the data, getting it into and out of the system correctly can be tough, because the earth is not round, or for that matter uniform.

Dan Blair
+4  A: 

Thanks for all the quick answers. Based on the answer by amdfan, I put this code together that does the job in C#.

/// <summary>The regular expression parser used to parse the lat/long</summary>
private static Regex Parser = new Regex("^(?<deg>[-+0-9]+)[^0-9]+(?<min>[0-9]+)[^0-9]+(?<sec>[0-9.,]+)[^0-9.,ENSW]+(?<pos>[ENSW]*)$");

/// <summary>Parses the lat lon value.</summary>
/// <param name="value">The value.</param>
/// <remarks>It must have at least 3 parts 'degrees' 'minutes' 'seconds'. If it 
/// has E/W and N/S this is used to change the sign.</remarks>
/// <returns></returns>
public static double ParseLatLonValue(string value)
{
    // If it starts and finishes with a quote, strip them off
    if (value.StartsWith("\"") && value.EndsWith("\""))
    {
        value = value.Substring(1, value.Length - 2).Replace("\"\"", "\"");
    }

    // Now parse using the regex parser
    Match match = Parser.Match(value);
    if (!match.Success)
    {
        throw new ArgumentException(string.Format(CultureInfo.CurrentUICulture, "Lat/long value of '{0}' is not recognised", value));
    }

    // Convert - adjust the sign if necessary
    double deg = double.Parse(match.Groups["deg"].Value);
    double min = double.Parse(match.Groups["min"].Value);
    double sec = double.Parse(match.Groups["sec"].Value);
    double result = deg + (min / 60) + (sec / 3600);
    if (match.Groups["pos"].Success)
    {
        char ch = match.Groups["pos"].Value[0];
        result = ((ch == 'S') || (ch == 'W')) ? -result : result;
    }
    return result;
}
Nick R