How to Boost Database Development Productivity on Linux, Docker, and Kubernetes with Microsoft SQL Server 2017
Many maps come with both a Latitude/Longitude grid for a given datum/ellipsoid as well as a Universal Transverse Mercator (UTM) grid to determine coordinates. There are many applications today that utilize some form of mapping capability. That, along with the increasing need to integrate GPS units (which typically provide UTM coordinates) with applications, made me think that a control for entering and displaying UTM Coordinates would be useful to keep around.
So I developed CGCUTMCoordinateCtrl and derived it from my new Multi-Field Edit Control class, CGCMultiFieldEdit, to provide a single control for entering and displaying UTM Coordinates.
First, I'll hit the high-points of the UTM Coordinate System.
The Universal Transverse Mercator Coordinate System consists of 60 vertical (North/South) UTM Zones that start at the 180 degree longitude meridian and wrap around the Earth towards the East and are numbered 1 through 60. Each UTM Zone is 6 degrees wide. Thus, UTM Zone 1 begins at 180 Degrees West and extends east to 174 Degrees West. The system is further divided into 20 horizonal (East/West) bands that start at -80 degrees south latitude with band labeled "C" and ends north to +84 degrees latitude with band "X". Bands "I" and "O" are skipped to avoid confusion with the numbers 1 and 0 respectively.
Coordinates are given in Easting and Northing values expressed in meters. The north/south component of the coordinate, or Northing, is expressed in meters relative to the Equator. It may sound strange but when specifying a coordinate's position North of the Equator, or Northing, the Equator is assigned a value of 0 meters. But when giving a coordinate's position south of the Equator, still refered to as the Northing, the Equator is assumed a value of 10,000,000 meters and the Northing for the coordinate is expressed as a positive value relative to the 10,000,000 meter Equator. So, if you were expressing a coordinate in the Southern Hemisphere that was 60,000 meters south of the Equator, that coordinate would have a Northing of 9,940,000 meters.
The East/West component of a UTM Coordinate, or the Easting, is expressed relative to an imaginary line that runs down the middle of each of the UTM Zones. This line is called the Central Meridian and is arbitrarily assigned an Easting of 500,000 meters. All UTM Zones are subdivided down the middle by a Central Meridian assigned an Easting of 500,000 meters. The Easting value of a UTM coordinate is expressed relative to the Central Meridian in the same way that the Northing is expressed relative to the Equator. Only the Central Meridian doesn't change value like the Equator does depending on which side of the Central Meridian that your standing on. So, a coordinate that is 1,000 meters to the West of the Central Meridian of any given UTM Zone has an Easting of 499,000 meters.
This scheme allows the UTM Coordinate System to avoid the use of negative numbers. It also permits two different coordinates to have the same Northing and the same Easting!
So, how can we uniquely identify a coordinate on the Earth? You must, at a minimum, use the UTM Zone, numbered 1 through 60, along with the Easting and Northing values. Alternately, since the Northing values are typically expressed relative to the Equator, some mapping applications occasionally use "N" or "North" and "S" or "South" to indicate the hemisphere instead of using the UTM Band.
Due to the arbitrary Northing values assigned to the Equator and the Easting value assigned to all UTM Zone Central Meridians, Easting and Northing values are often referred to as "False Easting" and "False Northing".
A lot of work just to avoid negative numbers, huh?
Now, to add to your confusion, there are numerous ways in which the Easting and Northing values themselves may be abbreviated! This, together with the fact that the UTM system is only good to -80 degrees latitude and +84 degrees latitude, is why most pilots (from what I understand) like to use good ole latitude and longitude.
Further, the amount of abbreviation may vary according to the convention adopted for a particular map or application.
So, I have created a control class that has the ability to be reformatted to most forms in which you are likely to see a UTM Coordinate represented.
Following is a description of the styles supported by CGCUTMCoordinateCtrl.
UTM Zone Styles
- CGCUTMCoordinateCtrl::GCS_ZONE (DEFAULT)
The UTM Zone is used in the control. This will be the first field on the left in the control and will be used to display/enter a number from 1 to 60 that represents the UTM Zone. Often, a particular application may not need to keep track of the zone in which a particular coordinate is located. Or, it may keep track of it by some other means. Therefore, I provide the ability to eliminate the UTM Zone from the control or to use it.
A UTM Coordinate without a UTM Zone. You would use this if you had an application that only need to concern itself with a geographic area confined to a single UTM Zone or if the application kept track of the zone by other means.
Hemisphere Indicator Styles
- CGCUTMCoordinateCtrl::GCS_HEM_BAND (DEFAULT)
The UTM Band is used in the control. This will be the second field from the left and will be used to display/enter a character in the range of "C" to "X" skipping "I" and "O" to specify a UTM Band. Again, there may not be a need to use this in a given application so I provide the ability to eliminate the UTM Band from the control or to use it. This will be the second field from the left if the UTM Zone is being used (the control has GCS_ZONE style). If the control is not using the UTM Zone (the control has GCS_NO_ZONE style), then the UTM Band indicator will be the first field on the left.
If you specify this style, the control will use "N" and "S" to indicate the Northern or Southern hemisphere instead of the UTM Band. Again, this will be the second field from the left provided that the UTM Zone is being used (the control has the GCS_ZONE style). If the UTM Zone is not being used (the control has style GCS_NO_ZONE), then the hemisphere indicator will be the first field on the left.
A UTM Coordinate with no hemisphere indicator or band indicator. This would be used if the application only needed to work in either the Northern hemisphere or the Southern hemisphere but not both. Or if the application kept track of the hemisphere or UTM Band by other means.
The Easting and Northing values are always displayed with the Easting displayed to the left of the Northing as is customary when specifying UTM coordinates.
This class implements a UTM coordinate entry/display control capable of displaying abbreviated coordinates. Typically, when abbreviating a UTM Coordinate, the digits representing 1,000,000 meters and 100,000 meters are dropped. The 1 meter, 10 meter and 100 meter digits are used according to the accuracy you need. That is, to increase the accuracy, a digit is added. This results is several possible formats for the amount of abbreviation that this control should handle.
To support this, I have defined the following additional styles:
Easting/Nothing Abbreviation StylesNOTE: When describing the following abbreviation styles, the 10,000,000m digit is ignored for Northing values expressed for Southern coordinates because my design treats the 10,000,000 meter mark as 0.
The 1,000,000m and 100,000m digits are dropped along with the 1m, 10m, and 100m digits. The result would be Easting and Northing values with only 2 digits each. These are the 1,000m and 10,000m digits. This would define a 1000 square meter area.
The 1,000,000m and 100,000m digits are dropped along with the 1m, and 10m digits. The result would be Easting and Northing values with 3 digits each. This would define a 100 square meter area.
The 1,000,000m and 100,000m digits are dropped along with the 1m digit. The result would be Easting and Northing values with 4 digits each. This would define a 10 square meter area.
The 1,000,000m and 100,000m digits are dropped only. The result would be Easting and Northing values with 5 digits each. This would define a 1 square meter area.
- CGCUTMCoordinateCtrl::GCS_FULL (DEFAULT)
All digits, including the 1,000,000m and 100,000m digits are used. This too would define a 1 square meter area, it just throughs in the digits that usually aren't needed.
Easting/Northing Separator StylesOften, when abbreviating a UTM coordinate, the Easting and Northing values are concatenated. Thus, an abbreviated UTM coordinate such as Easting 04 and Northing 91 would be written as "0491". So, the CGCUTMCoordinateCtrl class provides a style to allow the programmer to display/enter Easting and Northing values juxtaposed in this manner.
- CGCUTMCoordinateCtrl::GCS_SEP (DEFAULT)
Specifies that a field separator be used between the Easting and Northing fields. This is the default.
This specifies that no field separator be used when displaying the Easting and Northing fields. I do not personnaly like this style but the fact is, when abbreviated UTM Easting and Northing values are written/displayed, they are often concatenated into a single string of numbers. Therefore, I provide a style that allows you to not use a separator between the Easting and Northing fields.
Finally, one additional style is defined:
This is equivalent to applying the GCS_FULL, GCS_HEM_BAND, GCS_ZONE and GCS_SEP styles. In other words, a complete, unabbreviated UTM coordinate.
The client calls the public method
CGCUTMCoordinateCtrl::SetStyle(const UINT Style = GCS_DEFAULT)
to set the style desired. The styles may be logically ORed together in a single call.
There is a corresponding method to obtain the current style of the control:
UINT CGCUTMCoordinateCtrl::GetStyle() const;
The application may call the method
BOOL CGCUTMCoordinateCtrl::Set(const UINT Zone, const char HemisphereIndicator, const unsigned long Easting, const unsigned long Northing);
to set the control to display a specific UTM Coordinate.
If the current style of the control includes the style GCS_NO_ZONE, the Zone parameter of the method Set() will be ignored. Further, if the control has the style GCS_NOHEM, the HemisphereIndicator parameter will also be ignored.
If the control has the style GCS_ZONE, then the Zone parameter must be in the range of 1 to 60. If the control has the style GCS_HEM_BAND, the HemisphereIndicator must be in the range of 'C' to 'X' excluding 'I' and 'O'. If the control has the style GCS_HEM_NS, then the HemisphereIndicator parameter must be either 'N' or 'S'.
The Easting and Northing parameters for the Set() method are validated for range according to the current accuracy (abbreviation) style of the control. Specifically, they are validated as follows:
- If the style is GCS_FULL, the Easting value must be in the range of 0 to 1,000,000 and the Northing value must be in the range of 0 to 9,999,999.
- If the style is GCS_1_METER, both the Easting and Northing values must be in the range of 0 to 99,999.
- If the style is GCS_10_METER, both the Easting and Northing values must be in the range of 0 to 9,999.
- If the style is GCS_100_METER, both the Easting and Northing values must be in the range of 0 to 999.
- If the style is GCS_1000_METER, both the Easting and Northing values must be in the range of 0 to 99.
If the restrictions on the input parameters to the Set() method are not met, then the control will not be changed and the method will return FALSE.
A public method is provided to obtain the currently displayed coordinate:
void CGCUTMCoordinateCtrl::Get(UINT& Zone, char& HemisphereIndicator, unsigned long& Easting, unsigned long& Northing) const;
If the control has the style GCS_NO_ZONE, 0 will be returned in the Zone parameter. If the control has the style GCS_HOHEM, then ' ' will be returned for the HemisphereIndicator.
This control performs no validation on the input such as correct Easting/Northing values for a particular Zone and Band. It is the responsibility of the application to validate the data entered into the Easting and Northing fields. This class is intended as a data-entry/data display control class and not a library of coordinate conversion/calculation routines.
One final note, I have derived my CGCMultiFieldEdit class from my CGCColorEdit class to provide the capability to change the background and text colors for the control as well as control the font used. If you do not need these capabilities, you may modify CGCMultiFieldEdit to derive directly from CEdit and the control will still work perfectly.
The demo program allows you to apply the different styles to the control and observe their affects. I have provided many comments in the source code so it should be easy to understand.
I hope that this control proves useful.