OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
GEO_get_geoid.c
Go to the documentation of this file.
1 /* DEBUG */
2 #include <math.h>
3 
4 #include "GEO_earth.h"
5 #include "GEO_geo.h"
6 #include "PGS_MODIS_35251.h"
7 #include "smfio.h"
8 
10 (
11  double latitude,
12  double longitude
13 )
14 /*
15 !C*****************************************************************************
16 !Description:
17  Routine in the DEM group of the Level-1A geolocation
18  software to retrieve and store the geoid height information.
19 
20 !Input Parameters:
21  latitude latitude of the requested location (radians)
22  longitude longitude of the requested location (radians)
23 
24 !Output Parameters:
25  None
26 
27 Return value:
28  The height of the geoid in meters, or BAD_GEOID if it could not
29  be retrieved, bilinearly interpolated to the specified latitude
30  and longitude.
31 
32 Global variables:
33  None
34 
35 Called by:
36  GEO_terrain_correct()
37 
38 Call functions:
39  modsmf()
40  PGS_DEM_GetSize()
41  PGS_DEM_GetQualityData()
42 
43 !Revision History:
44 # $Log: GEO_get_geoid.c,v $
45 # Revision 6.1 2011/02/15 18:44:31 kuyper
46 # Changed to bilinearly interpolated geoid heights, to avoid artifacts at the
47 # arbitrary boundaries used by older nearest-neighbor algorithm.
48 #
49 # Revision 4.1 2003/10/27 01:14:30 vlin
50 # Message buffer size expanded.
51 #
52 # Revision 2.3 1999/03/12 17:37:49 fhliang
53 # Capitalized Prolog section names.
54 #
55  * Revision 2.2 1999/02/02 18:04:58 kuyper
56  * Make some implicit conversions explicit.
57  *
58  * Revision 2.1 1999/02/02 17:14:59 lma
59  * *** empty log message ***
60  *
61 #
62 # Liqun Ma <lma@ltpmail.gsfc.nasa.gov>
63 
64 !Requirements:
65  PR03-F-3.3.1-1
66 
67 !Team-unique Header:
68  This software is developed by the MODIS Science Data Support
69  Team for the National Aeronautics and Space Administration,
70  Goddard Space Flight Center, under contract NAS5-32373.
71 
72 !END*************************************************************************
73 */
74 
75 {
76  #define ROWS 180
77  #define COLS 360
78 
79  /* Arbitrary limits imposed by poor design of SDP Toolkit, for calls to
80  * PGS_DEM_GetQualityData().
81  */
82  #define MIN_LAT (-90.0*(1.0-1.0/(double)ROWS))
83  #define MAX_LON (180.0*(1.0-1.0/(double)COLS))
84 
85  typedef int16 geoid_height_t[COLS];
86  static geoid_height_t *geoid_height = NULL;
87  if(!geoid_height) {
88  geoid_height = calloc(ROWS, sizeof(geoid_height_t));
89  geoid_height[0][0] = BAD_GEOID;
90  }
91  int lat_lo, lat_hi, lon_lo, lon_hi;
92  double dlat, dlon;
93  char msgbuf[128] = "";
94  static char filefunc[] = __FILE__ ", GEO_get_geoid";
95 
96  latitude *= RAD2DEG;
97  longitude *= RAD2DEG;
98 
99  /* Accept arbitrary longitudes, adjust into range. */
100  /* Algorithm is inefficient if fabs(longitude) is large; it's only intended
101  * to cover possibilities such as use of the range 0<=longitude<360 */
102  while( longitude < -180.0 )
103  longitude += 360.0;
104  while( longitude >= 180.0 )
105  longitude -= 360.0;
106 
107  lon_lo = (int)floor(longitude+179.5);
108  dlon = longitude + 179.5 - lon_lo;
109  lon_hi = lon_lo + 1;
110 
111  /* wrap around at 180E/180W line. */
112  if(lon_lo < 0)
113  lon_lo = COLS-1;
114  else if(lon_hi > COLS-1)
115  lon_hi = 0;
116 
117  lat_lo = (int)floor(89.5-latitude);
118  dlat = 89.5 - latitude - lat_lo;
119  lat_hi = lat_lo + 1;
120 
121  /* Flatten out at poles. */
122  if(lat_lo < 0)
123  dlat = lat_lo = lat_hi = 0;
124  else if(lat_hi > ROWS-1)
125  {
126  lat_lo = lat_hi = ROWS-1;
127  dlon = 0.0;
128  }
129 
130  if( geoid_height[0][0] == BAD_GEOID )
131  { /* First call to this routine. */
132  PGSt_integer numPixVertical;
133  PGSt_integer numPixHorizontal;
134  PGSt_integer sizeDataType;
135  PGSt_double longitude_arry[2] = { -180.0,MAX_LON};
136  PGSt_double latitude_arry[2] = {90.0, MIN_LAT};
137 
138  if( PGS_DEM_GetSize(PGSd_DEM_30ARC, PGSd_DEM_GEOID, PGSd_DEM_DEGREE,
139  latitude_arry, longitude_arry, &numPixVertical, &numPixHorizontal,
140  &sizeDataType ) != PGS_S_SUCCESS )
141  {
142  modsmf(MODIS_E_GEO, "PGS_DEM_GetSize", filefunc);
143 
144  return BAD_GEOID;
145  }
146 
147 
148  if( (numPixVertical != ROWS) || (numPixHorizontal != COLS) ||
149  ((size_t)sizeDataType != sizeof(geoid_height[0][0])) )
150  {
151  sprintf(msgbuf,
152  "\nnumPixVertical= %ld numPixHorizontal= %ld sizeDataType= %ld",
153  (long)numPixVertical,(long)numPixHorizontal,(long)sizeDataType);
154  modsmf(MODIS_E_GEO_BAD_SIZE, msgbuf, filefunc);
155 
156  return BAD_GEOID;
157  }
158 
159 
160  if( PGS_DEM_GetQualityData(PGSd_DEM_30ARC, PGSd_DEM_GEOID,
161  PGSd_DEM_DEGREE, latitude_arry, longitude_arry,
162  (void *)geoid_height) != PGS_S_SUCCESS )
163  {
164  modsmf(MODIS_E_GEO, "PGS_DEM_GetQualityData", filefunc);
165  return BAD_GEOID;
166  }
167  }
168 
169  return (int)floor( (1-dlon)*((1.0-dlat)*geoid_height[lat_lo][lon_lo] +
170  dlat*geoid_height[lat_hi][lon_lo]) +
171  dlon*((1.0-dlat)*geoid_height[lat_lo][lon_hi] +
172  dlat*geoid_height[lat_hi][lon_hi]) + 0.5);
173 }
174 
integer, parameter int16
Definition: cubeio.f90:3
real(single), dimension(:,:), allocatable longitude
#define NULL
Definition: decode_rs.h:63
#define MODIS_E_GEO_BAD_SIZE
real(single), dimension(:,:), allocatable latitude
#define MIN_LAT
#define MODIS_E_GEO
#define ROWS
#define MAX_LON
#define RAD2DEG
Definition: GEO_geo.h:173
#define COLS
int GEO_get_geoid(double latitude, double longitude)
Definition: GEO_get_geoid.c:10
#define BAD_GEOID
Definition: GEO_earth.h:119