OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
goodfor.c
Go to the documentation of this file.
1 /*******************************************************************************
2 NAME GOODE'S HOMOLOSINE
3 
4 PURPOSE: Transforms input longitude and latitude to Easting and
5  Northing for the Goode's Homolosine projection. The
6  longitude and latitude must be in radians. The Easting
7  and Northing values will be returned in meters.
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 goodforint
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 forward equations--mapping lat,long to x,y
81  -------------------------------------------------------------*/
82 long goodfor
83 (
84  double lon, /* (I) Longitude */
85  double lat, /* (I) Latitude */
86  double *x, /* (O) X projection coordinate */
87  double *y /* (O) Y projection coordinate */
88 )
89 {
90 double delta_lon; /* Delta longitude (Given longitude - center */
91 double theta;
92 double delta_theta;
93 double constant;
94 long i;
95 long region;
96 
97 /* Forward equations
98  -----------------*/
99 if (lat >= 0.710987989993) /* if on or above 40 44' 11.8" */
100  {
101  if (lon <= -0.698131700798) region = 0; /* If to the left of -40 */
102  else region = 2;
103  }
104 else if (lat >= 0.0) /* Between 0.0 and 40 44' 11.8" */
105  {
106  if (lon <= -0.698131700798) region = 1; /* If to the left of -40 */
107  else region = 3;
108  }
109 else if (lat >= -0.710987989993) /* Between 0.0 & -40 44' 11.8" */
110  {
111  if (lon <= -1.74532925199) region = 4; /* If between -180 and -100 */
112  else if (lon <= -0.349065850399) region = 5; /* If between -100 and -20 */
113  else if (lon <= 1.3962634016) region = 8; /* If between -20 and 80 */
114  else region = 9; /* If between 80 and 180 */
115  }
116 else /* Below -40 44' */
117  {
118  if (lon <= -1.74532925199) region = 6; /* If between -180 and -100 */
119  else if (lon <= -0.349065850399) region = 7; /* If between -100 and -20 */
120  else if (lon <= 1.3962634016) region = 10; /* If between -20 and 80 */
121  else region = 11; /* If between 80 and 180 */
122  }
123 
124 if (region==1||region==3||region==4||region==5||region==8||region==9)
125  {
126  delta_lon = adjust_lon(lon - lon_center[region]);
127  *x = feast[region] + R * delta_lon * cos(lat);
128  *y = R * lat;
129  }
130 else
131  {
132  delta_lon = adjust_lon(lon - lon_center[region]);
133  theta = lat;
134  constant = PI * sin(lat);
135 
136 /* Iterate using the Newton-Raphson method to find theta
137  -----------------------------------------------------*/
138  for (i=0;;i++)
139  {
140  delta_theta = -(theta + sin(theta) - constant) / (1.0 + cos(theta));
141  theta += delta_theta;
142  if (fabs(delta_theta) < EPSLN) break;
143  if (i >= 50)
144  {
145  GCTP_PRINT_ERROR("Iteration failed to converge");
146  return(251);
147  }
148  }
149  theta /= 2.0;
150 
151  /* If the latitude is 90 deg, force the x coordinate to be
152  "0 + false easting" this is done here because of precision problems
153  with "cos(theta)"
154  ------------------------------------------------------------------*/
155  if (PI / 2 - fabs(lat) < EPSLN)
156  delta_lon = 0;
157  *x = feast[region] + 0.900316316158 * R * delta_lon * cos(theta);
158  *y = R * (1.4142135623731 * sin(theta) - 0.0528035274542
159  * gctp_get_sign(lat));
160  }
161 
162 return(OK);
163 }
int r
Definition: decode_rs.h:73
void gctp_print_title(const char *proj_name)
Definition: gctp_report.c:14
long goodfor(double lon, double lat, double *x, double *y)
Definition: goodfor.c:83
#define GCTP_PRINT_ERROR(format,...)
Definition: oli_local.h:81
int gctp_get_sign(double x)
Definition: gctp_utility.c:103
float * lat
double adjust_lon(double x)
Definition: proj_cproj.c:349
#define PI
Definition: l3_get_org.c:6
long goodforint(double r)
Definition: goodfor.c:35
#define OK
Definition: ancil.h:30
#define fabs(a)
Definition: misc.h:93
float * lon
void gctp_print_radius(double radius)
Definition: gctp_report.c:22
#define R
Definition: make_L3_v1.1.c:96
int i
Definition: decode_rs.h:71
#define EPSLN
Definition: proj_define.h:86