00001 // CLASSIFICATION: UNCLASSIFIED 00002 00003 /***************************************************************************/ 00004 /* RSC IDENTIFIER: Datum Library 00005 * 00006 * ABSTRACT 00007 * 00008 * This component provides datum shifts for a large collection of local 00009 * datums, WGS72, and WGS84. A particular datum can be accessed by using its 00010 * standard 5-letter code to find its index in the datum table. The index 00011 * can then be used to retrieve the name, type, ellipsoid code, and datum 00012 * shift parameters, and to perform shifts to or from that datum. 00013 * 00014 * By sequentially retrieving all of the datum codes and/or names, a menu 00015 * of the available datums can be constructed. The index values resulting 00016 * from selections from this menu can then be used to access the parameters 00017 * of the selected datum, or to perform datum shifts involving that datum. 00018 * 00019 * This component supports both 3-parameter local datums, for which only X, 00020 * Y, and Z translations relative to WGS 84 have been defined, and 00021 * 7-parameter local datums, for which X, Y, and Z rotations, and a scale 00022 * factor, are also defined. It also includes entries for WGS 84 (with an 00023 * index of 0), and WGS 72 (with an index of 1), but no shift parameter 00024 * values are defined for these. 00025 * 00026 * This component provides datum shift functions for both geocentric and 00027 * geodetic coordinates. WGS84 is used as an intermediate state when 00028 * shifting from one local datum to another. When geodetic coordinates are 00029 * given Molodensky's method is used, except near the poles where the 3-step 00030 * step method is used instead. Specific algorithms are used for shifting 00031 * between WGS72 and WGS84. 00032 * 00033 * This component depends on two data files, named 3_param.dat and 00034 * 7_param.dat, which contain the datum parameter values. Copies of these 00035 * files must be located in the directory specified by the value of the 00036 * environment variable "MSPCCS_DATA", if defined, or else in the current 00037 * directory whenever a program containing this component is executed. 00038 * 00039 * Additional datums can be added to these files, either manually or using 00040 * the Create_Datum function. However, if a large number of datums are 00041 * added, the datum table array sizes in this component will have to be 00042 * increased. 00043 * 00044 * This component depends on two other components: the Ellipsoid component 00045 * for access to ellipsoid parameters; and the Geocentric component for 00046 * conversions between geodetic and geocentric coordinates. 00047 * 00048 * ERROR HANDLING 00049 * 00050 * This component checks for input file errors and input parameter errors. 00051 * If an invalid value is found, the error code is combined with the current 00052 * error code using the bitwise or. This combining allows multiple error 00053 * codes to be returned. The possible error codes are: 00054 * 00055 * DATUM_NO_ERROR : No errors occurred in function 00056 * DATUM_NOT_INITIALIZED_ERROR : Datum module has not been initialized 00057 * DATUM_7PARAM_FILE_OPEN_ERROR : 7 parameter file opening error 00058 * DATUM_7PARAM_FILE_PARSING_ERROR : 7 parameter file structure error 00059 * DATUM_7PARAM_OVERFLOW_ERROR : 7 parameter table overflow 00060 * DATUM_3PARAM_FILE_OPEN_ERROR : 3 parameter file opening error 00061 * DATUM_3PARAM_FILE_PARSING_ERROR : 3 parameter file structure error 00062 * DATUM_3PARAM_OVERFLOW_ERROR : 3 parameter table overflow 00063 * DATUM_INVALID_INDEX_ERROR : Index out of valid range (less than one 00064 * or more than Number_of_Datums) 00065 * DATUM_INVALID_SRC_INDEX_ERROR : Source datum index invalid 00066 * DATUM_INVALID_DEST_INDEX_ERROR : Destination datum index invalid 00067 * DATUM_INVALID_CODE_ERROR : Datum code not found in table 00068 * DATUM_LAT_ERROR : Latitude out of valid range (-90 to 90) 00069 * DATUM_LON_ERROR : Longitude out of valid range (-180 to 00070 * 360) 00071 * DATUM_SIGMA_ERROR : Standard error values must be positive 00072 * (or -1 if unknown) 00073 * DATUM_DOMAIN_ERROR : Domain of validity not well defined 00074 * DATUM_ELLIPSE_ERROR : Error in ellipsoid module 00075 * DATUM_NOT_USERDEF_ERROR : Datum code is not user defined - cannot 00076 * be deleted 00077 * 00078 * 00079 * REUSE NOTES 00080 * 00081 * Datum is intended for reuse by any application that needs access to 00082 * datum shift parameters relative to WGS 84. 00083 * 00084 * 00085 * REFERENCES 00086 * 00087 * Further information on Datum can be found in the Reuse Manual. 00088 * 00089 * Datum originated from : U.S. Army Topographic Engineering Center (USATEC) 00090 * Geospatial Information Division (GID) 00091 * 7701 Telegraph Road 00092 * Alexandria, VA 22310-3864 00093 * 00094 * LICENSES 00095 * 00096 * None apply to this component. 00097 * 00098 * RESTRICTIONS 00099 * 00100 * Datum has no restrictions. 00101 * 00102 * ENVIRONMENT 00103 * 00104 * Datum was tested and certified in the following environments: 00105 * 00106 * 1. Solaris 2.5 with GCC 2.8.1 00107 * 2. MS Windows 95 with MS Visual C++ 6 00108 * 00109 * MODIFICATIONS 00110 * 00111 * Date Description 00112 * ---- ----------- 00113 * 11/20/08 Original Code 00114 * 05/26/10 S. Gillis, BAEts26674, Added Validate Datum API to the 00115 * in MSP Geotrans 3.0 00116 * 06/04/10 S. Gillis, BAEts26676, Fixed the error always returned 00117 * when calling CCS API getDatumParamters 00118 */ 00119 00120 00121 /***************************************************************************/ 00122 /* 00123 * INCLUDES 00124 */ 00125 00126 #include "DatumLibrary.h" 00127 #include "DatumLibraryImplementation.h" 00128 #include "CoordinateConversionException.h" 00129 #include "ErrorMessages.h" 00130 00131 /* 00132 * DatumLibrary.h - accesses datum information 00133 * DatumLibraryImplementation.h - for prototype error ehecking and error codes 00134 */ 00135 00136 00137 using namespace MSP::CCS; 00138 00139 00140 /************************************************************************/ 00141 /* FUNCTIONS 00142 * 00143 */ 00144 00145 DatumLibrary::DatumLibrary( DatumLibraryImplementation* __datumLibraryImplementation ) 00146 { 00147 /* 00148 * The constructor creates an empty list to store the datum information 00149 * contained in two external files, 3_param.dat and 7_param.dat. 00150 */ 00151 00152 _datumLibraryImplementation = __datumLibraryImplementation; 00153 } 00154 00155 00156 DatumLibrary::DatumLibrary( const DatumLibrary &dl ) 00157 { 00158 _datumLibraryImplementation = dl._datumLibraryImplementation; 00159 } 00160 00161 00162 DatumLibrary::~DatumLibrary() 00163 { 00164 _datumLibraryImplementation = 0; 00165 } 00166 00167 00168 DatumLibrary& DatumLibrary::operator=( const DatumLibrary &dl ) 00169 { 00170 if ( &dl == this ) 00171 return *this; 00172 00173 _datumLibraryImplementation = dl._datumLibraryImplementation; 00174 00175 return *this; 00176 } 00177 00178 00179 void DatumLibrary::defineDatum( const int datumType, const char *datumCode, const char *datumName, const char *ellipsoidCode, 00180 double deltaX, double deltaY, double deltaZ, 00181 double sigmaX, double sigmaY, double sigmaZ, 00182 double westLongitude, double eastLongitude, double southLatitude, double northLatitude, 00183 double rotationX, double rotationY, double rotationZ, double scaleFactor) 00184 { 00185 /* The function defineDatum creates a new local (3 or 7-parameter) datum with the 00186 * specified code, name, shift values, and standard error values or rotation and scale factor values. 00187 * If the datum table has not been initialized, the specified code is already in use, 00188 * or a new version of the 3-param.dat or 7-param.dat file cannot be created, an 00189 * exception is thrown. Note that the indexes 00190 * of all datums in the datum table may be changed by this function. 00191 * 00192 * datumType : Specifies 3 parameter or 7 parameter datum (input) 00193 * datumCode : 5-letter new datum code. (input) 00194 * datumName : Name of the new datum (input) 00195 * ellipsoidCode : 2-letter code for the associated ellipsoid (input) 00196 * deltaX : X translation to WGS84 in meters (input) 00197 * deltaY : Y translation to WGS84 in meters (input) 00198 * deltaZ : Z translation to WGS84 in meters (input) 00199 * sigmaX : Standard error in X in meters (input) 00200 * sigmaY : Standard error in Y in meters (input) 00201 * sigmaZ : Standard error in Z in meters (input) 00202 * westLongitude : Western edge of validity rectangle in radians (input) 00203 * eastLongitude : Eastern edge of validity rectangle in radians (input) 00204 * southLatitude : Southern edge of validity rectangle in radians(input) 00205 * northLatitude : Northern edge of validity rectangle in radians(input) 00206 * rotationX : X rotation to WGS84 in arc seconds (input) 00207 * rotationY : Y rotation to WGS84 in arc seconds (input) 00208 * rotationZ : Z rotation to WGS84 in arc seconds (input) 00209 * scalefactor : Scale factor (input) 00210 * 00211 */ 00212 00213 if( datumType == DatumType::threeParamDatum ) 00214 { 00215 _datumLibraryImplementation->define3ParamDatum( datumCode, datumName, ellipsoidCode, 00216 deltaX, deltaY, deltaZ, sigmaX, sigmaY, sigmaZ, 00217 westLongitude, eastLongitude, southLatitude, northLatitude ); 00218 } 00219 else if( datumType == DatumType::sevenParamDatum ) 00220 { 00221 _datumLibraryImplementation->define7ParamDatum( datumCode, datumName, ellipsoidCode, 00222 deltaX, deltaY, deltaZ, rotationX, rotationY, rotationZ, 00223 scaleFactor ); 00224 } 00225 } 00226 00227 00228 void DatumLibrary::removeDatum( const char* code ) 00229 { 00230 /* 00231 * The function removeDatum deletes a local (3-parameter) datum with the 00232 * specified code. If the datum table has not been initialized or a new 00233 * version of the 3-param.dat file cannot be created, an error code is returned, 00234 * otherwise DATUM_NO_ERROR is returned. Note that the indexes of all datums 00235 * in the datum table may be changed by this function. 00236 * 00237 * code : 5-letter datum code. (input) 00238 * 00239 */ 00240 00241 _datumLibraryImplementation->removeDatum( code ); 00242 } 00243 00244 00245 void DatumLibrary::getDatumCount( long *count ) 00246 { 00247 /* 00248 * The function datumCount returns the number of Datums in the table 00249 * if the table was initialized without error. 00250 * 00251 * count : number of datums in the datum table (output) 00252 */ 00253 00254 _datumLibraryImplementation->datumCount( count ); 00255 } 00256 00257 00258 void DatumLibrary::getDatumIndex( const char *code, long *index ) 00259 { 00260 /* 00261 * The function datumIndex returns the index of the datum with the 00262 * specified code. 00263 * 00264 * code : The datum code being searched for. (input) 00265 * index : The index of the datum in the table with the (output) 00266 * specified code. 00267 */ 00268 00269 _datumLibraryImplementation->datumIndex( code, index ); 00270 } 00271 00272 00273 void DatumLibrary::getDatumInfo( const long index, char *code, char *name, char *ellipsoidCode ) 00274 { 00275 /* 00276 * The function getDatumInfo returns the 5-letter code, name and 00277 * 2-letter ellipsoid code of the datum referenced by index. 00278 * 00279 * index : The index of a given datum in the datum table. (input) 00280 * code : The datum Code of the datum referenced by Index. (output) 00281 * name : The datum Name of the datum referenced by Index. (output) 00282 * ellipsoidCode : The ellipsoid code for the ellipsoid associated with (output) 00283 * the datum referenced by index. 00284 */ 00285 00286 _datumLibraryImplementation->datumCode( index, code ); 00287 _datumLibraryImplementation->datumName( index, name ); 00288 _datumLibraryImplementation->datumEllipsoidCode( index, ellipsoidCode ); 00289 } 00290 00291 00292 void DatumLibrary::getDatumParameters( const long index, DatumType::Enum *datumType, double *deltaX, double *deltaY, double *deltaZ, 00293 double *sigmaX, double *sigmaY, double *sigmaZ, 00294 double *westLongitude, double *eastLongitude, double *southLatitude, double *northLatitude, 00295 double *rotationX, double *rotationY, double *rotationZ, double *scaleFactor ) 00296 { 00297 /* 00298 * The function getDatumParameters returns the following datum parameters 00299 * (specified as output parameters below): datumType, deltaX, deltaY, deltaZ, 00300 * sigmaX, sigmaY, sigmaZ, westLongitude, eastLongitude, southLatitude, 00301 * northLatitude, rotationX, rotationY, rotationZ, and scaleFactor. 00302 * 00303 * sigmaX, sigmaY, and sigmaZ only apply to 3 parameter datum and will be 00304 * set to 0 if the datum type is a 7 parameter datum. 00305 * 00306 * rotationX, rotationY, rotationZ, and scaleFactor only apply to 7 00307 * parameter datum and will be set to 0 if the datum type is a 3 parameter 00308 * datum. 00309 * 00310 * If the datum type is neither a 3 parameter datum nor a 7 parameter datum, 00311 * a CoordinateConversionException will be thrown. 00312 * 00313 * index : The index of a given datum in the datum table (input) 00314 * datumType : Specifies datum type (output) 00315 * deltaX : X translation to WGS84 in meters (output) 00316 * deltaY : Y translation to WGS84 in meters (output) 00317 * deltaZ : Z translation to WGS84 in meters (output) 00318 * sigmaX : Standard error in X in meters (output) 00319 * sigmaY : Standard error in Y in meters (output) 00320 * sigmaZ : Standard error in Z in meters (output) 00321 * westLongitude : Western edge of validity rectangle in radians (output) 00322 * eastLongitude : Eastern edge of validity rectangle in radians (output) 00323 * southLatitude : Southern edge of validity rectangle in radians (output) 00324 * northLatitude : Northern edge of validity rectangle in radians (output) 00325 * rotationX : X rotation to WGS84 in arc seconds (output) 00326 * rotationY : Y rotation to WGS84 in arc seconds (output) 00327 * rotationZ : Z rotation to WGS84 in arc seconds (output) 00328 * scaleFactor : Scale factor (output) 00329 */ 00330 00331 _datumLibraryImplementation->retrieveDatumType( index, datumType ); 00332 _datumLibraryImplementation->datumTranslationValues( 00333 index, deltaX, deltaY, deltaZ ); 00334 _datumLibraryImplementation->datumValidRectangle( 00335 index, westLongitude, eastLongitude, southLatitude, northLatitude ); 00336 00337 //If DatumType is DatumType::threeParamDatum 00338 if(*datumType == DatumType::threeParamDatum) 00339 { 00340 _datumLibraryImplementation->datumStandardErrors( 00341 index, sigmaX, sigmaY, sigmaZ ); 00342 00343 //Initialize since they could not be set in datumSevenParameters() 00344 *rotationX = 0; 00345 *rotationY = 0; 00346 *rotationZ = 0; 00347 *scaleFactor = 0; 00348 } 00349 //If DatumType is DatumType::sevenParamDatum 00350 else if(*datumType == DatumType::sevenParamDatum) 00351 { 00352 _datumLibraryImplementation->datumSevenParameters( 00353 index, rotationX, rotationY, rotationZ, scaleFactor ); 00354 00355 //Initialize since they could not be set in datumStandardErrors() 00356 *sigmaX = 0; 00357 *sigmaY = 0; 00358 *sigmaZ = 0; 00359 } 00360 else 00361 { 00362 throw CoordinateConversionException( ErrorMessages::datumType ); 00363 } 00364 } 00365 00366 00367 void DatumLibrary::getDatumValidRectangle( const long index, double *westLongitude, double *eastLongitude, double *southLatitude, double *northLatitude ) 00368 { 00369 /* 00370 * The function datumValidRectangle returns the edges of the validity 00371 * rectangle for the datum referenced by index. 00372 * 00373 * index : The index of a given datum in the datum table (input) 00374 * westLongitude : Western edge of validity rectangle in radians (output) 00375 * eastLongitude : Eastern edge of validity rectangle in radians (output) 00376 * southLatitude : Southern edge of validity rectangle in radians (output) 00377 * northLatitude : Northern edge of validity rectangle in radians (output) 00378 * 00379 */ 00380 00381 _datumLibraryImplementation->datumValidRectangle( index, westLongitude, eastLongitude, southLatitude, northLatitude ); 00382 } 00383 00384 void DatumLibrary::validDatum( const long index, double longitude, 00385 double latitude, long *result ) 00386 { 00387 /* 00388 * The function validDatum checks whether or not the specified location 00389 * is within the validity rectangle for the specified datum. It returns 00390 * zero if the specified location is NOT within the validity rectangle, 00391 * and returns 1 otherwise. 00392 * 00393 * index : The index of a given datum in the datum table (input) 00394 * latitude : Latitude of the location to be checked in radians (input) 00395 * longitude : Longitude of the location to be checked in radians (input) 00396 * result : Indicates whether location is inside (1) or outside (0) 00397 * of the validity rectangle of the specified datum (output) 00398 */ 00399 00400 _datumLibraryImplementation->validDatum( index, longitude, latitude, result ); 00401 } 00402 00403 00404 // CLASSIFICATION: UNCLASSIFIED