OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
goodinv.c
Go to the documentation of this file.
1 /*******************************************************************************
2 NAME GOODE'S HOMOLOSINE
3 
4 PURPOSE: Transforms input Easting and Northing to longitude and
5  latitude for the Goode's Homolosine projection. The
6  Easting and Northing must be in meters. The longitude
7  and latitude values will be returned in radians.
8 
9 ALGORITHM REFERENCES
10 
11 1. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
12  U.S. Geological Survey Professional Paper 1453 , United State Government
13  Printing Office, Washington D.C., 1989.
14 
15 2. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
16  Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
17  State Government Printing Office, Washington D.C., 1987.
18 
19 3. Goode, J.P., 1925, The Homolosine projection: a new device for
20  portraying the Earth's surface entire: Assoc. Am. Geographers, Annals,
21  v. 15, p. 119-125
22 *******************************************************************************/
23 #include "oli_cproj.h"
24 #include "oli_local.h"
25 
26 /* Variables common to all subroutines in this code file
27  -----------------------------------------------------*/
28 static double R; /* Radius of the earth (sphere) */
29 static double lon_center[12]; /* Central meridians, one for each region */
30 static double feast[12]; /* False easting, one for each region */
31 
32 /* Initialize the Goode`s Homolosine projection
33  --------------------------------------------*/
34 long goodinvint
35 (
36  double r /* (I) Radius of the earth (sphere) */
37 )
38 {
39 /* Place parameters in static storage for common use
40  -------------------------------------------------*/
41 R = r;
42 
43 /* Initialize central meridians for each of the 12 regions
44  -------------------------------------------------------*/
45 lon_center[0] = -1.74532925199; /* -100.0 degrees */
46 lon_center[1] = -1.74532925199; /* -100.0 degrees */
47 lon_center[2] = 0.523598775598; /* 30.0 degrees */
48 lon_center[3] = 0.523598775598; /* 30.0 degrees */
49 lon_center[4] = -2.79252680319; /* -160.0 degrees */
50 lon_center[5] = -1.0471975512; /* -60.0 degrees */
51 lon_center[6] = -2.79252680319; /* -160.0 degrees */
52 lon_center[7] = -1.0471975512; /* -60.0 degrees */
53 lon_center[8] = 0.349065850399; /* 20.0 degrees */
54 lon_center[9] = 2.44346095279; /* 140.0 degrees */
55 lon_center[10] = 0.349065850399; /* 20.0 degrees */
56 lon_center[11] = 2.44346095279; /* 140.0 degrees */
57 
58 /* Initialize false eastings for each of the 12 regions
59  ----------------------------------------------------*/
60 feast[0] = R * -1.74532925199;
61 feast[1] = R * -1.74532925199;
62 feast[2] = R * 0.523598775598;
63 feast[3] = R * 0.523598775598;
64 feast[4] = R * -2.79252680319;
65 feast[5] = R * -1.0471975512;
66 feast[6] = R * -2.79252680319;
67 feast[7] = R * -1.0471975512;
68 feast[8] = R * 0.349065850399;
69 feast[9] = R * 2.44346095279;
70 feast[10] = R * 0.349065850399;
71 feast[11] = R * 2.44346095279;
72 
73 /* Report parameters to the user
74  -----------------------------*/
75 gctp_print_title("GOODE'S HOMOLOSINE EQUAL-AREA");
77 return(OK);
78 }
79 
80 /* Goode`s Homolosine inverse equations--mapping x,y to lat,long
81  -------------------------------------------------------------*/
82 long goodinv
83 (
84  double x, /* (I) X projection coordinate */
85  double y, /* (I) Y projection coordinate */
86  double *lon, /* (O) Longitude */
87  double *lat /* (O) Latitude */
88 )
89 {
90 double arg;
91 double theta;
92 double temp;
93 long region;
94 
95 /* Inverse equations
96  -----------------*/
97 if (y >= R * 0.710987989993) /* if on or above 40 44' 11.8" */
98  {
99  if (x <= R * -0.698131700798) region = 0; /* If to the left of -40 */
100  else region = 2;
101  }
102 else if (y >= 0.0) /* Between 0.0 and 40 44' 11.8" */
103  {
104  if (x <= R * -0.698131700798) region = 1; /* If to the left of -40 */
105  else region = 3;
106  }
107 else if (y >= R * -0.710987989993) /* Between 0.0 & -40 44' 11.8" */
108  {
109  if (x <= R * -1.74532925199) region = 4; /* If between -180 and -100 */
110  else if (x <= R * -0.349065850399) region = 5; /* If between -100 and -20 */
111  else if (x <= R * 1.3962634016) region = 8; /* If between -20 and 80 */
112  else region = 9; /* If between 80 and 180 */
113  }
114 else /* Below -40 44' 11.8" */
115  {
116  if (x <= R * -1.74532925199) region = 6; /* If between -180 and -100 */
117  else if (x <= R * -0.349065850399) region = 7; /* If between -100 and -20 */
118  else if (x <= R * 1.3962634016) region = 10; /* If between -20 and 80 */
119  else region = 11; /* If between 80 and 180 */
120  }
121 x = x - feast[region];
122 
123 if (region==1||region==3||region==4||region==5||region==8||region==9)
124  {
125  *lat = y / R;
126  if (fabs(*lat) > HALF_PI)
127  {
128  GCTP_PRINT_ERROR("Input data error");
129  return(252);
130  }
131  temp = fabs(*lat) - HALF_PI;
132  if (fabs(temp) > EPSLN)
133  {
134  temp = lon_center[region] + x / (R * cos(*lat));
135  *lon = adjust_lon(temp);
136  }
137  else *lon = lon_center[region];
138  }
139 else
140  {
141  arg = (y + 0.0528035274542 * R * gctp_get_sign(y)) / (1.4142135623731 * R);
142  if (fabs(arg) > 1.0) return(IN_BREAK);
143  theta = asin(arg);
144  *lon = lon_center[region]+(x/(0.900316316158 * R * cos(theta)));
145  if(*lon < -(PI + EPSLN)) return(IN_BREAK);
146  arg = (2.0 * theta + sin(2.0 * theta)) / PI;
147  if (fabs(arg) > 1.0) return(IN_BREAK);
148  *lat = asin(arg);
149  }
150 /* because of precision problems, long values of 180 deg and -180 deg
151  may be mixed.
152  ----------------------------------------------------------------*/
153 if (((x < 0) && (PI - *lon < EPSLN)) || ((x > 0) && (PI + *lon < EPSLN)))
154  *lon = -(*lon);
155 
156 /* Are we in a interrupted area? If so, return status code of IN_BREAK.
157  ---------------------------------------------------------------------*/
158 if (region == 0 && (*lon < -(PI + EPSLN) || *lon > -0.698131700798))
159  return(IN_BREAK);
160 if (region == 1 && (*lon < -(PI + EPSLN) || *lon > -0.698131700798))
161  return(IN_BREAK);
162 if (region == 2 && (*lon < -0.698131700798 || *lon > PI + EPSLN))
163  return(IN_BREAK);
164 if (region == 3 && (*lon < -0.698131700798 || *lon > PI + EPSLN))
165  return(IN_BREAK);
166 if (region == 4 && (*lon < -(PI + EPSLN) || *lon > -1.74532925199))
167  return(IN_BREAK);
168 if (region == 5 && (*lon < -1.74532925199 || *lon > -0.349065850399))
169  return(IN_BREAK);
170 if (region == 6 && (*lon < -(PI + EPSLN) || *lon > -1.74532925199))
171  return(IN_BREAK);
172 if (region == 7 && (*lon < -1.74532925199 || *lon > -0.349065850399))
173  return(IN_BREAK);
174 if (region == 8 && (*lon < -0.349065850399 || *lon > 1.3962634016))
175  return(IN_BREAK);
176 if (region == 9 && (*lon < 1.3962634016|| *lon > PI + EPSLN))
177  return(IN_BREAK);
178 if (region ==10 && (*lon < -0.349065850399 || *lon > 1.3962634016))
179  return(IN_BREAK);
180 if (region ==11 && (*lon < 1.3962634016 || *lon > PI + EPSLN))
181  return(IN_BREAK);
182 return(OK);
183 }
184 
int r
Definition: decode_rs.h:73
void gctp_print_title(const char *proj_name)
Definition: gctp_report.c:14
#define GCTP_PRINT_ERROR(format,...)
Definition: oli_local.h:81
int gctp_get_sign(double x)
Definition: gctp_utility.c:103
float * lat
long goodinv(double x, double y, double *lon, double *lat)
Definition: goodinv.c:83
double adjust_lon(double x)
Definition: proj_cproj.c:349
#define PI
Definition: l3_get_org.c:6
#define HALF_PI
Definition: proj_define.h:84
#define IN_BREAK
Definition: proj_define.h:69
#define OK
Definition: ancil.h:30
#define fabs(a)
Definition: misc.h:93
long goodinvint(double r)
Definition: goodinv.c:35
float * lon
void gctp_print_radius(double radius)
Definition: gctp_report.c:22
#define R
Definition: make_L3_v1.1.c:96
#define EPSLN
Definition: proj_define.h:86