1 /*****************************************************************************
2  * $Id: GDapi.c 29336 2015-06-14 17:37:21Z rouault $
3  *
4  * This module has a number of additions and improvements over the original
5  * implementation to be suitable for usage in GDAL HDF driver.
6  *
7  * Andrey Kiselev <dron@ak4719.spb.edu> is responsible for all the changes.
8  ****************************************************************************/
9 
10 /*
11 Copyright (C) 1996 Hughes and Applied Research Corporation
12 
13 Permission to use, modify, and distribute this software and its documentation
14 for any purpose without fee is hereby granted, provided that the above
15 copyright notice appear in all copies and that both that copyright notice and
16 this permission notice appear in supporting documentation.
17 */
18 /*****************************************************************************
19 REVISIONS:
20 
21 Aug 31, 1999  Abe Taaheri    Changed memory allocation for utility strings to
22                              the size of UTLSTR_MAX_SIZE.
23 			     Added error check for memory unavailibilty in
24 			     several functions.
25 			     Added check for NULL metabuf returned from
26 			     EHmeta... functions. NULL pointer retruned from
27 			     EHmeta... functions indicate that memory could not
28 			     be allocated for metabuf.
29 Jun  27, 2000  Abe Taaheri   Added support for EASE grid that uses
30                              Behrmann Cylinderical Equal Area (BCEA) projection
31 Oct  23, 2000  Abe Taaheri   Updated for ISINUS projection, so that both codes
32                              31 and 99 can be used for this projection.
33 Jan  15, 2003   Abe Taaheri  Modified for generalization of EASE Grid.
34 
35 Jun  05, 2003 Bruce Beaumont / Abe Taaheri
36 
37                              Fixed SQUARE definition.
38                              Added static projection number/name translation
39                              Added projection table lookup in GDdefproj.
40                              Removed projection table from GDdefproj
41                              Added projection table lookup in GDprojinfo
42                              Removed projection table from GDprojinfo
43                              Added cast for compcode in call to SDsetcompress
44                                 in GDdeffield to avoid compiler errors
45                              Removed declaration for unused variable endptr
46                                 in GDSDfldsrch
47                              Removed initialization code for unused variables
48                                 in GDSDfldsrch
49                              Removed declarations for unused variables
50                                 BCEA_scale, r0, s0, xMtr0, xMtr1, yMtr0,
51                                 and yMtr1 in GDll2ij
52                              Removed initialization code for unused variables
53                                 in GDll2ij
54                              Added code in GEO projection handling to allow
55                                 map to span dateline in GDll2ij
56                              Changed "for each point" loop in GDll2ij to
57                                 return -2147483648.0 for xVal and yVal if
58                                 for_trans returned an error instead of
59                                 returning an error to the caller
60                                 (Note: MAXLONG is defined as 2147483647.0 in
61                                  function cproj.c of GCTP)
62                              Added code in GDij2ll to use for_trans to
63                                 translate the BCEA corner points from packed
64                                 degrees to meters
65                              Removed declarations for unused variables
66                                 BCEA_scale, r0, s0, xMtr, yMtr, epsilon,
67                                 beta, qp_cea, kz_cea, eccen, eccen_sq,
68                                 phi1, sinphi1, cosphi1, lon, lat, xcor,
69                                 ycor, and nlatlon from GDij2ll
70                              Removed initialization code for unused variables
71                                 in GDij2ll
72                              Added declarations for xMtr0, yMtr0, xMtr1, and
73                                 yMtr1 in GDij2ll
74                              Added special-case code for BCEA
75                              Changed "for each point" loop in GDij2ll to
76                                 return PGSd_GCT_IN_ERROR (1.0e51) for
77                                 longitude and latitude values if inv_trans
78                                 returned an error instead of return an error
79                                 to the caller
80                              Removed declaration for unused variable ii in
81                                 GDgetpixvalues
82                              Removed declaration for unused variable
83                                 numTileDims in GDtileinfo
84                              Added error message and error return at the
85                                 end of GDll2mm_cea
86                              Added return statement to GDll2mm_cea
87 ******************************************************************************/
88 #include "cpl_string.h"
89 #include "stdio.h"
90 #include "mfhdf.h"
91 #include "hcomp.h"
92 #include <math.h>
93 #include "HdfEosDef.h"
94 
95 #include "hdf4compat.h"
96 
97 extern  void for_init(int32, int32, float64 *, int32, char *, char *, int32 *,
98                       int32 (*for_trans[])());
99 extern  void inv_init(int32, int32, float64 *, int32, char *, char *, int32 *,
100                       int32 (*inv_trans[])());
101 
102 #define	GDIDOFFSET 4194304
103 #define SQUARE(x)       ((x) * (x))   /* x**2 */
104 #define M_PI1		3.14159265358979323846
105 
106 static int32 GDXSDcomb[512*5];
107 static char  GDXSDname[HDFE_NAMBUFSIZE];
108 static char  GDXSDdims[HDFE_DIMBUFSIZE];
109 
110 
111 #define NGRID 200
112 /* Grid Structure External Arrays */
113 struct gridStructure
114 {
115     int32 active;
116     int32 IDTable;
117     int32 VIDTable[2];
118     int32 fid;
119     int32 nSDS;
120     int32 *sdsID;
121     int32 compcode;
122     intn  compparm[5];
123     int32 tilecode;
124     int32 tilerank;
125     int32 tiledims[8];
126 };
127 static struct gridStructure GDXGrid[NGRID];
128 
129 
130 
131 #define NGRIDREGN 256
132 struct gridRegion
133 {
134     int32 fid;
135     int32 gridID;
136     int32 xStart;
137     int32 xCount;
138     int32 yStart;
139     int32 yCount;
140     int32 somStart;
141     int32 somCount;
142     float64 upleftpt[2];
143     float64 lowrightpt[2];
144     int32 StartVertical[8];
145     int32 StopVertical[8];
146     char *DimNamePtr[8];
147 };
148 static struct gridRegion *GDXRegion[NGRIDREGN];
149 
150 /* define a macro for the string size of the utility strings and some dimension
151    list strings. The value of 80 in the previous version of this code
152    may not be enough in some cases. The length now is 512 which seems to
153    be more than enough to hold larger strings. */
154 
155 #define UTLSTR_MAX_SIZE 512
156 
157 /* Static projection table */
158 static const struct {
159     int32 projcode;
160     char *projname;
161 } Projections[] = {
162     {GCTP_GEO,	   "GCTP_GEO"},
163     {GCTP_UTM,	   "GCTP_UTM"},
164     {GCTP_SPCS,	   "GCTP_SPCS"},
165     {GCTP_ALBERS,  "GCTP_ALBERS"},
166     {GCTP_LAMCC,   "GCTP_LAMCC"},
167     {GCTP_MERCAT,  "GCTP_MERCAT"},
168     {GCTP_PS,	   "GCTP_PS"},
169     {GCTP_POLYC,   "GCTP_POLYC"},
170     {GCTP_EQUIDC,  "GCTP_EQUIDC"},
171     {GCTP_TM,	   "GCTP_TM"},
172     {GCTP_STEREO,  "GCTP_STEREO"},
173     {GCTP_LAMAZ,   "GCTP_LAMAZ"},
174     {GCTP_AZMEQD,  "GCTP_AZMEQD"},
175     {GCTP_GNOMON,  "GCTP_GNOMON"},
176     {GCTP_ORTHO,   "GCTP_ORTHO"},
177     {GCTP_GVNSP,   "GCTP_GVNSP"},
178     {GCTP_SNSOID,  "GCTP_SNSOID"},
179     {GCTP_EQRECT,  "GCTP_EQRECT"},
180     {GCTP_MILLER,  "GCTP_MILLER"},
181     {GCTP_VGRINT,  "GCTP_VGRINT"},
182     {GCTP_HOM,	   "GCTP_HOM"},
183     {GCTP_ROBIN,   "GCTP_ROBIN"},
184     {GCTP_SOM,	   "GCTP_SOM"},
185     {GCTP_ALASKA,  "GCTP_ALASKA"},
186     {GCTP_GOOD,	   "GCTP_GOOD"},
187     {GCTP_MOLL,	   "GCTP_MOLL"},
188     {GCTP_IMOLL,   "GCTP_IMOLL"},
189     {GCTP_HAMMER,  "GCTP_HAMMER"},
190     {GCTP_WAGIV,   "GCTP_WAGIV"},
191     {GCTP_WAGVII,  "GCTP_WAGVII"},
192     {GCTP_OBLEQA,  "GCTP_OBLEQA"},
193     {GCTP_ISINUS1, "GCTP_ISINUS1"},
194     {GCTP_CEA,	   "GCTP_CEA"},
195     {GCTP_BCEA,	   "GCTP_BCEA"},
196     {GCTP_ISINUS,  "GCTP_ISINUS"},
197     {-1,	   NULL}
198 };
199 
200 /* Compression Codes */
201 static const char *HDFcomp[] = {
202     "HDFE_COMP_NONE",
203     "HDFE_COMP_RLE",
204     "HDFE_COMP_NBIT",
205     "HDFE_COMP_SKPHUFF",
206     "HDFE_COMP_DEFLATE"
207 };
208 
209 /* Origin Codes */
210 static const char *originNames[] = {
211     "HDFE_GD_UL",
212     "HDFE_GD_UR",
213     "HDFE_GD_LL",
214     "HDFE_GD_LR"
215 };
216 
217 /* Pixel Registration Codes */
218 static const char *pixregNames[] = {
219     "HDFE_CENTER",
220     "HDFE_CORNER"
221 };
222 
223 /* Grid Function Prototypes (internal routines) */
224 static intn GDchkgdid(int32, char *, int32 *, int32 *, int32 *);
225 static intn GDSDfldsrch(int32, int32, const char *, int32 *, int32 *,
226                         int32 *, int32 *, int32 [], int32 *);
227 static intn GDwrrdfield(int32, char *, char *,
228                         int32 [], int32 [], int32 [], VOIDP datbuf);
229 static intn GDwrrdattr(int32, char *, int32, int32, char *, VOIDP);
230 static intn GDll2ij(int32, int32, float64 [], int32, int32, int32, float64[],
231                     float64[], int32, float64[], float64[], int32[], int32[],
232                     float64[], float64[]);
233 static intn  GDgetdefaults(int32, int32, float64[], int32,
234                            float64[], float64[]);
235 static intn GDtangentpnts(int32, float64[], float64[], float64[], float64[],
236                           float64 [], int32 *);
237 static intn GDwrrdtile(int32, char *, char *, int32 [], VOIDP);
238 static intn GDll2mm_cea(int32,int32, int32, float64[], int32, int32,
239                         float64[], float64[], int32, float64[],float64[],
240                         float64[], float64[], float64 *, float64 *);
241 
242 static intn GDmm2ll_cea(int32, int32, int32, float64[],	int32, int32,
243                         float64[], float64[], int32, float64[], float64[],
244                         float64[], float64[]);
245 
246 /*----------------------------------------------------------------------------|
247 |  BEGIN_PROLOG                                                               |
248 |                                                                             |
249 |  FUNCTION: GDopen                                                           |
250 |                                                                             |
251 |  DESCRIPTION: Opens or creates HDF file in order to create, read, or write  |
252 |                a grid.                                                      |
253 |                                                                             |
254 |                                                                             |
255 |  Return Value    Type     Units     Description                             |
256 |  ============   ======  =========   =====================================   |
257 |  fid            int32               HDF-EOS file ID                         |
258 |                                                                             |
259 |  INPUTS:                                                                    |
260 |  filename       char                Filename                                |
261 |  access         intn                HDF access code                         |
262 |                                                                             |
263 |                                                                             |
264 |  OUTPUTS:                                                                   |
265 |             None                                                            |
266 |                                                                             |
267 |  NOTES:                                                                     |
268 |                                                                             |
269 |                                                                             |
270 |   Date     Programmer   Description                                         |
271 |  ======   ============  =================================================   |
272 |  Jun 96   Joel Gales    Original Programmer                                 |
273 |                                                                             |
274 |  END_PROLOG                                                                 |
275 -----------------------------------------------------------------------------*/
276 int32
GDopen(char * filename,intn access)277 GDopen(char *filename, intn access)
278 
279 {
280     int32           fid /* HDF-EOS file ID */ ;
281 
282     /* Call EHopen to perform file access */
283     /* ---------------------------------- */
284     fid = EHopen(filename, access);
285 
286     return (fid);
287 
288 }
289 
290 
291 
292 /*----------------------------------------------------------------------------|
293 |  BEGIN_PROLOG                                                               |
294 |                                                                             |
295 |  FUNCTION: GDcreate                                                         |
296 |                                                                             |
297 |  DESCRIPTION: Creates a grid within the file.                               |
298 |                                                                             |
299 |                                                                             |
300 |  Return Value    Type     Units     Description                             |
301 |  ============   ======  =========   =====================================   |
302 |  gridID         int32               Grid structure ID                       |
303 |                                                                             |
304 |  INPUTS:                                                                    |
305 |  fid            int32               File ID                                 |
306 |  gridname       char                Grid structure name                     |
307 |  xdimsize       int32               Number of columns in grid               |
308 |  ydimsize       int32               Number of rows in grid                  |
309 |  upleftpt       float64             Location (m/deg) of upper left corner   |
310 |  lowrightpt     float64             Location (m/deg) of lower right corner  |
311 |                                                                             |
312 |                                                                             |
313 |  OUTPUTS:                                                                   |
314 |             None                                                            |
315 |                                                                             |
316 |  NOTES:                                                                     |
317 |                                                                             |
318 |                                                                             |
319 |   Date     Programmer   Description                                         |
320 |  ======   ============  =================================================   |
321 |  Jun 96   Joel Gales    Original Programmer                                 |
322 |  Aug 96   Joel Gales    Make metadata ODL compliant                         |
323 |  Aug 96   Joel Gales    Check grid name for ODL compliance                  |
324 |                                                                             |
325 |  END_PROLOG                                                                 |
326 -----------------------------------------------------------------------------*/
327 int32
GDcreate(int32 fid,char * gridname,int32 xdimsize,int32 ydimsize,float64 upleftpt[],float64 lowrightpt[])328 GDcreate(int32 fid, char *gridname, int32 xdimsize, int32 ydimsize,
329 	 float64 upleftpt[], float64 lowrightpt[])
330 {
331     intn            i;		/* Loop index */
332     intn            ngridopen = 0;	/* # of grid structures open */
333     intn            status = 0;	/* routine return status variable */
334 
335     uint8           access;	/* Read/Write file access code */
336 
337     int32           HDFfid;	/* HDF file id */
338     int32           vgRef;	/* Vgroup reference number */
339     int32           vgid[3];	/* Vgroup ID array */
340     int32           gridID = -1;/* HDF-EOS grid ID */
341 
342     int32           sdInterfaceID;	/* HDF SDS interface ID */
343     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
344     int32           nGrid = 0;	/* Grid counter */
345 
346     char            name[80];	/* Vgroup name */
347     char            class[80];	/* Vgroup class */
348     char            errbuf[256];/* Buffer for error message */
349     char            utlbuf[1024];	/* Utility buffer */
350     char            header[128];/* Structural metadata header string */
351     char            footer[256];/* Structural metadata footer string */
352     char            refstr1[128];	/* Upper left ref string (metadata) */
353     char            refstr2[128];	/* Lower right ref string (metadata) */
354 
355 
356     /*
357      * Check HDF-EOS file ID, get back HDF file ID, SD interface ID  and
358      * access code
359      */
360     status = EHchkfid(fid, gridname, &HDFfid, &sdInterfaceID, &access);
361 
362 
363     /* Check gridname for length */
364     /* ------------------------- */
365     if ((intn) strlen(gridname) > VGNAMELENMAX)
366     {
367 	status = -1;
368 	HEpush(DFE_GENAPP, "GDcreate", __FILE__, __LINE__);
369 	HEreport("Gridname \"%s\" must be less than %d characters.\n",
370 		 gridname, VGNAMELENMAX);
371     }
372 
373 
374 
375     if (status == 0)
376     {
377 	/* Determine number of grids currently opened */
378 	/* ------------------------------------------- */
379 	for (i = 0; i < NGRID; i++)
380 	{
381 	    ngridopen += GDXGrid[i].active;
382 	}
383 
384 
385 	/* Setup file interface */
386 	/* -------------------- */
387 	if (ngridopen < NGRID)
388 	{
389 
390 	    /* Check that grid has not been previously opened */
391 	    /* ----------------------------------------------- */
392 	    vgRef = -1;
393 
394 	    while (1)
395 	    {
396 		vgRef = Vgetid(HDFfid, vgRef);
397 
398 		/* If no more Vgroups then exist while loop */
399 		/* ---------------------------------------- */
400 		if (vgRef == -1)
401 		{
402 		    break;
403 		}
404 
405 		/* Get name and class of Vgroup */
406 		/* ---------------------------- */
407 		vgid[0] = Vattach(HDFfid, vgRef, "r");
408 		Vgetname(vgid[0], name);
409 		Vgetclass(vgid[0], class);
410 		Vdetach(vgid[0]);
411 
412 
413 		/* If GRID then increment # grid counter */
414 		/* ------------------------------------- */
415 		if (strcmp(class, "GRID") == 0)
416 		{
417 		    nGrid++;
418 		}
419 
420 
421 		/* If grid already exist, return error */
422 		/* ------------------------------------ */
423 		if (strcmp(name, gridname) == 0 &&
424 		    strcmp(class, "GRID") == 0)
425 		{
426 		    status = -1;
427 		    HEpush(DFE_GENAPP, "GDcreate", __FILE__, __LINE__);
428 		    HEreport("\"%s\" already exists.\n", gridname);
429 		    break;
430 		}
431 	    }
432 
433 
434 	    if (status == 0)
435 	    {
436 		/* Create Root Vgroup for Grid */
437 		/* ---------------------------- */
438 		vgid[0] = Vattach(HDFfid, -1, "w");
439 
440 
441 		/* Set Name and Class (GRID) */
442 		/* -------------------------- */
443 		Vsetname(vgid[0], gridname);
444 		Vsetclass(vgid[0], "GRID");
445 
446 
447 
448 		/* Create Data Fields Vgroup */
449 		/* ------------------------- */
450 		vgid[1] = Vattach(HDFfid, -1, "w");
451 		Vsetname(vgid[1], "Data Fields");
452 		Vsetclass(vgid[1], "GRID Vgroup");
453 		Vinsert(vgid[0], vgid[1]);
454 
455 
456 
457 		/* Create Attributes Vgroup */
458 		/* ------------------------ */
459 		vgid[2] = Vattach(HDFfid, -1, "w");
460 		Vsetname(vgid[2], "Grid Attributes");
461 		Vsetclass(vgid[2], "GRID Vgroup");
462 		Vinsert(vgid[0], vgid[2]);
463 
464 
465 
466 		/* Establish Grid in Structural MetaData Block */
467 		/* -------------------------------------------- */
468 		sprintf(header, "%s%d%s%s%s%s%d%s%s%d%s",
469 			"\tGROUP=GRID_", (int)(nGrid + 1),
470 			"\n\t\tGridName=\"", gridname, "\"\n",
471 			"\t\tXDim=", (int)xdimsize, "\n",
472 			"\t\tYDim=", (int)ydimsize, "\n");
473 
474 
475 		sprintf(footer,
476 			"%s%s%s%s%s%s%s%d%s",
477 			"\t\tGROUP=Dimension\n",
478 			"\t\tEND_GROUP=Dimension\n",
479 			"\t\tGROUP=DataField\n",
480 			"\t\tEND_GROUP=DataField\n",
481 			"\t\tGROUP=MergedFields\n",
482 			"\t\tEND_GROUP=MergedFields\n",
483 			"\tEND_GROUP=GRID_", (int)(nGrid + 1), "\n");
484 
485 
486 
487 		/* Build Ref point Col-Row strings */
488 		/* ------------------------------- */
489 		if (upleftpt == NULL ||
490 		    (upleftpt[0] == 0 && upleftpt[1] == 0 &&
491 		     lowrightpt[0] == 0 && lowrightpt[1] == 0))
492 		{
493 		    strcpy(refstr1, "DEFAULT");
494 		    strcpy(refstr2, "DEFAULT");
495 		}
496 		else
497 		{
498 		    CPLsprintf(refstr1, "%s%f%s%f%s",
499 			    "(", upleftpt[0], ",", upleftpt[1], ")");
500 
501 		    CPLsprintf(refstr2, "%s%f%s%f%s",
502 			    "(", lowrightpt[0], ",", lowrightpt[1], ")");
503 		}
504 
505 		sprintf(utlbuf,
506 			"%s%s%s%s%s%s%s%s",
507 			header,
508 			"\t\tUpperLeftPointMtrs=", refstr1, "\n",
509 			"\t\tLowerRightMtrs=", refstr2, "\n",
510 			footer);
511 
512 		status = EHinsertmeta(sdInterfaceID, "", "g", 1002L,
513 				      utlbuf, NULL);
514 
515 	    }
516 	}
517 	else
518 	{
519 	    /* Too many files opened */
520 	    /* --------------------- */
521 	    status = -1;
522 	    strcpy(errbuf,
523 		   "No more than %d grids may be open simutaneously");
524 	    strcat(errbuf, " (%s)");
525 	    HEpush(DFE_DENIED, "GDcreate", __FILE__, __LINE__);
526 	    HEreport(errbuf, NGRID, gridname);
527 	}
528 
529 
530 	/* Assign gridID # & Load grid and GDXGrid.fid table entries */
531 	/* --------------------------------------------------------- */
532 	if (status == 0)
533 	{
534 
535 	    for (i = 0; i < NGRID; i++)
536 	    {
537 		if (GDXGrid[i].active == 0)
538 		{
539 		    gridID = i + idOffset;
540 		    GDXGrid[i].active = 1;
541 		    GDXGrid[i].IDTable = vgid[0];
542 		    GDXGrid[i].VIDTable[0] = vgid[1];
543 		    GDXGrid[i].VIDTable[1] = vgid[2];
544 		    GDXGrid[i].fid = fid;
545 		    status = 0;
546 		    break;
547 		}
548 	    }
549 
550 	}
551     }
552     return (gridID);
553 }
554 
555 
556 
557 /*----------------------------------------------------------------------------|
558 |  BEGIN_PROLOG                                                               |
559 |                                                                             |
560 |  FUNCTION: GDattach                                                         |
561 |                                                                             |
562 |  DESCRIPTION: Attaches to an existing grid within the file.                 |
563 |                                                                             |
564 |                                                                             |
565 |  Return Value    Type     Units     Description                             |
566 |  ============   ======  =========   =====================================   |
567 |  gridID         int32               grid structure ID                       |
568 |                                                                             |
569 |  INPUTS:                                                                    |
570 |  fid            int32               HDF-EOS file id                         |
571 |  gridname       char                grid sructure name                      |
572 |                                                                             |
573 |                                                                             |
574 |  OUTPUTS:                                                                   |
575 |             None                                                            |
576 |                                                                             |
577 |  NOTES:                                                                     |
578 |                                                                             |
579 |                                                                             |
580 |   Date     Programmer   Description                                         |
581 |  ======   ============  =================================================   |
582 |  Jun 96   Joel Gales    Original Programmer                                 |
583 |  Sep 99   Abe Taaheri   Modified test for memory allocation check when no   |
584 |                         SDSs are in the grid, NCR24147                    |
585 |                                                                             |
586 |  END_PROLOG                                                                 |
587 -----------------------------------------------------------------------------*/
588 int32
GDattach(int32 fid,char * gridname)589 GDattach(int32 fid, char *gridname)
590 
591 {
592     intn            i;		/* Loop index */
593     intn            j;		/* Loop index */
594     intn            ngridopen = 0;	/* # of grid structures open */
595     intn            status;	/* routine return status variable */
596 
597     uint8           acs;	/* Read/Write file access code */
598 
599     int32           HDFfid;	/* HDF file id */
600     int32           vgRef;	/* Vgroup reference number */
601     int32           vgid[3];	/* Vgroup ID array */
602     int32           gridID = -1;/* HDF-EOS grid ID */
603     int32          *tags;	/* Pnt to Vgroup object tags array */
604     int32          *refs;	/* Pnt to Vgroup object refs array */
605     int32           dum;	/* dummy varible */
606     int32           sdInterfaceID;	/* HDF SDS interface ID */
607     int32           nObjects;	/* # of objects in Vgroup */
608     int32           nSDS;	/* SDS counter */
609     int32           index;	/* SDS index */
610     int32           sdid;	/* SDS object ID */
611     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
612 
613     char            name[80];	/* Vgroup name */
614     char            class[80];	/* Vgroup class */
615     char            errbuf[256];/* Buffer for error message */
616     char            acsCode[1];	/* Read/Write access char: "r/w" */
617 
618 
619     /* Check HDF-EOS file ID, get back HDF file ID and access code */
620     /* ----------------------------------------------------------- */
621     status = EHchkfid(fid, gridname, &HDFfid, &dum, &acs);
622 
623 
624     if (status == 0)
625     {
626 	/* Convert numeric access code to character */
627 	/* ---------------------------------------- */
628 
629 	acsCode[0] = (acs == 1) ? 'w' : 'r';
630 
631 	/* Determine number of grids currently opened */
632 	/* ------------------------------------------- */
633 	for (i = 0; i < NGRID; i++)
634 	{
635 	    ngridopen += GDXGrid[i].active;
636 	}
637 
638 
639 	/* If room for more ... */
640 	/* -------------------- */
641 	if (ngridopen < NGRID)
642 	{
643 
644 	    /* Search Vgroups for Grid */
645 	    /* ------------------------ */
646 	    vgRef = -1;
647 
648 	    while (1)
649 	    {
650 		vgRef = Vgetid(HDFfid, vgRef);
651 
652 		/* If no more Vgroups then exist while loop */
653 		/* ---------------------------------------- */
654 		if (vgRef == -1)
655 		{
656 		    break;
657 		}
658 
659 		/* Get name and class of Vgroup */
660 		/* ---------------------------- */
661 		vgid[0] = Vattach(HDFfid, vgRef, "r");
662 		Vgetname(vgid[0], name);
663 		Vgetclass(vgid[0], class);
664 
665 
666 		/*
667 		 * If Vgroup with gridname and class GRID found, load tables
668 		 */
669 
670 		if (strcmp(name, gridname) == 0 &&
671 		    strcmp(class, "GRID") == 0)
672 		{
673 		    /* Attach to "Data Fields" and "Grid Attributes" Vgroups */
674 		    /* ----------------------------------------------------- */
675 		    tags = (int32 *) malloc(sizeof(int32) * 2);
676 		    if(tags == NULL)
677 		    {
678 			HEpush(DFE_NOSPACE,"GDattach", __FILE__, __LINE__);
679 			return(-1);
680 		    }
681 		    refs = (int32 *) malloc(sizeof(int32) * 2);
682 		    if(refs == NULL)
683 		    {
684 			HEpush(DFE_NOSPACE,"GDattach", __FILE__, __LINE__);
685 			free(tags);
686 			return(-1);
687 		    }
688 		    Vgettagrefs(vgid[0], tags, refs, 2);
689 		    vgid[1] = Vattach(HDFfid, refs[0], acsCode);
690 		    vgid[2] = Vattach(HDFfid, refs[1], acsCode);
691 		    free(tags);
692 		    free(refs);
693 
694 
695 		    /* Setup External Arrays */
696 		    /* --------------------- */
697 		    for (i = 0; i < NGRID; i++)
698 		    {
699 			/* Find empty entry in array */
700 			/* ------------------------- */
701 			if (GDXGrid[i].active == 0)
702 			{
703 			    /*
704 			     * Set gridID, Set grid entry active, Store root
705 			     * Vgroup ID, Store sub Vgroup IDs, Store HDF-EOS
706 			     * file ID
707 			     */
708 			    gridID = i + idOffset;
709 			    GDXGrid[i].active = 1;
710 			    GDXGrid[i].IDTable = vgid[0];
711 			    GDXGrid[i].VIDTable[0] = vgid[1];
712 			    GDXGrid[i].VIDTable[1] = vgid[2];
713 			    GDXGrid[i].fid = fid;
714 			    break;
715 			}
716 		    }
717 
718 		    /* Get SDS interface ID */
719 		    /* -------------------- */
720 		    status = GDchkgdid(gridID, "GDattach", &dum,
721 				       &sdInterfaceID, &dum);
722 
723 
724 		    /* Get # of entries within Data Vgroup & search for SDS */
725 		    /* ---------------------------------------------------- */
726 		    nObjects = Vntagrefs(vgid[1]);
727 
728 		    if (nObjects > 0)
729 		    {
730 			/* Get tag and ref # for Data Vgroup objects */
731 			/* ----------------------------------------- */
732 			tags = (int32 *) malloc(sizeof(int32) * nObjects);
733 			if(tags == NULL)
734 			{
735 			    HEpush(DFE_NOSPACE,"GDattach", __FILE__, __LINE__);
736 			    return(-1);
737 			}
738 			refs = (int32 *) malloc(sizeof(int32) * nObjects);
739 			if(refs == NULL)
740 			{
741 			    HEpush(DFE_NOSPACE,"GDattach", __FILE__, __LINE__);
742 			    free(tags);
743 			    return(-1);
744 			}
745 			Vgettagrefs(vgid[1], tags, refs, nObjects);
746 
747 			/* Count number of SDS & allocate SDS ID array */
748 			/* ------------------------------------------- */
749 			nSDS = 0;
750 			for (j = 0; j < nObjects; j++)
751 			{
752 			    if (tags[j] == DFTAG_NDG)
753 			    {
754 				nSDS++;
755 			    }
756 			}
757 			GDXGrid[i].sdsID = (int32 *) calloc(nSDS, 4);
758 			if(GDXGrid[i].sdsID == NULL && nSDS != 0)
759 			{
760 			    HEpush(DFE_NOSPACE,"GDattach", __FILE__, __LINE__);
761 			    free(tags);
762 			    free(refs);
763 			    return(-1);
764 			}
765 			nSDS = 0;
766 
767 
768 
769 			/* Fill SDS ID array */
770 			/* ----------------- */
771 			for (j = 0; j < nObjects; j++)
772 			{
773 			    /* If object is SDS then get id */
774 			    /* ---------------------------- */
775 			    if (tags[j] == DFTAG_NDG)
776 			    {
777 				index = SDreftoindex(sdInterfaceID, refs[j]);
778 				sdid = SDselect(sdInterfaceID, index);
779 				GDXGrid[i].sdsID[nSDS] = sdid;
780 				nSDS++;
781 				GDXGrid[i].nSDS++;
782 			    }
783 			}
784 			free(tags);
785 			free(refs);
786 		    }
787 		    break;
788 		}
789 
790 		/* Detach Vgroup if not desired Grid */
791 		/* --------------------------------- */
792 		Vdetach(vgid[0]);
793 	    }
794 
795 	    /* If Grid not found then set up error message */
796 	    /* ------------------------------------------- */
797 	    if (gridID == -1)
798 	    {
799 		HEpush(DFE_RANGE, "GDattach", __FILE__, __LINE__);
800 		HEreport("Grid: \"%s\" does not exist within HDF file.\n",
801 			 gridname);
802 	    }
803 	}
804 	else
805 	{
806 	    /* Too many files opened */
807 	    /* --------------------- */
808 	    gridID = -1;
809 	    strcpy(errbuf,
810 		   "No more than %d grids may be open simutaneously");
811 	    strcat(errbuf, " (%s)");
812 	    HEpush(DFE_DENIED, "GDattach", __FILE__, __LINE__);
813 	    HEreport(errbuf, NGRID, gridname);
814 	}
815 
816     }
817     return (gridID);
818 }
819 
820 
821 /*----------------------------------------------------------------------------|
822 |  BEGIN_PROLOG                                                               |
823 |                                                                             |
824 |  FUNCTION: GDchkgdid                                                        |
825 |                                                                             |
826 |  DESCRIPTION:                                                               |
827 |                                                                             |
828 |                                                                             |
829 |  Return Value    Type     Units     Description                             |
830 |  ============   ======  =========   =====================================   |
831 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
832 |                                                                             |
833 |  INPUTS:                                                                    |
834 |  gridID         int32               grid structure ID                       |
835 |  routname       char                Name of routine calling GDchkgdid       |
836 |                                                                             |
837 |  OUTPUTS:                                                                   |
838 |  fid            int32               File ID                                 |
839 |  sdInterfaceID  int32               SDS interface ID                        |
840 |  gdVgrpID       int32               grid Vgroup ID                          |
841 |                                                                             |
842 |                                                                             |
843 |  OUTPUTS:                                                                   |
844 |             None                                                            |
845 |                                                                             |
846 |  NOTES:                                                                     |
847 |                                                                             |
848 |                                                                             |
849 |   Date     Programmer   Description                                         |
850 |  ======   ============  =================================================   |
851 |  Jun 96   Joel Gales    Original Programmer                                 |
852 |                                                                             |
853 |  END_PROLOG                                                                 |
854 -----------------------------------------------------------------------------*/
855 static intn
GDchkgdid(int32 gridID,char * routname,int32 * fid,int32 * sdInterfaceID,int32 * gdVgrpID)856 GDchkgdid(int32 gridID, char *routname,
857 	  int32 * fid, int32 * sdInterfaceID, int32 * gdVgrpID)
858 {
859     intn            status = 0;	/* routine return status variable */
860     uint8           access;	/* Read/Write access code */
861     int32           gID;	/* Grid ID - offset */
862 
863     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
864 
865     static const char message1[] =
866         "Invalid grid id: %d in routine \"%s\".  ID must be >= %d and < %d.\n";
867     static const char message2[] =
868         "Grid id %d in routine \"%s\" not active.\n";
869 
870 
871 
872     /* Check for valid grid id */
873 
874     if (gridID < idOffset || gridID >= NGRID + idOffset)
875     {
876 	status = -1;
877 	HEpush(DFE_RANGE, "GDchkgdid", __FILE__, __LINE__);
878 	HEreport(message1, gridID, routname, idOffset, NGRID + idOffset);
879     }
880     else
881     {
882 
883 	/* Compute "reduced" ID */
884 	/* -------------------- */
885 	gID = gridID % idOffset;
886 
887 
888 	/* Check for active grid ID */
889 	/* ------------------------ */
890 	if (GDXGrid[gID].active == 0)
891 	{
892 	    status = -1;
893 	    HEpush(DFE_GENAPP, "GDchkgdid", __FILE__, __LINE__);
894 	    HEreport(message2, gridID, routname);
895 	}
896 	else
897 	{
898 
899 	    /* Get file & SDS ids and Grid key */
900 	    /* -------------------------------- */
901 	    status = EHchkfid(GDXGrid[gID].fid, " ",
902 			      fid, sdInterfaceID, &access);
903 	    *gdVgrpID = GDXGrid[gID].IDTable;
904 	}
905     }
906     return (status);
907 
908 }
909 
910 
911 /*----------------------------------------------------------------------------|
912 |  BEGIN_PROLOG                                                               |
913 |                                                                             |
914 |  FUNCTION: GDdefdim                                                         |
915 |                                                                             |
916 |  DESCRIPTION: Defines a new dimension within the grid.                      |
917 |                                                                             |
918 |                                                                             |
919 |  Return Value    Type     Units     Description                             |
920 |  ============   ======  =========   =====================================   |
921 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
922 |                                                                             |
923 |  INPUTS:                                                                    |
924 |  gridID         int32               grid structure ID                       |
925 |  dimname        char                Dimension name to define                |
926 |  dim            int32               Dimemsion value                         |
927 |                                                                             |
928 |                                                                             |
929 |  OUTPUTS:                                                                   |
930 |             None                                                            |
931 |                                                                             |
932 |  NOTES:                                                                     |
933 |                                                                             |
934 |                                                                             |
935 |   Date     Programmer   Description                                         |
936 |  ======   ============  =================================================   |
937 |  Jun 96   Joel Gales    Original Programmer                                 |
938 |                                                                             |
939 |  END_PROLOG                                                                 |
940 -----------------------------------------------------------------------------*/
941 intn
GDdefdim(int32 gridID,char * dimname,int32 dim)942 GDdefdim(int32 gridID, char *dimname, int32 dim)
943 
944 {
945     intn            status;	/* routine return status variable */
946 
947     int32           fid;	/* HDF-EOS file id */
948     int32           sdInterfaceID;	/* HDF SDS interface ID */
949     int32           gdVgrpID;	/* Grid root Vgroup ID */
950     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
951 
952     char            gridname[80] /* Grid name */ ;
953 
954 
955     /* Check for valid grid id */
956     status = GDchkgdid(gridID, "GDdefinedim",
957 		       &fid, &sdInterfaceID, &gdVgrpID);
958 
959 
960     /* Make sure dimension >= 0 */
961     /* ------------------------ */
962     if (dim < 0)
963     {
964 	status = -1;
965 	HEpush(DFE_GENAPP, "GDdefdim", __FILE__, __LINE__);
966 	HEreport("Dimension value for \"%s\" less than zero: %d.\n",
967 		 dimname, dim);
968     }
969 
970 
971     /* Write Dimension to Structural MetaData */
972     /* -------------------------------------- */
973     if (status == 0)
974     {
975 	Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
976 	status = EHinsertmeta(sdInterfaceID, gridname, "g", 0L,
977 			      dimname, &dim);
978     }
979     return (status);
980 
981 }
982 
983 /*----------------------------------------------------------------------------|
984 |  BEGIN_PROLOG                                                               |
985 |                                                                             |
986 |  FUNCTION: GDdefproj                                                        |
987 |                                                                             |
988 |  DESCRIPTION: Defines projection of grid.                                   |
989 |                                                                             |
990 |                                                                             |
991 |  Return Value    Type     Units     Description                             |
992 |  ============   ======  =========   =====================================   |
993 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
994 |                                                                             |
995 |  INPUTS:                                                                    |
996 |  gridID         int32               Grid structure ID                       |
997 |  projcode       int32               GCTP projection code                    |
998 |  zonecode       int32               UTM zone code                           |
999 |  spherecode     int32               GCTP spheriod code                      |
1000 |  projparm       float64             Projection parameters                   |
1001 |                                                                             |
1002 |  OUTPUTS:                                                                   |
1003 |             None                                                            |
1004 |                                                                             |
1005 |  NOTES:                                                                     |
1006 |                                                                             |
1007 |                                                                             |
1008 |   Date     Programmer   Description                                         |
1009 |  ======   ============  =================================================   |
1010 |  Jun 96   Joel Gales    Original Programmer                                 |
1011 |  Jun 00   Abe Taaheri   Added support for EASE grid                         |
1012 |                                                                             |
1013 |  END_PROLOG                                                                 |
1014 -----------------------------------------------------------------------------*/
1015 intn
GDdefproj(int32 gridID,int32 projcode,int32 zonecode,int32 spherecode,float64 projparm[])1016 GDdefproj(int32 gridID, int32 projcode, int32 zonecode, int32 spherecode,
1017 	  float64 projparm[])
1018 {
1019     intn            i;		/* Loop index */
1020     intn	    projx;	/* Projection table index */
1021     intn            status = 0;	/* routine return status variable */
1022 
1023     int32           fid;	/* HDF-EOS file ID */
1024     int32           sdInterfaceID;	/* HDF SDS interface ID */
1025     int32           gdVgrpID;	/* Grid root Vgroup ID */
1026     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
1027     int32           slen;	/* String length */
1028     float64         EHconvAng();
1029     char            utlbuf[1024];	/* Utility Buffer */
1030     char            projparmbuf[512];	/* Projection parameter metadata
1031 					 * string */
1032     char            gridname[80];	/* Grid Name */
1033 
1034 
1035     /* Check for valid grid id */
1036     /* ----------------------- */
1037     status = GDchkgdid(gridID, "GDdefproj", &fid, &sdInterfaceID, &gdVgrpID);
1038 
1039     if (status == 0)
1040     {
1041 	/*
1042 	 * If projection not GEO, UTM, or State Code build projection
1043 	 * parameter string
1044 	 */
1045 	if (projcode != GCTP_GEO &&
1046 	    projcode != GCTP_UTM &&
1047 	    projcode != GCTP_SPCS)
1048 	{
1049 
1050 	    /* Begin projection parameter list with "(" */
1051 	    strcpy(projparmbuf, "(");
1052 
1053 	    for (i = 0; i < 13; i++)
1054 	    {
1055 		/* If projparm[i] = 0 ... */
1056 		if (projparm[i] == 0.0)
1057 		{
1058 		    strcpy(utlbuf, "0,");
1059 		}
1060 		else
1061 		{
1062 		    /* if projparm[i] is integer ... */
1063 		    if ((int32) projparm[i] == projparm[i])
1064 		    {
1065 			sprintf(utlbuf, "%d%s",
1066 				(int) projparm[i], ",");
1067 		    }
1068 		    /* else projparm[i] is non-zero floating point ... */
1069 		    else
1070 		    {
1071 			CPLsprintf(utlbuf, "%f%s",	projparm[i], ",");
1072 		    }
1073 		}
1074 		strcat(projparmbuf, utlbuf);
1075 	    }
1076 	    slen = strlen(projparmbuf);
1077 
1078 	    /* Add trailing ")" */
1079 	    projparmbuf[slen - 1] = ')';
1080 	}
1081 
1082 	for (projx = 0; Projections[projx].projcode != -1; projx++)
1083 	  {
1084 	    if (projcode == Projections[projx].projcode)
1085 	      {
1086 		break;
1087 	      }
1088 	  }
1089 
1090 
1091 	/* Build metadata string */
1092 	/* --------------------- */
1093 	if ((projcode == GCTP_GEO))
1094 	{
1095 	    sprintf(utlbuf,
1096 		    "%s%s%s",
1097 		    "\t\tProjection=", Projections[projx].projname, "\n");
1098 	}
1099 	else if (projcode == GCTP_UTM || projcode == GCTP_SPCS)
1100 	{
1101 	    sprintf(utlbuf,
1102 		    "%s%s%s%s%d%s%s%d%s",
1103 		    "\t\tProjection=", Projections[projx].projname, "\n",
1104 		    "\t\tZoneCode=", (int)zonecode, "\n",
1105 		    "\t\tSphereCode=", (int)spherecode, "\n");
1106 	}
1107 	else
1108 	{
1109 	    sprintf(utlbuf,
1110 		    "%s%s%s%s%s%s%s%d%s",
1111 		    "\t\tProjection=", Projections[projx].projname, "\n",
1112 		    "\t\tProjParams=", projparmbuf, "\n",
1113 		    "\t\tSphereCode=", (int)spherecode, "\n");
1114 	}
1115 
1116 
1117 	/* Insert in structural metadata */
1118 	/* ----------------------------- */
1119 	Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
1120 	status = EHinsertmeta(sdInterfaceID, gridname, "g", 101L,
1121 			      utlbuf, NULL);
1122     }
1123 
1124     return (status);
1125 }
1126 
1127 
1128 
1129 /*----------------------------------------------------------------------------|
1130 |  BEGIN_PROLOG                                                               |
1131 |                                                                             |
1132 |  FUNCTION: GDblkSOMoffset                                                   |
1133 |                                                                             |
1134 |  DESCRIPTION: Writes Block SOM offset values                                |
1135 |                                                                             |
1136 |                                                                             |
1137 |  Return Value    Type     Units     Description                             |
1138 |  ============   ======  =========   =====================================   |
1139 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
1140 |                                                                             |
1141 |  INPUTS:                                                                    |
1142 |  gridID         int32               Grid structure ID                       |
1143 |  offset         float32             Offset values                           |
1144 |  count          int32               Number of offset values                 |
1145 |  code           char                w/r code (w/r)                          |
1146 |                                                                             |
1147 |  OUTPUTS:                                                                   |
1148 |             None                                                            |
1149 |                                                                             |
1150 |  NOTES:                                                                     |
1151 |                                                                             |
1152 |                                                                             |
1153 |   Date     Programmer   Description                                         |
1154 |  ======   ============  =================================================   |
1155 |  Sep 96   Joel Gales    Original Programmer                                 |
1156 |  Mar 99   David Wynne   Changed data type of offset array from int32 to     |
1157 |                         float32, NCR 21197                                  |
1158 |                                                                             |
1159 |  END_PROLOG                                                                 |
1160 -----------------------------------------------------------------------------*/
1161 intn
GDblkSOMoffset(int32 gridID,float32 offset[],int32 count,char * code)1162 GDblkSOMoffset(int32 gridID, float32 offset[], int32 count, char *code)
1163 {
1164     intn            status = 0;	/* routine return status variable */
1165 
1166     int32           fid;	/* HDF-EOS file ID */
1167     int32           sdInterfaceID;	/* HDF SDS interface ID */
1168     int32           gdVgrpID;	/* Grid root Vgroup ID */
1169     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
1170     int32           projcode;	/* GCTP projection code */
1171 
1172     float64         projparm[13];	/* Projection parameters */
1173 
1174     char            utlbuf[128];/* Utility Buffer */
1175     char            gridname[80];	/* Grid Name */
1176 
1177     /* Check for valid grid id */
1178     status = GDchkgdid(gridID, "GDblkSOMoffset",
1179 		       &fid, &sdInterfaceID, &gdVgrpID);
1180 
1181     if (status == 0)
1182     {
1183 	/* Get projection parameters */
1184 	status = GDprojinfo(gridID, &projcode, NULL, NULL, projparm);
1185 
1186 	/* If SOM projection with projparm[11] non-zero ... */
1187 	if (projcode == GCTP_SOM && projparm[11] != 0)
1188 	{
1189 	    Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
1190 	    sprintf(utlbuf, "%s%s", "_BLKSOM:", gridname);
1191 
1192 	    /* Write offset values as attribute */
1193 	    if (strcmp(code, "w") == 0)
1194 	    {
1195 		status = GDwriteattr(gridID, utlbuf, DFNT_FLOAT32,
1196 				     count, offset);
1197 	    }
1198 	    /* Read offset values from attribute */
1199 	    else if (strcmp(code, "r") == 0)
1200 	    {
1201 		status = GDreadattr(gridID, utlbuf, offset);
1202 	    }
1203 	}
1204     }
1205     return (status);
1206 }
1207 
1208 
1209 /*----------------------------------------------------------------------------|
1210 |  BEGIN_PROLOG                                                               |
1211 |                                                                             |
1212 |  FUNCTION: GDdefcomp                                                        |
1213 |                                                                             |
1214 |  DESCRIPTION: Defines compression type and parameters                       |
1215 |                                                                             |
1216 |                                                                             |
1217 |  Return Value    Type     Units     Description                             |
1218 |  ============   ======  =========   =====================================   |
1219 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
1220 |                                                                             |
1221 |  INPUTS:                                                                    |
1222 |  gridID         int32               grid structure ID                       |
1223 |  compcode       int32               compression code                        |
1224 |  compparm       intn                compression parameters                  |
1225 |                                                                             |
1226 |  OUTPUTS:                                                                   |
1227 |             None                                                            |
1228 |                                                                             |
1229 |  NOTES:                                                                     |
1230 |                                                                             |
1231 |                                                                             |
1232 |   Date     Programmer   Description                                         |
1233 |  ======   ============  =================================================   |
1234 |  Sep 96   Joel Gales    Original Programmer                                 |
1235 |                                                                             |
1236 |  END_PROLOG                                                                 |
1237 -----------------------------------------------------------------------------*/
1238 intn
GDdefcomp(int32 gridID,int32 compcode,intn compparm[])1239 GDdefcomp(int32 gridID, int32 compcode, intn compparm[])
1240 {
1241     intn            status = 0;	/* routine return status variable */
1242 
1243     int32           fid;	/* HDF-EOS file id */
1244     int32           sdInterfaceID;	/* HDF SDS interface ID */
1245     int32           gdVgrpID;	/* Grid root Vgroup ID */
1246     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
1247     int32           gID;	/* gridID - offset */
1248 
1249     /* Check for valid grid id */
1250     status = GDchkgdid(gridID, "GDdefcomp", &fid, &sdInterfaceID, &gdVgrpID);
1251 
1252     if (status == 0)
1253     {
1254 	gID = gridID % idOffset;
1255 
1256 	/* Set compression code in compression exteral array */
1257 	GDXGrid[gID].compcode = compcode;
1258 
1259 	switch (compcode)
1260 	{
1261 	    /* Set NBIT compression parameters in compression external array */
1262 	case HDFE_COMP_NBIT:
1263 
1264 	    GDXGrid[gID].compparm[0] = compparm[0];
1265 	    GDXGrid[gID].compparm[1] = compparm[1];
1266 	    GDXGrid[gID].compparm[2] = compparm[2];
1267 	    GDXGrid[gID].compparm[3] = compparm[3];
1268 
1269 	    break;
1270 
1271 	    /* Set GZIP compression parameter in compression external array */
1272 	case HDFE_COMP_DEFLATE:
1273 
1274 	    GDXGrid[gID].compparm[0] = compparm[0];
1275 
1276 	    break;
1277 
1278 	}
1279     }
1280 
1281     return (status);
1282 }
1283 
1284 
1285 
1286 
1287 /*----------------------------------------------------------------------------|
1288 |  BEGIN_PROLOG                                                               |
1289 |                                                                             |
1290 |  FUNCTION: GDdeftile                                                        |
1291 |                                                                             |
1292 |  DESCRIPTION: Defines tiling parameters                                     |
1293 |                                                                             |
1294 |                                                                             |
1295 |  Return Value    Type     Units     Description                             |
1296 |  ============   ======  =========   =====================================   |
1297 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
1298 |                                                                             |
1299 |  INPUTS:                                                                    |
1300 |  gridID         int32               grid structure ID                       |
1301 |  tilecode       int32               tile code                               |
1302 |  tilerank       int32               number of tiling dimensions             |
1303 |  tiledims       int32               tiling dimensions                       |
1304 |                                                                             |
1305 |  OUTPUTS:                                                                   |
1306 |             None                                                            |
1307 |                                                                             |
1308 |  NOTES:                                                                     |
1309 |                                                                             |
1310 |                                                                             |
1311 |   Date     Programmer   Description                                         |
1312 |  ======   ============  =================================================   |
1313 |  Jan 97   Joel Gales    Original Programmer                                 |
1314 |                                                                             |
1315 |  END_PROLOG                                                                 |
1316 -----------------------------------------------------------------------------*/
1317 intn
GDdeftile(int32 gridID,int32 tilecode,int32 tilerank,int32 tiledims[])1318 GDdeftile(int32 gridID, int32 tilecode, int32 tilerank, int32 tiledims[])
1319 {
1320     intn            i;		/* Loop index */
1321     intn            status = 0;	/* routine return status variable */
1322 
1323     int32           fid;	/* HDF-EOS file id */
1324     int32           sdInterfaceID;	/* HDF SDS interface ID */
1325     int32           gdVgrpID;	/* Grid root Vgroup ID */
1326     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
1327     int32           gID;	/* gridID - offset */
1328 
1329     /* Check for valid grid id */
1330     /* ----------------------- */
1331     status = GDchkgdid(gridID, "GDdeftile", &fid, &sdInterfaceID, &gdVgrpID);
1332 
1333 
1334     if (status == 0)
1335     {
1336 	gID = gridID % idOffset;
1337 
1338 	for (i = 0; i < 8; i++)
1339 	{
1340 	    GDXGrid[gID].tiledims[i] = 0;
1341 	}
1342 
1343 	GDXGrid[gID].tilecode = tilecode;
1344 
1345 	switch (tilecode)
1346 	{
1347 	case HDFE_NOTILE:
1348 
1349 	    GDXGrid[gID].tilerank = 0;
1350 
1351 	    break;
1352 
1353 
1354 	case HDFE_TILE:
1355 
1356 	    GDXGrid[gID].tilerank = tilerank;
1357 
1358 	    for (i = 0; i < tilerank; i++)
1359 	    {
1360 		GDXGrid[gID].tiledims[i] = tiledims[i];
1361 
1362 		if (GDXGrid[gID].tiledims[i] == 0)
1363 		{
1364 		    GDXGrid[gID].tiledims[i] = 1;
1365 		}
1366 	    }
1367 
1368 	    break;
1369 
1370 	}
1371     }
1372 
1373     return (status);
1374 }
1375 
1376 
1377 
1378 
1379 /*----------------------------------------------------------------------------|
1380 |  BEGIN_PROLOG                                                               |
1381 |                                                                             |
1382 |  FUNCTION: GDdeforigin                                                      |
1383 |                                                                             |
1384 |  DESCRIPTION: Defines the origin of the grid data.                          |
1385 |                                                                             |
1386 |                                                                             |
1387 |  Return Value    Type     Units     Description                             |
1388 |  ============   ======  =========   =====================================   |
1389 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
1390 |                                                                             |
1391 |  INPUTS:                                                                    |
1392 |  gridID         int32               grid structure ID                       |
1393 |  origincode     int32               origin code                             |
1394 |                                     HDFE_GD_UL (0)                          |
1395 |                                     HDFE_GD_UR (1)                          |
1396 |			              HDFE_GD_LL (2)                          |
1397 |                                     HDFE_GD_LR (3)                          |
1398 |                                                                             |
1399 |                                                                             |
1400 |  OUTPUTS:                                                                   |
1401 |             None                                                            |
1402 |                                                                             |
1403 |  NOTES:                                                                     |
1404 |                                                                             |
1405 |                                                                             |
1406 |   Date     Programmer   Description                                         |
1407 |  ======   ============  =================================================   |
1408 |  Jun 96   Joel Gales    Original Programmer                                 |
1409 |                                                                             |
1410 |  END_PROLOG                                                                 |
1411 -----------------------------------------------------------------------------*/
1412 intn
GDdeforigin(int32 gridID,int32 origincode)1413 GDdeforigin(int32 gridID, int32 origincode)
1414 {
1415     intn            status = 0;	/* routine return status variable */
1416 
1417     int32           fid;	/* HDF-EOS file ID */
1418     int32           gdVgrpID;	/* Grid root Vgroup ID */
1419     int32           sdInterfaceID;	/* HDF SDS interface ID */
1420     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
1421 
1422     char            utlbuf[64];	/* Utility buffer */
1423     char            gridname[80];	/* Grid name */
1424 
1425 
1426     /* Check for valid grid id */
1427     status = GDchkgdid(gridID, "GDdeforigin",
1428 		       &fid, &sdInterfaceID, &gdVgrpID);
1429 
1430     if (status == 0)
1431     {
1432 	/* If proper origin code then write to structural metadata */
1433 	/* ------------------------------------------------------- */
1434 	if (origincode >= 0 && origincode < sizeof(originNames))
1435 	{
1436 	    sprintf(utlbuf, "%s%s%s",
1437 		    "\t\tGridOrigin=", originNames[origincode], "\n");
1438 
1439 	    Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
1440 	    status = EHinsertmeta(sdInterfaceID, gridname, "g", 101L,
1441 				  utlbuf, NULL);
1442 	}
1443 	else
1444 	{
1445 	    status = -1;
1446 	    HEpush(DFE_GENAPP, "GDdeforigin", __FILE__, __LINE__);
1447 	    HEreport("Improper Grid Origin code: %d\n", origincode);
1448 	}
1449     }
1450 
1451     return (status);
1452 }
1453 
1454 /*----------------------------------------------------------------------------|
1455 |  BEGIN_PROLOG                                                               |
1456 |                                                                             |
1457 |  FUNCTION: GDdefpixreg                                                      |
1458 |                                                                             |
1459 |  DESCRIPTION: Defines pixel registration within grid cell.                  |
1460 |                                                                             |
1461 |                                                                             |
1462 |  Return Value    Type     Units     Description                             |
1463 |  ============   ======  =========   =====================================   |
1464 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
1465 |                                                                             |
1466 |  INPUTS:                                                                    |
1467 |  gridID         int32               grid structure ID                       |
1468 |  pixregcode     int32               Pixel registration code                 |
1469 |                                     HDFE_CENTER (0)                         |
1470 |                                     HDFE_CORNER (1)                         |
1471 |                                                                             |
1472 |                                                                             |
1473 |  OUTPUTS:                                                                   |
1474 |             None                                                            |
1475 |                                                                             |
1476 |  NOTES:                                                                     |
1477 |                                                                             |
1478 |                                                                             |
1479 |   Date     Programmer   Description                                         |
1480 |  ======   ============  =================================================   |
1481 |  Jun 96   Joel Gales    Original Programmer                                 |
1482 |                                                                             |
1483 |  END_PROLOG                                                                 |
1484 -----------------------------------------------------------------------------*/
1485 intn
GDdefpixreg(int32 gridID,int32 pixregcode)1486 GDdefpixreg(int32 gridID, int32 pixregcode)
1487 {
1488     intn            status = 0;	/* routine return status variable */
1489 
1490     int32           fid;	/* HDF-EOS file ID */
1491     int32           gdVgrpID;	/* Grid root Vgroup ID */
1492     int32           sdInterfaceID;	/* HDF SDS interface ID */
1493     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
1494 
1495     char            utlbuf[64];	/* Utility buffer */
1496     char            gridname[80];	/* Grid name */
1497 
1498     /* Check for valid grid id */
1499     status = GDchkgdid(gridID, "GDdefpixreg",
1500 		       &fid, &sdInterfaceID, &gdVgrpID);
1501 
1502     if (status == 0)
1503     {
1504 	/* If proper pix reg code then write to structural metadata */
1505 	/* -------------------------------------------------------- */
1506 	if (pixregcode >= 0 && pixregcode < sizeof(pixregNames))
1507 	{
1508 	    sprintf(utlbuf, "%s%s%s",
1509 		    "\t\tPixelRegistration=", pixregNames[pixregcode], "\n");
1510 
1511 	    Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
1512 	    status = EHinsertmeta(sdInterfaceID, gridname, "g", 101L,
1513 				  utlbuf, NULL);
1514 	}
1515 	else
1516 	{
1517 	    status = -1;
1518 	    HEpush(DFE_GENAPP, "GDdefpixreg", __FILE__, __LINE__);
1519 	    HEreport("Improper Pixel Registration code: %d\n", pixregcode);
1520 	}
1521     }
1522 
1523     return (status);
1524 
1525 }
1526 
1527 
1528 
1529 
1530 
1531 /*----------------------------------------------------------------------------|
1532 |  BEGIN_PROLOG                                                               |
1533 |                                                                             |
1534 |  FUNCTION: GDdiminfo                                                        |
1535 |                                                                             |
1536 |  DESCRIPTION: Retrieve size of specified dimension.                         |
1537 |                                                                             |
1538 |                                                                             |
1539 |  Return Value    Type     Units     Description                             |
1540 |  ============   ======  =========   =====================================   |
1541 |  size           int32               Size of dimension                       |
1542 |                                                                             |
1543 |  INPUTS:                                                                    |
1544 |  gridID         int32               grid structure id                       |
1545 |  dimname        char                Dimension name                          |
1546 |                                                                             |
1547 |                                                                             |
1548 |  OUTPUTS:                                                                   |
1549 |             None                                                            |
1550 |                                                                             |
1551 |  NOTES:                                                                     |
1552 |                                                                             |
1553 |                                                                             |
1554 |   Date     Programmer   Description                                         |
1555 |  ======   ============  =================================================   |
1556 |  Jun 96   Joel Gales    Original Programmer                                 |
1557 |  Aug 96   Joel Gales    Make metadata ODL compliant                         |
1558 |  Jan 97   Joel Gales    Check for metadata error status from EHgetmetavalue |
1559 |                                                                             |
1560 |  END_PROLOG                                                                 |
1561 -----------------------------------------------------------------------------*/
1562 int32
GDdiminfo(int32 gridID,char * dimname)1563 GDdiminfo(int32 gridID, char *dimname)
1564 
1565 {
1566     intn            status;	/* routine return status variable */
1567 
1568     int32           fid;	/* HDF-EOS file ID */
1569     int32           sdInterfaceID;	/* HDF SDS interface ID */
1570     int32           gdVgrpID;	/* Grid root Vgroup ID */
1571     int32           size;	/* Dimension size */
1572     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
1573 
1574 
1575     char           *metabuf;	/* Pointer to structural metadata (SM) */
1576     char           *metaptrs[2];/* Pointers to begin and end of SM section */
1577     char            gridname[80];	/* Grid Name */
1578     char           *utlstr;	/* Utility string */
1579 
1580     /* Allocate space for utility string */
1581     /* --------------------------------- */
1582     utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
1583     if(utlstr == NULL)
1584     {
1585 	HEpush(DFE_NOSPACE,"GDdiminfo", __FILE__, __LINE__);
1586 	return(-1);
1587     }
1588     /* Initialize return value */
1589     /* ----------------------- */
1590     size = -1;
1591 
1592 
1593     /* Check Grid ID */
1594     /* ------------- */
1595     status = GDchkgdid(gridID, "GDdiminfo", &fid, &sdInterfaceID, &gdVgrpID);
1596 
1597 
1598     if (status == 0)
1599     {
1600 	/* Get grid name */
1601 	/* ------------- */
1602 	Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
1603 
1604 
1605 	/* Get pointers to "Dimension" section within SM */
1606 	/* --------------------------------------------- */
1607 	metabuf = (char *) EHmetagroup(sdInterfaceID, gridname, "g",
1608 				       "Dimension", metaptrs);
1609 
1610 	if(metabuf == NULL)
1611 	{
1612 	    free(utlstr);
1613 	    return(-1);
1614 	}
1615 
1616 	/* Search for dimension name (surrounded by quotes) */
1617 	/* ------------------------------------------------ */
1618 	sprintf(utlstr, "%s%s%s", "\"", dimname, "\"\n");
1619 	metaptrs[0] = strstr(metaptrs[0], utlstr);
1620 
1621 	/*
1622 	 * If dimension found within grid structure then get dimension value
1623 	 */
1624 	if (metaptrs[0] < metaptrs[1] && metaptrs[0] != NULL)
1625 	{
1626 	    /* Set endptr at end of dimension definition entry */
1627 	    /* ----------------------------------------------- */
1628 	    metaptrs[1] = strstr(metaptrs[0], "\t\t\tEND_OBJECT");
1629 
1630 	    status = EHgetmetavalue(metaptrs, "Size", utlstr);
1631 
1632 	    if (status == 0)
1633 	    {
1634 		size = atol(utlstr);
1635 	    }
1636 	    else
1637 	    {
1638 		HEpush(DFE_GENAPP, "GDdiminfo", __FILE__, __LINE__);
1639 		HEreport("\"Size\" string not found in metadata.\n");
1640 	    }
1641 	}
1642 	else
1643 	{
1644 	    HEpush(DFE_GENAPP, "GDdiminfo", __FILE__, __LINE__);
1645 	    HEreport("Dimension \"%s\" not found.\n", dimname);
1646 	}
1647 
1648 	free(metabuf);
1649     }
1650     free(utlstr);
1651     return (size);
1652 }
1653 
1654 
1655 
1656 
1657 
1658 /*----------------------------------------------------------------------------|
1659 |  BEGIN_PROLOG                                                               |
1660 |                                                                             |
1661 |  FUNCTION: GDgridinfo                                                       |
1662 |                                                                             |
1663 |  DESCRIPTION: Returns xdim, ydim and location of upper left and lower       |
1664 |                right corners, in meters.                                    |
1665 |                                                                             |
1666 |                                                                             |
1667 |  Return Value    Type     Units     Description                             |
1668 |  ============   ======  =========   =====================================   |
1669 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
1670 |                                                                             |
1671 |  INPUTS:                                                                    |
1672 |  fid            int32               File ID                                 |
1673 |  gridname       char                Grid structure name                     |
1674 |                                                                             |
1675 |  OUTPUTS:                                                                   |
1676 |  xdimsize       int32               Number of columns in grid               |
1677 |  ydimsize       int32               Number of rows in grid                  |
1678 |  upleftpt       float64             Location (m/deg) of upper left corner   |
1679 |  lowrightpt     float64             Location (m/deg) of lower right corner  |
1680 |                                                                             |
1681 |  NOTES:                                                                     |
1682 |                                                                             |
1683 |                                                                             |
1684 |   Date     Programmer   Description                                         |
1685 |  ======   ============  =================================================   |
1686 |  Jun 96   Joel Gales    Original Programmer                                 |
1687 |  Jan 97   Joel Gales    Check for metadata error status from EHgetmetavalue |
1688 |                                                                             |
1689 |  END_PROLOG                                                                 |
1690 -----------------------------------------------------------------------------*/
1691 intn
GDgridinfo(int32 gridID,int32 * xdimsize,int32 * ydimsize,float64 upleftpt[],float64 lowrightpt[])1692 GDgridinfo(int32 gridID, int32 * xdimsize, int32 * ydimsize,
1693 	   float64 upleftpt[], float64 lowrightpt[])
1694 
1695 {
1696     intn            status = 0;	/* routine return status variable */
1697     intn            statmeta = 0;	/* EHgetmetavalue return status */
1698 
1699     int32           fid;	/* HDF-EOS file ID */
1700     int32           sdInterfaceID;	/* HDF SDS interface ID */
1701     int32           gdVgrpID;	/* Grid root Vgroup ID */
1702     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
1703 
1704 
1705     char           *metabuf;	/* Pointer to structural metadata (SM) */
1706     char           *metaptrs[2];/* Pointers to begin and end of SM section */
1707     char            gridname[80];	/* Grid Name */
1708     char           *utlstr;	/* Utility string */
1709 
1710     /* Allocate space for utility string */
1711     /* --------------------------------- */
1712     utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
1713     if(utlstr == NULL)
1714     {
1715 	HEpush(DFE_NOSPACE,"GDgridinfo", __FILE__, __LINE__);
1716 	return(-1);
1717     }
1718     /* Check Grid ID */
1719     /* ------------- */
1720     status = GDchkgdid(gridID, "GDgridinfo", &fid, &sdInterfaceID, &gdVgrpID);
1721 
1722     if (status == 0)
1723     {
1724 	/* Get grid name */
1725 	/* ------------- */
1726 	Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
1727 
1728 
1729 	/* Get pointers to grid structure section within SM */
1730 	/* ------------------------------------------------ */
1731 	metabuf = (char *) EHmetagroup(sdInterfaceID, gridname, "g",
1732 				       NULL, metaptrs);
1733 
1734 	if(metabuf == NULL)
1735 	{
1736 	    free(utlstr);
1737 	    return(-1);
1738 	}
1739 
1740 
1741 	/* Get xdimsize if requested */
1742 	/* ------------------------- */
1743 	if (xdimsize != NULL)
1744 	{
1745 	    statmeta = EHgetmetavalue(metaptrs, "XDim", utlstr);
1746 	    if (statmeta == 0)
1747 	    {
1748 		*xdimsize = atol(utlstr);
1749 	    }
1750 	    else
1751 	    {
1752 		status = -1;
1753 		HEpush(DFE_GENAPP, "GDgridinfo", __FILE__, __LINE__);
1754 		HEreport("\"XDim\" string not found in metadata.\n");
1755 	    }
1756 	}
1757 
1758 
1759 	/* Get ydimsize if requested */
1760 	/* ------------------------- */
1761 	if (ydimsize != NULL)
1762 	{
1763 	    statmeta = EHgetmetavalue(metaptrs, "YDim", utlstr);
1764 	    if (statmeta == 0)
1765 	    {
1766 		*ydimsize = atol(utlstr);
1767 	    }
1768 	    else
1769 	    {
1770 		status = -1;
1771 		HEpush(DFE_GENAPP, "GDgridinfo", __FILE__, __LINE__);
1772 		HEreport("\"YDim\" string not found in metadata.\n");
1773 	    }
1774 	}
1775 
1776 
1777 	/* Get upleftpt if requested */
1778 	/* ------------------------- */
1779 	if (upleftpt != NULL)
1780 	{
1781 	    statmeta = EHgetmetavalue(metaptrs, "UpperLeftPointMtrs", utlstr);
1782 	    if (statmeta == 0)
1783 	    {
1784 		/* If value is "DEFAULT" then return zeros */
1785 		/* --------------------------------------- */
1786 		if (strcmp(utlstr, "DEFAULT") == 0)
1787 		{
1788 		    upleftpt[0] = 0;
1789 		    upleftpt[1] = 0;
1790 		}
1791 		else
1792 		{
1793 		    sscanf(utlstr, "(%lf,%lf)",
1794 			   &upleftpt[0], &upleftpt[1]);
1795 		}
1796 	    }
1797 	    else
1798 	    {
1799 		status = -1;
1800 		HEpush(DFE_GENAPP, "GDgridinfo", __FILE__, __LINE__);
1801 		HEreport(
1802 		  "\"UpperLeftPointMtrs\" string not found in metadata.\n");
1803 	    }
1804 
1805 	}
1806 
1807 	/* Get lowrightpt if requested */
1808 	/* --------------------------- */
1809 	if (lowrightpt != NULL)
1810 	{
1811 	    statmeta = EHgetmetavalue(metaptrs, "LowerRightMtrs", utlstr);
1812 	    if (statmeta == 0)
1813 	    {
1814 		/* If value is "DEFAULT" then return zeros */
1815 		if (strcmp(utlstr, "DEFAULT") == 0)
1816 		{
1817 		    lowrightpt[0] = 0;
1818 		    lowrightpt[1] = 0;
1819 		}
1820 		else
1821 		{
1822 		    sscanf(utlstr, "(%lf,%lf)",
1823 			   &lowrightpt[0], &lowrightpt[1]);
1824 		}
1825 	    }
1826 	    else
1827 	    {
1828 		status = -1;
1829 		HEpush(DFE_GENAPP, "GDgridinfo", __FILE__, __LINE__);
1830 		HEreport(
1831 		      "\"LowerRightMtrs\" string not found in metadata.\n");
1832 	    }
1833 	}
1834 
1835 	free(metabuf);
1836     }
1837     free(utlstr);
1838     return (status);
1839 }
1840 
1841 
1842 
1843 
1844 
1845 
1846 
1847 /*----------------------------------------------------------------------------|
1848 |  BEGIN_PROLOG                                                               |
1849 |                                                                             |
1850 |  FUNCTION: GDprojinfo                                                       |
1851 |                                                                             |
1852 |  DESCRIPTION: Returns GCTP projection code, zone code, spheroid code        |
1853 |                and projection parameters.                                   |
1854 |                                                                             |
1855 |                                                                             |
1856 |  Return Value    Type     Units     Description                             |
1857 |  ============   ======  =========   =====================================   |
1858 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
1859 |                                                                             |
1860 |  INPUTS:                                                                    |
1861 |  gridID         int32               Grid structure ID                       |
1862 |                                                                             |
1863 |  OUTPUTS:                                                                   |
1864 |  projcode       int32               GCTP projection code                    |
1865 |  zonecode       int32               UTM zone code                           |
1866 |  spherecode     int32               GCTP spheriod code                      |
1867 |  projparm       float64             Projection parameters                   |
1868 |                                                                             |
1869 |  NOTES:                                                                     |
1870 |                                                                             |
1871 |                                                                             |
1872 |   Date     Programmer   Description                                         |
1873 |  ======   ============  =================================================   |
1874 |  Jun 96   Joel Gales    Original Programmer                                 |
1875 |  Oct 96   Joel Gales    Add check for no projection code                    |
1876 |  Jan 97   Joel Gales    Check for metadata error status from EHgetmetavalue |
1877 |  Jun 00   Abe Taaheri   Added support for EASE grid                         |
1878 |                                                                             |
1879 |  END_PROLOG                                                                 |
1880 -----------------------------------------------------------------------------*/
1881 intn
GDprojinfo(int32 gridID,int32 * projcode,int32 * zonecode,int32 * spherecode,float64 projparm[])1882 GDprojinfo(int32 gridID, int32 * projcode, int32 * zonecode,
1883 	   int32 * spherecode, float64 projparm[])
1884 
1885 {
1886     intn            i;		/* Loop index */
1887     intn            projx;		/* Loop index */
1888     intn            status = 0;	/* routine return status variable */
1889     intn            statmeta = 0;	/* EHgetmetavalue return status */
1890 
1891     int32           fid;	/* HDF-EOS file ID */
1892     int32           sdInterfaceID;	/* HDF SDS interface ID */
1893     int32           gdVgrpID;	/* Grid root Vgroup ID */
1894     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
1895 
1896 
1897     char           *metabuf;	/* Pointer to structural metadata (SM) */
1898     char           *metaptrs[2];/* Pointers to begin and end of SM section */
1899     char            gridname[80];	/* Grid Name */
1900     char           *utlstr;	/* Utility string */
1901     char            fmt[96];	/* Format String */
1902 
1903     /* Allocate space for utility string */
1904     /* --------------------------------- */
1905     utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
1906     if(utlstr == NULL)
1907     {
1908 	HEpush(DFE_NOSPACE,"GDprojinfo", __FILE__, __LINE__);
1909 	return(-1);
1910     }
1911 
1912     /* Check Grid ID */
1913     /* ------------- */
1914     status = GDchkgdid(gridID, "GDprojinfo", &fid, &sdInterfaceID, &gdVgrpID);
1915 
1916     if (status == 0)
1917     {
1918 	/* Get grid name */
1919 	/* ------------- */
1920 	Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
1921 
1922 
1923 	/* Get pointers to grid structure section within SM */
1924 	/* ------------------------------------------------ */
1925 	metabuf = (char *) EHmetagroup(sdInterfaceID, gridname, "g",
1926 				       NULL, metaptrs);
1927 
1928 	if(metabuf == NULL)
1929 	{
1930 	    free(utlstr);
1931 	    return(-1);
1932 	}
1933 
1934 
1935 	/* Get projcode if requested */
1936 	/* ------------------------- */
1937 	if (projcode != NULL)
1938 	{
1939 	    *projcode = -1;
1940 
1941 	    statmeta = EHgetmetavalue(metaptrs, "Projection", utlstr);
1942 	    if (statmeta == 0)
1943 	    {
1944 		/* Loop through projection codes until found */
1945 		/* ----------------------------------------- */
1946 		for (projx = 0; Projections[projx].projcode != -1; projx++)
1947 		    if (strcmp(utlstr, Projections[projx].projname) == 0)
1948 			break;
1949 		if (Projections[projx].projname != NULL)
1950 		    *projcode = Projections[projx].projcode;
1951 	    }
1952 	    else
1953 	    {
1954 		status = -1;
1955 		HEpush(DFE_GENAPP, "GDprojinfo", __FILE__, __LINE__);
1956 		HEreport("Projection Code not defined for \"%s\".\n",
1957 			 gridname);
1958 
1959 		if (projparm != NULL)
1960 		{
1961 		    for (i = 0; i < 13; i++)
1962 		    {
1963 			projparm[i] = -1;
1964 		    }
1965 		}
1966 	    }
1967 	}
1968 
1969 
1970 	/* Get zonecode if requested */
1971 	/* ------------------------- */
1972 	if (zonecode != NULL)
1973 	{
1974 	    *zonecode = -1;
1975 
1976 
1977 	    /* Zone code only relevant for UTM and State Code projections */
1978 	    /* ---------------------------------------------------------- */
1979 	    if (*projcode == GCTP_UTM || *projcode == GCTP_SPCS)
1980 	    {
1981 		statmeta = EHgetmetavalue(metaptrs, "ZoneCode", utlstr);
1982 		if (statmeta == 0)
1983 		{
1984 		    *zonecode = atol(utlstr);
1985 		}
1986 		else
1987 		{
1988 		    status = -1;
1989 		    HEpush(DFE_GENAPP, "GDprojinfo", __FILE__, __LINE__);
1990 		    HEreport("Zone Code not defined for \"%s\".\n",
1991 			     gridname);
1992 		}
1993 	    }
1994 	}
1995 
1996 
1997 	/* Get projection parameters if requested */
1998 	/* -------------------------------------- */
1999 	if (projparm != NULL)
2000 	{
2001 
2002 	    /*
2003 	     * Note: No projection parameters for GEO, UTM, and State Code
2004 	     * projections
2005 	     */
2006 	    if (*projcode == GCTP_GEO || *projcode == GCTP_UTM ||
2007 		*projcode == GCTP_SPCS)
2008 	    {
2009 		for (i = 0; i < 13; i++)
2010 		{
2011 		    projparm[i] = 0.0;
2012 		}
2013 
2014 	    }
2015 	    else
2016 	    {
2017 		statmeta = EHgetmetavalue(metaptrs, "ProjParams", utlstr);
2018 
2019 		if (statmeta == 0)
2020 		{
2021 
2022 		    /* Build format string to read projection parameters */
2023 		    /* ------------------------------------------------- */
2024 		    strcpy(fmt, "%lf,");
2025 		    for (i = 1; i <= 11; i++)
2026 			strcat(fmt, "%lf,");
2027 		    strcat(fmt, "%lf");
2028 
2029 
2030 		    /* Read parameters from numeric list */
2031 		    /* --------------------------------- */
2032 		    sscanf(&utlstr[1], fmt,
2033 			   &projparm[0], &projparm[1],
2034 			   &projparm[2], &projparm[3],
2035 			   &projparm[4], &projparm[5],
2036 			   &projparm[6], &projparm[7],
2037 			   &projparm[8], &projparm[9],
2038 			   &projparm[10], &projparm[11],
2039 			   &projparm[12]);
2040 		}
2041 		else
2042 		{
2043 		    status = -1;
2044 		    HEpush(DFE_GENAPP, "GDprojinfo", __FILE__, __LINE__);
2045 		    HEreport("Projection parameters not defined for \"%s\".\n",
2046 			     gridname);
2047 
2048 		}
2049 	    }
2050 	}
2051 
2052 
2053 	/* Get spherecode if requested */
2054 	/* --------------------------- */
2055 	if (spherecode != NULL)
2056 	{
2057 	    *spherecode = 0;
2058 
2059 	    /* Note: Spherecode not defined for GEO projection */
2060 	    /* ----------------------------------------------- */
2061 	    if ((*projcode != GCTP_GEO))
2062 	    {
2063 		EHgetmetavalue(metaptrs, "SphereCode", utlstr);
2064 		if (statmeta == 0)
2065 		{
2066 		    *spherecode = atol(utlstr);
2067 		}
2068 	    }
2069 	}
2070 	free(metabuf);
2071 
2072     }
2073     free(utlstr);
2074     return (status);
2075 }
2076 
2077 
2078 
2079 /*----------------------------------------------------------------------------|
2080 |  BEGIN_PROLOG                                                               |
2081 |                                                                             |
2082 |  FUNCTION: GDorigininfo                                                     |
2083 |                                                                             |
2084 |  DESCRIPTION: Returns origin code                                           |
2085 |                                                                             |
2086 |                                                                             |
2087 |  Return Value    Type     Units     Description                             |
2088 |  ============   ======  =========   =====================================   |
2089 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
2090 |                                                                             |
2091 |  INPUTS:                                                                    |
2092 |  gridID         int32               Grid structure ID                       |
2093 |                                                                             |
2094 |                                                                             |
2095 |  OUTPUTS:                                                                   |
2096 |  origincode     int32               grid origin code                        |
2097 |                                                                             |
2098 |  NOTES:                                                                     |
2099 |                                                                             |
2100 |                                                                             |
2101 |   Date     Programmer   Description                                         |
2102 |  ======   ============  =================================================   |
2103 |  Jun 96   Joel Gales    Original Programmer                                 |
2104 |  Jan 97   Joel Gales    Check for metadata error status from EHgetmetavalue |
2105 |                                                                             |
2106 |  END_PROLOG                                                                 |
2107 -----------------------------------------------------------------------------*/
2108 intn
GDorigininfo(int32 gridID,int32 * origincode)2109 GDorigininfo(int32 gridID, int32 * origincode)
2110 {
2111     intn            i;		/* Loop index */
2112     intn            status = 0;	/* routine return status variable */
2113     intn            statmeta = 0;	/* EHgetmetavalue return status */
2114 
2115     int32           fid;	/* HDF-EOS file ID */
2116     int32           sdInterfaceID;	/* HDF SDS interface ID */
2117     int32           gdVgrpID;	/* Grid root Vgroup ID */
2118     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
2119 
2120 
2121     char           *metabuf;	/* Pointer to structural metadata (SM) */
2122     char           *metaptrs[2];/* Pointers to begin and end of SM section */
2123     char            gridname[80];	/* Grid Name */
2124     char           *utlstr;	/* Utility string */
2125 
2126     /* Allocate space for utility string */
2127     /* --------------------------------- */
2128     utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
2129     if(utlstr == NULL)
2130     {
2131 	HEpush(DFE_NOSPACE,"GDorigininfo", __FILE__, __LINE__);
2132 	return(-1);
2133     }
2134     /* Check Grid ID */
2135     /* ------------- */
2136     status = GDchkgdid(gridID, "GDorigininfo",
2137 		       &fid, &sdInterfaceID, &gdVgrpID);
2138 
2139 
2140     /* Initialize pixreg code to -1 (in case of error) */
2141     /* ----------------------------------------------- */
2142     *origincode = -1;
2143 
2144     if (status == 0)
2145     {
2146 	/* Set default origin code */
2147 	/* ----------------------- */
2148 	*origincode = 0;
2149 
2150 
2151 	/* Get grid name */
2152 	/* ------------- */
2153 	Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
2154 
2155 
2156 	/* Get pointers to grid structure section within SM */
2157 	/* ------------------------------------------------ */
2158 	metabuf = (char *) EHmetagroup(sdInterfaceID, gridname, "g",
2159 				       NULL, metaptrs);
2160 
2161 	if(metabuf == NULL)
2162 	{
2163 	    free(utlstr);
2164 	    return(-1);
2165 	}
2166 
2167 
2168 	statmeta = EHgetmetavalue(metaptrs, "GridOrigin", utlstr);
2169 
2170 	if (statmeta == 0)
2171 	{
2172 	    /*
2173 	     * If "GridOrigin" string found in metadata then convert to
2174 	     * numeric origin code (fixed added: Jan 97)
2175 	     */
2176 	    for (i = 0; i < sizeof(originNames); i++)
2177 	    {
2178 		if (strcmp(utlstr, originNames[i]) == 0)
2179 		{
2180 		    *origincode = i;
2181 		    break;
2182 		}
2183 	    }
2184 	}
2185 
2186 	free(metabuf);
2187     }
2188     free(utlstr);
2189     return (status);
2190 }
2191 
2192 
2193 
2194 
2195 
2196 
2197 /*----------------------------------------------------------------------------|
2198 |  BEGIN_PROLOG                                                               |
2199 |                                                                             |
2200 |  FUNCTION: GDpixreginfo                                                     |
2201 |                                                                             |
2202 |  DESCRIPTION:                                                               |
2203 |                                                                             |
2204 |                                                                             |
2205 |  Return Value    Type     Units     Description                             |
2206 |  ============   ======  =========   =====================================   |
2207 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
2208 |                                                                             |
2209 |  INPUTS:                                                                    |
2210 |  gridID         int32               Grid structure ID                       |
2211 |                                                                             |
2212 |                                                                             |
2213 |  OUTPUTS:                                                                   |
2214 |  pixregcode     int32               Pixel registration code                 |
2215 |                                                                             |
2216 |                                                                             |
2217 |  OUTPUTS:                                                                   |
2218 |             None                                                            |
2219 |                                                                             |
2220 |  NOTES:                                                                     |
2221 |                                                                             |
2222 |                                                                             |
2223 |   Date     Programmer   Description                                         |
2224 |  ======   ============  =================================================   |
2225 |  Jun 96   Joel Gales    Original Programmer                                 |
2226 |  Jan 97   Joel Gales    Check for metadata error status from EHgetmetavalue |
2227 |                                                                             |
2228 |  END_PROLOG                                                                 |
2229 -----------------------------------------------------------------------------*/
2230 intn
GDpixreginfo(int32 gridID,int32 * pixregcode)2231 GDpixreginfo(int32 gridID, int32 * pixregcode)
2232 {
2233     intn            i;		/* Loop index */
2234     intn            status = 0;	/* routine return status variable */
2235     intn            statmeta = 0;	/* EHgetmetavalue return status */
2236 
2237     int32           fid;	/* HDF-EOS file ID */
2238     int32           sdInterfaceID;	/* HDF SDS interface ID */
2239     int32           gdVgrpID;	/* Grid root Vgroup ID */
2240     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
2241 
2242 
2243     char           *metabuf;	/* Pointer to structural metadata (SM) */
2244     char           *metaptrs[2];/* Pointers to begin and end of SM section */
2245     char            gridname[80];	/* Grid Name */
2246     char           *utlstr;	/* Utility string */
2247 
2248     /* Allocate space for utility string */
2249     /* --------------------------------- */
2250     utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
2251     if(utlstr == NULL)
2252     {
2253 	HEpush(DFE_NOSPACE,"GDpixreginfo", __FILE__, __LINE__);
2254 	return(-1);
2255     }
2256     /* Check Grid ID */
2257     status = GDchkgdid(gridID, "GDpixreginfo",
2258 		       &fid, &sdInterfaceID, &gdVgrpID);
2259 
2260     /* Initialize pixreg code to -1 (in case of error) */
2261     *pixregcode = -1;
2262 
2263     if (status == 0)
2264     {
2265 	/* Set default pixreg code */
2266 	*pixregcode = 0;
2267 
2268 	/* Get grid name */
2269 	Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
2270 
2271 	/* Get pointers to grid structure section within SM */
2272 	metabuf = (char *) EHmetagroup(sdInterfaceID, gridname, "g",
2273 				       NULL, metaptrs);
2274 
2275 	if(metabuf == NULL)
2276 	{
2277 	    free(utlstr);
2278 	    return(-1);
2279 	}
2280 
2281 
2282 	statmeta = EHgetmetavalue(metaptrs, "PixelRegistration", utlstr);
2283 
2284 	if (statmeta == 0)
2285 	{
2286 	    /*
2287 	     * If "PixelRegistration" string found in metadata then convert
2288 	     * to numeric origin code (fixed added: Jan 97)
2289 	     */
2290 
2291 	    for (i = 0; i < sizeof(pixregNames); i++)
2292 	    {
2293 		if (strcmp(utlstr, pixregNames[i]) == 0)
2294 		{
2295 		    *pixregcode = i;
2296 		    break;
2297 		}
2298 	    }
2299 	}
2300 	free(metabuf);
2301     }
2302     free(utlstr);
2303     return (status);
2304 }
2305 
2306 
2307 
2308 /*----------------------------------------------------------------------------|
2309 |  BEGIN_PROLOG                                                               |
2310 |                                                                             |
2311 |  FUNCTION: GDcompinfo                                                       |
2312 |                                                                             |
2313 |  DESCRIPTION:                                                               |
2314 |                                                                             |
2315 |                                                                             |
2316 |  Return Value    Type     Units     Description                             |
2317 |  ============   ======  =========   =====================================   |
2318 |  status         intn                                                        |
2319 |                                                                             |
2320 |  INPUTS:                                                                    |
2321 |  gridID         int32                                                       |
2322 |  compcode       int32                                                       |
2323 |  compparm       intn                                                        |
2324 |                                                                             |
2325 |                                                                             |
2326 |  OUTPUTS:                                                                   |
2327 |             None                                                            |
2328 |                                                                             |
2329 |  NOTES:                                                                     |
2330 |                                                                             |
2331 |                                                                             |
2332 |   Date     Programmer   Description                                         |
2333 |  ======   ============  =================================================   |
2334 |  Oct 96   Joel Gales    Original Programmer                                 |
2335 |  Jan 97   Joel Gales    Check for metadata error status from EHgetmetavalue |
2336 |                                                                             |
2337 |  END_PROLOG                                                                 |
2338 -----------------------------------------------------------------------------*/
2339 intn
GDcompinfo(int32 gridID,char * fieldname,int32 * compcode,intn compparm[])2340 GDcompinfo(int32 gridID, char *fieldname, int32 * compcode, intn compparm[])
2341 {
2342     intn            i;		/* Loop index */
2343     intn            status = 0;	/* routine return status variable */
2344     intn            statmeta = 0;	/* EHgetmetavalue return status */
2345 
2346     int32           fid;	/* HDF-EOS file ID */
2347     int32           sdInterfaceID;	/* HDF SDS interface ID */
2348     int32           gdVgrpID;	/* Grid root Vgroup ID */
2349     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
2350 
2351 
2352     char           *metabuf;	/* Pointer to structural metadata (SM) */
2353     char           *metaptrs[2];/* Pointers to begin and end of SM section */
2354     char            gridname[80];	/* Grid Name */
2355     char           *utlstr;/* Utility string */
2356 
2357     /* Allocate space for utility string */
2358     /* --------------------------------- */
2359     utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
2360     if(utlstr == NULL)
2361     {
2362 	HEpush(DFE_NOSPACE,"GDcompinfo", __FILE__, __LINE__);
2363 	return(-1);
2364     }
2365     /* Check Grid ID */
2366     status = GDchkgdid(gridID, "GDcompinfo", &fid, &sdInterfaceID, &gdVgrpID);
2367 
2368 
2369     if (status == 0)
2370     {
2371 	/* Get grid name */
2372 	Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
2373 
2374 	/* Get pointers to "DataField" section within SM */
2375 	metabuf = (char *) EHmetagroup(sdInterfaceID, gridname, "g",
2376 				       "DataField", metaptrs);
2377 	if(metabuf == NULL)
2378 	{
2379 	    free(utlstr);
2380 	    return(-1);
2381 	}
2382 
2383 
2384 	/* Search for field */
2385 	sprintf(utlstr, "%s%s%s", "\"", fieldname, "\"\n");
2386 	metaptrs[0] = strstr(metaptrs[0], utlstr);
2387 
2388 
2389 	/* If field found and user wants compression code ... */
2390 	if (metaptrs[0] < metaptrs[1] && metaptrs[0] != NULL)
2391 	{
2392 	    if (compcode != NULL)
2393 	    {
2394 		/* Set endptr at end of field's definition entry */
2395 		metaptrs[1] = strstr(metaptrs[0], "\t\t\tEND_OBJECT");
2396 
2397 		/* Get compression type */
2398 		statmeta = EHgetmetavalue(metaptrs, "CompressionType", utlstr);
2399 
2400 		/*
2401 		 * Default is no compression if "CompressionType" string not
2402 		 * in metadata
2403 		 */
2404 		*compcode = HDFE_COMP_NONE;
2405 
2406 		/* If compression code is found ... */
2407 		if (statmeta == 0)
2408 		{
2409 		    /* Loop through compression types until match */
2410 		    for (i = 0; i < sizeof(HDFcomp); i++)
2411 		    {
2412 			if (strcmp(utlstr, HDFcomp[i]) == 0)
2413 			{
2414 			    *compcode = i;
2415 			    break;
2416 			}
2417 		    }
2418 		}
2419 	    }
2420 
2421 	    /* If user wants compression parameters ... */
2422 	    if (compparm != NULL && compcode != NULL)
2423 	    {
2424 		/* Initialize to zero */
2425 		for (i = 0; i < 4; i++)
2426 		{
2427 		    compparm[i] = 0.0;
2428 		}
2429 
2430 		/*
2431 		 * Get compression parameters if NBIT or DEFLATE compression
2432 		 */
2433 		if (*compcode == HDFE_COMP_NBIT)
2434 		{
2435 		    statmeta =
2436 			EHgetmetavalue(metaptrs, "CompressionParams", utlstr);
2437 		    if (statmeta == 0)
2438 		    {
2439 			sscanf(utlstr, "(%d,%d,%d,%d)",
2440 			       &compparm[0], &compparm[1],
2441 			       &compparm[2], &compparm[3]);
2442 		    }
2443 		    else
2444 		    {
2445 			status = -1;
2446 			HEpush(DFE_GENAPP, "GDcompinfo", __FILE__, __LINE__);
2447 			HEreport(
2448 				 "\"CompressionParams\" string not found in metadata.\n");
2449 		    }
2450 		}
2451 		else if (*compcode == HDFE_COMP_DEFLATE)
2452 		{
2453 		    statmeta =
2454 			EHgetmetavalue(metaptrs, "DeflateLevel", utlstr);
2455 		    if (statmeta == 0)
2456 		    {
2457 			sscanf(utlstr, "%d", &compparm[0]);
2458 		    }
2459 		    else
2460 		    {
2461 			status = -1;
2462 			HEpush(DFE_GENAPP, "GDcompinfo", __FILE__, __LINE__);
2463 			HEreport(
2464 			"\"DeflateLevel\" string not found in metadata.\n");
2465 		    }
2466 		}
2467 	    }
2468 	}
2469 	else
2470 	{
2471 	    HEpush(DFE_GENAPP, "GDcompinfo", __FILE__, __LINE__);
2472 	    HEreport("Fieldname \"%s\" not found.\n", fieldname);
2473 	}
2474 
2475 	free(metabuf);
2476 
2477     }
2478     free(utlstr);
2479     return (status);
2480 }
2481 
2482 
2483 
2484 
2485 
2486 
2487 /*----------------------------------------------------------------------------|
2488 |  BEGIN_PROLOG                                                               |
2489 |                                                                             |
2490 |  FUNCTION: GDfieldinfo                                                      |
2491 |                                                                             |
2492 |  DESCRIPTION: Retrieve information about a specific geolocation or data     |
2493 |                field in the grid.                                           |
2494 |                                                                             |
2495 |                                                                             |
2496 |  Return Value    Type     Units     Description                             |
2497 |  ============   ======  =========   =====================================   |
2498 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
2499 |                                                                             |
2500 |  INPUTS:                                                                    |
2501 |  gridID         int32               grid structure id                       |
2502 |  fieldname      char                name of field                           |
2503 |                                                                             |
2504 |                                                                             |
2505 |  OUTPUTS:                                                                   |
2506 |  rank           int32               rank of field (# of dims)               |
2507 |  dims           int32               field dimensions                        |
2508 |  numbertype     int32               field number type                       |
2509 |  dimlist        char                field dimension list                    |
2510 |                                                                             |
2511 |                                                                             |
2512 |  OUTPUTS:                                                                   |
2513 |             None                                                            |
2514 |                                                                             |
2515 |  NOTES:                                                                     |
2516 |                                                                             |
2517 |                                                                             |
2518 |   Date     Programmer   Description                                         |
2519 |  ======   ============  =================================================   |
2520 |  Jun 96   Joel Gales    Original Programmer                                 |
2521 |  Aug 96   Joel Gales    Make metadata ODL compliant                         |
2522 |  Jan 97   Joel Gales    Check for metadata error status from EHgetmetavalue |
2523 |  Feb 99   Abe Taaheri   Changed memcpy to memmove to avoid overlapping      |
2524 |                         problem when copying strings                        |
2525 |                                                                             |
2526 |  END_PROLOG                                                                 |
2527 -----------------------------------------------------------------------------*/
2528 intn
GDfieldinfo(int32 gridID,char * fieldname,int32 * rank,int32 dims[],int32 * numbertype,char * dimlist)2529 GDfieldinfo(int32 gridID, char *fieldname, int32 * rank, int32 dims[],
2530 	    int32 * numbertype, char *dimlist)
2531 
2532 {
2533     intn            i;		    /* Loop index */
2534     intn            status;	    /* routine return status variable */
2535     intn            statmeta = 0;   /* EHgetmetavalue return status */
2536 
2537     int32           fid;	    /* HDF-EOS file ID */
2538     int32           sdInterfaceID;  /* HDF SDS interface ID */
2539     int32           idOffset = GDIDOFFSET;  /* Grid ID offset */
2540     int32           ndims;	    /* Number of dimensions */
2541     int32           slen[8];	    /* Length of each entry in parsed string */
2542     int32           dum;	    /* Dummy variable */
2543     int32           xdim;	    /* X dim size */
2544     int32           ydim;	    /* Y dim size */
2545     int32           sdid;	    /* SDS id */
2546 
2547     char           *metabuf;	    /* Pointer to structural metadata (SM) */
2548     char           *metaptrs[2];    /* Pointers to begin and end of SM section */
2549     char            gridname[80];   /* Grid Name */
2550     char           *utlstr;	    /* Utility string */
2551     char           *ptr[8];	    /* String pointers for parsed string */
2552     char            dimstr[64];	    /* Individual dimension entry string */
2553 
2554 
2555     /* Allocate space for utility string */
2556     /* --------------------------------- */
2557     utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
2558     if(utlstr == NULL)
2559     {
2560 	HEpush(DFE_NOSPACE,"GDfieldinfo", __FILE__, __LINE__);
2561 	return(-1);
2562     }
2563     *rank = -1;
2564     *numbertype = -1;
2565 
2566     status = GDchkgdid(gridID, "GDfieldinfo", &fid, &sdInterfaceID, &dum);
2567 
2568     if (status == 0)
2569     {
2570 
2571 	Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
2572 
2573 	metabuf = (char *) EHmetagroup(sdInterfaceID, gridname, "g",
2574 				       "DataField", metaptrs);
2575 	if(metabuf == NULL)
2576 	{
2577 	    free(utlstr);
2578 	    return(-1);
2579 	}
2580 
2581 
2582 	/* Search for field */
2583 	sprintf(utlstr, "%s%s%s", "\"", fieldname, "\"\n");
2584 	metaptrs[0] = strstr(metaptrs[0], utlstr);
2585 
2586 	/* If field found ... */
2587 	if (metaptrs[0] < metaptrs[1] && metaptrs[0] != NULL)
2588 	{
2589 
2590 	    /* Set endptr at end of dimension definition entry */
2591 	    metaptrs[1] = strstr(metaptrs[0], "\t\t\tEND_OBJECT");
2592 
2593 	    /* Get DataType string */
2594 	    statmeta = EHgetmetavalue(metaptrs, "DataType", utlstr);
2595 
2596 	    /* Convert to numbertype code */
2597 	    if (statmeta == 0)
2598 		*numbertype = EHnumstr(utlstr);
2599 	    else
2600 	    {
2601 		status = -1;
2602 		HEpush(DFE_GENAPP, "GDfieldinfo", __FILE__, __LINE__);
2603 		HEreport("\"DataType\" string not found in metadata.\n");
2604 	    }
2605 
2606 	    /*
2607 	     * Get DimList string and trim off leading and trailing parens
2608 	     * "()"
2609 	     */
2610 	    statmeta = EHgetmetavalue(metaptrs, "DimList", utlstr);
2611 
2612 	    if (statmeta == 0)
2613 	    {
2614 		memmove(utlstr, utlstr + 1, strlen(utlstr) - 2);
2615 		utlstr[strlen(utlstr) - 2] = 0;
2616 
2617 		/* Parse trimmed DimList string and get rank */
2618 		ndims = EHparsestr(utlstr, ',', ptr, slen);
2619 		*rank = ndims;
2620 	    }
2621 	    else
2622 	    {
2623 		status = -1;
2624 		HEpush(DFE_GENAPP, "GDfieldinfo", __FILE__, __LINE__);
2625 		HEreport("\"DimList\" string not found in metadata.\n");
2626 	    }
2627 
2628 
2629 	    if (status == 0)
2630 	    {
2631 		status = GDgridinfo(gridID, &xdim, &ydim, NULL, NULL);
2632 
2633 		for (i = 0; i < ndims; i++)
2634 		{
2635 		    memcpy(dimstr, ptr[i] + 1, slen[i] - 2);
2636 		    dimstr[slen[i] - 2] = 0;
2637 
2638 		    if (strcmp(dimstr, "XDim") == 0)
2639 		    {
2640 			dims[i] = xdim;
2641 		    }
2642 		    else if (strcmp(dimstr, "YDim") == 0)
2643 		    {
2644 			dims[i] = ydim;
2645 		    }
2646 		    else
2647 		    {
2648 			dims[i] = GDdiminfo(gridID, dimstr);
2649 		    }
2650 
2651 
2652 		    if (dimlist != NULL)
2653 		    {
2654 			if (i == 0)
2655 			{
2656 			    dimlist[0] = 0;
2657 			}
2658 
2659 			if (i > 0)
2660 			{
2661 			    strcat(dimlist, ",");
2662 			}
2663 			strcat(dimlist, dimstr);
2664 		    }
2665 		}
2666 
2667 
2668 		if (dims[0] == 0)
2669 		{
2670 		    status = GDSDfldsrch(gridID, sdInterfaceID, fieldname,
2671 					 &sdid, &dum, &dum, &dum, dims,
2672 					 &dum);
2673 		}
2674 	    }
2675 	}
2676 
2677 	free(metabuf);
2678     }
2679 
2680     if (*rank == -1)
2681     {
2682 	status = -1;
2683 
2684 	HEpush(DFE_GENAPP, "GDfieldinfo", __FILE__, __LINE__);
2685 	HEreport("Fieldname \"%s\" not found.\n", fieldname);
2686     }
2687     free(utlstr);
2688     return (status);
2689 }
2690 
2691 
2692 
2693 
2694 
2695 
2696 /*----------------------------------------------------------------------------|
2697 |  BEGIN_PROLOG                                                               |
2698 |                                                                             |
2699 |  FUNCTION: GDdeffield                                                       |
2700 |                                                                             |
2701 |  DESCRIPTION: Defines a new data field within the grid.                     |
2702 |                                                                             |
2703 |                                                                             |
2704 |  Return Value    Type     Units     Description                             |
2705 |  ============   ======  =========   =====================================   |
2706 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
2707 |                                                                             |
2708 |  INPUTS:                                                                    |
2709 |  gridID         int32               grid structure ID                       |
2710 |  fieldname      char                fieldname                               |
2711 |  dimlist        char                Dimension list (comma-separated list)   |
2712 |  numbertype     int32               field type                              |
2713 |  merge          int32               merge code                              |
2714 |                                                                             |
2715 |                                                                             |
2716 |  OUTPUTS:                                                                   |
2717 |             None                                                            |
2718 |                                                                             |
2719 |  NOTES:                                                                     |
2720 |                                                                             |
2721 |                                                                             |
2722 |   Date     Programmer   Description                                         |
2723 |  ======   ============  =================================================   |
2724 |  Jun 96   Joel Gales    Original Programmer                                 |
2725 |  Aug 96   Joel Gales    Check name for ODL compliance                       |
2726 |  Sep 96   Joel Gales    Make string array "dimbuf" dynamic                  |
2727 |  Sep 96   Joel Gales    Add support for Block SOM (MISR)                    |
2728 |  Jan 97   Joel Gales    Add support for tiling                              |
2729 |  Feb 99   Abe Taaheri   Changed strcpy to memmove to avoid overlapping      |
2730 |                         problem when copying strings                        |
2731 |                                                                             |
2732 |  END_PROLOG                                                                 |
2733 -----------------------------------------------------------------------------*/
2734 intn
GDdeffield(int32 gridID,char * fieldname,char * dimlist,int32 numbertype,int32 merge)2735 GDdeffield(int32 gridID, char *fieldname, char *dimlist,
2736 	   int32 numbertype, int32 merge)
2737 
2738 {
2739     intn            i;		/* Loop index */
2740     intn            status;	/* routine return status variable */
2741     intn            found;	/* utility found flag */
2742     intn            foundNT = 0;/* found number type flag */
2743     intn            foundAllDim = 1;	/* found all dimensions flag */
2744     intn            first = 1;	/* first entry flag */
2745 
2746     int32           fid;	/* HDF-EOS file ID */
2747     int32           vgid;	/* Geo/Data field Vgroup ID */
2748     int32           sdInterfaceID;	/* HDF SDS interface ID */
2749     int32           sdid;	/* SDS object ID */
2750     int32           dimid;	/* SDS dimension ID */
2751     int32           gdVgrpID;	/* Grid root Vgroup ID */
2752     int32           dims[8];	/* Dimension size array */
2753     int32           dimsize;	/* Dimension size */
2754     int32           rank = 0;	/* Field rank */
2755     int32           slen[32];	/* String length array */
2756     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
2757     int32           compcode;	/* Compression code */
2758     int32           tilecode;	/* Tiling code */
2759     int32           chunkFlag;	/* Chunking (Tiling) flag */
2760     int32           gID;	/* GridID - offset */
2761     int32           xdim;	/* Grid X dimension */
2762     int32           ydim;	/* Grid Y dimension */
2763     int32           projcode;	/* Projection Code */
2764 
2765     float64         projparm[13];	/* Projection Parameters */
2766 
2767     char           *dimbuf;	/* Dimension buffer */
2768     char           *dimlist0;	/* Auxilliary dimension list */
2769     char           *comma;	/* Pointer to comma */
2770     char           *dimcheck;	/* Dimension check buffer */
2771     char            utlbuf[512];/* Utility buffer */
2772     char            utlbuf2[256];	/* Utility buffer 1 */
2773     char           *ptr[32];	/* String pointer array */
2774     char            gridname[80];	/* Grid name */
2775     char            parmbuf[128];	/* Parameter string buffer */
2776     char            errbuf1[128];	/* Error buffer 1 */
2777     char            errbuf2[128];	/* Error buffer 2 */
2778     static const char errmsg1[] = "Dimension: %d (size: %d) not divisible by ";
2779     /* Tiling  error message part 1 */
2780     static const char errmsg2[] = "tile dimension (size:  %d).\n";
2781     /* Tiling  error message part 2 */
2782     char            errmsg[128];/* Tiling error message */
2783 
2784     /* Valid number types */
2785     static const uint16 good_number[10] = {
2786         3, 4, 5, 6, 20, 21, 22, 23, 24, 25
2787     };
2788 
2789     comp_info       c_info;	/* Compression parameter structure */
2790 
2791     HDF_CHUNK_DEF   chunkDef;	/* Tiling structure */
2792 
2793 
2794 
2795     /* Setup error message strings */
2796     /* --------------------------- */
2797     strcpy(errbuf1, "GDXSDname array too small.\nPlease increase ");
2798     strcat(errbuf1, "size of HDFE_NAMBUFSIZE in \"HdfEosDef.h\".\n");
2799     strcpy(errbuf2, "GDXSDdims array too small.\nPlease increase ");
2800     strcat(errbuf2, "size of HDFE_DIMBUFSIZE in \"HdfEosDef.h\".\n");
2801 
2802 
2803     /* Build tiling dimension error message */
2804     /* ------------------------------------ */
2805     strcpy(errmsg, errmsg1);
2806     strcat(errmsg, errmsg2);
2807 
2808     /*
2809      * Check for proper grid ID and return HDF-EOS file ID, SDinterface ID,
2810      * and grid root Vgroup ID
2811      */
2812     status = GDchkgdid(gridID, "GDdefinefield",
2813 		       &fid, &sdInterfaceID, &gdVgrpID);
2814 
2815 
2816     if (status == 0)
2817     {
2818 	/* Remove offset from grid ID & get gridname */
2819 	gID = gridID % idOffset;
2820 	Vgetname(GDXGrid[gID].IDTable, gridname);
2821 
2822 
2823 	/* Allocate space for dimension buffer and auxilliary dimension list */
2824 	/* ----------------------------------------------------------------- */
2825 	dimbuf = (char *) calloc(strlen(dimlist) + 64, 1);
2826 	if(dimbuf == NULL)
2827 	{
2828 	    HEpush(DFE_NOSPACE,"GDdeffield", __FILE__, __LINE__);
2829 	    return(-1);
2830 	}
2831 	dimlist0 = (char *) calloc(strlen(dimlist) + 64, 1);
2832 	if(dimlist0 == NULL)
2833 	{
2834 	    HEpush(DFE_NOSPACE,"GDdeffield", __FILE__, __LINE__);
2835 	    free(dimbuf);
2836 	    return(-1);
2837 	}
2838 
2839 
2840 	/* Get Grid and Projection info */
2841 	/* ---------------------------- */
2842 	status = GDgridinfo(gridID, &xdim, &ydim, NULL, NULL);
2843 	status = GDprojinfo(gridID, &projcode, NULL, NULL, projparm);
2844 
2845 
2846 	/* Setup Block Dimension if "Blocked" SOM projection */
2847 	/* ------------------------------------------------- */
2848 	if (projcode == GCTP_SOM && (int32) projparm[11] != 0)
2849 	{
2850 	    dimsize = GDdiminfo(gridID, "SOMBlockDim");
2851 
2852 	    /* If "SOMBlockDim" not yet defined then do it */
2853 	    if (dimsize == -1)
2854 	    {
2855 		GDdefdim(gridID, "SOMBlockDim", (int32) projparm[11]);
2856 	    }
2857 
2858 	    /* If not 1D field then prepend to dimension list */
2859 	    if (strchr(dimlist, ',') != NULL)
2860 	    {
2861 		strcpy(dimbuf, "SOMBlockDim,");
2862 		strcat(dimbuf, dimlist);
2863 	    }
2864 	    else
2865 	    {
2866 		strcpy(dimbuf, dimlist);
2867 	    }
2868 	}
2869 	else
2870 	{
2871 	    /* If not "Blocked" SOM then just copy dim list to dim buffer */
2872 	    strcpy(dimbuf, dimlist);
2873 	}
2874 
2875 	/*
2876 	 * Copy dimension buffer to auxilliary dimlist and Append comma to
2877 	 * end of dimension list
2878 	 */
2879 	strcpy(dimlist0, dimbuf);
2880 	strcat(dimbuf, ",");
2881 
2882 
2883 	/* Find comma */
2884 	/* ---------- */
2885 	comma = strchr(dimbuf, ',');
2886 
2887 
2888 	/*
2889 	 * Loop through entries in dimension list to make sure they are
2890 	 * defined in grid
2891 	 */
2892 	while (comma != NULL)
2893 	{
2894 	    /* Copy dimension list entry to dimcheck */
2895 	    /* ------------------------------------- */
2896 	    dimcheck = (char *) calloc(comma - dimbuf + 1, 1);
2897 	    if(dimcheck == NULL)
2898 	    {
2899 		HEpush(DFE_NOSPACE,"GDdeffield", __FILE__, __LINE__);
2900 		free(dimbuf);
2901 		free(dimlist0);
2902 		return(-1);
2903 	    }
2904 	    memcpy(dimcheck, dimbuf, comma - dimbuf);
2905 
2906 
2907 	    /* Get Dimension Size */
2908 	    /* ------------------ */
2909 	    if (strcmp(dimcheck, "XDim") == 0)
2910 	    {
2911 		/* If "XDim" then use xdim value for grid definition */
2912 		/* ------------------------------------------------- */
2913 		dimsize = xdim;
2914 		found = 1;
2915 		dims[rank] = dimsize;
2916 		rank++;
2917 	    }
2918 	    else if (strcmp(dimcheck, "YDim") == 0)
2919 	    {
2920 		/* If "YDim" then use ydim value for grid definition */
2921 		/* ------------------------------------------------- */
2922 		dimsize = ydim;
2923 		found = 1;
2924 		dims[rank] = dimsize;
2925 		rank++;
2926 	    }
2927 	    else
2928 	    {
2929 		/* "Regular" Dimension */
2930 		/* ------------------- */
2931 		dimsize = GDdiminfo(gridID, dimcheck);
2932 		if (dimsize != -1)
2933 		{
2934 		    found = 1;
2935 		    dims[rank] = dimsize;
2936 		    rank++;
2937 		}
2938 		else
2939 		{
2940 		    found = 0;
2941 		}
2942 	    }
2943 
2944 
2945 	    /*
2946 	     * If dimension list entry not found - set error return status,
2947 	     * append name to utility buffer for error report
2948 	     */
2949 	    if (found == 0)
2950 	    {
2951 		status = -1;
2952 		foundAllDim = 0;
2953 		if (first == 1)
2954 		{
2955 		    strcpy(utlbuf, dimcheck);
2956 		}
2957 		else
2958 		{
2959 		    strcat(utlbuf, ",");
2960 		    strcat(utlbuf, dimcheck);
2961 		}
2962 		first = 0;
2963 	    }
2964 
2965 	    /*
2966 	     * Go to next dimension entry, find next comma, & free up
2967 	     * dimcheck buffer
2968 	     */
2969 	    memmove(dimbuf, comma + 1, strlen(comma)-1);
2970 	    dimbuf[strlen(comma)-1]= 0;
2971 	    comma = strchr(dimbuf, ',');
2972 	    free(dimcheck);
2973 	}
2974 	free(dimbuf);
2975 
2976 
2977 
2978 	/* Check fieldname length */
2979 	/* ---------------------- */
2980 	if (status == 0)
2981 	{
2982 /* if ((intn) strlen(fieldname) > MAX_NC_NAME - 7)
2983 ** this was changed because HDF4.1r3 made a change in the
2984 ** hlimits.h file.  We have notidfied NCSA and asked to have
2985 ** it made the same as in previous versions of HDF
2986 ** see ncr 26314.  DaW  Apr 2000
2987 */
2988             if((intn) strlen(fieldname) > (256 - 7))
2989 	    {
2990 		status = -1;
2991 		HEpush(DFE_GENAPP, "GDdefinefield", __FILE__, __LINE__);
2992 		HEreport("Fieldname \"%s\" too long.\n", fieldname);
2993 	    }
2994 	}
2995 
2996 
2997 
2998 	/* Check for valid numbertype */
2999 	/* -------------------------- */
3000 	if (status == 0)
3001 	{
3002 	    for (i = 0; i < 10; i++)
3003 	    {
3004 		if (numbertype == good_number[i])
3005 		{
3006 		    foundNT = 1;
3007 		    break;
3008 		}
3009 	    }
3010 
3011 	    if (foundNT == 0)
3012 	    {
3013 		HEpush(DFE_BADNUMTYPE, "GDdeffield", __FILE__, __LINE__);
3014 		HEreport("Invalid number type: %d (%s).\n",
3015 			 numbertype, fieldname);
3016 		status = -1;
3017 	    }
3018 	}
3019 
3020 
3021 	/* Define Field */
3022 	/* ------------ */
3023 	if (status == 0)
3024 	{
3025 	    /* Get Field Vgroup id, compresion code, & tiling code */
3026 	    /* -------------------------------------------------- */
3027 	    vgid = GDXGrid[gID].VIDTable[0];
3028 	    compcode = GDXGrid[gID].compcode;
3029 	    tilecode = GDXGrid[gID].tilecode;
3030 
3031 
3032 	    /* SDS Interface (Multi-dim fields) */
3033 	    /* -------------------------------- */
3034 
3035 
3036 	    /*
3037 	     * If rank is less than or equal to 3 (and greater than 1) and
3038 	     * AUTOMERGE is set and the first dimension is not appendable and
3039 	     * the compression code is set to none then ...
3040 	     */
3041 	    if (rank >= 2 && rank <= 3 && merge == HDFE_AUTOMERGE &&
3042 		dims[0] != 0 && compcode == HDFE_COMP_NONE &&
3043 		tilecode == HDFE_NOTILE)
3044 	    {
3045 
3046 		/* Find first empty slot in external combination array */
3047 		/* --------------------------------------------------- */
3048 		i = 0;
3049 		while (GDXSDcomb[5 * i] != 0)
3050 		{
3051 		    i++;
3052 		}
3053 
3054 		/*
3055 		 * Store dimensions, grid root Vgroup ID, and number type in
3056 		 * external combination array "GDXSDcomb"
3057 		 */
3058 		if (rank == 2)
3059 		{
3060 		    /* If 2-dim field then set lowest dimension to 1 */
3061 		    /* --------------------------------------------- */
3062 		    GDXSDcomb[5 * i] = 1;
3063 		    GDXSDcomb[5 * i + 1] = dims[0];
3064 		    GDXSDcomb[5 * i + 2] = dims[1];
3065 		}
3066 		else
3067 		{
3068 		    GDXSDcomb[5 * i] = dims[0];
3069 		    GDXSDcomb[5 * i + 1] = dims[1];
3070 		    GDXSDcomb[5 * i + 2] = dims[2];
3071 		}
3072 
3073 		GDXSDcomb[5 * i + 3] = gdVgrpID;
3074 		GDXSDcomb[5 * i + 4] = numbertype;
3075 
3076 
3077 		/* Concatanate fieldname with combined name string */
3078 		/* ----------------------------------------------- */
3079 		if ((intn) strlen(GDXSDname) +
3080 		    (intn) strlen(fieldname) + 2 < HDFE_NAMBUFSIZE)
3081 		{
3082 		    strcat(GDXSDname, fieldname);
3083 		    strcat(GDXSDname, ",");
3084 		}
3085 		else
3086 		{
3087 		    /* GDXSDname array too small! */
3088 		    /* -------------------------- */
3089 		    HEpush(DFE_GENAPP, "GDdefinefield",
3090 			   __FILE__, __LINE__);
3091 		    HEreport(errbuf1);
3092 		    status = -1;
3093 		    free(dimlist0);
3094 		    return (status);
3095 		}
3096 
3097 
3098 		/*
3099 		 * If 2-dim field then set lowest dimension (in 3-dim array)
3100 		 * to "ONE"
3101 		 */
3102 		if (rank == 2)
3103 		{
3104 		    if ((intn) strlen(GDXSDdims) + 5 < HDFE_DIMBUFSIZE)
3105 		    {
3106 			strcat(GDXSDdims, "ONE,");
3107 		    }
3108 		    else
3109 		    {
3110 			/* GDXSDdims array too small! */
3111 			/* -------------------------- */
3112 			HEpush(DFE_GENAPP, "GDdefinefield",
3113 			       __FILE__, __LINE__);
3114 			HEreport(errbuf2);
3115 			status = -1;
3116 			free(dimlist0);
3117 			return (status);
3118 		    }
3119 		}
3120 
3121 
3122 		/*
3123 		 * Concatanate field dimlist to merged dimlist and separate
3124 		 * fields with semi-colon
3125 		 */
3126 		if ((intn) strlen(GDXSDdims) +
3127 		    (intn) strlen(dimlist0) + 2 < HDFE_DIMBUFSIZE)
3128 		{
3129 		    strcat(GDXSDdims, dimlist0);
3130 		    strcat(GDXSDdims, ";");
3131 		}
3132 		else
3133 		{
3134 		    /* GDXSDdims array too small! */
3135 		    /* -------------------------- */
3136 		    HEpush(DFE_GENAPP, "GDdefinefield",
3137 			   __FILE__, __LINE__);
3138 		    HEreport(errbuf2);
3139 		    status = -1;
3140 		    free(dimlist0);
3141 		    return (status);
3142 		}
3143 
3144 	    }			/* End Multi-Dim Merge Section */
3145 	    else
3146 	    {
3147 
3148 		/* Multi-Dim No Merge Section */
3149 		/* ========================== */
3150 
3151 
3152 		/* Check that field dims are divisible by tile dims */
3153 		/* ------------------------------------------------ */
3154 		if (tilecode == HDFE_TILE)
3155 		{
3156 		    for (i = 0; i < GDXGrid[gID].tilerank; i++)
3157 		    {
3158 			if ((dims[i] % GDXGrid[gID].tiledims[i]) != 0)
3159 			{
3160 			    HEpush(DFE_GENAPP, "GDdeffield",
3161 				   __FILE__, __LINE__);
3162 			    HEreport(errmsg,
3163 				     i, dims[i], GDXGrid[gID].tiledims[0]);
3164 			    status = -1;
3165 			}
3166 		    }
3167 
3168 		    if (status == -1)
3169 		    {
3170 			free(dimlist0);
3171 			return (status);
3172 		    }
3173 		}
3174 
3175 
3176 		/* Create SDS dataset */
3177 		/* ------------------ */
3178 		sdid = SDcreate(sdInterfaceID, fieldname,
3179 				numbertype, rank, dims);
3180 
3181 
3182 		/* Store Dimension Names in SDS */
3183 		/* ---------------------------- */
3184 		rank = EHparsestr(dimlist0, ',', ptr, slen);
3185 		for (i = 0; i < rank; i++)
3186 		{
3187 		    /* Dimension name = Swathname:Dimname */
3188 		    /* ---------------------------------- */
3189 		    memcpy(utlbuf, ptr[i], slen[i]);
3190 		    utlbuf[slen[i]] = 0;
3191 		    strcat(utlbuf, ":");
3192 		    strcat(utlbuf, gridname);
3193 
3194 		    dimid = SDgetdimid(sdid, i);
3195 		    SDsetdimname(dimid, utlbuf);
3196 		}
3197 
3198 
3199 		/* Setup Compression */
3200 		/* ----------------- */
3201 		if (compcode == HDFE_COMP_NBIT)
3202 		{
3203 		    c_info.nbit.nt = numbertype;
3204 		    c_info.nbit.sign_ext = GDXGrid[gID].compparm[0];
3205 		    c_info.nbit.fill_one = GDXGrid[gID].compparm[1];
3206 		    c_info.nbit.start_bit = GDXGrid[gID].compparm[2];
3207 		    c_info.nbit.bit_len = GDXGrid[gID].compparm[3];
3208 		}
3209 		else if (compcode == HDFE_COMP_SKPHUFF)
3210 		{
3211 		    c_info.skphuff.skp_size = (intn) DFKNTsize(numbertype);
3212 		}
3213 		else if (compcode == HDFE_COMP_DEFLATE)
3214 		{
3215 		    c_info.deflate.level = GDXGrid[gID].compparm[0];
3216 		}
3217 
3218 
3219 		/* If field is compressed w/o tiling then call SDsetcompress */
3220 		/* --------------------------------------------------------- */
3221 		if (compcode != HDFE_COMP_NONE && tilecode == HDFE_NOTILE)
3222 		{
3223 		    status = SDsetcompress(sdid, (comp_coder_t) compcode, &c_info);
3224 		}
3225 
3226 
3227 		/* Setup Tiling */
3228 		/* ------------ */
3229 		if (tilecode == HDFE_TILE)
3230 		{
3231 		    /* Tiling without Compression */
3232 		    /* -------------------------- */
3233 		    if (compcode == HDFE_COMP_NONE)
3234 		    {
3235 
3236 			/* Setup chunk lengths */
3237 			/* ------------------- */
3238 			for (i = 0; i < GDXGrid[gID].tilerank; i++)
3239 			{
3240 			    chunkDef.chunk_lengths[i] =
3241 				GDXGrid[gID].tiledims[i];
3242 			}
3243 
3244 			chunkFlag = HDF_CHUNK;
3245 		    }
3246 
3247 		    /* Tiling with Compression */
3248 		    /* ----------------------- */
3249 		    else
3250 		    {
3251 			/* Setup chunk lengths */
3252 			/* ------------------- */
3253 			for (i = 0; i < GDXGrid[gID].tilerank; i++)
3254 			{
3255 			    chunkDef.comp.chunk_lengths[i] =
3256 				GDXGrid[gID].tiledims[i];
3257 			}
3258 
3259 
3260 			/* Setup chunk flag & chunk compression type */
3261 			/* ----------------------------------------- */
3262 			chunkFlag = HDF_CHUNK | HDF_COMP;
3263 			chunkDef.comp.comp_type = compcode;
3264 
3265 
3266 			/* Setup chunk compression parameters */
3267 			/* ---------------------------------- */
3268 			if (compcode == HDFE_COMP_SKPHUFF)
3269 			{
3270 			    chunkDef.comp.cinfo.skphuff.skp_size =
3271 				c_info.skphuff.skp_size;
3272 			}
3273 			else if (compcode == HDFE_COMP_DEFLATE)
3274 			{
3275 			    chunkDef.comp.cinfo.deflate.level =
3276 				c_info.deflate.level;
3277 			}
3278 		    }
3279 
3280 		    /* Call SDsetchunk routine */
3281 		    /* ----------------------- */
3282 		    status = SDsetchunk(sdid, chunkDef, chunkFlag);
3283 		}
3284 
3285 
3286 		/* Attach to Vgroup */
3287 		/* ---------------- */
3288 		Vaddtagref(vgid, DFTAG_NDG, SDidtoref(sdid));
3289 
3290 
3291 		/* Store SDS dataset IDs */
3292 		/* --------------------- */
3293 
3294 		/* Allocate space for the SDS ID array */
3295 		/* ----------------------------------- */
3296 		if (GDXGrid[gID].nSDS > 0)
3297 		{
3298 		    /* Array already exists therefore reallocate */
3299 		    /* ----------------------------------------- */
3300 		    GDXGrid[gID].sdsID = (int32 *)
3301 			realloc((void *) GDXGrid[gID].sdsID,
3302 				(GDXGrid[gID].nSDS + 1) * 4);
3303 		    if(GDXGrid[gID].sdsID == NULL)
3304 		    {
3305 			HEpush(DFE_NOSPACE,"GDdeffield", __FILE__, __LINE__);
3306 			free(dimlist0);
3307 			return(-1);
3308 		    }
3309 		}
3310 		else
3311 		{
3312 		    /* Array does not exist */
3313 		    /* -------------------- */
3314 		    GDXGrid[gID].sdsID = (int32 *) calloc(1, 4);
3315 		    if(GDXGrid[gID].sdsID == NULL)
3316 		    {
3317 			HEpush(DFE_NOSPACE,"GDdeffield", __FILE__, __LINE__);
3318 			free(dimlist0);
3319 			return(-1);
3320 		    }
3321 		}
3322 
3323 		/* Store SDS ID in array & increment count */
3324 		/* --------------------------------------- */
3325 		GDXGrid[gID].sdsID[GDXGrid[gID].nSDS] = sdid;
3326 		GDXGrid[gID].nSDS++;
3327 
3328 	    }
3329 
3330 
3331 	    /* Setup metadata string */
3332 	    /* --------------------- */
3333 	    sprintf(utlbuf, "%s%s%s", fieldname, ":", dimlist0);
3334 
3335 
3336 	    /* Setup compression metadata */
3337 	    /* -------------------------- */
3338 	    if (compcode != HDFE_COMP_NONE)
3339 	    {
3340 		sprintf(utlbuf2,
3341 			"%s%s",
3342 			":\n\t\t\t\tCompressionType=", HDFcomp[compcode]);
3343 
3344 		switch (compcode)
3345 		{
3346 		case HDFE_COMP_NBIT:
3347 
3348 		    sprintf(parmbuf,
3349 			    "%s%d,%d,%d,%d%s",
3350 			    "\n\t\t\t\tCompressionParams=(",
3351 			    GDXGrid[gID].compparm[0],
3352 			    GDXGrid[gID].compparm[1],
3353 			    GDXGrid[gID].compparm[2],
3354 			    GDXGrid[gID].compparm[3], ")");
3355 		    strcat(utlbuf2, parmbuf);
3356 		    break;
3357 
3358 
3359 		case HDFE_COMP_DEFLATE:
3360 
3361 		    sprintf(parmbuf,
3362 			    "%s%d",
3363 			    "\n\t\t\t\tDeflateLevel=",
3364 			    GDXGrid[gID].compparm[0]);
3365 		    strcat(utlbuf2, parmbuf);
3366 		    break;
3367 		}
3368 		strcat(utlbuf, utlbuf2);
3369 	    }
3370 
3371 
3372 
3373 
3374 	    /* Setup tiling metadata */
3375 	    /* --------------------- */
3376 	    if (tilecode == HDFE_TILE)
3377 	    {
3378 		if (compcode == HDFE_COMP_NONE)
3379 		{
3380 		    sprintf(utlbuf2, "%s%d",
3381 			    ":\n\t\t\t\tTilingDimensions=(",
3382 			    (int)GDXGrid[gID].tiledims[0]);
3383 		}
3384 		else
3385 		{
3386 		    sprintf(utlbuf2, "%s%d",
3387 			    "\n\t\t\t\tTilingDimensions=(",
3388 			    (int)GDXGrid[gID].tiledims[0]);
3389 		}
3390 
3391 		for (i = 1; i < GDXGrid[gID].tilerank; i++)
3392 		{
3393 		    sprintf(parmbuf, ",%d", (int)GDXGrid[gID].tiledims[i]);
3394 		    strcat(utlbuf2, parmbuf);
3395 		}
3396 		strcat(utlbuf2, ")");
3397 		strcat(utlbuf, utlbuf2);
3398 	    }
3399 
3400 
3401 	    /* Insert field metadata within File Structural Metadata */
3402 	    /* ----------------------------------------------------- */
3403 	    status = EHinsertmeta(sdInterfaceID, gridname, "g", 4L,
3404 				  utlbuf, &numbertype);
3405 
3406 	}
3407 	free(dimlist0);
3408 
3409     }
3410 
3411     /* If all dimensions not found then report error */
3412     /* --------------------------------------------- */
3413     if (foundAllDim == 0)
3414     {
3415 	HEpush(DFE_GENAPP, "GDdeffield", __FILE__, __LINE__);
3416 	HEreport("Dimension(s): \"%s\" not found (%s).\n",
3417 		 utlbuf, fieldname);
3418 	status = -1;
3419     }
3420 
3421     return (status);
3422 }
3423 
3424 
3425 
3426 
3427 /*----------------------------------------------------------------------------|
3428 |  BEGIN_PROLOG                                                               |
3429 |                                                                             |
3430 |  FUNCTION: GDwritefieldmeta                                                 |
3431 |                                                                             |
3432 |  DESCRIPTION: Writes field meta data for an existing grid field not         |
3433 |               defined within the grid API routine "GDdeffield".             |
3434 |                                                                             |
3435 |  Return Value    Type     Units     Description                             |
3436 |  ============   ======  =========   =====================================   |
3437 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
3438 |                                                                             |
3439 |  INPUTS:                                                                    |
3440 |  gridID         int32               grid structure ID                       |
3441 |  fieldname      char                fieldname                               |
3442 |  dimlist        char                Dimension list (comma-separated list)   |
3443 |  numbertype     int32               field type                              |
3444 |                                                                             |
3445 |                                                                             |
3446 |  OUTPUTS:                                                                   |
3447 |             None                                                            |
3448 |                                                                             |
3449 |  NOTES:                                                                     |
3450 |                                                                             |
3451 |                                                                             |
3452 |   Date     Programmer   Description                                         |
3453 |  ======   ============  =================================================   |
3454 |  Jun 96   Joel Gales    Original Programmer                                 |
3455 |                                                                             |
3456 |  END_PROLOG                                                                 |
3457 -----------------------------------------------------------------------------*/
3458 intn
GDwritefieldmeta(int32 gridID,char * fieldname,char * dimlist,int32 numbertype)3459 GDwritefieldmeta(int32 gridID, char *fieldname, char *dimlist,
3460 		 int32 numbertype)
3461 {
3462     intn            status = 0;	/* routine return status variable */
3463 
3464     int32           sdInterfaceID;	/* HDF SDS interface ID */
3465     int32           dum;	/* dummy variable */
3466     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
3467 
3468     char            utlbuf[256];/* Utility buffer */
3469     char            gridname[80];	/* Grid name */
3470 
3471 
3472     status = GDchkgdid(gridID, "GDwritefieldmeta", &dum, &sdInterfaceID,
3473 		       &dum);
3474 
3475     if (status == 0)
3476     {
3477 	sprintf(utlbuf, "%s%s%s", fieldname, ":", dimlist);
3478 
3479 	Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
3480 	status = EHinsertmeta(sdInterfaceID, gridname, "g", 4L,
3481 			      utlbuf, &numbertype);
3482     }
3483     return (status);
3484 }
3485 
3486 
3487 
3488 
3489 /*----------------------------------------------------------------------------|
3490 |  BEGIN_PROLOG                                                               |
3491 |                                                                             |
3492 |  FUNCTION: GDSDfldsrch                                                      |
3493 |                                                                             |
3494 |  DESCRIPTION: Retrieves information from SDS fields                         |
3495 |                                                                             |
3496 |                                                                             |
3497 |  Return Value    Type     Units     Description                             |
3498 |  ============   ======  =========   =====================================   |
3499 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
3500 |                                                                             |
3501 |  INPUTS:                                                                    |
3502 |  gridID         int32               grid structure ID                       |
3503 |  sdInterfaceID  int32               SD interface ID                         |
3504 |  fieldname      char                field name                              |
3505 |                                                                             |
3506 |                                                                             |
3507 |  OUTPUTS:                                                                   |
3508 |  sdid           int32               SD element ID                           |
3509 |  rankSDS        int32               Rank of SDS                             |
3510 |  rankFld        int32               True rank of field (merging)            |
3511 |  offset         int32               Offset of field within merged field     |
3512 |  dims           int32               Dimensions of field                     |
3513 |  solo           int32               Solo field flag                         |
3514 |                                                                             |
3515 |  NOTES:                                                                     |
3516 |                                                                             |
3517 |                                                                             |
3518 |   Date     Programmer   Description                                         |
3519 |  ======   ============  =================================================   |
3520 |  Jun 96   Joel Gales    Original Programmer                                 |
3521 |  Aug 96   Joel Gales    Make metadata ODL compliant                         |
3522 |                                                                             |
3523 |  END_PROLOG                                                                 |
3524 -----------------------------------------------------------------------------*/
3525 static intn
GDSDfldsrch(int32 gridID,int32 sdInterfaceID,const char * fieldname,int32 * sdid,int32 * rankSDS,int32 * rankFld,int32 * offset,int32 dims[],int32 * solo)3526 GDSDfldsrch(int32 gridID, int32 sdInterfaceID, const char *fieldname,
3527             int32 * sdid, int32 * rankSDS, int32 * rankFld, int32 * offset,
3528             int32 dims[], int32 * solo)
3529 {
3530     intn            i;		/* Loop index */
3531     intn            status = -1;/* routine return status variable */
3532 
3533     int32           gID;	/* GridID - offset */
3534     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
3535     int32           dum;	/* Dummy variable */
3536     int32           dums[128];	/* Dummy array */
3537     int32           attrIndex;	/* Attribute index */
3538 
3539     char            name[2048];	/* Merged-Field Names */
3540     char            gridname[80];	/* Grid Name */
3541     char           *utlstr;/* Utility string */
3542     char           *metabuf;	/* Pointer to structural metadata (SM) */
3543     char           *metaptrs[2];/* Pointers to begin and end of SM section */
3544     char           *oldmetaptr;	/* Pointer within SM section */
3545     char           *metaptr;	/* Pointer within SM section */
3546 
3547 
3548     /* Allocate space for utility string */
3549     /* --------------------------------- */
3550     utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
3551     if(utlstr == NULL)
3552     {
3553 	HEpush(DFE_NOSPACE,"GDSDfldsrch", __FILE__, __LINE__);
3554 	return(-1);
3555     }
3556     /* Set solo flag to 0 (no) */
3557     /* ----------------------- */
3558     *solo = 0;
3559 
3560 
3561     /* Compute "reduced" grid ID */
3562     /* ------------------------- */
3563     gID = gridID % idOffset;
3564 
3565 
3566     /* Loop through all SDSs in grid */
3567     /* ----------------------------- */
3568     for (i = 0; i < GDXGrid[gID].nSDS; i++)
3569     {
3570 	/* If active SDS ... */
3571 	/* ----------------- */
3572 	if (GDXGrid[gID].sdsID[i] != 0)
3573 	{
3574 	    /* Get SDS ID, name, rankSDS, and dimensions */
3575 	    /* ----------------------------------------- */
3576 	    *sdid = GDXGrid[gID].sdsID[i];
3577 	    SDgetinfo(*sdid, name, rankSDS, dims, &dum, &dum);
3578 	    *rankFld = *rankSDS;
3579 
3580 
3581 	    /* If merged field ... */
3582 	    /* ------------------- */
3583 	    if (strstr(name, "MRGFLD_") == &name[0])
3584 	    {
3585 		/* Get grid name */
3586 		/* ------------- */
3587 		Vgetname(GDXGrid[gID].IDTable, gridname);
3588 
3589 
3590 		/* Get pointers to "MergedFields" section within SM */
3591 		/* ------------------------------------------------ */
3592 		metabuf = (char *) EHmetagroup(sdInterfaceID, gridname, "g",
3593 					       "MergedFields", metaptrs);
3594 		if(metabuf == NULL)
3595 		{
3596 		    free(utlstr);
3597 		    return(-1);
3598 		}
3599 
3600 
3601 		/* Initialize metaptr to beg. of section */
3602 		/* ------------------------------------- */
3603 		metaptr = metaptrs[0];
3604 
3605 
3606 		/* Store metaptr in order to recover */
3607 		/* --------------------------------- */
3608 		oldmetaptr = metaptr;
3609 
3610 
3611 		/* Search for Merged field name */
3612 		/* ---------------------------- */
3613 		sprintf(utlstr, "%s%s%s", "MergedFieldName=\"",
3614 			name, "\"\n");
3615 		metaptr = strstr(metaptr, utlstr);
3616 
3617 
3618 		/* If not found check for old metadata */
3619 		/* ----------------------------------- */
3620 		if (metaptr == NULL)
3621 		{
3622 		    sprintf(utlstr, "%s%s%s", "OBJECT=\"", name, "\"\n");
3623 		    metaptr = strstr(oldmetaptr, utlstr);
3624 		}
3625 
3626 
3627 		/* Get field list and strip off leading and trailing quotes */
3628 		/* -------------------------------------------------------- */
3629 		EHgetmetavalue(metaptrs, "FieldList", name);
3630 		memmove(name, name + 1, strlen(name) - 2);
3631 		name[strlen(name) - 2] = 0;
3632 
3633 
3634 		/* Search for desired field within merged field list */
3635 		/* ------------------------------------------------- */
3636 		sprintf(utlstr, "%s%s%s", "\"", fieldname, "\"");
3637 		dum = EHstrwithin(utlstr, name, ',');
3638 
3639 		free(metabuf);
3640 	    }
3641 	    else
3642 	    {
3643 		/* If solo (unmerged) check if SDS name matches fieldname */
3644 		/* ------------------------------------------------------ */
3645 		dum = EHstrwithin(fieldname, name, ',');
3646 		if (dum != -1)
3647 		{
3648 		    *solo = 1;
3649 		    *offset = 0;
3650 		}
3651 	    }
3652 
3653 
3654 
3655 	    /* If field found ... */
3656 	    /* ------------------ */
3657 	    if (dum != -1)
3658 	    {
3659 		status = 0;
3660 
3661 		/* If merged field ... */
3662 		/* ------------------- */
3663 		if (*solo == 0)
3664 		{
3665 		    /* Get "Field Offsets" SDS attribute index */
3666 		    /* --------------------------------------- */
3667 		    attrIndex = SDfindattr(*sdid, "Field Offsets");
3668 
3669 		    /*
3670 		     * If attribute exists then get offset of desired field
3671 		     * within merged field
3672 		     */
3673 		    if (attrIndex != -1)
3674 		    {
3675 			SDreadattr(*sdid, attrIndex, (VOIDP) dums);
3676 			*offset = dums[dum];
3677 		    }
3678 
3679 
3680 		    /* Get "Field Dims" SDS attribute index */
3681 		    /* ------------------------------------ */
3682 		    attrIndex = SDfindattr(*sdid, "Field Dims");
3683 
3684 		    /*
3685 		     * If attribute exists then get 0th dimension of desired
3686 		     * field within merged field
3687 		     */
3688 		    if (attrIndex != -1)
3689 		    {
3690 			SDreadattr(*sdid, attrIndex, (VOIDP) dums);
3691 			dims[0] = dums[dum];
3692 
3693 			/* If this dimension = 1 then field is really 2 dim */
3694 			/* ------------------------------------------------ */
3695 			if (dums[dum] == 1)
3696 			{
3697 			    *rankFld = 2;
3698 			}
3699 		    }
3700 		}
3701 
3702 
3703 		/* Break out of SDS loop */
3704 		/* --------------------- */
3705 		break;
3706 	    }			/* End of found field section */
3707 	}
3708 	else
3709 	{
3710 	    /* First non-active SDS signifies no more, break out of SDS loop */
3711 	    /* ------------------------------------------------------------- */
3712 	    break;
3713 	}
3714     }
3715     free(utlstr);
3716     return (status);
3717 }
3718 
3719 
3720 
3721 
3722 /*----------------------------------------------------------------------------|
3723 |  BEGIN_PROLOG                                                               |
3724 |                                                                             |
3725 |  FUNCTION: GDwrrdfield                                                      |
3726 |                                                                             |
3727 |  DESCRIPTION: Writes/Reads fields                                           |
3728 |                                                                             |
3729 |                                                                             |
3730 |  Return Value    Type     Units     Description                             |
3731 |  ============   ======  =========   =====================================   |
3732 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
3733 |                                                                             |
3734 |  INPUTS:                                                                    |
3735 |  gridID         int32               grid structure ID                       |
3736 |  fieldname      char                fieldname                               |
3737 |  code           char                Write/Read code (w/r)                   |
3738 |  start          int32               start array                             |
3739 |  stride         int32               stride array                            |
3740 |  edge           int32               edge array                              |
3741 |  datbuf         void                data buffer for read                    |
3742 |                                                                             |
3743 |                                                                             |
3744 |  OUTPUTS:                                                                   |
3745 |  datbuf         void                data buffer for write                   |
3746 |                                                                             |
3747 |                                                                             |
3748 |  NOTES:                                                                     |
3749 |                                                                             |
3750 |                                                                             |
3751 |   Date     Programmer   Description                                         |
3752 |  ======   ============  =================================================   |
3753 |  Jun 96   Joel Gales    Original Programmer                                 |
3754 |  Feb 97   Joel Gales    Stride = 1 HDF compression workaround               |
3755 |                                                                             |
3756 |  END_PROLOG                                                                 |
3757 -----------------------------------------------------------------------------*/
3758 static intn
GDwrrdfield(int32 gridID,char * fieldname,char * code,int32 start[],int32 stride[],int32 edge[],VOIDP datbuf)3759 GDwrrdfield(int32 gridID, char *fieldname, char *code,
3760 	    int32 start[], int32 stride[], int32 edge[], VOIDP datbuf)
3761 
3762 {
3763     intn            i;		/* Loop index */
3764     intn            status = 0;	/* routine return status variable */
3765 
3766     int32           fid;	/* HDF-EOS file ID */
3767     int32           sdInterfaceID;	/* HDF SDS interface ID */
3768     int32           sdid;	/* SDS ID */
3769     int32           dum;	/* Dummy variable */
3770     int32           rankSDS;	/* Rank of SDS */
3771     int32           rankFld;	/* Rank of field */
3772 
3773     int32           offset[8];	/* I/O offset (start) */
3774     int32           incr[8];	/* I/O increment (stride) */
3775     int32           count[8];	/* I/O count (edge) */
3776     int32           dims[8];	/* Field/SDS dimensions */
3777     int32           mrgOffset;	/* Merged field offset */
3778     int32           strideOne;	/* Strides = 1 flag */
3779 
3780 
3781     /* Check for valid grid ID */
3782     /* ----------------------- */
3783     status = GDchkgdid(gridID, "GDwrrdfield", &fid, &sdInterfaceID, &dum);
3784 
3785 
3786     if (status == 0)
3787     {
3788 	/* Check that field exists */
3789 	/* ----------------------- */
3790 	status = GDfieldinfo(gridID, fieldname, &rankSDS, dims, &dum, NULL);
3791 
3792 
3793 	if (status != 0)
3794 	{
3795 	    HEpush(DFE_GENAPP, "GDwrrdfield", __FILE__, __LINE__);
3796 	    HEreport("Fieldname \"%s\" does not exist.\n", fieldname);
3797 	    status = -1;
3798 
3799 	}
3800 
3801 
3802 	if (status == 0)
3803 	{
3804 	    status = GDSDfldsrch(gridID, sdInterfaceID, fieldname, &sdid,
3805 				 &rankSDS, &rankFld, &mrgOffset, dims, &dum);
3806 
3807 
3808 	    /* Set I/O offset Section */
3809 	    /* ---------------------- */
3810 
3811 	    /*
3812 	     * If start == NULL (default) set I/O offset of 0th field to
3813 	     * offset within merged field (if any) and the rest to 0
3814 	     */
3815 	    if (start == NULL)
3816 	    {
3817 		for (i = 0; i < rankSDS; i++)
3818 		{
3819 		    offset[i] = 0;
3820 		}
3821 		offset[0] = mrgOffset;
3822 	    }
3823 	    else
3824 	    {
3825 		/*
3826 		 * ... otherwise set I/O offset to user values, adjusting the
3827 		 * 0th field with the merged field offset (if any)
3828 		 */
3829 		if (rankFld == rankSDS)
3830 		{
3831 		    for (i = 0; i < rankSDS; i++)
3832 		    {
3833 			offset[i] = start[i];
3834 		    }
3835 		    offset[0] += mrgOffset;
3836 		}
3837 		else
3838 		{
3839 		    /*
3840 		     * If field really 2-dim merged in 3-dim field then set
3841 		     * 0th field offset to merge offset and then next two to
3842 		     * the user values
3843 		     */
3844 		    for (i = 0; i < rankFld; i++)
3845 		    {
3846 			offset[i + 1] = start[i];
3847 		    }
3848 		    offset[0] = mrgOffset;
3849 		}
3850 	    }
3851 
3852 
3853 
3854 	    /* Set I/O stride Section */
3855 	    /* ---------------------- */
3856 
3857 	    /*
3858 	     * If stride == NULL (default) set I/O stride to 1
3859 	     */
3860 	    if (stride == NULL)
3861 	    {
3862 		for (i = 0; i < rankSDS; i++)
3863 		{
3864 		    incr[i] = 1;
3865 		}
3866 	    }
3867 	    else
3868 	    {
3869 		/*
3870 		 * ... otherwise set I/O stride to user values
3871 		 */
3872 		if (rankFld == rankSDS)
3873 		{
3874 		    for (i = 0; i < rankSDS; i++)
3875 		    {
3876 			incr[i] = stride[i];
3877 		    }
3878 		}
3879 		else
3880 		{
3881 		    /*
3882 		     * If field really 2-dim merged in 3-dim field then set
3883 		     * 0th field stride to 1 and then next two to the user
3884 		     * values.
3885 		     */
3886 		    for (i = 0; i < rankFld; i++)
3887 		    {
3888 			incr[i + 1] = stride[i];
3889 		    }
3890 		    incr[0] = 1;
3891 		}
3892 	    }
3893 
3894 
3895 
3896 	    /* Set I/O count Section */
3897 	    /* --------------------- */
3898 
3899 	    /*
3900 	     * If edge == NULL (default) set I/O count to number of remaining
3901 	     * entries (dims - start) / increment.  Note that 0th field
3902 	     * offset corrected for merged field offset (if any).
3903 	     */
3904 	    if (edge == NULL)
3905 	    {
3906 		for (i = 1; i < rankSDS; i++)
3907 		{
3908 		    count[i] = (dims[i] - offset[i]) / incr[i];
3909 		}
3910 		count[0] = (dims[0] - (offset[0] - mrgOffset)) / incr[0];
3911 	    }
3912 	    else
3913 	    {
3914 		/*
3915 		 * ... otherwise set I/O count to user values
3916 		 */
3917 		if (rankFld == rankSDS)
3918 		{
3919 		    for (i = 0; i < rankSDS; i++)
3920 		    {
3921 			count[i] = edge[i];
3922 		    }
3923 		}
3924 		else
3925 		{
3926 		    /*
3927 		     * If field really 2-dim merged in 3-dim field then set
3928 		     * 0th field count to 1 and then next two to the user
3929 		     * values.
3930 		     */
3931 		    for (i = 0; i < rankFld; i++)
3932 		    {
3933 			count[i + 1] = edge[i];
3934 		    }
3935 		    count[0] = 1;
3936 		}
3937 	    }
3938 
3939 
3940 	    /* Perform I/O with relevant HDF I/O routine */
3941 	    /* ----------------------------------------- */
3942 	    if (strcmp(code, "w") == 0)
3943 	    {
3944 		/* Set strideOne to true (1) */
3945 		/* ------------------------- */
3946 		strideOne = 1;
3947 
3948 
3949 		/* If incr[i] != 1 set strideOne to false (0) */
3950 		/* ------------------------------------------ */
3951 		for (i = 0; i < rankSDS; i++)
3952 		{
3953 		    if (incr[i] != 1)
3954 		    {
3955 			strideOne = 0;
3956 			break;
3957 		    }
3958 		}
3959 
3960 
3961 		/*
3962 		 * If strideOne is true use NULL parameter for stride. This
3963 		 * is a work-around to HDF compression problem
3964 		 */
3965 		if (strideOne == 1)
3966 		{
3967 		    status = SDwritedata(sdid, offset, NULL, count,
3968 					 (VOIDP) datbuf);
3969 		}
3970 		else
3971 		{
3972 		    status = SDwritedata(sdid, offset, incr, count,
3973 					 (VOIDP) datbuf);
3974 		}
3975 	    }
3976 	    else
3977 	    {
3978 		status = SDreaddata(sdid, offset, incr, count,
3979 				    (VOIDP) datbuf);
3980 	    }
3981 	}
3982     }
3983 
3984     return (status);
3985 }
3986 
3987 
3988 /*----------------------------------------------------------------------------|
3989 |  BEGIN_PROLOG                                                               |
3990 |                                                                             |
3991 |  FUNCTION: GDwritefield                                                     |
3992 |                                                                             |
3993 |  DESCRIPTION: Writes data to a grid field.                                  |
3994 |                                                                             |
3995 |                                                                             |
3996 |  Return Value    Type     Units     Description                             |
3997 |  ============   ======  =========   =====================================   |
3998 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
3999 |                                                                             |
4000 |  INPUTS:                                                                    |
4001 |  gridID         int32               grid structure ID                       |
4002 |  fieldname      char                fieldname                               |
4003 |  start          int32               start array                             |
4004 |  stride         int32               stride array                            |
4005 |  edge           int32               edge array                              |
4006 |                                                                             |
4007 |                                                                             |
4008 |  OUTPUTS:                                                                   |
4009 |  data           void                data buffer for write                   |
4010 |                                                                             |
4011 |  NOTES:                                                                     |
4012 |                                                                             |
4013 |                                                                             |
4014 |   Date     Programmer   Description                                         |
4015 |  ======   ============  =================================================   |
4016 |  Jun 96   Joel Gales    Original Programmer                                 |
4017 |                                                                             |
4018 |  END_PROLOG                                                                 |
4019 -----------------------------------------------------------------------------*/
4020 intn
GDwritefield(int32 gridID,char * fieldname,int32 start[],int32 stride[],int32 edge[],VOIDP data)4021 GDwritefield(int32 gridID, char *fieldname,
4022 	     int32 start[], int32 stride[], int32 edge[], VOIDP data)
4023 
4024 {
4025     intn            status = 0;	/* routine return status variable */
4026 
4027     status = GDwrrdfield(gridID, fieldname, "w", start, stride, edge,
4028 			 data);
4029     return (status);
4030 }
4031 
4032 
4033 
4034 
4035 
4036 /*----------------------------------------------------------------------------|
4037 |  BEGIN_PROLOG                                                               |
4038 |                                                                             |
4039 |  FUNCTION: GDreadfield                                                      |
4040 |                                                                             |
4041 |  DESCRIPTION: Reads data from a grid field.                                 |
4042 |                                                                             |
4043 |                                                                             |
4044 |  Return Value    Type     Units     Description                             |
4045 |  ============   ======  =========   =====================================   |
4046 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
4047 |                                                                             |
4048 |  INPUTS:                                                                    |
4049 |  gridID         int32               grid structure ID                       |
4050 |  fieldname      char                fieldname                               |
4051 |  start          int32               start array                             |
4052 |  stride         int32               stride array                            |
4053 |  edge           int32               edge array                              |
4054 |  buffer         void                data buffer for read                    |
4055 |                                                                             |
4056 |                                                                             |
4057 |  OUTPUTS:                                                                   |
4058 |     None                                                                    |
4059 |                                                                             |
4060 |  NOTES:                                                                     |
4061 |                                                                             |
4062 |                                                                             |
4063 |   Date     Programmer   Description                                         |
4064 |  ======   ============  =================================================   |
4065 |  Jun 96   Joel Gales    Original Programmer                                 |
4066 |                                                                             |
4067 |  END_PROLOG                                                                 |
4068 -----------------------------------------------------------------------------*/
4069 intn
GDreadfield(int32 gridID,char * fieldname,int32 start[],int32 stride[],int32 edge[],VOIDP buffer)4070 GDreadfield(int32 gridID, char *fieldname,
4071 	    int32 start[], int32 stride[], int32 edge[], VOIDP buffer)
4072 
4073 {
4074     intn            status = 0;	/* routine return status variable */
4075 
4076     status = GDwrrdfield(gridID, fieldname, "r", start, stride, edge,
4077 			 buffer);
4078     return (status);
4079 }
4080 
4081 
4082 
4083 
4084 /*----------------------------------------------------------------------------|
4085 |  BEGIN_PROLOG                                                               |
4086 |                                                                             |
4087 |  FUNCTION: GDwrrdattr                                                       |
4088 |                                                                             |
4089 |  DESCRIPTION:                                                               |
4090 |                                                                             |
4091 |                                                                             |
4092 |  Return Value    Type     Units     Description                             |
4093 |  ============   ======  =========   =====================================   |
4094 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
4095 |                                                                             |
4096 |  INPUTS:                                                                    |
4097 |  gridID         int32               grid structure ID                       |
4098 |  attrname       char                attribute name                          |
4099 |  numbertype     int32               attribute HDF numbertype                |
4100 |  count          int32               Number of attribute elements            |
4101 |  wrcode         char                Read/Write Code "w/r"                   |
4102 |  datbuf         void                I/O buffer                              |
4103 |                                                                             |
4104 |  OUTPUTS:                                                                   |
4105 |  datbuf                                                                     |
4106 |                                                                             |
4107 |  NOTES:                                                                     |
4108 |                                                                             |
4109 |                                                                             |
4110 |   Date     Programmer   Description                                         |
4111 |  ======   ============  =================================================   |
4112 |  Jun 96   Joel Gales    Original Programmer                                 |
4113 |  Oct 96   Joel Gales    Get Attribute Vgroup ID from external array         |
4114 |                                                                             |
4115 |  END_PROLOG                                                                 |
4116 -----------------------------------------------------------------------------*/
4117 static intn
GDwrrdattr(int32 gridID,char * attrname,int32 numbertype,int32 count,char * wrcode,VOIDP datbuf)4118 GDwrrdattr(int32 gridID, char *attrname, int32 numbertype, int32 count,
4119 	   char *wrcode, VOIDP datbuf)
4120 
4121 {
4122     intn            status;	/* routine return status variable */
4123 
4124     int32           fid;	/* HDF-EOS file ID */
4125     int32           attrVgrpID;	/* Grid attribute ID */
4126     int32           dum;	/* dummy variable */
4127     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
4128 
4129 
4130     /* Check Grid id */
4131     status = GDchkgdid(gridID, "GDwrrdattr", &fid, &dum, &dum);
4132 
4133     if (status == 0)
4134     {
4135 	/* Perform Attribute I/O */
4136 	/* --------------------- */
4137 	attrVgrpID = GDXGrid[gridID % idOffset].VIDTable[1];
4138 	status = EHattr(fid, attrVgrpID, attrname, numbertype, count,
4139 			wrcode, datbuf);
4140     }
4141     return (status);
4142 }
4143 
4144 
4145 
4146 /*----------------------------------------------------------------------------|
4147 |  BEGIN_PROLOG                                                               |
4148 |                                                                             |
4149 |  FUNCTION: GDwriteattr                                                      |
4150 |                                                                             |
4151 |  DESCRIPTION: Writes/updates attribute in a grid.                           |
4152 |                                                                             |
4153 |                                                                             |
4154 |  Return Value    Type     Units     Description                             |
4155 |  ============   ======  =========   =====================================   |
4156 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
4157 |                                                                             |
4158 |  INPUTS:                                                                    |
4159 |  gridID         int32               grid structure ID                       |
4160 |  attrname       char                attribute name                          |
4161 |  numbertype     int32               attribute HDF numbertype                |
4162 |  count          int32               Number of attribute elements            |
4163 |  datbuf         void                I/O buffer                              |
4164 |                                                                             |
4165 |  OUTPUTS:                                                                   |
4166 |             None                                                            |
4167 |                                                                             |
4168 |  NOTES:                                                                     |
4169 |                                                                             |
4170 |                                                                             |
4171 |   Date     Programmer   Description                                         |
4172 |  ======   ============  =================================================   |
4173 |  Jun 96   Joel Gales    Original Programmer                                 |
4174 |                                                                             |
4175 |  END_PROLOG                                                                 |
4176 -----------------------------------------------------------------------------*/
4177 intn
GDwriteattr(int32 gridID,char * attrname,int32 numbertype,int32 count,VOIDP datbuf)4178 GDwriteattr(int32 gridID, char *attrname, int32 numbertype, int32 count,
4179 	    VOIDP datbuf)
4180 {
4181     intn            status = 0;	/* routine return status variable */
4182 
4183     /* Call GDwrrdattr routine to write attribute */
4184     /* ------------------------------------------ */
4185     status = GDwrrdattr(gridID, attrname, numbertype, count, "w", datbuf);
4186 
4187     return (status);
4188 }
4189 
4190 
4191 
4192 /*----------------------------------------------------------------------------|
4193 |  BEGIN_PROLOG                                                               |
4194 |                                                                             |
4195 |  FUNCTION: GDreadattr                                                       |
4196 |                                                                             |
4197 |  DESCRIPTION: Reads attribute from a grid.                                  |
4198 |                                                                             |
4199 |                                                                             |
4200 |  Return Value    Type     Units     Description                             |
4201 |  ============   ======  =========   =====================================   |
4202 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
4203 |                                                                             |
4204 |  INPUTS:                                                                    |
4205 |  gridID         int32               grid structure ID                       |
4206 |  attrname       char                attribute name                          |
4207 |                                                                             |
4208 |  OUTPUTS:                                                                   |
4209 |  datbuf         void                I/O buffer                              |
4210 |                                                                             |
4211 |  NOTES:                                                                     |
4212 |                                                                             |
4213 |                                                                             |
4214 |   Date     Programmer   Description                                         |
4215 |  ======   ============  =================================================   |
4216 |  Jun 96   Joel Gales    Original Programmer                                 |
4217 |                                                                             |
4218 |  END_PROLOG                                                                 |
4219 -----------------------------------------------------------------------------*/
4220 intn
GDreadattr(int32 gridID,char * attrname,VOIDP datbuf)4221 GDreadattr(int32 gridID, char *attrname, VOIDP datbuf)
4222 {
4223     intn            status = 0;	/* routine return status variable */
4224     int32           dum = 0;	/* dummy variable */
4225 
4226     /* Call GDwrrdattr routine to read attribute */
4227     /* ----------------------------------------- */
4228     status = GDwrrdattr(gridID, attrname, dum, dum, "r", datbuf);
4229 
4230     return (status);
4231 }
4232 
4233 
4234 
4235 
4236 
4237 /*----------------------------------------------------------------------------|
4238 |  BEGIN_PROLOG                                                               |
4239 |                                                                             |
4240 |  FUNCTION: GDattrinfo                                                       |
4241 |                                                                             |
4242 |  DESCRIPTION:                                                               |
4243 |                                                                             |
4244 |                                                                             |
4245 |  Return Value    Type     Units     Description                             |
4246 |  ============   ======  =========   =====================================   |
4247 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
4248 |                                                                             |
4249 |  INPUTS:                                                                    |
4250 |  gridID         int32               grid structure ID                       |
4251 |  attrname       char                attribute name                          |
4252 |                                                                             |
4253 |  OUTPUTS:                                                                   |
4254 |  numbertype     int32               attribute HDF numbertype                |
4255 |  count          int32               Number of attribute elements            |
4256 |                                                                             |
4257 |                                                                             |
4258 |  OUTPUTS:                                                                   |
4259 |             None                                                            |
4260 |                                                                             |
4261 |  NOTES:                                                                     |
4262 |                                                                             |
4263 |                                                                             |
4264 |   Date     Programmer   Description                                         |
4265 |  ======   ============  =================================================   |
4266 |  Jun 96   Joel Gales    Original Programmer                                 |
4267 |  Oct 96   Joel Gales    Get Attribute Vgroup ID from external array         |
4268 |                                                                             |
4269 |  END_PROLOG                                                                 |
4270 -----------------------------------------------------------------------------*/
4271 intn
GDattrinfo(int32 gridID,char * attrname,int32 * numbertype,int32 * count)4272 GDattrinfo(int32 gridID, char *attrname, int32 * numbertype, int32 * count)
4273 {
4274     intn            status = 0;	/* routine return status variable */
4275 
4276     int32           fid;	/* HDF-EOS file ID */
4277     int32           attrVgrpID;	/* Grid attribute ID */
4278     int32           dum;	/* dummy variable */
4279     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
4280 
4281     status = GDchkgdid(gridID, "GDattrinfo", &fid, &dum, &dum);
4282 
4283     attrVgrpID = GDXGrid[gridID % idOffset].VIDTable[1];
4284 
4285     status = EHattrinfo(fid, attrVgrpID, attrname, numbertype,
4286 			count);
4287 
4288     return (status);
4289 }
4290 
4291 
4292 
4293 
4294 
4295 
4296 /*----------------------------------------------------------------------------|
4297 |  BEGIN_PROLOG                                                               |
4298 |                                                                             |
4299 |  FUNCTION: GDinqattrs                                                       |
4300 |                                                                             |
4301 |  DESCRIPTION:                                                               |
4302 |                                                                             |
4303 |                                                                             |
4304 |  Return Value    Type     Units     Description                             |
4305 |  ============   ======  =========   =====================================   |
4306 |  nattr          int32               Number of attributes in swath struct    |
4307 |                                                                             |
4308 |  INPUTS:                                                                    |
4309 |  grid ID        int32               grid structure ID                       |
4310 |                                                                             |
4311 |  OUTPUTS:                                                                   |
4312 |  attrnames      char                Attribute names in swath struct         |
4313 |                                     (Comma-separated list)                  |
4314 |  strbufsize     int32               Attributes name list string length      |
4315 |                                                                             |
4316 |  OUTPUTS:                                                                   |
4317 |             None                                                            |
4318 |                                                                             |
4319 |  NOTES:                                                                     |
4320 |                                                                             |
4321 |                                                                             |
4322 |   Date     Programmer   Description                                         |
4323 |  ======   ============  =================================================   |
4324 |  Jun 96   Joel Gales    Original Programmer                                 |
4325 |  Oct 96   Joel Gales    Initialize nattr                                    |
4326 |  Oct 96   Joel Gales    Get Attribute Vgroup ID from external array         |
4327 |                                                                             |
4328 |  END_PROLOG                                                                 |
4329 -----------------------------------------------------------------------------*/
4330 int32
GDinqattrs(int32 gridID,char * attrnames,int32 * strbufsize)4331 GDinqattrs(int32 gridID, char *attrnames, int32 * strbufsize)
4332 {
4333     intn            status;	/* routine return status variable */
4334 
4335     int32           fid;	/* HDF-EOS file ID */
4336     int32           attrVgrpID;	/* Grid attribute ID */
4337     int32           dum;	/* dummy variable */
4338     int32           nattr = 0;	/* Number of attributes */
4339     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
4340 
4341 
4342     /* Check Grid id */
4343     status = GDchkgdid(gridID, "GDinqattrs", &fid, &dum, &dum);
4344 
4345     if (status == 0)
4346     {
4347 	attrVgrpID = GDXGrid[gridID % idOffset].VIDTable[1];
4348 	nattr = EHattrcat(fid, attrVgrpID, attrnames, strbufsize);
4349     }
4350 
4351     return (nattr);
4352 }
4353 
4354 
4355 
4356 
4357 
4358 
4359 #define REMQUOTE \
4360 \
4361 memmove(utlstr, utlstr + 1, strlen(utlstr) - 2); \
4362 utlstr[strlen(utlstr) - 2] = 0;
4363 
4364 
4365 /*----------------------------------------------------------------------------|
4366 |  BEGIN_PROLOG                                                               |
4367 |                                                                             |
4368 |  FUNCTION: GDinqdims                                                        |
4369 |                                                                             |
4370 |  DESCRIPTION: Retrieve information about all dimensions defined in a grid.  |
4371 |                                                                             |
4372 |                                                                             |
4373 |  Return Value    Type     Units     Description                             |
4374 |  ============   ======  =========   =====================================   |
4375 |  nDim           int32               Number of defined dimensions            |
4376 |                                                                             |
4377 |  INPUTS:                                                                    |
4378 |  gridID         int32               grid structure ID                       |
4379 |                                                                             |
4380 |  OUTPUTS:                                                                   |
4381 |  dimnames       char                Dimension names (comma-separated)       |
4382 |  dims           int32               Dimension values                        |
4383 |                                                                             |
4384 |                                                                             |
4385 |  OUTPUTS:                                                                   |
4386 |             None                                                            |
4387 |                                                                             |
4388 |  NOTES:                                                                     |
4389 |                                                                             |
4390 |                                                                             |
4391 |   Date     Programmer   Description                                         |
4392 |  ======   ============  =================================================   |
4393 |  Jun 96   Joel Gales    Original Programmer                                 |
4394 |  Aug 96   Joel Gales    Make metadata ODL compliant                         |
4395 |  Feb 97   Joel Gales    Set nDim to -1 if status = -1                       |
4396 |                                                                             |
4397 |  END_PROLOG                                                                 |
4398 -----------------------------------------------------------------------------*/
4399 int32
GDinqdims(int32 gridID,char * dimnames,int32 dims[])4400 GDinqdims(int32 gridID, char *dimnames, int32 dims[])
4401 {
4402     intn            status;	/* routine return status variable */
4403 
4404     int32           fid;	/* HDF-EOS file ID */
4405     int32           sdInterfaceID;	/* HDF SDS interface ID */
4406     int32           gdVgrpID;	/* Grid root Vgroup ID */
4407     int32           size;	/* Dimension size */
4408     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
4409     int32           nDim = 0;	/* Number of dimensions */
4410 
4411     char           *metabuf;	/* Pointer to structural metadata (SM) */
4412     char           *metaptrs[2];/* Pointers to begin and end of SM section */
4413     char            gridname[80];	/* Grid Name */
4414     char           *utlstr;/* Utility string */
4415 
4416     /* Allocate space for utility string */
4417     /* --------------------------------- */
4418     utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
4419     if(utlstr == NULL)
4420     {
4421 	HEpush(DFE_NOSPACE,"GDinqdims", __FILE__, __LINE__);
4422 	return(-1);
4423     }
4424     /* Check for valid grid id */
4425     /* ----------------------- */
4426     status = GDchkgdid(gridID, "GDinqdims", &fid, &sdInterfaceID, &gdVgrpID);
4427 
4428     if (status == 0)
4429     {
4430 	/* If dimension names or sizes are requested */
4431 	/* ----------------------------------------- */
4432 	if (dimnames != NULL || dims != NULL)
4433 	{
4434 	    /* Get grid name */
4435 	    /* ------------- */
4436 	    Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
4437 
4438 
4439 	    /* Get pointers to "Dimension" section within SM */
4440 	    /* --------------------------------------------- */
4441 	    metabuf = (char *) EHmetagroup(sdInterfaceID, gridname, "g",
4442 					   "Dimension", metaptrs);
4443 	    if(metabuf == NULL)
4444 	    {
4445 		free(utlstr);
4446 		return(-1);
4447 	    }
4448 
4449 
4450 	    /* If dimension names are requested then "clear" name buffer */
4451 	    /* --------------------------------------------------------- */
4452 	    if (dimnames != NULL)
4453 	    {
4454 		dimnames[0] = 0;
4455 	    }
4456 
4457 	    while (metaptrs[0] < metaptrs[1] && metaptrs[0] != NULL)
4458 	    {
4459 		strcpy(utlstr, "\t\tOBJECT=");
4460 		metaptrs[0] = strstr(metaptrs[0], utlstr);
4461 		if (metaptrs[0] < metaptrs[1] && metaptrs[0] != NULL)
4462 		{
4463 		    /* Get Dimension Name */
4464 		    /* ------------------ */
4465 		    if (dimnames != NULL)
4466 		    {
4467 			/* Check 1st for old meta data then new */
4468 			/* ------------------------------------ */
4469 			EHgetmetavalue(metaptrs, "OBJECT", utlstr);
4470 			if (utlstr[0] != '"')
4471 			{
4472 			    metaptrs[0] =
4473 				strstr(metaptrs[0], "\t\t\t\tDimensionName=");
4474 			    EHgetmetavalue(metaptrs, "DimensionName", utlstr);
4475 			}
4476 
4477 			/* Strip off double quotes */
4478 			/* ----------------------- */
4479 			memmove(utlstr, utlstr + 1, strlen(utlstr) - 2);
4480 			utlstr[strlen(utlstr) - 2] = 0;
4481 
4482 			if (nDim > 0)
4483 			{
4484 			    strcat(dimnames, ",");
4485 			}
4486 			strcat(dimnames, utlstr);
4487 		    }
4488 
4489 		    /* Get Dimension Size */
4490 		    /* ------------------ */
4491 		    if (dims != NULL)
4492 		    {
4493 			EHgetmetavalue(metaptrs, "Size", utlstr);
4494 			size = atol(utlstr);
4495 			dims[nDim] = size;
4496 		    }
4497 		    nDim++;
4498 		}
4499 	    }
4500 	    free(metabuf);
4501 
4502 	}
4503     }
4504 
4505 
4506     /* Set nDim to -1 if error status exists */
4507     /* ------------------------------------- */
4508     if (status == -1)
4509     {
4510 	nDim = -1;
4511     }
4512     free(utlstr);
4513     return (nDim);
4514 }
4515 
4516 
4517 
4518 
4519 
4520 
4521 /*----------------------------------------------------------------------------|
4522 |  BEGIN_PROLOG                                                               |
4523 |                                                                             |
4524 |  FUNCTION: GDinqfields                                                      |
4525 |                                                                             |
4526 |  DESCRIPTION: Retrieve information about all data fields defined in a grid. |
4527 |                                                                             |
4528 |                                                                             |
4529 |  Return Value    Type     Units     Description                             |
4530 |  ============   ======  =========   =====================================   |
4531 |  nFld           int32               Number of fields in swath               |
4532 |                                                                             |
4533 |  INPUTS:                                                                    |
4534 |  gridID         int32               grid structure ID                       |
4535 |                                                                             |
4536 |                                                                             |
4537 |  OUTPUTS:                                                                   |
4538 |  fieldlist      char                Field names (comma-separated)           |
4539 |  rank           int32               Array of ranks                          |
4540 |  numbertype     int32               Array of HDF number types               |
4541 |                                                                             |
4542 |  NOTES:                                                                     |
4543 |                                                                             |
4544 |                                                                             |
4545 |   Date     Programmer   Description                                         |
4546 |  ======   ============  =================================================   |
4547 |  Jun 96   Joel Gales    Original Programmer                                 |
4548 |  Aug 96   Joel Gales    Make metadata ODL compliant                         |
4549 |  Feb 97   Joel Gales    Set nFld to -1 if status = -1                       |
4550 |                                                                             |
4551 |  END_PROLOG                                                                 |
4552 -----------------------------------------------------------------------------*/
4553 int32
GDinqfields(int32 gridID,char * fieldlist,int32 rank[],int32 numbertype[])4554 GDinqfields(int32 gridID, char *fieldlist, int32 rank[],
4555 	    int32 numbertype[])
4556 {
4557     intn            status;	/* routine return status variable */
4558 
4559     int32           fid;	/* HDF-EOS file ID */
4560     int32           sdInterfaceID;	/* HDF SDS interface ID */
4561     int32           gdVgrpID;	/* Grid root Vgroup ID */
4562     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
4563     int32           nFld = 0;	/* Number of mappings */
4564     int32           slen[8];	/* String length array */
4565 
4566     char           *metabuf;	/* Pointer to structural metadata (SM) */
4567     char           *metaptrs[2];/* Pointers to begin and end of SM section */
4568     char            gridname[80];	/* Grid Name */
4569     char           *utlstr;/* Utility string */
4570     char           *ptr[8];	/* String pointer array */
4571 
4572     /* Allocate space for utility string */
4573     /* --------------------------------- */
4574     utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
4575     if(utlstr == NULL)
4576     {
4577 	HEpush(DFE_NOSPACE,"GDinqfields", __FILE__, __LINE__);
4578 	return(-1);
4579     }
4580     /* Check for valid grid id */
4581     /* ----------------------- */
4582     status = GDchkgdid(gridID, "GDinqfields", &fid, &sdInterfaceID, &gdVgrpID);
4583     if (status == 0)
4584     {
4585 
4586 	/* If field names, ranks,  or number types desired ... */
4587 	/* --------------------------------------------------- */
4588 	if (fieldlist != NULL || rank != NULL || numbertype != NULL)
4589 	{
4590 	    /* Get grid name */
4591 	    /* ------------- */
4592 	    Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
4593 
4594 
4595 	    /* Get pointers to "DataField" section within SM */
4596 	    /* --------------------------------------------- */
4597 	    metabuf = (char *) EHmetagroup(sdInterfaceID, gridname, "g",
4598 					   "DataField", metaptrs);
4599 	    if(metabuf == NULL)
4600 	    {
4601 		free(utlstr);
4602 		return(-1);
4603 	    }
4604 
4605 
4606 	    /* If field names are desired then "clear" name buffer */
4607 	    /* --------------------------------------------------- */
4608 	    if (fieldlist != NULL)
4609 	    {
4610 		fieldlist[0] = 0;
4611 	    }
4612 
4613 
4614 	    /* Begin loop through mapping entries in metadata */
4615 	    /* ---------------------------------------------- */
4616 	    while (1)
4617 	    {
4618 		/* Search for OBJECT string */
4619 		/* ------------------------ */
4620 		metaptrs[0] = strstr(metaptrs[0], "\t\tOBJECT=");
4621 
4622 
4623 		/* If found within "Data" Field metadata section .. */
4624 		/* ------------------------------------------------ */
4625 		if (metaptrs[0] < metaptrs[1] && metaptrs[0] != NULL)
4626 		{
4627 		    /* Get Fieldnames (if desired) */
4628 		    /* --------------------------- */
4629 		    if (fieldlist != NULL)
4630 		    {
4631 			/* Check 1st for old meta data then new */
4632 			/* ------------------------------------ */
4633 			EHgetmetavalue(metaptrs, "OBJECT", utlstr);
4634 
4635 			/*
4636 			 * If OBJECT value begins with double quote then old
4637 			 * metadata, field name is OBJECT value. Otherwise
4638 			 * search for "DataFieldName" string
4639 			 */
4640 
4641 			if (utlstr[0] != '"')
4642 			{
4643 			    strcpy(utlstr, "\t\t\t\t");
4644 			    strcat(utlstr, "DataFieldName");
4645 			    strcat(utlstr, "=");
4646 			    metaptrs[0] = strstr(metaptrs[0], utlstr);
4647 			    EHgetmetavalue(metaptrs, "DataFieldName", utlstr);
4648 			}
4649 
4650 			/* Strip off double quotes */
4651 			/* ----------------------- */
4652 			REMQUOTE
4653 
4654 
4655 			/* Add to fieldlist */
4656 			/* ---------------- */
4657 			    if (nFld > 0)
4658 			{
4659 			    strcat(fieldlist, ",");
4660 			}
4661 			strcat(fieldlist, utlstr);
4662 
4663 		    }
4664 		    /* Get Numbertype */
4665 		    if (numbertype != NULL)
4666 		    {
4667 			EHgetmetavalue(metaptrs, "DataType", utlstr);
4668 			numbertype[nFld] = EHnumstr(utlstr);
4669 		    }
4670 		    /*
4671 		     * Get Rank (if desired) by counting # of dimensions in
4672 		     * "DimList" string
4673 		     */
4674 		    if (rank != NULL)
4675 		    {
4676 			EHgetmetavalue(metaptrs, "DimList", utlstr);
4677 			rank[nFld] = EHparsestr(utlstr, ',', ptr, slen);
4678 		    }
4679 		    /* Increment number of fields */
4680 		    nFld++;
4681 		}
4682 		else
4683 		    /* No more fields found */
4684 		{
4685 		    break;
4686 		}
4687 	    }
4688 	    free(metabuf);
4689 	}
4690     }
4691 
4692     /* Set nFld to -1 if error status exists */
4693     /* ------------------------------------- */
4694     if (status == -1)
4695     {
4696 	nFld = -1;
4697     }
4698     free(utlstr);
4699     return (nFld);
4700 }
4701 
4702 
4703 
4704 
4705 
4706 /*----------------------------------------------------------------------------|
4707 |  BEGIN_PROLOG                                                               |
4708 |                                                                             |
4709 |  FUNCTION: GDnentries                                                       |
4710 |                                                                             |
4711 |  DESCRIPTION: Returns number of entries and descriptive string buffer       |
4712 |                size for a specified entity.                                 |
4713 |                                                                             |
4714 |                                                                             |
4715 |  Return Value    Type     Units     Description                             |
4716 |  ============   ======  =========   =====================================   |
4717 |  nEntries       int32               Number of entries                       |
4718 |                                                                             |
4719 |  INPUTS:                                                                    |
4720 |  gridID         int32               grid structure ID                       |
4721 |  entrycode      int32               Entry code                              |
4722 |	                              HDFE_NENTDIM  (0)                       |
4723 |	                              HDFE_NENTDFLD (4)                       |
4724 |                                                                             |
4725 |                                                                             |
4726 |  OUTPUTS:                                                                   |
4727 |  strbufsize     int32               Length of comma-separated list          |
4728 |                                     (Does not include null-terminator       |
4729 |                                                                             |
4730 |  NOTES:                                                                     |
4731 |                                                                             |
4732 |                                                                             |
4733 |   Date     Programmer   Description                                         |
4734 |  ======   ============  =================================================   |
4735 |  Jun 96   Joel Gales    Original Programmer                                 |
4736 |  Aug 96   Joel Gales    Make metadata ODL compliant                         |
4737 |  Feb 97   Joel Gales    Set nEntries to -1 if status = -1                   |
4738 |                                                                             |
4739 |  END_PROLOG                                                                 |
4740 -----------------------------------------------------------------------------*/
4741 int32
GDnentries(int32 gridID,int32 entrycode,int32 * strbufsize)4742 GDnentries(int32 gridID, int32 entrycode, int32 * strbufsize)
4743 
4744 {
4745     intn            status;	/* routine return status variable */
4746     intn            i;		/* Loop index */
4747 
4748     int32           fid;	/* HDF-EOS file ID */
4749     int32           sdInterfaceID;	/* HDF SDS interface ID */
4750     int32           gdVgrpID;	/* Grid root Vgroup ID */
4751     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
4752     int32           nEntries = 0;	/* Number of entries */
4753     int32           metaflag;	/* Old (0), New (1) metadata flag) */
4754     int32           nVal = 0;	/* Number of strings to search for */
4755 
4756     char           *metabuf = NULL;	/* Pointer to structural metadata (SM) */
4757     char           *metaptrs[2];/* Pointers to begin and end of SM section */
4758     char            gridname[80];	/* Grid Name */
4759     char           *utlstr;/* Utility string */
4760     char            valName[2][32];	/* Strings to search for */
4761 
4762     /* Allocate space for utility string */
4763     /* --------------------------------- */
4764     utlstr = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
4765     if(utlstr == NULL)
4766     {
4767 	HEpush(DFE_NOSPACE,"GDnentries", __FILE__, __LINE__);
4768 	return(-1);
4769     }
4770     status = GDchkgdid(gridID, "GDnentries", &fid, &sdInterfaceID, &gdVgrpID);
4771 
4772     if (status == 0)
4773     {
4774 	/* Get grid name */
4775 	Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
4776 
4777 	/* Zero out string buffer size */
4778 	*strbufsize = 0;
4779 
4780 
4781 	/*
4782 	 * Get pointer to  relevant section within SM and Get names of
4783 	 * metadata strings to inquire about
4784 	 */
4785 	switch (entrycode)
4786 	{
4787 	case HDFE_NENTDIM:
4788 	    {
4789 		metabuf = (char *) EHmetagroup(sdInterfaceID, gridname, "g",
4790 					       "Dimension", metaptrs);
4791 		if(metabuf == NULL)
4792 		{
4793 		    free(utlstr);
4794 		    return(-1);
4795 		}
4796 
4797 		nVal = 1;
4798 		strcpy(&valName[0][0], "DimensionName");
4799 	    }
4800 	    break;
4801 
4802 	case HDFE_NENTDFLD:
4803 	    {
4804 		metabuf = (char *) EHmetagroup(sdInterfaceID, gridname, "g",
4805 					       "DataField", metaptrs);
4806 		if(metabuf == NULL)
4807 		{
4808 		    free(utlstr);
4809 		    return(-1);
4810 		}
4811 
4812 		nVal = 1;
4813 		strcpy(&valName[0][0], "DataFieldName");
4814 	    }
4815 	    break;
4816 	}
4817 
4818 
4819 	/*
4820 	 * Check for presence of 'GROUP="' string If found then old metadata,
4821 	 * search on OBJECT string
4822 	 */
4823 	metaflag = (strstr(metabuf, "GROUP=\"") == NULL) ? 1 : 0;
4824 	if (metaflag == 0)
4825 	{
4826 	    nVal = 1;
4827 	    strcpy(&valName[0][0], "\t\tOBJECT");
4828 	}
4829 
4830 
4831 	/* Begin loop through entries in metadata */
4832 	/* -------------------------------------- */
4833 	while (1)
4834 	{
4835 	    /* Search for first string */
4836 	    strcpy(utlstr, &valName[0][0]);
4837 	    strcat(utlstr, "=");
4838 	    metaptrs[0] = strstr(metaptrs[0], utlstr);
4839 
4840 	    /* If found within relevant metadata section ... */
4841 	    if (metaptrs[0] < metaptrs[1] && metaptrs[0] != NULL)
4842 	    {
4843 		for (i = 0; i < nVal; i++)
4844 		{
4845 		    /*
4846 		     * Get all string values Don't count quotes
4847 		     */
4848 		    EHgetmetavalue(metaptrs, &valName[i][0], utlstr);
4849 		    *strbufsize += strlen(utlstr) - 2;
4850 		}
4851 		/* Increment number of entries */
4852 		nEntries++;
4853 
4854 		/* Go to end of OBJECT */
4855 		metaptrs[0] = strstr(metaptrs[0], "END_OBJECT");
4856 	    }
4857 	    else
4858 		/* No more entries found */
4859 	    {
4860 		break;
4861 	    }
4862 	}
4863 	free(metabuf);
4864 
4865 
4866 	/* Count comma separators & slashes (if mappings) */
4867 	/* ---------------------------------------------- */
4868 	if (nEntries > 0)
4869 	{
4870 	    *strbufsize += nEntries - 1;
4871 	    *strbufsize += (nVal - 1) * nEntries;
4872 	}
4873     }
4874 
4875 
4876     /* Set nEntries to -1 if error status exists */
4877     /* ----------------------------------------- */
4878     if (status == -1)
4879     {
4880 	nEntries = -1;
4881     }
4882 
4883     free(utlstr);
4884     return (nEntries);
4885 }
4886 
4887 
4888 
4889 
4890 
4891 /*----------------------------------------------------------------------------|
4892 |  BEGIN_PROLOG                                                               |
4893 |                                                                             |
4894 |  FUNCTION: GDinqgrid                                                        |
4895 |                                                                             |
4896 |  DESCRIPTION: Returns number and names of grid structures in file           |
4897 |                                                                             |
4898 |                                                                             |
4899 |  Return Value    Type     Units     Description                             |
4900 |  ============   ======  =========   =====================================   |
4901 |  nGrid          int32               Number of grid structures in file       |
4902 |                                                                             |
4903 |  INPUTS:                                                                    |
4904 |  filename       char                HDF-EOS filename                        |
4905 |                                                                             |
4906 |  OUTPUTS:                                                                   |
4907 |  gridlist       char                List of grid names (comma-separated)    |
4908 |  strbufsize     int32               Length of gridlist                      |
4909 |                                                                             |
4910 |  NOTES:                                                                     |
4911 |                                                                             |
4912 |                                                                             |
4913 |   Date     Programmer   Description                                         |
4914 |  ======   ============  =================================================   |
4915 |  Jun 96   Joel Gales    Original Programmer                                 |
4916 |                                                                             |
4917 |  END_PROLOG                                                                 |
4918 -----------------------------------------------------------------------------*/
4919 int32
GDinqgrid(char * filename,char * gridlist,int32 * strbufsize)4920 GDinqgrid(char *filename, char *gridlist, int32 * strbufsize)
4921 {
4922     int32           nGrid;	/* Number of grid structures in file */
4923 
4924     /* Call "EHinquire" routine */
4925     /* ------------------------ */
4926     nGrid = EHinquire(filename, "GRID", gridlist, strbufsize);
4927 
4928     return (nGrid);
4929 }
4930 
4931 
4932 /*----------------------------------------------------------------------------|
4933 |  BEGIN_PROLOG                                                               |
4934 |                                                                             |
4935 |  FUNCTION: GDsetfillvalue                                                   |
4936 |                                                                             |
4937 |  DESCRIPTION: Sets fill value for the specified field.                      |
4938 |                                                                             |
4939 |                                                                             |
4940 |  Return Value    Type     Units     Description                             |
4941 |  ============   ======  =========   =====================================   |
4942 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
4943 |                                                                             |
4944 |  INPUTS:                                                                    |
4945 |  gridID         int32               grid structure ID                       |
4946 |  fieldname      char                field name                              |
4947 |  fillval        void                fill value                              |
4948 |                                                                             |
4949 |  OUTPUTS:                                                                   |
4950 |             None                                                            |
4951 |                                                                             |
4952 |  NOTES:                                                                     |
4953 |                                                                             |
4954 |                                                                             |
4955 |   Date     Programmer   Description                                         |
4956 |  ======   ============  =================================================   |
4957 |  Jun 96   Joel Gales    Original Programmer                                 |
4958 |                                                                             |
4959 |  END_PROLOG                                                                 |
4960 -----------------------------------------------------------------------------*/
4961 intn
GDsetfillvalue(int32 gridID,char * fieldname,VOIDP fillval)4962 GDsetfillvalue(int32 gridID, char *fieldname, VOIDP fillval)
4963 {
4964     intn            status;	/* routine return status variable */
4965 
4966     int32           fid;	/* HDF-EOS file ID */
4967     int32           sdInterfaceID;	/* HDF SDS interface ID */
4968     int32           gdVgrpID;	/* Grid root Vgroup ID */
4969     int32           sdid;	/* SDS id */
4970     int32           nt;		/* Number type */
4971     int32           dims[8];	/* Dimensions array */
4972     int32           dum;	/* Dummy variable */
4973     int32           solo;	/* "Solo" (non-merged) field flag */
4974 
4975     char            name[80];	/* Fill value "attribute" name */
4976 
4977     /* Check for valid grid ID and get SDS interface ID */
4978     status = GDchkgdid(gridID, "GDsetfillvalue",
4979 		       &fid, &sdInterfaceID, &gdVgrpID);
4980 
4981     if (status == 0)
4982     {
4983 	/* Get field info */
4984 	status = GDfieldinfo(gridID, fieldname, &dum, dims, &nt, NULL);
4985 
4986 	if (status == 0)
4987 	{
4988 	    /* Get SDS ID and solo flag */
4989 	    status = GDSDfldsrch(gridID, sdInterfaceID, fieldname,
4990 				 &sdid, &dum, &dum, &dum,
4991 				 dims, &solo);
4992 
4993 	    /* If unmerged field then call HDF set field routine */
4994 	    if (solo == 1)
4995 	    {
4996 		status = SDsetfillvalue(sdid, fillval);
4997 	    }
4998 
4999 	    /*
5000 	     * Store fill value in attribute.  Name is given by fieldname
5001 	     * prepended with "_FV_"
5002 	     */
5003 	    strcpy(name, "_FV_");
5004 	    strcat(name, fieldname);
5005 	    status = GDwriteattr(gridID, name, nt, 1, fillval);
5006 
5007 
5008 	}
5009 	else
5010 	{
5011 	    HEpush(DFE_GENAPP, "GDsetfillvalue", __FILE__, __LINE__);
5012 	    HEreport("Fieldname \"%s\" does not exist.\n", fieldname);
5013 	}
5014     }
5015     return (status);
5016 }
5017 
5018 
5019 
5020 
5021 
5022 
5023 
5024 /*----------------------------------------------------------------------------|
5025 |  BEGIN_PROLOG                                                               |
5026 |                                                                             |
5027 |  FUNCTION: GDgetfillvalue                                                   |
5028 |                                                                             |
5029 |  DESCRIPTION: Retrieves fill value for a specified field.                   |
5030 |                                                                             |
5031 |                                                                             |
5032 |  Return Value    Type     Units     Description                             |
5033 |  ============   ======  =========   =====================================   |
5034 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
5035 |                                                                             |
5036 |  INPUTS:                                                                    |
5037 |  gridID         int32               grid structure ID                       |
5038 |  fieldname      char                field name                              |
5039 |                                                                             |
5040 |  OUTPUTS:                                                                   |
5041 |  fillval        void                fill value                              |
5042 |                                                                             |
5043 |  NOTES:                                                                     |
5044 |                                                                             |
5045 |                                                                             |
5046 |   Date     Programmer   Description                                         |
5047 |  ======   ============  =================================================   |
5048 |  Jun 96   Joel Gales    Original Programmer                                 |
5049 |                                                                             |
5050 |  END_PROLOG                                                                 |
5051 -----------------------------------------------------------------------------*/
5052 intn
GDgetfillvalue(int32 gridID,char * fieldname,VOIDP fillval)5053 GDgetfillvalue(int32 gridID, char *fieldname, VOIDP fillval)
5054 {
5055     intn            status;	/* routine return status variable */
5056 
5057     int32           nt;		/* Number type */
5058     int32           dims[8];	/* Dimensions array */
5059     int32           dum;	/* Dummy variable */
5060 
5061     char            name[80];	/* Fill value "attribute" name */
5062 
5063     status = GDchkgdid(gridID, "GDgetfillvalue", &dum, &dum, &dum);
5064 
5065     /* Check for valid grid ID */
5066     if (status == 0)
5067     {
5068 	/* Get field info */
5069 	status = GDfieldinfo(gridID, fieldname, &dum, dims, &nt, NULL);
5070 
5071 	if (status == 0)
5072 	{
5073 	    /* Read fill value attribute */
5074 	    strcpy(name, "_FV_");
5075 	    strcat(name, fieldname);
5076 	    status = GDreadattr(gridID, name, fillval);
5077 	}
5078 	else
5079 	{
5080 	    HEpush(DFE_GENAPP, "GDgetfillvalue", __FILE__, __LINE__);
5081 	    HEreport("Fieldname \"%s\" does not exist.\n", fieldname);
5082 	}
5083 
5084     }
5085     return (status);
5086 }
5087 
5088 
5089 
5090 
5091 
5092 /*----------------------------------------------------------------------------|
5093 |  BEGIN_PROLOG                                                               |
5094 |                                                                             |
5095 |  FUNCTION: GDdetach                                                         |
5096 |                                                                             |
5097 |  DESCRIPTION: Detaches from grid interface and performs file housekeeping.  |
5098 |                                                                             |
5099 |                                                                             |
5100 |  Return Value    Type     Units     Description                             |
5101 |  ============   ======  =========   =====================================   |
5102 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
5103 |                                                                             |
5104 |  INPUTS:                                                                    |
5105 |  gridID         int32               grid structure ID                       |
5106 |                                                                             |
5107 |                                                                             |
5108 |  OUTPUTS:                                                                   |
5109 |             None                                                            |
5110 |                                                                             |
5111 |  NOTES:                                                                     |
5112 |                                                                             |
5113 |                                                                             |
5114 |   Date     Programmer   Description                                         |
5115 |  ======   ============  =================================================   |
5116 |  Jun 96   Joel Gales    Original Programmer                                 |
5117 |  Sep 96   Joel Gales    Setup dim names for SDsetdimname in dimbuf1 rather  |
5118 |                         that utlstr                                         |
5119 |  Oct 96   Joel Gales    Detach Grid Vgroups                                 |
5120 |  Oct 96   Joel Gales    "Detach" from SDS                                   |
5121 |  Nov 96   Joel Gales    Call GDchkgdid to check for proper grid ID          |
5122 |  Dec 96   Joel Gales    Add multiple vertical subsetting garbage collection |
5123 |  Oct 98   Abe Taaheri   Added GDXRegion[k]->DimNamePtr[i] =0; after freeing |
5124 |                         memory                                              |
5125 |  Sep 99   Abe Taaheri   Changed memcpy to memmove because of overlapping    |
5126 |                         source and destination for GDXSDcomb, nameptr, and  |
5127 |                         dimptr. memcpy may cause unexpected results.        |
5128 |                                                                             |
5129 |  END_PROLOG                                                                 |
5130 -----------------------------------------------------------------------------*/
5131 intn
GDdetach(int32 gridID)5132 GDdetach(int32 gridID)
5133 
5134 {
5135     intn            i;		/* Loop index */
5136     intn            j;		/* Loop index */
5137     intn            k;		/* Loop index */
5138     intn            status = 0;	/* routine return status variable */
5139     intn            statusFill = 0;	/* return status from GDgetfillvalue */
5140 
5141     int32          *namelen;	/* Pointer to name string length array */
5142     int32          *dimlen;	/* Pointer to dim string length array */
5143     int32           slen1[3];	/* String length array 1 */
5144     int32           slen2[3];	/* String length array 2 */
5145     int32           nflds;	/* Number of fields */
5146     int32           match[5];	/* Merged field match array */
5147     int32           cmbfldcnt;	/* Number of fields combined */
5148     int32           sdid;	/* SDS ID */
5149     int32           vgid;	/* Vgroup ID */
5150     int32           dims[3];	/* Dimension array */
5151     int32          *offset;	/* Pointer to merged field offset array */
5152     int32          *indvdims;	/* Pointer to merged field size array */
5153     int32           sdInterfaceID;	/* SDS interface ID */
5154     int32           gID;	/* Grid ID - offset */
5155     int32           nflds0;	/* Number of fields */
5156     int32          *namelen0;	/* Pointer to name string length array */
5157     int32           rank;	/* Rank of merged field */
5158     int32           truerank;	/* True rank of merged field */
5159     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
5160     int32           dum;	/* Dummy variable */
5161 
5162     char           *nambuf;	/* Pointer to name buffer */
5163     char          **nameptr;	/* Pointer to name string pointer array */
5164     char          **dimptr;	/* Pointer to dim string pointer array */
5165     char          **nameptr0;	/* Pointer to name string pointer array */
5166     char           *ptr1[3];	/* String pointer array */
5167     char           *ptr2[3];	/* String pointer array */
5168     char            dimbuf1[128];	/* Dimension buffer 1 */
5169     char            dimbuf2[128];	/* Dimension buffer 2 */
5170     char            gridname[VGNAMELENMAX + 1];	/* Grid name */
5171     char           *utlbuf;	/* Utility buffer */
5172     char            fillval[32];/* Fill value buffer */
5173 
5174 
5175 
5176     status = GDchkgdid(gridID, "GDdetach", &dum, &sdInterfaceID, &dum);
5177 
5178     if (status == 0)
5179     {
5180 	gID = gridID % idOffset;
5181 	Vgetname(GDXGrid[gID].IDTable, gridname);
5182 
5183 	/* SDS combined fields */
5184 	/* ------------------- */
5185 	if (strlen(GDXSDname) == 0)
5186 	{
5187 	    nflds = 0;
5188 
5189 	    /* Allocate "dummy" arrays so free() doesn't bomb later */
5190 	    /* ---------------------------------------------------- */
5191 	    nameptr = (char **) calloc(1, sizeof(char *));
5192 	    if(nameptr == NULL)
5193 	    {
5194 		HEpush(DFE_NOSPACE,"GDdetach", __FILE__, __LINE__);
5195 		return(-1);
5196 	    }
5197 	    namelen = (int32 *) calloc(1, sizeof(int32));
5198 	    if(namelen == NULL)
5199 	    {
5200 		HEpush(DFE_NOSPACE,"GDdetach", __FILE__, __LINE__);
5201 		free(nameptr);
5202 		return(-1);
5203 	    }
5204 	    nameptr0 = (char **) calloc(1, sizeof(char *));
5205 	    if(nameptr0 == NULL)
5206 	    {
5207 		HEpush(DFE_NOSPACE,"GDdetach", __FILE__, __LINE__);
5208 		free(nameptr);
5209 		free(namelen);
5210 		return(-1);
5211 	    }
5212 	    namelen0 = (int32 *) calloc(1, sizeof(int32));
5213 	    if(namelen0 == NULL)
5214 	    {
5215 		HEpush(DFE_NOSPACE,"GDdetach", __FILE__, __LINE__);
5216 		free(nameptr);
5217 		free(namelen);
5218 		free(nameptr0);
5219 		return(-1);
5220 	    }
5221 	    dimptr = (char **) calloc(1, sizeof(char *));
5222 	    if(dimptr == NULL)
5223 	    {
5224 		HEpush(DFE_NOSPACE,"GDdetach", __FILE__, __LINE__);
5225 		free(nameptr);
5226 		free(namelen);
5227 		free(nameptr0);
5228 		free(namelen0);
5229 		return(-1);
5230 	    }
5231 	    dimlen = (int32 *) calloc(1, sizeof(int32));
5232 	    if(dimlen == NULL)
5233 	    {
5234 		HEpush(DFE_NOSPACE,"GDdetach", __FILE__, __LINE__);
5235 		free(nameptr);
5236 		free(namelen);
5237 		free(nameptr0);
5238 		free(namelen0);
5239 		free(dimptr);
5240 		return(-1);
5241 	    }
5242 	    offset = (int32 *) calloc(1, sizeof(int32));
5243 	    if(offset == NULL)
5244 	    {
5245 		HEpush(DFE_NOSPACE,"GDdetach", __FILE__, __LINE__);
5246 		free(nameptr);
5247 		free(namelen);
5248 		free(nameptr0);
5249 		free(namelen0);
5250 		free(dimptr);
5251 		free(dimlen);
5252 		return(-1);
5253 	    }
5254 	    indvdims = (int32 *) calloc(1, sizeof(int32));
5255 	    if(indvdims == NULL)
5256 	    {
5257 		HEpush(DFE_NOSPACE,"GDdetach", __FILE__, __LINE__);
5258 		free(nameptr);
5259 		free(namelen);
5260 		free(nameptr0);
5261 		free(namelen0);
5262 		free(dimptr);
5263 		free(dimlen);
5264 		free(offset);
5265 		return(-1);
5266 	    }
5267 	}
5268 	else
5269 	{
5270 	    /*
5271 	     * "Trim Off" trailing "," and ";" in GDXSDname & GDXSDdims
5272 	     * respectively
5273 	     */
5274 	    GDXSDname[strlen(GDXSDname) - 1] = 0;
5275 	    GDXSDdims[strlen(GDXSDdims) - 1] = 0;
5276 
5277 
5278 	    /* Get number of fields from GDXSDname string */
5279 	    /* ------------------------------------------ */
5280 	    nflds = EHparsestr(GDXSDname, ',', NULL, NULL);
5281 
5282 	    /* Allocate space for various dynamic arrays */
5283 	    /* ----------------------------------------- */
5284 	    nameptr = (char **) calloc(nflds, sizeof(char *));
5285 	    if(nameptr == NULL)
5286 	    {
5287 		HEpush(DFE_NOSPACE,"GDdetach", __FILE__, __LINE__);
5288 		return(-1);
5289 	    }
5290 	    namelen = (int32 *) calloc(nflds, sizeof(int32));
5291 	    if(namelen == NULL)
5292 	    {
5293 		HEpush(DFE_NOSPACE,"GDdetach", __FILE__, __LINE__);
5294 		free(nameptr);
5295 		return(-1);
5296 	    }
5297 	    nameptr0 = (char **) calloc(nflds, sizeof(char *));
5298 	    if(nameptr0 == NULL)
5299 	    {
5300 		HEpush(DFE_NOSPACE,"GDdetach", __FILE__, __LINE__);
5301 		free(nameptr);
5302 		free(namelen);
5303 		return(-1);
5304 	    }
5305 	    namelen0 = (int32 *) calloc(nflds, sizeof(int32));
5306 	    if(namelen0 == NULL)
5307 	    {
5308 		HEpush(DFE_NOSPACE,"GDdetach", __FILE__, __LINE__);
5309 		free(nameptr);
5310 		free(namelen);
5311 		free(nameptr0);
5312 		return(-1);
5313 	    }
5314 	    dimptr = (char **) calloc(nflds, sizeof(char *));
5315 	    if(dimptr == NULL)
5316 	    {
5317 		HEpush(DFE_NOSPACE,"GDdetach", __FILE__, __LINE__);
5318 		free(nameptr);
5319 		free(namelen);
5320 		free(nameptr0);
5321 		free(namelen0);
5322 		return(-1);
5323 	    }
5324 	    dimlen = (int32 *) calloc(nflds, sizeof(int32));
5325 	    if(dimlen == NULL)
5326 	    {
5327 		HEpush(DFE_NOSPACE,"GDdetach", __FILE__, __LINE__);
5328 		free(nameptr);
5329 		free(namelen);
5330 		free(nameptr0);
5331 		free(namelen0);
5332 		free(dimptr);
5333 		return(-1);
5334 	    }
5335 	    offset = (int32 *) calloc(nflds, sizeof(int32));
5336 	    if(offset == NULL)
5337 	    {
5338 		HEpush(DFE_NOSPACE,"GDdetach", __FILE__, __LINE__);
5339 		free(nameptr);
5340 		free(namelen);
5341 		free(nameptr0);
5342 		free(namelen0);
5343 		free(dimptr);
5344 		free(dimlen);
5345 		return(-1);
5346 	    }
5347 	    indvdims = (int32 *) calloc(nflds, sizeof(int32));
5348 	    if(indvdims == NULL)
5349 	    {
5350 		HEpush(DFE_NOSPACE,"GDdetach", __FILE__, __LINE__);
5351 		free(nameptr);
5352 		free(namelen);
5353 		free(nameptr0);
5354 		free(namelen0);
5355 		free(dimptr);
5356 		free(dimlen);
5357 		free(offset);
5358 		return(-1);
5359 	    }
5360 
5361 	    /* Parse GDXSDname and GDXSDdims strings */
5362 	    /* ------------------------------------- */
5363 	    nflds = EHparsestr(GDXSDname, ',', nameptr, namelen);
5364 	    nflds = EHparsestr(GDXSDdims, ';', dimptr, dimlen);
5365 	}
5366 
5367 
5368 	for (i = 0; i < nflds; i++)
5369 	{
5370 	    if (GDXSDcomb[5 * i] != 0 &&
5371 		GDXSDcomb[5 * i + 3] == GDXGrid[gID].IDTable)
5372 	    {
5373 		nambuf = (char *) calloc(strlen(GDXSDname) + 1, 1);
5374 		if(nambuf == NULL)
5375 		{
5376 		    HEpush(DFE_NOSPACE,"GDdetach", __FILE__, __LINE__);
5377 		    free(nameptr);
5378 		    free(namelen);
5379 		    free(nameptr0);
5380 		    free(namelen0);
5381 		    free(dimptr);
5382 		    free(dimlen);
5383 		    free(offset);
5384 		    return(-1);
5385 		}
5386 		utlbuf = (char *) calloc(strlen(GDXSDname) * 2 + 7, 1);
5387 		if(utlbuf == NULL)
5388 		{
5389 		    HEpush(DFE_NOSPACE,"GDdetach", __FILE__, __LINE__);
5390 		    free(nambuf);
5391 		    free(nameptr);
5392 		    free(namelen);
5393 		    free(nameptr0);
5394 		    free(namelen0);
5395 		    free(dimptr);
5396 		    free(dimlen);
5397 		    free(offset);
5398 		    return(-1);
5399 		}
5400 
5401 		for (k = 0; k < sizeof(dimbuf1); k++)
5402 		    dimbuf1[k] = 0;
5403 
5404 
5405 		/* Load array to match, name & parse dims */
5406 		/* -------------------------------------- */
5407 		memcpy(match, &GDXSDcomb[5 * i], 20);
5408 		memcpy(nambuf, nameptr[i], namelen[i]);
5409 
5410 		memcpy(dimbuf1, dimptr[i], dimlen[i]);
5411 		dum = EHparsestr(dimbuf1, ',', ptr1, slen1);
5412 
5413 
5414 		/* Separate combined dimension from others */
5415 		/* --------------------------------------- */
5416 		dimbuf1[slen1[0]] = 0;
5417 
5418 		offset[0] = 0;
5419 		indvdims[0] = abs(match[0]);
5420 
5421 		for (j = i + 1, cmbfldcnt = 0; j < nflds; j++)
5422 		{
5423 		    for (k = 0; k < sizeof(dimbuf2); k++)
5424 			dimbuf2[k] = 0;
5425 		    memcpy(dimbuf2, dimptr[j], dimlen[j]);
5426 		    dum = EHparsestr(dimbuf2, ',', ptr2, slen2);
5427 		    dimbuf2[slen2[0]] = 0;
5428 
5429 
5430 		    if (GDXSDcomb[5 * j] != 0 &&
5431 			strcmp(dimbuf1 + slen1[0],
5432 			       dimbuf2 + slen2[0]) == 0 &&
5433 			match[1] == GDXSDcomb[5 * j + 1] &&
5434 			match[2] == GDXSDcomb[5 * j + 2] &&
5435 			match[3] == GDXSDcomb[5 * j + 3] &&
5436 			match[4] == GDXSDcomb[5 * j + 4])
5437 		    {
5438 			/* Add to combined dimension size */
5439 			match[0] += GDXSDcomb[5 * j];
5440 
5441 			/* Concatanate name */
5442 			strcat(nambuf, ",");
5443 			memcpy(nambuf + strlen(nambuf),
5444 			       nameptr[j], namelen[j]);
5445 
5446 			/* Store individual dims and dim offsets */
5447 			cmbfldcnt++;
5448 			indvdims[cmbfldcnt] = abs(GDXSDcomb[5 * j]);
5449 			offset[cmbfldcnt] =
5450 			    offset[cmbfldcnt - 1] + indvdims[cmbfldcnt - 1];
5451 
5452 			GDXSDcomb[5 * j] = 0;
5453 		    }
5454 		}
5455 
5456 
5457 		/* Create SDS */
5458 		/* ---------- */
5459 		nflds0 = EHparsestr(nambuf, ',', nameptr0, namelen0);
5460 
5461 		if (abs(match[0]) == 1)
5462 		{
5463 		    for (k = 0; k < 2; k++)
5464 			dims[k] = abs(match[k + 1]);
5465 
5466 		    rank = 2;
5467 
5468 		    sdid = SDcreate(sdInterfaceID, nambuf,
5469 				    GDXSDcomb[5 * i + 4], 2, dims);
5470 		}
5471 		else
5472 		{
5473 		    for (k = 0; k < 3; k++)
5474 			dims[k] = abs(match[k]);
5475 
5476 		    rank = 3;
5477 
5478 		    if (cmbfldcnt > 0)
5479 		    {
5480 			strcpy(utlbuf, "MRGFLD_");
5481 			memcpy(utlbuf + 7, nameptr0[0], namelen0[0]);
5482 			utlbuf[7 + namelen0[0]] = 0;
5483 			strcat(utlbuf, ":");
5484 			strcat(utlbuf, nambuf);
5485 
5486 			status = EHinsertmeta(sdInterfaceID, gridname, "g",
5487 					      6L, utlbuf, NULL);
5488 		    }
5489 		    else
5490 		    {
5491 			strcpy(utlbuf, nambuf);
5492 		    }
5493 
5494 		    sdid = SDcreate(sdInterfaceID, utlbuf,
5495 				    GDXSDcomb[5 * i + 4], 3, dims);
5496 
5497 
5498 		    if (cmbfldcnt > 0)
5499 		    {
5500 			SDsetattr(sdid, "Field Dims", DFNT_INT32,
5501 				  cmbfldcnt + 1, (VOIDP) indvdims);
5502 
5503 			SDsetattr(sdid, "Field Offsets", DFNT_INT32,
5504 				  cmbfldcnt + 1, (VOIDP) offset);
5505 		    }
5506 
5507 		}
5508 
5509 
5510 
5511 		/* Register Dimensions in SDS */
5512 		/* -------------------------- */
5513 		for (k = 0; k < rank; k++)
5514 		{
5515 		    if (rank == 2)
5516 		    {
5517 			memcpy(dimbuf2, ptr1[k + 1], slen1[k + 1]);
5518 			dimbuf2[slen1[k + 1]] = 0;
5519 		    }
5520 		    else
5521 		    {
5522 			memcpy(dimbuf2, ptr1[k], slen1[k]);
5523 			dimbuf2[slen1[k]] = 0;
5524 		    }
5525 
5526 
5527 		    if (k == 0 && rank > 2 && cmbfldcnt > 0)
5528 		    {
5529 			sprintf(dimbuf2, "%s%s_%d", "MRGDIM:",
5530 				gridname, (int)dims[0]);
5531 		    }
5532 		    else
5533 		    {
5534 			strcat(dimbuf2, ":");
5535 			strcat(dimbuf2, gridname);
5536 		    }
5537 		    SDsetdimname(SDgetdimid(sdid, k), (char *) dimbuf2);
5538 		}
5539 
5540 
5541 
5542 		/* Write Fill Value */
5543 		/* ---------------- */
5544 		for (k = 0; k < nflds0; k++)
5545 		{
5546 		    memcpy(utlbuf, nameptr0[k], namelen0[k]);
5547 		    utlbuf[namelen[k]] = 0;
5548 		    statusFill = GDgetfillvalue(gridID, utlbuf, fillval);
5549 
5550 		    if (statusFill == 0)
5551 		    {
5552 			if (cmbfldcnt > 0)
5553 			{
5554 			    dims[0] = indvdims[k];
5555 			    truerank = (dims[0] == 1) ? 2 : 3;
5556 			    EHfillfld(sdid, rank, truerank,
5557 				      DFKNTsize(match[4]), offset[k],
5558 				      dims, fillval);
5559 			}
5560 			else
5561 			{
5562 			    status = SDsetfillvalue(sdid, fillval);
5563 			}
5564 		    }
5565 		}
5566 
5567 
5568 		vgid = GDXGrid[gID].VIDTable[0];
5569 		Vaddtagref(vgid, DFTAG_NDG, SDidtoref(sdid));
5570 		SDendaccess(sdid);
5571 
5572 		free(nambuf);
5573 		free(utlbuf);
5574 
5575 	    }
5576 	}
5577 
5578 
5579 	for (i = 0; i < nflds; i++)
5580 	{
5581 	    if (GDXSDcomb[5 * i + 3] == GDXGrid[gID].IDTable)
5582 	    {
5583 		if (i == (nflds - 1))
5584 		{
5585 		    GDXSDcomb[5 * i] = 0;
5586 		    *(nameptr[i] - (nflds != 1)) = 0;
5587 		    *(dimptr[i] - (nflds != 1)) = 0;
5588 		}
5589 		else
5590 		{
5591 		    /* memcpy(&GDXSDcomb[5 * i],
5592 			   &GDXSDcomb[5 * (i + 1)],
5593 			   (512 - i - 1) * 5 * 4);*/
5594 		    memmove(&GDXSDcomb[5 * i],
5595 			   &GDXSDcomb[5 * (i + 1)],
5596 			   (512 - i - 1) * 5 * 4);
5597 		   /* memcpy(nameptr[i],
5598 			   nameptr[i + 1],
5599 			   nameptr[0] + 2048 - nameptr[i + 1] - 1);*/
5600 		    memmove(nameptr[i],
5601 			   nameptr[i + 1],
5602 			   nameptr[0] + 2048 - nameptr[i + 1] - 1);
5603 		    /* memcpy(dimptr[i],
5604 			   dimptr[i + 1],
5605 			   dimptr[0] + 2048 * 2 - dimptr[i + 1] - 1);*/
5606 		    memmove(dimptr[i],
5607 			   dimptr[i + 1],
5608 			   dimptr[0] + 2048 * 2 - dimptr[i + 1] - 1);
5609 		}
5610 
5611 		i--;
5612 		nflds = EHparsestr(GDXSDname, ',', nameptr, namelen);
5613 		nflds = EHparsestr(GDXSDdims, ';', dimptr, dimlen);
5614 	    }
5615 	}
5616 
5617 	if (nflds != 0)
5618 	{
5619 	    strcat(GDXSDname, ",");
5620 	    strcat(GDXSDdims, ";");
5621 	}
5622 
5623 
5624 
5625 	/* Free up a bunch of dynamically allocated arrays */
5626 	/* ----------------------------------------------- */
5627 	free(nameptr);
5628 	free(namelen);
5629 	free(nameptr0);
5630 	free(namelen0);
5631 	free(dimptr);
5632 	free(dimlen);
5633 	free(offset);
5634 	free(indvdims);
5635 
5636 
5637 
5638 	/* "Detach" from previously attached SDSs */
5639 	/* -------------------------------------- */
5640 	for (k = 0; k < GDXGrid[gID].nSDS; k++)
5641 	{
5642 	    SDendaccess(GDXGrid[gID].sdsID[k]);
5643 	}
5644 	free(GDXGrid[gID].sdsID);
5645 	GDXGrid[gID].sdsID = 0;
5646 	GDXGrid[gID].nSDS = 0;
5647 
5648 
5649 
5650 	/* Detach Grid Vgroups */
5651 	/* ------------------- */
5652 	Vdetach(GDXGrid[gID].VIDTable[0]);
5653 	Vdetach(GDXGrid[gID].VIDTable[1]);
5654 	Vdetach(GDXGrid[gID].IDTable);
5655 
5656 	GDXGrid[gID].active = 0;
5657 	GDXGrid[gID].VIDTable[0] = 0;
5658 	GDXGrid[gID].VIDTable[1] = 0;
5659 	GDXGrid[gID].IDTable = 0;
5660 	GDXGrid[gID].fid = 0;
5661 
5662 
5663 
5664 
5665 	/* Free Region Pointers */
5666 	/* -------------------- */
5667 	for (k = 0; k < NGRIDREGN; k++)
5668 	{
5669 	    if (GDXRegion[k] != 0 &&
5670 		GDXRegion[k]->gridID == gridID)
5671 	    {
5672 		for (i = 0; i < 8; i++)
5673 		{
5674 		    if (GDXRegion[k]->DimNamePtr[i] != 0)
5675 		    {
5676 			free(GDXRegion[k]->DimNamePtr[i]);
5677 			GDXRegion[k]->DimNamePtr[i] = 0;
5678 		    }
5679 		}
5680 
5681 		free(GDXRegion[k]);
5682 		GDXRegion[k] = 0;
5683 	    }
5684 	}
5685     }
5686     return (status);
5687 }
5688 
5689 
5690 /*----------------------------------------------------------------------------|
5691 |  BEGIN_PROLOG                                                               |
5692 |                                                                             |
5693 |  FUNCTION: GDclose                                                          |
5694 |                                                                             |
5695 |  DESCRIPTION: Closes file.                                                  |
5696 |                                                                             |
5697 |                                                                             |
5698 |  Return Value    Type     Units     Description                             |
5699 |  ============   ======  =========   =====================================   |
5700 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
5701 |                                                                             |
5702 |  INPUTS:                                                                    |
5703 |  fid            int32               File ID                                 |
5704 |                                                                             |
5705 |                                                                             |
5706 |  OUTPUTS:                                                                   |
5707 |             None                                                            |
5708 |                                                                             |
5709 |  NOTES:                                                                     |
5710 |                                                                             |
5711 |                                                                             |
5712 |   Date     Programmer   Description                                         |
5713 |  ======   ============  =================================================   |
5714 |  Jun 96   Joel Gales    Original Programmer                                 |
5715 |                                                                             |
5716 |  END_PROLOG                                                                 |
5717 -----------------------------------------------------------------------------*/
5718 intn
GDclose(int32 fid)5719 GDclose(int32 fid)
5720 
5721 {
5722     intn            status = 0;	/* routine return status variable */
5723 
5724     /* Call EHclose to perform file close */
5725     /* ---------------------------------- */
5726     status = EHclose(fid);
5727 
5728     return (status);
5729 }
5730 
5731 
5732 /*----------------------------------------------------------------------------|
5733 |  BEGIN_PROLOG                                                               |
5734 |                                                                             |
5735 |  FUNCTION: GDgetdefaults                                                    |
5736 |                                                                             |
5737 |  DESCRIPTION:                                                               |
5738 |                                                                             |
5739 |                                                                             |
5740 |  Return Value    Type     Units     Description                             |
5741 |  ============   ======  =========   =====================================   |
5742 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
5743 |                                                                             |
5744 |  INPUTS:                                                                    |
5745 |  projcode       int32               GCTP projection code                    |
5746 |  zonecode       int32               UTM zone code                           |
5747 |  projparm       float64             Projection parameters                   |
5748 |  spherecode     int32               GCTP spheriod code                      |
5749 |  upleftpt       float64             upper left corner coordinates           |
5750 |  lowrightpt     float64             lower right corner coordinates          |
5751 |                                                                             |
5752 |                                                                             |
5753 |  OUTPUTS:                                                                   |
5754 |  upleftpt       float64             upper left corner coordinates           |
5755 |  lowrightpt     float64             lower right corner coordinates          |
5756 |                                                                             |
5757 |  NOTES:                                                                     |
5758 |                                                                             |
5759 |                                                                             |
5760 |   Date     Programmer   Description                                         |
5761 |  ======   ============  =================================================   |
5762 |  Aug 96   Joel Gales    Original Programmer                                 |
5763 |  Sep 96   Raj Gejjaga   Fixed  bugs in Polar Stereographic and Goode        | |                         Homolosine default calculations.                    |
5764 |  Sep 96   Raj Gejjaga   Added code to compute default boundary points       |
5765 |                         for Lambert Azimuthal Polar and Equitorial          |
5766 |                         projections.                                        |
5767 |  Feb 97   Raj Gejjaga   Added code to compute default boundary points       |
5768 |                         for Integerized Sinusoidal Grid.  Added error       |
5769 |                         handling code.                                      |
5770 |  Jun 00   Abe Taaheri   Added support for EASE grid                         |
5771 |                                                                             |
5772 |  END_PROLOG                                                                 |
5773 -----------------------------------------------------------------------------*/
5774 static intn
GDgetdefaults(int32 projcode,int32 zonecode,float64 projparm[],int32 spherecode,float64 upleftpt[],float64 lowrightpt[])5775 GDgetdefaults(int32 projcode, int32 zonecode, float64 projparm[],
5776 	      int32 spherecode, float64 upleftpt[], float64 lowrightpt[])
5777 {
5778     int32           errorcode = 0, status = 0;
5779     int32(*for_trans[100]) ();
5780 
5781     float64         lon, lat, plat, x, y;
5782     float64         plon, tlon, llon, rlon, pplon, LLon, LLat, RLon, RLat;
5783 
5784 
5785     /* invoke GCTP initialization routine */
5786     /* ---------------------------------- */
5787     for_init(projcode, zonecode, projparm, spherecode, NULL, NULL,
5788 	     &errorcode, for_trans);
5789 
5790     /* Report error if any */
5791     /* ------------------- */
5792     if (errorcode != 0)
5793     {
5794 	status = -1;
5795 	HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
5796 	HEreport("GCTP Error: %d\n", errorcode);
5797 	return (status);
5798     }
5799 
5800     /* Compute Default Boundary Points for EASE Grid          */
5801     /* Use Global coverage */
5802     /* ------------------------------------------------------ */
5803     if (projcode == GCTP_BCEA &&
5804 	upleftpt[0] == 0 && upleftpt[1] == 0 &&
5805 	lowrightpt[0] == 0 && lowrightpt[1] == 0)
5806     {
5807 	upleftpt[0] = EHconvAng(EASE_GRID_DEFAULT_UPLEFT_LON, HDFE_DEG_DMS);
5808 	upleftpt[1] = EHconvAng(EASE_GRID_DEFAULT_UPLEFT_LAT, HDFE_DEG_DMS);
5809 	lowrightpt[0] = EHconvAng(EASE_GRID_DEFAULT_LOWRGT_LON, HDFE_DEG_DMS);
5810 	lowrightpt[1] = EHconvAng(EASE_GRID_DEFAULT_LOWRGT_LAT, HDFE_DEG_DMS);
5811     }
5812 
5813 /* Compute Default Boundary Points for CEA     */
5814    /* --------------------------------------------*/
5815    if (projcode == GCTP_CEA &&
5816       upleftpt[0] == 0 && upleftpt[1] == 0 &&
5817       lowrightpt[0] == 0 && lowrightpt[1] == 0)
5818     {
5819       LLon = EHconvAng(EASE_GRID_DEFAULT_UPLEFT_LON, HDFE_DEG_RAD);
5820       LLat = EHconvAng(EASE_GRID_DEFAULT_UPLEFT_LAT, HDFE_DEG_RAD);
5821       RLon = EHconvAng(EASE_GRID_DEFAULT_LOWRGT_LON, HDFE_DEG_RAD);
5822       RLat = EHconvAng(EASE_GRID_DEFAULT_LOWRGT_LAT, HDFE_DEG_RAD);
5823 
5824       errorcode = for_trans[projcode] (LLon, LLat, &x, &y);
5825       if (errorcode != 0)
5826       {
5827            status = -1;
5828            HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
5829            HEreport("GCTP Error: %d\n", errorcode);
5830            return (status);
5831       }
5832         upleftpt[0] = x;
5833         upleftpt[1] = y;
5834 
5835       errorcode = for_trans[projcode] (RLon, RLat, &x, &y);
5836       if (errorcode != 0)
5837       {
5838            status = -1;
5839            HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
5840            HEreport("GCTP Error: %d\n", errorcode);
5841            return (status);
5842       }
5843       lowrightpt[0] = x;
5844       lowrightpt[1] = y;
5845 
5846     }
5847 
5848 
5849     /* Compute Default Boundary Points for Polar Sterographic */
5850     /* ------------------------------------------------------ */
5851     if (projcode == GCTP_PS &&
5852 	upleftpt[0] == 0 && upleftpt[1] == 0 &&
5853 	lowrightpt[0] == 0 && lowrightpt[1] == 0)
5854     {
5855 	/*
5856 	 * Convert the longitude and latitude from the DMS to decimal degree
5857 	 * format.
5858 	 */
5859 	plon = EHconvAng(projparm[4], HDFE_DMS_DEG);
5860 	plat = EHconvAng(projparm[5], HDFE_DMS_DEG);
5861 
5862 	/*
5863 	 * Compute the longitudes at 90, 180 and 270 degrees from the central
5864 	 * longitude.
5865 	 */
5866 
5867 	if (plon <= 0.0)
5868 	{
5869 	    tlon = 180.0 + plon;
5870 	    pplon = plon + 360.0;
5871 	}
5872 	else
5873 	{
5874 	    tlon = plon - 180.0;
5875 	    pplon = plon;
5876 	}
5877 
5878 	rlon = pplon + 90.0;
5879 	if (rlon > 360.0)
5880 	    rlon = rlon - 360;
5881 
5882 	if (rlon > 180.0)
5883 	    rlon = rlon - 360.0;
5884 
5885 	if (rlon <= 0.0)
5886 	    llon = 180.0 + rlon;
5887 	else
5888 	    llon = rlon - 180.0;
5889 
5890 
5891 	/* Convert all four longitudes from decimal degrees to radians */
5892 	plon = EHconvAng(plon, HDFE_DEG_RAD);
5893 	tlon = EHconvAng(tlon, HDFE_DEG_RAD);
5894 	llon = EHconvAng(llon, HDFE_DEG_RAD);
5895 	rlon = EHconvAng(rlon, HDFE_DEG_RAD);
5896 
5897 	errorcode = for_trans[projcode] (llon, 0.0, &x, &y);
5898 	if (errorcode != 0)
5899 	{
5900 	    status = -1;
5901 	    HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
5902 	    HEreport("GCTP Error: %d\n", errorcode);
5903 	    return (status);
5904 	}
5905 
5906 	upleftpt[0] = x;
5907 
5908 	errorcode = for_trans[projcode] (rlon, 0.0, &x, &y);
5909 	if (errorcode != 0)
5910 	{
5911 	    status = -1;
5912 	    HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
5913 	    HEreport("GCTP Error: %d\n", errorcode);
5914 	    return (status);
5915 	}
5916 
5917 	lowrightpt[0] = x;
5918 
5919 	/*
5920 	 * Compute the upperleft and lowright y values based on the south or
5921 	 * north polar projection
5922 	 */
5923 
5924 	if (plat < 0.0)
5925 	{
5926 	    errorcode = for_trans[projcode] (plon, 0.0, &x, &y);
5927 	    if (errorcode != 0)
5928 	    {
5929 		status = -1;
5930 		HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
5931 		HEreport("GCTP Error: %d\n", errorcode);
5932 		return (status);
5933 	    }
5934 
5935 	    upleftpt[1] = y;
5936 
5937 	    errorcode = for_trans[projcode] (tlon, 0.0, &x, &y);
5938 	    if (errorcode != 0)
5939 	    {
5940 		status = -1;
5941 		HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
5942 		HEreport("GCTP Error: %d\n", errorcode);
5943 		return (status);
5944 	    }
5945 
5946 	    lowrightpt[1] = y;
5947 
5948 	}
5949 	else
5950 	{
5951 	    errorcode = for_trans[projcode] (tlon, 0.0, &x, &y);
5952 	    if (errorcode != 0)
5953 	    {
5954 		status = -1;
5955 		HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
5956 		HEreport("GCTP Error: %d\n", errorcode);
5957 		return (status);
5958 	    }
5959 
5960 	    upleftpt[1] = y;
5961 
5962 	    errorcode = for_trans[projcode] (plon, 0.0, &x, &y);
5963 	    if (errorcode != 0)
5964 	    {
5965 		status = -1;
5966 		HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
5967 		HEreport("GCTP Error: %d\n", errorcode);
5968 		return (status);
5969 	    }
5970 
5971 	    lowrightpt[1] = y;
5972 
5973 	}
5974     }
5975 
5976 
5977     /* Compute Default Boundary Points for Goode Homolosine */
5978     /* ---------------------------------------------------- */
5979     if (projcode == GCTP_GOOD &&
5980 	upleftpt[0] == 0 && upleftpt[1] == 0 &&
5981 	lowrightpt[0] == 0 && lowrightpt[1] == 0)
5982     {
5983 	lon = EHconvAng(-180, HDFE_DEG_RAD);
5984 	lat = 0.0;
5985 
5986 	errorcode = for_trans[projcode] (lon, lat, &x, &y);
5987 	if (errorcode != 0)
5988 	{
5989 	    status = -1;
5990 	    HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
5991 	    HEreport("GCTP Error: %d\n", errorcode);
5992 	    return (status);
5993 	}
5994 
5995 	upleftpt[0] = -fabs(x);
5996 	lowrightpt[0] = +fabs(x);
5997 
5998 	lat = EHconvAng(90, HDFE_DEG_RAD);
5999 
6000 	errorcode = for_trans[projcode] (lon, lat, &x, &y);
6001 	if (errorcode != 0)
6002 	{
6003 	    status = -1;
6004 	    HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
6005 	    HEreport("GCTP Error: %d\n", errorcode);
6006 	    return (status);
6007 	}
6008 
6009 	upleftpt[1] = +fabs(y);
6010 	lowrightpt[1] = -fabs(y);
6011     }
6012 
6013     /* Compute Default Boundary Points for Lambert Azimuthal */
6014     /* ----------------------------------------------------- */
6015     if (projcode == GCTP_LAMAZ &&
6016 	upleftpt[0] == 0 && upleftpt[1] == 0 &&
6017 	lowrightpt[0] == 0 && lowrightpt[1] == 0)
6018     {
6019 	/*
6020 	 * Convert the longitude and latitude from the DMS to decimal degree
6021 	 * format.
6022 	 */
6023 	plon = EHconvAng(projparm[4], HDFE_DMS_DEG);
6024 	plat = EHconvAng(projparm[5], HDFE_DMS_DEG);
6025 
6026 	/*
6027 	 * Compute the longitudes at 90, 180 and 270 degrees from the central
6028 	 * longitude.
6029 	 */
6030 
6031 	if (plon <= 0.0)
6032 	{
6033 	    tlon = 180.0 + plon;
6034 	    pplon = plon + 360.0;
6035 	}
6036 	else
6037 	{
6038 	    tlon = plon - 180.0;
6039 	    pplon = plon;
6040 	}
6041 
6042 	rlon = pplon + 90.0;
6043 	if (rlon > 360.0)
6044 	    rlon = rlon - 360;
6045 
6046 	if (rlon > 180.0)
6047 	    rlon = rlon - 360.0;
6048 
6049 	if (rlon <= 0.0)
6050 	    llon = 180.0 + rlon;
6051 	else
6052 	    llon = rlon - 180.0;
6053 
6054 	/* Convert all four longitudes from decimal degrees to radians */
6055 	plon = EHconvAng(plon, HDFE_DEG_RAD);
6056 	tlon = EHconvAng(tlon, HDFE_DEG_RAD);
6057 	llon = EHconvAng(llon, HDFE_DEG_RAD);
6058 	rlon = EHconvAng(rlon, HDFE_DEG_RAD);
6059 
6060 	errorcode = for_trans[projcode] (llon, 0.0, &x, &y);
6061 	if (errorcode != 0)
6062 	{
6063 	    status = -1;
6064 	    HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
6065 	    HEreport("GCTP Error: %d\n", errorcode);
6066 	    return (status);
6067 	}
6068 
6069 	upleftpt[0] = x;
6070 
6071 	errorcode = for_trans[projcode] (rlon, 0.0, &x, &y);
6072 	if (errorcode != 0)
6073 	{
6074 	    status = -1;
6075 	    HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
6076 	    HEreport("GCTP Error: %d\n", errorcode);
6077 	    return (status);
6078 	}
6079 
6080 	lowrightpt[0] = x;
6081 
6082 	/*
6083 	 * Compute upperleft and lowerright values based on whether the
6084 	 * projection is south polar, north polar or equitorial
6085 	 */
6086 
6087 	if (plat == -90.0)
6088 	{
6089 	    errorcode = for_trans[projcode] (plon, 0.0, &x, &y);
6090 	    if (errorcode != 0)
6091 	    {
6092 		status = -1;
6093 		HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
6094 		HEreport("GCTP Error: %d\n", errorcode);
6095 		return (status);
6096 	    }
6097 
6098 	    upleftpt[1] = y;
6099 
6100 	    errorcode = for_trans[projcode] (tlon, 0.0, &x, &y);
6101 	    if (errorcode != 0)
6102 	    {
6103 		status = -1;
6104 		HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
6105 		HEreport("GCTP Error: %d\n", errorcode);
6106 		return (status);
6107 	    }
6108 
6109 	    lowrightpt[1] = y;
6110 	}
6111 	else if (plat == 90.0)
6112 	{
6113 	    errorcode = for_trans[projcode] (tlon, 0.0, &x, &y);
6114 	    if (errorcode != 0)
6115 	    {
6116 		status = -1;
6117 		HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
6118 		HEreport("GCTP Error: %d\n", errorcode);
6119 		return (status);
6120 	    }
6121 
6122 	    upleftpt[1] = y;
6123 
6124 	    errorcode = for_trans[projcode] (plon, 0.0, &x, &y);
6125 	    if (errorcode != 0)
6126 	    {
6127 		status = -1;
6128 		HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
6129 		HEreport("GCTP Error: %d\n", errorcode);
6130 		return (status);
6131 	    }
6132 
6133 	    lowrightpt[1] = y;
6134 	}
6135 	else
6136 	{
6137 	    lat = EHconvAng(90, HDFE_DEG_RAD);
6138 	    errorcode = for_trans[projcode] (plon, lat, &x, &y);
6139 	    if (errorcode != 0)
6140 	    {
6141 		status = -1;
6142 		HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
6143 		HEreport("GCTP Error: %d\n", errorcode);
6144 		return (status);
6145 	    }
6146 
6147 	    upleftpt[1] = y;
6148 
6149 	    lat = EHconvAng(-90, HDFE_DEG_RAD);
6150 	    errorcode = for_trans[projcode] (plon, lat, &x, &y);
6151 	    if (errorcode != 0)
6152 	    {
6153 		status = -1;
6154 		HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
6155 		HEreport("GCTP Error: %d\n", errorcode);
6156 		return (status);
6157 	    }
6158 
6159 	    lowrightpt[1] = y;
6160 	}
6161     }
6162 
6163     /* Compute Default Boundary Points for Integerized Sinusoidal Grid */
6164     /* --------------------------------------------------------------- */
6165     if (((projcode == GCTP_ISINUS) || (projcode == GCTP_ISINUS1)) &&
6166 	upleftpt[0] == 0 && upleftpt[1] == 0 &&
6167 	lowrightpt[0] == 0 && lowrightpt[1] == 0)
6168     {
6169 	/*
6170 	 * Convert the longitude and latitude from the DMS to decimal degree
6171 	 * format.
6172 	 */
6173 	plon = EHconvAng(projparm[4], HDFE_DMS_DEG);
6174 	plat = EHconvAng(projparm[5], HDFE_DMS_DEG);
6175 
6176 	/*
6177 	 * Compute the longitudes at 90, 180 and 270 degrees from the central
6178 	 * longitude.
6179 	 */
6180 
6181 	if (plon <= 0.0)
6182 	{
6183 	    tlon = 180.0 + plon;
6184 	    pplon = plon + 360.0;
6185 	}
6186 	else
6187 	{
6188 	    tlon = plon - 180.0;
6189 	    pplon = plon;
6190 	}
6191 
6192 	rlon = pplon + 90.0;
6193 	if (rlon > 360.0)
6194 	    rlon = rlon - 360;
6195 
6196 	if (rlon > 180.0)
6197 	    rlon = rlon - 360.0;
6198 
6199 	if (rlon <= 0.0)
6200 	    llon = 180.0 + rlon;
6201 	else
6202 	    llon = rlon - 180.0;
6203 
6204 	/* Convert all four longitudes from decimal degrees to radians */
6205 	plon = EHconvAng(plon, HDFE_DEG_RAD);
6206 	tlon = EHconvAng(tlon, HDFE_DEG_RAD);
6207 	llon = EHconvAng(llon, HDFE_DEG_RAD);
6208 	rlon = EHconvAng(rlon, HDFE_DEG_RAD);
6209 
6210 	errorcode = for_trans[projcode] (llon, 0.0, &x, &y);
6211 	if (errorcode != 0)
6212 	{
6213 	    status = -1;
6214 	    HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
6215 	    HEreport("GCTP Error: %d\n", errorcode);
6216 	    return (status);
6217 	}
6218 
6219 	upleftpt[0] = x;
6220 
6221 	errorcode = for_trans[projcode] (rlon, 0.0, &x, &y);
6222 	if (errorcode != 0)
6223 	{
6224 	    status = -1;
6225 	    HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
6226 	    HEreport("GCTP Error: %d\n", errorcode);
6227 	    return (status);
6228 	}
6229 
6230 	lowrightpt[0] = x;
6231 
6232 	lat = EHconvAng(90, HDFE_DEG_RAD);
6233 	errorcode = for_trans[projcode] (plon, lat, &x, &y);
6234 	if (errorcode != 0)
6235 	{
6236 	    status = -1;
6237 	    HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
6238 	    HEreport("GCTP Error: %d\n", errorcode);
6239 	    return (status);
6240 	}
6241 
6242 	upleftpt[1] = y;
6243 
6244 	lat = EHconvAng(-90, HDFE_DEG_RAD);
6245 	errorcode = for_trans[projcode] (plon, lat, &x, &y);
6246 	if (errorcode != 0)
6247 	{
6248 	    status = -1;
6249 	    HEpush(DFE_GENAPP, "GDgetdefaults", __FILE__, __LINE__);
6250 	    HEreport("GCTP Error: %d\n", errorcode);
6251 	    return (status);
6252 	}
6253 
6254 	lowrightpt[1] = y;
6255     }
6256     return (errorcode);
6257 }
6258 
6259 /*----------------------------------------------------------------------------|
6260 |  BEGIN_PROLOG                                                               |
6261 |                                                                             |
6262 |  FUNCTION: GDll2ij                                                          |
6263 |                                                                             |
6264 |  DESCRIPTION:                                                               |
6265 |                                                                             |
6266 |                                                                             |
6267 |  Return Value    Type     Units     Description                             |
6268 |  ============   ======  =========   =====================================   |
6269 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
6270 |                                                                             |
6271 |  INPUTS:                                                                    |
6272 |  projcode       int32               GCTP projection code                    |
6273 |  zonecode       int32               UTM zone code                           |
6274 |  projparm       float64             Projection parameters                   |
6275 |  spherecode     int32               GCTP spheriod code                      |
6276 |  xdimsize       int32               xdimsize from GDcreate                  |
6277 |  ydimsize       int32               ydimsize from GDcreate                  |
6278 |  upleftpt       float64             upper left corner coordinates           |
6279 |  lowrightpt     float64             lower right corner coordinates          |
6280 |  npnts          int32               number of lon-lat points                |
6281 |  longitude      float64             longitude array (radians)               |
6282 |  latitude       float64             latitude array (radians)                |
6283 |                                                                             |
6284 |  OUTPUTS:                                                                   |
6285 |  row            int32               Row array                               |
6286 |  col            int32               Column array                            |
6287 |  xval           float64             X value array                           |
6288 |  yval           float64             Y value array                           |
6289 |                                                                             |
6290 |                                                                             |
6291 |  NOTES:                                                                     |
6292 |                                                                             |
6293 |                                                                             |
6294 |   Date     Programmer   Description                                         |
6295 |  ======   ============  =================================================   |
6296 |  Jun 96   Joel Gales    Original Programmer                                 |
6297 |  Aug 96   Joel Gales    Return x and y values if requested                  |
6298 |  Jun 00   Abe Taaheri   Added support for EASE grid                         |
6299 |                                                                             |
6300 |  END_PROLOG                                                                 |
6301 -----------------------------------------------------------------------------*/
6302 static intn
GDll2ij(int32 projcode,int32 zonecode,float64 projparm[],int32 spherecode,int32 xdimsize,int32 ydimsize,float64 upleftpt[],float64 lowrightpt[],int32 npnts,float64 longitude[],float64 latitude[],int32 row[],int32 col[],float64 xval[],float64 yval[])6303 GDll2ij(int32 projcode, int32 zonecode, float64 projparm[],
6304 	int32 spherecode, int32 xdimsize, int32 ydimsize,
6305 	float64 upleftpt[], float64 lowrightpt[],
6306 	int32 npnts, float64 longitude[], float64 latitude[],
6307 	int32 row[], int32 col[], float64 xval[], float64 yval[])
6308 
6309 
6310 {
6311     intn            i;		/* Loop index */
6312     intn            status = 0;	/* routine return status variable */
6313 
6314     int32           errorcode = 0;	/* GCTP error code */
6315     int32(*for_trans[100]) ();	/* GCTP function pointer */
6316 
6317     float64         xVal;	/* Scaled x distance */
6318     float64         yVal;	/* Scaled y distance */
6319     float64         xMtr;	/* X value in meters from GCTP */
6320     float64         yMtr;	/* Y value in meters from GCTP */
6321     float64         lonrad0;	/* Longitude in radians of upleft point */
6322     float64         latrad0 = 0;	/* Latitude in radians of upleft point */
6323     float64         lonrad;	/* Longitude in radians of point */
6324     float64         latrad;	/* Latitude in radians of point */
6325     float64         scaleX;	/* X scale factor */
6326     float64         scaleY;	/* Y scale factor */
6327     float64         EHconvAng();/* Angle conversion routine */
6328     float64         xMtr0, xMtr1, yMtr0, yMtr1;
6329     float64         lonrad1;	/* Longitude in radians of lowright point */
6330 
6331     /* If projection not GEO call GCTP initialization routine */
6332     /* ------------------------------------------------------ */
6333     if (projcode != GCTP_GEO)
6334     {
6335 	for_init(projcode, zonecode, projparm, spherecode, NULL, NULL,
6336 		 &errorcode, for_trans);
6337 
6338 	/* Report error if any */
6339 	/* ------------------- */
6340 	if (errorcode != 0)
6341 	{
6342 	    status = -1;
6343 	    HEpush(DFE_GENAPP, "GDll2ij", __FILE__, __LINE__);
6344 	    HEreport("GCTP Error: %d\n", errorcode);
6345 	}
6346     }
6347 
6348 
6349     if (status == 0)
6350     {
6351 	/* GEO projection */
6352 	/* -------------- */
6353 	if (projcode == GCTP_GEO)
6354 	{
6355 	    /* Convert upleft and lowright X coords from DMS to radians */
6356 	    /* -------------------------------------------------------- */
6357 	    lonrad0 = EHconvAng(upleftpt[0], HDFE_DMS_RAD);
6358 	    lonrad = EHconvAng(lowrightpt[0], HDFE_DMS_RAD);
6359 
6360 	    /* Compute x scale factor */
6361 	    /* ---------------------- */
6362 	    scaleX = (lonrad - lonrad0) / xdimsize;
6363 
6364 
6365 	    /* Convert upleft and lowright Y coords from DMS to radians */
6366 	    /* -------------------------------------------------------- */
6367 	    latrad0 = EHconvAng(upleftpt[1], HDFE_DMS_RAD);
6368 	    latrad = EHconvAng(lowrightpt[1], HDFE_DMS_RAD);
6369 
6370 
6371 	    /* Compute y scale factor */
6372 	    /* ---------------------- */
6373 	    scaleY = (latrad - latrad0) / ydimsize;
6374 	}
6375 
6376 	/* BCEA projection */
6377         /* -------------- */
6378 	else if ( projcode == GCTP_BCEA)
6379 	{
6380 	    /* Convert upleft and lowright X coords from DMS to radians */
6381 	    /* -------------------------------------------------------- */
6382 
6383 	    lonrad0 = EHconvAng(upleftpt[0], HDFE_DMS_RAD);
6384 	    lonrad = EHconvAng(lowrightpt[0], HDFE_DMS_RAD);
6385 
6386 	    /* Convert upleft and lowright Y coords from DMS to radians */
6387 	    /* -------------------------------------------------------- */
6388 	    latrad0 = EHconvAng(upleftpt[1], HDFE_DMS_RAD);
6389 	    latrad = EHconvAng(lowrightpt[1], HDFE_DMS_RAD);
6390 
6391 	    /* Convert from lon/lat to meters(or whatever unit is, i.e unit
6392 	       of r_major and r_minor) using GCTP */
6393 	    /* ----------------------------------------- */
6394 	    errorcode = for_trans[projcode] (lonrad0, latrad0, &xMtr0, &yMtr0);
6395 
6396 
6397 	    /* Report error if any */
6398 	    /* ------------------- */
6399 	    if (errorcode != 0)
6400 	    {
6401 		status = -1;
6402 		HEpush(DFE_GENAPP, "GDll2ij", __FILE__, __LINE__);
6403 		HEreport("GCTP Error: %d\n", errorcode);
6404 		return (status);
6405 	    }
6406 
6407 	    /* Convert from lon/lat to meters(or whatever unit is, i.e unit
6408 	       of r_major and r_minor) using GCTP */
6409 	    /* ----------------------------------------- */
6410 	    errorcode = for_trans[projcode] (lonrad, latrad, &xMtr1, &yMtr1);
6411 
6412 
6413 	    /* Report error if any */
6414 	    /* ------------------- */
6415 	    if (errorcode != 0)
6416 	    {
6417 		status = -1;
6418 		HEpush(DFE_GENAPP, "GDll2ij", __FILE__, __LINE__);
6419 		HEreport("GCTP Error: %d\n", errorcode);
6420 		return (status);
6421 	    }
6422 
6423 	    /* Compute x scale factor */
6424 	    /* ---------------------- */
6425 	    scaleX = (xMtr1 - xMtr0) / xdimsize;
6426 
6427 	    /* Compute y scale factor */
6428 	    /* ---------------------- */
6429 	    scaleY = (yMtr1 - yMtr0) / ydimsize;
6430 	}
6431 	else
6432 	{
6433 	    /* Non-GEO, Non_BCEA projections */
6434 	    /* ---------------------------- */
6435 
6436 	    /* Compute x & y scale factors */
6437 	    /* --------------------------- */
6438 	    scaleX = (lowrightpt[0] - upleftpt[0]) / xdimsize;
6439 	    scaleY = (lowrightpt[1] - upleftpt[1]) / ydimsize;
6440 	}
6441 
6442 
6443 
6444 	/* Loop through all points */
6445 	/* ----------------------- */
6446 	for (i = 0; i < npnts; i++)
6447 	{
6448 	    /* Convert lon & lat from decimal degrees to radians */
6449 	    /* ------------------------------------------------- */
6450 	    lonrad = EHconvAng(longitude[i], HDFE_DEG_RAD);
6451 	    latrad = EHconvAng(latitude[i], HDFE_DEG_RAD);
6452 
6453 
6454 	    /* GEO projection */
6455 	    /* -------------- */
6456 	    if (projcode == GCTP_GEO)
6457 	    {
6458 	        /*allow map to span dateline */
6459 	        lonrad0 = EHconvAng(upleftpt[0], HDFE_DMS_RAD);
6460 	        lonrad1 = EHconvAng(lowrightpt[0], HDFE_DMS_RAD);
6461 		/* if time-line is paased */
6462 		if(lonrad < lonrad1)
6463 		  {
6464 		    if (lonrad < lonrad0) lonrad += 2.0 * M_PI1;
6465 		    if (lonrad > lonrad1) lonrad -= 2.0 * M_PI1;
6466 		  }
6467 
6468 		/* Compute scaled distance to point from origin */
6469 		/* -------------------------------------------- */
6470 		xVal = (lonrad - lonrad0) / scaleX;
6471 		yVal = (latrad - latrad0) / scaleY;
6472 	    }
6473 	    else
6474 	    {
6475 		/* Convert from lon/lat to meters using GCTP */
6476 		/* ----------------------------------------- */
6477 		errorcode = for_trans[projcode] (lonrad, latrad, &xMtr, &yMtr);
6478 
6479 
6480 		/* Report error if any */
6481 		/* ------------------- */
6482 		if (errorcode != 0)
6483 		{
6484 		  /*status = -1;
6485 		    HEpush(DFE_GENAPP, "GDll2ij", __FILE__, __LINE__);
6486 		    HEreport("GCTP Error: %d\n", errorcode);
6487 		    return (status); */                  /* Bruce Beaumont */
6488 		    xVal = -2147483648.0;	         /* Bruce Beaumont */
6489 		    yVal = -2147483648.0;	         /* Bruce Beaumont */
6490 		}/* (Note: MAXLONG is defined as 2147483647.0 in
6491 		    function cproj.c of GCTP) */
6492 		else {
6493 		  /* if projection is BCEA normalize x and y by cell size and
6494 		     measure it from the uperleft corner of the grid */
6495 
6496 		  /* Compute scaled distance to point from origin */
6497 		  /* -------------------------------------------- */
6498 		  if(  projcode == GCTP_BCEA)
6499 		    {
6500 		      xVal = (xMtr - xMtr0) / scaleX;
6501 		      yVal = (yMtr - yMtr0) / scaleY;
6502 		    }
6503 		  else
6504 		    {
6505 		      xVal = (xMtr - upleftpt[0]) / scaleX;
6506 		      yVal = (yMtr - upleftpt[1]) / scaleY;
6507 		    }
6508 		}
6509 	    }
6510 
6511 
6512 	    /* Compute row and col from scaled distance */
6513 	    /* ---------------------------------------- */
6514 	    col[i] = (int32) xVal;
6515 	    row[i] = (int32) yVal;
6516 
6517 	    /* Store scaled distances if requested */
6518 	    /* ----------------------------------- */
6519 	    if (xval != NULL)
6520 	    {
6521 		xval[i] = xVal;
6522 	    }
6523 
6524 	    if (yval != NULL)
6525 	    {
6526 		yval[i] = yVal;
6527 	    }
6528 	}
6529     }
6530     return (status);
6531 }
6532 
6533 
6534 
6535 
6536 /*----------------------------------------------------------------------------|
6537 |  BEGIN_PROLOG                                                               |
6538 |                                                                             |
6539 |  FUNCTION: GDrs2ll                                                          |
6540 |                                                                             |
6541 |  DESCRIPTION:  Converts EASE grid's (r,s) coordinates to longitude and      |
6542 |                latritude (in decimal degrees).                              |
6543 |                                                                             |
6544 |                                                                             |
6545 |  Return Value    Type     Units     Description                             |
6546 |  ============   ======  =========   =====================================   |
6547 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
6548 |                                                                             |
6549 |  INPUTS:                                                                    |
6550 |  projcode       int32               GCTP projection code                    |
6551 |  projparm       float64             Projection parameters                   |
6552 |  xdimsize       int32               xdimsize from GDcreate                  |
6553 |  ydimsize       int32               ydimsize from GDcreate                  |
6554 |  pixcen         int32               pixel center code                       |
6555 |  npnts          int32               number of lon-lat points                |
6556 |  s              int32               s coordinate                            |
6557 |  r              int32               r coordinate                            |
6558 |  pixcen         int32               Code from GDpixreginfo                  |
6559 |  pixcnr         int32               Code from GDorigininfo                  |
6560 |  upleft         float64             upper left corner coordinates (DMS)     |
6561 |  lowright       float64             lower right corner coordinates (DMS)    |
6562 |                                                                             |
6563 |                                                                             |
6564 |  OUTPUTS:                                                                   |
6565 |  longitude      float64             longitude array (decimal degrees)       |
6566 |  latitude       float64             latitude array  (decimal degrees)       |
6567 |                                                                             |
6568 |  NOTES:                                                                     |
6569 |                                                                             |
6570 |                                                                             |
6571 |   Date     Programmer   Description                                         |
6572 |  ======   ============  =================================================   |
6573 |  Jul 00   Abe Taaheri   Original Programmer                                 |
6574 |                                                                             |
6575 |  END_PROLOG                                                                 |
6576 -----------------------------------------------------------------------------*/
6577 intn
GDrs2ll(int32 projcode,float64 projparm[],int32 xdimsize,int32 ydimsize,float64 upleft[],float64 lowright[],int32 npnts,float64 r[],float64 s[],float64 longitude[],float64 latitude[],int32 pixcen,int32 pixcnr)6578 GDrs2ll(int32 projcode, float64 projparm[],
6579 	int32 xdimsize, int32 ydimsize,
6580 	float64 upleft[], float64 lowright[],
6581 	int32 npnts, float64 r[], float64 s[],
6582 	float64 longitude[], float64 latitude[], int32 pixcen, int32 pixcnr)
6583 {
6584     intn            i;		    /* Loop index */
6585     intn            status = 0;	    /* routine return status variable */
6586 
6587     int32           errorcode = 0;  /* GCTP error code */
6588     int32(*inv_trans[100]) ();	    /* GCTP function pointer */
6589 
6590     float64         pixadjX = 0.0;  /* Pixel adjustment (x) */
6591     float64         pixadjY = 0.0;  /* Pixel adjustment (y) */
6592     float64         lonrad;	    /* Longitude in radians of point */
6593     float64         latrad;	    /* Latitude in radians of point */
6594     float64         EHconvAng();    /* Angle conversion routine */
6595     float64         xMtr;	    /* X value in meters from GCTP */
6596     float64         yMtr;	    /* Y value in meters from GCTP */
6597     float64         epsilon;
6598     float64         beta;
6599     float64         qp_cea = 0;
6600     float64         kz_cea = 0;
6601     float64         eccen, eccen_sq;
6602     float64         phi1, sinphi1, cosphi1;
6603     float64         scaleX, scaleY;
6604 
6605     int32           zonecode=0;
6606 
6607     int32           spherecode=0;
6608     float64         lon[2],lat[2];
6609     float64         xcor[2], ycor[2];
6610     int32           nlatlon;
6611 
6612     /* If projection is BCEA define scale, r0 and s0 */
6613     if (projcode == GCTP_BCEA)
6614     {
6615 	eccen_sq = 1.0 - SQUARE(projparm[1]/projparm[0]);
6616 	eccen = sqrt(eccen_sq);
6617 	if(eccen < 0.00001)
6618 	  {
6619 	    qp_cea = 2.0;
6620 	  }
6621 	else
6622 	  {
6623 	    qp_cea =
6624 	      (1.0 - eccen_sq)*((1.0/(1.0 - eccen_sq))-(1.0/(2.0*eccen))*
6625 				log((1.0 - eccen)/(1.0 + eccen)));
6626 	  }
6627 	phi1 = EHconvAng(projparm[5],HDFE_DMS_RAD);
6628 	cosphi1 = cos(phi1);
6629 	sinphi1 = sin(phi1);
6630 	kz_cea = cosphi1/(sqrt(1.0 - (eccen_sq*sinphi1*sinphi1)));
6631     }
6632 
6633 
6634 
6635 
6636     /* Compute adjustment of position within pixel */
6637     /* ------------------------------------------- */
6638     if (pixcen == HDFE_CENTER)
6639     {
6640 	/* Pixel defined at center */
6641 	/* ----------------------- */
6642 	pixadjX = 0.5;
6643 	pixadjY = 0.5;
6644     }
6645     else
6646     {
6647 	switch (pixcnr)
6648 	{
6649 	case HDFE_GD_UL:
6650 	    {
6651 		/* Pixel defined at upper left corner */
6652 		/* ---------------------------------- */
6653 		pixadjX = 0.0;
6654 		pixadjY = 0.0;
6655 		break;
6656 	    }
6657 
6658 	case HDFE_GD_UR:
6659 	    {
6660 		/* Pixel defined at upper right corner */
6661 		/* ----------------------------------- */
6662 		pixadjX = 1.0;
6663 		pixadjY = 0.0;
6664 		break;
6665 	    }
6666 
6667 	case HDFE_GD_LL:
6668 	    {
6669 		/* Pixel defined at lower left corner */
6670 		/* ---------------------------------- */
6671 		pixadjX = 0.0;
6672 		pixadjY = 1.0;
6673 		break;
6674 	    }
6675 
6676 	case HDFE_GD_LR:
6677 	    {
6678 		/* Pixel defined at lower right corner */
6679 		/* ----------------------------------- */
6680 		pixadjX = 1.0;
6681 		pixadjY = 1.0;
6682 		break;
6683 	    }
6684 
6685 	}
6686     }
6687 
6688     /* If projection is BCEA call GCTP initialization routine */
6689     /* ------------------------------------------------------ */
6690     if (projcode == GCTP_BCEA)
6691     {
6692 
6693 	inv_init(projcode, 0, projparm, 0, NULL, NULL,
6694 		 &errorcode, inv_trans);
6695 
6696 	/* Report error if any */
6697 	/* ------------------- */
6698 	if (errorcode != 0)
6699 	{
6700 	    status = -1;
6701 	    HEpush(DFE_GENAPP, "GDrs2ll", __FILE__, __LINE__);
6702 	    HEreport("GCTP Error: %d\n", errorcode);
6703 	}
6704 	else
6705 	{
6706 	    /* For each point ... */
6707 	    /* ------------------ */
6708 	  for (i = 0; i < npnts; i++)
6709 	    {
6710 	      /* Convert from EASE grid's (r,s) to lon/lat (radians)
6711 		 using GCTP */
6712 	      /* --------------------------------------------------- */
6713 	      nlatlon = 2;
6714 	      lon[0] = upleft[0];
6715 	      lon[1] = lowright[0];
6716 	      lat[0] = upleft[1];
6717 	      lat[1] = lowright[1];
6718 	      status =
6719 		GDll2mm_cea(projcode,zonecode,spherecode,projparm,
6720 			    xdimsize, ydimsize,
6721 			    upleft, lowright, nlatlon,
6722 			    lon, lat,
6723 			    xcor, ycor, &scaleX, &scaleY);
6724 
6725 	      if (status == -1)
6726 		{
6727 		  HEpush(DFE_GENAPP, "GDrs2ll", __FILE__, __LINE__);
6728 		  return (status);
6729 		}
6730 
6731 	      xMtr = (r[i]/ scaleX + pixadjX - 0.5)* scaleX;
6732 	      yMtr = - (s[i]/fabs(scaleY) + pixadjY - 0.5)* fabs(scaleY);
6733 
6734 
6735 	      /* allow .5 cell tolerance in arcsin function
6736 		 (used in bceainv function) so that grid
6737 		 coordinates which are less than .5 cells
6738 		 above 90.00N or below 90.00S are given lat of 90.00
6739 	      */
6740 
6741 	      epsilon = 1 + 0.5 * (fabs(scaleY)/projparm[0]);
6742 	      beta = 2.0 * (yMtr - projparm[7]) * kz_cea/(projparm[0] * qp_cea);
6743 
6744 	      if( fabs (beta) > epsilon)
6745 		{
6746 		  status = -1;
6747 		  HEpush(DFE_GENAPP, "GDrs2ll", __FILE__, __LINE__);
6748 		  HEreport("GCTP Error: %s %s %s\n", "grid coordinates",
6749 			   "are more than .5 cells",
6750 			   "above 90.00N or below 90.00S. ");
6751 		  return (status);
6752 		}
6753 	      else if( beta <= -1)
6754 		{
6755 		  errorcode = inv_trans[projcode] (xMtr, 0.0,
6756 						   &lonrad, &latrad);
6757 		  latrad = - M_PI1/2;
6758 		}
6759 	      else if( beta >= 1)
6760 		{
6761 		  errorcode = inv_trans[projcode] (xMtr, 0.0,
6762 						   &lonrad, &latrad);
6763 		  latrad = M_PI1/2;
6764 		}
6765 	      else
6766 		{
6767 		  errorcode = inv_trans[projcode] (xMtr, yMtr,
6768 						   &lonrad, &latrad);
6769 		}
6770 
6771 	      /* Report error if any */
6772 	      /* ------------------- */
6773 	      if (errorcode != 0)
6774 		{
6775 		  status = -1;
6776 		  HEpush(DFE_GENAPP, "GDrs2ll", __FILE__, __LINE__);
6777 		  HEreport("GCTP Error: %d\n", errorcode);
6778 		  return (status);
6779 		}
6780 
6781 	      /* Convert from radians to decimal degrees */
6782 	      /* --------------------------------------- */
6783 	      longitude[i] = EHconvAng(lonrad, HDFE_RAD_DEG);
6784 	      latitude[i] = EHconvAng(latrad, HDFE_RAD_DEG);
6785 	    }
6786 	}
6787     }
6788 
6789 
6790 
6791 
6792     return (status);
6793 }
6794 
6795 
6796 
6797 /*----------------------------------------------------------------------------|
6798 |  BEGIN_PROLOG                                                               |
6799 |                                                                             |
6800 |  FUNCTION: lamaxDxDtheta                                                    |
6801 |                                                                             |
6802 |  DESCRIPTION: Partial derivative along longitude line for Lambert Azimuthal |
6803 |                                                                             |
6804 |                                                                             |
6805 |  Return Value    Type     Units     Description                             |
6806 |  ============   ======  =========   =====================================   |
6807 |                 float64             Dx/D(theta) for LAMAZ projection        |
6808 |                                                                             |
6809 |  INPUTS:                                                                    |
6810 |  parms          float64             Parameters defining partial derivative  |
6811 |                                                                             |
6812 |  OUTPUTS:                                                                   |
6813 |             None                                                            |
6814 |                                                                             |
6815 |  NOTES:                                                                     |
6816 |                                                                             |
6817 |                                                                             |
6818 |   Date     Programmer   Description                                         |
6819 |  ======   ============  =================================================   |
6820 |  Nov 96   Joel Gales    Original Programmer                                 |
6821 |                                                                             |
6822 |  END_PROLOG                                                                 |
6823 -----------------------------------------------------------------------------*/
6824 float64
lamazDxDtheta(float64 parms[])6825 lamazDxDtheta(float64 parms[])
6826 {
6827     float64         snTheta, sn2Theta, snTheta1, csTheta1, csLamda;
6828 
6829     snTheta = sin(EHconvAng(parms[0], HDFE_DEG_RAD));
6830     sn2Theta = sin(2 * EHconvAng(parms[0], HDFE_DEG_RAD));
6831     snTheta1 = sin(EHconvAng(parms[1], HDFE_DEG_RAD));
6832     csTheta1 = cos(EHconvAng(parms[1], HDFE_DEG_RAD));
6833     csLamda = cos(EHconvAng(parms[2], HDFE_DEG_RAD) -
6834 		  EHconvAng(parms[3], HDFE_DEG_RAD));
6835 
6836     return (4 * snTheta +
6837 	    (csTheta1 * csLamda * sn2Theta) +
6838 	    (2 * snTheta1 * (1 + (snTheta * snTheta))));
6839 }
6840 
6841 
6842 
6843 
6844 /*----------------------------------------------------------------------------|
6845 |  BEGIN_PROLOG                                                               |
6846 |                                                                             |
6847 |  FUNCTION: lamaxDxDlamda                                                    |
6848 |                                                                             |
6849 |  DESCRIPTION: Partial derivative along latitude line for Lambert Azimuthal  |
6850 |                                                                             |
6851 |                                                                             |
6852 |  Return Value    Type     Units     Description                             |
6853 |  ============   ======  =========   =====================================   |
6854 |                 float64             Dx/D(lamda) for LAMAZ projection        |
6855 |                                                                             |
6856 |  INPUTS:                                                                    |
6857 |  parms          float64             Parameters defining partial derivative  |
6858 |                                                                             |
6859 |  OUTPUTS:                                                                   |
6860 |             None                                                            |
6861 |                                                                             |
6862 |  NOTES:                                                                     |
6863 |                                                                             |
6864 |                                                                             |
6865 |   Date     Programmer   Description                                         |
6866 |  ======   ============  =================================================   |
6867 |  Nov 96   Joel Gales    Original Programmer                                 |
6868 |                                                                             |
6869 |  END_PROLOG                                                                 |
6870 -----------------------------------------------------------------------------*/
6871 float64
lamazDxDlamda(float64 parms[])6872 lamazDxDlamda(float64 parms[])
6873 {
6874     float64         snTheta, csTheta, snTheta1, csTheta1, csLamda;
6875     float64         cs, sn;
6876 
6877     snTheta = sin(EHconvAng(parms[2], HDFE_DEG_RAD));
6878     csTheta = cos(EHconvAng(parms[2], HDFE_DEG_RAD));
6879     snTheta1 = sin(EHconvAng(parms[1], HDFE_DEG_RAD));
6880     csTheta1 = cos(EHconvAng(parms[1], HDFE_DEG_RAD));
6881     csLamda = cos(EHconvAng(parms[0], HDFE_DEG_RAD) -
6882 		  EHconvAng(parms[3], HDFE_DEG_RAD));
6883 
6884     cs = csTheta * csTheta1;
6885     sn = snTheta * snTheta1;
6886 
6887     return (cs + (2 * (1 + sn) + (cs * csLamda)) * csLamda);
6888 }
6889 
6890 
6891 
6892 /*----------------------------------------------------------------------------|
6893 |  BEGIN_PROLOG                                                               |
6894 |                                                                             |
6895 |  FUNCTION: lamaxDyDtheta                                                    |
6896 |                                                                             |
6897 |  DESCRIPTION: Partial derivative along longitude line for Lambert Azimuthal |
6898 |                                                                             |
6899 |                                                                             |
6900 |  Return Value    Type     Units     Description                             |
6901 |  ============   ======  =========   =====================================   |
6902 |                 float64             Dy/D(theta) for LAMAZ projection        |
6903 |                                                                             |
6904 |  INPUTS:                                                                    |
6905 |  parms          float64             Parameters defining partial derivative  |
6906 |                                                                             |
6907 |  OUTPUTS:                                                                   |
6908 |             None                                                            |
6909 |                                                                             |
6910 |  NOTES:                                                                     |
6911 |                                                                             |
6912 |                                                                             |
6913 |   Date     Programmer   Description                                         |
6914 |  ======   ============  =================================================   |
6915 |  Nov 96   Joel Gales    Original Programmer                                 |
6916 |                                                                             |
6917 |  END_PROLOG                                                                 |
6918 -----------------------------------------------------------------------------*/
6919 float64
lamazDyDtheta(float64 parms[])6920 lamazDyDtheta(float64 parms[])
6921 {
6922     float64         snTheta, csTheta, snTheta1, csTheta1, csLamda;
6923     float64         sn2, cs2, sndiff;
6924 
6925     snTheta = sin(EHconvAng(parms[0], HDFE_DEG_RAD));
6926     csTheta = cos(EHconvAng(parms[0], HDFE_DEG_RAD));
6927     snTheta1 = sin(EHconvAng(parms[1], HDFE_DEG_RAD));
6928     csTheta1 = cos(EHconvAng(parms[1], HDFE_DEG_RAD));
6929     csLamda = cos(EHconvAng(parms[2], HDFE_DEG_RAD) -
6930 		  EHconvAng(parms[3], HDFE_DEG_RAD));
6931 
6932     sn2 = snTheta1 * snTheta;
6933     cs2 = csTheta1 * csTheta;
6934     sndiff = snTheta1 - snTheta;
6935 
6936     return (cs2 * (sn2 * (1 + (csLamda * csLamda)) + 2) +
6937 	    csLamda * (2 * (1 + sn2 * sn2) - (sndiff * sndiff)));
6938 }
6939 
6940 
6941 
6942 /*----------------------------------------------------------------------------|
6943 |  BEGIN_PROLOG                                                               |
6944 |                                                                             |
6945 |  FUNCTION: homDyDtheta                                                      |
6946 |                                                                             |
6947 |  DESCRIPTION: Partial derivative along longitude line for Oblique Mercator  |
6948 |                                                                             |
6949 |                                                                             |
6950 |  Return Value    Type     Units     Description                             |
6951 |  ============   ======  =========   =====================================   |
6952 |                 float64             Dx/D(theta) for HOM projection          |
6953 |                                                                             |
6954 |  INPUTS:                                                                    |
6955 |  parms          float64             Parameters defining partial derivative  |
6956 |                                                                             |
6957 |  OUTPUTS:                                                                   |
6958 |             None                                                            |
6959 |                                                                             |
6960 |  NOTES:                                                                     |
6961 |                                                                             |
6962 |                                                                             |
6963 |   Date     Programmer   Description                                         |
6964 |  ======   ============  =================================================   |
6965 |  Mar 97   Joel Gales    Original Programmer                                 |
6966 |                                                                             |
6967 |  END_PROLOG                                                                 |
6968 -----------------------------------------------------------------------------*/
6969 float64
homDyDtheta(float64 parms[])6970 homDyDtheta(float64 parms[])
6971 {
6972     float64         tnTheta, tnTheta1, snLamda;
6973 
6974     tnTheta = tan(EHconvAng(parms[0], HDFE_DEG_RAD));
6975     tnTheta1 = tan(EHconvAng(parms[1], HDFE_DEG_RAD));
6976     snLamda = cos(EHconvAng(parms[2], HDFE_DEG_RAD) -
6977 		  EHconvAng(parms[3], HDFE_DEG_RAD));
6978 
6979     return (tnTheta * snLamda + tnTheta1);
6980 }
6981 
6982 
6983 
6984 
6985 /*----------------------------------------------------------------------------|
6986 |  BEGIN_PROLOG                                                               |
6987 |                                                                             |
6988 |  FUNCTION: GDtangentpnts                                                    |
6989 |                                                                             |
6990 |  DESCRIPTION: Finds tangent points along lon/lat lines                      |
6991 |                                                                             |
6992 |                                                                             |
6993 |  Return Value    Type     Units     Description                             |
6994 |  ============   ======  =========   =====================================   |
6995 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
6996 |                                                                             |
6997 |  INPUTS:                                                                    |
6998 |  projcode       int32               Projection code                         |
6999 |  projparm       float64             Projection parameters                   |
7000 |  cornerlon      float64  dec deg    Longitude of opposite corners of box    |
7001 |  cornerlat      float64  dec deg    Latitude of opposite corners of box     |
7002 |  longitude      float64  dec deg    Longitude of points to check            |
7003 |  latitude       float64  dec deg    Latitude of points to check             |
7004 |                                                                             |
7005 |                                                                             |
7006 |  OUTPUTS:                                                                   |
7007 |  npnts          int32               Number of points to check in subset     |
7008 |                                                                             |
7009 |  NOTES:                                                                     |
7010 |                                                                             |
7011 |                                                                             |
7012 |   Date     Programmer   Description                                         |
7013 |  ======   ============  =================================================   |
7014 |  Nov 96   Joel Gales    Original Programmer                                 |
7015 |  Mar 97   Joel Gales    Add support for LAMCC, POLYC, TM                    |
7016 |  Aug 99   Abe Taaheri   Add support for ALBERS, and MERCAT projections.     |
7017 |                         Also changed misstyped bisectParm[2] to             |
7018 |                         bisectParm[3] for HOM projection.                   |
7019 |  Jun 00   Abe Taaheri   Added support for EASE grid                         |
7020 |                                                                             |
7021 |  END_PROLOG                                                                 |
7022 -----------------------------------------------------------------------------*/
7023 static intn
GDtangentpnts(int32 projcode,float64 projparm[],float64 cornerlon[],float64 cornerlat[],float64 longitude[],float64 latitude[],int32 * npnts)7024 GDtangentpnts(int32 projcode, float64 projparm[], float64 cornerlon[],
7025 	      float64 cornerlat[], float64 longitude[], float64 latitude[],
7026 	      int32 * npnts)
7027 {
7028     intn            i;		/* Loop index */
7029     intn            status = 0;	/* routine return status variable */
7030 
7031     float64         lonrad;	/* Longitude (radians) */
7032     float64         latrad;	/* Latitude (radians) */
7033     float64         cs[4];	/* Cosine array */
7034     float64         sn[4];	/* Sine array */
7035     float64         csTest;	/* Cosine test value */
7036     float64         snTest;	/* Sine test value */
7037     float64         crs01;	/* Cross product */
7038     float64         crsTest[2];	/* Cross product array */
7039     float64         longPol;	/* Longitude beneath pole */
7040     float64         minLat;	/* Minimum latitude */
7041     float64         bisectParm[4];	/* Bisection parameters */
7042     float64         tanLat;	/* Tangent latitude */
7043     float64         tanLon;	/* Tangent lontitude */
7044     float64         dotPrd;	/* Dot product */
7045     float64         centMerd;	/* Central Meridian */
7046     float64         orgLat;	/* Latitude of origin */
7047     float64         dpi;	/* Double precision pi */
7048 
7049     float64         lamazDxDtheta();	/* Lambert Azimuthal Dx/Dtheta */
7050     float64         lamazDxDlamda();	/* Lambert Azimuthal Dx/Dlamda */
7051     float64         lamazDyDtheta();	/* Lambert Azimuthal Dy/Dtheta */
7052     float64         homDyDtheta();	/* Oblique Mercator  Dy/Dtheta */
7053 
7054 
7055     /* Conpute pi (double precsion) */
7056     /* ---------------------------- */
7057     dpi = atan(1.0) * 4;
7058 
7059 
7060     switch (projcode)
7061     {
7062       case GCTP_MERCAT:
7063 	{
7064 	    /* No need for tangent points, since MERCAT projection
7065 	       is rectangular */
7066 	}
7067 	break;
7068       case GCTP_BCEA:
7069 	{
7070 	    /* No need for tangent points, since BCEA projection
7071 	       is rectangular */
7072 	}
7073 	break;
7074      case GCTP_CEA:
7075       {
7076              /* No need for tangent points, since CEA projection
7077                 is rectangular */
7078       }
7079       break;
7080 
7081       case GCTP_PS:
7082 	{
7083 	    /* Add "xy axis" points for Polar Stereographic if necessary */
7084 	    /* --------------------------------------------------------- */
7085 
7086 
7087 	    /* Get minimum of corner latitudes */
7088 	    /* ------------------------------- */
7089 	    minLat = (fabs(cornerlat[0]) <= fabs(cornerlat[1]))
7090 		? cornerlat[0] : cornerlat[1];
7091 
7092 
7093 	    /* Compute sine and cosine of corner longitudes */
7094 	    /* -------------------------------------------- */
7095 	    for (i = 0; i < 2; i++)
7096 	    {
7097 		lonrad = EHconvAng(cornerlon[i], HDFE_DEG_RAD);
7098 		cs[i] = cos(lonrad);
7099 		sn[i] = sin(lonrad);
7100 	    }
7101 
7102 
7103 	    /* Compute cross product */
7104 	    /* --------------------- */
7105 	    crs01 = cs[0] * sn[1] - cs[1] * sn[0];
7106 
7107 
7108 	    /* Convert longitude beneath pole from DMS to DEG */
7109 	    /* ---------------------------------------------- */
7110 	    longPol = EHconvAng(projparm[4], HDFE_DMS_RAD);
7111 
7112 
7113 
7114 	    for (i = 0; i < 4; i++)
7115 	    {
7116 		csTest = cos(longPol);
7117 		snTest = sin(longPol);
7118 
7119 		crsTest[0] = cs[0] * snTest - csTest * sn[0];
7120 		crsTest[1] = cs[1] * snTest - csTest * sn[1];
7121 
7122 		if ((crs01 > 0 && crsTest[0] > 0 && crsTest[1] < 0) ||
7123 		    (crs01 < 0 && crsTest[0] < 0 && crsTest[1] < 0) ||
7124 		    (crs01 < 0 && crsTest[0] > 0 && crsTest[1] < 0) ||
7125 		    (crs01 < 0 && crsTest[0] > 0 && crsTest[1] > 0))
7126 		{
7127 		    longitude[*npnts] = EHconvAng(longPol, HDFE_RAD_DEG);
7128 		    latitude[*npnts] = minLat;
7129 		    (*npnts)++;
7130 		}
7131 		longPol += 0.5 * dpi;
7132 	    }
7133 	}
7134 	break;
7135 
7136 
7137       case GCTP_LAMAZ:
7138 	{
7139 	    if ((int32) projparm[5] == +90000000 ||
7140 		(int32) projparm[5] == -90000000)
7141 	    {
7142 		/* Add "xy axis" points for Polar Lambert Azimuthal */
7143 		/* ------------------------------------------------ */
7144 		minLat = (fabs(cornerlat[0]) <= fabs(cornerlat[1]))
7145 		    ? cornerlat[0] : cornerlat[1];
7146 
7147 		for (i = 0; i < 2; i++)
7148 		{
7149 		    lonrad = EHconvAng(cornerlon[i], HDFE_DEG_RAD);
7150 		    cs[i] = cos(lonrad);
7151 		    sn[i] = sin(lonrad);
7152 		}
7153 		crs01 = cs[0] * sn[1] - cs[1] * sn[0];
7154 
7155 		longPol = EHconvAng(projparm[4], HDFE_DMS_RAD);
7156 		for (i = 0; i < 4; i++)
7157 		{
7158 		    csTest = cos(longPol);
7159 		    snTest = sin(longPol);
7160 
7161 		    crsTest[0] = cs[0] * snTest - csTest * sn[0];
7162 		    crsTest[1] = cs[1] * snTest - csTest * sn[1];
7163 
7164 		    if ((crs01 > 0 && crsTest[0] > 0 && crsTest[1] < 0) ||
7165 			(crs01 < 0 && crsTest[0] < 0 && crsTest[1] < 0) ||
7166 			(crs01 < 0 && crsTest[0] > 0 && crsTest[1] < 0) ||
7167 			(crs01 < 0 && crsTest[0] > 0 && crsTest[1] > 0))
7168 		    {
7169 			longitude[*npnts] = EHconvAng(longPol, HDFE_RAD_DEG);
7170 			latitude[*npnts] = minLat;
7171 			(*npnts)++;
7172 		    }
7173 		    longPol += 0.5 * dpi;
7174 		}
7175 	    }
7176 	    else if ((int32) projparm[5] == 0)
7177 	    {
7178 		/* Add "Equator" points for Equatorial Lambert Azimuthal */
7179 		/* ----------------------------------------------------- */
7180 		if (cornerlat[0] * cornerlat[1] < 0)
7181 		{
7182 		    longitude[4] = cornerlon[0];
7183 		    latitude[4] = 0;
7184 
7185 		    longitude[5] = cornerlon[1];
7186 		    latitude[5] = 0;
7187 
7188 		    *npnts = 6;
7189 		}
7190 	    }
7191 	    else
7192 	    {
7193 		/* Add tangent points for Oblique Lambert Azimuthal */
7194 		/* ------------------------------------------------ */
7195 		bisectParm[0] = EHconvAng(projparm[5], HDFE_DMS_DEG);
7196 		bisectParm[2] = EHconvAng(projparm[4], HDFE_DMS_DEG);
7197 
7198 
7199 		/* Tangent to y-axis along longitude */
7200 		/* --------------------------------- */
7201 		for (i = 0; i < 2; i++)
7202 		{
7203 		    bisectParm[1] = cornerlon[i];
7204 
7205 		    if (EHbisect(lamazDxDtheta, bisectParm, 3,
7206 				 cornerlat[0], cornerlat[1],
7207 				 0.0001, &tanLat) == 0)
7208 		    {
7209 			longitude[*npnts] = cornerlon[i];
7210 			latitude[*npnts] = tanLat;
7211 			(*npnts)++;
7212 		    }
7213 		}
7214 
7215 		/* Tangent to y-axis along latitude */
7216 		/* -------------------------------- */
7217 		for (i = 0; i < 2; i++)
7218 		{
7219 		    bisectParm[1] = cornerlat[i];
7220 
7221 		    if (EHbisect(lamazDxDlamda, bisectParm, 3,
7222 				 cornerlon[0], cornerlon[1],
7223 				 0.0001, &tanLon) == 0)
7224 		    {
7225 			longitude[*npnts] = tanLon;
7226 			latitude[*npnts] = cornerlat[i];
7227 			(*npnts)++;
7228 		    }
7229 		}
7230 
7231 
7232 		/* Tangent to x-axis along longitude */
7233 		/* --------------------------------- */
7234 		for (i = 0; i < 2; i++)
7235 		{
7236 		    bisectParm[1] = cornerlon[i];
7237 
7238 		    if (EHbisect(lamazDyDtheta, bisectParm, 3,
7239 				 cornerlat[0], cornerlat[1],
7240 				 0.0001, &tanLat) == 0)
7241 		    {
7242 			longitude[*npnts] = cornerlon[i];
7243 			latitude[*npnts] = tanLat;
7244 			(*npnts)++;
7245 		    }
7246 		}
7247 
7248 		/* Tangent to x-axis along latitude */
7249 		/* -------------------------------- */
7250 		for (i = 0; i < 2; i++)
7251 		{
7252 		    lonrad = EHconvAng(cornerlon[i], HDFE_DEG_RAD);
7253 		    cs[i] = cos(lonrad);
7254 		    sn[i] = sin(lonrad);
7255 		}
7256 		crs01 = cs[0] * sn[1] - cs[1] * sn[0];
7257 
7258 		longPol = EHconvAng(projparm[4], HDFE_DMS_RAD);
7259 		for (i = 0; i < 2; i++)
7260 		{
7261 		    csTest = cos(longPol);
7262 		    snTest = sin(longPol);
7263 
7264 		    crsTest[0] = cs[0] * snTest - csTest * sn[0];
7265 		    crsTest[1] = cs[1] * snTest - csTest * sn[1];
7266 
7267 		    if ((crs01 > 0 && crsTest[0] > 0 && crsTest[1] < 0) ||
7268 			(crs01 < 0 && crsTest[0] < 0 && crsTest[1] < 0) ||
7269 			(crs01 < 0 && crsTest[0] > 0 && crsTest[1] < 0) ||
7270 			(crs01 < 0 && crsTest[0] > 0 && crsTest[1] > 0))
7271 		    {
7272 			longitude[*npnts] = EHconvAng(longPol, HDFE_RAD_DEG);
7273 			latitude[*npnts] = cornerlat[0];
7274 			(*npnts)++;
7275 			longitude[*npnts] = EHconvAng(longPol, HDFE_RAD_DEG);
7276 			latitude[*npnts] = cornerlat[1];
7277 			(*npnts)++;
7278 		    }
7279 		    longPol += dpi;
7280 		}
7281 	    }
7282 	}
7283 	break;
7284 
7285 
7286       case GCTP_GOOD:
7287 	{
7288 	    /* Add "Equator" points for Goode Homolosine if necessary */
7289 	    /* ------------------------------------------------------ */
7290 	    if (cornerlat[0] * cornerlat[1] < 0)
7291 	    {
7292 		longitude[4] = cornerlon[0];
7293 		latitude[4] = 0;
7294 
7295 		longitude[5] = cornerlon[1];
7296 		latitude[5] = 0;
7297 
7298 		*npnts = 6;
7299 	    }
7300 	}
7301 	break;
7302 
7303 
7304       case GCTP_LAMCC:
7305 	{
7306 	    /* Compute sine and cosine of corner longitudes */
7307 	    /* -------------------------------------------- */
7308 	    for (i = 0; i < 2; i++)
7309 	    {
7310 		lonrad = EHconvAng(cornerlon[i], HDFE_DEG_RAD);
7311 		cs[i] = cos(lonrad);
7312 		sn[i] = sin(lonrad);
7313 	    }
7314 
7315 
7316 	    /* Compute dot product */
7317 	    /* ------------------- */
7318 	    dotPrd = cs[0] * cs[1] + sn[0] * sn[1];
7319 
7320 
7321 	    /* Convert central meridian (DMS to DEG) & compute sin & cos */
7322 	    /* --------------------------------------------------------- */
7323 	    centMerd = EHconvAng(projparm[4], HDFE_DMS_DEG);
7324 	    lonrad = EHconvAng(centMerd, HDFE_DEG_RAD);
7325 	    cs[1] = cos(lonrad);
7326 	    sn[1] = sin(lonrad);
7327 
7328 
7329 	    /* If box brackets central meridian ... */
7330 	    /* ------------------------------------ */
7331 	    if (cs[0] * cs[1] + sn[0] * sn[1] > dotPrd)
7332 	    {
7333 		latitude[4] = cornerlat[0];
7334 		longitude[4] = centMerd;
7335 
7336 		latitude[5] = cornerlat[1];
7337 		longitude[5] = centMerd;
7338 
7339 		*npnts = 6;
7340 	    }
7341 	}
7342 	break;
7343 
7344 
7345       case GCTP_ALBERS:
7346 	{
7347 	    /* Compute sine and cosine of corner longitudes */
7348 	    /* -------------------------------------------- */
7349 	    for (i = 0; i < 2; i++)
7350 	    {
7351 		lonrad = EHconvAng(cornerlon[i], HDFE_DEG_RAD);
7352 		cs[i] = cos(lonrad);
7353 		sn[i] = sin(lonrad);
7354 	    }
7355 
7356 
7357 	    /* Compute dot product */
7358 	    /* ------------------- */
7359 	    dotPrd = cs[0] * cs[1] + sn[0] * sn[1];
7360 
7361 
7362 	    /* Convert central meridian (DMS to DEG) & compute sin & cos */
7363 	    /* --------------------------------------------------------- */
7364 	    centMerd = EHconvAng(projparm[4], HDFE_DMS_DEG);
7365 	    lonrad = EHconvAng(centMerd, HDFE_DEG_RAD);
7366 	    cs[1] = cos(lonrad);
7367 	    sn[1] = sin(lonrad);
7368 
7369 
7370 	    /* If box brackets central meridian ... */
7371 	    /* ------------------------------------ */
7372 	    if (cs[0] * cs[1] + sn[0] * sn[1] > dotPrd)
7373 	    {
7374 		latitude[4] = cornerlat[0];
7375 		longitude[4] = centMerd;
7376 
7377 		latitude[5] = cornerlat[1];
7378 		longitude[5] = centMerd;
7379 
7380 		*npnts = 6;
7381 	    }
7382 	}
7383 	break;
7384 
7385 
7386       case GCTP_POLYC:
7387 	{
7388 	    /* Compute sine and cosine of corner longitudes */
7389 	    /* -------------------------------------------- */
7390 	    for (i = 0; i < 2; i++)
7391 	    {
7392 		lonrad = EHconvAng(cornerlon[i], HDFE_DEG_RAD);
7393 		cs[i] = cos(lonrad);
7394 		sn[i] = sin(lonrad);
7395 	    }
7396 
7397 
7398 	    /* Compute dot product */
7399 	    /* ------------------- */
7400 	    dotPrd = cs[0] * cs[1] + sn[0] * sn[1];
7401 
7402 
7403 	    /* Convert central meridian (DMS to DEG) & compute sin & cos */
7404 	    /* --------------------------------------------------------- */
7405 	    centMerd = EHconvAng(projparm[4], HDFE_DMS_DEG);
7406 	    lonrad = EHconvAng(centMerd, HDFE_DEG_RAD);
7407 	    cs[1] = cos(lonrad);
7408 	    sn[1] = sin(lonrad);
7409 
7410 
7411 	    /* If box brackets central meridian ... */
7412 	    /* ------------------------------------ */
7413 	    if (cs[0] * cs[1] + sn[0] * sn[1] > dotPrd)
7414 	    {
7415 		latitude[4] = cornerlat[0];
7416 		longitude[4] = centMerd;
7417 
7418 		latitude[5] = cornerlat[1];
7419 		longitude[5] = centMerd;
7420 
7421 		*npnts = 6;
7422 	    }
7423 	}
7424 	break;
7425 
7426 
7427       case GCTP_TM:
7428 	{
7429 	    /* Compute sine and cosine of corner longitudes */
7430 	    /* -------------------------------------------- */
7431 	    for (i = 0; i < 2; i++)
7432 	    {
7433 		lonrad = EHconvAng(cornerlon[i], HDFE_DEG_RAD);
7434 		cs[i] = cos(lonrad);
7435 		sn[i] = sin(lonrad);
7436 	    }
7437 
7438 
7439 	    /* Compute dot product */
7440 	    /* ------------------- */
7441 	    dotPrd = cs[0] * cs[1] + sn[0] * sn[1];
7442 
7443 
7444 	    for (i = -1; i <= 1; i++)
7445 	    {
7446 		centMerd = EHconvAng(projparm[4], HDFE_DMS_DEG);
7447 		lonrad = EHconvAng(centMerd + 90 * i, HDFE_DEG_RAD);
7448 		csTest = cos(lonrad);
7449 		snTest = sin(lonrad);
7450 
7451 
7452 		/* If box brackets meridian ... */
7453 		/* ---------------------------- */
7454 		if (csTest * cs[1] + snTest * sn[1] > dotPrd)
7455 		{
7456 		    latitude[*npnts] = cornerlat[0];
7457 		    longitude[*npnts] = centMerd;
7458 		    (*npnts)++;
7459 
7460 		    latitude[*npnts] = cornerlat[1];
7461 		    longitude[*npnts] = centMerd;
7462 		    (*npnts)++;
7463 		}
7464 	    }
7465 
7466 
7467 
7468 	    /* Compute sine and cosine of corner latitudes */
7469 	    /* ------------------------------------------- */
7470 	    for (i = 0; i < 2; i++)
7471 	    {
7472 		latrad = EHconvAng(cornerlat[i], HDFE_DEG_RAD);
7473 		cs[i] = cos(latrad);
7474 		sn[i] = sin(latrad);
7475 	    }
7476 
7477 
7478 	    /* Compute dot product */
7479 	    /* ------------------- */
7480 	    dotPrd = cs[0] * cs[1] + sn[0] * sn[1];
7481 
7482 
7483 	    /* Convert origin latitude (DMS to DEG) & compute sin & cos */
7484 	    /* -------------------------------------------------------- */
7485 	    orgLat = EHconvAng(projparm[5], HDFE_DMS_DEG);
7486 	    latrad = EHconvAng(orgLat, HDFE_DEG_RAD);
7487 	    cs[1] = cos(latrad);
7488 	    sn[1] = sin(latrad);
7489 
7490 
7491 	    /* If box brackets origin latitude ... */
7492 	    /* ----------------------------------- */
7493 	    if (cs[0] * cs[1] + sn[0] * sn[1] > dotPrd)
7494 	    {
7495 		latitude[*npnts] = orgLat;
7496 		longitude[*npnts] = cornerlon[0];
7497 		(*npnts)++;
7498 
7499 		latitude[*npnts] = orgLat;
7500 		longitude[*npnts] = cornerlon[1];
7501 		(*npnts)++;
7502 	    }
7503 	}
7504 	break;
7505 
7506 
7507       case GCTP_HOM:
7508 	{
7509 	    /* Tangent to y-axis along longitude */
7510 	    /* --------------------------------- */
7511 	    if (projparm[12] == 0)
7512 	    {
7513 		cs[0] = cos(EHconvAng(projparm[8], HDFE_DMS_RAD));
7514 		sn[0] = sin(EHconvAng(projparm[8], HDFE_DMS_RAD));
7515 		cs[1] = cos(EHconvAng(projparm[9], HDFE_DMS_RAD));
7516 		sn[1] = sin(EHconvAng(projparm[9], HDFE_DMS_RAD));
7517 		cs[2] = cos(EHconvAng(projparm[10], HDFE_DMS_RAD));
7518 		sn[2] = sin(EHconvAng(projparm[10], HDFE_DMS_RAD));
7519 		cs[3] = cos(EHconvAng(projparm[11], HDFE_DMS_RAD));
7520 		sn[3] = sin(EHconvAng(projparm[11], HDFE_DMS_RAD));
7521 
7522 		bisectParm[3] = atan2(
7523 			    (cs[1] * sn[3] * cs[0] - sn[1] * cs[3] * cs[2]),
7524 			   (sn[1] * cs[3] * sn[2] - cs[1] * sn[3] * sn[0]));
7525 		bisectParm[0] = atan(
7526 		 (sin(bisectParm[3]) * sn[0] - cos(bisectParm[3]) * cs[0]) /
7527 				     (sn[1] / cs[1]));
7528 		bisectParm[2] = bisectParm[3] + 0.5 * dpi;
7529 	    }
7530 	    else
7531 	    {
7532 		cs[0] = cos(EHconvAng(projparm[3], HDFE_DMS_RAD));
7533 		sn[0] = sin(EHconvAng(projparm[3], HDFE_DMS_RAD));
7534 		cs[1] = cos(EHconvAng(projparm[4], HDFE_DMS_RAD));
7535 		sn[1] = sin(EHconvAng(projparm[4], HDFE_DMS_RAD));
7536 
7537 		bisectParm[0] = asin(cs[1] * sn[0]);
7538 		bisectParm[2] = atan2(-cs[0], (-sn[1] * sn[0])) + 0.5 * dpi;
7539 	    }
7540 
7541 	    for (i = 0; i < 2; i++)
7542 	    {
7543 		bisectParm[1] = cornerlon[i];
7544 
7545 		if (EHbisect(homDyDtheta, bisectParm, 3,
7546 			     cornerlat[0], cornerlat[1],
7547 			     0.0001, &tanLat) == 0)
7548 		{
7549 		    longitude[*npnts] = cornerlon[i];
7550 		    latitude[*npnts] = tanLat;
7551 		    (*npnts)++;
7552 		}
7553 	    }
7554 
7555 	}
7556 	break;
7557     }
7558 
7559 
7560     return (status);
7561 }
7562 
7563 
7564 
7565 /*----------------------------------------------------------------------------|
7566 |  BEGIN_PROLOG                                                               |
7567 |                                                                             |
7568 |  FUNCTION: GDdefboxregion                                                   |
7569 |                                                                             |
7570 |  DESCRIPTION: Defines region for subsetting in a grid.                      |
7571 |                                                                             |
7572 |                                                                             |
7573 |  Return Value    Type     Units     Description                             |
7574 |  ============   ======  =========   =====================================   |
7575 |  regionID       int32               Region ID                               |
7576 |                                                                             |
7577 |  INPUTS:                                                                    |
7578 |  gridID         int32               Grid structure ID                       |
7579 |  cornerlon      float64  dec deg    Longitude of opposite corners of box    |
7580 |  cornerlat      float64  dec deg    Latitude of opposite corners of box     |
7581 |                                                                             |
7582 |                                                                             |
7583 |  OUTPUTS:                                                                   |
7584 |             None                                                            |
7585 |                                                                             |
7586 |  NOTES:                                                                     |
7587 |                                                                             |
7588 |                                                                             |
7589 |   Date     Programmer   Description                                         |
7590 |  ======   ============  =================================================   |
7591 |  Jun 96   Joel Gales    Original Programmer                                 |
7592 |  Oct 96   Joel Gales    "Clamp" subset region around grid                   |
7593 |  Oct 96   Joel Gales    Fix "outside region" check                          |
7594 |  Nov 96   Joel Gales    Add check for "tangent" points (GDtangentpnts)      |
7595 |  Dec 96   Joel Gales    Trap if no projection code defined                  |
7596 |  Dec 96   Joel Gales    Add multiple vertical subsetting capability         |
7597 |  Mar 99   David Wynne   Fix for NCR 21195, allow subsetting of MISR SOM     |
7598 |                         data sets                                           |
7599 |  Jun 00   Abe Taaheri   Added support for EASE grid                         |
7600 |                                                                             |
7601 |  END_PROLOG                                                                 |
7602 -----------------------------------------------------------------------------*/
7603 int32
GDdefboxregion(int32 gridID,float64 cornerlon[],float64 cornerlat[])7604 GDdefboxregion(int32 gridID, float64 cornerlon[], float64 cornerlat[])
7605 {
7606     intn            i;		    /* Loop index */
7607     intn            j;		    /* Loop index */
7608     intn            k;		    /* Loop index */
7609     intn            n;		    /* Loop index */
7610     intn            status = 0;	    /* routine return status variable */
7611 
7612     int32           fid;	    /* HDF-EOS file ID */
7613     int32           sdInterfaceID;  /* HDF SDS interface ID */
7614     int32           gdVgrpID;	    /* Grid root Vgroup ID */
7615     int32           regionID = -1;  /* Region ID */
7616     int32           xdimsize;	    /* XDim size */
7617     int32           ydimsize;	    /* YDim size */
7618     int32           projcode;	    /* Projection code */
7619     int32           zonecode;	    /* Zone code */
7620     int32           spherecode;	    /* Sphere code */
7621     int32           row[32];	    /* Row array */
7622     int32           col[32];	    /* Column array */
7623     int32           minCol = 0;	    /* Minimun column value */
7624     int32           minRow = 0;	    /* Minimun row value */
7625     int32           maxCol = 0;	    /* Maximun column value */
7626     int32           maxRow = 0;	    /* Maximun row value */
7627     int32           npnts;	    /* Number of boundary
7628                                        (edge & tangent) pnts */
7629 
7630     float64         longitude[32];  /* Longitude array */
7631     float64         latitude[32];   /* Latitude array */
7632     float64         upleftpt[2];    /* Upper left pt coordinates */
7633     float64         lowrightpt[2];  /* Lower right pt coordinates */
7634     float64         somupleftpt[2]; /* temporary Upper left pt coordinates
7635                                        for SOM projection */
7636     float64         somlowrightpt[2];   /* temporary Lower right pt
7637                                            coordinates for SOM projection */
7638     float64         projparm[16];   /* Projection parameters */
7639     float64         xscale;	    /* X scale */
7640     float64         yscale;	    /* Y scale */
7641     float64         lonrad0;	    /* Longitude of upper left point
7642                                        (radians) */
7643     float64         latrad0;	    /* Latitude of upper left point (radians) */
7644     float64         lonrad2;	    /* Longitude of point (radians) */
7645     float64         latrad2;	    /* Latitude of point (radians) */
7646 
7647     /* Used for SOM projection  */
7648     char            *utlbuf;
7649     char            *gridname;
7650     int32	    blockindexstart = -1;
7651     int32	    blockindexstop = -1;
7652     float32         offset[180];
7653     float64         templeftpt[2];
7654     float64         temprightpt[2];
7655     int32           idOffset = GDIDOFFSET;	/* Grid ID offset */
7656     float64         xmtr[2], ymtr[2];
7657     float64         lon[2],lat[2];
7658     float64         xcor[2], ycor[2];
7659     int32           nlatlon;
7660     float64         upleftpt_m[2];
7661 
7662 
7663     utlbuf = (char *)calloc(128, sizeof(char));
7664     if(utlbuf == NULL)
7665     {
7666 	HEpush(DFE_NOSPACE,"GDdefboxregion", __FILE__, __LINE__);
7667 	return(-1);
7668     }
7669     gridname = (char *)calloc(128, sizeof(char));
7670     if(gridname == NULL)
7671     {
7672 	HEpush(DFE_NOSPACE,"GDdefboxregion", __FILE__, __LINE__);
7673 	free(utlbuf);
7674 	return(-1);
7675     }
7676 
7677     /* Check for valid grid ID */
7678     /* ----------------------- */
7679     status = GDchkgdid(gridID, "GDdefboxregion",
7680 		       &fid, &sdInterfaceID, &gdVgrpID);
7681 
7682 
7683     if (status == 0)
7684     {
7685 	/* Get grid info */
7686 	/* ------------- */
7687 	status = GDgridinfo(gridID, &xdimsize, &ydimsize,
7688 			    upleftpt, lowrightpt);
7689 
7690 
7691 	/* If error then bail */
7692 	/* ------------------ */
7693 	if (status != 0)
7694 	{
7695 	    regionID = -1;
7696 	    free(utlbuf);
7697 	    free(gridname);
7698 	    return (regionID);
7699 	}
7700 
7701 
7702 	/* Get proj info */
7703 	/* ------------- */
7704 	status = GDprojinfo(gridID, &projcode, &zonecode,
7705 			    &spherecode, projparm);
7706 
7707 
7708 	/* If no projection code defined then bail */
7709 	/* --------------------------------------- */
7710 	if (projcode == -1)
7711 	{
7712 	    regionID = -1;
7713 	    free(utlbuf);
7714 	    free(gridname);
7715 	    return (regionID);
7716 	}
7717 
7718 
7719 	/* Get default values for upleft and lowright if necessary */
7720 	/* ------------------------------------------------------- */
7721 	if (upleftpt[0] == 0 && upleftpt[1] == 0 &&
7722 	    lowrightpt[0] == 0 && lowrightpt[1] == 0)
7723 	{
7724 	    status = GDgetdefaults(projcode, zonecode, projparm, spherecode,
7725 				   upleftpt, lowrightpt);
7726 
7727 	    /* If error then bail */
7728 	    /* ------------------ */
7729 	    if (status != 0)
7730 	    {
7731 		regionID = -1;
7732 		free(utlbuf);
7733 		free(gridname);
7734 		return (regionID);
7735 	    }
7736 	}
7737 
7738 
7739 
7740 	/* Fill-up longitude and latitude arrays */
7741 	/* ------------------------------------- */
7742 	longitude[0] = cornerlon[0];
7743 	latitude[0] = cornerlat[0];
7744 
7745 	longitude[1] = cornerlon[0];
7746 	latitude[1] = cornerlat[1];
7747 
7748 	longitude[2] = cornerlon[1];
7749 	latitude[2] = cornerlat[0];
7750 
7751 	longitude[3] = cornerlon[1];
7752 	latitude[3] = cornerlat[1];
7753 
7754 	npnts = 4;
7755 
7756 
7757 	/* Find additional tangent points from GDtangentpnts */
7758 	/* ------------------------------------------------- */
7759 	status = GDtangentpnts(projcode, projparm, cornerlon, cornerlat,
7760 			       longitude, latitude, &npnts);
7761 
7762         /* If SOM projection with projparm[11] non-zero ... */
7763         if (projcode == GCTP_SOM && projparm[11] != 0)
7764         {
7765             Vgetname(GDXGrid[gridID % idOffset].IDTable, gridname);
7766             sprintf(utlbuf, "%s%s", "_BLKSOM:", gridname);
7767 	    status = GDreadattr(gridID, utlbuf, offset);
7768 
7769             somupleftpt[0] = upleftpt[0];
7770             somupleftpt[1] = upleftpt[1];
7771             somlowrightpt[0]= lowrightpt[0];
7772             somlowrightpt[1] = lowrightpt[1];
7773 
7774             k = 0;
7775             n = 2;
7776 
7777             for (j = 0; j <= projparm[11] - 1; j++)
7778             {
7779 
7780 		/* Convert from lon/lat to row/col */
7781 		/* ------------------------------- */
7782 		status = GDll2ij(projcode, zonecode, projparm, spherecode,
7783 			 xdimsize, ydimsize, somupleftpt, somlowrightpt,
7784 			 npnts, longitude, latitude, row, col, NULL, NULL);
7785 
7786 
7787 	       /* Find min/max values for row & col */
7788 	       /* --------------------------------- */
7789 	       minCol = col[0];
7790 	       minRow = row[0];
7791 	       maxCol = col[0];
7792 	       maxRow = row[0];
7793 	       for (i = 1; i < npnts; i++)
7794 	       {
7795 	          if (col[i] < minCol)
7796 	          {
7797 		     minCol = col[i];
7798 	          }
7799 
7800 	          if (col[i] > maxCol)
7801 	          {
7802 		     maxCol = col[i];
7803 	          }
7804 
7805 	          if (row[i] < minRow)
7806 	          {
7807 		     minRow = row[i];
7808 	          }
7809 
7810 	          if (row[i] > maxRow)
7811 	          {
7812 		     maxRow = row[i];
7813 	           }
7814 	        }
7815 
7816 
7817 
7818 	        /* "Clamp" if outside Grid */
7819 	        /* ----------------------- */
7820 	        minCol = (minCol < 0) ? 0 : minCol;
7821 	        minRow = (minRow < 0) ? 0 : minRow;
7822 
7823 	        maxCol = (maxCol >= xdimsize) ? xdimsize - 1 : maxCol;
7824 	        maxRow = (maxRow >= ydimsize) ? ydimsize - 1 : maxRow;
7825 
7826 
7827 	        /* Check whether subset region is outside grid region */
7828 	        /* -------------------------------------------------- */
7829 	        if (minCol >= xdimsize || minRow >= ydimsize ||
7830 		    maxCol < 0 || maxRow < 0)
7831 	        {
7832                    if ( blockindexstart == -1 && (projparm[11]) == j)
7833                    {
7834                       status = -1;
7835 	              HEpush(DFE_GENAPP, "GDdefboxregion", __FILE__, __LINE__);
7836 	              HEreport("Subset Region outside of Grid Region\n");
7837                       regionID = -1;
7838                    }
7839 	        }
7840                 else
7841                 {
7842                    if (k == 0)
7843                    {
7844                       blockindexstart = j;
7845                       blockindexstop = j;
7846                       k = 1;
7847                    }
7848                    else
7849                    {
7850                       blockindexstop = j;
7851                    }
7852                 }
7853                 templeftpt[0] = upleftpt[0] + ((offset[j]/xdimsize)*abs(upleftpt[0] - lowrightpt[0])) + abs((upleftpt[0] - lowrightpt[0]))*(n-1);
7854                 templeftpt[1] = upleftpt[1] + ((lowrightpt[1] - upleftpt[1]))*(n-1);
7855 
7856                 temprightpt[0] = lowrightpt[0] + ((offset[j]/xdimsize)*abs(lowrightpt[0] - upleftpt[0])) + abs((lowrightpt[0] - upleftpt[0]))*(n-1);
7857                 temprightpt[1] = lowrightpt[1] + ((upleftpt[1] - lowrightpt[1]))*(n-1);
7858 
7859                 somupleftpt[0] = templeftpt[0];
7860                 somupleftpt[1] = templeftpt[1];
7861 
7862                 somlowrightpt[0] = temprightpt[0];
7863                 somlowrightpt[1] = temprightpt[1];
7864                 n++;
7865              }
7866          }
7867          else
7868          {
7869 
7870 	    /* Convert from lon/lat to row/col */
7871 	    /* ------------------------------- */
7872 
7873 	    status = GDll2ij(projcode, zonecode, projparm, spherecode,
7874 			 xdimsize, ydimsize, upleftpt, lowrightpt,
7875 			 npnts, longitude, latitude, row, col, NULL, NULL);
7876 
7877 	    /* Find min/max values for row & col */
7878 	    /* --------------------------------- */
7879 	    minCol = col[0];
7880 	    minRow = row[0];
7881 	    maxCol = col[0];
7882 	    maxRow = row[0];
7883 	    for (i = 1; i < npnts; i++)
7884 	    {
7885 	       if (col[i] < minCol)
7886 	       {
7887 		  minCol = col[i];
7888 	       }
7889 
7890 	       if (col[i] > maxCol)
7891 	       {
7892 	          maxCol = col[i];
7893 	       }
7894 
7895 	       if (row[i] < minRow)
7896 	       {
7897 		  minRow = row[i];
7898 	       }
7899 
7900 	       if (row[i] > maxRow)
7901 	       {
7902 		  maxRow = row[i];
7903 	       }
7904 	    }
7905 
7906 
7907 
7908 	    /* "Clamp" if outside Grid */
7909 	    /* ----------------------- */
7910 	    minCol = (minCol < 0) ? 0 : minCol;
7911 	    minRow = (minRow < 0) ? 0 : minRow;
7912 
7913 	    maxCol = (maxCol >= xdimsize) ? xdimsize - 1 : maxCol;
7914 	    maxRow = (maxRow >= ydimsize) ? ydimsize - 1 : maxRow;
7915 
7916 
7917 	    /* Check whether subset region is outside grid region */
7918 	    /* -------------------------------------------------- */
7919 	    if (minCol >= xdimsize || minRow >= ydimsize || maxCol < 0 || maxRow < 0)
7920 	    {
7921 	       status = -1;
7922 	       HEpush(DFE_GENAPP, "GDdefboxregion", __FILE__, __LINE__);
7923 	       HEreport("Subset Region outside of Grid Region\n");
7924 	       regionID = -1;
7925 
7926 	    }
7927          }
7928 	    if (status == 0)
7929 	    {
7930 	       /* Store grid region info */
7931 	       /* ---------------------- */
7932 	       for (i = 0; i < NGRIDREGN; i++)
7933 	       {
7934 		/* Find first empty grid region */
7935 		/* ---------------------------- */
7936 		if (GDXRegion[i] == 0)
7937 		{
7938 		    /* Allocate space for grid region entry */
7939 		    /* ------------------------------------ */
7940 		    GDXRegion[i] = (struct gridRegion *)
7941 			calloc(1, sizeof(struct gridRegion));
7942 		    if(GDXRegion[i] == NULL)
7943 		    {
7944 			HEpush(DFE_NOSPACE,"GDdefboxregion", __FILE__, __LINE__);
7945 			free(utlbuf);
7946 			free(gridname);
7947 			return(-1);
7948 		    }
7949 
7950 
7951 		    /* Store file and grid ID */
7952 		    /* ---------------------- */
7953 		    GDXRegion[i]->fid = fid;
7954 		    GDXRegion[i]->gridID = gridID;
7955 
7956 
7957 		    /* Initialize vertical subset entries to -1 */
7958 		    /* ---------------------------------------- */
7959 		    for (j = 0; j < 8; j++)
7960 		    {
7961 			GDXRegion[i]->StartVertical[j] = -1;
7962 			GDXRegion[i]->StopVertical[j] = -1;
7963 		    }
7964 
7965 
7966 		    /* Store start & count along x & y */
7967 		    /* ------------------------------- */
7968 		    GDXRegion[i]->xStart = minCol;
7969 		    GDXRegion[i]->xCount = maxCol - minCol + 1;
7970 		    GDXRegion[i]->yStart = minRow;
7971 		    GDXRegion[i]->yCount = maxRow - minRow + 1;
7972 
7973 
7974 		    /* Store upleft and lowright points of subset region */
7975 		    /* ------------------------------------------------- */
7976 		    if (projcode == GCTP_GEO )
7977 		    {
7978 			/* GEO projection */
7979 			/* ------------------------ */
7980 
7981 			/* Convert upleft & lowright lon from DMS to radians */
7982 			/* ------------------------------------------------- */
7983 			lonrad0 = EHconvAng(upleftpt[0], HDFE_DMS_RAD);
7984 			lonrad2 = EHconvAng(lowrightpt[0], HDFE_DMS_RAD);
7985 
7986 			/* Compute X scale */
7987 			/* --------------- */
7988 			xscale = (lonrad2 - lonrad0) / xdimsize;
7989 
7990 			/* Convert upleft & lowright lat from DMS to radians */
7991 			/* ------------------------------------------------- */
7992 			latrad0 = EHconvAng(upleftpt[1], HDFE_DMS_RAD);
7993 			latrad2 = EHconvAng(lowrightpt[1], HDFE_DMS_RAD);
7994 
7995 			/* Compute Y scale */
7996 			/* --------------- */
7997 			yscale = (latrad2 - latrad0) / ydimsize;
7998 
7999 
8000 			/* MinCol -> radians -> DMS -> upleftpt[0] */
8001 			/* --------------------------------------- */
8002 			GDXRegion[i]->upleftpt[0] =
8003 			    EHconvAng(lonrad0 + xscale * minCol,
8004 				      HDFE_RAD_DMS);
8005 
8006 
8007 			/* MinRow -> radians -> DMS -> upleftpt[1] */
8008 			/* --------------------------------------- */
8009 			GDXRegion[i]->upleftpt[1] =
8010 			    EHconvAng(latrad0 + yscale * minRow,
8011 				      HDFE_RAD_DMS);
8012 
8013 
8014 			/* MinCol + 1 -> radians -> DMS -> lowrightpt[0] */
8015 			/* --------------------------------------------- */
8016 			GDXRegion[i]->lowrightpt[0] =
8017 			    EHconvAng(lonrad0 + xscale * (maxCol + 1),
8018 				      HDFE_RAD_DMS);
8019 
8020 
8021 			/* MinRow + 1 -> radians -> DMS -> lowrightpt[1] */
8022 			/* --------------------------------------------- */
8023 			GDXRegion[i]->lowrightpt[1] =
8024 			    EHconvAng(latrad0 + yscale * (maxRow + 1),
8025 				      HDFE_RAD_DMS);
8026 		    }
8027 		    else if (projcode == GCTP_BCEA)
8028 		    {
8029 			/* BCEA projection */
8030 			/* -------------- */
8031 		      nlatlon = 2;
8032 		      lon[0] = upleftpt[0];
8033 		      lon[1] = lowrightpt[0];
8034 		      lat[0] = upleftpt[1];
8035 		      lat[1] = lowrightpt[1];
8036 		      status =
8037 			GDll2mm_cea(projcode,zonecode,spherecode,projparm,
8038 				    xdimsize, ydimsize,
8039 				    upleftpt, lowrightpt,nlatlon,
8040 				    lon, lat,
8041 				    xcor, ycor, &xscale, &yscale);
8042 		      upleftpt_m[0] = xcor[0];
8043 		      upleftpt_m[1] = ycor[0];
8044 
8045 
8046 		      if (status == -1)
8047 			{
8048 			  HEpush(DFE_GENAPP, "GDdefboxregion", __FILE__, __LINE__);
8049 			  free(utlbuf);
8050 			  free(gridname);
8051 			  return (status);
8052 			}
8053 
8054 			/* MinCol -> meters -> upleftpt[0] */
8055 			/* ------------------------------- */
8056 			xmtr[0] = upleftpt_m[0] + xscale * minCol;
8057 
8058 			/* MinRow -> meters -> upleftpt[1] */
8059 			/* ------------------------------- */
8060 			ymtr[0] = upleftpt_m[1] + yscale * minRow;
8061 
8062 			/* MinCol + 1 -> meters -> lowrightpt[0] */
8063 			/* ------------------------------------- */
8064 			xmtr[1] = upleftpt_m[0] + xscale * (maxCol + 1);
8065 
8066 			/* MinRow + 1 -> meters -> lowrightpt[1] */
8067 			/* ------------------------------------- */
8068 			ymtr[1] = upleftpt_m[1] + yscale * (maxRow + 1);
8069 
8070 			/* Convert upleft & lowright lon from DMS to radians */
8071 			/* ------------------------------------------------- */
8072 			npnts = 2;
8073 			status = GDmm2ll_cea(projcode, zonecode, spherecode,
8074 					     projparm, xdimsize, ydimsize,
8075 					     upleftpt, lowrightpt, npnts,
8076 					     xmtr,  ymtr,
8077 					     longitude, latitude);
8078 			if (status == -1)
8079 			  {
8080 			    HEpush(DFE_GENAPP, "GDdefboxregion", __FILE__, __LINE__);
8081 			    free(utlbuf);
8082 			    free(gridname);
8083 			    return (status);
8084 			}
8085 			GDXRegion[i]->upleftpt[0] = longitude[0];
8086 
8087 			GDXRegion[i]->upleftpt[1] = latitude[0];
8088 
8089 			GDXRegion[i]->lowrightpt[0] = longitude[1];
8090 
8091 			GDXRegion[i]->lowrightpt[1] = latitude[1];
8092 		    }
8093 		    else if (projcode == GCTP_SOM)
8094                     {
8095 		       /* Store start & count along x & y */
8096 		       /* ------------------------------- */
8097 		       GDXRegion[i]->xStart = 0;
8098 		       GDXRegion[i]->xCount = xdimsize;
8099 		       GDXRegion[i]->yStart = 0;
8100 		       GDXRegion[i]->yCount = ydimsize;
8101 
8102                        GDXRegion[i]->somStart = blockindexstart;
8103                        GDXRegion[i]->somCount = blockindexstop - blockindexstart + 1;
8104 
8105 		       /* Store upleft and lowright points of subset region */
8106 		       /* ------------------------------------------------- */
8107                        if (blockindexstart == 0)
8108                        {
8109                           GDXRegion[i]->upleftpt[0] = upleftpt[0];
8110                           GDXRegion[i]->upleftpt[1] = upleftpt[1];
8111                           GDXRegion[i]->lowrightpt[0] = lowrightpt[0];
8112                           GDXRegion[i]->lowrightpt[1] = lowrightpt[1];
8113                        }
8114                        else
8115                        {
8116                           GDXRegion[i]->upleftpt[0] =
8117 			    (lowrightpt[0] - upleftpt[0])*
8118 			    (offset[blockindexstart-1]/xdimsize) + upleftpt[0];
8119                           GDXRegion[i]->upleftpt[1] =
8120 			    (lowrightpt[1] - upleftpt[1])*
8121 			    (blockindexstart+1-1) + upleftpt[1];
8122 
8123                           GDXRegion[i]->lowrightpt[0] =
8124 			    (lowrightpt[0] - upleftpt[0])*
8125 			    (offset[blockindexstart-1]/xdimsize) + lowrightpt[0];
8126                           GDXRegion[i]->lowrightpt[1] =
8127 			    (lowrightpt[1] - upleftpt[1])*
8128 			    (blockindexstart+1-1) + lowrightpt[1];
8129 
8130                        }
8131                     }
8132                     else
8133 		    {
8134 			/* Non-GEO, Non-BCEA projections */
8135 			/* ---------------------------- */
8136 
8137 			/* Compute X & Y scale */
8138 			/* ------------------- */
8139 			xscale = (lowrightpt[0] - upleftpt[0]) / xdimsize;
8140 			yscale = (lowrightpt[1] - upleftpt[1]) / ydimsize;
8141 
8142 
8143 			/* MinCol -> meters -> upleftpt[0] */
8144 			/* ------------------------------- */
8145 			GDXRegion[i]->upleftpt[0] = upleftpt[0] +
8146 			    xscale * minCol;
8147 
8148 
8149 			/* MinRow -> meters -> upleftpt[1] */
8150 			/* ------------------------------- */
8151 			GDXRegion[i]->upleftpt[1] = upleftpt[1] +
8152 			    yscale * minRow;
8153 
8154 
8155 			/* MinCol + 1 -> meters -> lowrightpt[0] */
8156 			/* ------------------------------------- */
8157 			GDXRegion[i]->lowrightpt[0] = upleftpt[0] +
8158 			    xscale * (maxCol + 1);
8159 
8160 
8161 			/* MinRow + 1 -> meters -> lowrightpt[1] */
8162 			/* ------------------------------------- */
8163 			GDXRegion[i]->lowrightpt[1] = upleftpt[1] +
8164 			  yscale * (maxRow + 1);
8165 		    }
8166 
8167 		    /* Store region ID */
8168 		    /* --------------- */
8169 		    regionID = i;
8170 		    break;
8171 		}
8172 
8173 	}
8174       }
8175 
8176     }
8177     free(utlbuf);
8178     free(gridname);
8179     return (regionID);
8180 }
8181 
8182 
8183 
8184 
8185 
8186 /*----------------------------------------------------------------------------|
8187 |  BEGIN_PROLOG                                                               |
8188 |                                                                             |
8189 |  FUNCTION: GDregioninfo                                                     |
8190 |                                                                             |
8191 |  DESCRIPTION: Retrieves size of region in bytes.                            |
8192 |                                                                             |
8193 |                                                                             |
8194 |  Return Value    Type     Units     Description                             |
8195 |  ============   ======  =========   =====================================   |
8196 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
8197 |                                                                             |
8198 |  INPUTS:                                                                    |
8199 |  gridID         int32               Grid structure ID                       |
8200 |  regionID       int32               Region ID                               |
8201 |  fieldname      char                Fieldname                               |
8202 |                                                                             |
8203 |                                                                             |
8204 |  OUTPUTS:                                                                   |
8205 |  ntype          int32               field number type                       |
8206 |  rank           int32               field rank                              |
8207 |  dims           int32               dimensions of field region              |
8208 |  size           int32               size in bytes of field region           |
8209 |  upleftpt       float64             Upper left corner coord for region      |
8210 |  lowrightpt     float64             Lower right corner coord for region     |
8211 |                                                                             |
8212 |  NOTES:                                                                     |
8213 |                                                                             |
8214 |                                                                             |
8215 |   Date     Programmer   Description                                         |
8216 |  ======   ============  =================================================   |
8217 |  Jun 96   Joel Gales    Original Programmer                                 |
8218 |  Aug 96   Joel Gales    Add vertical subsetting                             |
8219 |  Dec 96   Joel Gales    Add multiple vertical subsetting capability         |
8220 |  Apr 99   David Wynne   Added support for MISR SOM projection, NCR 21195    |
8221 |                                                                             |
8222 |  END_PROLOG                                                                 |
8223 -----------------------------------------------------------------------------*/
8224 intn
GDregioninfo(int32 gridID,int32 regionID,char * fieldname,int32 * ntype,int32 * rank,int32 dims[],int32 * size,float64 upleftpt[],float64 lowrightpt[])8225 GDregioninfo(int32 gridID, int32 regionID, char *fieldname,
8226 	     int32 * ntype, int32 * rank, int32 dims[], int32 * size,
8227 	     float64 upleftpt[], float64 lowrightpt[])
8228 {
8229     intn            j;		/* Loop index */
8230     intn            status = 0;	/* routine return status variable */
8231 
8232     int32           fid;	/* HDF-EOS file ID */
8233     int32           sdInterfaceID;	/* HDF SDS interface ID */
8234     int32           gdVgrpID;	/* Grid root Vgroup ID */
8235     int32           index;	/* Dimension index */
8236 
8237     char            dimlist[256];	/* Dimension list */
8238     char           *errMesg = "Vertical Dimension Not Found: \"%s\".\n";
8239     char           *errM1 = "Both \"XDim\" and \"YDim\" must be present ";
8240     char           *errM2 = "in the dimension list for \"%s\".\n";
8241     char            errbuf[256];/* Error buffer */
8242 
8243 
8244     /* Check for valid grid ID */
8245     /* ----------------------- */
8246     status = GDchkgdid(gridID, "GDregioninfo", &fid, &sdInterfaceID,
8247 		       &gdVgrpID);
8248 
8249 
8250     /* Check for valid region ID */
8251     /* ------------------------- */
8252     if (status == 0)
8253     {
8254 	if (regionID < 0 || regionID >= NGRIDREGN)
8255 	{
8256 	    status = -1;
8257 	    HEpush(DFE_RANGE, "GDregioninfo", __FILE__, __LINE__);
8258 	    HEreport("Invalid Region id: %d.\n", regionID);
8259 	}
8260     }
8261 
8262 
8263     /* Check for active region ID */
8264     /* -------------------------- */
8265     if (status == 0)
8266     {
8267 	if (GDXRegion[regionID] == 0)
8268 	{
8269 	    status = -1;
8270 	    HEpush(DFE_GENAPP, "GDregioninfo", __FILE__, __LINE__);
8271 	    HEreport("Inactive Region ID: %d.\n", regionID);
8272 	}
8273     }
8274 
8275 
8276 
8277     /* Check that region defined for this file */
8278     /* --------------------------------------- */
8279     if (status == 0)
8280     {
8281 	if (GDXRegion[regionID]->fid != fid)
8282 	{
8283 	    status = -1;
8284 	    HEpush(DFE_GENAPP, "GDregioninfo", __FILE__, __LINE__);
8285 	    HEreport("Region is not defined for this file.\n");
8286 	}
8287     }
8288 
8289 
8290     /* Check that region defined for this grid */
8291     /* --------------------------------------- */
8292     if (status == 0)
8293     {
8294 	if (GDXRegion[regionID]->gridID != gridID)
8295 	{
8296 	    status = -1;
8297 	    HEpush(DFE_GENAPP, "GDregioninfo", __FILE__, __LINE__);
8298 	    HEreport("Region is not defined for this Grid.\n");
8299 	}
8300     }
8301 
8302 
8303 
8304     /* Check for valid fieldname */
8305     /* ------------------------- */
8306     if (status == 0)
8307     {
8308 	status = GDfieldinfo(gridID, fieldname, rank, dims, ntype, dimlist);
8309 
8310 	if (status != 0)
8311 	{
8312 	    /* Fieldname not found in grid */
8313 	    /* --------------------------- */
8314 	    status = -1;
8315 	    HEpush(DFE_GENAPP, "GDregioninfo", __FILE__, __LINE__);
8316 	    HEreport("Fieldname \"%s\" not found.\n",
8317 		     fieldname);
8318 	}
8319 	else if (*rank == 1)
8320 	{
8321 	    /* Field is 1 dimensional */
8322 	    /* ---------------------- */
8323 	    status = -1;
8324 	    HEpush(DFE_GENAPP, "GDregioninfo", __FILE__, __LINE__);
8325 	    HEreport(
8326 		     "One-Dimesional fields \"%s\" may not be subsetted.\n",
8327 		     fieldname);
8328 	}
8329 	else
8330 	{
8331 	    /* "XDim" and/or "YDim" not found */
8332 	    /* ------------------------------ */
8333 	    if (EHstrwithin("XDim", dimlist, ',') == -1 ||
8334 		EHstrwithin("YDim", dimlist, ',') == -1)
8335 	    {
8336 		status = -1;
8337 		HEpush(DFE_GENAPP, "GDregioninfo", __FILE__, __LINE__);
8338 		sprintf(errbuf, "%s%s", errM1, errM2);
8339 		HEreport(errbuf, fieldname);
8340 	    }
8341 	}
8342     }
8343 
8344 
8345 
8346     /* If no problems ... */
8347     /* ------------------ */
8348     if (status == 0)
8349     {
8350         /* Check if SOM projection */
8351         /* ----------------------- */
8352         if (EHstrwithin("SOMBlockDim", dimlist, ',') == 0)
8353         {
8354             dims[EHstrwithin("SOMBlockDim", dimlist, ',')] =
8355                 GDXRegion[regionID]->somCount;
8356         }
8357 
8358 	/* Load XDim dimension from region entry */
8359 	/* ------------------------------------- */
8360 	if (GDXRegion[regionID]->xCount != 0)
8361 	{
8362 	    dims[EHstrwithin("XDim", dimlist, ',')] =
8363 		GDXRegion[regionID]->xCount;
8364 	}
8365 
8366 	/* Load YDim dimension from region entry */
8367 	/* ------------------------------------- */
8368 	if (GDXRegion[regionID]->yCount != 0)
8369 	{
8370 	    dims[EHstrwithin("YDim", dimlist, ',')] =
8371 		GDXRegion[regionID]->yCount;
8372 	}
8373 
8374 
8375 	/* Vertical Subset */
8376 	/* --------------- */
8377 	for (j = 0; j < 8; j++)
8378 	{
8379 
8380 	    /* If active vertical subset ... */
8381 	    /* ----------------------------- */
8382 	    if (GDXRegion[regionID]->StartVertical[j] != -1)
8383 	    {
8384 		/* Find vertical dimension within dimlist */
8385 		/* -------------------------------------- */
8386 		index = EHstrwithin(GDXRegion[regionID]->DimNamePtr[j],
8387 				    dimlist, ',');
8388 
8389 		/* If dimension found ... */
8390 		/* ---------------------- */
8391 		if (index != -1)
8392 		{
8393 		    /* Compute dimension size */
8394 		    /* ---------------------- */
8395 		    dims[index] =
8396 			GDXRegion[regionID]->StopVertical[j] -
8397 			GDXRegion[regionID]->StartVertical[j] + 1;
8398 		}
8399 		else
8400 		{
8401 		    /* Vertical dimension not found */
8402 		    /* ---------------------------- */
8403 		    status = -1;
8404 		    *size = -1;
8405 		    HEpush(DFE_GENAPP, "GDregioninfo",
8406 			   __FILE__, __LINE__);
8407 		    HEreport(errMesg,
8408 			     GDXRegion[regionID]->DimNamePtr[j]);
8409 		}
8410 	    }
8411 	}
8412 
8413 
8414 	if (status == 0)
8415 	{
8416 	    /* Compute number of total elements */
8417 	    /* -------------------------------- */
8418 	    *size = dims[0];
8419 	    for (j = 1; j < *rank; j++)
8420 	    {
8421 		*size *= dims[j];
8422 	    }
8423 
8424 	    /* Multiply by size in bytes of numbertype */
8425 	    /* --------------------------------------- */
8426 	    *size *= DFKNTsize(*ntype);
8427 
8428 
8429 	    /* Return upper left and lower right subset values */
8430 	    /* ----------------------------------------------- */
8431 	    upleftpt[0] = GDXRegion[regionID]->upleftpt[0];
8432 	    upleftpt[1] = GDXRegion[regionID]->upleftpt[1];
8433 	    lowrightpt[0] = GDXRegion[regionID]->lowrightpt[0];
8434 	    lowrightpt[1] = GDXRegion[regionID]->lowrightpt[1];
8435 	}
8436     }
8437     return (status);
8438 }
8439 
8440 
8441 
8442 
8443 
8444 /*----------------------------------------------------------------------------|
8445 |  BEGIN_PROLOG                                                               |
8446 |                                                                             |
8447 |  FUNCTION: GDextractregion                                                  |
8448 |                                                                             |
8449 |  DESCRIPTION: Retrieves data from specified region.                         |
8450 |                                                                             |
8451 |                                                                             |
8452 |  Return Value    Type     Units     Description                             |
8453 |  ============   ======  =========   =====================================   |
8454 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
8455 |                                                                             |
8456 |  INPUTS:                                                                    |
8457 |  gridID         int32               Grid structure ID                       |
8458 |  regionID       int32               Region ID                               |
8459 |  fieldname      char                Fieldname                               |
8460 |                                                                             |
8461 |  OUTPUTS:                                                                   |
8462 |  buffer         void                Data buffer containing subsetted region |
8463 |                                                                             |
8464 |                                                                             |
8465 |  NOTES:                                                                     |
8466 |                                                                             |
8467 |                                                                             |
8468 |   Date     Programmer   Description                                         |
8469 |  ======   ============  =================================================   |
8470 |  Jun 96   Joel Gales    Original Programmer                                 |
8471 |  Aug 96   Joel Gales    Add vertical subsetting                             |
8472 |  Dec 96   Joel Gales    Add multiple vertical subsetting capability         |
8473 |  Apr 99   David Wynne   Add support for MISR SOM projection, NCR 21195      |
8474 |                                                                             |
8475 |  END_PROLOG                                                                 |
8476 -----------------------------------------------------------------------------*/
8477 intn
GDextractregion(int32 gridID,int32 regionID,char * fieldname,VOIDP buffer)8478 GDextractregion(int32 gridID, int32 regionID, char *fieldname,
8479 		VOIDP buffer)
8480 {
8481     intn            i;		/* Loop index */
8482     intn            j;		/* Loop index */
8483     intn            status = 0;	/* routine return status variable */
8484 
8485     int32           fid;	/* HDF-EOS file ID */
8486     int32           sdInterfaceID;	/* HDF SDS interface ID */
8487     int32           gdVgrpID;	/* Grid root Vgroup ID */
8488     int32           index;	/* Dimension index */
8489     int32           start[8];	/* Start array for data read */
8490     int32           edge[8];	/* Edge array for data read */
8491     int32           dims[8];	/* Dimensions */
8492     int32           rank;	/* Field rank */
8493     int32           ntype;	/* Field number type */
8494     int32           origincode;	/* Pixel origin code */
8495 
8496     char            dimlist[256];	/* Dimension list */
8497     char           *errMesg = "Vertical Dimension Not Found: \"%s\".\n";
8498     char           *errM1 = "Both \"XDim\" and \"YDim\" must be present ";
8499     char           *errM2 = "in the dimension list for \"%s\".\n";
8500     char            errbuf[256];/* Error buffer */
8501 
8502 
8503     /* Check for valid grid ID */
8504     /* ----------------------- */
8505     status = GDchkgdid(gridID, "GDextractregion", &fid, &sdInterfaceID,
8506 		       &gdVgrpID);
8507 
8508 
8509     /* Check for valid region ID */
8510     /* ------------------------- */
8511     if (status == 0)
8512     {
8513 	if (regionID < 0 || regionID >= NGRIDREGN)
8514 	{
8515 	    status = -1;
8516 	    HEpush(DFE_RANGE, "GDextractregion", __FILE__, __LINE__);
8517 	    HEreport("Invalid Region id: %d.\n", regionID);
8518 	}
8519     }
8520 
8521 
8522     /* Check for active region ID */
8523     /* -------------------------- */
8524     if (status == 0)
8525     {
8526 	if (GDXRegion[regionID] == 0)
8527 	{
8528 	    status = -1;
8529 	    HEpush(DFE_GENAPP, "GDextractregion", __FILE__, __LINE__);
8530 	    HEreport("Inactive Region ID: %d.\n", regionID);
8531 	}
8532     }
8533 
8534 
8535 
8536     /* Check that region defined for this file */
8537     /* --------------------------------------- */
8538     if (status == 0)
8539     {
8540 	if (GDXRegion[regionID]->fid != fid)
8541 	{
8542 	    status = -1;
8543 	    HEpush(DFE_GENAPP, "GDextractregion", __FILE__, __LINE__);
8544 	    HEreport("Region is not defined for this file.\n");
8545 	}
8546     }
8547 
8548 
8549     /* Check that region defined for this grid */
8550     /* --------------------------------------- */
8551     if (status == 0)
8552     {
8553 	if (GDXRegion[regionID]->gridID != gridID)
8554 	{
8555 	    status = -1;
8556 	    HEpush(DFE_GENAPP, "GDextractregion", __FILE__, __LINE__);
8557 	    HEreport("Region is not defined for this Grid.\n");
8558 	}
8559     }
8560 
8561 
8562 
8563     /* Check for valid fieldname */
8564     /* ------------------------- */
8565     if (status == 0)
8566     {
8567 	status = GDfieldinfo(gridID, fieldname, &rank, dims, &ntype, dimlist);
8568 
8569 	if (status != 0)
8570 	{
8571 	    /* Fieldname not found in grid */
8572 	    /* --------------------------- */
8573 	    status = -1;
8574 	    HEpush(DFE_GENAPP, "GDextractregion", __FILE__, __LINE__);
8575 	    HEreport("Fieldname \"%s\" not found.\n",
8576 		     fieldname);
8577 	}
8578 	else if (rank == 1)
8579 	{
8580 	    /* Field is 1 dimensional */
8581 	    /* ---------------------- */
8582 	    status = -1;
8583 	    HEpush(DFE_GENAPP, "GDextractregion", __FILE__, __LINE__);
8584 	    HEreport(
8585 		     "One-Dimesional fields \"%s\" may not be subsetted.\n",
8586 		     fieldname);
8587 	}
8588 	else
8589 	{
8590 	    /* "XDim" and/or "YDim" not found */
8591 	    /* ------------------------------ */
8592 	    if (EHstrwithin("XDim", dimlist, ',') == -1 ||
8593 		EHstrwithin("YDim", dimlist, ',') == -1)
8594 	    {
8595 		status = -1;
8596 		HEpush(DFE_GENAPP, "GDextractregion", __FILE__, __LINE__);
8597 		sprintf(errbuf, "%s%s", errM1, errM2);
8598 		HEreport(errbuf, fieldname);
8599 	    }
8600 	}
8601     }
8602 
8603 
8604 
8605     if (status == 0)
8606     {
8607 
8608 	/* Get origin order info */
8609 	/* --------------------- */
8610 	status = GDorigininfo(gridID, &origincode);
8611 
8612 
8613 	/* Initialize start & edge arrays */
8614 	/* ------------------------------ */
8615 	for (i = 0; i < rank; i++)
8616 	{
8617 	    start[i] = 0;
8618 	    edge[i] = dims[i];
8619 	}
8620 
8621 
8622 	/* if MISR SOM projection, set start */
8623 	/* & edge arrays for SOMBlockDim     */
8624 	/* --------------------------------- */
8625 	if (EHstrwithin("SOMBlockDim", dimlist, ',') == 0)
8626 	{
8627 	    index = EHstrwithin("SOMBlockDim", dimlist, ',');
8628 	    edge[index] = GDXRegion[regionID]->somCount;
8629 	    start[index] = GDXRegion[regionID]->somStart;
8630 	}
8631 
8632 
8633 	/* Set start & edge arrays for XDim */
8634 	/* -------------------------------- */
8635 	index = EHstrwithin("XDim", dimlist, ',');
8636 	if (GDXRegion[regionID]->xCount != 0)
8637 	{
8638 	    edge[index] = GDXRegion[regionID]->xCount;
8639 	    start[index] = GDXRegion[regionID]->xStart;
8640 	}
8641 
8642 	/* Adjust X-dim start if origin on right edge */
8643 	/* ------------------------------------------ */
8644 	if ((origincode & 1) == 1)
8645 	{
8646 	    start[index] = dims[index] - (start[index] + edge[index]);
8647 	}
8648 
8649 
8650 	/* Set start & edge arrays for YDim */
8651 	/* -------------------------------- */
8652 	index = EHstrwithin("YDim", dimlist, ',');
8653 	if (GDXRegion[regionID]->yCount != 0)
8654 	{
8655 	    start[index] = GDXRegion[regionID]->yStart;
8656 	    edge[index] = GDXRegion[regionID]->yCount;
8657 	}
8658 
8659 	/* Adjust Y-dim start if origin on lower edge */
8660 	/* ------------------------------------------ */
8661 	if ((origincode & 2) == 2)
8662 	{
8663 	    start[index] = dims[index] - (start[index] + edge[index]);
8664 	}
8665 
8666 
8667 
8668 	/* Vertical Subset */
8669 	/* --------------- */
8670 	for (j = 0; j < 8; j++)
8671 	{
8672 	    /* If active vertical subset ... */
8673 	    /* ----------------------------- */
8674 	    if (GDXRegion[regionID]->StartVertical[j] != -1)
8675 	    {
8676 
8677 		/* Find vertical dimension within dimlist */
8678 		/* -------------------------------------- */
8679 		index = EHstrwithin(GDXRegion[regionID]->DimNamePtr[j],
8680 				    dimlist, ',');
8681 
8682 		/* If dimension found ... */
8683 		/* ---------------------- */
8684 		if (index != -1)
8685 		{
8686 		    /* Compute start and edge for vertical dimension */
8687 		    /* --------------------------------------------- */
8688 		    start[index] = GDXRegion[regionID]->StartVertical[j];
8689 		    edge[index] = GDXRegion[regionID]->StopVertical[j] -
8690 			GDXRegion[regionID]->StartVertical[j] + 1;
8691 		}
8692 		else
8693 		{
8694 		    /* Vertical dimension not found */
8695 		    /* ---------------------------- */
8696 		    status = -1;
8697 		    HEpush(DFE_GENAPP, "GDextractregion", __FILE__, __LINE__);
8698 		    HEreport(errMesg,
8699 			     GDXRegion[regionID]->DimNamePtr[j]);
8700 		}
8701 	    }
8702 	}
8703 
8704 
8705 	/* Read into data buffer */
8706 	/* --------------------- */
8707 	if (status == 0)
8708 	{
8709 	    status = GDreadfield(gridID, fieldname, start, NULL, edge, buffer);
8710 	}
8711     }
8712     return (status);
8713 }
8714 
8715 
8716 
8717 
8718 /*----------------------------------------------------------------------------|
8719 |  BEGIN_PROLOG                                                               |
8720 |                                                                             |
8721 |  FUNCTION: GDdupregion                                                      |
8722 |                                                                             |
8723 |  DESCRIPTION: Duplicates a region                                           |
8724 |                                                                             |
8725 |                                                                             |
8726 |  Return Value    Type     Units     Description                             |
8727 |  ============   ======  =========   =====================================   |
8728 |  newregionID    int32               New region ID                           |
8729 |                                                                             |
8730 |  INPUTS:                                                                    |
8731 |  oldregionID    int32               Old region ID                           |
8732 |                                                                             |
8733 |  OUTPUTS:                                                                   |
8734 |             None                                                            |
8735 |                                                                             |
8736 |  NOTES:                                                                     |
8737 |                                                                             |
8738 |                                                                             |
8739 |   Date     Programmer   Description                                         |
8740 |  ======   ============  =================================================   |
8741 |  Jan 97   Joel Gales    Original Programmer                                 |
8742 |  Oct 98   Abe Taaheri   changed *GDXRegion[i] = *GDXRegion[oldregionID];    |
8743 |                         to copy elements of structure one by one to avoid   |
8744 |                         copying pointer for DimNamePtr to another place that|
8745 |                         causes "Freeing Unallocated Memory" in purify when  |
8746 |                         using GDdetach                                      |
8747 |                                                                             |
8748 |  END_PROLOG                                                                 |
8749 -----------------------------------------------------------------------------*/
8750 int32
GDdupregion(int32 oldregionID)8751 GDdupregion(int32 oldregionID)
8752 {
8753     intn            i;		/* Loop index */
8754     intn            j;          /* Loop index */
8755     int32           slendupregion;
8756     int32           newregionID = -1;	/* New region ID */
8757 
8758 
8759     /* Find first empty (inactive) region */
8760     /* ---------------------------------- */
8761     for (i = 0; i < NGRIDREGN; i++)
8762     {
8763 	if (GDXRegion[i] == 0)
8764 	{
8765 	    /* Allocate space for new grid region entry */
8766 	    /* ---------------------------------------- */
8767 	    GDXRegion[i] = (struct gridRegion *)
8768 		calloc(1, sizeof(struct gridRegion));
8769 	    if(GDXRegion[i] == NULL)
8770 	    {
8771 		HEpush(DFE_NOSPACE,"GDdupregion", __FILE__, __LINE__);
8772 		return(-1);
8773 	    }
8774 
8775 
8776 	    /* Copy old region structure data to new region */
8777 	    /* -------------------------------------------- */
8778 
8779             GDXRegion[i]->fid = GDXRegion[oldregionID]->fid;
8780             GDXRegion[i]->gridID = GDXRegion[oldregionID]->gridID;
8781             GDXRegion[i]->xStart = GDXRegion[oldregionID]->xStart;
8782             GDXRegion[i]->xCount = GDXRegion[oldregionID]->xCount;
8783             GDXRegion[i]->yStart = GDXRegion[oldregionID]->yStart;
8784             GDXRegion[i]->yCount = GDXRegion[oldregionID]->yCount;
8785             GDXRegion[i]->upleftpt[0] = GDXRegion[oldregionID]->upleftpt[0];
8786             GDXRegion[i]->upleftpt[1] = GDXRegion[oldregionID]->upleftpt[1];
8787             GDXRegion[i]->lowrightpt[0] = GDXRegion[oldregionID]->lowrightpt[0];
8788             GDXRegion[i]->lowrightpt[1] = GDXRegion[oldregionID]->lowrightpt[1];
8789             for (j = 0; j < 8; j++)
8790             {
8791                 GDXRegion[i]->StartVertical[j] = GDXRegion[oldregionID]->StartVertical[j];
8792                 GDXRegion[i]->StopVertical[j] = GDXRegion[oldregionID]->StopVertical[j];
8793             }
8794 
8795             for (j=0; j<8; j++)
8796             {
8797                 if(GDXRegion[oldregionID]->DimNamePtr[j] != NULL)
8798                 {
8799                     slendupregion = strlen(GDXRegion[oldregionID]->DimNamePtr[j]);
8800                     GDXRegion[i]->DimNamePtr[j] = (char *) malloc(slendupregion + 1);
8801                     strcpy(GDXRegion[i]->DimNamePtr[j],GDXRegion[oldregionID]->DimNamePtr[j]);
8802 		}
8803             }
8804 
8805 
8806 	    /* Define new region ID */
8807 	    /* -------------------- */
8808 	    newregionID = i;
8809 
8810 	    break;
8811 	}
8812     }
8813     return (newregionID);
8814 }
8815 
8816 
8817 /*----------------------------------------------------------------------------|
8818 |  BEGIN_PROLOG                                                               |
8819 |                                                                             |
8820 |  FUNCTION: GDdefvrtregion                                                   |
8821 |                                                                             |
8822 |  DESCRIPTION: Finds elements of a monotonic field within a vertical subset  |
8823 |               region.                                                       |
8824 |                                                                             |
8825 |                                                                             |
8826 |  Return Value    Type     Units     Description                             |
8827 |  ============   ======  =========   =====================================   |
8828 |  regionID       int32               Region ID                               |
8829 |                                                                             |
8830 |  INPUTS:                                                                    |
8831 |  gridID         int32               Grid structure ID                       |
8832 |  regionID       int32               Region ID                               |
8833 |  vertObj        char                Vertical object to subset               |
8834 |  range          float64             Vertical subsetting range               |
8835 |                                                                             |
8836 |  OUTPUTS:                                                                   |
8837 |             None                                                            |
8838 |                                                                             |
8839 |  NOTES:                                                                     |
8840 |                                                                             |
8841 |                                                                             |
8842 |   Date     Programmer   Description                                         |
8843 |  ======   ============  =================================================   |
8844 |  Aug 96   Joel Gales    Original Programmer                                 |
8845 |  Dec 96   Joel Gales    Add multiple vertical subsetting capability         |
8846 |  Feb 97   Joel Gales    Store XDim, YDim, upleftpt, lowrightpt in GDXRegion |
8847 |                                                                             |
8848 |  END_PROLOG                                                                 |
8849 -----------------------------------------------------------------------------*/
8850 #define SETGRIDREG \
8851 \
8852 status = GDgridinfo(gridID, &xdimsize, &ydimsize, upleftpt, lowrightpt); \
8853 for (k = 0; k < NGRIDREGN; k++) \
8854 { \
8855     if (GDXRegion[k] == 0) \
8856     { \
8857         GDXRegion[k] = (struct gridRegion *) \
8858 	  calloc(1, sizeof(struct gridRegion)); \
8859 	GDXRegion[k]->fid = fid; \
8860 	GDXRegion[k]->gridID = gridID; \
8861 	GDXRegion[k]->xStart = 0; \
8862 	GDXRegion[k]->xCount = xdimsize; \
8863 	GDXRegion[k]->yStart = 0; \
8864 	GDXRegion[k]->yCount = ydimsize; \
8865 	GDXRegion[k]->upleftpt[0] = upleftpt[0]; \
8866 	GDXRegion[k]->upleftpt[1] = upleftpt[1]; \
8867 	GDXRegion[k]->lowrightpt[0] = lowrightpt[0]; \
8868 	GDXRegion[k]->lowrightpt[1] = lowrightpt[1]; \
8869 	regionID = k; \
8870 	for (j=0; j<8; j++) \
8871         { \
8872              GDXRegion[k]->StartVertical[j] = -1; \
8873              GDXRegion[k]->StopVertical[j]  = -1; \
8874         } \
8875 	break; \
8876      } \
8877 }
8878 
8879 #define FILLVERTREG \
8880 for (j=0; j<8; j++) \
8881 { \
8882     if (GDXRegion[regionID]->StartVertical[j] == -1) \
8883     { \
8884 	GDXRegion[regionID]->StartVertical[j] = i; \
8885 	GDXRegion[regionID]->DimNamePtr[j] = \
8886 	    (char *) malloc(slen + 1); \
8887 	memcpy(GDXRegion[regionID]->DimNamePtr[j], \
8888 	       dimlist, slen + 1); \
8889 	break; \
8890     } \
8891 } \
8892 
8893 
8894 
8895 int32
GDdefvrtregion(int32 gridID,int32 regionID,char * vertObj,float64 range[])8896 GDdefvrtregion(int32 gridID, int32 regionID, char *vertObj, float64 range[])
8897 {
8898     intn            i, j, k, status;
8899     uint8           found = 0;
8900 
8901     int16           vertINT16;
8902 
8903     int32           fid, sdInterfaceID, slen;
8904     int32           gdVgrpID, rank, nt, dims[8], size;
8905     int32           vertINT32;
8906     int32           xdimsize;
8907     int32           ydimsize;
8908 
8909     float32         vertFLT32;
8910     float64         vertFLT64;
8911     float64         upleftpt[2];
8912     float64         lowrightpt[2];
8913 
8914     char           *vertArr;
8915     char           *dimlist;
8916 
8917     /* Allocate space for dimlist */
8918     /* --------------------------------- */
8919     dimlist = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
8920     if(dimlist == NULL)
8921     {
8922 	HEpush(DFE_NOSPACE,"GDdefvrtregion", __FILE__, __LINE__);
8923 	return(-1);
8924     }
8925     /* Check for valid grid ID */
8926     /* ----------------------- */
8927     status = GDchkgdid(gridID, "GDdefvrtregion",
8928 		       &fid, &sdInterfaceID, &gdVgrpID);
8929 
8930     if (status == 0)
8931     {
8932 	memcpy(dimlist, vertObj, 4);
8933 	dimlist[4] = 0;
8934 
8935 	if (strcmp(dimlist, "DIM:") == 0)
8936 	{
8937 	    slen = strlen(vertObj) - 4;
8938 	    if (regionID == -1)
8939 	    {
8940 		SETGRIDREG;
8941 	    }
8942 	    for (j = 0; j < 8; j++)
8943 	    {
8944 		if (GDXRegion[regionID]->StartVertical[j] == -1)
8945 		{
8946 		    GDXRegion[regionID]->StartVertical[j] = (int32) range[0];
8947 		    GDXRegion[regionID]->StopVertical[j] = (int32) range[1];
8948 		    GDXRegion[regionID]->DimNamePtr[j] =
8949 			(char *) malloc(slen + 1);
8950 		    if(GDXRegion[regionID]->DimNamePtr[j] == NULL)
8951 		    {
8952 			HEpush(DFE_NOSPACE,"GDdefvrtregion", __FILE__, __LINE__);
8953 			free(dimlist);
8954 			return(-1);
8955 		    }
8956 		    memcpy(GDXRegion[regionID]->DimNamePtr[j],
8957 			   vertObj + 4, slen + 1);
8958 		    break;
8959 		}
8960 	    }
8961 	}
8962 	else
8963 	{
8964 	    status = GDfieldinfo(gridID, vertObj, &rank, dims, &nt, dimlist);
8965 	    if (status != 0)
8966 	    {
8967 		status = -1;
8968 		HEpush(DFE_GENAPP, "GDdefvrtregion", __FILE__, __LINE__);
8969 		HEreport("Vertical Field: \"%s\" not found.\n", vertObj);
8970 	    }
8971 	    else
8972 	    {
8973 		if (rank != 1)
8974 		{
8975 		    status = -1;
8976 		    HEpush(DFE_GENAPP, "GDdefvrtregion", __FILE__, __LINE__);
8977 		    HEreport("Vertical Field: \"%s\" must be 1-dim.\n",
8978 			     vertObj);
8979 		}
8980 		else
8981 		{
8982 		    slen = strlen(dimlist);
8983 		    size = DFKNTsize(nt);
8984 		    vertArr = (char *) calloc(dims[0], size);
8985 		    if(vertArr == NULL)
8986 		    {
8987 			HEpush(DFE_NOSPACE,"GDdefvrtregion", __FILE__, __LINE__);
8988 			free(dimlist);
8989 			return(-1);
8990 		    }
8991 
8992 		    status = GDreadfield(gridID, vertObj,
8993 					 NULL, NULL, NULL, vertArr);
8994 
8995 		    switch (nt)
8996 		    {
8997 		    case DFNT_INT16:
8998 
8999 			for (i = 0; i < dims[0]; i++)
9000 			{
9001 			    memcpy(&vertINT16, vertArr + i * size, size);
9002 
9003 			    if (vertINT16 >= range[0] &&
9004 				vertINT16 <= range[1])
9005 			    {
9006 				found = 1;
9007 				if (regionID == -1)
9008 				{
9009 				    SETGRIDREG;
9010 				}
9011 				FILLVERTREG;
9012 
9013 				break;
9014 			    }
9015 			}
9016 
9017 			if (found == 1)
9018 			{
9019 			    for (i = dims[0] - 1; i >= 0; i--)
9020 			    {
9021 				memcpy(&vertINT16, vertArr + i * size, size);
9022 
9023 				if (vertINT16 >= range[0] &&
9024 				    vertINT16 <= range[1])
9025 				{
9026 				    GDXRegion[regionID]->StopVertical[j] = i;
9027 				    break;
9028 				}
9029 			    }
9030 			}
9031 			else
9032 			{
9033 			    status = -1;
9034 			}
9035 			break;
9036 
9037 
9038 		    case DFNT_INT32:
9039 
9040 			for (i = 0; i < dims[0]; i++)
9041 			{
9042 			    memcpy(&vertINT32, vertArr + i * size, size);
9043 
9044 			    if (vertINT32 >= range[0] &&
9045 				vertINT32 <= range[1])
9046 			    {
9047 				found = 1;
9048 				if (regionID == -1)
9049 				{
9050 				    SETGRIDREG;
9051 				}
9052 				FILLVERTREG;
9053 
9054 				break;
9055 			    }
9056 			}
9057 
9058 			if (found == 1)
9059 			{
9060 			    for (i = dims[0] - 1; i >= 0; i--)
9061 			    {
9062 				memcpy(&vertINT32, vertArr + i * size, size);
9063 
9064 				if (vertINT32 >= range[0] &&
9065 				    vertINT32 <= range[1])
9066 				{
9067 				    GDXRegion[regionID]->StopVertical[j] = i;
9068 				    break;
9069 				}
9070 			    }
9071 			}
9072 			else
9073 			{
9074 			    status = -1;
9075 			}
9076 			break;
9077 
9078 
9079 		    case DFNT_FLOAT32:
9080 
9081 			for (i = 0; i < dims[0]; i++)
9082 			{
9083 			    memcpy(&vertFLT32, vertArr + i * size, size);
9084 
9085 			    if (vertFLT32 >= range[0] &&
9086 				vertFLT32 <= range[1])
9087 			    {
9088 				found = 1;
9089 				if (regionID == -1)
9090 				{
9091 				    SETGRIDREG;
9092 				}
9093 				FILLVERTREG;
9094 
9095 				break;
9096 			    }
9097 			}
9098 
9099 			if (found == 1)
9100 			{
9101 			    for (i = dims[0] - 1; i >= 0; i--)
9102 			    {
9103 				memcpy(&vertFLT32, vertArr + i * size, size);
9104 
9105 				if (vertFLT32 >= range[0] &&
9106 				    vertFLT32 <= range[1])
9107 				{
9108 				    GDXRegion[regionID]->StopVertical[j] = i;
9109 				    break;
9110 				}
9111 			    }
9112 			}
9113 			else
9114 			{
9115 			    status = -1;
9116 			}
9117 			break;
9118 
9119 
9120 		    case DFNT_FLOAT64:
9121 
9122 			for (i = 0; i < dims[0]; i++)
9123 			{
9124 			    memcpy(&vertFLT64, vertArr + i * size, size);
9125 
9126 			    if (vertFLT64 >= range[0] &&
9127 				vertFLT64 <= range[1])
9128 			    {
9129 				found = 1;
9130 				if (regionID == -1)
9131 				{
9132 				    SETGRIDREG;
9133 				}
9134 				FILLVERTREG;
9135 
9136 				break;
9137 			    }
9138 			}
9139 
9140 			if (found == 1)
9141 			{
9142 			    for (i = dims[0] - 1; i >= 0; i--)
9143 			    {
9144 				memcpy(&vertFLT64, vertArr + i * size, size);
9145 
9146 				if (vertFLT64 >= range[0] &&
9147 				    vertFLT64 <= range[1])
9148 				{
9149 				    GDXRegion[regionID]->StopVertical[j] = i;
9150 				    break;
9151 				}
9152 			    }
9153 			}
9154 			else
9155 			{
9156 			    status = -1;
9157 			}
9158 			break;
9159 
9160 		    }
9161 		    free(vertArr);
9162 		}
9163 	    }
9164 	}
9165     }
9166     if (status == -1)
9167     {
9168 	regionID = -1;
9169     }
9170     free(dimlist);
9171     return (regionID);
9172 }
9173 
9174 
9175 
9176 
9177 
9178 /*----------------------------------------------------------------------------|
9179 |  BEGIN_PROLOG                                                               |
9180 |                                                                             |
9181 |  FUNCTION: GDdeftimeperiod                                                  |
9182 |                                                                             |
9183 |  DESCRIPTION: Finds elements of the "Time" field within a given time        |
9184 |               period.                                                       |
9185 |                                                                             |
9186 |                                                                             |
9187 |  Return Value    Type     Units     Description                             |
9188 |  ============   ======  =========   =====================================   |
9189 |  periodID       int32               Period ID                               |
9190 |                                                                             |
9191 |  INPUTS:                                                                    |
9192 |  gridID         int32               Grid structure ID                       |
9193 |  periodID       int32               Period ID                               |
9194 |  starttime      float64 TAI sec     Start of time period                    |
9195 |  stoptime       float64 TAI sec     Stop of time period                     |
9196 |                                                                             |
9197 |  OUTPUTS:                                                                   |
9198 |             None                                                            |
9199 |                                                                             |
9200 |  NOTES:                                                                     |
9201 |                                                                             |
9202 |                                                                             |
9203 |   Date     Programmer   Description                                         |
9204 |  ======   ============  =================================================   |
9205 |  Aug 96   Joel Gales    Original Programmer                                 |
9206 |                                                                             |
9207 |  END_PROLOG                                                                 |
9208 -----------------------------------------------------------------------------*/
9209 int32
GDdeftimeperiod(int32 gridID,int32 periodID,float64 starttime,float64 stoptime)9210 GDdeftimeperiod(int32 gridID, int32 periodID, float64 starttime,
9211 		float64 stoptime)
9212 {
9213     float64         timerange[2];
9214 
9215     timerange[0] = starttime;
9216     timerange[1] = stoptime;
9217 
9218     periodID = GDdefvrtregion(gridID, periodID, "Time", timerange);
9219 
9220     return (periodID);
9221 }
9222 
9223 
9224 
9225 /*----------------------------------------------------------------------------|
9226 |  BEGIN_PROLOG                                                               |
9227 |                                                                             |
9228 |  FUNCTION: GDgetpixels                                                      |
9229 |                                                                             |
9230 |  DESCRIPTION: Finds row and columns for specified lon/lat values            |
9231 |                                                                             |
9232 |                                                                             |
9233 |  Return Value    Type     Units     Description                             |
9234 |  ============   ======  =========   =====================================   |
9235 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
9236 |                                                                             |
9237 |  INPUTS:                                                                    |
9238 |  gridID         int32               Grid structure ID                       |
9239 |  nLonLat        int32               Number of lonlat values                 |
9240 |  lonVal         float64  dec deg    Longitude values                        |
9241 |  latVal         float64  dec deg    Latitude values                         |
9242 |                                                                             |
9243 |                                                                             |
9244 |  OUTPUTS:                                                                   |
9245 |  pixRow         int32               Pixel rows                              |
9246 |  pixCol         int32               Pixel columns                           |
9247 |                                                                             |
9248 |  NOTES:                                                                     |
9249 |                                                                             |
9250 |                                                                             |
9251 |   Date     Programmer   Description                                         |
9252 |  ======   ============  =================================================   |
9253 |  Aug 96   Joel Gales    Original Programmer                                 |
9254 |  Oct 96   Joel Gales    Set row/col to -1 if outside boundary               |
9255 |  Mar 97   Joel Gales    Adjust row/col for CORNER pixel registration        |
9256 |                                                                             |
9257 |  END_PROLOG                                                                 |
9258 -----------------------------------------------------------------------------*/
9259 intn
GDgetpixels(int32 gridID,int32 nLonLat,float64 lonVal[],float64 latVal[],int32 pixRow[],int32 pixCol[])9260 GDgetpixels(int32 gridID, int32 nLonLat, float64 lonVal[], float64 latVal[],
9261 	    int32 pixRow[], int32 pixCol[])
9262 {
9263     intn            i;		/* Loop index */
9264     intn            status = 0;	/* routine return status variable */
9265 
9266     int32           fid;	/* HDF-EOS file ID */
9267     int32           sdInterfaceID;	/* HDF SDS interface ID */
9268     int32           gdVgrpID;	/* Grid root Vgroup ID */
9269 
9270     int32           xdimsize;	/* Size of "XDim" */
9271     int32           ydimsize;	/* Size of "YDim" */
9272     int32           projcode;	/* GCTP projection code */
9273     int32           zonecode;	/* Zone code */
9274     int32           spherecode;	/* Sphere code */
9275     int32           origincode;	/* Origin code */
9276     int32           pixregcode;	/* Pixel registration code */
9277 
9278     float64         upleftpt[2];/* Upper left point */
9279     float64         lowrightpt[2];	/* Lower right point */
9280     float64         projparm[16];	/* Projection parameters */
9281     float64        *xVal;	/* Pointer to point x location values */
9282     float64        *yVal;	/* Pointer to point y location values */
9283 
9284 
9285     /* Check for valid grid ID */
9286     /* ----------------------- */
9287     status = GDchkgdid(gridID, "GDgetpixels", &fid, &sdInterfaceID, &gdVgrpID);
9288 
9289     if (status == 0)
9290     {
9291 	/* Get grid info */
9292 	/* ------------- */
9293 	status = GDgridinfo(gridID, &xdimsize, &ydimsize,
9294 			    upleftpt, lowrightpt);
9295 
9296 
9297 	/* Get projection info */
9298 	/* ------------------- */
9299 	status = GDprojinfo(gridID, &projcode, &zonecode,
9300 			    &spherecode, projparm);
9301 
9302 
9303 	/* Get explicit upleftpt & lowrightpt if defaults are used */
9304 	/* ------------------------------------------------------- */
9305 	status = GDgetdefaults(projcode, zonecode, projparm, spherecode,
9306 			       upleftpt, lowrightpt);
9307 
9308 
9309 	/* Get pixel registration and origin info */
9310 	/* -------------------------------------- */
9311 	status = GDorigininfo(gridID, &origincode);
9312 	status = GDpixreginfo(gridID, &pixregcode);
9313 
9314 
9315 	/* Allocate space for x & y locations */
9316 	/* ---------------------------------- */
9317 	xVal = (float64 *) calloc(nLonLat, sizeof(float64));
9318 	if(xVal == NULL)
9319 	{
9320 	    HEpush(DFE_NOSPACE,"GDgetpixels", __FILE__, __LINE__);
9321 	    return(-1);
9322 	}
9323 	yVal = (float64 *) calloc(nLonLat, sizeof(float64));
9324 	if(yVal == NULL)
9325 	{
9326 	    HEpush(DFE_NOSPACE,"GDgetpixels", __FILE__, __LINE__);
9327 	    free(xVal);
9328 	    return(-1);
9329 	}
9330 
9331 
9332 	/* Get pixRow, pixCol, xVal, & yVal */
9333 	/* -------------------------------- */
9334 	status = GDll2ij(projcode, zonecode, projparm, spherecode,
9335 			 xdimsize, ydimsize, upleftpt, lowrightpt,
9336 			 nLonLat, lonVal, latVal, pixRow, pixCol,
9337 			 xVal, yVal);
9338 
9339 
9340 
9341 	/* Loop through all lon/lat values */
9342 	/* ------------------------------- */
9343 	for (i = 0; i < nLonLat; i++)
9344 	{
9345 	    /* Adjust columns & rows for "corner" registered grids */
9346 	    /* --------------------------------------------------- */
9347 	    if (pixregcode == HDFE_CORNER)
9348 	    {
9349 		if (origincode == HDFE_GD_UL)
9350 		{
9351 		    if (xVal[i] - pixCol[i] > 0.5)
9352 		    {
9353 			++pixCol[i];
9354 		    }
9355 
9356 		    if (yVal[i] - pixRow[i] > 0.5)
9357 		    {
9358 			++pixRow[i];
9359 		    }
9360 		}
9361 		else if (origincode == HDFE_GD_UR)
9362 		{
9363 		    if (xVal[i] - pixCol[i] <= 0.5)
9364 		    {
9365 			--pixCol[i];
9366 		    }
9367 
9368 		    if (yVal[i] - pixRow[i] > 0.5)
9369 		    {
9370 			++pixRow[i];
9371 		    }
9372 		}
9373 		else if (origincode == HDFE_GD_LL)
9374 		{
9375 		    if (xVal[i] - pixCol[i] > 0.5)
9376 		    {
9377 			++pixCol[i];
9378 		    }
9379 
9380 		    if (yVal[i] - pixRow[i] <= 0.5)
9381 		    {
9382 			--pixRow[i];
9383 		    }
9384 		}
9385 		else if (origincode == HDFE_GD_LR)
9386 		{
9387 		    if (xVal[i] - pixCol[i] <= 0.5)
9388 		    {
9389 			--pixCol[i];
9390 		    }
9391 
9392 		    if (yVal[i] - pixRow[i] <= 0.5)
9393 		    {
9394 			--pixRow[i];
9395 		    }
9396 		}
9397 	    }
9398 
9399 
9400 	    /* If outside grid boundaries then set to -1 */
9401 	    /* ----------------------------------------- */
9402 	    if (pixCol[i] < 0 || pixCol[i] >= xdimsize ||
9403 		pixRow[i] < 0 || pixRow[i] >= ydimsize)
9404 	    {
9405 		pixCol[i] = -1;
9406 		pixRow[i] = -1;
9407 	    }
9408 	}
9409 	free(xVal);
9410 	free(yVal);
9411     }
9412     return (status);
9413 }
9414 
9415 
9416 
9417 
9418 
9419 /*----------------------------------------------------------------------------|
9420 |  BEGIN_PROLOG                                                               |
9421 |                                                                             |
9422 |  FUNCTION: GDgetpixvalues                                                   |
9423 |                                                                             |
9424 |  DESCRIPTION: Retrieves data from specified pixels.                         |
9425 |                                                                             |
9426 |                                                                             |
9427 |  Return Value    Type     Units     Description                             |
9428 |  ============   ======  =========   =====================================   |
9429 |  size*nPixels   int32               Size of data buffer                     |
9430 |                                                                             |
9431 |  INPUTS:                                                                    |
9432 |  gridID         int32               Grid structure ID                       |
9433 |  nPixels        int32               Number of pixels                        |
9434 |  pixRow         int32               Pixel row numbers                       |
9435 |  pixCol         int32               Pixel column numbers                    |
9436 |  fieldname      char                Fieldname                               |
9437 |                                                                             |
9438 |  OUTPUTS:                                                                   |
9439 |  buffer         void                Data buffer                             |
9440 |                                                                             |
9441 |                                                                             |
9442 |  NOTES:                                                                     |
9443 |                                                                             |
9444 |                                                                             |
9445 |   Date     Programmer   Description                                         |
9446 |  ======   ============  =================================================   |
9447 |  Aug 96   Joel Gales    Original Programmer                                 |
9448 |  Oct 96   Joel Gales    Check for pixels outside boundaries (-1)            |
9449 |  Mar 98   Abe Taaheri   revised to reduce overhead for rechecking           |
9450 |                         for gridid, fieldname, etc in GDreadfield.          |
9451 |  June 98  AT            fixed bug with 2-dim field merged in 3-dim field    |
9452 |                         (for offset and count)                              |
9453 |  END_PROLOG                                                                 |
9454 -----------------------------------------------------------------------------*/
9455 int32
GDgetpixvalues(int32 gridID,int32 nPixels,int32 pixRow[],int32 pixCol[],char * fieldname,VOIDP buffer)9456 GDgetpixvalues(int32 gridID, int32 nPixels, int32 pixRow[], int32 pixCol[],
9457 	       char *fieldname, VOIDP buffer)
9458 {
9459     intn            i;		/* Loop index */
9460     intn            j;		/* Loop index */
9461     intn            status = 0;	/* routine return status variable */
9462 
9463     int32           fid;	/* HDF-EOS file ID */
9464     int32           sdInterfaceID;	/* HDF SDS interface ID */
9465     int32           gdVgrpID;	/* Grid root Vgroup ID */
9466 
9467     int32           start[8];	/* GDreadfield start array */
9468     int32           edge[8];	/* GDreadfield edge array */
9469     int32           dims[8];	/* Field dimensions */
9470     int32           rank;	/* Field rank */
9471     int32           xdum;	/* Location of "XDim" within field list */
9472     int32           ydum;	/* Location of "YDim" within field list */
9473     int32           ntype;	/* Field number type */
9474     int32           origincode;	/* Origin code */
9475     int32           bufOffset;	/* Data buffer offset */
9476     int32           size;	/* Size of returned data buffer for each
9477 				 * value in bytes */
9478     int32           offset[8];	/* I/O offset (start) */
9479     int32           incr[8];	/* I/O increment (stride) */
9480     int32           count[8];	/* I/O count (edge) */
9481     int32           sdid;	/* SDS ID */
9482     int32           rankSDS;	/* Rank of SDS */
9483     int32           rankFld;	/* Rank of field */
9484     int32           dum;	/* Dummy variable */
9485     int32           mrgOffset;	/* Merged field offset */
9486 
9487     char           *dimlist;	/* Dimension list */
9488 
9489 
9490 
9491     /* Allocate space for dimlist */
9492     /* --------------------------------- */
9493     dimlist = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
9494     if(dimlist == NULL)
9495     {
9496 	HEpush(DFE_NOSPACE,"GDgetpixvalues", __FILE__, __LINE__);
9497 	return(-1);
9498     }
9499     /* Check for valid grid ID */
9500     /* ----------------------- */
9501     status = GDchkgdid(gridID, "GDgetpixvalues",
9502 		       &fid, &sdInterfaceID, &gdVgrpID);
9503 
9504 
9505     if (status == 0)
9506     {
9507 	/* Get field list */
9508 	/* -------------- */
9509 	status = GDfieldinfo(gridID, fieldname, &rank, dims, &ntype, dimlist);
9510 
9511 
9512 	/* Check for "XDim" & "YDim" in dimension list */
9513 	/* ------------------------------------------- */
9514 	if (status == 0)
9515 	{
9516 	    xdum = EHstrwithin("XDim", dimlist, ',');
9517 	    ydum = EHstrwithin("YDim", dimlist, ',');
9518 
9519 	    if (xdum == -1)
9520 	    {
9521 		status = -1;
9522 		HEpush(DFE_GENAPP, "GDgetpixvalues", __FILE__, __LINE__);
9523 		HEreport(
9524 		     "\"XDim\" not present in dimlist for field: \"%s\".\n",
9525 			 fieldname);
9526 	    }
9527 
9528 
9529 	    if (ydum == -1)
9530 	    {
9531 		status = -1;
9532 		HEpush(DFE_GENAPP, "GDgetpixvalues", __FILE__, __LINE__);
9533 		HEreport(
9534 		     "\"YDim\" not present in dimlist for field: \"%s\".\n",
9535 			 fieldname);
9536 	    }
9537 	}
9538 	else
9539 	{
9540 	    status = -1;
9541 	    HEpush(DFE_GENAPP, "GDgetpixvalues", __FILE__, __LINE__);
9542 	    HEreport("Fieldname \"%s\" not found.\n", fieldname);
9543 	}
9544 
9545 
9546 	if (status == 0)
9547 	{
9548 
9549 	    /* Get origin order info */
9550 	    /* --------------------- */
9551 	    status = GDorigininfo(gridID, &origincode);
9552 
9553 
9554 	    /* Initialize start & edge arrays */
9555 	    /* ------------------------------ */
9556 	    for (i = 0; i < rank; i++)
9557 	    {
9558 		start[i] = 0;
9559 		edge[i] = dims[i];
9560 	    }
9561 
9562 
9563 	    /* Compute size of data buffer for each pixel */
9564 	    /* ------------------------------------------ */
9565 	    edge[xdum] = 1;
9566 	    edge[ydum] = 1;
9567 	    size = edge[0];
9568 	    for (j = 1; j < rank; j++)
9569 	    {
9570 		size *= edge[j];
9571 	    }
9572 	    size *= DFKNTsize(ntype);
9573 
9574 
9575 
9576 	    /* If data values are requested ... */
9577 	    /* -------------------------------- */
9578 	    if (buffer != NULL)
9579 	    {
9580 		/* get sdid */
9581 		status = GDSDfldsrch(gridID, sdInterfaceID, fieldname, &sdid,
9582 				  &rankSDS, &rankFld, &mrgOffset, dims, &dum);
9583 
9584 		/* Loop through all pixels */
9585 		/* ----------------------- */
9586 		for (i = 0; i < nPixels; i++)
9587 		{
9588 		    /* Conmpute offset within returned data buffer */
9589 		    /* ------------------------------------------- */
9590 		    bufOffset = size * i;
9591 
9592 
9593 		    /* If pixel row & column OK ... */
9594 		    /* ---------------------------- */
9595 		    if (pixCol[i] != -1 && pixRow[i] != -1)
9596 		    {
9597 			start[xdum] = pixCol[i];
9598 			start[ydum] = pixRow[i];
9599 
9600 
9601 			/* Adjust X-dim start if origin on right edge */
9602 			/* ------------------------------------------ */
9603 			if ((origincode & 1) == 1)
9604 			{
9605 			    start[xdum] = dims[xdum] - (start[xdum] + 1);
9606 			}
9607 
9608 
9609 			/* Adjust Y-dim start if origin on lower edge */
9610 			/* ------------------------------------------ */
9611 			if ((origincode & 2) == 2)
9612 			{
9613 			    start[ydum] = dims[ydum] - (start[ydum] + 1);
9614 			}
9615 
9616 			/* Set I/O offset and count Section */
9617 			/* ---------------------- */
9618 
9619 			/*
9620 			 * start and edge != NULL, set I/O offset and count to
9621 			 * user values, adjusting the
9622 			 * 0th field with the merged field offset (if any)
9623 			 */
9624 			if (rankFld == rankSDS)
9625 			{
9626 			    for (j = 0; j < rankSDS; j++)
9627 			    {
9628 				offset[j] = start[j];
9629 				count[j] = edge[j];
9630 			    }
9631 			    offset[0] += mrgOffset;
9632 			}
9633 			else
9634 			{
9635 			    /*
9636 			     * If field really 2-dim merged in 3-dim field then set
9637 			     * 0th field offset to merge offset and then next two to
9638 			     * the user values
9639 			     */
9640 			    for (j = 0; j < rankFld; j++)
9641 			    {
9642 				offset[j + 1] = start[j];
9643 				count[j + 1] = edge[j];
9644 			    }
9645 			    offset[0] = mrgOffset;
9646 			    count[0] = 1;
9647 			}
9648 
9649 
9650 
9651 			/* Set I/O stride Section */
9652 			/* ---------------------- */
9653 
9654 			/* In original code stride enetred as NULL.
9655 			   Abe Taaheri June 12, 1998 */
9656 			/*
9657 			 * If stride == NULL (default) set I/O stride to 1
9658 			 */
9659 			for (j = 0; j < rankSDS; j++)
9660 			{
9661 			    incr[j] = 1;
9662 			}
9663 
9664 
9665 			/* Read into data buffer */
9666 			/* --------------------- */
9667 			status = SDreaddata(sdid,
9668 					    offset, incr, count,
9669 				 (VOIDP) ((uint8 *) buffer + bufOffset));
9670 		    }
9671 		}
9672 	    }
9673 	}
9674     }
9675 
9676 
9677     /* If successful return size of returned data in bytes */
9678     /* --------------------------------------------------- */
9679     if (status == 0)
9680     {
9681 	free(dimlist);
9682 	return (size * nPixels);
9683     }
9684     else
9685     {
9686 	free(dimlist);
9687 	return ((int32) status);
9688     }
9689 }
9690 
9691 
9692 /*----------------------------------------------------------------------------|
9693 |  BEGIN_PROLOG                                                               |
9694 |                                                                             |
9695 |  FUNCTION: GDinterpolate                                                    |
9696 |                                                                             |
9697 |  DESCRIPTION: Performs bilinear interpolate on a set of xy values           |
9698 |                                                                             |
9699 |                                                                             |
9700 |  Return Value    Type     Units     Description                             |
9701 |  ============   ======  =========   =====================================   |
9702 |  nRetn*nValues*  int32               Size of data buffer                    |
9703 |  sizeof(float64)                                                            |
9704 |                                                                             |
9705 |  INPUTS:                                                                    |
9706 |  gridID         int32               Grid structure ID                       |
9707 |  nValues        int32               Number of lon/lat points to interpolate |
9708 |  xyValues       float64             XY values of points to interpolate      |
9709 |  fieldname      char                Fieldname                               |
9710 |                                                                             |
9711 |  OUTPUTS:                                                                   |
9712 |  interpVal      float64             Interpolated Data Values                |
9713 |                                                                             |
9714 |                                                                             |
9715 |  NOTES:                                                                     |
9716 |                                                                             |
9717 |                                                                             |
9718 |   Date     Programmer   Description                                         |
9719 |  ======   ============  =================================================   |
9720 |  Aug 96   Joel Gales    Original Programmer                                 |
9721 |  Oct 96   Joel Gales    Fix array index problem with interpVal write        |
9722 |  Apr 97   Joel Gales    Trap interpolation boundary out of bounds error     |
9723 |  Jun 98   Abe Taaheri   changed the return value so that the Return Value   |
9724 |                         is size in bytes for the data buffer which is       |
9725 |                         float64.
9726 |                                                                             |
9727 |  END_PROLOG                                                                 |
9728 -----------------------------------------------------------------------------*/
9729 int32
GDinterpolate(int32 gridID,int32 nValues,float64 lonVal[],float64 latVal[],char * fieldname,float64 interpVal[])9730 GDinterpolate(int32 gridID, int32 nValues, float64 lonVal[], float64 latVal[],
9731 	      char *fieldname, float64 interpVal[])
9732 {
9733     intn            i;		/* Loop index */
9734     intn            j;		/* Loop index */
9735     intn            k;		/* Loop index */
9736     intn            status = 0;	/* routine return status variable */
9737 
9738     int32           fid;	/* HDF-EOS file ID */
9739     int32           sdInterfaceID;	/* HDF SDS interface ID */
9740     int32           gdVgrpID;	/* Grid root Vgroup ID */
9741     int32           xdimsize;	/* XDim size */
9742     int32           ydimsize;	/* YDim size */
9743     int32           projcode;	/* Projection code */
9744     int32           zonecode;	/* Zone code */
9745     int32           spherecode;	/* Sphere code */
9746     int32           pixregcode;	/* Pixel registration code */
9747     int32           origincode;	/* Origin code */
9748     int32           dims[8];	/* Field dimensions */
9749     int32           numsize;	/* Size in bytes of number type */
9750     int32           rank;	/* Field rank */
9751     int32           xdum;	/* Location of "XDim" within field list */
9752     int32           ydum;	/* Location of "YDim" within field list */
9753     int32           ntype;	/* Number type */
9754     int32           dum;	/* Dummy variable */
9755     int32           size;	/* Size of returned data buffer for each
9756 				 * value in bytes */
9757     int32           pixCol[4];	/* Pixel columns for 4 nearest neighbors */
9758     int32           pixRow[4];	/* Pixel rows for 4 nearest neighbors */
9759     int32           tDen;	/* Interpolation denominator value 1 */
9760     int32           uDen;	/* Interpolation denominator value 2 */
9761     int32           nRetn;	/* Number of data values returned */
9762 
9763     float64         upleftpt[2];/* Upper left pt coordinates */
9764     float64         lowrightpt[2];	/* Lower right pt coordinates */
9765     float64         projparm[16];	/* Projection parameters */
9766     float64         xVal;	/* "Exact" x location of interpolated point */
9767     float64         yVal;	/* "Exact" y location of interpolated point */
9768     float64         tNum = 0.0;	/* Interpolation numerator value 1 */
9769     float64         uNum = 0.0;	/* Interpolation numerator value 2 */
9770 
9771     int16           i16[4];	/* Working buffer (int16) */
9772     int32           i32[4];	/* Working buffer (int132) */
9773     float32         f32[4];	/* Working buffer (float32) */
9774     float64         f64[4];	/* Working buffer (float64) */
9775 
9776     char           *pixVal;	/* Nearest neighbor values */
9777     char           *dimlist;	/* Dimension list */
9778 
9779     /* Allocate space for dimlist */
9780     /* --------------------------------- */
9781     dimlist = (char *) calloc(UTLSTR_MAX_SIZE, sizeof(char));
9782     if(dimlist == NULL)
9783     {
9784 	HEpush(DFE_NOSPACE,"GDinterpolate", __FILE__, __LINE__);
9785 	return(-1);
9786     }
9787     /* Check for valid grid ID */
9788     /* ----------------------- */
9789     status = GDchkgdid(gridID, "GDinterpolate",
9790 		       &fid, &sdInterfaceID, &gdVgrpID);
9791 
9792 
9793     /* If no problems ... */
9794     /* ------------------ */
9795     if (status == 0)
9796     {
9797 	/* Get field information */
9798 	/* --------------------- */
9799 	status = GDfieldinfo(gridID, fieldname, &rank, dims, &ntype, dimlist);
9800 
9801 
9802 	/* Check for "XDim" & "YDim" in dimension list */
9803 	/* ------------------------------------------- */
9804 	if (status == 0)
9805 	{
9806 	    xdum = EHstrwithin("XDim", dimlist, ',');
9807 	    ydum = EHstrwithin("YDim", dimlist, ',');
9808 
9809 	    if (xdum == -1)
9810 	    {
9811 		status = -1;
9812 		HEpush(DFE_GENAPP, "GDinterpolate", __FILE__, __LINE__);
9813 		HEreport(
9814 		     "\"XDim\" not present in dimlist for field: \"%s\".\n",
9815 			 fieldname);
9816 	    }
9817 
9818 
9819 	    if (ydum == -1)
9820 	    {
9821 		status = -1;
9822 		HEpush(DFE_GENAPP, "GDinterpolate", __FILE__, __LINE__);
9823 		HEreport(
9824 		     "\"YDim\" not present in dimlist for field: \"%s\".\n",
9825 			 fieldname);
9826 	    }
9827 	}
9828 	else
9829 	{
9830 	    /* Fieldname not found in grid */
9831 	    /* --------------------------- */
9832 	    status = -1;
9833 	    HEpush(DFE_GENAPP, "GDinterpolate", __FILE__, __LINE__);
9834 	    HEreport("Fieldname \"%s\" not found.\n", fieldname);
9835 	}
9836 
9837 
9838 	/* If no problems ... */
9839 	/* ------------------ */
9840 	if (status == 0)
9841 	{
9842 	    /* Compute size of data buffer for each interpolated value */
9843 	    /* ------------------------------------------------------- */
9844 	    dims[xdum] = 1;
9845 	    dims[ydum] = 1;
9846 	    size = dims[0];
9847 	    for (i = 1; i < rank; i++)
9848 	    {
9849 		size *= dims[i];
9850 	    }
9851 	    numsize = DFKNTsize(ntype);
9852 	    size *= numsize;
9853 
9854 	    nRetn = size / numsize;
9855 
9856 
9857 
9858 	    /* If interpolated values are requested ... */
9859 	    /* ---------------------------------------- */
9860 	    if (interpVal != NULL)
9861 	    {
9862 		/* Get grid info */
9863 		/* ------------- */
9864 		status = GDgridinfo(gridID, &xdimsize, &ydimsize,
9865 				    upleftpt, lowrightpt);
9866 
9867 
9868 		/* Get projection info */
9869 		/* ------------------- */
9870 		status = GDprojinfo(gridID, &projcode, &zonecode,
9871 				    &spherecode, projparm);
9872 
9873 
9874 		/* Get explicit upleftpt & lowrightpt if defaults are used */
9875 		/* ------------------------------------------------------- */
9876 		status = GDgetdefaults(projcode, zonecode, projparm,
9877 				       spherecode, upleftpt, lowrightpt);
9878 
9879 
9880 		/* Get pixel registration and origin info */
9881 		/* -------------------------------------- */
9882 		status = GDpixreginfo(gridID, &pixregcode);
9883 		status = GDorigininfo(gridID, &origincode);
9884 
9885 
9886 
9887 		/* Loop through all interpolated points */
9888 		/* ------------------------------------ */
9889 		for (i = 0; i < nValues; i++)
9890 		{
9891 		    /* Get row & column of point pixel */
9892 		    /* ------------------------------- */
9893 		    status = GDll2ij(projcode, zonecode, projparm, spherecode,
9894 				   xdimsize, ydimsize, upleftpt, lowrightpt,
9895 				     1, &lonVal[i], &latVal[i],
9896 				     pixRow, pixCol, &xVal, &yVal);
9897 
9898 
9899 		    /* Get diff of interp. point from pixel location */
9900 		    /* --------------------------------------------- */
9901 		    if (pixregcode == HDFE_CENTER)
9902 		    {
9903 			tNum = xVal - (pixCol[0] + 0.5);
9904 			uNum = yVal - (pixRow[0] + 0.5);
9905 		    }
9906 		    else if (origincode == HDFE_GD_UL)
9907 		    {
9908 			tNum = xVal - pixCol[0];
9909 			uNum = yVal - pixRow[0];
9910 		    }
9911 		    else if (origincode == HDFE_GD_UR)
9912 		    {
9913 			tNum = xVal - (pixCol[0] + 1);
9914 			uNum = yVal - pixRow[0];
9915 		    }
9916 		    else if (origincode == HDFE_GD_LL)
9917 		    {
9918 			tNum = xVal - pixCol[0];
9919 			uNum = yVal - (pixRow[0] + 1);
9920 		    }
9921 		    else if (origincode == HDFE_GD_LR)
9922 		    {
9923 			tNum = xVal - (pixCol[0] + 1);
9924 			uNum = yVal - (pixRow[0] + 1);
9925 		    }
9926 
9927 
9928 		    /* Get rows and columns of other nearest neighbor pixels */
9929 		    /* ----------------------------------------------------- */
9930 		    pixCol[1] = pixCol[0];
9931 		    pixRow[3] = pixRow[0];
9932 
9933 		    if (tNum >= 0)
9934 		    {
9935 			pixCol[2] = pixCol[0] + 1;
9936 			pixCol[3] = pixCol[0] + 1;
9937 		    }
9938 
9939 		    if (tNum < 0)
9940 		    {
9941 			pixCol[2] = pixCol[0] - 1;
9942 			pixCol[3] = pixCol[0] - 1;
9943 		    }
9944 
9945 		    if (uNum >= 0)
9946 		    {
9947 			pixRow[2] = pixRow[0] + 1;
9948 			pixRow[1] = pixRow[0] + 1;
9949 		    }
9950 
9951 		    if (uNum < 0)
9952 		    {
9953 			pixRow[2] = pixRow[0] - 1;
9954 			pixRow[1] = pixRow[0] - 1;
9955 		    }
9956 
9957 
9958 		    /* Get values of nearest neighbors  */
9959 		    /* -------------------------------- */
9960 		    pixVal = (char *) malloc(4 * size);
9961 		    if(pixVal == NULL)
9962 		    {
9963 			HEpush(DFE_NOSPACE,"GDinterpolate", __FILE__, __LINE__);
9964 			free(dimlist);
9965 			return(-1);
9966 		    }
9967 		    dum = GDgetpixvalues(gridID, 4, pixRow, pixCol,
9968 					 fieldname, pixVal);
9969 
9970 
9971 		    /* Trap interpolation boundary out of range error */
9972 		    /* ---------------------------------------------- */
9973 		    if (dum == -1)
9974 		    {
9975 			status = -1;
9976 			HEpush(DFE_GENAPP, "GDinterpolate", __FILE__, __LINE__);
9977 			HEreport("Interpolation boundary outside of grid.\n");
9978 		    }
9979 		    else
9980 		    {
9981 
9982 			/*
9983 			 * Algorithm taken for Numerical Recipies in C, 2nd
9984 			 * edition, Section 3.6
9985 			 */
9986 
9987 			/* Perform bilinear interpolation */
9988 			/* ------------------------------ */
9989 			tDen = pixCol[3] - pixCol[0];
9990 			uDen = pixRow[1] - pixRow[0];
9991 
9992 			switch (ntype)
9993 			{
9994 			case DFNT_INT16:
9995 
9996 
9997 			    /* Loop through all returned data values */
9998 			    /* ------------------------------------- */
9999 			    for (j = 0; j < nRetn; j++)
10000 			    {
10001 				/* Copy 4 NN values into working array */
10002 				/* ----------------------------------- */
10003 				for (k = 0; k < 4; k++)
10004 				{
10005 				    memcpy(&i16[k],
10006 					   pixVal + j * numsize + k * size,
10007 					   sizeof(int16));
10008 				}
10009 
10010 				/* Compute interpolated value */
10011 				/* -------------------------- */
10012 				interpVal[i * nRetn + j] =
10013 				    (1 - tNum / tDen) * (1 - uNum / uDen) *
10014 				    i16[0] +
10015 				    (tNum / tDen) * (1 - uNum / uDen) *
10016 				    i16[3] +
10017 				    (tNum / tDen) * (uNum / uDen) *
10018 				    i16[2] +
10019 				    (1 - tNum / tDen) * (uNum / uDen) *
10020 				    i16[1];
10021 			    }
10022 			    break;
10023 
10024 
10025 			case DFNT_INT32:
10026 
10027 			    for (j = 0; j < nRetn; j++)
10028 			    {
10029 				for (k = 0; k < 4; k++)
10030 				{
10031 				    memcpy(&i32[k],
10032 					   pixVal + j * numsize + k * size,
10033 					   sizeof(int32));
10034 				}
10035 
10036 				interpVal[i * nRetn + j] =
10037 				    (1 - tNum / tDen) * (1 - uNum / uDen) *
10038 				    i32[0] +
10039 				    (tNum / tDen) * (1 - uNum / uDen) *
10040 				    i32[3] +
10041 				    (tNum / tDen) * (uNum / uDen) *
10042 				    i32[2] +
10043 				    (1 - tNum / tDen) * (uNum / uDen) *
10044 				    i32[1];
10045 			    }
10046 			    break;
10047 
10048 
10049 			case DFNT_FLOAT32:
10050 
10051 			    for (j = 0; j < nRetn; j++)
10052 			    {
10053 				for (k = 0; k < 4; k++)
10054 				{
10055 				    memcpy(&f32[k],
10056 					   pixVal + j * numsize + k * size,
10057 					   sizeof(float32));
10058 				}
10059 
10060 				interpVal[i * nRetn + j] =
10061 				    (1 - tNum / tDen) * (1 - uNum / uDen) *
10062 				    f32[0] +
10063 				    (tNum / tDen) * (1 - uNum / uDen) *
10064 				    f32[3] +
10065 				    (tNum / tDen) * (uNum / uDen) *
10066 				    f32[2] +
10067 				    (1 - tNum / tDen) * (uNum / uDen) *
10068 				    f32[1];
10069 			    }
10070 			    break;
10071 
10072 
10073 			case DFNT_FLOAT64:
10074 
10075 			    for (j = 0; j < nRetn; j++)
10076 			    {
10077 				for (k = 0; k < 4; k++)
10078 				{
10079 				    memcpy(&f64[k],
10080 					   pixVal + j * numsize + k * size,
10081 					   sizeof(float64));
10082 				}
10083 
10084 				interpVal[i * nRetn + j] =
10085 				    (1 - tNum / tDen) * (1 - uNum / uDen) *
10086 				    f64[0] +
10087 				    (tNum / tDen) * (1 - uNum / uDen) *
10088 				    f64[3] +
10089 				    (tNum / tDen) * (uNum / uDen) *
10090 				    f64[2] +
10091 				    (1 - tNum / tDen) * (uNum / uDen) *
10092 				    f64[1];
10093 			    }
10094 			    break;
10095 			}
10096 		    }
10097 		    free(pixVal);
10098 		}
10099 	    }
10100 	}
10101     }
10102 
10103 
10104     /* If successful return size of returned data in bytes */
10105     /* --------------------------------------------------- */
10106     if (status == 0)
10107     {
10108 	/*always return size of float64 buffer */
10109 	free(dimlist);
10110 	return (nRetn  * nValues * sizeof(float64));
10111     }
10112     else
10113     {
10114 	free(dimlist);
10115 	return ((int32) status);
10116     }
10117 
10118 }
10119 /***********************************************
10120 GDwrrdtile --
10121      This function is the underlying function below GDwritetile and
10122      GDreadtile.
10123 
10124 
10125 Author--
10126 Alexis Zubrow
10127 
10128 ********************************************************/
10129 
10130 static intn
GDwrrdtile(int32 gridID,char * fieldname,char * code,int32 start[],VOIDP datbuf)10131 GDwrrdtile(int32 gridID, char *fieldname, char *code, int32 start[],
10132 	   VOIDP datbuf)
10133 {
10134     intn            i;		/* Loop index */
10135     intn            status = 0;	/* routine return status variable */
10136 
10137     int32           fid;	/* HDF-EOS file ID */
10138     int32           sdInterfaceID;	/* HDF SDS interface ID */
10139     int32           sdid;	/* SDS ID */
10140 
10141     int32           dum;	/* Dummy variable */
10142     int32           rankSDS;	/* Rank of SDS/Field */
10143 
10144     int32           dims[8];	/* Field/SDS dimensions */
10145     int32           tileFlags;	/* flag to determine if field is tiled */
10146     int32           numTileDims;/* number of tiles spanning a dimension */
10147     HDF_CHUNK_DEF   tileDef;	/* union holding tiling info. */
10148 
10149 
10150     /* Get gridID */
10151     status = GDchkgdid(gridID, "GDwrrdtile", &fid, &sdInterfaceID, &dum);
10152     if (status == 0)
10153     {
10154 
10155 	/* Get field info */
10156 	status = GDfieldinfo(gridID, fieldname, &rankSDS, dims, &dum, NULL);
10157 
10158 	if (status == 0)
10159 	{
10160 
10161 	    /* Check whether fieldname is in SDS (multi-dim field) */
10162 	    /* --------------------------------------------------- */
10163 	    status = GDSDfldsrch(gridID, sdInterfaceID, fieldname, &sdid,
10164 				 &rankSDS, &dum, &dum, dims, &dum);
10165 
10166 
10167 
10168 	    /*
10169 	     * Check for errors in parameters passed to GDwritetile or
10170 	     * GDreadtile
10171 	     */
10172 
10173 	    /* Check if untiled field */
10174 	    status = SDgetchunkinfo(sdid, &tileDef, &tileFlags);
10175 	    if (tileFlags == HDF_NONE)
10176 	    {
10177 		HEpush(DFE_GENAPP, "GDwrrdtile", __FILE__, __LINE__);
10178 		HEreport("Field \"%s\" is not tiled.\n", fieldname);
10179 		status = -1;
10180 		return (status);
10181 
10182 	    }
10183 
10184 	    /*
10185 	     * Check if rd/wr tilecoords are within the extent of the field
10186 	     */
10187 	    for (i = 0; i < rankSDS; i++)
10188 	    {
10189 		/*
10190 		 * Calculate the number of tiles which span a dimension of
10191 		 * the field
10192 		 */
10193 		numTileDims = dims[i] / tileDef.chunk_lengths[i];
10194 		if ((start[i] >= numTileDims) || (start[i] < 0))
10195 		{
10196 		    /*
10197 		     * ERROR INDICATING BEYOND EXTENT OF THAT DIMENSION OR
10198 		     * NEGATIVE TILECOORDS
10199 		     */
10200 		    HEpush(DFE_GENAPP, "GDwrrdtile", __FILE__, __LINE__);
10201 		    HEreport("Tilecoords for dimension \"%d\" ...\n", i);
10202 		    HEreport("is beyond the extent of dimension length\n");
10203 		    status = -1;
10204 
10205 		}
10206 	    }
10207 
10208 	    if (status == -1)
10209 	    {
10210 		return (status);
10211 	    }
10212 
10213 
10214 	    /* Actually write/read to the field */
10215 
10216 	    if (strcmp(code, "w") == 0)	/* write tile */
10217 	    {
10218 		status = SDwritechunk(sdid, start, (VOIDP) datbuf);
10219 	    }
10220 	    else if (strcmp(code, "r") == 0)	/* read tile */
10221 	    {
10222 		status = SDreadchunk(sdid, start, (VOIDP) datbuf);
10223 	    }
10224 
10225 
10226 	}
10227 
10228 	/* Non-existent fieldname */
10229 	else
10230 	{
10231 	    HEpush(DFE_GENAPP, "GDwrrdtile", __FILE__, __LINE__);
10232 	    HEreport("Fieldname \"%s\" does not exist.\n", fieldname);
10233 	    status = -1;
10234 	}
10235 
10236     }
10237 
10238     return (status);
10239 }
10240 
10241 
10242 /***********************************************
10243 GDtileinfo --
10244      This function queries the field to determine if it is tiled.  If it is
10245      tile, one can retrieve some of the characteristics of the tiles.
10246 
10247 Author--  Alexis Zubrow
10248 
10249 ********************************************************/
10250 
10251 
10252 intn
GDtileinfo(int32 gridID,char * fieldname,int32 * tilecode,int32 * tilerank,int32 tiledims[])10253 GDtileinfo(int32 gridID, char *fieldname, int32 * tilecode, int32 * tilerank,
10254 	   int32 tiledims[])
10255 
10256 {
10257     intn            i;		/* Loop index */
10258     intn            status = 0;	/* routine return status variable */
10259 
10260     int32           fid;	/* HDF-EOS file ID */
10261     int32           sdInterfaceID;	/* HDF SDS interface ID */
10262     int32           sdid;	/* SDS ID */
10263 
10264     int32           dum;	/* Dummy variable */
10265     int32           rankSDS;	/* Rank of SDS/Field/tile */
10266 
10267     int32           dims[8];	/* Field/SDS dimensions */
10268     int32           tileFlags;	/* flag to determine if field is tiled */
10269     HDF_CHUNK_DEF   tileDef;	/* union holding tiling info. */
10270 
10271 
10272     /* Check if improper gridID */
10273     status = GDchkgdid(gridID, "GDtileinfo", &fid, &sdInterfaceID, &dum);
10274     if (status == 0)
10275     {
10276 
10277 	/* Get field info */
10278 	status = GDfieldinfo(gridID, fieldname, &rankSDS, dims, &dum, NULL);
10279 
10280 	if (status == 0)
10281 	{
10282 
10283 	    /* Check whether fieldname is in SDS (multi-dim field) */
10284 	    /* --------------------------------------------------- */
10285 	    status = GDSDfldsrch(gridID, sdInterfaceID, fieldname, &sdid,
10286 				 &rankSDS, &dum, &dum, dims, &dum);
10287 
10288 
10289 
10290 	    /* Query field for tiling information */
10291 	    status = SDgetchunkinfo(sdid, &tileDef, &tileFlags);
10292 
10293 	    /* If field is untiled, return untiled flag */
10294 	    if (tileFlags == HDF_NONE)
10295 	    {
10296 		*tilecode = HDFE_NOTILE;
10297 		return (status);
10298 	    }
10299 
10300 	    /* IF field is tiled or tiled with compression */
10301 	    else if ((tileFlags == HDF_CHUNK) ||
10302 		     (tileFlags == (HDF_CHUNK | HDF_COMP)))
10303 	    {
10304 		if (tilecode != NULL)
10305 		{
10306 		    *tilecode = HDFE_TILE;
10307 		}
10308 		if (tilerank != NULL)
10309 		{
10310 		    *tilerank = rankSDS;
10311 		}
10312 		if (tiledims != NULL)
10313 		{
10314 		    /* Assign size of tile dimensions */
10315 		    for (i = 0; i < rankSDS; i++)
10316 		    {
10317 			tiledims[i] = tileDef.chunk_lengths[i];
10318 		    }
10319 		}
10320 	    }
10321 	}
10322 
10323 	/* Non-existent fieldname */
10324 	else
10325 	{
10326 	    HEpush(DFE_GENAPP, "GDtileinfo", __FILE__, __LINE__);
10327 	    HEreport("Fieldname \"%s\" does not exist.\n", fieldname);
10328 	    status = -1;
10329 	}
10330 
10331     }
10332     return (status);
10333 }
10334 /***********************************************
10335 GDwritetile --
10336      This function writes one tile to a particular field.
10337 
10338 
10339 Author--
10340 Alexis Zubrow
10341 
10342 ********************************************************/
10343 
10344 intn
GDwritetile(int32 gridID,char * fieldname,int32 tilecoords[],VOIDP tileData)10345 GDwritetile(int32 gridID, char *fieldname, int32 tilecoords[],
10346 	    VOIDP tileData)
10347 {
10348     char            code[] = "w";	/* write tile code */
10349     intn            status = 0;	/* routine return status variable */
10350 
10351     status = GDwrrdtile(gridID, fieldname, code, tilecoords, tileData);
10352 
10353     return (status);
10354 }
10355 /***********************************************
10356 GDreadtile --
10357      This function reads one tile from a particular field.
10358 
10359 
10360 Author--
10361 Alexis Zubrow
10362 
10363 ********************************************************/
10364 
10365 intn
GDreadtile(int32 gridID,char * fieldname,int32 tilecoords[],VOIDP tileData)10366 GDreadtile(int32 gridID, char *fieldname, int32 tilecoords[],
10367 	   VOIDP tileData)
10368 {
10369     char            code[] = "r";	/* read tile code */
10370     intn            status = 0;	/* routine return status variable */
10371 
10372     status = GDwrrdtile(gridID, fieldname, code, tilecoords, tileData);
10373 
10374     return (status);
10375 }
10376 /***********************************************
10377 GDsettilecache --
10378      This function sets the cache size for a tiled field.
10379 
10380 
10381 Author--
10382 Alexis Zubrow
10383 
10384 ********************************************************/
10385 
10386 intn
GDsettilecache(int32 gridID,char * fieldname,int32 maxcache,int32 cachecode)10387 GDsettilecache(int32 gridID, char *fieldname, int32 maxcache, int32 cachecode)
10388 {
10389 
10390     intn            status = 0;	/* routine return status variable */
10391 
10392     int32           fid;	/* HDF-EOS file ID */
10393     int32           sdInterfaceID;	/* HDF SDS interface ID */
10394     int32           sdid;	/* SDS ID */
10395 
10396     int32           dum;	/* Dummy variable */
10397 
10398     int32           dims[8];	/* Field/SDS dimensions */
10399 
10400 
10401     /* Check gridID */
10402     status = GDchkgdid(gridID, "GDwrrdtile", &fid, &sdInterfaceID, &dum);
10403     if (status == 0)
10404     {
10405 
10406 	/* Get field info */
10407 	status = GDfieldinfo(gridID, fieldname, &dum, dims, &dum, NULL);
10408 
10409 	if (status == 0)
10410 	{
10411 
10412 	    /* Check whether fieldname is in SDS (multi-dim field) */
10413 	    /* --------------------------------------------------- */
10414 	    status = GDSDfldsrch(gridID, sdInterfaceID, fieldname, &sdid,
10415 				 &dum, &dum, &dum, dims, &dum);
10416 
10417 
10418 	    /* Check if maxcache is less than or equal to zero */
10419 	    if (maxcache <= 0)
10420 	    {
10421 		HEpush(DFE_GENAPP, "GDsettilecache", __FILE__, __LINE__);
10422 		HEreport("Improper maxcache \"%d\"... \n", maxcache);
10423 		HEreport("maxcache must be greater than zero.\n");
10424 		status = -1;
10425 		return (status);
10426 	    }
10427 
10428 
10429 	    /* Set the number of tiles to cache */
10430 	    /* Presently, the only cache flag allowed is 0 */
10431 	    status = SDsetchunkcache(sdid, maxcache, 0);
10432 
10433 
10434 	}
10435 
10436 	/* Non-existent fieldname */
10437 	else
10438 	{
10439 	    HEpush(DFE_GENAPP, "GDwrrdtile", __FILE__, __LINE__);
10440 	    HEreport("Fieldname \"%s\" does not exist.\n", fieldname);
10441 	    status = -1;
10442 	}
10443 
10444     }
10445 
10446     return (status);
10447 }
10448 
10449 /*----------------------------------------------------------------------------|
10450 |  BEGIN_PROLOG                                                               |
10451 |                                                                             |
10452 |  FUNCTION: GDsettilecomp                                                    |
10453 |                                                                             |
10454 |  DESCRIPTION: Sets the tiling/compression parameters for the   specified    |
10455 |               field. This can be called after GDsetfillvalue and assumes    |
10456 |               that the field was defined with no compression/tiling  set    |
10457 |               by GDdeftile or GDdefcomp.                                    |
10458 |                                                                             |
10459 |               This function replaces the following sequence:                |
10460 |                  GDdefcomp                                                  |
10461 |                  GDdeftile                                                  |
10462 |                  GDdeffield                                                 |
10463 |                  GDsetfillvalue                                             |
10464 |               with:                                                         |
10465 |                  GDdeffield                                                 |
10466 |                  GDsetfillvalue                                             |
10467 |                  GDsettilecomp                                              |
10468 |               so that fill values will work correctly.                      |
10469 |                                                                             |
10470 |  Return Value    Type     Units     Description                             |
10471 |  ============   ======  =========   =====================================   |
10472 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
10473 |                                                                             |
10474 |  INPUTS:                                                                    |
10475 |  gridID         int32               grid structure ID                       |
10476 |  fieldname      char                field name                              |
10477 |  tilerank       int32               number of tiling dimensions             |
10478 |  tiledims       int32               tiling dimensions                       |
10479 |  compcode       int32               compression code                        |
10480 |  compparm       intn                compression parameters                  |
10481 |                                                                             |
10482 |  OUTPUTS:                                                                   |
10483 |             None                                                            |
10484 |                                                                             |
10485 |  NOTES:                                                                     |
10486 |                                                                             |
10487 |                                                                             |
10488 |   Date     Programmer   Description                                         |
10489 |  ======   ============  =================================================   |
10490 |  Jun 98   MISR          Used GDsetfillvalue as a template and copied        |
10491 |                         tiling/comp portions of GDdeffield.(NCR15866).      |
10492 |                                                                             |
10493 |  END_PROLOG                                                                 |
10494 -----------------------------------------------------------------------------*/
10495 intn
GDsettilecomp(int32 gridID,char * fieldname,int32 tilerank,int32 * tiledims,int32 compcode,intn * compparm)10496 GDsettilecomp(int32 gridID, char *fieldname, int32 tilerank, int32*
10497                tiledims, int32 compcode, intn* compparm)
10498 {
10499     intn            status;     /* routine return status variable */
10500 
10501     int32           fid;        /* HDF-EOS file ID */
10502     int32           sdInterfaceID;      /* HDF SDS interface ID */
10503     int32           gdVgrpID;   /* Grid root Vgroup ID */
10504     int             i;          /* Looping variable. */
10505     int32           sdid;       /* SDS id */
10506     int32           nt;         /* Number type */
10507     int32           dims[8];    /* Dimensions array */
10508     int32           dum;        /* Dummy variable */
10509     int32           solo;       /* "Solo" (non-merged) field flag */
10510     comp_info       c_info;     /* Compression parameter structure */
10511     HDF_CHUNK_DEF   chunkDef;   /* Tiling structure */
10512     int32           chunkFlag;  /* Chunking (Tiling) flag */
10513 
10514     /* Check for valid grid ID and get SDS interface ID */
10515     status = GDchkgdid(gridID, "GDsetfillvalue",
10516                        &fid, &sdInterfaceID, &gdVgrpID);
10517 
10518     if (status == 0)
10519     {
10520         /* Get field info */
10521         status = GDfieldinfo(gridID, fieldname, &dum, dims, &nt, NULL);
10522 
10523         if (status == 0)
10524         {
10525             /* Get SDS ID and solo flag */
10526             status = GDSDfldsrch(gridID, sdInterfaceID, fieldname,
10527                                  &sdid, &dum, &dum, &dum,
10528                                  dims, &solo);
10529             if (status !=0) {
10530               HEpush(DFE_GENAPP, "GDsettilecomp", __FILE__, __LINE__);
10531               HEreport("GDSDfldsrch failed\n", fieldname);
10532               return FAIL;
10533             }
10534             /* Tiling with Compression */
10535             /* ----------------------- */
10536 
10537 
10538             /* Setup Compression */
10539             /* ----------------- */
10540             if (compcode == HDFE_COMP_NBIT)
10541               {
10542                 c_info.nbit.nt = nt;
10543                 c_info.nbit.sign_ext = compparm[0];
10544                 c_info.nbit.fill_one = compparm[1];
10545                 c_info.nbit.start_bit = compparm[2];
10546                 c_info.nbit.bit_len = compparm[3];
10547               }
10548             else if (compcode == HDFE_COMP_SKPHUFF)
10549               {
10550                 c_info.skphuff.skp_size = (intn) DFKNTsize(nt);
10551               }
10552             else if (compcode == HDFE_COMP_DEFLATE)
10553               {
10554                 c_info.deflate.level = compparm[0];
10555               }
10556 
10557             /* Setup chunk lengths */
10558             /* ------------------- */
10559             for (i = 0; i < tilerank; i++)
10560               {
10561                 chunkDef.comp.chunk_lengths[i] = tiledims[i];
10562               }
10563 
10564             /* Setup chunk flag & chunk compression type */
10565             /* ----------------------------------------- */
10566             chunkFlag = HDF_CHUNK | HDF_COMP;
10567             chunkDef.comp.comp_type = compcode;
10568 
10569             /* Setup chunk compression parameters */
10570             /* ---------------------------------- */
10571             if (compcode == HDFE_COMP_SKPHUFF)
10572               {
10573                 chunkDef.comp.cinfo.skphuff.skp_size =
10574                   c_info.skphuff.skp_size;
10575               }
10576             else if (compcode == HDFE_COMP_DEFLATE)
10577               {
10578                 chunkDef.comp.cinfo.deflate.level =
10579                   c_info.deflate.level;
10580               }
10581             /* Call SDsetchunk routine */
10582             /* ----------------------- */
10583             status = SDsetchunk(sdid, chunkDef, chunkFlag);
10584             if (status ==FAIL) {
10585               HEpush(DFE_GENAPP, "GDsettilecomp", __FILE__, __LINE__);
10586               HEreport("Fieldname \"%s\" does not exist.\n",
10587                        fieldname);
10588               return status;
10589             }
10590         }
10591         else
10592         {
10593             HEpush(DFE_GENAPP, "GDsettilecomp", __FILE__, __LINE__);
10594             HEreport("Fieldname \"%s\" does not exist.\n", fieldname);
10595         }
10596     }
10597     return (status);
10598 }
10599 
10600 /*----------------------------------------------------------------------------|
10601 |  BEGIN_PROLOG                                                               |
10602 |                                                                             |
10603 |  FUNCTION: GDll2mm_cea                                                      |
10604 |                                                                             |
10605 |  DESCRIPTION:                                                               |
10606 |                                                                             |
10607 |                                                                             |
10608 |  Return Value    Type     Units     Description                             |
10609 |  ============   ======  =========   =====================================   |
10610 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
10611 |                                                                             |
10612 |  INPUTS:                                                                    |
10613 |  projcode       int32               GCTP projection code                    |
10614 |  zonecode       int32               UTM zone code                           |
10615 |  projparm       float64             Projection parameters                   |
10616 |  spherecode     int32               GCTP spheriod code                      |
10617 |  xdimsize       int32               xdimsize from GDcreate                  |
10618 |  ydimsize       int32               ydimsize from GDcreate                  |
10619 |  upleftpt       float64             upper left corner coordinates  (DMS)    |
10620 |  lowrightpt     float64             lower right corner coordinates (DMS)    |
10621 |  longitude      float64             longitude array (DMS)                   |
10622 |  latitude       float64             latitude array (DMS)                    |
10623 |  npnts          int32               number of lon-lat points                |
10624 |                                                                             |
10625 |  OUTPUTS:                                                                   |
10626 |  x              float64             X value array                           |
10627 |  y              float64             Y value array                           |
10628 |  scaleX	  float64             X grid size                             |
10629 |  scaley         float64             Y grid size                             |
10630 |                                                                             |
10631 |  NOTES:                                                                     |
10632 |                                                                             |
10633 |                                                                             |
10634 |   Date     Programmer   Description                                         |
10635 |  ======   ============  =================================================   |
10636 |  Oct 02   Abe Taaheri   Added support for EASE grid                         |
10637 |                                                                             |
10638 |  END_PROLOG                                                                 |
10639 -----------------------------------------------------------------------------*/
GDll2mm_cea(int32 projcode,int32 zonecode,int32 spherecode,float64 projparm[],int32 xdimsize,int32 ydimsize,float64 upleftpt[],float64 lowrightpt[],int32 npnts,float64 lon[],float64 lat[],float64 x[],float64 y[],float64 * scaleX,float64 * scaleY)10640 static intn GDll2mm_cea(int32 projcode,int32 zonecode, int32 spherecode,
10641 		 float64 projparm[],
10642 		 int32 xdimsize, int32 ydimsize,
10643 		 float64 upleftpt[], float64 lowrightpt[], int32 npnts,
10644 		 float64 lon[],float64 lat[],
10645 		 float64 x[],float64 y[], float64 *scaleX,float64 *scaleY)
10646 {
10647     intn            status = 0;	/* routine return status variable */
10648     int32           errorcode = 0;	/* GCTP error code */
10649     float64         xMtr0, xMtr1, yMtr0, yMtr1;
10650     float64         lonrad0;	/* Longitude in radians of upleft point */
10651     float64         latrad0;     /* Latitude in radians of upleft point */
10652     float64         lonrad;	/* Longitude in radians of point */
10653     float64         latrad;	/* Latitude in radians of point */
10654     int32(*for_trans[100]) ();	/* GCTP function pointer */
10655 
10656     if(npnts <= 0)
10657       {
10658 	HEpush(DFE_GENAPP, " GDll2mm_cea", __FILE__, __LINE__);
10659 	HEreport("Improper npnts value\"%d\"... \n", npnts);
10660 	HEreport("npnts must be greater than zero.\n");
10661 	status = -1;
10662 	return (status);
10663       }
10664     if ( projcode == GCTP_BCEA)
10665       {
10666 	for_init(projcode, zonecode, projparm, spherecode, NULL, NULL,
10667 		 &errorcode, for_trans);
10668 	/* Convert upleft and lowright X coords from DMS to radians */
10669 	/* -------------------------------------------------------- */
10670 
10671 	lonrad0 = EHconvAng(upleftpt[0], HDFE_DMS_RAD);
10672 	lonrad = EHconvAng(lowrightpt[0], HDFE_DMS_RAD);
10673 
10674 	/* Convert upleft and lowright Y coords from DMS to radians */
10675 	/* -------------------------------------------------------- */
10676 	latrad0 = EHconvAng(upleftpt[1], HDFE_DMS_RAD);
10677 	latrad = EHconvAng(lowrightpt[1], HDFE_DMS_RAD);
10678 
10679 	/* Convert from lon/lat to meters(or whatever unit is, i.e unit
10680 	   of r_major and r_minor) using GCTP */
10681 	/* ----------------------------------------- */
10682 	errorcode = for_trans[projcode] (lonrad0, latrad0, &xMtr0, &yMtr0);
10683 	x[0] = xMtr0;
10684 	y[0] = yMtr0;
10685 
10686 	/* Report error if any */
10687 	/* ------------------- */
10688 	if (errorcode != 0)
10689 	  {
10690 	    status = -1;
10691 	    HEpush(DFE_GENAPP, "GDll2mm_cea", __FILE__, __LINE__);
10692 	    HEreport("GCTP Error: %d\n", errorcode);
10693 	    return (status);
10694 	  }
10695 
10696 	/* Convert from lon/lat to meters(or whatever unit is, i.e unit
10697 	   of r_major and r_minor) using GCTP */
10698 	/* ----------------------------------------- */
10699 	errorcode = for_trans[projcode] (lonrad, latrad, &xMtr1, &yMtr1);
10700 	x[1] = xMtr1;
10701 	y[1] = yMtr1;
10702 
10703 	/* Report error if any */
10704 	/* ------------------- */
10705 	if (errorcode != 0)
10706 	  {
10707 	    status = -1;
10708 	    HEpush(DFE_GENAPP, "GDll2mm_cea", __FILE__, __LINE__);
10709 	    HEreport("GCTP Error: %d\n", errorcode);
10710 	    return (status);
10711 	  }
10712 
10713 	/* Compute x scale factor */
10714 	/* ---------------------- */
10715 	*scaleX = (xMtr1 - xMtr0) / xdimsize;
10716 
10717 	/* Compute y scale factor */
10718 	/* ---------------------- */
10719 	*scaleY = (yMtr1 - yMtr0) / ydimsize;
10720       }
10721     else
10722       {
10723         status = -1;
10724         HEpush(DFE_GENAPP, "GDll2mm_cea", __FILE__, __LINE__);
10725         HEreport("Wrong projection code; this function is only for EASE grid");
10726         return (status);
10727       }
10728     return (0);
10729 }
10730 
10731 
10732 /*----------------------------------------------------------------------------|
10733 |  BEGIN_PROLOG                                                               |
10734 |                                                                             |
10735 |  FUNCTION: GDmm2ll_cea                                                      |
10736 |                                                                             |
10737 |  DESCRIPTION:                                                               |
10738 |                                                                             |
10739 |                                                                             |
10740 |  Return Value    Type     Units     Description                             |
10741 |  ============   ======  =========   =====================================   |
10742 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
10743 |                                                                             |
10744 |  INPUTS:                                                                    |
10745 |  projcode       int32               GCTP projection code                    |
10746 |  zonecode       int32               UTM zone code                           |
10747 |  projparm       float64             Projection parameters                   |
10748 |  spherecode     int32               GCTP spheriod code                      |
10749 |  xdimsize       int32               xdimsize from GDcreate                  |
10750 |  ydimsize       int32               ydimsize from GDcreate                  |
10751 |  upleftpt       float64             upper left corner coordinates (DMS)     |
10752 |  lowrightpt     float64             lower right corner coordinates (DMS)    |
10753 |  x              float64             X value array                           |
10754 |  y              float64             Y value array                           |
10755 |  npnts          int32               number of x-y points                    |
10756 |                                                                             |
10757 |  OUTPUTS:                                                                   |
10758 |  longitude      float64             longitude array (DMS)                   |
10759 |  latitude       float64             latitude array (DMS)                    |
10760 |                                                                             |
10761 |  NOTES:                                                                     |
10762 |                                                                             |
10763 |                                                                             |
10764 |   Date     Programmer   Description                                         |
10765 |  ======   ============  =================================================   |
10766 |  Oct 02   Abe Taaheri   Added support for EASE grid                         |
10767 |                                                                             |
10768 |  END_PROLOG                                                                 |
10769 -----------------------------------------------------------------------------*/
GDmm2ll_cea(int32 projcode,int32 zonecode,int32 spherecode,float64 projparm[],int32 xdimsize,int32 ydimsize,float64 upleftpt[],float64 lowrightpt[],int32 npnts,float64 x[],float64 y[],float64 longitude[],float64 latitude[])10770 static intn GDmm2ll_cea(int32 projcode,int32 zonecode, int32 spherecode,
10771 		 float64 projparm[],
10772 		 int32 xdimsize, int32 ydimsize,
10773 		 float64 upleftpt[], float64 lowrightpt[], int32 npnts,
10774 		 float64 x[], float64 y[],
10775 		 float64 longitude[], float64 latitude[])
10776 {
10777     intn            status = 0;	/* routine return status variable */
10778     int32           errorcode = 0;	/* GCTP error code */
10779     int32(*inv_trans[100]) ();	/* GCTP function pointer */
10780     int32 i;
10781 
10782     if(npnts <= 0)
10783       {
10784 	HEpush(DFE_GENAPP, " GDmm2ll_cea", __FILE__, __LINE__);
10785 	HEreport("Improper npnts value\"%d\"... \n", npnts);
10786 	HEreport("npnts must be greater than zero.\n");
10787 	status = -1;
10788 	return (status);
10789       }
10790     if ( projcode == GCTP_BCEA)
10791       {
10792 	inv_init(projcode, zonecode, projparm, spherecode, NULL, NULL,
10793 		 &errorcode, inv_trans);
10794 
10795 	/* Convert from meters(or whatever unit is, i.e unit
10796 	   of r_major and r_minor) to lat/lon using GCTP */
10797 	/* ----------------------------------------- */
10798 	for(i=0; i<npnts; i++)
10799 	  {
10800 	    errorcode =
10801 	      inv_trans[projcode] (x[i], y[i],&longitude[i], &latitude[i]);
10802 	    /* Report error if any */
10803 	    /* ------------------- */
10804 	    if (errorcode != 0)
10805 	      {
10806 		status = -1;
10807 		HEpush(DFE_GENAPP, "GDmm2ll_cea", __FILE__, __LINE__);
10808 		HEreport("GCTP Error: %d\n", errorcode);
10809 		return (status);
10810 	      }
10811 	    longitude[i] = EHconvAng(longitude[i], HDFE_RAD_DMS);
10812 	    latitude[i] = EHconvAng(latitude[i], HDFE_RAD_DMS);
10813 	  }
10814       }
10815     else
10816       {
10817 	/* Wrong projection code; this function is only for EASE grid */
10818       }
10819     return(status);
10820 }
10821 
10822 /*----------------------------------------------------------------------------|
10823 |  BEGIN_PROLOG                                                               |
10824 |                                                                             |
10825 |  FUNCTION: GDsdid                                                           |
10826 |                                                                             |
10827 |  DESCRIPTION: Returns SD element ID for grid field                          |
10828 |                                                                             |
10829 |                                                                             |
10830 |  Return Value    Type     Units     Description                             |
10831 |  ============   ======  =========   =====================================   |
10832 |  status         intn                return status (0) SUCCEED, (-1) FAIL    |
10833 |                                                                             |
10834 |  INPUTS:                                                                    |
10835 |  gridID         int32               grid structure ID                       |
10836 |  fieldname      const char          field name                              |
10837 |                                                                             |
10838 |                                                                             |
10839 |  OUTPUTS:                                                                   |
10840 |  sdid           int32               SD element ID                           |
10841 |                                                                             |
10842 |  NOTES:                                                                     |
10843 |                                                                             |
10844 |                                                                             |
10845 |   Date     Programmer   Description                                         |
10846 |  ======   ============  =================================================   |
10847 |  Oct 07   Andrey Kiselev  Original Programmer                               |
10848 |                                                                             |
10849 |  END_PROLOG                                                                 |
10850 -----------------------------------------------------------------------------*/
10851 intn
GDsdid(int32 gridID,const char * fieldname,int32 * sdid)10852 GDsdid(int32 gridID, const char *fieldname, int32 *sdid)
10853 {
10854     intn            status;	        /* routine return status variable */
10855     int32           fid;	        /* HDF-EOS file ID */
10856     int32           sdInterfaceID;      /* HDF SDS interface ID */
10857     int32           dum;	        /* Dummy variable */
10858     int32           dims[H4_MAX_VAR_DIMS]; /* Field/SDS dimensions */
10859 
10860     status = GDchkgdid(gridID, "GDsdid", &fid, &sdInterfaceID, &dum);
10861     if (status != -1)
10862     {
10863         status = GDSDfldsrch(gridID, sdInterfaceID, fieldname,
10864                              sdid, &dum, &dum, &dum, dims, &dum);
10865     }
10866 
10867     return (status);
10868 }
10869 
10870