NASA Logo
Ocean Color Science Software

ocssw V2022
get_dem_height.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <math.h>
3 #include <hdfi.h>
4 #include <mfhdf.h>
5 #include <genutils.h>
6 #include "terrain.h"
7 
8 #define RADEG 57.29577951
9 
10 /*
11  Exactly replicate the functionality of get_dem_height.f
12  Originally written by: Frederick S. Patt, SAIC GSC, June 1, 2000
13  Translated by: Gwyn F. Fireman, SAIC, July 2013 (with help from f2c)
14  */
15 
16 /* DEM structure (from dem_s.fin) */
17 struct {
18  int32 nrows; // Number of rows in grid
19  int32 neq; // Number of tiles in equatorial row
20  int32 ntiles; // Number of tiles in grid
21  int32 nftiles; // Number of filled tiles
22  int32 isize; // Tile array size
23  int32 itsize; // Array size of nominal area
24  int32 ioff; // Offset of nominal tile in array
25  int16 ncols[121]; // Number of tiles in each row
26  int16 nstart[121]; // Start tile # for each row (0-base)
27  int16 irecno[18338]; // Record no. for tile (0-base; -1 if not filled)
28  int16 iflag[18338]; // Tile flag (0=sea, 1=flag, 2=filled)
29  int16 ihmin[18338]; // Minimum terrain height in tile
30  int16 ihmax[18338]; // Maximum terrain height in tile
31 } dem;
32 
33 /* Function prototypes */
34 float bilin(float *, float *, int32 *, int16 *, int32 *);
35 int initialize_dem(const char *, int32 *);
36 
37 /* get_dem_height */
38 int get_dem_height(const char *demfile,
39  float *xlon, float *xlat,
40  float *senz, float *sena,
41  float *height) {
42  /* Local variables */
43  int32 status = 0;
44  static float tilat, tilon, tslon, tslat, tansnz, sinsna, cossna;
45  static float x0, y0, x, y, dx, dy, dd, dist, distn, ddist;
46  static float coslat, hgt1, hgt2, los1, los2;
47  static int16 npts, iflag;
48  static int16 i, irow, icol, itile;
49  static int16* tile;
50  static int32 tileid;
51 
52  /* Initialized data */
53  static int firstCall = 1;
54  static int32 idims[3] = {1, 220, 220};
55  static int32 istart[3] = {0, 0, 0};
56  static int32 itilem = -999;
57  static float step = .5f;
58  static float tszmin = .01f;
59  static float snzmax = 56.f;
60  static float remm = 6371000.f; // Earth mean radius in meters
61 
62  /* Check if file is open */
63  if (firstCall) {
64  firstCall = 0;
65 
66  tile = (int16*) allocateMemory(48400 * sizeof (int16), "get_dem_height - tile");
67 
68  /* Open DEM file and fill structure */
69  if (initialize_dem(demfile, &tileid) != 0) {
70  return 1;
71  }
72 
73  /* Compute constants used for calculations */
74  /* Tile size in latitude */
75  tslat = 180.f / (dem.nrows - 1);
76 
77  /* Nominal tile grid point spacing in meters */
78  distn = remm * tslat / (dem.itsize * RADEG);
79 
80  /* Set step size in meters */
81  ddist = step * distn;
82  }
83 
84  /* Compute tile # */
85  irow = (*xlat - 0.0001f + 90.f) / tslat + .5f;
86  icol = (*xlon - 0.0001f + 180.f) / 360.f * dem.ncols[irow];
87  itile = dem.nstart[irow] + icol;
88  iflag = dem.iflag[itile];
89 
90  /* Set nominal values (sea level) */
91  *height = 0.f;
92  dist = 0.f;
93 
94  /* If sea level, return input values */
95  if (iflag == 0) {
96  return 0;
97  }
98 
99  /* Compute needed trig functions of angles */
100  tansnz = tan(*senz / RADEG);
101  sinsna = sin(*sena / RADEG);
102  cossna = cos(*sena / RADEG);
103  coslat = cos(*xlat / RADEG);
104 
105  /* If flat tile */
106  if (iflag == 1) {
107  npts = 2;
108  *height = (float) dem.ihmax[itile];
109  dist = *height * tansnz * remm / (remm + *height);
110 
111  /* Else terrain tile */
112  } else {
113 
114  /* Check for tile already in memory */
115  if (itile != itilem) {
116 
117  /* Read tile array from file */
118  istart[0] = dem.irecno[itile];
119  // printf("Tile %d record %d\n",itile,istart[0]);
120  itilem = itile;
121  if (SDreaddata(tileid, istart, NULL, idims, tile) != 0) {
122  printf("Error reading tile %d record %d\n",
123  itile, dem.irecno[itile]);
124  return 1;
125  }
126 
127  /* Compute longitude width of tile */
128  tslon = 360.f / dem.ncols[irow];
129 
130  /* Compute coordinates of lower-left corner of nominal tile */
131  tilat = (irow - .5f) * tslat - 90.f;
132  tilon = icol * tslon - 180.f;
133  }
134 
135  /* Get terrain heights under line-of-sight */
136 
137  /* Determine maximum number of points needed */
138  npts = dem.ihmax[itile] * tansnz / ddist + 2;
139 
140  /* Determine location of input lon/lat on tile grid */
141  /* (recall that points are bin centers) */
142  x0 = (*xlon - tilon) / tslon * dem.itsize + dem.ioff + .5f;
143  y0 = (*xlat - tilat) / tslat * dem.itsize + dem.ioff + .5f;
144 
145  /* Get interpolated height at input lon/lat */
146  *height = bilin(&x0, &y0, &dem.isize, tile, &status);
147  dist = 0.f;
148 
149  /* Check for zero height and low-slope tile */
150  if (*height == 0.f && iflag == 2) {
151  return 0;
152  }
153  /* Compute grid step size */
154  dx = step * sinsna;
155  dy = step * cossna;
156 
157  /* Correct horizontal step size for latitude and tile size */
158  dx = dx * tslat / (coslat * tslon);
159 
160  /* Find intersection point */
161 
162  /* Check for sensor zenith close to zero */
163  if (tansnz < tszmin) {
164  dist = *height * tansnz;
165 
166  /* Else step downward along line-of-sight */
167  } else {
168 
169  /* Initialize search parameters */
170  hgt1 = 0.f;
171  hgt2 = 0.f;
172  i = npts;
173  dist = i * ddist;
174 
175  /* Compute LOS height with correction for Earth curvature effect */
176  los1 = dist * (dist * tansnz / 2.f + remm)
177  / (remm * tansnz - dist);
178 
179  /* Continue until line-of-sight crosses terrain */
180  while (los1 > hgt1) {
181  --i;
182  los2 = los1;
183  hgt2 = hgt1;
184  dist = i * ddist;
185  x = x0 + i * dx;
186  y = y0 + i * dy;
187  hgt1 = bilin(&x, &y, &dem.isize, tile, &status);
188 
189  /* Check for current point outside tile area and print warning message */
190  if (status != 0 && i < 1) {
191  printf("Warning: %d %d outside tile range\n", (int) x, (int) y);
192  }
193  los1 = dist * (dist * tansnz / 2.f + remm)
194  / (remm * tansnz - dist);
195  }
196 
197  /* Interpolate to find intersection point */
198  dd = (hgt1 - los1) / (hgt1 - los1 + los2 - hgt2);
199  dist += dd * ddist;
200  x += dd * dx;
201  y += dd * dy;
202  hgt1 = bilin(&x, &y, &dem.isize, tile, &status);
203 
204  /* Check for final height outside tile area */
205  if (status != 0) {
206 
207  /* If within GAC swath, return with error */
208  if (*senz <= snzmax) {
209  printf("Bilinear interpolation error %d %d %d\n",
210  (int) x, (int) y, (int) dem.isize);
211  return 0;
212  } else {
213  status = 0;
214  }
215 
216  } else {
217  *height = hgt1;
218  }
219  }
220 
221  /* Compute adjustments to lon, lat, solar zenith and azimuth */
222  /* (need to look at corrections for polar regions) */
223  *xlon += dist * sinsna * RADEG / (remm * coslat);
224  *xlat += dist * cossna * RADEG / remm;
225  *senz -= dist * RADEG / remm;
226 
227  /* Check for longitude transition over date line */
228  if (*xlon > 180.f) {
229  *xlon -= 360.f;
230  }
231  if (*xlon < -180.f) {
232  *xlon += 360.f;
233  }
234  }
235 
236  return 0;
237 } /* get_dem_height */
238 
239 
240 #define tile_ref(a_1,a_2) tile[(a_2)*tile_dim1 + a_1]
241 
242 float bilin(float *x, float *y, int32 *isize, int16 *tile, int32 *status) {
243  /* System generated locals */
244  int tile_dim1, tile_offset;
245  float ret_val;
246 
247  /* Local variables */
248  static float dx, dy;
249  static int32 ix, iy;
250 
251  /* Parameter adjustments */
252  tile_dim1 = *isize;
253  tile_offset = 1 + tile_dim1;
254  tile -= (int32) tile_offset;
255 
256  /* Compute indices */
257  ix = *x;
258  iy = *y;
259 
260  /* Check indices against array size */
261  if ((ix > 0) && (ix < *isize) && (iy > 0) && (iy < *isize)) {
262 
263  dx = *x - ix;
264  dy = *y - iy;
265 
266  ret_val = (1 - dx) * (1 - dy) * tile_ref(ix, iy)
267  + dx * (1 - dy) * tile_ref(ix + 1, iy)
268  + (1 - dx) * dy * tile_ref(ix, iy + 1)
269  + dx * dy * tile_ref(ix + 1, iy + 1);
270  status[0] = 0;
271 
272  } else {
273  ret_val = 0.f;
274  status[0] = -1;
275  }
276 
277  return ret_val;
278 } /* bilin */
279 #undef tile_ref
280 
281 int initialize_dem(const char *demfile, int32 *tileid) {
282  /* Initialized data */
283  int32 status = 0;
284  static int32 istart = 0;
285  static int32 istr = 1;
286 
287  /* Local variables */
288  static int32 ind;
289  static int32 at_id, sd_id, idims, fileid;
290 
291  status = 0;
292  tileid[0] = -1;
293 
294  /* Open file */
295  fileid = SDstart(demfile, DFACC_RDONLY);
296  if (fileid == -1) {
297  printf("Error opening DEM file: %s\n", demfile);
298  status = -1;
299  return 0;
300  }
301 
302  /* Read file attributes */
303 
304  at_id = SDfindattr(fileid, "Number of rows");
305  if (at_id == -1) {
306  printf("Error getting index for Number of rows\n");
307  return 0;
308  }
309  status = SDreadattr(fileid, at_id, &dem.nrows);
310  if (status == -1) {
311  printf("Error getting value for Number of rows\n");
312  return 0;
313  }
314 
315  at_id = SDfindattr(fileid, "Equator tiles");
316  if (at_id == -1) {
317  printf("Error getting index for Equator tiles\n");
318  return 0;
319  }
320  status = SDreadattr(fileid, at_id, &dem.neq);
321  if (status == -1) {
322  printf("Error getting value for Equator tiles\n");
323  return 0;
324  }
325 
326  at_id = SDfindattr(fileid, "Array size");
327  if (at_id == -1) {
328  printf("Error getting index for Array size\n");
329  return 0;
330  }
331  status = SDreadattr(fileid, at_id, &dem.isize);
332  if (status == -1) {
333  printf("Error getting value for Array size\n");
334  return 0;
335  }
336 
337  at_id = SDfindattr(fileid, "Tile size");
338  if (at_id == -1) {
339  printf("Error getting index for Tile size\n");
340  return 0;
341  }
342  status = SDreadattr(fileid, at_id, &dem.itsize);
343  if (status == -1) {
344  printf("Error getting value for Tile size\n");
345  return 0;
346  }
347 
348  at_id = SDfindattr(fileid, "Array tile offset");
349  if (at_id == -1) {
350  printf("Error getting index for Array tile offset\n");
351  return 0;
352  }
353  status = SDreadattr(fileid, at_id, &dem.ioff);
354  if (status == -1) {
355  printf("Error getting value for Array tile offset\n");
356  return 0;
357  }
358 
359  at_id = SDfindattr(fileid, "Number of tiles");
360  if (at_id == -1) {
361  printf("Error getting index for Number of tiles\n");
362  return 0;
363  }
364  status = SDreadattr(fileid, at_id, &dem.ntiles);
365  if (status == -1) {
366  printf("Error getting value for Number of tiles\n");
367  return 0;
368  }
369 
370  at_id = SDfindattr(fileid, "Number of filled tiles");
371  if (at_id == -1) {
372  printf("Error getting index for Number of filled tiles\n");
373  return 0;
374  }
375  status = SDreadattr(fileid, at_id, &dem.nftiles);
376  if (status == -1) {
377  printf("Error getting value for Number of filled tiles\n");
378  return 0;
379  }
380 
381  /* Read index arrays */
382 
383  idims = dem.nrows;
384 
385  ind = SDnametoindex(fileid, "Row_number_of_tiles");
386  if (ind == -1) {
387  printf("Error getting index for Row_number_of_tiles\n");
388  return 0;
389  }
390  sd_id = SDselect(fileid, ind);
391  if (sd_id == -1) {
392  printf("Error selecting Row_number_of_tiles\n");
393  return 0;
394  }
395  status = SDreaddata(sd_id, &istart, &istr, &idims, dem.ncols);
396  if (status == -1) {
397  printf("Error reading Row_number_of_tiles\n");
398  return 0;
399  }
400  status = SDendaccess(sd_id);
401 
402  ind = SDnametoindex(fileid, "Row_start_tile");
403  if (ind == -1) {
404  printf("Error getting index for Row_start_tile\n");
405  return 0;
406  }
407  sd_id = SDselect(fileid, ind);
408  if (sd_id == -1) {
409  printf("Error selecting Row_start_tile\n");
410  return 0;
411  }
412  status = SDreaddata(sd_id, &istart, &istr, &idims, dem.nstart);
413  if (status == -1) {
414  printf("Error reading Row_start_tile\n");
415  return 0;
416  }
417  status = SDendaccess(sd_id);
418 
419  idims = dem.ntiles;
420 
421  ind = SDnametoindex(fileid, "DEM_tile_record");
422  if (ind == -1) {
423  printf("Error getting index for DEM_tile_record\n");
424  return 0;
425  }
426  sd_id = SDselect(fileid, ind);
427  if (sd_id == -1) {
428  printf("Error selecting DEM_tile_record\n");
429  return 0;
430  }
431  status = SDreaddata(sd_id, &istart, &istr, &idims, dem.irecno);
432  if (status == -1) {
433  printf("Error reading DEM_tile_record\n");
434  return 0;
435  }
436  status = SDendaccess(sd_id);
437 
438  ind = SDnametoindex(fileid, "DEM_tile_flag");
439  if (ind == -1) {
440  printf("Error getting index for DEM_tile_flag\n");
441  return 0;
442  }
443  sd_id = SDselect(fileid, ind);
444  if (sd_id == -1) {
445  printf("Error selecting DEM_tile_flag\n");
446  return 0;
447  }
448  status = SDreaddata(sd_id, &istart, &istr, &idims, dem.iflag);
449  if (status == -1) {
450  printf("Error reading DEM_tile_flag\n");
451  return 0;
452  }
453  status = SDendaccess(sd_id);
454 
455  ind = SDnametoindex(fileid, "Tile_minimum_height");
456  if (ind == -1) {
457  printf("Error getting index for Tile_minimum_height\n");
458  return 0;
459  }
460  sd_id = SDselect(fileid, ind);
461  if (sd_id == -1) {
462  printf("Error selecting Tile_minimum_height\n");
463  return 0;
464  }
465  status = SDreaddata(sd_id, &istart, &istr, &idims, dem.ihmin);
466  if (status == -1) {
467  printf("Error reading Tile_minimum_height\n");
468  return 0;
469  }
470  status = SDendaccess(sd_id);
471 
472  ind = SDnametoindex(fileid, "Tile_maximum_height");
473  if (ind == -1) {
474  printf("Error getting index for Tile_maximum_height\n");
475  return 0;
476  }
477  sd_id = SDselect(fileid, ind);
478  if (sd_id == -1) {
479  printf("Error selecting Tile_maximum_height\n");
480  return 0;
481  }
482  status = SDreaddata(sd_id, &istart, &istr, &idims, dem.ihmax);
483  if (status == -1) {
484  printf("Error reading Tile_maximum_height\n");
485  return 0;
486  }
487  status = SDendaccess(sd_id);
488 
489  /* Get SDS ID for tile array */
490  ind = SDnametoindex(fileid, "DEM_tile_data");
491  if (ind == -1) {
492  printf("Error getting index for DEM_tile_data\n");
493  return 0;
494  }
495  tileid[0] = SDselect(fileid, ind);
496  if (tileid[0] == -1) {
497  printf("Error selecting DEM_tile_flag\n");
498  }
499  return 0;
500 } /* initialize_dem */
501 
502 /**************************************************************************/
503 
504 int interp_dem_height(const char *demfile,
505  float *xlon, float *xlat,
506  float *height) {
507  /* Local variables */
508  int32 status = 0;
509  static float tilat, tilon, tslon, tslat;
510  static float x0, y0;
511  static int16 iflag;
512  static int16 irow, icol, itile;
513  static int16* tile;
514  static int32 tileid;
515 
516  /* Initialized data */
517  static int firstCall = 1;
518  static int32 idims[3] = {1, 220, 220};
519  static int32 istart[3] = {0, 0, 0};
520  static int32 itilem = -999;
521 
522  /* Check if file is open */
523  if (firstCall) {
524  firstCall = 0;
525 
526  tile = (int16*) allocateMemory(48400 * sizeof (int16), "interp_dem_height - tile");
527 
528  /* Open DEM file and fill structure */
529  if (initialize_dem(demfile, &tileid) != 0) {
530  return 1;
531  }
532 
533  /* Compute constants used for calculations */
534  /* Tile size in latitude */
535  tslat = 180.f / (dem.nrows - 1);
536  }
537 
538  /* Compute tile # */
539  irow = (*xlat - 0.0001f + 90.f) / tslat + .5f;
540  icol = (*xlon - 0.0001f + 180.f) / 360.f * dem.ncols[irow];
541  itile = dem.nstart[irow] + icol;
542  iflag = dem.iflag[itile];
543 
544  /* Set nominal values (sea level) */
545  *height = 0.f;
546 
547  /* If sea level, return input values */
548  if (iflag == 0) {
549  return 0;
550  }
551 
552  /* If flat tile */
553  if (iflag == 1) {
554  *height = (float) dem.ihmax[itile];
555 
556  /* Else terrain tile */
557  } else {
558 
559  /* Check for tile already in memory */
560  if (itile != itilem) {
561 
562  /* Read tile array from file */
563  istart[0] = dem.irecno[itile];
564  // printf("Tile %d record %d\n",itile,istart[0]);
565  itilem = itile;
566  if (SDreaddata(tileid, istart, NULL, idims, tile) != 0) {
567  printf("Error reading tile %d record %d\n",
568  itile, dem.irecno[itile]);
569  return 1;
570  }
571 
572  /* Compute longitude width of tile */
573  tslon = 360.f / dem.ncols[irow];
574 
575  /* Compute coordinates of lower-left corner of nominal tile */
576  tilat = (irow - .5f) * tslat - 90.f;
577  tilon = icol * tslon - 180.f;
578  }
579 
580  /* Determine location of input lon/lat on tile grid */
581  /* (recall that points are bin centers) */
582  x0 = (*xlon - tilon) / tslon * dem.itsize + dem.ioff + .5f;
583  y0 = (*xlat - tilat) / tslat * dem.itsize + dem.ioff + .5f;
584 
585  /* Get interpolated height at input lon/lat */
586  *height = bilin(&x0, &y0, &dem.isize, tile, &status);
587  }
588 
589  return 0;
590 }
integer, parameter int16
Definition: cubeio.f90:3
int32 isize
int32 ntiles
int status
Definition: l1_czcs_hdf.c:32
int16 ihmax[18338]
void * allocateMemory(size_t numBytes, const char *name)
Definition: allocateMemory.c:7
#define NULL
Definition: decode_rs.h:63
int initialize_dem(char *, int32 *)
int interp_dem_height(char *demfile, float *xlon, float *xlat, float *height)
int32 nrows
character(len=1000) if
Definition: names.f90:13
int16 nstart[121]
int32 neq
double precision function f(R1)
Definition: tmd.lp.f:1454
float bilin(float *, float *, int32 *, int16 *, int32 *)
int32 itsize
int16 iflag[18338]
struct @125 dem
int32 nftiles
#define tile_ref(a_1, a_2)
float xlon[LAC_PIXEL_NUM]
Definition: l1a_seawifs.c:93
int get_dem_height(char *demfile, float *xlon, float *xlat, float *senz, float *sena, float *height)
int32 ioff
int16 ncols[121]
int16 ihmin[18338]
int i
Definition: decode_rs.h:71
#define RADEG
Definition: get_dem_height.c:8
int16 irecno[18338]