IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jan 4, 2005, 3:55:40 PM (22 years ago)
Author:
Paul Price
Message:

Updated to handle higher polynomial orders than linear, and to calculate the output size itself

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/stac/src/stacInvertMaps.c

    r2500 r2897  
    55
    66#define MAX(x,y) ((x) > (y) ? (x) : (y))
    7 
    8 psArray *stacInvertMaps(const psArray *maps // Array of maps to invert
     7#define NUM_GRID 20
     8
     9psArray *stacInvertMaps(const psArray *maps, // Array of maps to invert
     10                        const stacConfig *config // Configuration
    911    )
    1012{
     
    1416    psTrace("stac.invertMaps", 1, "Inverting maps....\n");
    1517
    16     for (int i = 0; i < nMaps; i++) {
    17         // Can't handle higher order than linear yet
    18         if (((psPlaneTransform*)maps->data[i])->x->nX != 2 ||
    19             ((psPlaneTransform*)maps->data[i])->x->nY != 2 ||
    20             ((psPlaneTransform*)maps->data[i])->y->nX != 2 ||
    21             ((psPlaneTransform*)maps->data[i])->y->nY != 2) {
    22             psError("stac.invertMaps",
    23                     "STAC cannot currently support orders other than linear.\n");
    24             psFree(inverted);
    25             return NULL;
    26         }
    27 
    28         psPlaneTransform *newMap = psPlaneTransformAlloc(2, 2); // Inverted map
    29         psPlaneTransform *oldMap = (psPlaneTransform*)maps->data[i]; // Uninverted map
    30 
    31         // Now, simply do a 2x2 matrix inversion
    32 
    33         double a = oldMap->x->coeff[1][0];
    34         double b = oldMap->x->coeff[0][1];
    35         double c = oldMap->y->coeff[1][0];
    36         double d = oldMap->y->coeff[0][1];
    37         double e = oldMap->x->coeff[0][0];
    38         double f = oldMap->y->coeff[0][0];
    39 
    40         double invDet = 1.0 / (a * d - b * c); // Inverse of the determinant
    41 
    42         // Not entirely sure why this works, but it appears to do so.......................................
    43         newMap->x->coeff[1][0] = invDet * a;
    44         newMap->x->coeff[0][1] = - invDet * b;
    45         newMap->y->coeff[1][0] = - invDet * c;
    46         newMap->y->coeff[0][1] = invDet * d;
    47 
    48         newMap->x->coeff[0][0] = - invDet * (d * e + c * f);
    49         newMap->y->coeff[0][0] = - invDet * (b * e + a * f);
     18    // Coordinates for the transformations
     19    psPlane *inCoord = psAlloc(sizeof(psPlane));
     20    psPlane *outCoord = psAlloc(sizeof(psPlane));
     21
     22    for (int mapNum = 0; mapNum < nMaps; mapNum++) {
     23
     24        psPlaneTransform *oldMap = (psPlaneTransform*)maps->data[mapNum]; // Uninverted map
     25        // Check input
     26        if (oldMap->x->nX != oldMap->x->nY) {
     27            psError("stac.invertMaps", "Polynomial order in x and y don't match for map %d\n", mapNum);
     28            return NULL;
     29        }
     30        if (oldMap->y->nX != oldMap->y->nY) {
     31            psError("stac.invertMaps", "Polynomial order in x and y don't match for map %d\n", mapNum);
     32            return NULL;
     33        }
     34        if (oldMap->x->nX != oldMap->y->nX) {
     35            psError("stac.invertMaps", "Polynomial order in x and y don't match for map %d\n", mapNum);
     36            return NULL;
     37        }
     38        int order = oldMap->x->nX;      // Polynomial order
     39        psTrace("stac.invertMaps", 4, "Generating order %d polynomial inverse transformation.\n", order);
     40        psPlaneTransform *newMap = psPlaneTransformAlloc(order, order); // Inverted map
     41
     42        // Create fake polynomial to use in evaluation
     43        psDPolynomial2D *fakePoly = psDPolynomial2DAlloc(order, order, PS_POLYNOMIAL_ORD);
     44        for (int i = 0; i < order; i++) {
     45            for (int j = 0; j < order; j++) {
     46                fakePoly->coeff[i][j] = 1.0; // Set all coeffecients to 1
     47                fakePoly->mask[i][j] = 1; // Mask all coefficients; unmask to evaluate
     48            }
     49        }
     50
     51        // A grid of xin,yin --> xout,yout
     52        psVector *xIn = psVectorAlloc(NUM_GRID * NUM_GRID, PS_TYPE_F32);
     53        psVector *yIn = psVectorAlloc(NUM_GRID * NUM_GRID, PS_TYPE_F32);
     54        psVector *xOut = psVectorAlloc(NUM_GRID * NUM_GRID, PS_TYPE_F32);
     55        psVector *yOut = psVectorAlloc(NUM_GRID * NUM_GRID, PS_TYPE_F32);
     56
     57        // Create grid of points
     58        for (int yint = 0; yint < NUM_GRID; yint++) {
     59            inCoord->y = (float)(yint * config->outny) / (float)(NUM_GRID - 1);
     60            for (int xint = 0; xint < NUM_GRID; xint++) {
     61                inCoord->x = (float)(xint * config->outnx) / (float)(NUM_GRID - 1);
     62
     63                (void)psPlaneTransformApply(outCoord, oldMap, inCoord);
     64
     65                xOut->data.F32[yint*NUM_GRID + xint] = inCoord->x;
     66                yOut->data.F32[yint*NUM_GRID + xint] = inCoord->y;
     67                xIn->data.F32[yint*NUM_GRID + xint] = outCoord->x;
     68                yIn->data.F32[yint*NUM_GRID + xint] = outCoord->y;
     69            }
     70        }
     71
     72        // Initialise the matrix and vectors
     73        int nCoeff = order * (order + 1) / 2; // Number of polynomial coefficients
     74        psImage *matrix = psImageAlloc(nCoeff, nCoeff, PS_TYPE_F64); // Matrix for solution
     75        psVector *xVector = psVectorAlloc(nCoeff, PS_TYPE_F64); // Vector for solution in x
     76        psVector *yVector = psVectorAlloc(nCoeff, PS_TYPE_F64); // Vector for solution in y
     77        for (int i = 0; i < nCoeff; i++) {
     78            for (int j = 0; j < nCoeff; j++) {
     79                matrix->data.F64[i][j] = 0.0;
     80            }
     81            xVector->data.F64[i] = 0.0;
     82            yVector->data.F64[i] = 0.0;
     83        }
     84
     85        // Iterate over the grid points
     86        for (int g = 0; g < NUM_GRID*NUM_GRID; g++) {
     87
     88            // Iterate over the polynomial coefficients, accumulating the matrix and vectors
     89            for (int i = 0, ijIndex = 0; i < order; i++) {
     90                for (int j = 0; j < order - i; j++, ijIndex++) {
     91
     92                    fakePoly->mask[i][j] = 0;
     93                    double ijPoly = psDPolynomial2DEval(xIn->data.F32[g], yIn->data.F32[g], fakePoly);
     94                    fakePoly->mask[i][j] = 1;
     95
     96                    for (int m = 0, mnIndex = 0; m < order; m++) {
     97                        for (int n = 0; n < order - m; n++, mnIndex++) {
     98                           
     99                            fakePoly->mask[m][n] = 0;
     100                            double mnPoly = psDPolynomial2DEval(xIn->data.F32[g], yIn->data.F32[g], fakePoly);
     101                            fakePoly->mask[m][n] = 1;
     102
     103                            matrix->data.F64[ijIndex][mnIndex] += ijPoly * mnPoly;
     104                        }
     105                    }
     106                   
     107                    xVector->data.F64[ijIndex] += ijPoly * (double)xOut->data.F32[g];
     108                    yVector->data.F64[ijIndex] += ijPoly * (double)yOut->data.F32[g];
     109                }
     110            } // Iterating over coefficients
     111        } // Iterating over grid points
     112
     113        // Solution via LU Decomposition
     114        psVector *permutation = psVectorAlloc(nCoeff, PS_TYPE_F64); // Permutation vector for LU Decomposition
     115        psImage *luMatrix = psMatrixLUD(NULL, permutation, matrix); // LU decomposed matrix
     116        psVector *xSolution = psMatrixLUSolve(NULL, luMatrix, xVector, permutation); // Solution in x
     117        psVector *ySolution = psMatrixLUSolve(NULL, luMatrix, yVector, permutation); // Solution in y
     118
     119        // Stuff coefficients into transformation
     120        for (int i = 0, ijIndex = 0; i < order; i++) {
     121            for (int j = 0; j < order - i; j++, ijIndex++) {
     122                newMap->x->coeff[i][j] = xSolution->data.F64[ijIndex];
     123                newMap->y->coeff[i][j] = ySolution->data.F64[ijIndex];
     124            }
     125        }
     126        inverted->data[mapNum] = newMap;
     127
     128#ifdef TESTING
     129        // Print x coefficients
     130        psTrace("stac.invertMaps", 7, "x' = \n");
     131        for (int i = 0; i < order; i++) {
     132            for (int j = 0; j < order - i; j++) {
     133                psTrace("stac.invertMaps", 7, "      %f x^%d y^%d\n", newMap->x->coeff[i][j], i, j);
     134            }
     135        }
     136        // Print y coefficients
     137        psTrace("stac.invertMaps", 7, "y' = \n");
     138        for (int i = 0; i < order; i++) {
     139            for (int j = 0; j < order - i; j++) {
     140                psTrace("stac.invertMaps", 7, "      %f x^%d y^%d\n", newMap->y->coeff[i][j], i, j);
     141            }
     142        }
     143#endif
    50144
    51145#ifdef TESTING
     
    64158#endif
    65159
    66         inverted->data[i] = newMap;     // Stuff into the array
     160        psFree(permutation);
     161        psFree(luMatrix);
     162        psFree(matrix);
     163        psFree(xVector);
     164        psFree(yVector);
     165        psFree(xSolution);
     166        psFree(ySolution);
     167        psFree(fakePoly);
     168        psFree(xIn);
     169        psFree(yIn);
     170        psFree(xOut);
     171        psFree(yOut);
    67172    }
     173
     174    psFree(inCoord);
     175    psFree(outCoord);
     176               
     177
     178#if 0
     179        // Can't handle higher order than linear yet
     180        if (((psPlaneTransform*)maps->data[i])->x->nX != 2 ||
     181            ((psPlaneTransform*)maps->data[i])->x->nY != 2 ||
     182            ((psPlaneTransform*)maps->data[i])->y->nX != 2 ||
     183            ((psPlaneTransform*)maps->data[i])->y->nY != 2) {
     184            psError("stac.invertMaps",
     185                    "STAC cannot currently support orders other than linear.\n");
     186            psFree(inverted);
     187            return NULL;
     188        }
     189
     190        psPlaneTransform *newMap = psPlaneTransformAlloc(2, 2); // Inverted map
     191        psPlaneTransform *oldMap = (psPlaneTransform*)maps->data[i]; // Uninverted map
     192
     193        // Now, simply do a 2x2 matrix inversion
     194
     195        double a = oldMap->x->coeff[1][0];
     196        double b = oldMap->x->coeff[0][1];
     197        double c = oldMap->y->coeff[1][0];
     198        double d = oldMap->y->coeff[0][1];
     199        double e = oldMap->x->coeff[0][0];
     200        double f = oldMap->y->coeff[0][0];
     201
     202        double invDet = 1.0 / (a * d - b * c); // Inverse of the determinant
     203
     204        // Not entirely sure why this works, but it appears to do so.......................................
     205        newMap->x->coeff[1][0] = invDet * a;
     206        newMap->x->coeff[0][1] = - invDet * b;
     207        newMap->y->coeff[1][0] = - invDet * c;
     208        newMap->y->coeff[0][1] = invDet * d;
     209
     210        newMap->x->coeff[0][0] = - invDet * (d * e + c * f);
     211        newMap->y->coeff[0][0] = - invDet * (b * e + a * f);
     212#endif
     213
    68214
    69215    return inverted;
Note: See TracChangeset for help on using the changeset viewer.