140 using namespace MSP::CCS;
150 const double PI = 3.14159265358979323e0;
183 {{74.5, 75.5, 273.5, 280.0},
184 {66.5, 67.5, 293.5, 295.0},
185 {62.5, 64.0, 133.0, 136.5},
186 {60.5, 61.5, 208.5, 210.0},
187 {60.5, 61.0, 219.0, 220.5},
188 {51.0, 53.0, 172.0, 174.5},
189 {52.0, 53.0, 192.5, 194.0},
190 {51.0, 52.0, 188.5, 191.0},
191 {50.0, 52.0, 178.0, 182.5},
192 {43.0, 46.0, 148.0, 153.5},
193 {43.0, 45.0, 84.0, 89.5},
194 {40.0, 41.0, 70.5, 72.0},
195 {36.5, 37.0, 78.5, 79.0},
196 {36.0, 37.0, 348.0, 349.5},
197 {35.0, 36.0, 171.0, 172.5},
198 {34.0, 35.0, 140.5, 142.0},
199 {29.5, 31.0, 78.5, 81.0},
200 {28.5, 30.0, 81.5, 83.0},
201 {26.5, 30.0, 142.0, 143.5},
202 {26.0, 29.0, 91.5, 96.0},
203 {27.5, 29.0, 84.0, 86.5},
204 {28.0, 29.0, 342.5, 344.0},
205 {26.5, 28.0, 88.5, 90.0},
206 {25.0, 26.0, 189.0, 190.5},
207 {23.0, 24.0, 195.0, 196.5},
208 {21.0, 21.5, 204.0, 204.5},
209 {20.0, 21.0, 283.5, 288.0},
210 {18.5, 20.5, 204.0, 205.5},
211 {18.0, 20.0, 291.0, 296.5},
212 {17.0, 18.0, 298.0, 299.5},
213 {15.0, 16.0, 122.0, 123.5},
214 {12.0, 14.0, 144.5, 147.0},
215 {11.0, 12.0, 141.5, 144.0},
216 {9.5, 11.5, 125.0, 127.5},
217 {10.0, 11.0, 286.0, 287.5},
218 {6.0, 9.5, 287.0, 289.5},
219 {5.0, 7.0, 124.0, 128.5},
220 {-1.0, 1.0, 125.0, 128.5},
221 {-3.0, -1.5, 281.0, 282.5},
222 {-7.0, -5.0, 150.5, 155.0},
223 {-8.0, -7.0, 107.0, 108.5},
224 {-9.0, -7.0, 147.0, 149.5},
225 {-11.0, -10.0, 161.5, 163.0},
226 {-14.5, -13.5, 166.0, 167.5},
227 {-18.5, -17.0, 186.5, 188.0},
228 {-20.5, -20.0, 168.0, 169.5},
229 {-23.0, -20.0, 184.5, 187.0},
230 {-27.0, -24.0, 288.0, 290.5},
231 {-53.0, -52.0, 312.0, 313.5},
232 {-56.0, -55.0, 333.0, 334.5},
233 {-61.5, -60.0, 312.5, 317.0},
234 {-61.5, -60.5, 300.5, 303.0},
235 {-73.0, -72.0, 24.5, 26.0}};
248 char *b = (
char *) buffer;
250 for (
size_t c = 0; c < count; c ++)
252 for (
size_t s = 0; s < size / 2; s ++)
254 temp = b[c*size + s];
255 b[c*size + s] = b[c*size + size - s - 1];
256 b[c*size + size - s - 1] = temp;
268 size_t actual_count = fread(buffer, size, count, stream);
270 if(ferror(stream) || actual_count < count )
272 char message[256] =
"";
273 strcpy( message,
"Error reading binary file." );
303 GeoidLibrary::deleteInstance();
314 int GeoidLibrary::instanceCount = 0;
336 if ( --instanceCount < 1 )
343 void GeoidLibrary::deleteInstance()
371 delete [] egm96GeoidList;
372 delete [] egm84GeoidList;
373 delete [] egm84ThirtyMinGeoidList;
390 egm96GeoidList[i] = gl.egm96GeoidList[i];
395 egm84GeoidList[j] = gl.egm84GeoidList[j];
400 egm84ThirtyMinGeoidList[k] = gl.egm84ThirtyMinGeoidList[k];
403 *( this->egm2008Geoid ) = *( gl.egm2008Geoid );
409 void GeoidLibrary::loadGeoids()
423 egm96GeoidList = NULL;
424 egm84GeoidList = NULL;
425 egm84ThirtyMinGeoidList = NULL;
432 initializeEGM96Geoid();
436 delete egm96GeoidList;
437 egm96GeoidList = NULL;
441 initializeEGM84Geoid();
445 delete egm84GeoidList;
446 egm84GeoidList = NULL;
450 initializeEGM84ThirtyMinGeoid();
454 delete egm84ThirtyMinGeoidList;
455 egm84ThirtyMinGeoidList = NULL;
462 initializeEGM2008Geoid();
470 if (egm96GeoidList == NULL &&
471 egm84GeoidList == NULL &&
472 egm84ThirtyMinGeoidList == NULL)
475 "Error: GeoidLibrary::LoadGeoids: All geoid height buffer initialization failed.");
485 double ellipsoidHeight,
486 double *geoidHeight )
500 if (egm96GeoidList == NULL)
503 "Error: EGM96 Geoid height buffer is NULL");
513 *geoidHeight = ellipsoidHeight - delta_height;
520 double ellipsoidHeight,
521 double *geoidHeight )
535 if (egm96GeoidList == NULL)
538 "Error: EGM96 Geoid height buffer is NULL");
550 if( longitude_degrees < 0.0 )
551 longitude_degrees += 360.0;
571 if( latitude_degrees >= -60.0 && latitude_degrees < 60.0 )
585 naturalSplineInterpolate(
590 *geoidHeight = ellipsoidHeight - delta_height;
597 double ellipsoidHeight,
598 double *geoidHeight )
612 if (egm84GeoidList == NULL)
615 "Error: EGM84 Geoid height buffer is NULL");
625 *geoidHeight = ellipsoidHeight - delta_height;
632 double ellipsoidHeight,
633 double *geoidHeight )
647 if (egm84GeoidList == NULL)
650 "Error: EGM84 Geoid height buffer is NULL");
655 naturalSplineInterpolate(
658 egm84GeoidList, &delta_height );
660 *geoidHeight = ellipsoidHeight - delta_height;
665 double longitude,
double latitude,
double ellipsoidHeight,
666 double *geoidHeight )
681 if (egm84GeoidList == NULL)
684 "Error: EGM84 Geoid height buffer is NULL");
689 bilinearInterpolateDoubleHeights(
692 egm84ThirtyMinGeoidList, &delta_height );
694 *geoidHeight = ellipsoidHeight - delta_height;
701 double ellipsoidHeight,
702 double *geoidHeight )
722 if (this->egm2008Geoid == NULL)
725 "Error: EGM2008 geoid buffer is NULL" );
734 double geoidSeparation;
738 ( WSIZE, latitude, longitude, geoidSeparation );
740 if ( error != 0 )
throw;
742 *geoidHeight = ellipsoidHeight - geoidSeparation;
749 "Error: Could not convert ellipsoid height to EGM2008 geoid height" );
769 if (egm96GeoidList == NULL)
772 "Error: EGM96 Geoid height buffer is NULL");
782 *ellipsoidHeight = geoidHeight + delta_height;
790 double *ellipsoidHeight )
804 if (egm96GeoidList == NULL)
807 "Error: EGM96 Geoid height buffer is NULL");
819 if( longitude_degrees < 0.0 )
820 longitude_degrees += 360.0;
840 if( latitude_degrees >= -60.0 && latitude_degrees < 60.0 )
854 naturalSplineInterpolate(
859 *ellipsoidHeight = geoidHeight + delta_height;
877 if (egm84GeoidList == NULL)
880 "Error: EGM84 Geoid height buffer is NULL");
890 *ellipsoidHeight = geoidHeight + delta_height;
898 double *ellipsoidHeight )
912 if (egm84GeoidList == NULL)
915 "Error: EGM84 Geoid height buffer is NULL");
920 naturalSplineInterpolate(
923 egm84GeoidList, &delta_height );
925 *ellipsoidHeight = geoidHeight + delta_height;
930 double longitude,
double latitude,
double geoidHeight,
931 double *ellipsoidHeight )
946 if (egm84GeoidList == NULL)
949 "Error: EGM84 Geoid height buffer is NULL");
957 *ellipsoidHeight = geoidHeight + delta_height;
965 double *ellipsoidHeight )
985 if (this->egm2008Geoid == NULL)
988 "Error: EGM2008 geoid buffer is NULL");
997 double geoidSeparation;
1001 ( WSIZE, latitude, longitude, geoidSeparation );
1003 if ( error != 0 )
throw;
1005 *ellipsoidHeight = geoidHeight + geoidSeparation;
1012 "Error: Could not convert EGM2008 geoid height to ellipsoid height" );
1023 void GeoidLibrary::initializeEGM96Geoid()
1035 char* file_name = 0;
1036 char* path_name = NULL;
1037 long elevations_read = 0;
1038 long items_discarded = 0;
1040 FILE* geoid_height_file;
1048 path_name =
"/data/data/com.baesystems.msp.geotrans/lib/";
1049 file_name =
new char[ 80 ];
1050 strcpy( file_name, path_name );
1051 strcat( file_name,
"libegm96grd.so" );
1053 path_name = getenv(
"MSPCCS_DATA" );;
1054 if (path_name != NULL)
1056 file_name =
new char[ strlen( path_name ) + 11 ];
1057 strcpy( file_name, path_name );
1058 strcat( file_name,
"/" );
1062 file_name =
new char[ 21 ];
1063 strcpy( file_name,
"../../data/" );
1065 strcat( file_name,
"egm96.grd" );
1070 if ( ( geoid_height_file = fopen( file_name,
"rb" ) ) == NULL )
1072 delete [] file_name;
1075 char message[256] =
"";
1076 if (NULL == path_name)
1078 strcpy( message,
"Environment variable undefined: MSPCCS_DATA." );
1083 strcat( message,
": egm96.grd\n" );
1096 if( egm96GeoidHeaderList[0] != -90.0 ||
1097 egm96GeoidHeaderList[1] != 90.0 ||
1098 egm96GeoidHeaderList[2] != 0.0 ||
1099 egm96GeoidHeaderList[3] != 360.0 ||
1104 fclose( geoid_height_file );
1105 delete [] file_name;
1108 char message[256] =
"";
1110 strcat( message,
": egm96.grd\n" );
1119 fclose( geoid_height_file );
1120 geoid_height_file = 0;
1122 delete [] file_name;
1127 void GeoidLibrary::initializeEGM84Geoid()
1139 char* file_name = 0;
1140 char* path_name = NULL;
1141 long elevations_read = 0;
1143 FILE* geoid_height_file;
1151 path_name =
"/data/data/com.baesystems.msp.geotrans/lib/";
1152 file_name =
new char[ 80 ];
1153 strcpy( file_name, path_name );
1154 strcat( file_name,
"libegm84grd.so" );
1156 path_name = getenv(
"MSPCCS_DATA" );
1157 if (path_name != NULL)
1159 file_name =
new char[ strlen( path_name ) + 11 ];
1160 strcpy( file_name, path_name );
1161 strcat( file_name,
"/" );
1165 file_name =
new char[ 21 ];
1166 strcpy( file_name,
"../../data/" );
1168 strcat( file_name,
"egm84.grd" );
1173 if( ( geoid_height_file = fopen( file_name,
"rb" ) ) == NULL )
1175 delete [] file_name;
1178 char message[256] =
"";
1179 if (NULL == path_name)
1181 strcpy( message,
"Environment variable undefined: MSPCCS_DATA." );
1186 strcat( message,
": egm84.grd\n" );
1197 fclose( geoid_height_file );
1199 delete [] file_name;
1203 void GeoidLibrary::initializeEGM84ThirtyMinGeoid()
1215 char* file_name = 0;
1216 char* path_name = NULL;
1217 long elevations_read = 0;
1219 FILE* geoid_height_file;
1227 path_name =
"/data/data/com.baesystems.msp.geotrans/lib/";
1228 file_name =
new char[ 80 ];
1229 strcpy( file_name, path_name );
1230 strcat( file_name,
"libwwgridbin.so" );
1232 path_name = getenv(
"MSPCCS_DATA" );
1233 if (path_name != NULL)
1235 file_name =
new char[ strlen( path_name ) + 12 ];
1236 strcpy( file_name, path_name );
1237 strcat( file_name,
"/" );
1241 file_name =
new char[ 22 ];
1242 strcpy( file_name,
"../../data/" );
1244 strcat( file_name,
"wwgrid.bin" );
1249 if( ( geoid_height_file = fopen( file_name,
"rb" ) ) == NULL )
1251 delete [] file_name;
1254 char message[256] =
"";
1255 if (NULL == path_name)
1257 strcpy( message,
"Environment variable undefined: MSPCCS_DATA." );
1262 strcat( message,
": wwgrid.bin\n" );
1274 fclose( geoid_height_file );
1276 delete [] file_name;
1281 void GeoidLibrary::initializeEGM2008Geoid(
void )
1301 char message[256] =
"";
1302 char* gridUsage = NULL;
1304 gridUsage = getenv(
"EGM2008_GRID_USAGE" );
1306 if ( NULL == gridUsage )
1312 this->egm2008Geoid =
new Egm2008AoiGrid;
1316 if ( strcmp( gridUsage,
"FULL" ) == 0 )
1322 this->egm2008Geoid =
new Egm2008FullGrid;
1330 this->egm2008Geoid =
new Egm2008AoiGrid;
1337 void GeoidLibrary::bilinearInterpolateDoubleHeights(
1340 double scale_factor,
1343 double *height_buffer,
1344 double *delta_height )
1364 double offset_x, offset_y;
1365 double delta_x, delta_y;
1366 double _1_minus_delta_x, _1_minus_delta_y;
1367 double latitude_dd, longitude_dd;
1368 double height_se, height_sw, height_ne, height_nw;
1369 double w_sw, w_se, w_ne, w_nw;
1370 double south_lat, west_lon;
1372 int max_index = num_rows * num_cols - 1;
1378 if( ( longitude < -
PI ) || ( longitude >
TWO_PI ) )
1388 if( longitude_dd < 0.0 )
1390 offset_x = ( longitude_dd + 360.0 ) / scale_factor;
1394 offset_x = longitude_dd / scale_factor;
1396 offset_y = ( 90 - latitude_dd ) / scale_factor;
1401 post_x = ( int )( offset_x );
1402 if( ( post_x + 1 ) == num_cols )
1404 post_y = ( int )( offset_y + 1.0e-11 );
1405 if( ( post_y + 1 ) == num_rows )
1409 index = post_y * num_cols + post_x;
1411 height_nw = height_buffer[ 0 ];
1412 else if( index > max_index )
1413 height_nw = height_buffer[ max_index ];
1415 height_nw = height_buffer[ index ];
1417 end_index = index + 1;
1418 if( end_index > max_index )
1419 height_ne = height_buffer[ max_index ];
1421 height_ne = height_buffer[ end_index ];
1424 index = ( post_y + 1 ) * num_cols + post_x;
1426 height_sw = height_buffer[ 0 ];
1427 else if( index > max_index )
1428 height_sw = height_buffer[ max_index ];
1430 height_sw = height_buffer[ index ];
1433 end_index = index + 1;
1434 if( end_index > max_index )
1435 height_se = height_buffer[ max_index ];
1437 height_se = height_buffer[ end_index ];
1439 west_lon = post_x * scale_factor;
1442 south_lat = ( 90 - ( post_y * scale_factor ) ) - scale_factor;
1446 if( longitude_dd < 0.0 )
1447 delta_x = ( longitude_dd + 360.0 - west_lon ) / scale_factor;
1449 delta_x = ( longitude_dd - west_lon ) / scale_factor;
1450 delta_y = ( latitude_dd - south_lat ) / scale_factor;
1452 _1_minus_delta_x = 1 - delta_x;
1453 _1_minus_delta_y = 1 - delta_y;
1455 w_sw = _1_minus_delta_x * _1_minus_delta_y;
1456 w_se = delta_x * _1_minus_delta_y;
1457 w_ne = delta_x * delta_y;
1458 w_nw = _1_minus_delta_x * delta_y;
1461 height_sw * w_sw + height_se * w_se + height_ne * w_ne + height_nw * w_nw;
1465 void GeoidLibrary::bilinearInterpolate(
1468 double scale_factor,
1471 float *height_buffer,
1472 double *delta_height )
1492 double offset_x, offset_y;
1493 double delta_x, delta_y;
1494 double _1_minus_delta_x, _1_minus_delta_y;
1495 double latitude_dd, longitude_dd;
1496 double height_se, height_sw, height_ne, height_nw;
1497 double w_sw, w_se, w_ne, w_nw;
1498 double south_lat, west_lon;
1500 int max_index = num_rows * num_cols - 1;
1506 if( ( longitude < -
PI ) || ( longitude >
TWO_PI ) )
1515 if( longitude_dd < 0.0 )
1517 offset_x = ( longitude_dd + 360.0 ) / scale_factor;
1521 offset_x = longitude_dd / scale_factor;
1523 offset_y = ( 90 - latitude_dd ) / scale_factor;
1528 post_x = ( int )( offset_x );
1529 if( ( post_x + 1 ) == num_cols )
1531 post_y = ( int )( offset_y + 1.0e-11 );
1532 if( ( post_y + 1 ) == num_rows )
1536 index = post_y * num_cols + post_x;
1538 height_nw = height_buffer[ 0 ];
1539 else if( index > max_index )
1540 height_nw = height_buffer[ max_index ];
1542 height_nw = height_buffer[ index ];
1544 end_index = index + 1;
1545 if( end_index > max_index )
1546 height_ne = height_buffer[ max_index ];
1548 height_ne = height_buffer[ end_index ];
1551 index = ( post_y + 1 ) * num_cols + post_x;
1553 height_sw = height_buffer[ 0 ];
1554 else if( index > max_index )
1555 height_sw = height_buffer[ max_index ];
1557 height_sw = height_buffer[ index ];
1560 end_index = index + 1;
1561 if( end_index > max_index )
1562 height_se = height_buffer[ max_index ];
1564 height_se = height_buffer[ end_index ];
1566 west_lon = post_x * scale_factor;
1569 south_lat = ( 90 - ( post_y * scale_factor ) ) - scale_factor;
1573 if( longitude_dd < 0.0 )
1574 delta_x = ( longitude_dd + 360.0 - west_lon ) / scale_factor;
1576 delta_x = ( longitude_dd - west_lon ) / scale_factor;
1577 delta_y = ( latitude_dd - south_lat ) / scale_factor;
1579 _1_minus_delta_x = 1 - delta_x;
1580 _1_minus_delta_y = 1 - delta_y;
1582 w_sw = _1_minus_delta_x * _1_minus_delta_y;
1583 w_se = delta_x * _1_minus_delta_y;
1584 w_ne = delta_x * delta_y;
1585 w_nw = _1_minus_delta_x * delta_y;
1588 height_sw * w_sw + height_se * w_se + height_ne * w_ne + height_nw * w_nw;
1592 void GeoidLibrary::naturalSplineInterpolate(
1595 double scale_factor,
1599 float *height_buffer,
1600 double *delta_height )
1620 int temp_offset_x, temp_offset_y;
1621 double offset_x, offset_y;
1622 double delta_x, delta_y;
1623 double delta_x2, delta_y2;
1624 double _1_minus_delta_x, _1_minus_delta_y;
1625 double _1_minus_delta_x2, _1_minus_delta_y2;
1626 double _3_minus_2_times_1_minus_delta_x, _3_minus_2_times_1_minus_delta_y;
1627 double _3_minus_2_times_delta_x, _3_minus_2_times_delta_y;
1628 double latitude_dd, longitude_dd;
1629 double height_se, height_sw, height_ne, height_nw;
1630 double w_sw, w_se, w_ne, w_nw;
1631 double south_lat, west_lon;
1633 double skip_factor = 1.0;
1639 if( ( longitude < -
PI ) || ( longitude >
TWO_PI ) )
1649 if( longitude_dd < 0.0 )
1651 offset_x = ( longitude_dd + 360.0 ) / scale_factor;
1655 offset_x = longitude_dd / scale_factor;
1657 offset_y = ( 90.0 - latitude_dd ) / scale_factor;
1662 post_x = ( int ) offset_x;
1663 if ( ( post_x + 1 ) == num_cols)
1665 post_y = ( int )( offset_y + 1.0e-11 );
1666 if ( ( post_y + 1 ) == num_rows)
1688 temp_offset_x = ( int )( post_x * skip_factor );
1689 temp_offset_y = ( int )( post_y * skip_factor + 1.0e-11 );
1690 if ( ( temp_offset_x + 1 ) == num_cols )
1692 if ( ( temp_offset_y + 1 ) == num_rows )
1696 index = ( int )( temp_offset_y * num_cols + temp_offset_x );
1698 height_nw = height_buffer[ 0 ];
1699 else if( index > max_index )
1700 height_nw = height_buffer[ max_index ];
1702 height_nw = height_buffer[ index ];
1704 end_index = index + (int)skip_factor;
1706 height_ne = height_buffer[ 0 ];
1707 else if( end_index > max_index )
1708 height_ne = height_buffer[ max_index ];
1710 height_ne = height_buffer[ end_index ];
1713 index = ( int )( ( temp_offset_y + skip_factor ) * num_cols + temp_offset_x );
1715 height_sw = height_buffer[ 0 ];
1716 else if( index > max_index )
1717 height_sw = height_buffer[ max_index ];
1719 height_sw = height_buffer[ index ];
1721 end_index = index + (int)skip_factor;
1723 height_se = height_buffer[ 0 ];
1724 else if( end_index > max_index )
1725 height_se = height_buffer[ max_index ];
1727 height_se = height_buffer[ end_index ];
1729 west_lon = post_x * scale_factor;
1732 south_lat = ( 90 - ( post_y * scale_factor ) ) - scale_factor;
1736 if( longitude_dd < 0.0 )
1737 delta_x = ( longitude_dd + 360.0 - west_lon ) / scale_factor;
1739 delta_x = ( longitude_dd - west_lon ) / scale_factor;
1740 delta_y = ( latitude_dd - south_lat ) / scale_factor;
1742 delta_x2 = delta_x * delta_x;
1743 delta_y2 = delta_y * delta_y;
1745 _1_minus_delta_x = 1 - delta_x;
1746 _1_minus_delta_y = 1 - delta_y;
1748 _1_minus_delta_x2 = _1_minus_delta_x * _1_minus_delta_x;
1749 _1_minus_delta_y2 = _1_minus_delta_y * _1_minus_delta_y;
1751 _3_minus_2_times_1_minus_delta_x = 3 - 2 * _1_minus_delta_x;
1752 _3_minus_2_times_1_minus_delta_y = 3 - 2 * _1_minus_delta_y;
1754 _3_minus_2_times_delta_x = 3 - 2 * delta_x;
1755 _3_minus_2_times_delta_y = 3 - 2 * delta_y;
1757 w_sw = _1_minus_delta_x2 * _1_minus_delta_y2 *
1758 ( _3_minus_2_times_1_minus_delta_x * _3_minus_2_times_1_minus_delta_y );
1760 w_se = delta_x2 * _1_minus_delta_y2 *
1761 ( _3_minus_2_times_delta_x * _3_minus_2_times_1_minus_delta_y );
1763 w_ne = delta_x2 * delta_y2 *
1764 ( _3_minus_2_times_delta_x * _3_minus_2_times_delta_y );
1766 w_nw = _1_minus_delta_x2 * delta_y2 *
1767 ( _3_minus_2_times_1_minus_delta_x * _3_minus_2_times_delta_y );
1770 height_sw * w_sw + height_se * w_se + height_ne * w_ne + height_nw * w_nw;