00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 #include <stdlib.h>
00102 #include <ctype.h>
00103 #include <stdio.h>
00104 #include <string.h>
00105 #include "EllipsoidLibraryImplementation.h"
00106 #include "Ellipsoid.h"
00107 #include "DatumLibraryImplementation.h"
00108 #include "CoordinateConversionException.h"
00109 #include "ErrorMessages.h"
00110 #include "CCSThreadMutex.h"
00111 #include "CCSThreadLock.h"
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 using namespace MSP::CCS;
00129 using MSP::CCSThreadMutex;
00130 using MSP::CCSThreadLock;
00131
00132
00133
00134
00135
00136
00137
00138 const int MAX_ELLIPSOIDS = 32;
00139 const int ELLIPSOID_CODE_LENGTH = 3;
00140 const int ELLIPSOID_NAME_LENGTH = 30;
00141 const int ELLIPSOID_BUF = 90;
00142 const int FILENAME_LENGTH = 128;
00143 const char *WGS84_Ellipsoid_Code = "WE";
00144 const char *WGS72_Ellipsoid_Code = "WD";
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 class MSP::CCS::EllipsoidLibraryImplementationCleaner
00156 {
00157 public:
00158
00159 ~EllipsoidLibraryImplementationCleaner()
00160 {
00161 CCSThreadLock lock(&EllipsoidLibraryImplementation::mutex);
00162 EllipsoidLibraryImplementation::deleteInstance();
00163 }
00164
00165 } ellipsoidLibraryImplementationCleanerInstance;
00166
00167
00168
00169 CCSThreadMutex EllipsoidLibraryImplementation::mutex;
00170 EllipsoidLibraryImplementation* EllipsoidLibraryImplementation::instance = 0;
00171 int EllipsoidLibraryImplementation::instanceCount = 0;
00172
00173
00174 EllipsoidLibraryImplementation* EllipsoidLibraryImplementation::getInstance()
00175 {
00176 CCSThreadLock lock(&mutex);
00177 if( instance == 0 )
00178 instance = new EllipsoidLibraryImplementation;
00179
00180 instanceCount++;
00181
00182 return instance;
00183 }
00184
00185
00186 void EllipsoidLibraryImplementation::removeInstance()
00187 {
00188
00189
00190
00191
00192 CCSThreadLock lock(&mutex);
00193 if( --instanceCount < 1 )
00194 {
00195 deleteInstance();
00196 }
00197 }
00198
00199
00200 void EllipsoidLibraryImplementation::deleteInstance()
00201 {
00202
00203
00204
00205
00206 if( instance != 0 )
00207 {
00208 delete instance;
00209 instance = 0;
00210 }
00211 }
00212
00213
00214 EllipsoidLibraryImplementation::EllipsoidLibraryImplementation():
00215 _datumLibraryImplementation( 0 )
00216 {
00217
00218
00219
00220
00221
00222 ellipsoidList.reserve( MAX_ELLIPSOIDS );
00223
00224 try
00225 {
00226 loadEllipsoids();
00227 }
00228 catch(CoordinateConversionException e)
00229 {
00230 throw e;
00231 }
00232 }
00233
00234
00235 EllipsoidLibraryImplementation::EllipsoidLibraryImplementation( const EllipsoidLibraryImplementation &el )
00236 {
00237 int size = el.ellipsoidList.size();
00238 for( int i = 0; i < size; i++ )
00239 ellipsoidList.push_back( new Ellipsoid( *( el.ellipsoidList[i] ) ) );
00240
00241 _datumLibraryImplementation = el._datumLibraryImplementation;
00242 }
00243
00244
00245 EllipsoidLibraryImplementation::~EllipsoidLibraryImplementation()
00246 {
00247 std::vector<Ellipsoid*>::iterator iter = ellipsoidList.begin();
00248 while( iter != ellipsoidList.end() )
00249 {
00250 delete( *iter );
00251 iter++;
00252 }
00253 ellipsoidList.clear();
00254
00255 _datumLibraryImplementation = 0;
00256 }
00257
00258
00259 EllipsoidLibraryImplementation& EllipsoidLibraryImplementation::operator=( const EllipsoidLibraryImplementation &el )
00260 {
00261 if ( &el == this )
00262 return *this;
00263
00264 int size = el.ellipsoidList.size();
00265 for( int i = 0; i < size; i++ )
00266 ellipsoidList[i] = new Ellipsoid( *( el.ellipsoidList[i] ) );
00267
00268 _datumLibraryImplementation = el._datumLibraryImplementation;
00269
00270 return *this;
00271 }
00272
00273
00274 void EllipsoidLibraryImplementation::defineEllipsoid( const char* code, const char* name, double semiMajorAxis, double flattening )
00275 {
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291 long code_length = 0;
00292 char *PathName = NULL;
00293 char FileName[FILENAME_LENGTH];
00294 char ellipsoid_code[ELLIPSOID_CODE_LENGTH];
00295 FILE *fp = NULL;
00296 long index = 0;
00297 long numEllipsoids = ellipsoidList.size();
00298 double inv_f = 1 / flattening;
00299
00300 if( !( numEllipsoids < MAX_ELLIPSOIDS ) )
00301 throw CoordinateConversionException( ErrorMessages::ellipsoidOverflow );
00302 else
00303 {
00304 try
00305 {
00306 ellipsoidIndex( code, &index );
00307 throw CoordinateConversionException( ErrorMessages::invalidEllipsoidCode );
00308 }
00309 catch(CoordinateConversionException e)
00310 {
00311 }
00312
00313 code_length = strlen( code );
00314 if( ( code_length > ( ELLIPSOID_CODE_LENGTH - 1 ) ) )
00315 throw CoordinateConversionException( ErrorMessages::invalidEllipsoidCode );
00316 if( semiMajorAxis <= 0.0 )
00317 throw CoordinateConversionException( ErrorMessages::semiMajorAxis );
00318 if( (inv_f < 250 ) || ( inv_f > 350 ) )
00319 {
00320 throw CoordinateConversionException( ErrorMessages::ellipsoidFlattening );
00321 }
00322
00323 strcpy( ellipsoid_code, code );
00324
00325 for( int i = 0; i < code_length; i++ )
00326 ellipsoid_code[i] = ( char )toupper( ellipsoid_code[i] );
00327
00328 double semiMinorAxis = semiMajorAxis * ( 1 - flattening );
00329 double eccentricitySquared = 2.0 * flattening - flattening * flattening;
00330 ellipsoidList.push_back( new Ellipsoid( index, ellipsoid_code, ( char* )name, semiMajorAxis, semiMinorAxis, flattening, eccentricitySquared, true ) );
00331
00332 numEllipsoids++;
00333
00334 CCSThreadLock lock(&mutex);
00335
00336
00337 PathName = getenv( "MSPCCS_DATA" );
00338 if( PathName != NULL )
00339 {
00340 strcpy( FileName, PathName );
00341 strcat( FileName, "/" );
00342 }
00343 else
00344 {
00345 strcpy( FileName, "../../data/" );
00346 }
00347 strcat( FileName, "ellips.dat" );
00348
00349 if( ( fp = fopen( FileName, "w" ) ) == NULL )
00350 {
00351 throw CoordinateConversionException( ErrorMessages::ellipsoidFileOpenError );
00352 }
00353
00354
00355 index = 0;
00356 while( index < numEllipsoids )
00357 {
00358 if( ellipsoidList[index]->userDefined() )
00359 fprintf( fp, "*");
00360
00361 fprintf( fp, "%-29s %-2s %11.9f %12.9f %13.13f \n",
00362 ellipsoidList[index]->name(),
00363 ellipsoidList[index]->code(),
00364 ellipsoidList[index]->semiMajorAxis(),
00365 ellipsoidList[index]->semiMinorAxis(),
00366 1 / ellipsoidList[index]->flattening() );
00367 index++;
00368 }
00369
00370 fclose( fp );
00371 }
00372 }
00373
00374
00375 void EllipsoidLibraryImplementation::removeEllipsoid( const char* code )
00376 {
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389 long index = 0;
00390 char *PathName = NULL;
00391 char FileName[FILENAME_LENGTH];
00392 FILE *fp = NULL;
00393
00394 ellipsoidIndex( code, &index );
00395 if( ellipsoidList[index]->userDefined() )
00396 {
00397 if( _datumLibraryImplementation )
00398 {
00399 if( _datumLibraryImplementation->datumUsesEllipsoid( code ) )
00400 throw CoordinateConversionException( ErrorMessages::ellipseInUse );
00401 }
00402 }
00403 else
00404 throw CoordinateConversionException( ErrorMessages::notUserDefined );
00405
00406
00407
00408
00409 {
00410 int numEllipsoids = ellipsoidList.size();
00411
00412 int i = 0;
00413 for( i = index; i < numEllipsoids; i++ )
00414 ellipsoidList[i] = ellipsoidList[i+1];
00415
00416 if( numEllipsoids != MAX_ELLIPSOIDS )
00417 ellipsoidList[i] = ellipsoidList[i+1];
00418 else
00419 ellipsoidList.erase( ellipsoidList.end() - 1 );
00420
00421 numEllipsoids--;
00422 ellipsoidList.resize( numEllipsoids );
00423
00424 CCSThreadLock lock(&mutex);
00425
00426
00427 PathName = getenv( "MSPCCS_DATA" );
00428 if( PathName != NULL )
00429 {
00430 strcpy( FileName, PathName );
00431 strcat( FileName, "/" );
00432 }
00433 else
00434 {
00435 strcpy( FileName, "../../data/" );
00436 }
00437 strcat( FileName, "ellips.dat" );
00438 if( ( fp = fopen( FileName, "w" ) ) == NULL )
00439 {
00440 throw CoordinateConversionException( ErrorMessages::ellipsoidFileOpenError );
00441 }
00442
00443 index = 0;
00444 while( index < numEllipsoids )
00445 {
00446 if( ellipsoidList[index]->userDefined() )
00447 fprintf( fp, "*" );
00448
00449 fprintf(fp, "%-29s %-2s %11.3f %12.4f %13.9f \n",
00450 ellipsoidList[index]->name(),
00451 ellipsoidList[index]->code(),
00452 ellipsoidList[index]->semiMajorAxis(),
00453 ellipsoidList[index]->semiMinorAxis(),
00454 1 / ellipsoidList[index]->flattening() );
00455 index++;
00456 }
00457
00458 fclose( fp );
00459 }
00460 }
00461
00462
00463 void EllipsoidLibraryImplementation::ellipsoidCount( long *count )
00464 {
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 *count = ellipsoidList.size();
00475 }
00476
00477
00478 void EllipsoidLibraryImplementation::ellipsoidIndex( const char *code, long* index )
00479 {
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 char temp_code[3];
00492 long i = 0;
00493 long j = 0;
00494
00495 while( j < ELLIPSOID_CODE_LENGTH )
00496 {
00497 temp_code[j] = ( char )toupper(code[j]);
00498 j++;
00499 }
00500 temp_code[ELLIPSOID_CODE_LENGTH - 1] = 0;
00501
00502 int numEllipsoids = ellipsoidList.size();
00503 while( ( i < numEllipsoids )
00504 && strcmp( temp_code, ellipsoidList[i]->code() ) )
00505 {
00506 i++;
00507 }
00508
00509 if( i == numEllipsoids )
00510 throw CoordinateConversionException( ErrorMessages::invalidEllipsoidCode );
00511 else
00512 {
00513 if ( strcmp( temp_code, ellipsoidList[i]->code() ) )
00514 throw CoordinateConversionException( ErrorMessages::invalidEllipsoidCode );
00515 else
00516 *index = i;
00517 }
00518 }
00519
00520
00521 void EllipsoidLibraryImplementation::ellipsoidCode( const long index, char *code )
00522 {
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533 strcpy( code, "" );
00534
00535 if ( ( index < 0 ) || ( index >= ellipsoidList.size() ) )
00536 throw CoordinateConversionException( ErrorMessages::invalidIndex );
00537 else
00538 strcpy( code, ellipsoidList[index]->code() );
00539 }
00540
00541
00542 void EllipsoidLibraryImplementation::ellipsoidName( const long index, char *name )
00543 {
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 strcpy( name,"" );
00556
00557 if( ( index < 0 ) || ( index >= ellipsoidList.size() ) )
00558 throw CoordinateConversionException( ErrorMessages::invalidIndex );
00559 else
00560 strcpy( name, ellipsoidList[index]->name() );
00561 }
00562
00563
00564 void EllipsoidLibraryImplementation::ellipsoidParameters( const long index, double *a, double *f )
00565 {
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577 *a = 0;
00578 *f = 0;
00579
00580 if( ( index < 0 ) || ( index >= ellipsoidList.size() ) )
00581 throw CoordinateConversionException( ErrorMessages::invalidIndex );
00582 else
00583 {
00584 Ellipsoid* ellipsoid = ellipsoidList[index];
00585 *a = ellipsoid->semiMajorAxis();
00586 *f = ellipsoid->flattening();
00587 }
00588 }
00589
00590
00591 void EllipsoidLibraryImplementation::ellipsoidEccentricity2( const long index, double *eccentricitySquared )
00592 {
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603 *eccentricitySquared = 0;
00604
00605 if( ( index < 0 ) || ( index >= ellipsoidList.size() ) )
00606 throw CoordinateConversionException( ErrorMessages::invalidIndex );
00607 else
00608 *eccentricitySquared = ellipsoidList[index]->eccentricitySquared();
00609 }
00610
00611
00612 void EllipsoidLibraryImplementation::ellipsoidUserDefined( const long index, long *result )
00613 {
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625 *result = false;
00626
00627 if( ( index < 0 ) || ( index >= ellipsoidList.size() ) )
00628 throw CoordinateConversionException( ErrorMessages::invalidIndex );
00629 else
00630 *result = ellipsoidList[index]->userDefined();
00631 }
00632
00633
00634 void EllipsoidLibraryImplementation::setDatumLibraryImplementation( DatumLibraryImplementation* __datumLibraryImplementation )
00635 {
00636
00637
00638
00639
00640
00641
00642
00643
00644 _datumLibraryImplementation = __datumLibraryImplementation;
00645 }
00646
00647
00648
00649
00650
00651
00652
00653 void EllipsoidLibraryImplementation::loadEllipsoids()
00654 {
00655
00656
00657
00658
00659
00660
00661 char* PathName = NULL;
00662 char* FileName = 0;
00663 FILE* fp = NULL;
00664 char buffer[ELLIPSOID_BUF];
00665 long index = 0;
00666
00667 CCSThreadLock lock(&mutex);
00668
00669
00670
00671
00672 PathName = getenv( "MSPCCS_DATA" );
00673 if (PathName != NULL)
00674 {
00675 FileName = new char[ strlen( PathName ) + 12 ];
00676 strcpy( FileName, PathName );
00677 strcat( FileName, "/" );
00678 }
00679 else
00680 {
00681 FileName = new char[ 22 ];
00682 strcpy( FileName, "../../data/" );
00683 }
00684 strcat( FileName, "ellips.dat" );
00685
00686
00687
00688 if( ( fp = fopen( FileName, "r" ) ) == NULL )
00689 {
00690 delete [] FileName;
00691 FileName = 0;
00692
00693 throw CoordinateConversionException( ErrorMessages::ellipsoidFileOpenError );
00694 }
00695
00696
00697 while( !feof( fp ) )
00698 {
00699 if( index <= MAX_ELLIPSOIDS )
00700 {
00701
00702 if( fgets( buffer, ELLIPSOID_BUF, fp ) )
00703 {
00704 char name[ELLIPSOID_NAME_LENGTH];
00705 char code[ELLIPSOID_CODE_LENGTH];
00706 double semiMajorAxis;
00707 double semiMinorAxis;
00708 double recpF;
00709
00710 sscanf( buffer, "%30c %s %lf %lf %lf", name, code, &semiMajorAxis, &semiMinorAxis, &recpF );
00711
00712 bool userDefined = false;
00713 if( name[0] == '*' )
00714 {
00715 userDefined = true;
00716 for( int i = 0; i < ELLIPSOID_NAME_LENGTH; i++ )
00717 name[i] = name[i+1];
00718 }
00719
00720 name[ELLIPSOID_NAME_LENGTH - 1] = '\0';
00721
00722 double flattening = 1 / recpF;
00723 double eccentricitySquared = 2.0 * flattening - flattening * flattening;
00724
00725 ellipsoidList.push_back( new Ellipsoid( index, code, name, semiMajorAxis, semiMinorAxis, flattening, eccentricitySquared, userDefined ) );
00726
00727 index++;
00728 }
00729 }
00730 else
00731 throw CoordinateConversionException( ErrorMessages::ellipsoidOverflow );
00732 }
00733
00734 fclose( fp );
00735
00736 delete [] FileName;
00737 FileName = 0;
00738 }
00739
00740