ocssw  1.0
/disk01/web/ocssw/build/src/landbin/proj_robinv.c (r8096/r2592)
Go to the documentation of this file.
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 }