123 using namespace MSP::CCS;
131 #define EPSILON 1.75e-7
160 #define ONEHT 100000.e0
161 #define TWOMIL 2000000.e0
164 #define PI 3.14159265358979323e0
165 #define PI_OVER_2 (PI / 2.0e0)
166 #define PI_OVER_180 (PI / 180.0e0)
168 #define MIN_EASTING 100000.0
169 #define MAX_EASTING 900000.0
170 #define MIN_NORTHING 0.0
171 #define MAX_NORTHING 10000000.0
172 #define MAX_PRECISION 5
173 #define MIN_MGRS_NON_POLAR_LAT (-80.0 * ( PI / 180.0 ))
174 #define MAX_MGRS_NON_POLAR_LAT ( 84.0 * ( PI / 180.0 ))
176 #define MIN_EAST_NORTH 0.0
177 #define MAX_EAST_NORTH 3999999.0
179 #define _6 (6.0 * (PI / 180.0))
180 #define _8 (8.0 * (PI / 180.0))
181 #define _72 (72.0 * (PI / 180.0))
182 #define _80 (80.0 * (PI / 180.0))
183 #define _80_5 (80.5 * (PI / 180.0))
184 #define _84_5 (84.5 * (PI / 180.0))
186 #define _500000 500000.0
194 #define CLARKE_1866 "CC"
195 #define CLARKE_1880 "CD"
196 #define BESSEL_1841 "BR"
197 #define BESSEL_1841_NAMIBIA "BN"
199 #define EPSILON2 4.99e-4
211 {
LETTER_C, 1100000.0, -72.0, -80.5, 0.0},
212 {
LETTER_D, 2000000.0, -64.0, -72.0, 2000000.0},
213 {
LETTER_E, 2800000.0, -56.0, -64.0, 2000000.0},
214 {
LETTER_F, 3700000.0, -48.0, -56.0, 2000000.0},
215 {
LETTER_G, 4600000.0, -40.0, -48.0, 4000000.0},
216 {
LETTER_H, 5500000.0, -32.0, -40.0, 4000000.0},
217 {
LETTER_J, 6400000.0, -24.0, -32.0, 6000000.0},
218 {
LETTER_K, 7300000.0, -16.0, -24.0, 6000000.0},
219 {
LETTER_L, 8200000.0, -8.0, -16.0, 8000000.0},
220 {
LETTER_M, 9100000.0, 0.0, -8.0, 8000000.0},
222 {
LETTER_P, 800000.0, 16.0, 8.0, 0.0},
223 {
LETTER_Q, 1700000.0, 24.0, 16.0, 0.0},
224 {
LETTER_R, 2600000.0, 32.0, 24.0, 2000000.0},
225 {
LETTER_S, 3500000.0, 40.0, 32.0, 2000000.0},
226 {
LETTER_T, 4400000.0, 48.0, 40.0, 4000000.0},
227 {
LETTER_U, 5300000.0, 56.0, 48.0, 4000000.0},
228 {
LETTER_V, 6200000.0, 64.0, 56.0, 6000000.0},
229 {
LETTER_W, 7000000.0, 72.0, 64.0, 6000000.0},
230 {
LETTER_X, 7900000.0, 84.5, 72.0, 6000000.0}};
258 double scale = 1.0e5;
316 char alphabet[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
320 i = sprintf (MGRSString+i,
"%2.2ld",zone);
322 strncpy(MGRSString,
" ", 2);
325 MGRSString[i++] = alphabet[letters[j]];
329 easting = fmod (easting, 100000.0);
330 if (easting >= 99999.5)
332 east = (long)((easting+
EPSILON2) /divisor);
333 i += sprintf (MGRSString+i,
"%*.*ld", precision, precision, east);
334 northing = fmod (northing, 100000.0);
335 if (northing >= 99999.5)
337 north = (long)((northing+
EPSILON2) /divisor);
338 i += sprintf (MGRSString+i,
"%*.*ld", precision, precision, north);
368 char tempMGRSString[100+1];
369 while( MGRSString[i] !=
'\0' || j == 100 )
371 if( MGRSString[i] !=
' ' )
374 if (!isdigit(MGRSString[i]) && !isalpha(MGRSString[i]) )
376 tempMGRSString[j] = MGRSString[i];
381 tempMGRSString[j] =
'\0';
386 while (tempMGRSString[i] ==
' ')
389 while (isdigit(tempMGRSString[i]))
397 strncpy (zone_string, tempMGRSString+j, 2);
399 sscanf (zone_string,
"%ld", zone);
400 if ((*zone < 1) || (*zone > 60))
409 while (isalpha(tempMGRSString[i]))
412 if (num_letters == 3)
415 letters[0] = (toupper(tempMGRSString[j]) - (long)
'A');
418 letters[1] = (toupper(tempMGRSString[j+1]) - (long)
'A');
421 letters[2] = (toupper(tempMGRSString[j+2]) - (long)
'A');
428 while (isdigit(tempMGRSString[i]))
431 if ((num_digits <= 10) && (num_digits%2 == 0))
435 char north_string[6];
446 strncpy (east_string, tempMGRSString+j, n);
448 sscanf (east_string,
"%ld", &east);
449 strncpy (north_string, tempMGRSString+j+n, n);
451 sscanf (north_string,
"%ld", &north);
453 halfMulti = multiplier * 0.5;
455 *easting = east * multiplier + halfMulti;
456 *northing = north * multiplier + halfMulti;
476 double ellipsoidSemiMajorAxis,
477 double ellipsoidFlattening,
478 char* ellipsoidCode ) :
493 double inv_f = 1 / ellipsoidFlattening;
495 if (ellipsoidSemiMajorAxis <= 0.0)
499 if ((inv_f < 250) || (inv_f > 350))
507 strncpy (MGRSEllipsoidCode, ellipsoidCode, 2);
508 MGRSEllipsoidCode[2] =
'\0';
518 ups =
new UPS( *( m.ups ) );
519 utm =
new UTM( *( m.utm ) );
523 strcpy( MGRSEllipsoidCode, m.MGRSEllipsoidCode );
541 ups->operator=( *m.ups );
542 utm->operator=( *m.utm );
546 strcpy( MGRSEllipsoidCode, m.MGRSEllipsoidCode );
590 double latitude = geodeticCoordinates->
latitude();
591 double longitude = geodeticCoordinates->
longitude();
613 mgrsorUSNGCoordinates = fromUTM(
614 utmCoordinates, longitude, latitude, precision );
615 delete utmCoordinates;
621 mgrsorUSNGCoordinates = fromUPS( upsCoordinates, precision );
622 delete upsCoordinates;
627 delete utmCoordinates;
628 delete upsCoordinates;
632 return mgrsorUSNGCoordinates;
654 double mgrs_northing;
661 mgrsorUSNGCoordinates->
MGRSString(), &zone, letters,
662 &mgrs_easting, &mgrs_northing, &precision );
668 utmCoordinates = toUTM(
669 zone, letters, mgrs_easting, mgrs_northing, precision );
676 delete utmCoordinates;
681 upsCoordinates = toUPS( letters, mgrs_easting, mgrs_northing );
683 delete upsCoordinates;
689 delete utmCoordinates;
690 delete upsCoordinates;
694 return geodeticCoordinates;
716 long zone = utmCoordinates->
zone();
717 char hemisphere = utmCoordinates->
hemisphere();
718 double easting = utmCoordinates->
easting();
719 double northing = utmCoordinates->
northing();
725 if ((zone < 1) || (zone > 60))
727 if ((hemisphere !=
'S') && (hemisphere !=
'N'))
743 double latitude = geodeticCoordinates->
latitude();
747 mgrsorUSNGCoordinates = fromUTM(
749 geodeticCoordinates->
longitude(), latitude, precision);
753 mgrsorUSNGCoordinates = fromUPS( upsCoordinates, precision );
758 delete upsCoordinates;
759 delete geodeticCoordinates;
763 delete upsCoordinates;
764 delete geodeticCoordinates;
766 return mgrsorUSNGCoordinates;
788 double mgrs_easting, mgrs_northing;
797 mgrsorUSNGCoordinates->
MGRSString(), &zone, letters,
798 &mgrs_easting, &mgrs_northing, &precision );
801 utmCoordinates = toUTM(
802 zone, letters, mgrs_easting, mgrs_northing, precision );
809 upsCoordinates = toUPS( letters, mgrs_easting, mgrs_northing );
816 delete utmCoordinates;
817 delete upsCoordinates;
818 delete geodeticCoordinates;
822 delete upsCoordinates;
823 delete geodeticCoordinates;
825 return utmCoordinates;
848 char hemisphere = upsCoordinates->
hemisphere();
849 double easting = upsCoordinates->
easting();
850 double northing = upsCoordinates->
northing();
856 if ((hemisphere !=
'N') && (hemisphere !=
'S'))
872 double latitude = geodeticCoordinates->
latitude();
876 mgrsorUSNGCoordinates = fromUPS( upsCoordinates, precision );
880 double longitude = geodeticCoordinates->
longitude();
881 mgrsorUSNGCoordinates = fromUTM(
882 utmCoordinates, longitude, latitude, precision );
887 delete utmCoordinates;
888 delete geodeticCoordinates;
892 delete utmCoordinates;
893 delete geodeticCoordinates;
895 return mgrsorUSNGCoordinates;
918 double mgrs_northing;
928 &zone, letters, &mgrs_easting, &mgrs_northing, &precision );
932 upsCoordinates = toUPS( letters, mgrs_easting, mgrs_northing );
939 utmCoordinates = toUTM(
940 zone, letters, mgrs_easting, mgrs_northing, precision );
952 delete utmCoordinates;
953 delete upsCoordinates;
954 delete geodeticCoordinates;
958 delete utmCoordinates;
959 delete geodeticCoordinates;
961 return upsCoordinates;
985 double pattern_offset;
986 double grid_northing;
988 long ltr2_high_value;
994 long zone = utmCoordinates->
zone();
995 char hemisphere = utmCoordinates->
hemisphere();
996 double easting = utmCoordinates->
easting();
997 double northing = utmCoordinates->
northing();
999 getLatitudeLetter( latitude, &letters[0] );
1006 natural_zone = (long)(31 + ((longitude+pad) /
_6));
1010 natural_zone = (long)(((longitude+pad) /
_6) - 29);
1013 if (natural_zone > 60)
1015 if (zone != natural_zone)
1021 utmOverride.convertFromGeodetic( &geodeticCoordinates );
1023 zone = utmCoordinatesOverride->
zone();
1024 hemisphere = utmCoordinatesOverride->
hemisphere();
1025 easting = utmCoordinatesOverride->
easting();
1026 northing = utmCoordinatesOverride->
northing();
1028 delete utmCoordinatesOverride;
1029 utmCoordinatesOverride = 0;
1035 if ((zone == 31) && (easting >=
_500000))
1040 if ((zone == 32) && (easting <
_500000))
1042 else if (((zone == 32) && (easting >=
_500000)) ||
1043 ((zone == 34) && (easting <
_500000)))
1045 else if (((zone == 34) && (easting >=
_500000)) ||
1046 ((zone == 36) && (easting <
_500000)))
1048 else if ((zone == 36) && (easting >=
_500000))
1058 utmOverride.convertFromGeodetic( &geodeticCoordinates );
1060 zone = utmCoordinatesOverride->
zone();
1061 hemisphere = utmCoordinatesOverride->
hemisphere();
1062 easting = utmCoordinatesOverride->
easting();
1063 northing = utmCoordinatesOverride->
northing();
1065 delete utmCoordinatesOverride;
1066 utmCoordinatesOverride = 0;
1071 easting = ( long )( (easting +
EPSILON2) /divisor ) * divisor;
1072 northing = ( long )( (northing+
EPSILON2) /divisor ) * divisor;
1074 if( latitude <= 0.0 && northing == 1.0e7 )
1080 getGridValues( zone, <r2_low_value, <r2_high_value, &pattern_offset );
1082 grid_northing = northing;
1084 while (grid_northing >=
TWOMIL)
1086 grid_northing = grid_northing -
TWOMIL;
1088 grid_northing = grid_northing + pattern_offset;
1089 if(grid_northing >=
TWOMIL)
1090 grid_northing = grid_northing -
TWOMIL;
1092 letters[2] = (long)(grid_northing /
ONEHT);
1094 letters[2] = letters[2] + 1;
1097 letters[2] = letters[2] + 1;
1099 letters[1] = ltr2_low_value + ((long)(easting /
ONEHT) - 1);
1101 letters[1] = letters[1] + 1;
1103 makeMGRSString( MGRSString, zone, letters, easting, northing, precision );
1132 double min_northing;
1133 double northing_offset;
1134 long ltr2_low_value;
1135 long ltr2_high_value;
1136 double pattern_offset;
1137 double grid_easting;
1138 double grid_northing;
1139 double temp_grid_northing = 0.0;
1140 double fabs_grid_northing = 0.0;
1141 double latitude = 0.0;
1142 double longitude = 0.0;
1143 double divisor = 1.0;
1146 if((letters[0] ==
LETTER_X) && ((zone == 32) || (zone == 34) || (zone == 36)))
1148 else if ((letters[0] ==
LETTER_V) && (zone == 31) && (letters[1] >
LETTER_D))
1157 getGridValues(zone, <r2_low_value, <r2_high_value, &pattern_offset);
1162 if((letters[1] < ltr2_low_value) ||
1163 (letters[1] > ltr2_high_value) ||
1167 grid_easting = (double)((letters[1]) - ltr2_low_value + 1) *
ONEHT;
1169 grid_easting = grid_easting -
ONEHT;
1171 double row_letter_northing = (double)(letters[2]) *
ONEHT;
1173 row_letter_northing = row_letter_northing -
ONEHT;
1176 row_letter_northing = row_letter_northing -
ONEHT;
1178 if (row_letter_northing >= TWOMIL)
1179 row_letter_northing = row_letter_northing -
TWOMIL;
1181 getLatitudeBandMinNorthing(letters[0], &min_northing, &northing_offset);
1183 grid_northing = row_letter_northing - pattern_offset;
1184 if(grid_northing < 0)
1187 grid_northing += northing_offset;
1189 if(grid_northing < min_northing)
1192 easting = grid_easting + easting;
1193 northing = grid_northing + northing;
1197 zone, hemisphere, easting, northing );
1207 delete utmCoordinates;
1211 double latitude = geodeticCoordinates->
latitude();
1213 delete geodeticCoordinates;
1214 geodeticCoordinates = 0;
1218 if( ! inLatitudeRange(letters[0], latitude,
PI_OVER_180/divisor) )
1221 long prevBand = letters[0] - 1;
1222 long nextBand = letters[0] + 1;
1225 prevBand = letters[0];
1228 nextBand = letters[0];
1236 if(inLatitudeRange( prevBand, latitude,
PI_OVER_180/divisor ) ||
1237 inLatitudeRange( nextBand, latitude,
PI_OVER_180/divisor ) )
1249 return utmCoordinates;
1269 double false_easting;
1270 double false_northing;
1271 double grid_easting;
1272 double grid_northing;
1273 long ltr2_low_value;
1277 char MGRSString[21];
1279 char hemisphere = upsCoordinates->
hemisphere();
1280 double easting = upsCoordinates->
easting();
1281 double northing = upsCoordinates->
northing();
1285 easting = (long)((easting +
EPSILON2) /divisor) * divisor;
1286 northing = (long)((northing+
EPSILON2) /divisor) * divisor;
1288 if (hemisphere ==
'N')
1290 if (easting >= TWOMIL)
1295 index = letters[0] - 22;
1302 if (easting >= TWOMIL)
1312 grid_northing = northing;
1313 grid_northing = grid_northing - false_northing;
1314 letters[2] = (long)(grid_northing / ONEHT);
1317 letters[2] = letters[2] + 1;
1320 letters[2] = letters[2] + 1;
1322 grid_easting = easting;
1323 grid_easting = grid_easting - false_easting;
1324 letters[1] = ltr2_low_value + ((long)(grid_easting / ONEHT));
1326 if (easting < TWOMIL)
1329 letters[1] = letters[1] + 3;
1332 letters[1] = letters[1] + 2;
1337 letters[1] = letters[1] + 2;
1340 letters[1] = letters[1] + 1;
1343 letters[1] = letters[1] + 3;
1346 makeMGRSString( MGRSString, 0, letters, easting, northing, precision );
1355 long letters[MGRS_LETTERS],
1371 long ltr2_high_value;
1372 long ltr3_high_value;
1373 long ltr2_low_value;
1374 double false_easting;
1375 double false_northing;
1376 double grid_easting;
1377 double grid_northing;
1385 index = letters[0] - 22;
1408 if ((letters[1] < ltr2_low_value) || (letters[1] > ltr2_high_value) ||
1412 ( letters[2] > ltr3_high_value))
1415 grid_northing = (double)letters[2] * ONEHT + false_northing;
1417 grid_northing = grid_northing -
ONEHT;
1420 grid_northing = grid_northing -
ONEHT;
1422 grid_easting = (double)((letters[1]) - ltr2_low_value) *ONEHT + false_easting;
1426 grid_easting = grid_easting - 300000.0;
1429 grid_easting = grid_easting - 200000.0;
1434 grid_easting = grid_easting - 200000.0;
1437 grid_easting = grid_easting -
ONEHT;
1440 grid_easting = grid_easting - 300000.0;
1443 easting = grid_easting + easting;
1444 northing = grid_northing + northing;
1451 void MGRS::getGridValues(
1453 long* ltr2_low_value,
1454 long* ltr2_high_value,
1455 double* pattern_offset )
1473 set_number = zone % 6;
1486 if ((set_number == 1) || (set_number == 4))
1491 else if ((set_number == 2) || (set_number == 5))
1496 else if ((set_number == 3) || (set_number == 6))
1505 if ((set_number % 2) == 0)
1506 *pattern_offset = 500000.0;
1508 *pattern_offset = 0.0;
1512 if ((set_number % 2) == 0)
1513 *pattern_offset = 1500000.0;
1515 *pattern_offset = 1000000.00;
1520 void MGRS::getLatitudeBandMinNorthing(
1522 double* min_northing,
1523 double* northing_offset )
1555 bool MGRS::inLatitudeRange(
long letter,
double latitude,
double border )
1566 bool result =
false;
1588 if( ((south - border) <= latitude) && (latitude <= (north + border)) )
1595 void MGRS::getLatitudeLetter(
double latitude,
int* letter )
1608 if (latitude >=
_72 && latitude <
_84_5)
1610 else if (latitude > -
_80_5 && latitude <
_72)
1612 band = (long)(((latitude +
_80) /
_8) + 1.0e-12);
MSP::CCS::MGRSorUSNGCoordinates * convertFromUTM(UTMCoordinates *utmCoordinates, long precision)
static const char * ellipsoidFlattening
MSP::CCS::GeodeticCoordinates * convertToGeodetic(MSP::CCS::UPSCoordinates *upsCoordinates)
MSP::CCS::UPSCoordinates * convertToUPS(MSP::CCS::MGRSorUSNGCoordinates *mgrsorUSNGCoordinates)
double computeScale(int prec)
const UPS_Constant UPS_Constant_Table[4]
#define BESSEL_1841_NAMIBIA
EllipsoidParameters * getParameters() const
static const char * longitude
MSP::CCS::GeodeticCoordinates * convertToGeodetic(MSP::CCS::MGRSorUSNGCoordinates *mgrsCoordinates)
static const char * semiMajorAxis
static const char * latitude
MGRS(double ellipsoidSemiMajorAxis, double ellipsoidFlattening, char *ellipsoidCode)
#define MIN_MGRS_NON_POLAR_LAT
MGRS & operator=(const MGRS &m)
MSP::CCS::UPSCoordinates * convertFromGeodetic(MSP::CCS::GeodeticCoordinates *geodeticCoordinates)
static const char * mgrsString
static const char * northing
static const char * precision
MSP::CCS::MGRSorUSNGCoordinates * convertFromGeodetic(MSP::CCS::GeodeticCoordinates *geodeticCoordinates, long precision)
MSP::CCS::MGRSorUSNGCoordinates * convertFromUPS(MSP::CCS::UPSCoordinates *upsCoordinates, long precision)
void makeMGRSString(char *MGRSString, long zone, int letters[MGRS_LETTERS], double easting, double northing, long precision)
MSP::CCS::UTMCoordinates * convertToUTM(MSP::CCS::MGRSorUSNGCoordinates *mgrsorUSNGCoordinates)
static const char * easting
static Enum toPrecision(int prec)
void breakMGRSString(char *MGRSString, long *zone, long letters[MGRS_LETTERS], double *easting, double *northing, long *precision)
MSP::CCS::GeodeticCoordinates * convertToGeodetic(MSP::CCS::UTMCoordinates *utmCoordinates)
void setWarningMessage(const char *__warningMessage)
const Latitude_Band Latitude_Band_Table[20]
#define MAX_MGRS_NON_POLAR_LAT
static const char * latitude
MSP::CCS::UTMCoordinates * convertFromGeodetic(MSP::CCS::GeodeticCoordinates *geodeticCoordinates, int utmZoneOverride=0)
const char * warningMessage() const
static const char * hemisphere