Changeset 3598 for trunk/psLib/src/astronomy/psCoord.c
- Timestamp:
- Mar 31, 2005, 1:01:46 PM (21 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/astronomy/psCoord.c (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/astronomy/psCoord.c
r3540 r3598 10 10 * @author GLG, MHPCC 11 11 * 12 * @version $Revision: 1.6 0$ $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 $ 14 14 * 15 15 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 26 26 #include "psLogMsg.h" 27 27 #include "psAstronomyErrors.h" 28 #include "psAstrometry.h" 29 #include "psMatrix.h" 28 30 #include <math.h> 29 31 #include <float.h> … … 59 61 /* FUNCTION IMPLEMENTATION - LOCAL */ 60 62 /*****************************************************************************/ 63 /***************************************************************************** 64 multiplyDPoly2D(trans1, trans2): Takes two 2-D polynomials as input and 65 multiplies them. Basically, for each non-zero coeff in the trans1 coeff[][] 66 array, you must multiply by all non-zero coeffs in trans2. 67 68 XXX: Inefficient in that the out polynomial is allocated every time. 69 *****************************************************************************/ 70 71 psDPolynomial2D *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 } 61 98 62 99 /*****************************************************************************/ … … 66 103 { 67 104 // There are non dynamic allocated items 105 } 106 107 /***************************************************************************** 108 p_psPlaneTransformLinearInvert(transform): : this is a private function which 109 simply inverts the supplied psPlaneTransform transform. It assumes that 110 "transform" is linear. 111 112 This program assumes that the inverse of the following linear equations: 113 X2 = A + (B * X1) + (C * Y1); 114 Y2 = D + (E * X1) + (F * Y1); 115 is 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)); 118 or 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 126 XXX: Since thre is now a general psPlaneTransformInvert() function, we 127 should rename this. 128 129 *****************************************************************************/ 130 psPlaneTransform *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 /***************************************************************************** 173 p_psIsProjectionLinear(): this is a private function which simply determines 174 if the supplied psPlaneTransform transform is linear: if any of the 175 cooefficients of order 2 are higher are non-zero, then it is not linear. 176 *****************************************************************************/ 177 psS32 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); 68 208 } 69 209 … … 721 861 } 722 862 863 864 865 /***************************************************************************** 866 psPlaneTransformCombine(out, trans1, trans2) 867 868 XXX: Much room for optimization. Currently, we call the polyMultiply 869 routine far too many times. 870 *****************************************************************************/ 871 psPlaneTransform *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 /***************************************************************************** 1006 psPlaneTransformFit(trans, source, dest, nRejIter, sigmaClip) 1007 1008 XXX: What about nRejIter? Iterations? 1009 XXX: Use static vectors for internal data. 1010 *****************************************************************************/ 1011 bool 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 /***************************************************************************** 1119 psPlaneTransformInvert(out, in, region, nSamples) 1120 1121 // XXX: Use static data structures. 1122 *****************************************************************************/ 1123 psPlaneTransform *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.
