Changeset 6309 for trunk/psLib/src/astro/psSphereOps.c
- Timestamp:
- Feb 2, 2006, 1:19:58 PM (20 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/astro/psSphereOps.c (modified) (31 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/astro/psSphereOps.c
r6039 r6309 8 8 * @author Dave Robbins, MHPCC 9 9 * 10 * @version $Revision: 1.1 0$ $Name: not supported by cvs2svn $11 * @date $Date: 2006-0 1-18 23:49:06$10 * @version $Revision: 1.11 $ $Name: not supported by cvs2svn $ 11 * @date $Date: 2006-02-02 23:19:58 $ 12 12 * 13 13 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 44 44 { 45 45 psSphereRot r,s,t; 46 47 // directly from ADD -- there must be a better way?!46 //The following represents: r =a rotation about the z-axis by alphaP, s =a rotation about 47 // the y-axis by deltaP, and t =a rotation about the z-axis by phiP. 48 48 r.q0=0; 49 49 r.q1=0; … … 71 71 bool psMemCheckSphereRot(psPtr ptr) 72 72 { 73 //See if the ptr corresponds to a psSphereRot* 73 74 return ( psMemGetDeallocator(ptr) == (psFreeFunc)sphereRotFree ); 74 75 } 75 76 76 77 //This function is really a second allocate function for psSphereRot's that uses quaternion 78 // component inputs instead of angle inputs as in psSphereRotAlloc. 77 79 psSphereRot* psSphereRotQuat(double q0, 78 80 double q1, … … 80 82 double q3) 81 83 { 84 //allocate space for a new sphere rotation and set deallocator 82 85 psSphereRot* rot = (psSphereRot*)psAlloc(sizeof(psSphereRot)); 83 86 psMemSetDeallocator(rot, (psFreeFunc)sphereRotFree); 84 87 88 //The magnitude of a rotation quaternion should = 1 so we normalize here in case the 89 // inputs have not been. 85 90 double len = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3); 86 91 rot->q0 = q0 / len; … … 92 97 } 93 98 94 psSphereRot* psSphereRotConjugate(psSphereRot *out, const psSphereRot *in) 95 { 99 psSphereRot* psSphereRotConjugate(psSphereRot *out, 100 const psSphereRot *in) 101 { 102 //if input sphere rotation is NULL, return NULL 96 103 if (in == NULL) { 97 104 psError(PS_ERR_BAD_PARAMETER_NULL, true, … … 99 106 return NULL; 100 107 } 108 //if output sphere rotation is NULL, allocate a new sphere rotation to return 101 109 if (out == NULL) { 102 110 out = (psSphereRot* ) psAlloc(sizeof(psSphereRot)); 103 111 psMemSetDeallocator(out, (psFreeFunc)sphereRotFree); 104 112 } 113 //Since q3 is the magnitude and q0,q1,q2 are direction, the conjugate rotation 114 // is formed by -q0,-q1,-q2,+q3. Note that this is the same as q0,q1,q2,-q3. 105 115 out->q0 = -in->q0; 106 116 out->q1 = -in->q1; … … 111 121 } 112 122 113 /******************************************************************************114 XXX: We convert Right Ascension angles to the range 0:PI. Is that acceptable?115 XXX: Should we do something for Declination as well?116 *****************************************************************************/117 123 psSphere* psSphereRotApply(psSphere* out, 118 124 const psSphereRot* transform, 119 125 const psSphere* coord) 120 126 { 127 //Make sure that input coordinates and rotation are not NULL 121 128 PS_ASSERT_PTR_NON_NULL(transform, NULL); 122 129 PS_ASSERT_PTR_NON_NULL(coord, NULL); 123 130 //If output coordinates is NULL allocate a new psSphere 124 131 if (out == NULL) { 125 132 out = psSphereAlloc(); 126 133 } 127 // double r = -coord->r; 128 // apply the transform by creating a new psSphereRot from the input coord 134 //apply the transform by creating a new psSphereRot from the input coord 129 135 // and combining it with the input transform (see ADD) 130 136 double cosD = cos(coord->d); … … 134 140 sin(coord->d), 135 141 0.0); 136 137 /* psSphereRot *test = psSphereRotICRSToGalactic(); 138 if (fabs(coord->d-DEG_TO_RAD(27.1283)) < 0.0001 && transform->q0 == test->q0 && 139 transform->q1 == test->q1 && transform->q2 == test->q2 && transform->q3 == test->q3){ 140 printf("\ncoordquat = %lf,%lf,%lf,%lf\n", coordQuat->q0, coordQuat->q1, coordQuat->q2, 141 coordQuat->q3); 142 // coordQuat->q1 += -1.0; 143 test->q3 = - test->q3; 144 *(psSphereRot**)&transform = test; 145 } 146 psFree(test); 147 */ 148 // Inserted by PAP 142 //Get the conjugate of the input rotation. Need to calculate r*p*R to apply rotation 143 // where R = r-conjugate. 149 144 psSphereRot *conjugate = psSphereRotConjugate(NULL, transform); 150 145 psSphereRot *temp = psSphereRotCombine(NULL, transform, coordQuat); 151 146 psSphereRot *result = psSphereRotCombine(NULL, temp, conjugate); 147 //From ADD we can find the new sphere coordinates, 148 // r is calculated as tan^-1 (q1/q0), d is sin^-1 (q2) 152 149 out->r = atan2(result->q1, result->q0); 153 // out->r = atan2(result->q1, result->q0);154 150 out->d = asin(result->q2); 155 151 out->rErr = 0.0; 156 152 out->dErr = 0.0; 157 158 if (out->r < -0.0001) { 153 //Simply for convention, we make sure all output r-parameters are positive in the range 154 // of 0 to 2pi 155 if (out->r < -0.000001) { 159 156 out->r += 2.0 * M_PI; 160 157 } … … 165 162 psFree(coordQuat); 166 163 return out; 167 // Pau.168 169 #if 0170 // psSphereRot* coordQuatConjugate = psSphereRotQuat(171 // coordQuat->q0, coordQuat->q1, coordQuat->q2, coordQuat->q3);172 // coordQuat = psSphereRotInvert(coordQuat);173 174 // calculate q=(rp)r'175 // coordQuat = psSphereRotCombine(coordQuat, transform, coordQuat);176 // coordQuat = psSphereRotCombine(coordQuat, coordQuat, coordQuatConjugate);177 // N.B., we can recycle coordQuat right away due to the implementation of178 // psSphereRotCombine; it puts the input values in a local variable first179 180 // out->r = atan2(coordQuat->q1,coordQuat->q0);181 // out->d = asin(coordQuat->q2);182 183 184 // psSphereRot *inv = psSphereRotInvert(transform);185 psSphereRot *inv = (psSphereRot*)psAlloc(sizeof(psSphereRot));186 *inv = *transform;187 // psSphereRot *result = psSphereRotCombine(NULL, transform, coordQuat);188 // inv = psSphereRotInvert(inv);189 // psSphereRotCombine(result, result, inv);190 // psSphereRot *result = psSphereRotCombine(NULL, inv, coordQuat);191 // psSphereRotCombine(result, result, transform);192 // psSphereRot *result = psSphereRotCombine(NULL, coordQuat, transform);193 // psSphereRotCombine(result, inv, result);194 195 psSphereRot *result = psSphereRotCombine(NULL, coordQuat, transform);196 inv = psSphereRotInvert(inv);197 // *(psSphereRot**)&transform = psSphereRotInvert( *(psSphereRot**)&transform);198 result = psSphereRotCombine(result, inv, result);199 // *(psSphereRot**)&transform = psSphereRotInvert( *(psSphereRot**)&transform);200 201 // out->r = atan2(result->q0, result->q1);202 out->r = atan2(result->q1, result->q0);203 out->d = asin(result->q2);204 out->rErr = 0.0;205 out->dErr = 0.0;206 psFree(inv);207 psFree(result);208 209 psFree(coordQuat);210 // psFree(coordQuatConjugate);211 212 return out;213 #endif214 164 } 215 165 … … 218 168 const psSphereRot* rot2) 219 169 { 170 //Make sure that input rotations are not NULL 220 171 PS_ASSERT_PTR_NON_NULL(rot1, NULL); 221 172 PS_ASSERT_PTR_NON_NULL(rot2, NULL); 222 173 //If output rotation is NULL, allocate a new psSphereRot to return 223 174 if (out == NULL) { 224 175 out = (psSphereRot* ) psAlloc(sizeof(psSphereRot)); … … 235 186 double b3 = rot2->q3; 236 187 237 // following came from ADD 238 // out->q0 = b3*a0 + b2*a1 - b1*a2 + b0*a3; 239 // out->q1 = b3*a1 - b2*a0 + b1*a3 + b0*a2; 240 // out->q2 = b3*a2 + b2*a3 + b1*a0 - b0*a1; 188 //Combine rot1 & rot2. Formulas here came from ADD. 241 189 out->q0 = a3*b0 + a0*b3 + a1*b2 - a2*b1; 242 190 out->q1 = a3*b1 - a0*b2 + a1*b3 + a2*b0; 243 191 out->q2 = a3*b2 + a0*b1 - a1*b0 + a2*b3; 244 245 192 out->q3 = b3*a3 - b2*a2 - b1*a1 - b0*a0; 246 193 … … 252 199 double phiP) 253 200 { 201 //This function should produce identical results to psSphereRotConjugate in most 202 // or possibly all situations. Creates the inverse rotation from the input angles. 254 203 return (psSphereRotAlloc(-phiP, -deltaP, -alphaP)); 255 204 } … … 258 207 { 259 208 psF64 T; 260 261 209 // Check for null parameter 262 210 PS_ASSERT_PTR_NON_NULL(time, NULL); 263 264 211 // Convert psTime to MJD 265 212 psF64 MJD = psTimeToMJD(time); 266 267 213 // Check the specified MJD is greater than 1900 268 214 if ( MJD < MJD_1900 ) { … … 270 216 return NULL; 271 217 } 272 273 218 // Calculate number of Julian centuries since 1900 274 219 T = ( MJD - MJD_1900 ) / JULIAN_CENTURY; 275 220 //Formulas for phiP, deltaP, alphaP came from ADD. 276 221 psF64 phiP = - DEG_TO_RAD(270.0); 277 222 psF64 deltaP = - (DEG_TO_RAD(23.0) + … … 289 234 { 290 235 psF64 T; 291 292 236 // Check for null parameter 293 237 PS_ASSERT_PTR_NON_NULL(time, NULL); 294 295 238 // Convert psTime to MJD 296 239 psF64 MJD = psTimeToMJD(time); 297 298 240 // Check the specified MJD is greater than 1900 299 241 if ( MJD < MJD_1900 ) { … … 301 243 return NULL; 302 244 } 303 304 245 // Calculate number of Julian centuries since 1900 305 246 T = ( MJD - MJD_1900 ) / JULIAN_CENTURY; 306 247 248 //Formulas for phiP, deltaP, alphaP came from ADD. Notice that the formulas are the 249 // same as for EclipticToICRS except that alpha=-phiP, deltaP=-deltaP, phiP=-alphaP to 250 // produce the inverse rotation as in psSphereRotInverse. 307 251 psF64 alphaP = DEG_TO_RAD(270.0); 308 252 psF64 deltaP = DEG_TO_RAD(23.0) + … … 317 261 } 318 262 319 // XXX: This is bug 245: alphaP swaps with phiP from psSphereTransformGalacticToICRS()320 263 psSphereRot* psSphereRotGalacticToICRS(void) 321 264 { 322 /* psF64 phiP = - DEG_TO_RAD(180.0-192.85948); 323 psF64 deltaP = - DEG_TO_RAD(90.0 - 27.12825); 324 psF64 alphaP = - DEG_TO_RAD(90.0+32.93192); 325 */ 265 //Formulas for alphaP, deltaP, phiP came from the ADD for ICRSToGalactic. Notice that 266 // this is the reason the inverse gets allocated and returned here. 326 267 psF64 alphaP = DEG_TO_RAD(180.0-192.85948); 327 268 psF64 deltaP = DEG_TO_RAD(90.0 - 27.12825); … … 332 273 psSphereRot* psSphereRotICRSToGalactic(void) 333 274 { 275 //Formulas for alphaP, deltaP, phiP came from ADD. 334 276 psF64 alphaP = DEG_TO_RAD(180.0-192.85948); 335 277 psF64 deltaP = DEG_TO_RAD(90.0 - 27.12825); … … 339 281 } 340 282 341 /****************************************************************************** 342 The basic idea is to project both positions onto the linear plane, with 343 position1 at the center, then calculate the linear offset between those 344 projections. 345 346 XXX: Do I need to check for unacceptable transformation parameters? Maybe, 347 if the points are on the North/South Pole, etc? 348 349 XXX: Do I need to somehow scale this projection? 350 351 XXX: Does PS_LINEAR mode make sense? The result must be returned in psSphere 352 regardless of the mode. 353 354 XXX: How to compound errors? 355 *****************************************************************************/ 283 //Calculates the difference between coordinates in position1 & 2 and returns this offset. 356 284 psSphere* psSphereGetOffset(const psSphere* position1, 357 285 const psSphere* position2, … … 359 287 psSphereOffsetUnit unit) 360 288 { 289 //Make sure that input coordinates are not NULL & that mode & unit are valid 361 290 PS_ASSERT_PTR_NON_NULL(position1, NULL); 362 291 PS_ASSERT_PTR_NON_NULL(position2, NULL); 363 364 292 // Check positions near 90 degree and issue warnings if necessary 365 293 if (position1->d >= DEG_TO_RAD(90.0)) { … … 373 301 return NULL; 374 302 } 375 376 303 // Allocate return structure 377 304 psSphere* tmp = psSphereAlloc(); … … 380 307 // onto tangent plane, set point projected into psSphere structure x->r y->d 381 308 if (mode == PS_LINEAR) { 309 //The basic idea is to project both positions onto the linear plane, with position1 310 // at the center, then calculate the linear offset between those projections. 382 311 psProjection* proj = psProjectionAlloc(position1->r, 383 312 position1->d, … … 385 314 1.0, 386 315 PS_PROJ_TAN); 387 388 316 // Perform projection onto tangent plane 389 317 psPlane* lin = psProject(position2, proj); 390 391 318 // Set return values 392 319 tmp->r = lin->x; 393 320 tmp->d = lin->y; 394 395 321 // Free data structures allocated 396 322 psFree(proj); … … 410 336 tmp->dErr = 0.0; 411 337 412 // Convert to desired units338 // Convert output to desired units 413 339 if (unit == PS_ARCSEC) { 414 340 tmp->r = RAD_TO_SEC(tmp->r); … … 428 354 return NULL; 429 355 } 356 430 357 // Invalid mode 431 358 } else { 432 433 359 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 434 360 PS_ERRORTEXT_psCoord_OFFSET_MODE_UNKNOWN, … … 442 368 } 443 369 444 /****************************************************************************** 445 XXX: Do we need to check for unacceptable transformation parameters? Maybe, 446 if the points are on the North/South Pole, etc? 447 448 XXX: Do we need to somehow scale this projection? 449 450 XXX: I copied the algorithm from the ADD exactly. 451 452 XXX: Should we compound errors? 453 *****************************************************************************/ 454 370 //Applies the specified offset to the input position coordinates and returns the new position. 455 371 psSphere* psSphereSetOffset(const psSphere* position, 456 372 const psSphere* offset, … … 458 374 psSphereOffsetUnit unit) 459 375 { 376 //Make sure that input coordinates are not NULL & that mode & unit are valid 460 377 PS_ASSERT_PTR_NON_NULL(position, NULL); 461 378 PS_ASSERT_PTR_NON_NULL(offset, NULL); … … 469 386 // new sphere coordinate 470 387 if (mode == PS_LINEAR) { 471 472 388 // Allocate plane coordinate and set coordinate 473 389 psPlane* lin = psPlaneAlloc(); 474 390 lin->x = offset->r; 475 391 lin->y = offset->d; 476 477 392 // Allocate and set projection structure 478 393 psProjection* proj = psProjectionAlloc(position->r, … … 481 396 1.0, 482 397 PS_PROJ_TAN); 483 484 398 // Project tangent plane coord to spherical coord 485 399 tmp = psDeproject(lin, proj); 486 487 400 // Free data structures used 488 401 psFree(proj); … … 492 405 // to the position and wrap to 0 to 2pi 493 406 } else if (mode == PS_SPHERICAL) { 494 495 407 // Convert offset unit to radians 496 408 if (unit == PS_ARCSEC) { … … 526 438 // Invalid mode report error 527 439 } else { 528 529 440 psError(PS_ERR_BAD_PARAMETER_VALUE, true, 530 441 PS_ERRORTEXT_psCoord_OFFSET_MODE_UNKNOWN,
Note:
See TracChangeset
for help on using the changeset viewer.
