Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

Longitude-Latitude String Parser and Formatter

4.58/5 (11 votes)
21 Sep 20064 min read 1   1.3K  
A class for longitude and latitude values so as to parse the string to render a double, or format a double into a string.

Sample Image - llstr.gif

Introduction

CLongLatString is a class to be used to parse any one of the many forms of representation of longitude or latitude to a double, or format a double that represents a geographic co-ordinate to a nice-looking geographic co-ordinate string.

Background

The Earth is divided up into a geographic grid lines of longitude and latitude. Longitude measures the angular distance east and west from Greenwich, England. Latitude measures the angular distance north and south from the Equator. Lines of equal longitude converge at the poles, while lines of equal latitude are parallel lines that circle the Earth. This is only one geographic coordinate system among many, but it is by far the most universally used and understood.

These co-ordinates are often expressed in terms of a hemisphere (N, S, E, and W), degrees, minutes, and seconds of arc. Some use decimal degrees, degree-minutes, or degree-minute-second combinations. Some replace the hemisphere with positive/negative signs (East is positive). On top of that, a wide number of delimiters and placements complicate the format, some leave out delimiters altogether, usually the last term is decimal while the previous are integers, and some run all the data together to save space, and the hemisphere term can be located anywhere in the co-ordinate.

Some examples of various geographic co-ordinate formats:

45:26:46N,     65:56:55W
45:26:46.302N, 65:56:55.903W
45°26’21"N,    65°58’36"W
45N26 21,      65W58 36
45.446195N,    65.948862W
45.446195,     -65.948862
N45° 26.7717’, W65° 56.93172’

Using the code

This class has a fairly powerful (I think) ability to automatically parse that data and extract the numeric value. This allows you, for example, to offer up one edit box for each geographic co-ordinate instead of a combo box for hemisphere and separate inputs for each of degree, minutes, and seconds.

CLongLatString is a class that deals with these various formats for longitude and latitude so that it can be easily handled and converted to double values for use with other geographic methods. The object maintains a double and a string for each value. The string is kept because sometimes there is a need to retain the original data, so as to maintain precision. You can output the string value from a double in the same way you can format CTime from a time_t using printf-like values, %C, %c, %H %h %D, %d, %M, %m, %S, and %s as the parameters.

CLongLatString does not deal with co-ordinates in pairs - it is more effective to have one object each with a value to indicate whether it is a longitude or latitude. So if you are initializing the data with a plain double, you must also indicate whether the value is longitude or latitude if you want to get any meaningful result out of it.

There are large number of constructors and a copy constructor. You can initialize it with a string or a double as needed. There are also conversion operators and assignment operators so you can easily convert to double or standard strings.

CLongLatString llstrLat1("45N54.2356");
CLongLatString llstrLat2("-45.98739874", LL_LATITUDE);
CLongLatString llstrLat5(-45.98739874, LL_LATITUDE);
CLongLatString llstrLat7("N", "45", "34", "33");
CLongLatString llstrLat8("N455698735", "HDDMMmmmmm");

If you are going to use the assignment operator with a double or a string that contains a text double, you must initialize that object to tell it whether it is a long or lat.

CLongLatString llstrLat(LL_LATITUDE);
llstrLat = -5.877789;
std::string str = llstrLat.Format("%Dd%M\’%S\"%H");
cout << str.c_str() << endl;
// Output -    5d52’40"S
llstrLat = -5.997789;   // Can be reused - still a latitude
str = llstrLat.Format("%Dd%M\’%S\"%H");
cout << str.c_str() << endl;

or a more complicated example:

std::string str = llstrLat.Format("%H%02D %.5m");
// Output -    S05 52.66734

Output Format

%H - hemisphere - single character of N,S,E,W
%C - integer co-ordinate, may be negative or positive
%c - decimal co-ordinate, the entire co-ordinate,
         may be negative or positive
%D - integer degrees, always positive
%M - integer degrees, always positive
%S - integer seconds, always positive, rounded
%d - decimal degrees, always positive
%m - decimal minutes, always positive
%s - decimal seconds, always positive
%% - for %

Standard printf formats may be used e.g. %03D to create three spaces with leading zeroes for integer degrees or %.5m to write decimal minutes out five places. The upper case identifiers use the same printf identifiers as for decimal (integer) formats, while the lower case identifiers use the floating point formats. All other flags will work as well as the entire substring is passed to the snprintf C function.

There are integer Get...() methods for each of the terms in integer and decimal form. If you need to extract string forms individually for each of the terms you can reuse the Format() method.

For example:

CLongLatString llstrLat(-5.9879875, LL_LATITUDE);
std::string strHemi = llstrLat.Format("%H");
std::string strDeg = llstrLat.Format("%02D");
std::string strMin = llstrLat.Format("%02M");
std::string strSec = llstrLat.Format("%05.2s");

Input Format

The input format is different and can only be used for cases of fixed length (e.g. "HDD MM.mmmmm" for "N45 04.25764") and is only used when the format is quite confusing and runs together. For most case in which the degrees, minute, seconds are separated by any whitespace or most delimiters, unspecified default input format should work. H indicates the location of the hemisphere, upper case character indicate the portion that is a digit to the left of the decimal place and lower case indicate digits that are to the right.

For example:

std::string strInputFormat = "HDDMMmmmmm";
CLongLatString llstrLat1("N650490807", strInputFormat);
CLongLatString llstrLat2;
llstrLat2.Set("N450490807", strInputFormat);
llstrLat2.Set("N45°04.0807\’");
    // No input format needed if there are enough delimiters

One caveat - don't input exponential notation in a string - it will misinterpret the "E" as East and will mangle the result. Be sure to use atof() on the argument before passing it on to the constructor or Set method.

That covers it. You can take a look at the methods provided in the header file and it repeats some of the format specs there, the methods are provided with a one line comment explanation. Let me know if there are any scientific accuracy problems or serious bugs.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here