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 #include <dxconfig.h>
10 
11 
12 
13 #include <stdio.h>
14 #include <math.h>
15 #include <string.h>
16 #include <dx/dx.h>
17 #include "groupinterpClass.h"
18 
19 GroupInterpolator
_dxfNewGroupInterpolator(Group g,enum interp_init initType,float fuzz,Matrix * m)20 _dxfNewGroupInterpolator(Group g,
21 	enum interp_init initType, float fuzz, Matrix *m)
22 {
23     return _dxf_NewGroupInterpolator(g, initType, fuzz, m,
24 				&_dxdgroupinterpolator_class);
25 }
26 
27 GroupInterpolator
_dxf_NewGroupInterpolator(Group g,enum interp_init initType,float fuzz,Matrix * m,struct groupinterpolator_class * class)28 _dxf_NewGroupInterpolator(Group g,
29 	enum interp_init initType, float fuzz, Matrix *m,
30 			struct groupinterpolator_class *class)
31 {
32     GroupInterpolator	gi;
33     int 		i, j;
34     Object		child;
35     Interpolator	*subPtr, sub, firstsub = NULL;
36     int			isMultigrid;
37 
38     CHECK(g, CLASS_GROUP);
39 
40     gi=(GroupInterpolator)
41 	_dxf_NewInterpolator((struct interpolator_class *)class, (Object)g);
42     if (!gi)
43 	return NULL;
44 
45     isMultigrid = DXGetGroupClass(g) == CLASS_MULTIGRID;
46 
47     /*
48      * Create array of pointers to interpolators for each descendent
49      * of the current group.  First, how many descendents?
50      */
51     for (i = 0; NULL != (child = DXGetEnumeratedMember(g, i, NULL)); i++);
52 
53     gi->subInterp = (Interpolator *)DXAllocate(i*sizeof(Interpolator *));
54     if (!gi->subInterp)
55     {
56 	DXFree((Pointer)gi);
57 	return NULL;
58     }
59 
60     /*
61      * Create interpolators for each.  Collect a group bound box
62      * as we do so.
63      */
64     subPtr = gi->subInterp;
65     gi->nMembers = 0;
66     for (i = 0; NULL != (child = DXGetEnumeratedMember(g, i, NULL)); i++)
67     {
68 	/*
69 	 * Ignore fields that have no elements
70 	 */
71 	if (DXGetObjectClass(child) == CLASS_FIELD)
72 	{
73 	    Array array;
74 	    int   nElements;
75 
76 	    if (DXEmptyField((Field)child))
77 		continue;
78 
79 	    array = (Array)DXGetComponentValue((Field)child, "connections");
80 	    if (! array)
81 		continue;
82 
83 	    DXGetArrayInfo(array, &nElements, NULL, NULL, NULL, NULL);
84 	    if (nElements == 0)
85 		continue;
86 	}
87 
88 	sub = (Interpolator)_dxfNewInterpolatorSwitch(child,
89 						initType, fuzz, m);
90 	if (! sub)
91 	{
92 	    DXDelete((Object)gi);
93 	    return NULL;
94 	}
95 
96 	*subPtr++ = sub;
97 
98 	DXReference((Object)sub);
99 
100 	gi->nMembers ++;
101 
102 	if (i == 0)
103 	{
104 	    DXGetType(sub->dataObject, &gi->interpolator.type,
105 				     &gi->interpolator.category,
106 				     &gi->interpolator.rank,
107 				     gi->interpolator.shape);
108 
109 	    gi->interpolator.nDim = sub->nDim;
110 
111 	    memcpy((void *)(gi->interpolator.min), (void *)(sub->min),
112 				gi->interpolator.nDim*sizeof(float));
113 	    memcpy((void *)(gi->interpolator.max), (void *)(sub->max),
114 				gi->interpolator.nDim*sizeof(float));
115 
116 	    firstsub = sub;
117 	}
118 	else
119 	{
120 	    for (j = 0; j < gi->interpolator.nDim; j++)
121 	    {
122 		if (sub->min[j] < gi->interpolator.min[j])
123 		    gi->interpolator.min[j] = sub->min[j];
124 		if (sub->max[j] > gi->interpolator.max[j])
125 		    gi->interpolator.max[j] = sub->max[j];
126 	    }
127 
128 	    if (! isMultigrid)
129 		((Interpolator)sub)->matrix = ((Interpolator)firstsub)->matrix;
130 	}
131     }
132 
133     /*
134      * Initially, no hint
135      */
136     gi->hint = NULL;
137 
138     return gi;
139 }
140 
141 Error
_dxfGroupInterpolator_Delete(GroupInterpolator gi)142 _dxfGroupInterpolator_Delete(GroupInterpolator gi)
143 {
144     int i;
145 
146     /*
147      * DXFree interpolator pointed to by hint
148      */
149     if (gi->hint)
150     {
151 	DXDelete((Object)gi->hint);
152 	gi->hint = NULL;
153     }
154 
155     /*
156      * DXFree descendent interpolators
157      */
158     if (gi->subInterp)
159     {
160 	for (i = 0; i < gi->nMembers; i++)
161 	    if (gi->subInterp[i])
162 	    {
163 		DXDelete((Object)gi->subInterp[i]);
164 		gi->subInterp[i] = NULL;
165 	    }
166 
167 	DXFree((Pointer)gi->subInterp);
168 	gi->subInterp = NULL;
169     }
170 
171     _dxfInterpolator_Delete((Interpolator)gi);
172 
173     return OK;
174 }
175 
176 int
_dxfGroupInterpolator_Interpolate(GroupInterpolator gi,int * n,float ** points,Pointer * values,Interpolator * parentHint,int fuzzFlag)177 _dxfGroupInterpolator_Interpolate(GroupInterpolator gi, int *n,
178     float **points, Pointer *values, Interpolator *parentHint, int fuzzFlag)
179 {
180     Interpolator	*sub, *subBase, myHint, newHint;
181     int			i, nMem, nAtStart;
182 
183     myHint = NULL;
184 
185     nAtStart = *n;
186 
187     /*
188      * Start with the child (possibly distant descendent)
189      * pointed to by the hint.
190      */
191     if (gi->hint)
192 	if (! _dxfInterpolate(gi->hint, n, points, values, &myHint, fuzzFlag))
193 	    return 0;
194 
195     /*
196      * Turn off fuzz as soon as a sample succeeds. All subsequent
197      * interpolation attempts will be done sans fuzz.
198      */
199     if (nAtStart > *n)
200 	fuzzFlag = FUZZ_OFF;
201 
202     /*
203      * As long as poits remain to be interpolated, call descendents
204      * to interpolate them.  When a point is encountered that does
205      * not lie in any child field, quit.
206      */
207     nMem = gi->nMembers;
208     subBase = gi->subInterp;
209     while(*n != 0)
210     {
211 	newHint = NULL;
212 
213 	sub = subBase;
214 	for (i = 0; i < nMem; i++)
215 	{
216 	    if ((*sub) != gi->hint)
217 		if (! _dxfInterpolate((*sub), n, points, values, &newHint, fuzzFlag))
218 		    return 0;
219 
220 	    /*
221 	     * Again, turn off fuzz as soon as a sample succeeds. All
222 	     * subsequent interpolation attempts will be done sans fuzz.
223 	     */
224 	    if (nAtStart > *n)
225 		fuzzFlag = FUZZ_OFF;
226 
227 	    if (newHint)
228 		break;
229 
230 	    sub++;
231 	}
232 
233 	/*
234 	 * Keep going as long as we have more points to interpolate and
235 	 * we interpolated some last time through the children.
236 	 */
237 	if (! newHint)
238 	    break;
239 
240 	myHint = newHint;
241     }
242 
243     /*
244      * If we didn't interpolate any points and there was a hint,
245      * delete the old hint.
246      */
247     if (gi->hint != myHint)
248     {
249 	if (gi->hint)
250 	    DXDelete((Object)(gi->hint));
251 
252 	if (myHint)
253 	    gi->hint = (Interpolator)DXReference((Object)(myHint));
254 	else
255 	    gi->hint = NULL;
256     }
257 
258     /*
259      * If the parent requested a hint, pass it up.
260      */
261     if (parentHint)
262 	*parentHint = myHint;
263 
264     return OK;
265 }
266 
267 Object
_dxfGroupInterpolator_Copy(GroupInterpolator old,enum _dxd_copy copy)268 _dxfGroupInterpolator_Copy(GroupInterpolator old, enum _dxd_copy copy)
269 {
270     GroupInterpolator new;
271 
272     new = (GroupInterpolator)
273 	_dxf_NewObject((struct object_class *)&_dxdgroupinterpolator_class);
274 
275     return (Object)_dxf_CopyGroupInterpolator(new, old, copy);
276 }
277 
278 GroupInterpolator
_dxf_CopyGroupInterpolator(GroupInterpolator new,GroupInterpolator old,enum _dxd_copy copy)279 _dxf_CopyGroupInterpolator(GroupInterpolator new, GroupInterpolator old,
280 								enum _dxd_copy copy)
281 {
282     Interpolator	*ns, *os;
283     int			i;
284 
285     if (old == NULL)
286 	return NULL;
287 
288     if (! _dxf_CopyInterpolator((Interpolator)new, (Interpolator)old))
289 	return NULL;
290 
291     new->nMembers = old->nMembers;
292 
293     new->subInterp = (Interpolator *)
294 			    DXAllocate(new->nMembers*sizeof(Interpolator));
295 
296     if (! new->subInterp)
297     {
298 	DXFree((Pointer)new);
299 	return NULL;
300     }
301 
302     ns = new->subInterp;
303     os = old->subInterp;
304     for (i = 0; i < new->nMembers; i++, os++, ns++)
305     {
306 	if (NULL ==  (*ns = (Interpolator)DXCopy((Object)*os, copy)))
307 	{
308 	    while(i-- > 0)
309 		DXDelete((Object)*(--ns));
310 	    DXFree((Pointer)new->subInterp);
311 	    DXFree((Pointer)new);
312 	    return NULL;
313 	}
314 	DXReference((Object)*ns);
315     }
316 
317     new->hint = NULL;
318 
319     return new;
320 }
321 
322 Interpolator
_dxfGroupInterpolator_LocalizeInterpolator(GroupInterpolator gi)323 _dxfGroupInterpolator_LocalizeInterpolator(GroupInterpolator gi)
324 {
325     int			i;
326     Interpolator	*childi;
327 
328     childi = gi->subInterp;
329     for (i = 0; i < gi->nMembers; i++, childi++)
330 	DXLocalizeInterpolator(*childi);
331 
332     return (Interpolator)gi;
333 }
334