1 /***********************************************************************/
2 /* Open Visualization Data Explorer                                    */
3 /* (C) Copyright IBM Corp. 1989,1999                                   */
4 /* ALL RIGHTS RESERVED                                                 */
5 /* This code licensed under the                                        */
6 /*    "IBM PUBLIC LICENSE - Open Visualization Data Explorer"          */
7 /***********************************************************************/
8 /*
9  * $Header: /src/master/dx/src/exec/dxmods/genimp.c,v 1.5 2000/08/24 20:08:37 davidt Exp $
10  */
11 
12 #include <dxconfig.h>
13 
14 
15 #include <string.h>
16 #include  "genimp.h"
17 
18 
19 /* GLOBAL variables : Do not depend on these initializations!! */
20 char	*_dxd_gi_filename=NULL;	/* input data file name (w/wo full paths) */
21 int	_dxd_gi_numdims=0;		/* dimensionality 			  */
22 int	_dxd_gi_dimsize[MAX_POS_DIMS]={0};/* dimension sizes			  */
23 int	_dxd_gi_series=0;		/* total number of records (time steps)	  */
24 int	_dxd_gi_numflds=0;		/* total number of fields 		  */
25 int	_dxd_gi_format=0;		/* either ASCII or BINARY 		  */
26 int	_dxd_gi_asciiformat=0;      /* either FREE or FIX for ascii file format */
27 int	_dxd_gi_majority=0;		/* either ROW or COL 			  */
28 interleave_type _dxd_gi_interleaving=DEFAULT_INTERLEAVE;
29 position_type _dxd_gi_positions=DEFAULT_PRODUCT;
30 float	*_dxd_gi_dataloc=NULL;      	/* Position locations            	  */
31 struct  variable **_dxd_gi_var={0};	/* pointers to variables 		  */
32 struct infoplace **_dxd_gi_fromfile = {0};	/* pointers to placeoffsets of grid	  */
33 int     *_dxd_gi_whichser=NULL;         /* Series numbers to be imported          */
34 int     *_dxd_gi_whichflds=NULL;	/* Field numbers to be imported           */
35 float   *_dxd_gi_seriesvalues=NULL;	/* Series values                          */
36 int     _dxd_gi_loc_index=0;		/* Index of field locations in XF array   */
37 int     _dxd_gi_pos_type[MAX_POS_DIMS] = {0};/* Position type of each dimension   */
38 dep_type _dxd_gi_dependency = DEP_POSITIONS;
39 conn_type _dxd_gi_connections=CONN_UNKNOWN;
40 ByteOrder _dxd_gi_byteorder=BO_MSB;	/* Byte order of binary files */
41 
42 struct header _dxd_gi_header = {0,SKIP_LINES};
43 struct header _dxd_gi_serseparat = {0,SKIP_LINES};
44 
45 static Error SetDefault(void);
46 static Array make_positions(void *XF);
47 static Field build_Field(int, void *, Array, Array);
48 static Error genimpsetup(char **fldnames, int *start, int *end, int *delta);
49 static Error SetDefault(void);
50 static void genimpcleanup(void);
51 static Object import_Group(FILE **);
52 
53 /*
54  * Given the series and field index calculate the corresponding index into
55  * an array (XF) of data pointers.
56  */
57 #define DATA_INDEX(s_index, f_index) (s_index*_dxd_gi_numflds + f_index)
58 
59 /*
60  * This is the top level routine for general importer. It takes the
61  * input parameters from the import module as defined by the m_Import
62  * driver.
63  *
64  * Returns the imported Object on success, and NULL and sets the error code
65  * on failure.  The return object can be a Field, Series, Group of fields
66  * or a Group of Series depending upon the data that is imported.
67  */
_dxf_gi_get_gen(struct parmlist * p)68 Object _dxf_gi_get_gen(struct parmlist *p)
69 {
70   Object gr;
71   FILE *datafp;
72 
73   datafp=NULL;
74   if (!(SetDefault()))
75     goto error;
76 
77   if (!(_dxf_gi_InputInfoTable(p->filename,p->format,&datafp)))
78     goto error;
79 
80   if (!(genimpsetup(p->fieldlist,
81 		    p->startframe,
82 		    p->endframe,
83 		    p->deltaframe)))
84     goto error;
85 
86   if(!(gr = import_Group(&datafp)))
87     goto error;
88 
89   if (datafp)
90     _dxfclose_dxfile(datafp,_dxd_gi_filename);
91   genimpcleanup();
92 
93   return gr;
94 
95  error:
96   if (datafp)
97     _dxfclose_dxfile(datafp,_dxd_gi_filename);
98   genimpcleanup();
99 
100   if ( DXGetError() == ERROR_NONE )
101     {
102       DXSetError(ERROR_INTERNAL,
103 	"General importer got an error but did not set the error code");
104     }
105 
106   return NULL;
107 }
108 
109 
110 /*
111  * Initialize the default global variable values  for the data file
112  * specification.
113  * NOTE: these may overriden after table is processed.
114  * Returns ERROR/OK and sets error code.
115  */
116 static Error
SetDefault(void)117 SetDefault(void)
118 {
119   int i;
120   _dxd_gi_series = 1;
121 
122   /* temporarily set number of fields to 0 (it's like a flag). We construct
123      one variable with the name "field" (the default field name), so actually
124      the number of fields is 1 */
125 
126   _dxd_gi_whichser = NULL;
127   _dxd_gi_whichflds = NULL;
128   _dxd_gi_seriesvalues = NULL;
129   _dxd_gi_dataloc = NULL;
130   _dxd_gi_filename = NULL;
131 
132   _dxd_gi_numflds = 0;
133 
134   /* Allocate pointers to the variable structure */
135   if ((_dxd_gi_var =
136     (struct variable **)DXAllocate(sizeof(struct variable *) *MAX_VARS))
137        == NULL)
138     goto error;
139 
140   for(i = 0; i < MAX_VARS; i++)
141     _dxd_gi_var[i] = NULL;
142 
143 
144   if((_dxd_gi_var[0] = (struct variable *)DXAllocate(sizeof(struct variable)))==NULL)
145       goto error;
146 
147   strcpy(_dxd_gi_var[0]->name, "field");
148   _dxd_gi_format       = ASCII;
149   _dxd_gi_asciiformat  = FREE;
150   _dxd_gi_majority     = ROW;
151   _dxd_gi_interleaving = DEFAULT_INTERLEAVE;
152   _dxd_gi_positions    = DEFAULT_PRODUCT;
153   _dxd_gi_header.size  = 0;
154   _dxd_gi_header.type = SKIP_NOTHING;
155   _dxd_gi_connections = CONN_UNKNOWN;
156   _dxd_gi_dependency = DEP_POSITIONS;
157   _dxd_gi_serseparat.size = 0;
158   _dxd_gi_serseparat.type = SKIP_NOTHING;
159   _dxd_gi_fromfile = NULL;
160   return OK;
161 
162 error:
163   return ERROR;
164 }
165 
166 
167 /*
168  * Initializes the _dxd_gi_whichser and GI_whichfld arrays to be used in the
169  * import_Group function.  This is done after parsing the info file
170  * once we know how many series and fields there will be.
171  * Returns OK/ERROR and sets error code.
172  */
173 static Error
genimpsetup(char ** fldnames,int * start,int * end,int * delta)174 genimpsetup(char **fldnames, int *start, int *end, int *delta)
175 {
176   int i, j, mystart, myend, mydelta;
177 
178   if(!(_dxd_gi_whichser = (int *)DXAllocate(_dxd_gi_series*sizeof(int))))
179       goto error;
180 
181   if(!(_dxd_gi_whichflds = (int *)DXAllocate(_dxd_gi_numflds*sizeof(int))))
182       goto error;
183 
184   for(i=0; i<_dxd_gi_numflds; i++)
185     _dxd_gi_whichflds[i] = OFF;
186 
187   for(i=0; i<_dxd_gi_series; i++)
188     _dxd_gi_whichser[i] = OFF;
189 
190   if (fldnames) {
191       for (j=0 ; fldnames[j] ; j++) {
192 	  for(i=0 ; i<_dxd_gi_numflds; i++)
193     	    if(!strcmp(fldnames[j],_dxd_gi_var[i]->name)) {
194 		_dxd_gi_whichflds[i] = ON;
195 		break;
196 	    }
197 	  if (i == _dxd_gi_numflds) {
198 	    DXSetError(ERROR_BAD_PARAMETER,"#10900",fldnames[j]);
199 	    goto error;
200 	  }
201       }
202       if (_dxd_gi_positions == FIELD_PRODUCT &&
203 	  _dxd_gi_whichflds[_dxd_gi_loc_index] == ON && j>1)
204 	 DXWarning("'locations' variable ignored when other field(s) are specified, the positions of the field(s) are the locations");
205 
206       if (_dxd_gi_positions == FIELD_PRODUCT)
207 	_dxd_gi_whichflds[_dxd_gi_loc_index] = ON;
208   } else {
209       for(i=0; i<_dxd_gi_numflds; i++)
210 	_dxd_gi_whichflds[i] = ON;
211   }
212 
213   if (!start)
214     mystart = 0;
215   else
216     mystart = *start;
217 
218   if (!end)
219     myend = _dxd_gi_series-1;
220   else
221     myend = *end;
222 
223   if (!delta)
224     mydelta = 1;
225   else {
226     mydelta = *delta;
227     if (mydelta <= 0)  {
228       DXSetError(ERROR_BAD_PARAMETER,"10020","'delta'");
229       goto error;
230     }
231   }
232 
233   if ( mystart >= _dxd_gi_series || myend >= _dxd_gi_series ){
234       DXSetError(ERROR_BAD_PARAMETER,"#10901");
235       goto error;
236   }
237 
238   if ( mystart > myend ){
239       DXSetError(ERROR_BAD_PARAMETER,"#12260",mystart,myend);
240       goto error;
241   }
242   for(i = mystart; i <= myend; i += mydelta)
243     _dxd_gi_whichser[i] = ON;
244   return OK;
245 
246  error:
247   return ERROR;
248 }
249 
250 /*
251  * Clean up allocated memory after we're all done importing the data.
252  */
253 static void
genimpcleanup(void)254 genimpcleanup(void)
255 {
256   int i;
257 
258   for(i=0; i<_dxd_gi_numflds; i++)
259     if(_dxd_gi_var[i])
260       DXFree((Pointer)_dxd_gi_var[i]);
261 
262   DXFree((Pointer)_dxd_gi_var);
263 
264   if(_dxd_gi_seriesvalues)
265     DXFree((Pointer)_dxd_gi_seriesvalues);
266 
267   if(_dxd_gi_whichflds)
268     DXFree((Pointer)_dxd_gi_whichflds);
269 
270   if(_dxd_gi_whichser)
271     DXFree((Pointer)_dxd_gi_whichser);
272 
273   if(_dxd_gi_dataloc)
274     DXFree((Pointer)_dxd_gi_dataloc);
275 
276   if (_dxd_gi_filename)
277     DXFree((Pointer)_dxd_gi_filename);
278 
279   if (_dxd_gi_fromfile){
280      for (i=0; _dxd_gi_fromfile[i]; i++){
281 	DXFree((Pointer)_dxd_gi_fromfile[i]->data);
282 	DXFree((Pointer)_dxd_gi_fromfile[i]->skip);
283 	DXFree((Pointer)_dxd_gi_fromfile[i]->width);
284         DXFree((Pointer)_dxd_gi_fromfile[i]);
285      }
286      DXFree(_dxd_gi_fromfile);
287   }
288 
289 }
290 
291 /*
292  * Generates a Field, Series, Field Group or Series  Group as defined
293  * in the text file and the input parameters to Import().
294  *
295  * XF  deserves some explanation; it is a one dimensional array of pointers
296  * such that each non-NULL pointer points to data for a given series and field
297  * within that series.  Data for the s'th series and the f'th field within
298  * series s is located at XF[s*_dxd_gi_numflds + f], where '_dxd_gi_numflds' is the number of
299  * fields in a each series (i.e. that are imported).  We allocate the full list
300  * of pointers (all NULL) and the initialize only the entries for which we
301  * should be importing data, indicated by _dxd_gi_whichser[s] and _dxd_gi_whichflds[f].
302  *
303  * We can allocate the memory for XF in local memory as we eventually call
304  * DXAddArrayData() with XF[?] as a parameter.  Since DXAddArrayData() copies the
305  * data in it is ok to use local memory for XF.
306  *
307  * Return the Object when successful otherwise a NULL and set the error code.
308  */
309 static Object
import_Group(FILE ** datafp)310 import_Group(FILE **datafp)
311 {
312   Group   g = NULL;
313   Object  o = NULL;
314   Field   fld = NULL;
315   Series  *ser = NULL;
316   Array con = NULL;
317   Array pos = NULL;
318   int f, i, j, d, size, member, imported_members, imported_fields;
319   int delete_pos = 0, delete_con = 0,loconly = 0;
320   int s;
321   void **XF;
322   int dimsize[MAX_POS_DIMS];
323 
324   /*size = _dxfnumGridPoints();*/
325 
326   if (!(XF = (void**)DXAllocateLocalZero(_dxd_gi_series*_dxd_gi_numflds*sizeof(void*))))
327       goto error;
328 
329   for (d = i = 0; i < _dxd_gi_series; i++)
330     {
331       if (_dxd_gi_whichser[i] == OFF )
332 	{
333 	  d+=_dxd_gi_numflds;
334 	}
335       else if (_dxd_gi_whichser[i] == ON)
336 	{
337 	  for (j = 0; j < _dxd_gi_numflds; j++)
338 	    {
339 	      if (_dxd_gi_whichflds[j] == ON)
340 		{
341 	          size = _dxfnumGridPoints(j);
342 		  if (!(XF[d] = (void*)DXAllocateLocalZero(size *
343 				_dxd_gi_var[j]->datadim * _dxd_gi_var[j]->databytes)))
344 		      goto error;
345 		}
346 	      d++;
347 	    }
348 	}
349       else
350 	  DXErrorGoto(ERROR_UNEXPECTED,"Error in generating group");
351     }
352 
353   /*
354    * DXRead in the data from the user's data file into the correct buffers
355    * pointed to by XF[i].  Buffers come back filled with data in correct
356    * byte order, in row majority order and denormalized if necessary.
357    */
358   if (!_dxf_gi_read_file(XF,datafp))
359     goto error;
360 
361   /*
362    * Make up the positions component based on the user's  'positions = '
363    * inputs.  If they have specified the field 'locations' keyword then
364    * positions are specific to each series so wait to create the component
365    * until we have the series number.
366    */
367   if (_dxd_gi_positions != FIELD_PRODUCT) {
368   	if (!(pos = make_positions(NULL)))
369       		goto error;
370 	delete_pos = 1;
371    }
372 
373 
374   /*
375    * Make a connections grid if they are needed (not using 'points =').
376    */
377   if (_dxd_gi_connections == CONN_GRID) {
378     /* check for dimensions of 1 */
379     for (i=0, j=0; i<_dxd_gi_numdims; i++)
380        if (_dxd_gi_dimsize[i] > 1) dimsize[j++] = _dxd_gi_dimsize[i];
381     if( !(con = DXMakeGridConnectionsV(j, dimsize)) )
382       goto error;
383     delete_con = 1;
384   }
385 
386   /*
387    * Determine the number of fields and series to produce and thus the
388    * type of output object to create and return.
389    */
390   for (i=0, imported_members=0; i<_dxd_gi_series ; i++)
391     if (_dxd_gi_whichser[i] == ON)
392       imported_members++;
393   ASSERT(imported_members > 0);
394 
395   /*
396    * Determine the number of imported fields and
397    * if there is more than one member of (each of) the field(s), then
398    * create a series for each imported field.
399    */
400   if (imported_members > 1) {
401 	ser = (Series*)DXAllocateLocalZero(_dxd_gi_numflds * sizeof(Series));
402 	if (!ser)
403 	    goto error;
404   }
405 
406   for (f=0, imported_fields=0; f<_dxd_gi_numflds; f++) {
407     if ((_dxd_gi_whichflds[f] == ON) &&
408 	!(_dxd_gi_positions == FIELD_PRODUCT && f == _dxd_gi_loc_index)) {
409           imported_fields++;
410 	  if ((imported_members > 1) && !(ser[f] = DXNewSeries()))
411 		goto error;
412     }
413   }
414   if (imported_fields==0 &&
415       _dxd_gi_positions == FIELD_PRODUCT ){
416      imported_fields = 1;
417      if ((imported_members > 1) && !(ser[0] = DXNewSeries()))
418            goto error;
419      loconly=1;
420    }
421 
422   ASSERT(imported_fields > 0);
423 
424   /*
425    * Create a group if the number of fields is greater than 1.
426    * The resulting group may be either a group of fields or series, but
427    * in either case the number of imported fields is greater than 1.
428    */
429   if ((imported_fields > 1) && !(g = DXNewGroup()))
430 	goto error;
431 
432 
433   /*
434    * For each imported series, and each imported field within that series
435    * build the field with the correct positions and connections and possibly
436    * insert it into either a series (imported_members > 1) or
437    * a group (imported_members == 1 && imported_fields > 1).
438    */
439   for (member = -1, s=0; s<_dxd_gi_series; s++) {
440     if (_dxd_gi_whichser[s] == ON) {		/* If this series was requested */
441 	member++;			/* Incremement series member # */
442 	if (_dxd_gi_positions == FIELD_PRODUCT){/* Make positions from 'locations' */
443 	    if (!(pos = make_positions(XF[s*_dxd_gi_numflds + _dxd_gi_loc_index])))
444 		goto error;
445 	    delete_pos = 1;
446         }
447         if (loconly==1){
448            if (!(fld = build_Field(-1,XF[s*_dxd_gi_numflds+f], pos, con)))
449                  goto error;
450            /* pos and con are now referenced */
451            delete_con = delete_pos = 0;
452 
453            if (imported_members > 1) {
454               if (!(DXSetSeriesMember(ser[0], member,
455                    (double)_dxd_gi_seriesvalues[s],(Object)fld)))
456                           goto error;
457               fld = NULL;     /* It is now referenced */
458            }
459            /* if only one member of series imported still add the
460             * series position attribute by hand */
461 	    else if (_dxd_gi_series > 1 ){
462 	       DXSetFloatAttribute((Object)fld,"series position",
463 				   _dxd_gi_seriesvalues[s]);
464 	    }
465         }
466 	for (f=0; f<_dxd_gi_numflds ; f++) {
467 	    if (_dxd_gi_whichflds[f] == ON &&
468               !(_dxd_gi_positions == FIELD_PRODUCT &&
469                       f == _dxd_gi_loc_index)) {
470 		 if (!(fld = build_Field(f,XF[s*_dxd_gi_numflds+f], pos, con)))
471 		      goto error;
472 
473 		    /* pos and con are now referenced */
474 		    delete_con = delete_pos = 0;
475 
476                     /* if only one member of series imported still add the
477 		     * series position attribute by hand */
478 		    if (_dxd_gi_series > 1 && imported_members ==1){
479 		       DXSetFloatAttribute((Object)fld,"series position",
480 					   _dxd_gi_seriesvalues[s]);
481 		    }
482 		    if (imported_members > 1) {
483 			if (!(DXSetSeriesMember(ser[f], member,
484 					      (double)_dxd_gi_seriesvalues[s],
485 					      (Object)fld)))
486 			  goto error;
487 			fld = NULL;	/* It is now referenced */
488 		    } else if (g) {
489 			if (!(DXSetMember(g, _dxd_gi_var[f]->name, (Object)fld)))
490 			    goto error;
491 			fld = NULL;	/* It is now referenced */
492 		    }
493 	    }
494 	}
495      }
496   }
497 
498   /*
499    * If imported_members > 1 && imported_fields > 1 then we have to
500    * create a group of series.
501    */
502   if (ser && g) {
503 	ASSERT(imported_members > 1);
504 	ASSERT(imported_fields  > 1);
505 	for (f=0 ; f<_dxd_gi_numflds ; f++) {
506 	    if (ser[f] && !(DXSetMember(g, _dxd_gi_var[f]->name, (Object)ser[f])))
507 		 goto error;
508 	    ser[f] = NULL;	/* It is now referenced */
509 	}
510   }
511 
512   /*
513    * DXFree up the memory we used.
514    */
515   if (XF)  {
516     for (i = 0; i < _dxd_gi_series*_dxd_gi_numflds; i++)
517       if (XF[i]) DXFree((Pointer)XF[i]);
518     DXFree((Pointer)XF);
519   }
520 
521   /*
522    * Return the correct object.
523    */
524   if (imported_fields == 1 && imported_members == 1) {
525     ASSERT(fld != NULL);
526     return (Object)fld;
527   } else if (imported_fields == 1 && imported_members > 1) {
528     /*
529      * Look for the first non-zero element of ser[], this is an alternative
530      * to looking in _dxd_gi_whichflds[].
531      */
532     o = NULL;
533     for (f=0 ; f<_dxd_gi_numflds && !o ; f++)
534 	o = (Object)ser[f];
535     ASSERT(o != NULL);
536     DXFree((Pointer)ser);
537     return (Object)o;
538   } else if (imported_fields > 1 && imported_members == 1) {
539     ASSERT(g != NULL);
540     return (Object)g;
541   } else if (imported_fields > 1 && imported_members > 1) {
542     ASSERT(g != NULL);
543     DXFree((Pointer)ser);
544     return (Object)g;
545   }
546 
547  error:
548   if (g) DXDelete((Object)g);
549   if (fld) DXDelete((Object)fld);
550   if (delete_pos && con) DXDelete((Object)pos);
551   if (delete_con && con) DXDelete((Object)con);
552 
553   if (ser)  {
554     for (f = 0; f < _dxd_gi_numflds; f++)
555       if (ser[f]) DXDelete((Object)ser[f]);
556     DXFree((Pointer)ser);
557   }
558 
559   if (XF)  {
560     for (i = 0; i < _dxd_gi_series*_dxd_gi_numflds; i++)
561       if (XF[i]) DXFree((Pointer)XF[i]);
562     DXFree((Pointer)XF);
563   }
564 
565   return NULL;
566 
567 }
568 
569 /*
570  * Build a field with the given series and field index, using data
571  * pointed to by XF[].  Specifics of the field are found in _dxd_gi_var[f_index].
572  * Return a field when successful otherwise a NULL and set error code.
573  */
574 static
build_Field(int f_index,void * XF,Array pos,Array con)575 Field build_Field(int f_index, void *XF, Array pos, Array con)
576 {
577   Field f = NULL;
578   Array a = NULL;
579   Object o = NULL;
580   int size;
581   char	*depstr;
582 
583   /*size = _dxfnumGridPoints();*/
584   size = _dxfnumGridPoints(f_index);
585 
586   if (!(f = DXNewField()))
587     goto error;
588 
589   /* f_index = -1 flag for locations only field */
590   if (f_index!=-1){
591   /*
592    * Create the "data" component for the field.
593    * FIXME:  Presently general importer supports only CATEGORY_REAL
594    */
595   if (_dxd_gi_var[f_index]->datadim > 1)  {
596     int shape = _dxd_gi_var[f_index]->datadim;
597     a = DXNewArrayV(_dxd_gi_var[f_index]->datatype, CATEGORY_REAL, 1, &shape);
598   } else
599     a = DXNewArray(_dxd_gi_var[f_index]->datatype, CATEGORY_REAL, 0);
600   if (!(a))
601     goto error;
602 
603   if ( !(DXAddArrayData(a, 0, size, (Pointer)XF)))
604     goto error;
605 
606   if ( !(DXSetComponentValue(f, "data", (Object)a)) )
607     goto error;
608 
609   /*
610    * Name the field.
611    */
612   if (!(o = (Object)DXNewString(_dxd_gi_var[f_index]->name))  ||
613       !DXSetAttribute((Object)f, "name", o))
614         goto error;
615   o = NULL;
616 
617   /*
618    * DXAdd correct data dependency.
619    */
620   /*  if (_dxd_gi_dependency == DEP_CONNECTIONS) */
621   if (_dxd_gi_var[f_index]->datadep == DEP_CONNECTIONS)
622 	depstr = "connections";
623   else
624 	depstr = "positions";
625 
626   if (!(o = (Object)DXNewString(depstr))  ||
627       !DXSetComponentAttribute(f, "data", "dep", o))
628 	goto error;
629   o = NULL;
630   }
631 
632   /*
633    * DXAdd positions to the field.
634    */
635   if( !(DXSetComponentValue(f, "positions", (Object)pos)))
636     goto error;
637 
638   /*
639    * DXAdd connections if requested ('grid =' as opposed to 'points =')
640    * to the field.
641    */
642   if (_dxd_gi_connections == CONN_GRID)
643     {
644       if( !(DXSetComponentValue(f, "connections", (Object)con)))
645 	goto error;
646     }
647 
648 #ifdef DO_ENDFIELD
649   if (!DXEndField(f))
650     goto error;
651 #endif
652 
653   return f;
654 
655  error:
656   if (f) DXDelete((Object)f);
657   if (a) DXDelete((Object)a);
658   if (o) DXDelete((Object)o);
659 
660   return NULL;
661 }
662 
663 
664 /*
665  * Create an Array of positions based on the global variable 'positions'
666  * and possibly the field data at XF (and _dxd_gi_var[loc_indx], user
667  * used 'locations' keyword) or _dxd_gi_dataloc[i] which holds data specified
668  * in the 'positions = ' statement.
669  *
670  * The output positions array has '_dxd_gi_numdims'  dimensions as follows,
671  * _dxd_gi_dimsize[0] X _dxd_gi_dimsize[1] ... X _dxd_gi_dimsize[_dxd_gi_numdims-1].
672  * The output array can be either, regular, regular product, mixed product,
673  * irregular or 'field' product for which data  is taken from XF.
674  *
675  * FIXME: general importer only supports TYPE_FLOAT and CATEGORY_REAL
676  *
677  */
678 static Array
make_positions(void * XF)679 make_positions(void *XF)
680 {
681   int size, i, j, k;
682   float origin[MAX_POS_DIMS], deltas[MAX_POS_DIMS*MAX_POS_DIMS], *mixpositions;
683   Array *mixarr = NULL, pos = NULL;
684   int shape;
685 
686   /*size = _dxfnumGridPoints();*/
687   size = _dxfnumGridPoints(-1);
688   mixarr = NULL;
689 
690   for (j=0; j<_dxd_gi_numdims; j++)
691       origin[j] = 0.0;
692 
693   for (j=0; j<_dxd_gi_numdims*_dxd_gi_numdims; j++)
694       deltas[j] = 0.0;
695 
696   if (_dxd_gi_positions == FIELD_PRODUCT)
697     {
698 
699        /*
700 	* Build an array to hold the user's data (which should be floats
701 	* or was converted to float in _dxf_gi_read_file()).
702 	* positions array should always be rank 1
703 	*/
704       shape = _dxd_gi_var[_dxd_gi_loc_index]->datadim;
705       pos = DXNewArrayV(TYPE_FLOAT, CATEGORY_REAL, 1, &shape);
706       if (!pos)
707 	goto error;
708 
709        /*
710 	* DXAdd the user's data to the array.
711 	*/
712       if (!DXAddArrayData(pos, 0, size, (Pointer)XF))
713 	goto error;
714     }
715   else if (_dxd_gi_positions == DEFAULT_PRODUCT)
716     {
717        /*
718 	* Build the default positions array, a compact product of
719 	* arrays with each dimension having an origin of 0 and a delta of 1.
720 	*/
721       for (i=0; i<_dxd_gi_numdims; i++)
722 	  origin[i] = 0.0;
723 
724       for (i=0, j=0; i<_dxd_gi_numdims; i++)
725 	{
726 	  deltas[j] = 1.0;
727 	  j += _dxd_gi_numdims + 1;
728 	}
729 
730       if( !(pos = DXMakeGridPositionsV(_dxd_gi_numdims, _dxd_gi_dimsize, origin, deltas)) )
731 	goto error;
732 
733     }
734   else if (_dxd_gi_positions == REGULAR_PRODUCT)
735     {
736        /*
737 	* The user specified a regular product array with origin,delta
738 	* for each dimension where origin[i] = _dxd_gi_dataloc[2*i] and
739  	* delta[i] = _dxd_gi_dataloc[2*i + 1] for each dimension i.
740 	*/
741       for (j=i=0; i<_dxd_gi_numdims; i++)
742 	{
743 	  origin[i] = _dxd_gi_dataloc[j];
744 	  j += 2;
745 	}
746       for (i=0, k=0, j=1; i<_dxd_gi_numdims; i++)
747 	{
748 	  deltas[k] = _dxd_gi_dataloc[j];
749 	  j += 2;
750 	  k += _dxd_gi_numdims + 1;
751 	}
752       if( !(pos = DXMakeGridPositionsV(_dxd_gi_numdims, _dxd_gi_dimsize, origin, deltas)) )
753 	goto error;
754 
755     }
756   else if (_dxd_gi_positions == IRREGULAR_PRODUCT)
757     {
758        /*
759 	* The user specified a set of irregular positions for each dimension
760 	* that are to make up an irregular product array.
761 	*/
762       shape = _dxd_gi_numdims;
763       pos = DXNewArrayV(TYPE_FLOAT, CATEGORY_REAL, 1, &shape);
764       if (!(pos))
765 	goto error;
766 
767       if (!DXAddArrayData(pos, 0, size, (Pointer)_dxd_gi_dataloc))
768 	goto error;
769 
770     }
771   else if (_dxd_gi_positions == MIXED_PRODUCT)
772     {
773        /*
774 	* The user specified a set of regular and irregular positions for
775 	* each dimension that are to make up a product array.
776 	*/
777       j = 0;
778       if (!(mixarr = (Array *)DXAllocateZero(_dxd_gi_numdims*sizeof(Array))))
779 	goto error;
780       for (i=0; i<_dxd_gi_numdims; i++)
781 	{
782 	  if (_dxd_gi_pos_type[i] == REGULAR)
783 	    {
784 	      for (k=0; k<_dxd_gi_numdims; k++)
785 		{
786 		  origin[k] = 0.0;
787 		  deltas[k] = 0.0;
788 		}
789 	      origin[i] = _dxd_gi_dataloc[j++];
790 	      deltas[i] = _dxd_gi_dataloc[j++];
791 	      mixarr[i] = (Array)DXNewRegularArray(TYPE_FLOAT, _dxd_gi_numdims,
792 						 _dxd_gi_dimsize[i],
793 						 (Pointer)origin,
794 						 (Pointer)deltas);
795 	      if (!mixarr[i])
796 		goto error;
797 	    }
798 	  else if (_dxd_gi_pos_type[i] == IRREGULAR)
799 	    {
800 	      if (!(mixpositions =
801 		    (float *)DXAllocate(_dxd_gi_numdims*_dxd_gi_dimsize[i]*sizeof(float))))
802 		  goto error;
803 
804 	      for (k=0; k<_dxd_gi_dimsize[i]*_dxd_gi_numdims; k++)
805 		  mixpositions[k] = 0.0;
806 
807 	      for (k=0; k<_dxd_gi_dimsize[i]; k++)
808 		  mixpositions[(k*_dxd_gi_numdims)+i] = _dxd_gi_dataloc[j++];
809 
810 
811 	      if (_dxd_gi_numdims > 1)
812 		{
813 	          shape = _dxd_gi_numdims;
814 		  if (!(mixarr[i] =
815 		       DXNewArrayV(TYPE_FLOAT, CATEGORY_REAL, 1, &shape)))
816 		    goto error;
817 		  if (!(DXAddArrayData(mixarr[i], 0, _dxd_gi_dimsize[i],
818 						(Pointer)mixpositions)))
819 		    goto error;
820 		}
821 	      else
822 		{
823 		  if (!(pos = DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 0)))
824 		    goto error;
825 		  if (!(DXAddArrayData(pos, 0, _dxd_gi_dimsize[i],
826 						(Pointer)mixpositions)))
827 		    goto error;
828 		}
829 	      DXFree((Pointer)mixpositions);
830 	    }
831 	}
832       if (_dxd_gi_numdims > 1)
833 	if (!(pos = (Array)DXNewProductArrayV(_dxd_gi_numdims, mixarr)))
834 	  goto error;
835       DXFree(mixarr);
836     }
837 
838   return pos;
839 
840 error:
841   if (pos) DXDelete((Object)pos);
842 
843   if (mixarr){
844     for(i=0; i<_dxd_gi_numdims; i++)
845       if (mixarr[i])
846 	DXDelete((Object)mixarr[i]);
847     DXFree(mixarr);
848   }
849 
850   return NULL;
851 }
852 
853 
854 /*
855    FN: figure out the number of grid points.
856 */
857 
_dxfnumGridPoints(int f_index)858 int _dxfnumGridPoints(int f_index)
859 {
860   int i, size;
861   int count;
862 
863   /* One less data point in each dimension of the grid  for dep connections */
864   /* f_index = -1 always like dep connections */
865   if (f_index!=-1 && _dxd_gi_var[f_index]->datadep == DEP_CONNECTIONS){
866      for (i = 0,size = 1,count = 0; i < _dxd_gi_numdims; i++) {
867 	if (_dxd_gi_dimsize[i] > 1)
868 	   size *= (_dxd_gi_dimsize[i] - 1);
869 	else
870 	   count++;
871      }
872      if (count == _dxd_gi_numdims)
873 	size = 0;
874   }
875   else{
876      for(i = 0, size = 1; i < _dxd_gi_numdims; size *= _dxd_gi_dimsize[i], i++)
877         ;
878   }
879 
880   return( size );
881 }
882 
883 
884