IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Mar 31, 2005, 1:01:46 PM (21 years ago)
Author:
desonia
Message:

cosmetic tweaks.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/astronomy/psCoord.c

    r3540 r3598  
    1010*  @author GLG, MHPCC
    1111*
    12 *  @version $Revision: 1.60 $ $Name: not supported by cvs2svn $
    13 *  @date $Date: 2005-03-29 19:41:56 $
     12*  @version $Revision: 1.61 $ $Name: not supported by cvs2svn $
     13*  @date $Date: 2005-03-31 23:01:46 $
    1414*
    1515*  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    2626#include "psLogMsg.h"
    2727#include "psAstronomyErrors.h"
     28#include "psAstrometry.h"
     29#include "psMatrix.h"
    2830#include <math.h>
    2931#include <float.h>
     
    5961/*  FUNCTION IMPLEMENTATION - LOCAL                                          */
    6062/*****************************************************************************/
     63/*****************************************************************************
     64multiplyDPoly2D(trans1, trans2): Takes two 2-D polynomials as input and
     65multiplies them.  Basically, for each non-zero coeff in the trans1 coeff[][]
     66array, you must multiply by all non-zero coeffs in trans2.
     67 
     68XXX: Inefficient in that the out polynomial is allocated every time.
     69 *****************************************************************************/
     70
     71psDPolynomial2D *multiplyDPoly2D(psDPolynomial2D *trans1,
     72                                 psDPolynomial2D *trans2)
     73{
     74    psS32 orderX = (trans1->nX + trans2->nX) - 1;
     75    psS32 orderY = (trans1->nX + trans2->nX) - 1;
     76
     77    psDPolynomial2D *out = psDPolynomial2DAlloc(orderX, orderY, PS_POLYNOMIAL_ORD);
     78    for (psS32 i = 0 ; i < out->nX; i++) {
     79        for (psS32 j = 0 ; j < out->nY; j++) {
     80            out->coeff[i][j] = 0.0;
     81            out->mask[i][j] = 0;
     82        }
     83    }
     84
     85    for (psS32 t1x = 0 ; t1x < trans1->nX ; t1x++) {
     86        for (psS32 t1y = 0 ; t1y < trans1->nY ; t1y++) {
     87            if (0.0 != trans1->coeff[t1x][t1y]) {
     88                for (psS32 t2x = 0 ; t2x < trans2->nX ; t2x++) {
     89                    for (psS32 t2y = 0 ; t2y < trans2->nY ; t2y++) {
     90                        out->coeff[t1x+t2x][t1y+t2y]+= (trans1->coeff[t1x][t1y] * trans2->coeff[t2x][t2y]);
     91                    }
     92                }
     93            }
     94        }
     95    }
     96    return(out);
     97}
    6198
    6299/*****************************************************************************/
     
    66103{
    67104    // There are non dynamic allocated items
     105}
     106
     107/*****************************************************************************
     108p_psPlaneTransformLinearInvert(transform): : this is a private function which
     109simply inverts the supplied psPlaneTransform transform.  It assumes that
     110"transform" is linear.
     111 
     112This program assumes that the inverse of the following linear equations:
     113        X2 = A + (B * X1) + (C * Y1);
     114        Y2 = D + (E * X1) + (F * Y1);
     115is
     116        Y1 = (Y2 - ((E/B) * X2) - D + ((E*A)/B)) / (F - ((C*E)/B));
     117        X1 = (Y2 - ((F/C) * X2) - D + ((F*A)/C)) / (E - ((F*B)/C));
     118or
     119 X1 = (-D + ((F*A)/C)) / (E - ((F*B)/C)) +
     120      (X2 * -((F/C) / (E - ((F*B)/C)))) +
     121             (Y2 * (1.0 / (E - ((F*B)/C))));
     122        Y1 = (-D + ((E*A)/B))/(F - ((C*E)/B)) +
     123             (X2 * -((E/B) / (F - ((C*E)/B)))) +
     124             (Y2 * (1.0 / (F - ((C*E)/B))));
     125 
     126XXX: Since thre is now a general psPlaneTransformInvert() function, we
     127should rename this.
     128 
     129 *****************************************************************************/
     130psPlaneTransform *p_psPlaneTransformLinearInvert(psPlaneTransform *transform)
     131{
     132    PS_PTR_CHECK_NULL(transform, 0);
     133    PS_PTR_CHECK_NULL(transform->x, 0);
     134    PS_PTR_CHECK_NULL(transform->y, 0);
     135
     136    psF64 A = 0.0;
     137    psF64 B = 0.0;
     138    psF64 C = 0.0;
     139    psF64 D = 0.0;
     140    psF64 E = 0.0;
     141    psF64 F = 0.0;
     142
     143    // XXX: Test this for correctness.
     144    A = transform->x->coeff[0][0];
     145    if (transform->x->nX >= 2) {
     146        B = transform->x->coeff[1][0];
     147    }
     148    if (transform->x->nY >= 2) {
     149        C = transform->x->coeff[0][1];
     150    }
     151    D = transform->y->coeff[0][0];
     152    if (transform->y->nX >= 2) {
     153        E = transform->y->coeff[1][0];
     154    }
     155    if (transform->y->nY >= 2) {
     156        F = transform->y->coeff[0][1];
     157    }
     158
     159    // XXX: Use the constructor here.
     160    psPlaneTransform *out = psPlaneTransformAlloc(2, 2);
     161
     162    out->x->coeff[0][0] = -D + ((F*A)/C) / (E - ((F*B)/C));
     163    out->x->coeff[1][0] = -(F/C) / (E - ((F*B)/C));
     164    out->x->coeff[0][1] =  1.0 / (E - ((F*B)/C));
     165    out->y->coeff[0][0] = -D + ((E*A)/B) / (F - ((C*E)/B));
     166    out->y->coeff[1][0] = -(E/B) / (F - ((C*E)/B));
     167    out->y->coeff[0][1] =  1.0 / (F - ((C*E)/B));
     168
     169    return(out);
     170}
     171
     172/*****************************************************************************
     173p_psIsProjectionLinear(): this is a private function which simply determines
     174if the supplied psPlaneTransform transform is linear: if any of the
     175cooefficients of order 2 are higher are non-zero, then it is not linear.
     176 *****************************************************************************/
     177psS32 p_psIsProjectionLinear(psPlaneTransform *transform)
     178{
     179    PS_PTR_CHECK_NULL(transform, 0);
     180    PS_PTR_CHECK_NULL(transform->x, 0);
     181    PS_PTR_CHECK_NULL(transform->y, 0);
     182
     183    for (psS32 i=0;i<(transform->x->nX);i++) {
     184        for (psS32 j=0;j<(transform->x->nY);j++) {
     185            if (transform->x->coeff[i][j] != 0.0) {
     186                if (!(((i == 0) && (j == 0)) ||
     187                        ((i == 0) && (j == 1)) ||
     188                        ((i == 1) && (j == 0)))) {
     189                    return(0);
     190                }
     191            }
     192        }
     193    }
     194
     195    for (psS32 i=0;i<(transform->y->nX);i++) {
     196        for (psS32 j=0;j<(transform->y->nY);j++) {
     197            if (transform->y->coeff[i][j] != 0.0) {
     198                if (!(((i == 0) && (j == 0)) ||
     199                        ((i == 0) && (j == 1)) ||
     200                        ((i == 1) && (j == 0)))) {
     201                    return(0);
     202                }
     203            }
     204        }
     205    }
     206
     207    return(1);
    68208}
    69209
     
    721861}
    722862
     863
     864
     865/*****************************************************************************
     866psPlaneTransformCombine(out, trans1, trans2)
     867 
     868XXX: Much room for optimization.  Currently, we call the polyMultiply
     869routine far too many times.
     870 *****************************************************************************/
     871psPlaneTransform *psPlaneTransformCombine(psPlaneTransform *out,
     872        const psPlaneTransform *trans1,
     873        const psPlaneTransform *trans2)
     874{
     875    PS_PTR_CHECK_NULL(trans1, NULL);
     876    PS_PTR_CHECK_NULL(trans2, NULL);
     877
     878    //
     879    // Determine the size of the new psPlaneTransform.
     880    //
     881    // PS_MAX(  Number of x terms in T2->x * number of x terms in T1->x,
     882    //          Number of y terms in T2->x * number of x terms in T1->y,
     883    psS32 orderXnX = PS_MAX((trans2->x->nX * trans1->x->nX),
     884                            (trans2->x->nY * trans1->y->nX));
     885    psS32 orderXnY = PS_MAX((trans2->x->nX * trans1->x->nY),
     886                            (trans2->x->nY * trans1->y->nY));
     887
     888    psS32 orderYnX = PS_MAX((trans2->y->nX * trans1->x->nX),
     889                            (trans2->y->nY * trans1->y->nX));
     890    psS32 orderYnY = PS_MAX((trans2->y->nX * trans1->x->nY),
     891                            (trans2->y->nY * trans1->y->nY));
     892    psS32 orderX = PS_MAX(orderXnX, orderYnX);
     893    psS32 orderY = PS_MAX(orderXnY, orderYnY);
     894
     895    //
     896    // Allocate the new psPlaneTransform, if necessary.
     897    //
     898    psPlaneTransform *myPT = NULL;
     899    if (out == NULL) {
     900        myPT = psPlaneTransformAlloc(orderX, orderY);
     901    } else {
     902        if ((out->x->nX == orderX) && (out->x->nY == orderY) &&
     903                (out->y->nX == orderX) && (out->y->nY == orderY)) {
     904            myPT = out;
     905        } else {
     906            psFree(out);
     907            myPT = psPlaneTransformAlloc(orderX, orderY);
     908        }
     909    }
     910
     911    //
     912    // Initialize the new psPlaneTransform, if necessary.
     913    //
     914    for (psS32 i = 0 ; i < orderX ; i++) {
     915        for (psS32 j = 0 ; j < orderY ; j++) {
     916            myPT->x->coeff[i][j] = 0.0;
     917            myPT->x->mask[i][j] = 0;
     918            myPT->y->coeff[i][j] = 0.0;
     919            myPT->y->mask[i][j] = 0;
     920        }
     921    }
     922
     923    //
     924    // For each term (a * x^i * y^j) in trans2, we substitute the appropriate
     925    // equation from trans1, and raise it to the appropriate power.  This is
     926    // done via the multiplyDPoly2D().  The result is a polynomial (currPoly)
     927    // and its coefficients are added into the myPT coeff matrix.
     928    //
     929    // XXX: This is horribly inefficient in that the trans1 polys are repeatedly
     930    // multiplied against themselves.  This can easily be improved.
     931    //
     932    for (psS32 t2x = 0 ; t2x < trans2->x->nX ; t2x++) {
     933        for (psS32 t2y = 0 ; t2y < trans2->x->nY ; t2y++) {
     934            psDPolynomial2D *currPoly = psDPolynomial2DAlloc(1, 1, PS_POLYNOMIAL_ORD);
     935            currPoly->coeff[0][0] = 1.0;
     936            currPoly->mask[0][0] = 0;
     937            psDPolynomial2D *newPoly = NULL;
     938
     939            if (trans2->x->mask[t2x][t2y] == 0) {
     940
     941                // Must raise trans1->y to the t2y-power.
     942                for (psS32 c = 0 ; c < t2y; c++) {
     943                    newPoly = multiplyDPoly2D(currPoly, trans1->y);
     944                    psFree(currPoly);
     945                    currPoly = newPoly;
     946                }
     947
     948                // Must raise trans1->x to the t2x-power.
     949                for (psS32 c = 0 ; c < t2x; c++) {
     950                    newPoly = multiplyDPoly2D(currPoly, trans1->x);
     951                    psFree(currPoly);
     952                    currPoly = newPoly;
     953                }
     954
     955                // Set the appropriate coeffs in myPT->x
     956                for (psS32 i = 0 ; i < currPoly->nX ; i++) {
     957                    for (psS32 j = 0 ; j < currPoly->nY ; j++) {
     958                        myPT->x->coeff[i][j]+= currPoly->coeff[i][j] * trans2->x->coeff[t2x][t2y];
     959                    }
     960                }
     961            }
     962            psFree(currPoly);
     963        }
     964    }
     965
     966
     967
     968    for (psS32 t2x = 0 ; t2x < trans2->y->nX ; t2x++) {
     969        for (psS32 t2y = 0 ; t2y < trans2->y->nY ; t2y++) {
     970            psDPolynomial2D *currPoly = psDPolynomial2DAlloc(1, 1, PS_POLYNOMIAL_ORD);
     971            currPoly->coeff[0][0] = 1.0;
     972            currPoly->mask[0][0] = 0;
     973            psDPolynomial2D *newPoly = NULL;
     974
     975            if (trans2->y->mask[t2x][t2y] == 0) {
     976
     977                // Must raise trans1->y to the t2y-power.
     978                for (psS32 c = 0 ; c < t2y; c++) {
     979                    newPoly = multiplyDPoly2D(currPoly, trans1->y);
     980                    psFree(currPoly);
     981                    currPoly = newPoly;
     982                }
     983
     984                // Must raise trans1->x to the t2x-power.
     985                for (psS32 c = 0 ; c < t2x; c++) {
     986                    newPoly = multiplyDPoly2D(currPoly, trans1->x);
     987                    psFree(currPoly);
     988                    currPoly = newPoly;
     989                }
     990
     991                // Set the appropriate coeffs in myPT->x
     992                for (psS32 i = 0 ; i < currPoly->nX ; i++) {
     993                    for (psS32 j = 0 ; j < currPoly->nY ; j++) {
     994                        myPT->y->coeff[i][j]+= currPoly->coeff[i][j] * trans2->y->coeff[t2x][t2y];
     995                    }
     996                }
     997            }
     998            psFree(currPoly);
     999        }
     1000    }
     1001
     1002    return(myPT);
     1003}
     1004
     1005/*****************************************************************************
     1006psPlaneTransformFit(trans, source, dest, nRejIter, sigmaClip)
     1007 
     1008XXX: What about nRejIter?  Iterations?
     1009XXX: Use static vectors for internal data.
     1010 *****************************************************************************/
     1011bool psPlaneTransformFit(psPlaneTransform *trans,
     1012                         const psArray *source,
     1013                         const psArray *dest,
     1014                         int nRejIter,
     1015                         float sigmaClip)
     1016{
     1017    PS_PTR_CHECK_NULL(trans, NULL);
     1018    PS_PTR_CHECK_NULL(source, NULL);
     1019    PS_PTR_CHECK_NULL(dest, NULL);
     1020
     1021    psS32 numCoords = PS_MIN(source->n, dest->n);
     1022    // This is not really necessary because of above conditionals.
     1023    psS32 order = PS_MAX(trans->x->nX, trans->x->nY);
     1024
     1025    //
     1026    // Create fake polynomial to use in evaluation
     1027    //
     1028    psDPolynomial2D *fakePoly = psDPolynomial2DAlloc(order, order, PS_POLYNOMIAL_ORD);
     1029    for (int i = 0; i < order; i++) {
     1030        for (int j = 0; j < order; j++) {
     1031            fakePoly->coeff[i][j] = 1.0;
     1032            fakePoly->mask[i][j] = 1;       // Mask all coefficients; unmask to evaluate
     1033        }
     1034    }
     1035
     1036    //
     1037    // Initialize the matrix and vectors
     1038    //
     1039    psS32 nCoeff = order * (order + 1) / 2; // Number of polynomial coefficients
     1040    psImage *matrix = psImageAlloc(nCoeff, nCoeff, PS_TYPE_F64); // Matrix for solution
     1041    psVector *xVector = psVectorAlloc(nCoeff, PS_TYPE_F64); // Vector for solution in x
     1042    psVector *yVector = psVectorAlloc(nCoeff, PS_TYPE_F64); // Vector for solution in y
     1043    for (psS32 i = 0; i < nCoeff; i++) {
     1044        for (psS32 j = 0; j < nCoeff; j++) {
     1045            matrix->data.F64[i][j] = 0.0;
     1046        }
     1047        xVector->data.F64[i] = 0.0;
     1048        yVector->data.F64[i] = 0.0;
     1049    }
     1050
     1051    //
     1052    // Iterate over the grid points
     1053    //
     1054    for (psS32 g = 0; g < numCoords; g++) {
     1055        // Iterate over the polynomial coefficients, accumulating the matrix and vectors
     1056
     1057        for (psS32 i = 0, ijIndex = 0; i < order; i++) {
     1058            for (psS32 j = 0; j < order - i; j++, ijIndex++) {
     1059                fakePoly->mask[i][j] = 0;
     1060                psF64 xIn = ((psPlane *) source->data[g])->x;
     1061                psF64 yIn = ((psPlane *) source->data[g])->y;
     1062                psF64 xOut = ((psPlane *) dest->data[g])->x;
     1063                psF64 yOut = ((psPlane *) dest->data[g])->y;
     1064                psF64 ijPoly = psDPolynomial2DEval(fakePoly, xIn, yIn);
     1065                fakePoly->mask[i][j] = 1;
     1066
     1067                for (psS32 m = 0, mnIndex = 0; m < order; m++) {
     1068                    for (psS32 n = 0; n < order - m; n++, mnIndex++) {
     1069                        fakePoly->mask[m][n] = 0;
     1070                        psF64 mnPoly = psDPolynomial2DEval(fakePoly, xIn, yIn);
     1071                        fakePoly->mask[m][n] = 1;
     1072
     1073                        matrix->data.F64[ijIndex][mnIndex] += ijPoly * mnPoly;
     1074                    }
     1075                }
     1076
     1077                xVector->data.F64[ijIndex] += ijPoly * xOut;
     1078                yVector->data.F64[ijIndex] += ijPoly * yOut;
     1079            }
     1080        }
     1081    }
     1082
     1083    //
     1084    // Solution via LU Decomposition
     1085    //
     1086    psVector *permutation = psVectorAlloc(nCoeff, PS_TYPE_F64); // Permutation vector for LU Decomposition
     1087    psImage *luMatrix = psMatrixLUD(NULL, &permutation, matrix); // LU decomposed matrix
     1088    psVector *xSolution = psMatrixLUSolve(NULL, luMatrix, xVector, permutation); // Solution in x
     1089    psVector *ySolution = psMatrixLUSolve(NULL, luMatrix, yVector, permutation); // Solution in y
     1090
     1091    //
     1092    // XXX: Should check the output of the matrix routines and return false if bad.
     1093    //
     1094
     1095    //
     1096    // Stuff coefficients into transformation
     1097    //
     1098    for (psS32 i = 0, ijIndex = 0; i < order; i++) {
     1099        for (psS32 j = 0; j < order - i; j++, ijIndex++) {
     1100            trans->x->coeff[i][j] = xSolution->data.F64[ijIndex];
     1101            trans->y->coeff[i][j] = ySolution->data.F64[ijIndex];
     1102        }
     1103    }
     1104
     1105    psFree(fakePoly);
     1106    psFree(permutation);
     1107    psFree(luMatrix);
     1108    psFree(xSolution);
     1109    psFree(ySolution);
     1110    psFree(matrix);
     1111    psFree(xVector);
     1112    psFree(yVector);
     1113
     1114    return(true);
     1115}
     1116
     1117
     1118/*****************************************************************************
     1119psPlaneTransformInvert(out, in, region, nSamples)
     1120 
     1121// XXX: Use static data structures.
     1122 *****************************************************************************/
     1123psPlaneTransform *psPlaneTransformInvert(psPlaneTransform *out,
     1124        const psPlaneTransform *in,
     1125        psRegion *region,
     1126        int nSamples)
     1127{
     1128    PS_PTR_CHECK_NULL(in, NULL);
     1129    //
     1130    // If the transform is linear, then invert it exactly and return.
     1131    //
     1132    if (p_psIsProjectionLinear((psPlaneTransform *) in)) {
     1133        printf("COOL: is linear\n");
     1134        return(p_psPlaneTransformLinearInvert((psPlaneTransform *) in));
     1135    }
     1136    PS_PTR_CHECK_NULL(region, NULL);
     1137    PS_INT_COMPARE(1, nSamples, NULL);
     1138
     1139    // Ensure that the input transformation is symmetrical.
     1140    if ((in->x->nX != in->x->nY) ||
     1141            (in->y->nX != in->y->nY) ||
     1142            (in->x->nX != in->y->nX)) {
     1143        psError(PS_ERR_BAD_PARAMETER_TYPE, true, "Input transformation must have same nX==nY.");
     1144    }
     1145    psS32 order = PS_MAX(in->x->nX, in->x->nY);
     1146
     1147    psPlaneTransform *myPT = NULL;
     1148    psPlane *inCoord = psPlaneAlloc();
     1149    psPlane *outCoord = psPlaneAlloc();
     1150
     1151    //
     1152    // Allocate a new psPlaneTransform if "out" is NULL, or has the wrong size.
     1153    //
     1154    if (out == NULL) {
     1155        myPT = psPlaneTransformAlloc(order, order);
     1156    } else {
     1157        if ((out->x->nX == order) && (out->x->nY == order) &&
     1158                (out->y->nX == order) && (out->y->nY == order)) {
     1159            myPT = out;
     1160        } else {
     1161            psFree(out);
     1162            myPT = psPlaneTransformAlloc(order, order);
     1163        }
     1164    }
     1165
     1166    //
     1167    // Copy the input transform to myPT.
     1168    //
     1169    for (psS32 i = 0 ; i < in->x->nX ; i++) {
     1170        for (psS32 j = 0 ; j < in->x->nY ; j++) {
     1171            myPT->x->coeff[i][j] = in->x->coeff[i][j];
     1172        }
     1173    }
     1174    for (psS32 i = 0 ; i < in->y->nX ; i++) {
     1175        for (psS32 j = 0 ; j < in->y->nY ; j++) {
     1176            myPT->y->coeff[i][j] = in->y->coeff[i][j];
     1177        }
     1178    }
     1179
     1180    //
     1181    // Create a grid of xin,yin --> xout,yout
     1182    //
     1183    psArray *inData = psArrayAlloc(nSamples * nSamples);
     1184    psArray *outData = psArrayAlloc(nSamples * nSamples);
     1185    for (psS32 i = 0 ; i < inData->n; i++) {
     1186        inData->data[i] = (psPtr *) psPlaneAlloc();
     1187        outData->data[i] = (psPtr *) psPlaneAlloc();
     1188    }
     1189
     1190    //
     1191    // Initialize the grid.
     1192    //
     1193    psS32 cnt = 0;
     1194    for (int yint = 0; yint < nSamples; yint++) {
     1195        inCoord->y = region->y0 + ((psF32) yint) * ((region->y1 - region->y0) / ((psF32) nSamples));
     1196        for (int xint = 0; xint < nSamples; xint++) {
     1197            inCoord->x = region->x0 + ((psF32) xint) * ((region->x1 - region->x0) / ((psF32) nSamples));
     1198            (void)psPlaneTransformApply(outCoord, in, inCoord);
     1199
     1200            ((psPlane *) outData->data[cnt])->x = inCoord->x;
     1201            ((psPlane *) outData->data[cnt])->y = inCoord->y;
     1202            ((psPlane *) inData->data[cnt])->x = outCoord->x;
     1203            ((psPlane *) inData->data[cnt])->y = outCoord->y;
     1204
     1205            cnt++;
     1206        }
     1207    }
     1208    bool rc = psPlaneTransformFit(myPT, inData, outData, 10, 100.0);
     1209
     1210    psFree(inCoord);
     1211    psFree(outCoord);
     1212    psFree(inData);
     1213    psFree(outData);
     1214
     1215    if (rc == true) {
     1216        return(myPT);
     1217    }
     1218
     1219    // XXX: Generate an error message, or warning message.
     1220    return(NULL);
     1221}
Note: See TracChangeset for help on using the changeset viewer.