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 #include <math.h>
00038 #include "geodesy.h"
00039 #include "constants.h"
00040
00041
00042
00043
00044
00045
00046
00047 static BOOL GEODESY_GetReferenceEllipseParameters_A_E2(
00048 const GEODESY_enumReferenceEllipse ellipse,
00049 double* a,
00050 double* e2
00051 );
00052
00053
00054 static BOOL GEODESY_GetReferenceEllipseParameters_A_B_E2(
00055 const GEODESY_enumReferenceEllipse ellipse,
00056 double* a,
00057 double* b,
00058 double* e2
00059 );
00060
00061
00062 static BOOL GEODESY_IsLatitudeValid(
00063 const double latitude
00064 );
00065
00066
00067
00068
00069
00070 BOOL GEODESY_GetReferenceEllipseParameters(
00071 const GEODESY_enumReferenceEllipse ellipse,
00072 double* a,
00073 double* b,
00074 double* f_inv,
00075 double* e2
00076 )
00077 {
00078 switch( ellipse )
00079 {
00080 case GEODESY_REFERENCE_ELLIPSE_AIRY_1830:
00081 *a = GEODESY_REFERENCE_ELLIPSE_AIRY_1830_A;
00082 *f_inv = GEODESY_REFERENCE_ELLIPSE_AIRY_1830_F_INV;
00083 *b = GEODESY_REFERENCE_ELLIPSE_AIRY_1830_B;
00084 *e2 = GEODESY_REFERENCE_ELLIPSE_AIRY_1830_E2;
00085 break;
00086
00087 case GEODESY_REFERENCE_ELLIPSE_MODIFED_AIRY:
00088 *a = GEODESY_REFERENCE_ELLIPSE_MODIFED_AIRY_A;
00089 *f_inv = GEODESY_REFERENCE_ELLIPSE_MODIFED_AIRY_F_INV;
00090 *b = GEODESY_REFERENCE_ELLIPSE_MODIFED_AIRY_B;
00091 *e2 = GEODESY_REFERENCE_ELLIPSE_MODIFED_AIRY_E2;
00092 break;
00093
00094 case GEODESY_REFERENCE_ELLIPSE_AUSTRALIAN_NATIONAL:
00095 *a = GEODESY_REFERENCE_ELLIPSE_AUSTRALIAN_NATIONAL_A;
00096 *f_inv = GEODESY_REFERENCE_ELLIPSE_AUSTRALIAN_NATIONAL_F_INV;
00097 *b = GEODESY_REFERENCE_ELLIPSE_AUSTRALIAN_NATIONAL_B;
00098 *e2 = GEODESY_REFERENCE_ELLIPSE_AUSTRALIAN_NATIONAL_E2;
00099 break;
00100
00101 case GEODESY_REFERENCE_ELLIPSE_BESSEL_1841:
00102 *a = GEODESY_REFERENCE_ELLIPSE_BESSEL_1841_A;
00103 *f_inv = GEODESY_REFERENCE_ELLIPSE_BESSEL_1841_F_INV;
00104 *b = GEODESY_REFERENCE_ELLIPSE_BESSEL_1841_B;
00105 *e2 = GEODESY_REFERENCE_ELLIPSE_BESSEL_1841_E2;
00106 break;
00107
00108 case GEODESY_REFERENCE_ELLIPSE_CLARKE_1866:
00109 *a = GEODESY_REFERENCE_ELLIPSE_CLARKE_1866_A;
00110 *f_inv = GEODESY_REFERENCE_ELLIPSE_CLARKE_1866_F_INV;
00111 *b = GEODESY_REFERENCE_ELLIPSE_CLARKE_1866_B;
00112 *e2 = GEODESY_REFERENCE_ELLIPSE_CLARKE_1866_E2;
00113 break;
00114
00115 case GEODESY_REFERENCE_ELLIPSE_CLARKE_1880:
00116 *a = GEODESY_REFERENCE_ELLIPSE_CLARKE_1880_A;
00117 *f_inv = GEODESY_REFERENCE_ELLIPSE_CLARKE_1880_F_INV;
00118 *b = GEODESY_REFERENCE_ELLIPSE_CLARKE_1880_B;
00119 *e2 = GEODESY_REFERENCE_ELLIPSE_CLARKE_1880_E2;
00120 break;
00121
00122 case GEODESY_REFERENCE_ELLIPSE_EVEREST_INDIA_1830:
00123 *a = GEODESY_REFERENCE_ELLIPSE_EVEREST_INDIA_1830_A;
00124 *f_inv = GEODESY_REFERENCE_ELLIPSE_EVEREST_INDIA_1830_F_INV;
00125 *b = GEODESY_REFERENCE_ELLIPSE_EVEREST_INDIA_1830_B;
00126 *e2 = GEODESY_REFERENCE_ELLIPSE_EVEREST_INDIA_1830_E2;
00127 break;
00128
00129 case GEODESY_REFERENCE_ELLIPSE_EVEREST_BRUNEI_E_MALAYSIA:
00130 *a = GEODESY_REFERENCE_ELLIPSE_EVEREST_BRUNEI_E_MALAYSIA_A;
00131 *f_inv = GEODESY_REFERENCE_ELLIPSE_EVEREST_BRUNEI_E_MALAYSIA_F_INV;
00132 *b = GEODESY_REFERENCE_ELLIPSE_EVEREST_BRUNEI_E_MALAYSIA_B;
00133 *e2 = GEODESY_REFERENCE_ELLIPSE_EVEREST_BRUNEI_E_MALAYSIA_E2;
00134 break;
00135
00136 case GEODESY_REFERENCE_ELLIPSE_EVEREST_W_MALAYSIA_SINGAPORE:
00137 *a = GEODESY_REFERENCE_ELLIPSE_EVEREST_W_MALAYSIA_SINGAPORE_A;
00138 *f_inv = GEODESY_REFERENCE_ELLIPSE_EVEREST_W_MALAYSIA_SINGAPORE_F_INV;
00139 *b = GEODESY_REFERENCE_ELLIPSE_EVEREST_W_MALAYSIA_SINGAPORE_B;
00140 *e2 = GEODESY_REFERENCE_ELLIPSE_EVEREST_W_MALAYSIA_SINGAPORE_E2;
00141 break;
00142
00143 case GEODESY_REFERENCE_ELLIPSE_GRS_1980:
00144 *a = GEODESY_REFERENCE_ELLIPSE_GRS_1980_A;
00145 *f_inv = GEODESY_REFERENCE_ELLIPSE_GRS_1980_F_INV;
00146 *b = GEODESY_REFERENCE_ELLIPSE_GRS_1980_B;
00147 *e2 = GEODESY_REFERENCE_ELLIPSE_GRS_1980_E2;
00148 break;
00149
00150 case GEODESY_REFERENCE_ELLIPSE_HELMERT_1906:
00151 *a = GEODESY_REFERENCE_ELLIPSE_HELMERT_1906_A;
00152 *f_inv = GEODESY_REFERENCE_ELLIPSE_HELMERT_1906_F_INV;
00153 *b = GEODESY_REFERENCE_ELLIPSE_HELMERT_1906_B;
00154 *e2 = GEODESY_REFERENCE_ELLIPSE_HELMERT_1906_E2;
00155 break;
00156
00157 case GEODESY_REFERENCE_ELLIPSE_HOUGH_1960:
00158 *a = GEODESY_REFERENCE_ELLIPSE_HOUGH_1960_A;
00159 *f_inv = GEODESY_REFERENCE_ELLIPSE_HOUGH_1960_F_INV;
00160 *b = GEODESY_REFERENCE_ELLIPSE_HOUGH_1960_B;
00161 *e2 = GEODESY_REFERENCE_ELLIPSE_HOUGH_1960_E2;
00162 break;
00163
00164 case GEODESY_REFERENCE_ELLIPSE_INTERNATIONAL_1924:
00165 *a = GEODESY_REFERENCE_ELLIPSE_INTERNATIONAL_1924_A;
00166 *f_inv = GEODESY_REFERENCE_ELLIPSE_INTERNATIONAL_1924_F_INV;
00167 *b = GEODESY_REFERENCE_ELLIPSE_INTERNATIONAL_1924_B;
00168 *e2 = GEODESY_REFERENCE_ELLIPSE_INTERNATIONAL_1924_E2;
00169 break;
00170
00171 case GEODESY_REFERENCE_ELLIPSE_SOUTH_AMERICAN_1969:
00172 *a = GEODESY_REFERENCE_ELLIPSE_SOUTH_AMERICAN_1969_A;
00173 *f_inv = GEODESY_REFERENCE_ELLIPSE_SOUTH_AMERICAN_1969_F_INV;
00174 *b = GEODESY_REFERENCE_ELLIPSE_SOUTH_AMERICAN_1969_B;
00175 *e2 = GEODESY_REFERENCE_ELLIPSE_SOUTH_AMERICAN_1969_E2;
00176 break;
00177
00178 case GEODESY_REFERENCE_ELLIPSE_WGS72:
00179 *a = GEODESY_REFERENCE_ELLIPSE_WGS72_A;
00180 *f_inv = GEODESY_REFERENCE_ELLIPSE_WGS72_F_INV;
00181 *b = GEODESY_REFERENCE_ELLIPSE_WGS72_B;
00182 *e2 = GEODESY_REFERENCE_ELLIPSE_WGS72_E2;
00183 break;
00184
00185 case GEODESY_REFERENCE_ELLIPSE_WGS84:
00186 *a = GEODESY_REFERENCE_ELLIPSE_WGS84_A;
00187 *f_inv = GEODESY_REFERENCE_ELLIPSE_WGS84_F_INV;
00188 *b = GEODESY_REFERENCE_ELLIPSE_WGS84_B;
00189 *e2 = GEODESY_REFERENCE_ELLIPSE_WGS84_E2;
00190 break;
00191
00192 default:
00193 return FALSE;
00194 break;
00195 }
00196 return TRUE;
00197 }
00198
00199
00200
00201 BOOL GEODESY_GetReferenceEllipseParameters_A_E2(
00202 const GEODESY_enumReferenceEllipse ellipse,
00203 double* a,
00204 double* e2
00205 )
00206 {
00207 double b;
00208 double f_inv;
00209 BOOL result;
00210
00211 result = GEODESY_GetReferenceEllipseParameters(
00212 ellipse,
00213 a,
00214 &b,
00215 &f_inv,
00216 e2 );
00217
00218 return result;
00219 }
00220
00221
00222
00223 BOOL GEODESY_GetReferenceEllipseParameters_A_B_E2(
00224 const GEODESY_enumReferenceEllipse ellipse,
00225 double* a,
00226 double* b,
00227 double* e2
00228 )
00229 {
00230 double f_inv;
00231 BOOL result;
00232
00233 result = GEODESY_GetReferenceEllipseParameters(
00234 ellipse,
00235 a,
00236 b,
00237 &f_inv,
00238 e2 );
00239
00240 return result;
00241 }
00242
00243
00244 BOOL GEODESY_IsLatitudeValid(
00245 const double latitude
00246 )
00247 {
00248
00249 if( latitude > HALFPI || latitude < -HALFPI )
00250 return FALSE;
00251 else
00252 return TRUE;
00253 }
00254
00255
00256
00257
00258
00259
00260
00261 BOOL GEODESY_ConvertGeodeticCurvilinearToEarthFixedCartesianCoordinates(
00262 const GEODESY_enumReferenceEllipse referenceEllipse,
00263 const double latitude,
00264 const double longitude,
00265 const double height,
00266 double *x,
00267 double *y,
00268 double *z
00269 )
00270 {
00271 double a;
00272 double e2;
00273 double N;
00274 double sinlat;
00275 double dtmp;
00276 BOOL result;
00277
00278
00279 result = GEODESY_GetReferenceEllipseParameters_A_E2( referenceEllipse, &a, &e2 );
00280 if( result == FALSE )
00281 {
00282 *x = 0.0;
00283 *y = 0.0;
00284 *z = 0.0;
00285 return FALSE;
00286 }
00287
00288
00289 result = GEODESY_IsLatitudeValid( latitude );
00290 if( result == FALSE )
00291 {
00292 *x = 0.0;
00293 *y = 0.0;
00294 *z = 0.0;
00295 return FALSE;
00296 }
00297
00298 sinlat = sin( latitude );
00299 N = a / sqrt( 1.0 - e2 * sinlat*sinlat );
00300 dtmp = (N + height) * cos(latitude);
00301
00302 *x = dtmp * cos(longitude);
00303 *y = dtmp * sin(longitude);
00304 *z = ( (1.0 - e2)*N + height ) * sinlat;
00305
00306 return TRUE;
00307 }
00308
00309
00310
00311
00312 BOOL GEODESY_ConvertEarthFixedCartesianToGeodeticCurvilinearCoordinates(
00313 const GEODESY_enumReferenceEllipse referenceEllipse,
00314 const double x,
00315 const double y,
00316 const double z,
00317 double *latitude,
00318 double *longitude,
00319 double *height
00320 )
00321 {
00322 double a;
00323 double b;
00324 double e2;
00325 double N;
00326 double p;
00327 double dtmp;
00328 double sinlat;
00329 double lat;
00330 double lon;
00331 double hgt;
00332 BOOL result;
00333
00334
00335 result = GEODESY_GetReferenceEllipseParameters_A_B_E2( referenceEllipse, &a, &b, &e2 );
00336 if( result == FALSE )
00337 {
00338 *latitude = 0;
00339 *longitude = 0;
00340 *height = 0;
00341 return FALSE;
00342 }
00343
00344 if( x == 0.0 && y == 0.0 )
00345 {
00346
00347
00348
00349
00350 lon = 0.0;
00351
00352 if( z < 0 )
00353 {
00354 hgt = -z - b;
00355 lat = -HALFPI;
00356 }
00357 else
00358 {
00359 hgt = z - b;
00360 lat = HALFPI;
00361 }
00362 }
00363 else
00364 {
00365 p = sqrt( x*x + y*y );
00366
00367
00368
00369
00370 lon = 2.0 * atan2( y , ( x + p ) );
00371
00372
00373 lat = atan( z / (p * (1.0 - e2)) );
00374 hgt = 0.0;
00375 do
00376 {
00377 dtmp = hgt;
00378 sinlat = sin(lat);
00379 N = a / sqrt( 1.0 - e2*sinlat*sinlat );
00380 hgt = p / cos(lat) - N;
00381 lat = atan( z / (p * ( 1.0 - e2*N/(N + hgt) )) );
00382
00383 } while( fabs( hgt - dtmp ) > 0.0001 );
00384 }
00385
00386 *latitude = lat;
00387 *longitude = lon;
00388 *height = hgt;
00389 return TRUE;
00390 }
00391
00392
00393 BOOL GEODESY_ComputeNorthingEastingVertical(
00394 const GEODESY_enumReferenceEllipse referenceEllipse,
00395 const double referenceLatitude,
00396 const double referenceLongitude,
00397 const double referenceHeight,
00398 const double latitude,
00399 const double longitude,
00400 const double height,
00401 double *northing,
00402 double *easting,
00403 double *vertical
00404 )
00405 {
00406 double x_ref;
00407 double y_ref;
00408 double z_ref;
00409 double x;
00410 double y;
00411 double z;
00412 double dx;
00413 double dy;
00414 double dz;
00415 double A;
00416 double B;
00417 double cosA;
00418 double sinA;
00419 double cosB;
00420 double sinB;
00421 BOOL result;
00422
00423 *northing = 0;
00424 *easting = 0;
00425 *vertical = 0;
00426
00427 result = GEODESY_IsLatitudeValid( referenceLatitude );
00428 if( result == FALSE )
00429 return FALSE;
00430 result = GEODESY_IsLatitudeValid( latitude );
00431 if( result == FALSE )
00432 return FALSE;
00433
00434 result = GEODESY_ConvertGeodeticCurvilinearToEarthFixedCartesianCoordinates(
00435 referenceEllipse,
00436 referenceLatitude,
00437 referenceLongitude,
00438 referenceHeight,
00439 &x_ref,
00440 &y_ref,
00441 &z_ref );
00442 if( result == FALSE )
00443 return FALSE;
00444
00445 result = GEODESY_ConvertGeodeticCurvilinearToEarthFixedCartesianCoordinates(
00446 referenceEllipse,
00447 latitude,
00448 longitude,
00449 height,
00450 &x,
00451 &y,
00452 &z );
00453 if( result == FALSE )
00454 return FALSE;
00455
00456
00457 A = referenceLatitude - HALFPI;
00458 B = referenceLongitude - PI;
00459
00460 cosA = cos(A);
00461 sinA = sin(A);
00462 cosB = cos(B);
00463 sinB = sin(B);
00464
00465
00466
00467 dx = x - x_ref;
00468 dy = y - y_ref;
00469 dz = z - z_ref;
00470
00471 *northing = cosA*cosB * dx + cosA*sinB * dy - sinA*dz;
00472 *easting = sinB * dx - cosB * dy;
00473 *vertical = sinA*cosB * dx + sinA*sinB * dy + cosA*dz;
00474 return TRUE;
00475 }
00476
00477
00478 BOOL GEODESY_ComputePositionDifference(
00479 const GEODESY_enumReferenceEllipse referenceEllipse,
00480 const double referenceLatitude,
00481 const double referenceLongitude,
00482 const double referenceHeight,
00483 const double latitude,
00484 const double longitude,
00485 const double height,
00486 double *difference_northing,
00487 double *difference_easting,
00488 double *difference_vertical
00489 )
00490 {
00491 BOOL result;
00492 result = GEODESY_ComputeNorthingEastingVertical(
00493 referenceEllipse,
00494 referenceLatitude,
00495 referenceLongitude,
00496 referenceHeight,
00497 latitude,
00498 longitude,
00499 height,
00500 difference_northing,
00501 difference_easting,
00502 difference_vertical );
00503 return result;
00504 }
00505
00506
00507
00508
00509 BOOL GEODESY_ComputeMeridianRadiusOfCurvature(
00510 const GEODESY_enumReferenceEllipse referenceEllipse,
00511 const double latitude,
00512 double* M
00513 )
00514 {
00515 double a;
00516 double e2;
00517 double dtmp;
00518 BOOL result;
00519
00520
00521 result = GEODESY_GetReferenceEllipseParameters_A_E2( referenceEllipse, &a, &e2 );
00522 if( result == FALSE )
00523 {
00524 *M = 0;
00525 return result;
00526 }
00527
00528 dtmp = sin(latitude);
00529 dtmp = sqrt( 1.0 - e2 * dtmp * dtmp );
00530 dtmp = dtmp*dtmp*dtmp;
00531
00532 *M = a * ( 1.0 - e2 ) / dtmp;
00533 return TRUE;
00534 }
00535
00536
00537
00538
00539
00540 BOOL GEODESY_ComputePrimeVerticalRadiusOfCurvature(
00541 const GEODESY_enumReferenceEllipse referenceEllipse,
00542 const double latitude,
00543 double* N
00544 )
00545 {
00546 double a;
00547 double e2;
00548 double W;
00549 BOOL result;
00550
00551
00552 result = GEODESY_GetReferenceEllipseParameters_A_E2( referenceEllipse, &a, &e2 );
00553 if( result == FALSE )
00554 {
00555 *N = 0;
00556 return result;
00557 }
00558
00559 W = sin(latitude);
00560 W = sqrt( 1.0 - e2 * W * W );
00561
00562 *N = a / W;
00563 return TRUE;
00564 }
00565
00566
00567 BOOL GEODESY_ComputeMeridianArcBetweenTwoLatitudes(
00568 const GEODESY_enumReferenceEllipse referenceEllipse,
00569 const double referenceLatitude,
00570 const double latitude,
00571 double* arc
00572 )
00573 {
00574 double a;
00575 double e2;
00576 double e4;
00577 double e6;
00578 double e8;
00579 double dtmp;
00580 double A;
00581 double B;
00582 double C;
00583 double D;
00584 double E;
00585 double arc_ref;
00586 double arc_p;
00587 BOOL result;
00588
00589 *arc = 0;
00590
00591 result = GEODESY_IsLatitudeValid( referenceLatitude );
00592 if( result == FALSE )
00593 return result;
00594
00595
00596 result = GEODESY_GetReferenceEllipseParameters_A_E2( referenceEllipse, &a, &e2 );
00597 if( result == FALSE )
00598 return result;
00599
00600 e4 = e2*e2;
00601 e6 = e4*e2;
00602 e8 = e6*e2;
00603 dtmp = a*(1.0-e2);
00604
00605 A = dtmp * ( 1.0 + 0.75 * e2 + 0.703125 * e4 + 0.68359375 * e6 + 0.67291259765625 * e8 );
00606 B = -dtmp * ( 0.375 * e2 + 0.46875 * e4 + 0.5126953125 * e6 + 0.538330078125 * e8 );
00607 C = dtmp * ( 0.05859375 * e4 + 0.1025390625 * e6 + 0.13458251953125 * e8 );
00608 D = -dtmp * ( 0.011393229167 * e6 + 0.025634765625 * e8 );
00609 E = dtmp * ( 2.4032593e-03 * e8 );
00610
00611 arc_ref = A*referenceLatitude + B*sin(2.0*referenceLatitude) + C*sin(4.0*referenceLatitude) + D*sin(6.0*referenceLatitude) + E*sin(8.0*referenceLatitude);
00612 arc_p = A*latitude + B*sin(2.0*latitude) + C*sin(4.0*latitude) + D*sin(6.0*latitude) + E*sin(8.0*latitude);
00613
00614 *arc = arc_p - arc_ref;
00615 return TRUE;
00616 }
00617
00618
00619
00620
00621 BOOL GEODESY_ComputeParallelArcBetweenTwoLongitudes(
00622 const GEODESY_enumReferenceEllipse referenceEllipse,
00623 const double referenceLatitude,
00624 const double referenceLongitude,
00625 const double longitude,
00626 double* arc
00627 )
00628 {
00629 double a;
00630 double e2;
00631 double N;
00632 BOOL result;
00633
00634 *arc = 0;
00635
00636
00637 result = GEODESY_GetReferenceEllipseParameters_A_E2( referenceEllipse, &a, &e2 );
00638 if( result == FALSE )
00639 return result;
00640
00641 result = GEODESY_IsLatitudeValid( referenceLatitude );
00642 if( result == FALSE )
00643 return result;
00644
00645 N = sin(referenceLatitude);
00646 N = a / sqrt( 1.0 - e2 * N * N );
00647
00648 *arc = N * cos(referenceLatitude) * (longitude - referenceLongitude);
00649 return TRUE;
00650 }
00651
00652
00653
00654
00655 BOOL GEODESY_RotateVectorFromLocalGeodeticFrameToEarthFixedFrame(
00656 const double referenceLatitude,
00657 const double referenceLongitude,
00658 const double dN,
00659 const double dE,
00660 const double dUp,
00661 double* dX,
00662 double* dY,
00663 double* dZ
00664 )
00665 {
00666 double sinlat;
00667 double coslat;
00668 double sinlon;
00669 double coslon;
00670 BOOL result;
00671
00672 result = GEODESY_IsLatitudeValid( referenceLatitude );
00673 if( result == FALSE )
00674 {
00675 *dX = 0;
00676 *dY = 0;
00677 *dZ = 0;
00678 return result;
00679 }
00680
00681 sinlat = sin(referenceLatitude);
00682 coslat = cos(referenceLatitude);
00683 sinlon = sin(referenceLongitude);
00684 coslon = cos(referenceLongitude);
00685
00686 *dX = -sinlat*coslon * dN - sinlon * dE + coslat*coslon * dUp;
00687 *dY = -sinlat*sinlon * dN + coslon * dE + coslat*sinlon * dUp;
00688 *dZ = coslat * dN + sinlat * dUp;
00689 return TRUE;
00690 }
00691
00692
00693
00694
00695 BOOL GEODESY_RotateVectorFromEarthFixedFrameToLocalGeodeticFrame(
00696 const double referenceLatitude,
00697 const double referenceLongitude,
00698 const double dX,
00699 const double dY,
00700 const double dZ,
00701 double* dN,
00702 double* dE,
00703 double* dUp
00704 )
00705 {
00706 double sinlat;
00707 double coslat;
00708 double sinlon;
00709 double coslon;
00710 BOOL result;
00711
00712 result = GEODESY_IsLatitudeValid( referenceLatitude );
00713 if( result == FALSE )
00714 {
00715 *dN = 0;
00716 *dE = 0;
00717 *dUp = 0;
00718 return result;
00719 }
00720
00721 sinlat = sin(referenceLatitude);
00722 coslat = cos(referenceLatitude);
00723 sinlon = sin(referenceLongitude);
00724 coslon = cos(referenceLongitude);
00725
00726 *dN = -sinlat*coslon * dX - sinlat*sinlon * dY + coslat * dZ;
00727 *dE = -sinlon * dX + coslon * dY;
00728 *dUp = coslat*coslon * dX + coslat*sinlon * dY + sinlat * dZ;
00729
00730 return TRUE;
00731 }
00732
00733
00734
00735 BOOL GEODESY_ComputeAzimuthAndElevationAnglesBetweenToPointsInTheEarthFixedFrame(
00736 const GEODESY_enumReferenceEllipse referenceEllipse,
00737 const double fromX,
00738 const double fromY,
00739 const double fromZ,
00740 const double toX,
00741 const double toY,
00742 const double toZ,
00743 double* elevation,
00744 double* azimuth
00745 )
00746 {
00747 double lat;
00748 double lon;
00749 double dX;
00750 double dY;
00751 double dZ;
00752 double dN;
00753 double dE;
00754 double dUp;
00755 double tmp;
00756 BOOL result;
00757
00758 *elevation = 0;
00759 *azimuth = 0;
00760
00761
00762 result = GEODESY_ConvertEarthFixedCartesianToGeodeticCurvilinearCoordinates(
00763 referenceEllipse,
00764 fromX,
00765 fromY,
00766 fromZ,
00767 &lat,
00768 &lon,
00769 &tmp );
00770 if( result == FALSE )
00771 return result;
00772
00773
00774 dX = toX - fromX;
00775 dY = toY - fromY;
00776 dZ = toZ - fromZ;
00777
00778
00779 result = GEODESY_RotateVectorFromEarthFixedFrameToLocalGeodeticFrame(
00780 lat,
00781 lon,
00782 dX,
00783 dY,
00784 dZ,
00785 &dN,
00786 &dE,
00787 &dUp );
00788 if( result == FALSE )
00789 return result;
00790
00791
00792 tmp = sqrt( dN*dN + dE*dE );
00793 *elevation = atan( dUp / tmp );
00794
00795
00796 *azimuth = atan2(dE, dN);
00797
00798
00799 if( *azimuth < 0.0 )
00800 *azimuth += TWOPI;
00801
00802 return TRUE;
00803 }
00804