nerdegutta.no
C: Convert Lat Lon to MGRS
18.08.24
Programming
Creating a C program that converts latitude and longitude to the Military Grid Reference System (MGRS) without using any external libraries involves several steps. The MGRS is a geocoordinate standard used by NATO militaries for locating points on the Earth. It's based on the Universal Transverse Mercator (UTM) coordinate system and the Universal Polar Stereographic (UPS) coordinate system.
Here’s an outline of the process:
Convert Latitude/Longitude to UTM:
#include < stdio.h > #include < math.h > // Constants #define WGS84_A 6378137.0 // major axis #define WGS84_F 298.257223563 // flattening #define WGS84_E2 (1 - (1 - 1 / WGS84_F) * (1 - 1 / WGS84_F)) // first eccentricity squared // Function prototypes void latLonToUTM(double lat, double lon, int *zone, double *easting, double *northing); void utmToMGRS(int zone, double easting, double northing, char *mgrs); // Helper functions int getZone(double lon); double degToRad(double deg); double radToDeg(double rad); int main() { double lat = 37.7749; // example latitude double lon = -122.4194; // example longitude int zone; double easting, northing; char mgrs[20]; // Convert latitude/longitude to UTM latLonToUTM(lat, lon, &zone, &easting, &northing); // Convert UTM to MGRS utmToMGRS(zone, easting, northing, mgrs); // Print the results printf("MGRS: %s ", mgrs); return 0; } // Converts latitude/longitude to UTM coordinates void latLonToUTM(double lat, double lon, int *zone, double *easting, double *northing) { double k0 = 0.9996; // scale factor double lon0, e2, N, T, C, A, M; *zone = getZone(lon); lon0 = ((*zone - 1) * 6 - 180 + 3) * M_PI / 180; // Central meridian lat = degToRad(lat); lon = degToRad(lon); e2 = WGS84_E2; N = WGS84_A / sqrt(1 - e2 * sin(lat) * sin(lat)); T = tan(lat) * tan(lat); C = e2 * cos(lat) * cos(lat) / (1 - e2); A = cos(lat) * (lon - lon0); M = WGS84_A * ((1 - e2 / 4 - 3 * e2 * e2 / 64 - 5 * e2 * e2 * e2 / 256) * lat - (3 * e2 / 8 + 3 * e2 * e2 / 32 + 45 * e2 * e2 * e2 / 1024) * sin(2 * lat) + (15 * e2 * e2 / 256 + 45 * e2 * e2 * e2 / 1024) * sin(4 * lat) - (35 * e2 * e2 * e2 / 3072) * sin(6 * lat)); *easting = k0 * N * (A + (1 - T + C) * A * A * A / 6 + (5 - 18 * T + T * T + 72 * C - 58 * e2) * A * A * A * A * A / 120) + 500000.0; *northing = k0 * (M + N * tan(lat) * (A * A / 2 + (5 - T + 9 * C + 4 * C * C) * A * A * A * A / 24 + (61 - 58 * T + T * T + 600 * C - 330 * e2) * A * A * A * A * A * A / 720)); // If in the southern hemisphere, adjust the northing if (lat < 0) *northing += 10000000.0; } // Determines the UTM zone from longitude int getZone(double lon) { return (int)((lon + 180) / 6) + 1; } // Converts degrees to radians double degToRad(double deg) { return deg * M_PI / 180.0; } // Converts radians to degrees double radToDeg(double rad) { return rad * 180.0 / M_PI; } // Converts UTM coordinates to MGRS void utmToMGRS(int zone, double easting, double northing, char *mgrs) { int e100k = (int)(easting / 100000.0); int n100k = (int)(northing / 100000.0) % 20; char e100kLetters[] = "ABCDEFGHJKLMNPQRSTUV"; char n100kLetters[] = "ABCDEFGHJKLMNPQRSTUV"; int eIndex = e100k % 8; int nIndex = (zone % 2 == 0) ? (n100k + 5) % 20 : n100k; snprintf(mgrs, 20, "%02d%c%c %05d %05d", zone, e100kLetters[eIndex], n100kLetters[nIndex], (int)fmod(easting, 100000), (int)fmod(northing, 100000)); }Explanation:
gcc LatlonToMGRS.c -Wall -lmImportant here is the -lm-parameter. This parameter link in the math.h library that we include in line #2, in the source code. I do not have an output name, so gcc will use the standard a.out-filename. When compiling is successful, you can run the program with ./a.out.