|
ocssw
1.0
|
00001 /******************************************************************************* 00002 NAME ROBINSON 00003 00004 PURPOSE: Transforms input Easting and Northing to longitude and 00005 latitude for the Robinson projection. The 00006 Easting and Northing must be in meters. The longitude 00007 and latitude values will be returned in radians. 00008 00009 PROGRAMMER DATE REASON 00010 ---------- ---- ------ 00011 T. Mittan March, 1993 Converted from FORTRAN to C. 00012 S. Nelson Nov, 1993 Changed number of iterations from 20 00013 to 75. This seemed to give a valid 00014 Latitude with less fatal errors. 00015 00016 This function was adapted from the Robinson projection code (FORTRAN) 00017 in the General Cartographic Transformation Package software which is 00018 available from the U.S. Geological Survey National Mapping Division. 00019 00020 ALGORITHM REFERENCES 00021 00022 1. "New Equal-Area Map Projections for Noncircular Regions", John P. Snyder, 00023 The American Cartographer, Vol 15, No. 4, October 1988, pp. 341-355. 00024 00025 2. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological 00026 Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United 00027 State Government Printing Office, Washington D.C., 1987. 00028 00029 3. "Software Documentation for GCTP General Cartographic Transformation 00030 Package", U.S. Geological Survey National Mapping Division, May 1982. 00031 *******************************************************************************/ 00032 #include "proj_cproj.h" 00033 #include <stdint.h> 00034 00035 /* Variables common to all subroutines in this code file 00036 -----------------------------------------------------*/ 00037 static double lon_center; /* Center longitude (projection center) */ 00038 static double R; /* Radius of the earth (sphere) */ 00039 static double false_easting; /* x offset in meters */ 00040 static double false_northing; /* y offset in meters */ 00041 static double pr[21]; 00042 static double xlr[21]; 00043 00044 /* Initialize the ROBINSON projection 00045 ---------------------------------*/ 00046 int robinvint(r, center_long,false_east,false_north) 00047 00048 double r; /* (I) Radius of the earth (sphere) */ 00049 double center_long; /* (I) Center longitude */ 00050 double false_east; /* x offset in meters */ 00051 double false_north; /* y offset in meters */ 00052 { 00053 int32_t i; 00054 00055 /* Place parameters in static storage for common use 00056 -------------------------------------------------*/ 00057 R = r; 00058 lon_center = center_long; 00059 false_easting = false_east; 00060 false_northing = false_north; 00061 00062 pr[1]= -0.062; 00063 xlr[1]=0.9986; 00064 pr[2]=0.0; 00065 xlr[2]=1.0; 00066 pr[3]=0.062; 00067 xlr[3]=0.9986; 00068 pr[4]=0.124; 00069 xlr[4]=0.9954; 00070 pr[5]=0.186; 00071 xlr[5]=0.99; 00072 pr[6]=0.248; 00073 xlr[6]=0.9822; 00074 pr[7]=0.31; 00075 xlr[7]=0.973; 00076 pr[8]=0.372; 00077 xlr[8]=0.96; 00078 pr[9]=0.434; 00079 xlr[9]=0.9427; 00080 pr[10]=0.4958; 00081 xlr[10]=0.9216; 00082 pr[11]=0.5571; 00083 xlr[11]=0.8962; 00084 pr[12]=0.6176; 00085 xlr[12]=0.8679; 00086 pr[13]=0.6769; 00087 xlr[13]=0.835; 00088 pr[14]=0.7346; 00089 xlr[14]=0.7986; 00090 pr[15]=0.7903; 00091 xlr[15]=0.7597; 00092 pr[16]=0.8435; 00093 xlr[16]=0.7186; 00094 pr[17]=0.8936; 00095 xlr[17]=0.6732; 00096 pr[18]=0.9394; 00097 xlr[18]=0.6213; 00098 pr[19]=0.9761; 00099 xlr[19]=0.5722; 00100 pr[20]=1.0; 00101 xlr[20]=0.5322; 00102 00103 for (i = 0; i < 21; i++) 00104 xlr[i] *= 0.9858; 00105 00106 return(OK); 00107 } 00108 00109 /* Robinson inverse equations--mapping x,y to lat/long 00110 ------------------------------------------------------------*/ 00111 int robinv(x, y, lon, lat) 00112 double x; /* (O) X projection coordinate */ 00113 double y; /* (O) Y projection coordinate */ 00114 double *lon; /* (I) Longitude */ 00115 double *lat; /* (I) Latitude */ 00116 00117 { 00118 double adjust_lon(); 00119 double yy; 00120 double p2; 00121 double u,v,t,c; 00122 double phid; 00123 double y1; 00124 int32_t ip1; 00125 int32_t i; 00126 00127 00128 /* Inverse equations 00129 -----------------*/ 00130 x -= false_easting; 00131 y -= false_northing; 00132 00133 yy = 2.0 * y / PI / R; 00134 phid = yy * 90.0; 00135 p2 = fabs(phid / 5.0); 00136 ip1 = (int32_t) (p2 - EPSLN); 00137 if (ip1 == 0) 00138 ip1 = 1; 00139 00140 /* Stirling's interpolation formula as used in forward transformation is 00141 reversed for first estimation of LAT. from rectangular coordinates. LAT. 00142 is then adjusted by iteration until use of forward series provides correct 00143 value of Y within tolerance. 00144 ---------------------------------------------------------------------------*/ 00145 for (i = 0;;) 00146 { 00147 u = pr[ip1 + 3] - pr[ip1 + 1]; 00148 v = pr[ip1 + 3] - 2.0 * pr[ip1 + 2] + pr[ip1 + 1]; 00149 t = 2.0 * (fabs(yy) - pr[ip1 + 2]) / u; 00150 c = v / u; 00151 p2 = t * (1.0 - c * t * (1.0 - 2.0 * c * t)); 00152 00153 if ((p2 >= 0.0) || (ip1 == 1)) 00154 { 00155 if (y >= 0) 00156 phid = (p2 + (double) ip1 ) * 5.0; 00157 else 00158 phid = -(p2 + (double) ip1 ) * 5.0; 00159 00160 do 00161 { 00162 p2 = fabs(phid / 5.0); 00163 ip1 = (int32_t) (p2 - EPSLN); 00164 p2 -= (double) ip1; 00165 00166 if (y >= 0) 00167 y1 = R * (pr[ip1 +2] + p2 *(pr[ip1 + 3] - pr[ip1 +1]) / 2.0 + p2 00168 * p2 * (pr[ip1 + 3] - 2.0 * pr[ip1 + 2] + pr[ip1 + 1])/2.0) 00169 * PI / 2.0; 00170 else 00171 y1 = -R * (pr[ip1 +2] + p2 *(pr[ip1 + 3] - pr[ip1 +1]) / 2.0 + p2 00172 * p2 * (pr[ip1 + 3] - 2.0 * pr[ip1 + 2] + pr[ip1 + 1])/2.0) 00173 * PI / 2.0; 00174 phid += -180.0 * (y1 - y) / PI / R; 00175 i++; 00176 if (i > 75) 00177 { 00178 /* 00179 p_error("Too many iterations in inverse","robinv-conv"); 00180 */ 00181 return(234); 00182 } 00183 } 00184 while (fabs(y1 - y) > .00001); 00185 break; 00186 } 00187 else 00188 { 00189 ip1 -= 1; 00190 if (ip1 < 0) 00191 { 00192 /* 00193 p_error("Too many iterations in inverse","robinv-conv"); 00194 */ 00195 return(234); 00196 } 00197 } 00198 } 00199 *lat = phid * .01745329252; 00200 00201 /* calculate LONG. using final LAT. with transposed forward Stirling's 00202 interpolation formula. 00203 ---------------------------------------------------------------------*/ 00204 *lon = lon_center + x / R / (xlr[ip1 + 2] + p2 * (xlr[ip1 + 3] - xlr[ip1 + 1]) 00205 / 2.0 + p2 * p2 * (xlr[ip1 + 3] - 2.0 * xlr[ip1 + 2] + 00206 xlr[ip1 + 1]) / 2.0); 00207 if ( (*lon < (-PI)) || (*lon > PI) ) 00208 return -1; 00209 /* 00210 *lon = adjust_lon(*lon); 00211 */ 00212 return(OK); 00213 }
1.7.6.1