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.