IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 5554


Ignore:
Timestamp:
Nov 21, 2005, 9:04:02 AM (21 years ago)
Author:
magnier
Message:

fixed p_psPlaneTransformLinearInvert, cleaned up psProject/psDeproject

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/eam_rel8_b0/psLib/src/astro/psCoord.c

    r5547 r5554  
    1010*  @author GLG, MHPCC
    1111*
    12 *  @version $Revision: 1.88.4.1 $ $Name: not supported by cvs2svn $
    13 *  @date $Date: 2005-11-18 20:22:35 $
     12*  @version $Revision: 1.88.4.2 $ $Name: not supported by cvs2svn $
     13*  @date $Date: 2005-11-21 19:04:02 $
    1414*
    1515*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    7676XXX: Use the ADD version which is based on determinants.
    7777 *****************************************************************************/
    78 psPlaneTransform *p_psPlaneTransformLinearInvert(psPlaneTransform *transform)
     78psPlaneTransform *p_psPlaneTransformLinearInvert_MHPCC(psPlaneTransform *transform)
    7979{
    8080    PS_ASSERT_PTR_NON_NULL(transform, 0);
     
    104104    }
    105105
    106     psPlaneTransform *out = psPlaneTransformAlloc(2, 2);
     106    psPlaneTransform *out = psPlaneTransformAlloc(1, 1);
    107107
    108108    /* This is sample code from IfA.  It didn't work initially, and I did not
    109109       spend any time debugging it.
    110 
    111         psF64 a = transform->x->coeff[1][0];
    112         psF64 b = transform->x->coeff[0][1];
    113         psF64 c = transform->y->coeff[1][0];
    114         psF64 d = transform->y->coeff[0][1];
    115         psF64 e = transform->x->coeff[0][0];
    116         psF64 f = transform->y->coeff[0][0];
    117 
    118         psF64 invDet = 1.0 / (a * d - b * c); // Inverse of the determinant
    119 
    120         // Not entirely sure why this works, but it appears to do so....................................!
    121         out->x->coeff[1][0] = invDet * a;
    122         out->x->coeff[0][1] = - invDet * b;
    123         out->y->coeff[1][0] = - invDet * c;
    124         out->y->coeff[0][1] = invDet * d;
    125 
    126         out->x->coeff[0][0] = - invDet * (d * e + c * f);
    127         out->y->coeff[0][0] = - invDet * (b * e + a * f);
     110       XXX EAM : here is the correct matrix inversion code
     111
     112        psF64 r11 = transform->x->coeff[1][0];
     113        psF64 r12 = transform->x->coeff[0][1];
     114        psF64 r21 = transform->y->coeff[1][0];
     115        psF64 r22 = transform->y->coeff[0][1];
     116        psF64 xo  = transform->x->coeff[0][0];
     117        psF64 yo  = transform->y->coeff[0][0];
     118
     119        psF64 invDet = 1.0 / (r11 * r22 - r12 * r21); // Inverse of the determinant
     120
     121        out->x->coeff[1][0] = +invDet * r22;
     122        out->x->coeff[0][1] = -invDet * r12;
     123        out->y->coeff[1][0] = -invDet * r21;
     124        out->y->coeff[0][1] = +invDet * r11;
     125
     126        out->x->coeff[0][0] = - invDet * (r22 * xo - r12 * yo);
     127        out->y->coeff[0][0] = - invDet * (r11 * yo - r21 * xo);
    128128    */
    129129    out->x->coeff[0][0] = (-D + ((F*A)/C)) / (E - ((F*B)/C));
     
    134134    out->y->coeff[0][1] =  1.0 / (F - ((C*E)/B));
    135135
     136    return(out);
     137}
     138
     139// XXX EAM : the above code yielded NaNs for the y coeffs.  below is the code
     140//           using the standard matrix representation.  note that this inversion
     141//           requires x->nX == 1, y->nY == 1 and x->nY <= 1, y->nX <= 1
     142psPlaneTransform *p_psPlaneTransformLinearInvert(psPlaneTransform *transform)
     143{
     144    PS_ASSERT_PTR_NON_NULL(transform, 0);
     145    PS_ASSERT_PTR_NON_NULL(transform->x, 0);
     146    PS_ASSERT_PTR_NON_NULL(transform->y, 0);
     147
     148    if (transform->x->nX != 1)
     149        return NULL;
     150    if (transform->y->nY != 1)
     151        return NULL;
     152    if (transform->x->nY > 1)
     153        return NULL;
     154    if (transform->y->nX > 1)
     155        return NULL;
     156
     157    // this choice is consistent with the nOrder form for the polynomials
     158    psPlaneTransform *out = psPlaneTransformAlloc(1, 1);
     159
     160    // unless the cross terms are available, set these matrix elements to 0
     161    psF64 r12 = 0.0;
     162    if (transform->x->nY == 1) {
     163        r12 = transform->x->coeff[0][1];
     164    }
     165    psF64 r21 = 0.0;
     166    if (transform->y->nX == 1) {
     167        r21 = transform->y->coeff[1][0];
     168    }
     169    psF64 r11 = transform->x->coeff[1][0];
     170    psF64 r22 = transform->y->coeff[0][1];
     171    psF64 xo  = transform->x->coeff[0][0];
     172    psF64 yo  = transform->y->coeff[0][0];
     173
     174    psF64 invDet = 1.0 / (r11 * r22 - r12 * r21);
     175
     176    // apply the results back to the polynomials
     177    out->x->coeff[0][0] = -invDet * (r22 * xo - r12 * yo);
     178    out->y->coeff[0][0] = -invDet * (r11 * yo - r21 * xo);
     179    out->x->coeff[1][0] = +invDet * r22;
     180    out->y->coeff[0][1] = +invDet * r11;
     181    if (transform->x->nY == 1) {
     182        out->x->coeff[0][1] = -invDet * r12;
     183    }
     184    if (transform->y->nX == 1) {
     185        out->y->coeff[1][0] = -invDet * r21;
     186    }
    136187    return(out);
    137188}
     
    389440    PS_ASSERT_PTR_NON_NULL(projection, NULL);
    390441
    391     psF64   theta = 0.0;
    392     psF64   phi   = 0.0;
     442    psF64 phi, theta;
     443    psF64 sinDp, cosDp, sinAlpha, cosAlpha, sinDelta, cosDelta;
     444    psF64 sinTheta, cosPhiCT, sinPhiCT, zeta;
     445
     446    bool zenithal = (projection->type == PS_PROJ_TAN) ||(projection->type == PS_PROJ_SIN);
    393447
    394448    // Allocate return value
    395449    psPlane* out = psPlaneAlloc();
    396450
    397     // Convert to projection spherical coordinate system
    398     theta = asin( sin(coord->d)*sin(projection->D) +
    399                   cos(coord->d)*cos(projection->D)*cos(coord->r-projection->R));
    400     phi = atan2( -1.0*cos(coord->d)*sin(coord->r-projection->R),
    401                  sin(coord->d)*cos(projection->D) - cos(coord->d)*sin(projection->D)*cos(coord->r-projection->R) );
     451    if (zenithal) {
     452        sinDp = sin(projection->D);
     453        cosDp = cos(projection->D);
     454        sinAlpha = sin(coord->r-projection->R);
     455        cosAlpha = cos(coord->r-projection->R);
     456        sinDelta = sin(coord->d);
     457        cosDelta = cos(coord->d);
     458
     459        sinTheta =  sinDelta*sinDp + cosDelta*cosDp*cosAlpha;
     460        cosPhiCT =  sinDelta*cosDp - cosDelta*sinDp*cosAlpha;
     461        sinPhiCT = -cosDelta*sinAlpha;
     462    } else {
     463        phi = coord->r - projection->R;
     464        theta = coord->d - projection->D;
     465    }
    402466
    403467    // Perform the specified projection
    404     // Gnomonic projection
    405     if (projection->type == PS_PROJ_TAN) {
    406         out->x = (cos(theta)*sin(phi))/sin(theta);
    407         out->y = (-1.0*cos(theta)*cos(phi))/sin(theta);
     468    switch (projection->type) {
     469    case PS_PROJ_TAN:
     470        // Gnomonic projection
     471        out->x = +sinPhiCT / sinTheta;
     472        out->y = -cosPhiCT / sinTheta;
     473        break;
     474    case PS_PROJ_SIN:
    408475        // Othrographic projection
    409     } else if (projection->type == PS_PROJ_SIN) {
    410         out->x = cos(theta)*sin(phi);
    411         out->y = -1.0*cos(theta)*cos(phi);
     476        out->x = +sinPhiCT;
     477        out->y = -cosPhiCT;
     478        break;
     479    case PS_PROJ_AIT:
    412480        // Hammer-Aitoff projection
    413     } else if ( projection->type == PS_PROJ_AIT) {
    414         psF64 zeta = 1.0/sqrt(0.5*(1.0+cos(theta)*cos(phi/2.0)));
     481        zeta = 1.0/sqrt(0.5*(1.0+cos(theta)*cos(phi/2.0)));
    415482        out->x = 2.0*zeta*cos(theta)*sin(phi/2.0);
    416483        out->y = zeta*sin(theta);
     484        break;
     485    case PS_PROJ_PAR:
    417486        // Parabolic projection
    418     } else if ( projection->type == PS_PROJ_PAR) {
    419487        out->x = phi*(2.0*cos(2.0*theta/3.0) - 1.0);
    420488        out->y = M_PI*sin(theta/3.0);
    421     } else {
     489    default:
    422490        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
    423491                PS_ERRORTEXT_psCoord_PROJECTION_TYPE_UNKNOWN,
     
    441509    PS_ASSERT_PTR_NON_NULL(projection, NULL);
    442510
     511    psF64 rho      = 0.0;
     512    psF64 sinTheta = 0.0;
     513    psF64 cosTheta = 0.0;
     514    psF64 sinPhi   = 0.0;
     515    psF64 cosPhi   = 0.0;
     516
    443517    psF64  theta = 0.0;
    444518    psF64  phi   = 0.0;
     
    450524    psF64  x = coord->x*projection->Xs;
    451525    psF64  y = coord->y*projection->Ys;
     526    psF64  R = sqrt(x*x + y*y);
     527
     528    bool zenithal = (projection->type == PS_PROJ_TAN) ||(projection->type == PS_PROJ_SIN);
    452529
    453530    // Perform inverse projection
    454     // Gnonomic deprojection
    455     if ( projection->type == PS_PROJ_TAN) {
    456         phi = atan(-1.0*x/y);
    457         theta = atan(1.0/sqrt(x*x+y*y));
     531    switch (projection->type) {
     532    case PS_PROJ_TAN:
     533        // Gnonomic deprojection
     534        rho      = sqrt (1 + R*R);
     535        sinTheta = 1 / rho;
     536        cosTheta = R / rho;
     537        sinPhi   = (R == 0) ? 0.0 : +x / R;
     538        cosPhi   = (R == 0) ? 1.0 : -y / R;
     539        break;
     540    case PS_PROJ_SIN:
    458541        // Orhtographic deprojection
    459     } else if ( projection->type == PS_PROJ_SIN) {
    460         phi = atan((-1.0*x)/y);
    461         theta = atan( sqrt(1.0-(x*x+y*y)) / sqrt(x*x+y*y));
     542        sinTheta = sqrt (1 - R*R);
     543        cosTheta = R;
     544        sinPhi   = (R == 0) ? 0.0 : +x / R;
     545        cosPhi   = (R == 0) ? 1.0 : -y / R;
     546        break;
     547    case PS_PROJ_AIT:
    462548        // Hammer-Aitoff deprojection
    463     } else if ( projection->type == PS_PROJ_AIT) {
    464         psF64 z = sqrt(1.0 - ((x/4.0)*(x/4.0)) - ((y/2.0)*(y/2.0)));
    465         phi = 2.0*atan((z*x) / (2.0*(2.0*z*z-1.0)) );
    466         theta = asin(y*z);
     549        // XXX EAM : need range check on z^2 : must be > 0
     550        // XXX EAM : old code, ADD, and elixir code are discrepant re x/4, y/2
     551        rho = sqrt(1.0 - PS_SQR(x/4.0) - PS_SQR(y/2.0));
     552        phi = 2.0*atan2((2.0*rho*rho-1.0), x*rho);
     553        theta = asin(y*rho);
     554        break;
     555    case PS_PROJ_PAR:
    467556        // Parabolic deprojection
    468     } else if ( projection->type == PS_PROJ_PAR) {
    469         psF64 rho = y/M_PI;
     557        rho = y/M_PI;
    470558        phi = x/(1.0 - 4.0*rho*rho);
    471559        theta = 3.0*asin(rho);
    472         // Invalid deprojection type
    473     } else {
     560        break;
     561    default:
    474562        psError(PS_ERR_BAD_PARAMETER_TYPE, true,
    475563                PS_ERRORTEXT_psCoord_PROJECTION_TYPE_UNKNOWN,
     
    479567    }
    480568
    481     // Convert from projection spherical coordinates
    482     out->d = asin( sin(theta)*sin(projection->D) +
    483                    cos(theta)*cos(projection->D)*cos(phi) );
    484     out->r = projection->R + atan2( -1.0*cos(theta)*sin(phi),
    485                                     sin(theta)*cos(projection->D) -
    486                                     cos(theta)*sin(projection->D)*cos(phi) );
     569    if (zenithal) {
     570        psF64 sinDp = sin(projection->D);
     571        psF64 cosDp = cos(projection->D);
     572
     573        // Convert from projection spherical coordinates
     574        psF64 delta = asin(sinTheta*sinDp + cosTheta*cosDp*cosPhi);
     575        psF64 sinAlphaF = -cosTheta*sinPhi;
     576        psF64 cosAlphaF = -cosTheta*cosPhi*sinDp + sinTheta*cosDp;
     577
     578        out->d = delta;
     579        out->r = atan2(sinAlphaF, cosAlphaF) + projection->R;
     580    } else {
     581        out->r = phi   + projection->R;
     582        out->d = theta + projection->D;
     583    }
    487584
    488585    // Return sphere coordinate
Note: See TracChangeset for help on using the changeset viewer.