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