OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
polar_stereographic.c
Go to the documentation of this file.
1 /*******************************************************************************
2 Name: POLAR STEREOGRAPHIC
3 
4 Purpose: Provides the transformations between Easting/Northing and longitude/
5  latitude for the Polar Stereographic projection. The Easting and Northing
6  values are in meters. The longitude and latitude are in radians.
7 
8 Algorithm References
9 
10 1. Snyder, John P., "Map Projections--A Working Manual", U.S. Geological
11  Survey Professional Paper 1395 (Supersedes USGS Bulletin 1532), United
12  State Government Printing Office, Washington D.C., 1987.
13 
14 2. Snyder, John P. and Voxland, Philip M., "An Album of Map Projections",
15  U.S. Geological Survey Professional Paper 1453 , United State Government
16  Printing Office, Washington D.C., 1989.
17 *******************************************************************************/
18 #include <stdlib.h>
19 #include "oli_cproj.h"
20 #include "gctp.h"
21 #include "oli_local.h"
22 
23 /* structure to hold the setup data relevant to this projection */
24 struct ps_proj
25 {
26  double r_major; /* major axis */
27  double r_minor; /* minor axis */
28  double e; /* eccentricity */
29  double e4; /* e4 calculated from eccentricity */
30  double center_lon; /* center longitude */
31  double center_lat; /* center latitude */
32  double fac; /* sign variable */
33  double ind; /* flag variable */
34  double mcs; /* small value m */
35  double tcs; /* small value t */
36  double false_northing; /* y offset in meters */
37  double false_easting; /* x offset in meters */
38 };
39 
40 /*****************************************************************************
41 Name: print_info
42 
43 Purpose: Prints a summary of information about this projection.
44 
45 Returns:
46  nothing
47 
48 *****************************************************************************/
49 static void print_info
50 (
51  const TRANSFORMATION *trans
52 )
53 {
54  struct ps_proj *cache_ptr = (struct ps_proj *)trans->cache;
55 
56  gctp_print_title("POLAR STEREOGRAPHIC");
57  gctp_print_radius2(cache_ptr->r_major, cache_ptr->r_minor);
58  gctp_print_cenlon(cache_ptr->center_lon);
59  gctp_print_offsetp(cache_ptr->false_easting, cache_ptr->false_northing);
60 }
61 
62 /*******************************************************************************
63 Name: common_init
64 
65 Purpose: Initialization routine for initializing the projection information
66  that is common to both the forward and inverse transformations.
67 
68 Returns:
69  GCTP_SUCCESS or GCTP_ERROR
70 
71 *******************************************************************************/
72 static int common_init
73 (
74  TRANSFORMATION *trans /* I/O: transformation to initialize */
75 )
76 {
77  double r_major; /* major axis */
78  double r_minor; /* minor axis */
79  double radius;
80  double center_lon; /* center longitude */
81  double center_lat; /* center latitude */
82  double false_easting; /* x offset in meters */
83  double false_northing; /* y offset in meters */
84 
85  double temp; /* temporary variable */
86  double con1; /* temporary angle */
87  double sinphi; /* sin value */
88  double cosphi; /* cos value */
89  double es; /* eccentricity squared */
90 
91  const GCTP_PROJECTION *proj = &trans->proj;
92  struct ps_proj *cache = NULL;
93  int spheroid = proj->spheroid;
94 
95  gctp_get_spheroid(spheroid, proj->parameters, &r_major, &r_minor, &radius);
96  false_easting = proj->parameters[6];
97  false_northing = proj->parameters[7];
98 
99  if (gctp_dms2degrees(proj->parameters[4], &center_lon) != GCTP_SUCCESS)
100  {
101  GCTP_PRINT_ERROR("Error converting center longitude in parameter 4 "
102  "from DMS to degrees: %f", proj->parameters[4]);
103  return GCTP_ERROR;
104  }
105  center_lon *= 3600 * S2R;
106 
107  if (gctp_dms2degrees(proj->parameters[5], &center_lat) != GCTP_SUCCESS)
108  {
109  GCTP_PRINT_ERROR("Error converting center latitude in parameter 4 "
110  "from DMS to degrees: %f", proj->parameters[5]);
111  return GCTP_ERROR;
112  }
113  center_lat *= 3600 * S2R;
114 
115  /* Allocate a structure for the cached info */
116  cache = malloc(sizeof(*cache));
117  if (!cache)
118  {
119  GCTP_PRINT_ERROR("Error allocating memory for cache buffer");
120  return GCTP_ERROR;
121  }
122  trans->cache = cache;
123 
124  /* Save the information to the cache */
125  cache->r_major = r_major;
126  cache->r_minor = r_minor;
127  cache->false_northing = false_northing;
128  cache->false_easting = false_easting;
129  temp = r_minor / r_major;
130  es = 1.0 - SQUARE(temp);
131  cache->e = sqrt(es);
132  cache->e4 = gctp_calc_e4(cache->e);
133  cache->center_lon = center_lon;
134  cache->center_lat = center_lat;
135  if (center_lat < 0)
136  cache->fac = -1.0;
137  else
138  cache->fac = 1.0;
139  cache->ind = 0;
140  cache->mcs = 0.0;
141  cache->tcs = 0.0;
142  if (fabs(fabs(center_lat) - HALF_PI) > EPSLN)
143  {
144  cache->ind = 1;
145  con1 = cache->fac * center_lat;
146  sincos(con1, &sinphi, &cosphi);
147  cache->mcs = gctp_calc_small_radius(cache->e, sinphi, cosphi);
148  cache->tcs = gctp_calc_small_t(cache->e, con1, sinphi);
149  }
150 
151  trans->print_info = print_info;
152 
153  return GCTP_SUCCESS;
154 }
155 
156 /*****************************************************************************
157 Name: inverse_transform
158 
159 Purpose: Transforms X,Y to lat,long
160 
161 Returns:
162  GCTP_SUCCESS or GCTP_ERROR
163 
164 *****************************************************************************/
165 static int inverse_transform
166 (
167  const TRANSFORMATION *trans, /* I: transformation information */
168  double x, /* I: X projection coordinate */
169  double y, /* I: Y projection coordinate */
170  double *lon, /* O: Longitude */
171  double *lat /* O: Latitude */
172 )
173 {
174  struct ps_proj *cache_ptr = (struct ps_proj *)trans->cache;
175  double rh; /* height above ellipsiod */
176  double ts; /* small value t */
177  double temp; /* temporary variable */
178  double phi2;
179 
180  x = (x - cache_ptr->false_easting) * cache_ptr->fac;
181  y = (y - cache_ptr->false_northing) * cache_ptr->fac;
182  rh = sqrt(x * x + y * y);
183  if (cache_ptr->ind != 0)
184  ts = rh * cache_ptr->tcs/(cache_ptr->r_major * cache_ptr->mcs);
185  else
186  ts = rh * cache_ptr->e4 / (cache_ptr->r_major * 2.0);
187  if (gctp_calc_phi2(cache_ptr->e, ts, &phi2) != GCTP_SUCCESS)
188  return GCTP_ERROR;
189 
190  *lat = cache_ptr->fac * phi2;
191  if (rh == 0)
192  *lon = cache_ptr->fac * cache_ptr->center_lon;
193  else
194  {
195  temp = atan2(x, -y);
196  *lon = adjust_lon(cache_ptr->fac * temp + cache_ptr->center_lon);
197  }
198 
199  return GCTP_SUCCESS;
200 }
201 
202 /*****************************************************************************
203 Name: forward_transform
204 
205 Purpose: Transforms lat,long to polar stereographic X,Y
206 
207 Returns:
208  GCTP_SUCCESS or GCTP_ERROR
209 
210 *****************************************************************************/
211 static int forward_transform
212 (
213  const TRANSFORMATION *trans, /* I: transformation information */
214  double lon, /* I: Longitude */
215  double lat, /* I: Latitude */
216  double *x, /* O: X projection coordinate */
217  double *y /* O: Y projection coordinate */
218 )
219 {
220  struct ps_proj *cache_ptr = (struct ps_proj *)trans->cache;
221 
222  double con1; /* adjusted longitude */
223  double con2; /* adjusted latitude */
224  double rh; /* height above ellipsoid */
225  double sinphi; /* sin value */
226  double ts; /* value of small t */
227 
228  con1 = cache_ptr->fac * adjust_lon(lon - cache_ptr->center_lon);
229  con2 = cache_ptr->fac * lat;
230  sinphi = sin(con2);
231  ts = gctp_calc_small_t(cache_ptr->e, con2, sinphi);
232  if (cache_ptr->ind != 0)
233  rh = cache_ptr->r_major * cache_ptr->mcs * ts / cache_ptr->tcs;
234  else
235  rh = 2.0 * cache_ptr->r_major * ts / cache_ptr->e4;
236  *x = cache_ptr->fac * rh * sin(con1) + cache_ptr->false_easting;
237  *y = -cache_ptr->fac * rh * cos(con1) + cache_ptr->false_northing;;
238 
239  return GCTP_SUCCESS;
240 }
241 
242 
243 /*****************************************************************************
244 Name: gctp_ps_inverse_init
245 
246 Purpose: Initializes the inverse polar stereographic transformation
247 
248 Returns:
249  GCTP_SUCCESS or GCTP_ERROR
250 
251 *****************************************************************************/
253 (
254  TRANSFORMATION *trans
255 )
256 {
257  /* Call the common routine used for the forward and inverse init */
258  if (common_init(trans) != GCTP_SUCCESS)
259  {
261  "Error initializing polar stereographic inverse projection");
262  return GCTP_ERROR;
263  }
264 
265  trans->transform = inverse_transform;
266 
267  return GCTP_SUCCESS;
268 }
269 
270 /*****************************************************************************
271 Name: gctp_ps_forward_init
272 
273 Purpose: Initializes the forward polar stereographic transformation
274 
275 Returns:
276  GCTP_SUCCESS or GCTP_ERROR
277 
278 *****************************************************************************/
280 (
281  TRANSFORMATION *trans
282 )
283 {
284  /* Call the common routine used for the forward and inverse init */
285  if (common_init(trans) != GCTP_SUCCESS)
286  {
288  "Error initializing polar stereographic forward projection");
289  return GCTP_ERROR;
290  }
291 
292  trans->transform = forward_transform;
293 
294  return GCTP_SUCCESS;
295 }
#define SQUARE(x)
Definition: proj_define.h:99
void gctp_print_title(const char *proj_name)
Definition: gctp_report.c:14
#define GCTP_ERROR
Definition: gctp.h:81
#define NULL
Definition: decode_rs.h:63
double center_lon
void gctp_print_cenlon(double A)
Definition: gctp_report.c:40
#define GCTP_PRINT_ERROR(format,...)
Definition: oli_local.h:81
float * lat
double false_northing
double adjust_lon(double x)
Definition: proj_cproj.c:349
def cache(filename, recache=False)
Definition: utils.py:145
double center_lat
int gctp_calc_phi2(double eccent, double ts, double *phi2)
Definition: gctp_utility.c:209
#define HALF_PI
Definition: proj_define.h:84
double gctp_calc_small_t(double eccent, double phi, double sinphi)
Definition: gctp_utility.c:277
int gctp_ps_forward_init(TRANSFORMATION *trans)
void gctp_print_offsetp(double A, double B)
Definition: gctp_report.c:91
#define GCTP_SUCCESS
Definition: gctp.h:82
int gctp_dms2degrees(double angle, double *degrees)
#define gctp_get_spheroid
Definition: oli_local.h:7
#define sincos
Definition: proj_define.h:108
double false_easting
void gctp_print_radius2(double radius1, double radius2)
Definition: gctp_report.c:30
int gctp_ps_inverse_init(TRANSFORMATION *trans)
double gctp_calc_small_radius(double eccent, double sinphi, double cosphi)
Definition: gctp_utility.c:253
#define fabs(a)
Definition: misc.h:93
#define S2R
Definition: proj_define.h:92
float * lon
void radius(double A)
Definition: proj_report.c:132
double gctp_calc_e4(double x)
Definition: gctp_utility.c:165
#define EPSLN
Definition: proj_define.h:86