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