void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double R, P, T, wl; double A,B; if(nrhs>4) { mexErrMsgTxt("Incorrect number of inputs."); return; } if(nlhs>2) { mexErrMsgTxt("Wrong number of outputs."); return; } //Get the relative humidity if(nrhs>0&&mxGetM(prhs[0])!=0) { R=getDoubleFromMatlab(prhs[0]); } else {//Otherwise get the value from the Constants class. R=getScalarMatlabClassConst("Constants","standardRelHumid"); } //Get the pressure if(nrhs>1&&mxGetM(prhs[1])!=0) { P=getDoubleFromMatlab(prhs[1]); } else {//Otherwise, get the value from the Constants class. P=getScalarMatlabClassConst("Constants","standardAtmosphericPressure"); } //Get the temperature if(nrhs>2&&mxGetM(prhs[2])!=0) { T=getDoubleFromMatlab(prhs[2]); } else {//Otherwise get the value from the Constants class. T=getScalarMatlabClassConst("Constants","standardTemp"); } //wl is inputted in meters, but needs to be in micrometers for the //function iauAtco13 if(nrhs>3&&mxGetM(prhs[3])!=0) { wl= getDoubleFromMatlab(prhs[3]); } else { wl=0.574e-6; } //Convert from Pascals to millibars. P*=0.01; //Convert from degrees Kelvin to degrees Centigrade. T+=-273.15; //Convert from meters to micrometers. wl*=1e6; //Get the parameters for the simple refraction model. iauRefco(P, T, R, wl,&A, &B); //Allocate space for the return values. plhs[0]=doubleMat2Matlab(&A,1,1); if(nlhs>1) { plhs[1]=doubleMat2Matlab(&B,1,1); } }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double c, *vObsFrame, *vObjInFrame, *vObjRef; mxArray *retMATLAB; size_t i, numVec; if(nrhs!=2) { mexErrMsgTxt("Incorrect number of inputs."); return; } if(nlhs>1) { mexErrMsgTxt("Wrong number of outputs."); return; } numVec=mxGetN(prhs[0]); if(numVec!=mxGetN(prhs[1])||mxGetM(prhs[0])!=3||mxGetM(prhs[1])!=3) { mexErrMsgTxt("The input vectors have the wrong dimensionality."); return; } checkRealDoubleArray(prhs[0]); vObsFrame=(double*)mxGetData(prhs[0]); checkRealDoubleArray(prhs[1]); vObjInFrame=(double*)mxGetData(prhs[1]); c=getScalarMatlabClassConst("Constants","speedOfLight"); //Allocate space for the return values. retMATLAB=mxCreateDoubleMatrix(3,numVec,mxREAL); vObjRef=(double*)mxGetData(retMATLAB); for(i=0; i<numVec; i++) { relVecAddC(c,vObsFrame+3*i,vObjInFrame+3*i,vObjRef+3*i); } plhs[0]=retMATLAB; }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { size_t numRow,numVec; mxArray *retMat; double *xVec, *retData; double TT1, TT2, UT11, UT12; //The if-statements below should properly initialize all of the EOP. //The following initializations to zero are to suppress warnings when //compiling with -Wconditional-uninitialized. double dX=0; double dY=0; double deltaT=0; double LOD=0; double GCRS2TIRS[3][3]; //Polar motion matrix. ITRS=POM*TIRS. We will just be setting it to the //identity matrix as polar motion is not taken into account when going //to the TIRS. double rident[3][3]={{1,0,0},{0,1,0},{0,0,1}}; double Omega[3];//The rotation vector in the TIRS if(nrhs<3||nrhs>6){ mexErrMsgTxt("Wrong number of inputs"); } if(nlhs>2) { mexErrMsgTxt("Wrong number of outputs."); } checkRealDoubleArray(prhs[0]); numRow = mxGetM(prhs[0]); numVec = mxGetN(prhs[0]); if(!(numRow==3||numRow==6)) { mexErrMsgTxt("The input vector has a bad dimensionality."); } xVec=(double*)mxGetData(prhs[0]); TT1=getDoubleFromMatlab(prhs[1]); TT2=getDoubleFromMatlab(prhs[2]); //If some values from the function getEOP will be needed if(nrhs<=5||mxIsEmpty(prhs[3])||mxIsEmpty(prhs[4])||mxIsEmpty(prhs[5])) { mxArray *retVals[5]; double *dXdY; mxArray *JulUTCMATLAB[2]; double JulUTC[2]; int retVal; //Get the time in UTC to look up the parameters by going to TAI and //then UTC. retVal=iauTttai(TT1, TT2, &JulUTC[0], &JulUTC[1]); if(retVal!=0) { mexErrMsgTxt("An error occurred computing TAI."); } retVal=iauTaiutc(JulUTC[0], JulUTC[1], &JulUTC[0], &JulUTC[1]); switch(retVal){ case 1: mexWarnMsgTxt("Dubious Date entered."); break; case -1: mexErrMsgTxt("Unacceptable date entered"); break; default: break; } JulUTCMATLAB[0]=doubleMat2Matlab(&JulUTC[0],1,1); JulUTCMATLAB[1]=doubleMat2Matlab(&JulUTC[1],1,1); //Get the Earth orientation parameters for the given date. mexCallMATLAB(5,retVals,2,JulUTCMATLAB,"getEOP"); mxDestroyArray(JulUTCMATLAB[0]); mxDestroyArray(JulUTCMATLAB[1]); //%We do not need the polar motion coordinates. mxDestroyArray(retVals[0]); checkRealDoubleArray(retVals[1]); if(mxGetM(retVals[1])!=2||mxGetN(retVals[1])!=1) { mxDestroyArray(retVals[1]); mxDestroyArray(retVals[2]); mxDestroyArray(retVals[3]); mxDestroyArray(retVals[4]); mexErrMsgTxt("Error using the getEOP function."); return; } dXdY=(double*)mxGetData(retVals[1]); dX=dXdY[0]; dY=dXdY[1]; //This is TT-UT1 deltaT=getDoubleFromMatlab(retVals[3]); LOD=getDoubleFromMatlab(retVals[4]); //Free the returned arrays. mxDestroyArray(retVals[1]); mxDestroyArray(retVals[2]); mxDestroyArray(retVals[3]); mxDestroyArray(retVals[4]); } //If deltaT=TT-UT1 is given if(nrhs>3&&!mxIsEmpty(prhs[3])) { deltaT=getDoubleFromMatlab(prhs[3]); } //Obtain UT1 from terestrial time and deltaT. iauTtut1(TT1, TT2, deltaT, &UT11, &UT12); //Get celestial pole offsets, if given. if(nrhs>4&&!mxIsEmpty(prhs[4])) { size_t dim1, dim2; checkRealDoubleArray(prhs[4]); dim1 = mxGetM(prhs[4]); dim2 = mxGetN(prhs[4]); if((dim1==2&&dim2==1)||(dim1==1&&dim2==2)) { double *dXdY=(double*)mxGetData(prhs[4]); dX=dXdY[0]; dY=dXdY[1]; } else { mexErrMsgTxt("The celestial pole offsets have the wrong dimensionality."); return; } } //If LOD is given if(nrhs>5&&mxIsEmpty(prhs[5])) { LOD=getDoubleFromMatlab(prhs[5]); } //Compute the rotation matrix for going from GCRS to ITRS as well as //the instantaneous vector angular momentum due to the Earth's rotation //in TIRS coordinates. { double x, y, s, era; double rc2i[3][3]; double omega; //Get the X,Y coordinates of the Celestial Intermediate Pole (CIP) and //the Celestial Intermediate Origin (CIO) locator s, using the IAU 2006 //precession and IAU 2000A nutation models. iauXys06a(TT1, TT2, &x, &y, &s); //Add the CIP offsets. x += dX; y += dY; //Get the GCRS-to-CIRS matrix iauC2ixys(x, y, s, rc2i); //Find the Earth rotation angle for the given UT1 time. era = iauEra00(UT11, UT12); //Set the polar motion matrix to the identity matrix so that the //conversion stops at the TIRS instead of the ITRS. //Combine the GCRS-to-CIRS matrix, the Earth rotation angle, and use //the identity matrix instead of the polar motion matrix to get a //to get the rotation matrix to go from GCRS to TIRS. iauC2tcio(rc2i, era, rident,GCRS2TIRS); //Next, to be able to transform the velocity, the rotation of the Earth //has to be taken into account. //The angular velocity vector of the Earth in the TIRS in radians. omega=getScalarMatlabClassConst("Constants","IERSMeanEarthRotationRate"); //Adjust for LOD omega=omega*(1-LOD/86400.0);//86400.0 is the number of seconds in a TT //day. Omega[0]=0; Omega[1]=0; Omega[2]=omega; } //Allocate space for the return vectors. retMat=mxCreateDoubleMatrix(numRow,numVec,mxREAL); retData=(double*)mxGetData(retMat); { size_t curVec; for(curVec=0;curVec<numVec;curVec++) { //Multiply the position vector with the rotation matrix. iauRxp(GCRS2TIRS, xVec+numRow*curVec, retData+numRow*curVec); //If a velocity vector was given. if(numRow>3) { double *posGCRS=xVec+numRow*curVec; double posTIRS[3]; double *velGCRS=xVec+numRow*curVec+3;//Velocity in GCRS double velTIRS[3]; double *retDataVel=retData+numRow*curVec+3; double rotVel[3]; //If a velocity was provided with the position, first //convert to TIRS coordinates, then account for the //rotation of the Earth. //Convert velocity from GCRS to TIRS. iauRxp(GCRS2TIRS, velGCRS, velTIRS); //Convert position from GCRS to TIRS iauRxp(GCRS2TIRS, posGCRS, posTIRS); //Evaluate the cross product for the angular velocity due //to the Earth's rotation. iauPxp(Omega, posTIRS, rotVel); //Subtract out the instantaneous velocity due to rotation. iauPmp(velTIRS, rotVel, retDataVel); } } } plhs[0]=retMat; //If the rotation matrix is desired on the output. if(nlhs>1) { double *elPtr; size_t i,j; plhs[1]=mxCreateDoubleMatrix(3,3,mxREAL); elPtr=(double*)mxGetData(plhs[1]); for (i=0;i<3;i++) { for(j=0;j<3;j++) { elPtr[i+3*j]=GCRS2TIRS[i][j]; } } } }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double TT1,TT2,*xVec; double deltaT=0; double LOD=0; size_t numRow,numVec; double CIRS2TIRS[3][3]; double TIRS2CIRS[3][3]; double Omega[3];//The rotation vector in the TIRS mxArray *retMat; double *retData; if(nrhs<3||nrhs>5){ mexErrMsgTxt("Wrong number of inputs"); } if(nlhs>2) { mexErrMsgTxt("Wrong number of outputs."); } checkRealDoubleArray(prhs[0]); numRow = mxGetM(prhs[0]); numVec = mxGetN(prhs[0]); if(!(numRow==3||numRow==6)) { mexErrMsgTxt("The input vector has a bad dimensionality."); } xVec=(double*)mxGetData(prhs[0]); TT1=getDoubleFromMatlab(prhs[1]); TT2=getDoubleFromMatlab(prhs[2]); //If some values from the function getEOP will be needed if(nrhs<=4||mxIsEmpty(prhs[3])||mxIsEmpty(prhs[4])) { mxArray *retVals[5]; mxArray *JulUTCMATLAB[2]; double JulUTC[2]; int retVal; //Get the time in UTC to look up the parameters by going to TAI and //then UTC. retVal=iauTttai(TT1, TT2, &JulUTC[0], &JulUTC[1]); if(retVal!=0) { mexErrMsgTxt("An error occurred computing TAI."); } retVal=iauTaiutc(JulUTC[0], JulUTC[1], &JulUTC[0], &JulUTC[1]); switch(retVal){ case 1: mexWarnMsgTxt("Dubious Date entered."); break; case -1: mexErrMsgTxt("Unacceptable date entered"); break; default: break; } JulUTCMATLAB[0]=doubleMat2Matlab(&JulUTC[0],1,1); JulUTCMATLAB[1]=doubleMat2Matlab(&JulUTC[1],1,1); //Get the Earth orientation parameters for the given date. mexCallMATLAB(5,retVals,2,JulUTCMATLAB,"getEOP"); mxDestroyArray(JulUTCMATLAB[0]); mxDestroyArray(JulUTCMATLAB[1]); //We do not need the polar motion coordinates. mxDestroyArray(retVals[0]); //We do not need the celestial pole offsets. mxDestroyArray(retVals[1]); //This is TT-UT1 deltaT=getDoubleFromMatlab(retVals[3]); LOD=getDoubleFromMatlab(retVals[4]); //Free the returned arrays. mxDestroyArray(retVals[2]); mxDestroyArray(retVals[3]); mxDestroyArray(retVals[4]); } //If deltaT=TT-UT1 is given if(nrhs>3&&!mxIsEmpty(prhs[3])) { deltaT=getDoubleFromMatlab(prhs[3]); } //If LOD is given if(nrhs>4&&!mxIsEmpty(prhs[4])) { LOD=getDoubleFromMatlab(prhs[4]); } //Compute the rotation matrix for going from CIRS to TIRS as well as //the instantaneous vector angular momentum due to the Earth's rotation //in GCRS coordinates. { double UT11, UT12; double era, omega; //Obtain UT1 from terestrial time and deltaT. iauTtut1(TT1, TT2, deltaT, &UT11, &UT12); //Find the Earth rotation angle for the given UT1 time. era = iauEra00(UT11, UT12); //Construct the rotation matrix. CIRS2TIRS[0][0]=1; CIRS2TIRS[0][1]=0; CIRS2TIRS[0][2]=0; CIRS2TIRS[1][0]=0; CIRS2TIRS[1][1]=1; CIRS2TIRS[1][2]=0; CIRS2TIRS[2][0]=0; CIRS2TIRS[2][1]=0; CIRS2TIRS[2][2]=1; iauRz(era, CIRS2TIRS); //To go from the TIRS to the GCRS, we need to use the inverse rotation //matrix, which is just the transpose of the rotation matrix. iauTr(CIRS2TIRS, TIRS2CIRS); //Next, to be able to transform the velocity, the rotation of the Earth //has to be taken into account. //The angular velocity vector of the Earth in the TIRS in radians. omega=getScalarMatlabClassConst("Constants","IERSMeanEarthRotationRate"); //Adjust for LOD omega=omega*(1-LOD/86400.0);//86400.0 is the number of seconds in a TT //day. Omega[0]=0; Omega[1]=0; Omega[2]=omega; } //Allocate space for the return vectors. retMat=mxCreateDoubleMatrix(numRow,numVec,mxREAL); retData=(double*)mxGetData(retMat); { size_t curVec; for(curVec=0;curVec<numVec;curVec++) { //Multiply the position vector with the rotation matrix. iauRxp(TIRS2CIRS, xVec+numRow*curVec, retData+numRow*curVec); //If a velocity vector was given. if(numRow>3) { double *posTIRS=xVec+numRow*curVec; double *velTIRS=xVec+numRow*curVec+3;//Velocity in GCRS double *retDataVel=retData+numRow*curVec+3; double rotVel[3]; //Evaluate the cross product for the angular velocity due //to the Earth's rotation. iauPxp(Omega, posTIRS, rotVel); //Add the instantaneous velocity due to rotation. iauPpp(velTIRS, rotVel, retDataVel); //Rotate from TIRS to GCRS iauRxp(TIRS2CIRS, retDataVel, retDataVel); } } } plhs[0]=retMat; if(nlhs>1) { double *elPtr; size_t i,j; plhs[1]=mxCreateDoubleMatrix(3,3,mxREAL); elPtr=(double*)mxGetData(plhs[1]); for (i=0;i<3;i++) { for(j=0;j<3;j++) { elPtr[i+3*j]=TIRS2CIRS[i][j]; } } } }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { size_t numRow,numVec; mxArray *retMat; double *xVec, *retData; double TT1, TT2, UT11, UT12; //The if-statements below should properly initialize all of the EOP. //The following initializations to zero are to suppress warnings when //compiling with -Wconditional-uninitialized. double xp=0; double yp=0; double deltaT=0; double LOD=0; double ITRS2TEME[3][3]; double PEF2TEME[3][3]; double WInv[3][3];//The inverse polar motion matrix to go from ITRS to PEF. double Omega[3];//The angular velocity vector for the Earth's rotation. if(nrhs<3||nrhs>6){ mexErrMsgTxt("Wrong number of inputs"); } if(nlhs>2) { mexErrMsgTxt("Wrong number of outputs."); return; } checkRealDoubleArray(prhs[0]); numRow = mxGetM(prhs[0]); numVec = mxGetN(prhs[0]); if(!(numRow==3||numRow==6)) { mexErrMsgTxt("The input vector has a bad dimensionality."); } xVec=(double*)mxGetData(prhs[0]); TT1=getDoubleFromMatlab(prhs[1]); TT2=getDoubleFromMatlab(prhs[2]); //If some values from the function getEOP will be needed if(nrhs<6||mxIsEmpty(prhs[3])||mxIsEmpty(prhs[4])||mxIsEmpty(prhs[5])) { mxArray *retVals[5]; double *xpyp; mxArray *JulUTCMATLAB[2]; double JulUTC[2]; int retVal; //Get the time in UTC to look up the parameters by going to TAI and //then UTC. retVal=iauTttai(TT1, TT2, &JulUTC[0], &JulUTC[1]); if(retVal!=0) { mexErrMsgTxt("An error occurred computing TAI."); } retVal=iauTaiutc(JulUTC[0], JulUTC[1], &JulUTC[0], &JulUTC[1]); switch(retVal){ case 1: mexWarnMsgTxt("Dubious Date entered."); break; case -1: mexErrMsgTxt("Unacceptable date entered"); break; default: break; } JulUTCMATLAB[0]=doubleMat2Matlab(&JulUTC[0],1,1); JulUTCMATLAB[1]=doubleMat2Matlab(&JulUTC[1],1,1); //Get the Earth orientation parameters for the given date. mexCallMATLAB(5,retVals,2,JulUTCMATLAB,"getEOP"); mxDestroyArray(JulUTCMATLAB[0]); mxDestroyArray(JulUTCMATLAB[1]); checkRealDoubleArray(retVals[0]); checkRealDoubleArray(retVals[1]); if(mxGetM(retVals[0])!=2||mxGetN(retVals[0])!=1||mxGetM(retVals[1])!=2||mxGetN(retVals[1])!=1) { mxDestroyArray(retVals[0]); mxDestroyArray(retVals[1]); mxDestroyArray(retVals[2]); mxDestroyArray(retVals[3]); mxDestroyArray(retVals[4]); mexErrMsgTxt("Error using the getEOP function."); return; } xpyp=(double*)mxGetData(retVals[0]); xp=xpyp[0]; yp=xpyp[1]; //The celestial pole offsets are not used. //This is TT-UT1 deltaT=getDoubleFromMatlab(retVals[3]); LOD=getDoubleFromMatlab(retVals[4]); //Free the returned arrays. mxDestroyArray(retVals[0]); mxDestroyArray(retVals[1]); mxDestroyArray(retVals[2]); mxDestroyArray(retVals[3]); mxDestroyArray(retVals[4]); } //If deltaT=TT-UT1 is given if(nrhs>3&&!mxIsEmpty(prhs[3])) { deltaT=getDoubleFromMatlab(prhs[3]); } //Obtain UT1 from terestrial time and deltaT. iauTtut1(TT1, TT2, deltaT, &UT11, &UT12); //Get polar motion values, if given. if(nrhs>4&&!mxIsEmpty(prhs[4])) { size_t dim1, dim2; checkRealDoubleArray(prhs[4]); dim1 = mxGetM(prhs[4]); dim2 = mxGetN(prhs[4]); if((dim1==2&&dim2==1)||(dim1==1&&dim2==2)) { double *xpyp=(double*)mxGetData(prhs[4]); xp=xpyp[0]; yp=xpyp[1]; } else { mexErrMsgTxt("The celestial pole offsets have the wrong dimensionality."); return; } } //If LOD is given if(nrhs>5&&!mxIsEmpty(prhs[5])) { LOD=getDoubleFromMatlab(prhs[5]); } { double GMST1982=iauGmst82(UT11, UT12); double TEME2PEF[3][3]; double TEME2ITRS[3][3]; double W[3][3]; double omega; //Get Greenwhich mean sidereal time under the IAU's 1982 model. This //is given in radians and will be used to build a rotation matrix to //rotate into the PEF system. GMST1982=iauGmst82(UT11, UT12); { double cosGMST,sinGMST; cosGMST=cos(GMST1982); sinGMST=sin(GMST1982); //Build the rotation matrix to rotate by GMST about the z-axis. This //will put the position vector in the PEF system. TEME2PEF[0][0]=cosGMST; TEME2PEF[0][1]=sinGMST; TEME2PEF[0][2]=0; TEME2PEF[1][0]=-sinGMST; TEME2PEF[1][1]=cosGMST; TEME2PEF[1][2]=0; TEME2PEF[2][0]=0; TEME2PEF[2][1]=0; TEME2PEF[2][2]=1.0; } //The inverse rotation is just the transpose iauTr(TEME2PEF, PEF2TEME); //To go from PEF to ITRS, we need to build the polar motion matrix //using the IAU's 1980 conventions. { double cosXp,sinXp,cosYp,sinYp; cosXp=cos(xp); sinXp=sin(xp); cosYp=cos(yp); sinYp=sin(yp); W[0][0]=cosXp; W[0][1]=sinXp*sinYp; W[0][2]=sinXp*cosYp; W[1][0]=0; W[1][1]=cosYp; W[1][2]=-sinYp; W[2][0]=-sinXp; W[2][1]=cosXp*sinXp; W[2][2]=cosXp*cosYp; } //The inverse rotation is just the transpose iauTr(W, WInv); //The total rotation matrix is thus the product of the two rotations. //TEME2ITRS=W*TEME2PEF; iauRxr(W, TEME2PEF, TEME2ITRS); //We want the inverse rotation iauTr(TEME2ITRS, ITRS2TEME); //The angular velocity vector of the Earth in the TIRS in radians. omega=getScalarMatlabClassConst("Constants","IERSMeanEarthRotationRate"); //Adjust for LOD omega=omega*(1-LOD/86400.0);//86400.0 is the number of seconds in a TT day. Omega[0]=0; Omega[1]=0; Omega[2]=omega; } //Allocate space for the return vectors. retMat=mxCreateDoubleMatrix(numRow,numVec,mxREAL); retData=(double*)mxGetData(retMat); { size_t curVec; for(curVec=0;curVec<numVec;curVec++) { //Multiply the position vector with the rotation matrix. iauRxp(ITRS2TEME, xVec+numRow*curVec, retData+numRow*curVec); //If a velocity vector was given. if(numRow>3) { double *posITRS=xVec+numRow*curVec; double *velITRS=xVec+numRow*curVec+3;//Velocity in TEME double posPEF[3]; double velPEF[3]; double *retDataVel=retData+numRow*curVec+3; double rotVel[3]; //If a velocity was provided with the position, first //convert to PEF coordinates, then account for the rotation //of the Earth, then rotate into TEME coordinates. //Convert velocity from ITRS to PEF. iauRxp(WInv, velITRS, velPEF); //Convert position from ITRS to PEF iauRxp(WInv, posITRS, posPEF); //Evaluate the cross product for the angular velocity due //to the Earth's rotation. iauPxp(Omega, posPEF, rotVel); //Add the instantaneous velocity due to rotation. iauPpp(velPEF, rotVel, retDataVel); //Rotate from the PEF into the TEME iauRxp(PEF2TEME, retDataVel, retDataVel); } } } plhs[0]=retMat; if(nlhs>1) { double *elPtr; size_t i,j; plhs[1]=mxCreateDoubleMatrix(3,3,mxREAL); elPtr=(double*)mxGetData(plhs[1]); for (i=0;i<3;i++) { for(j=0;j<3;j++) { elPtr[i+3*j]=ITRS2TEME[i][j]; } } } }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double *points,a,b,b2,f,e2,eps2,ec; size_t numVec,i; mxArray *retMat; double *retData; if(nrhs>3||nrhs<1){ mexErrMsgTxt("Wrong number of inputs"); } if(nlhs>1) { mexErrMsgTxt("Wrong number of outputs."); return; } checkRealDoubleArray(prhs[0]); numVec = mxGetN(prhs[0]); if(mxGetM(prhs[0])!=3) { mexErrMsgTxt("The input vector has a bad dimensionality."); } points=(double*)mxGetData(prhs[0]); //points[0] is x //points[1] is y //points[2] is z if(nrhs>1) { a=getDoubleFromMatlab(prhs[1]); } else { a=getScalarMatlabClassConst("Constants", "WGS84SemiMajorAxis"); } if(nrhs>2) { f=getDoubleFromMatlab(prhs[2]); } else { f=getScalarMatlabClassConst("Constants", "WGS84Flattening"); } b=a*(1-f);//The semi-minor axis of the reference ellipsoid. b2=b*b; //The square of the first numerical eccentricity. e2=2*f-f*f; //The square of the second numerical eccentricity. eps2=a*a/(b2)-1; //This value is used if Fukushima's method is chosen. ec=sqrt(1-e2); //Allocate space for the return variables. retMat=mxCreateDoubleMatrix(3,numVec,mxREAL); retData=(double*)mxGetData(retMat); for(i=0;i<numVec;i++) { double *phi, *lambda, *h; double x0,y0,z0; double r0,p,s,q; //Get the Cartesian point to convert. x0=points[3*i]; y0=points[3*i+1]; z0=points[3*i+2]; //Get the addresses of where the converted components will go phi=retData+3*i; lambda=retData+3*i+1; h=retData+3*i+2; r0=sqrt(x0*x0+y0*y0); p=fabs(z0)/eps2; s=r0*r0/(e2*eps2); q=p*p-b2+s; *lambda=atan2(y0,x0); if(q>=0) {//Use Sofair's algorithm double u,v,P,Q,t,c,w,z,Ne,val; u=p/sqrt(q); v=b2*u*u/q; P=27.0*v*s/q; Q=pow(sqrt(P+1.0)+sqrt(P),2.0/3.0); t=(1.0+Q+1/Q)/6.0; c=u*u-1+2*t; //This condition prevents finite precision problems due to //subtraction within the square root. c=fMax(c,0); c=sqrt(c); w=(c-u)/2.0; //The z coordinate of the closest point projected on the ellipsoid. //The fmax command deals with precision problems when the argument //is nearly zero. The problems arise due to the subtraction within //the square root. z=sqrt(t*t+v)-u*w-t/2.0-1.0/4.0; z=fMax(z,0); z=copySign(sqrt(q)*(w+sqrt(z)),z0); Ne=a*sqrt(1+eps2*z*z/b2); //The min and max terms deals with finite precision problems. val=fMin(z*(eps2+1)/Ne,1); val=fMax(val,-1.0); *phi=asin(val); *h=r0*cos(*phi)+z0*sin(*phi)-a*a/Ne; } else {//Use Fukushima's algorithm. double Cc,P,Z,S,C; //A gets a value within the loop. This initialization is just //to silence a warning when compiling with //-Wconditional-uninitialized double A=0; size_t curIter; const size_t maxIter=6; P=r0/a; Z=(ec/a)*fabs(z0); S=Z; C=ec*P; //Loop until convergence. Assume convergence in 6 iterations. for(curIter=0;curIter<maxIter;curIter++) { double B,F,D,SNew,CNew; A=sqrt(S*S+C*C); B=1.5*e2*S*C*C*((P*S-Z*C)*A-e2*S*C); F=P*A*A*A-e2*C*C*C; D=Z*A*A*A+e2*S*S*S; SNew=D*F-B*S; CNew=F*F-B*C; SNew=SNew/CNew; if(!isFinite(SNew)) { S=SNew; C=1; A=sqrt(S*S+C*C); break; } else { S=SNew; C=1; } } Cc=ec*C; //If the point is along the z-axis, then SNew and CNew will //both be zero, leading to a non-finite result. if(!isFinite(S)) { *phi=copySign(pi/2,z0); *h=fabs(z0)-b; } else { *phi=copySign(atan(S/Cc),z0); *h=(r0*Cc+fabs(z0)*S-b*A)/sqrt(Cc*Cc+S*S); } } } plhs[0]=retMat; }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { double *vOrig; double *obsVel; mxArray *retMATLAB; double c, *retVec; size_t numVec; if(nrhs<2||nrhs>3) { mexErrMsgTxt("Incorrect number of inputs."); return; } if(nlhs>1) { mexErrMsgTxt("Wrong number of outputs."); return; } numVec=mxGetN(prhs[0]); if(numVec!=mxGetN(prhs[1])||mxGetM(prhs[0])!=3||mxGetM(prhs[1])!=3) { mexErrMsgTxt("The input vectors have the wrong dimensionality."); return; } checkRealDoubleArray(prhs[0]); vOrig=(double*)mxGetData(prhs[0]); checkRealDoubleArray(prhs[1]); obsVel=(double*)mxGetData(prhs[1]); c=getScalarMatlabClassConst("Constants","speedOfLight"); //Allocate space for the return values. retMATLAB=mxCreateDoubleMatrix(3,numVec,mxREAL); retVec=(double*)mxGetData(retMATLAB); //If the third parameter is provided, then use the algorithm from the IAU. if(nrhs>2) { double AU, *sunDist; size_t curVec; //Needed to convert units. AU=getScalarMatlabClassConst("Constants","AstronomialUnit"); //If the dimensionality is wrong. if(!((mxGetM(prhs[2])==1&&mxGetN(prhs[2])==numVec)||(mxGetM(prhs[2])==numVec&&mxGetN(prhs[2])==1))) { mxDestroyArray(retMATLAB); mexErrMsgTxt("The input vectors have the wrong dimensionality."); return; } checkRealDoubleArray(prhs[0]); sunDist=(double*)mxGetData(prhs[2]); for(curVec=0;curVec<numVec;curVec++) { double vecMag,unitVec[3]; double v[3]; double s; double bm1; //Get a unit direction vector and magnitude. iauPn(vOrig+3*curVec, &vecMag, unitVec); //Convert the velocity to units of the speed of light. v[0]=obsVel[3*curVec]/c; v[1]=obsVel[3*curVec+1]/c; v[2]=obsVel[3*curVec+2]/c; //The distance to the sun in AU. s=sunDist[curVec]/AU; //The reciprocal of the Lorentz factor. bm1=sqrt(1-(v[0]*v[0]+v[1]*v[1]+v[2]*v[2])); //Perform the correction with the IAU's function. iauAb(unitVec, v, s, bm1,retVec+3*curVec); //Set the magnitude back to what it was. retVec[3*curVec]*=vecMag; retVec[3*curVec+1]*=vecMag; retVec[3*curVec+2]*=vecMag; } } else { //If the distance to the sun is not given, then just perform a normal //special relativistic correction. size_t curVec; for(curVec=0;curVec<numVec;curVec++) { double vecMag,lightVec[3]; //Get a unit direction vector and magnitude. iauPn(vOrig+3*curVec, &vecMag, lightVec); //The light is in direction lightVec with speed c lightVec[0]*=c; lightVec[1]*=c; lightVec[2]*=c; //The light travels at speed c with true direction uPosition. //Add the velocity vector of the observer to that of light. relVecAddC(c,obsVel+3*curVec,lightVec,retVec+3*curVec); //Because one vector had a magnitude of c, the returned vector //must have the same magnitude. Restore the previous magnitude. retVec[3*curVec]*=vecMag/c; retVec[3*curVec+1]*=vecMag/c; retVec[3*curVec+2]*=vecMag/c; } } //Set the return value. plhs[0]=retMATLAB; }