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.
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:
45N26 21, 65W58 36
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 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.
llstrLat = -5.877789;
std::string str = llstrLat.Format("%Dd%M\’%S\"%H");
cout << str.c_str() << endl;
llstrLat = -5.997789; 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");
%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
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");
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.
std::string strInputFormat = "HDDMMmmmmm";
CLongLatString llstrLat1("N650490807", strInputFormat);
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.