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 #include <dx/dx.h>
11 
12 
13 #include <stdio.h>
14 #include <math.h>
15 #include <string.h>
16 #include "trisRI2DClass.h"
17 
18 #define WALK_LENGTH	5
19 
20 #define FALSE 0
21 #define TRUE 1
22 
23 static Error _dxfInitializeTask(Pointer);
24 static Error _dxfInitialize(TrisRI2DInterpolator);
25 static int   _dxftriangular_coords(float *, float *,
26 		float *, float *, TriCoord *, float);
27 static int   _dxfCleanup(TrisRI2DInterpolator);
28 static int   _dxftriExit(int, TriCoord *, int *);
29 static int   _dxfTrisWalk(TrisRI2DInterpolator, float *, int, TriCoord *);
30 static int   _dxfTrisSearch(TrisRI2DInterpolator, float *, int, TriCoord *, int);
31 
32 int
_dxfRecognizeTrisRI2D(Field field)33 _dxfRecognizeTrisRI2D(Field field)
34 {
35     Array    array;
36     Type     t;
37     Category c;
38 
39     CHECK(field, CLASS_FIELD);
40 
41     ELT_TYPECHECK(field, "triangles");
42 
43     array = (Array)DXGetComponentValue(field, "positions");
44     if (!array)
45     {
46 	DXSetError(ERROR_MISSING_DATA, "#10240", "positions");
47 	return 0;
48     }
49 
50     DXGetArrayInfo(array, NULL, &t, &c, NULL, NULL);
51 
52     if (c != CATEGORY_REAL)
53     {
54 	DXSetError(ERROR_DATA_INVALID, "#11150", "connections");
55 	return 0;
56     }
57 
58     array = (Array)DXGetComponentValue(field, "connections");
59     if (!array)
60     {
61 	DXSetError(ERROR_MISSING_DATA, "#10240", "connections");
62 	return 0;
63     }
64 
65     DXGetArrayInfo(array, NULL, &t, &c, NULL, NULL);
66 
67     if (t != TYPE_INT || c != CATEGORY_REAL)
68     {
69 	DXSetError(ERROR_DATA_INVALID, "#11450");
70 	return 0;
71     }
72 
73     return 1;
74 }
75 
76 TrisRI2DInterpolator
_dxfNewTrisRI2DInterpolator(Field field,enum interp_init initType,double fuzz,Matrix * m)77 _dxfNewTrisRI2DInterpolator(Field field,
78 		enum interp_init initType, double fuzz, Matrix *m)
79 {
80     return (TrisRI2DInterpolator)_dxf_NewTrisRI2DInterpolator(field,
81 			    initType, fuzz, m, &_dxdtrisri2dinterpolator_class);
82 }
83 
84 TrisRI2DInterpolator
_dxf_NewTrisRI2DInterpolator(Field field,enum interp_init initType,float fuzz,Matrix * m,struct trisri2dinterpolator_class * class)85 _dxf_NewTrisRI2DInterpolator(Field field,
86 		enum interp_init initType, float fuzz, Matrix *m,
87 		struct trisri2dinterpolator_class *class)
88 {
89     TrisRI2DInterpolator 	ti;
90     float	*mm, *MM;
91 
92     ti = (TrisRI2DInterpolator)_dxf_NewFieldInterpolator(field, fuzz, m,
93 	    (struct fieldinterpolator_class *)class);
94 
95     if (! ti)
96 	return NULL;
97 
98     mm = ((Interpolator)ti)->min;
99     MM = ((Interpolator)ti)->max;
100 
101     if (((MM[0] - mm[0]) * (MM[1] - mm[1])) == 0.0)
102     {
103 	DXDelete((Object)ti);
104 	return NULL;
105     }
106 
107 
108     ti->pArray	= NULL;
109     ti->pHandle	= NULL;
110     ti->dArray	= NULL;
111     ti->dHandle	= NULL;
112     ti->tArray	= NULL;
113     ti->nArray	= NULL;
114     ti->grid	= NULL;
115 
116     ti->hint = -1;
117 
118     if (initType == INTERP_INIT_PARALLEL)
119     {
120 	if (! DXAddTask(_dxfInitializeTask, (Pointer)&ti, sizeof(ti), 1.0))
121 	{
122 	    DXDelete((Object)ti);
123 	    return NULL;
124 	}
125 
126     }
127     else if (initType == INTERP_INIT_IMMEDIATE)
128     {
129 	if (! _dxfInitialize(ti))
130 	{
131 	    DXDelete((Object)ti);
132 	    return NULL;
133 	}
134     }
135 
136     return ti;
137 }
138 
139 static Error
_dxfInitializeTask(Pointer p)140 _dxfInitializeTask(Pointer p)
141 {
142     return _dxfInitialize(*(TrisRI2DInterpolator *)p);
143 }
144 
145 static Error
_dxfInitialize(TrisRI2DInterpolator ti)146 _dxfInitialize(TrisRI2DInterpolator ti)
147 {
148     Field	field;
149     Type	dataType;
150     Category	dataCategory;
151     int		i;
152     int		*tri;
153     float	len, area;
154 
155     ti->fieldInterpolator.initialized = 1;
156 
157     field = (Field)((Interpolator)ti)->dataObject;
158 
159     /*
160      * De-reference data
161      */
162     ti->dArray   = (Array)DXGetComponentValue(field, "data");
163     if (!ti->dArray)
164     {
165 	DXSetError(ERROR_MISSING_DATA, "#10240", "data");
166 	return ERROR;
167     }
168     DXReference((Object)ti->dArray);
169 
170     DXGetArrayInfo(ti->dArray, NULL, &((Interpolator)ti)->type,
171 		&((Interpolator)ti)->category,
172 		&((Interpolator)ti)->rank, ((Interpolator)ti)->shape);
173 
174     ti->dHandle = DXCreateArrayHandle(ti->dArray);
175     if (! ti->dHandle)
176 	return ERROR;
177 
178 
179     /*
180      * Get the grid.
181      */
182     ti->pArray = (Array)DXGetComponentValue(field, "positions");
183     if (!ti->pArray)
184     {
185 	DXSetError(ERROR_MISSING_DATA, "#10240", "positions");
186 	return ERROR;
187     }
188     DXReference((Object)ti->pArray);
189 
190     ti->pHandle = DXCreateArrayHandle(ti->pArray);
191     if (! ti->pHandle)
192 	return ERROR;
193 
194     /*
195      * Get the triangles.
196      */
197     ti->tArray = (Array)DXGetComponentValue(field, "connections");
198     if (!ti->tArray)
199     {
200 	DXSetError(ERROR_MISSING_DATA, "#10240", "connections");
201 	return ERROR;
202     }
203     DXReference((Object)ti->tArray);
204 
205     DXGetArrayInfo(ti->tArray, &ti->nTriangles, NULL, NULL, NULL, NULL);
206 
207     /*
208      * get info about data values
209      */
210     DXGetArrayInfo(ti->dArray, NULL, &dataType, &dataCategory, NULL, NULL);
211 
212     /*
213      * Don't worry about maintaining shape of input; just determine how
214      * many values to interpolate.
215      */
216     ti->nElements = DXGetItemSize(ti->dArray) / DXTypeSize(dataType);
217 
218     if (ti->fieldInterpolator.localized)
219 	ti->triangles = (Triangle *)DXGetArrayDataLocal(ti->tArray);
220     else
221 	ti->triangles = (Triangle *)DXGetArrayData(ti->tArray);
222 
223     if (! ti->triangles)
224 	return ERROR;
225 
226     /*
227      * Get the neighbors
228      */
229     ti->nArray =
230 	DXNeighbors((Field)(ti->fieldInterpolator.interpolator.dataObject));
231     if (! ti->nArray)
232 	return ERROR;
233 
234     DXReference((Object)ti->nArray);
235 
236     if (ti->fieldInterpolator.localized)
237 	ti->neighbors = (Triangle *)DXGetArrayDataLocal(ti->nArray);
238     else
239 	ti->neighbors = (Triangle *)DXGetArrayData(ti->nArray);
240 
241     if (! ti->neighbors)
242 	return ERROR;
243 
244     if (ti->nTriangles)
245     {
246 	area = (((Interpolator)ti)->max[0] - ((Interpolator)ti)->min[0]) *
247 		    (((Interpolator)ti)->max[1] - ((Interpolator)ti)->min[1]);
248 
249 	area /= ti->nTriangles;
250 
251 	len = sqrt(area);
252 
253 	ti->fieldInterpolator.fuzz *= len;
254     }
255 
256     /*
257      * Create the search grid
258      */
259     ti->grid = _dxfMakeSearchGrid(((Interpolator)ti)->max,
260 			((Interpolator)ti)->min, ti->nTriangles, 2);
261     if (! ti->grid)
262 	return ERROR;
263 
264     tri = (int *)ti->triangles;
265 
266     for (i = 0; i < ti->nTriangles; i++)
267     {
268 	float *points[3], pbuf[6];
269 	register int j;
270 
271 	for (j = 0; j < 3; j++)
272 	    points[j] = (float *)
273 		DXGetArrayEntry(ti->pHandle, *tri++, (Pointer)(pbuf+2*j));
274 
275 	_dxfAddItemToSearchGrid(ti->grid, points, 3, i);
276     }
277 
278     return OK;
279 }
280 
281 Error
_dxfTrisRI2DInterpolator_Delete(TrisRI2DInterpolator ti)282 _dxfTrisRI2DInterpolator_Delete(TrisRI2DInterpolator ti)
283 {
284     _dxfCleanup(ti);
285     return _dxfFieldInterpolator_Delete((FieldInterpolator) ti);
286 }
287 
288 int
_dxfTrisRI2DInterpolator_PrimitiveInterpolate(TrisRI2DInterpolator ti,int * n,float ** points,Pointer * values,int fuzzFlag)289 _dxfTrisRI2DInterpolator_PrimitiveInterpolate(TrisRI2DInterpolator ti,
290 		    int *n, float **points, Pointer *values, int fuzzFlag)
291 {
292     int primNum;
293     TriCoord triCoord;
294     Triangle *tri;
295     int i;
296     int found;
297     Pointer v;
298     float *p;
299     int dep;
300     int itemSize;
301     InvalidComponentHandle icH = ((FieldInterpolator)ti)->invCon;
302     char *dbuf = NULL;
303     Matrix *xform;
304 
305     if (! ti->fieldInterpolator.initialized)
306     {
307 	if (! _dxfInitialize(ti))
308 	{
309 	    _dxfCleanup(ti);
310 	    return ERROR;
311 	}
312 
313 	ti->fieldInterpolator.initialized = 1;
314     }
315 
316     dep = ti->fieldInterpolator.data_dependency;
317     itemSize = DXGetItemSize(ti->dArray);
318 
319     dbuf = (char *)DXAllocate(3*itemSize);
320     if (! dbuf)
321 	return ERROR;
322 
323     if (((FieldInterpolator)ti)->xflag)
324 	xform = &(((FieldInterpolator)ti)->xform);
325     else
326 	xform = NULL;
327 
328     v = *values;
329     p = (float *)*points;
330 
331     /*
332      * For each point in the input, attempt to interpolate the point.
333      * When a point cannot be interpolated, quit.
334      */
335     while(*n != 0)
336     {
337 	float xpt[2];
338 	float *pPtr;
339 
340 	if (xform)
341 	{
342 	    xpt[0] = p[0]*xform->A[0][0] +
343 		     p[1]*xform->A[1][0] +
344 		          xform->b[0];
345 
346 	    xpt[1] = p[0]*xform->A[0][1] +
347 		     p[1]*xform->A[1][1] +
348 		          xform->b[1];
349 	    pPtr = xpt;
350 	}
351 	else
352 	    pPtr = p;
353 
354 
355 	found = -1;
356 
357 	/*
358 	 * Check the hint first, if one exists...
359 	 */
360 	if (ti->hint != -1)
361 	    found = _dxfTrisWalk(ti, pPtr, ti->hint, &triCoord);
362 
363 	/*
364 	 * If it wasn't found,  try the search grid
365 	 */
366 	if (found == -1)
367 	{
368 	    _dxfInitGetSearchGrid(ti->grid, (float *)pPtr);
369 	    while((primNum = _dxfGetNextSearchGrid(ti->grid)) != -1 && found == -1)
370                 found = _dxfTrisSearch(ti,
371 				pPtr, primNum, &triCoord, fuzzFlag);
372 	}
373 
374 	if (found == -1 || (icH && DXIsElementInvalid(icH, found)))
375 	    break;
376 
377 	ti->hint = found;
378 
379 #define INTERPOLATE(type, round)				\
380 {								\
381     type *d0, *d1, *d2, *r;					\
382 								\
383     tri = ti->triangles + found;				\
384     r = (type *)v;						\
385 								\
386     d0 = (type *)DXGetArrayEntry(ti->dHandle, tri->p, 		\
387 				(Pointer)dbuf);			\
388     d1 = (type *)DXGetArrayEntry(ti->dHandle, tri->q, 		\
389 				(Pointer)(dbuf+itemSize));	\
390     d2 = (type *)DXGetArrayEntry(ti->dHandle, tri->r, 		\
391 				(Pointer)(dbuf+2*itemSize));	\
392     for (i = 0; i < ti->nElements; i++)				\
393 	*r++ = (*d0++ * triCoord.p) + 				\
394 		    (*d1++ * triCoord.q) + 			\
395 			    (*d2++ * triCoord.r) + round;	\
396 								\
397     v = (Pointer)r;						\
398 }
399 
400 	if (((FieldInterpolator)ti)->cstData)
401 	{
402 	    memcpy(v, ((FieldInterpolator)ti)->cstData, itemSize);
403 	    v = (Pointer)(((char *)v) + itemSize);
404 	}
405 	else if (dep == DATA_POSITIONS_DEPENDENT)
406 	{
407             Type dataType;
408 
409             if ((dataType = ((Interpolator)ti)->type) == TYPE_FLOAT)
410             {
411                 INTERPOLATE(float, 0.0);
412             }
413             else if (dataType == TYPE_DOUBLE)
414             {
415                 INTERPOLATE(double, 0.0);
416             }
417             else if (dataType == TYPE_INT)
418             {
419                 INTERPOLATE(int, 0.5);
420             }
421             else if (dataType == TYPE_SHORT)
422             {
423                 INTERPOLATE(short, 0.5);
424             }
425             else if (dataType == TYPE_USHORT)
426             {
427                 INTERPOLATE(ushort, 0.5);
428             }
429             else if (dataType == TYPE_UINT)
430             {
431                 INTERPOLATE(uint, 0.5);
432             }
433             else if (dataType == TYPE_BYTE)
434             {
435                 INTERPOLATE(byte, 0.5);
436             }
437             else if (dataType == TYPE_UBYTE)
438             {
439                 INTERPOLATE(ubyte, 0.5);
440             }
441             else
442             {
443                 INTERPOLATE(unsigned char, 0.5);
444             }
445 	}
446 	else
447 	{
448 	    memcpy(v, DXGetArrayEntry(ti->dHandle,
449 						found, dbuf), itemSize);
450 	    v = (Pointer)(((char *)v) + itemSize);
451 	}
452 
453 
454 	/*
455 	 * Only use fuzz on first point
456 	 */
457 	fuzzFlag = FUZZ_OFF;
458 
459 	p += 2;
460 	*n -= 1;
461     }
462 
463     *values = v;
464     *points = (float *)p;
465 
466     return OK;
467 }
468 
469 static int
_dxfCleanup(TrisRI2DInterpolator ti)470 _dxfCleanup(TrisRI2DInterpolator ti)
471 {
472     if (ti->fieldInterpolator.localized)
473     {
474 	if (ti->neighbors)
475 	    DXFreeArrayDataLocal(ti->nArray, (Pointer)ti->neighbors);
476 	if (ti->triangles)
477 	    DXFreeArrayDataLocal(ti->tArray, (Pointer)ti->triangles);
478     }
479 
480     ti->neighbors = NULL;
481     ti->triangles = NULL;
482 
483     if (ti->pHandle)
484     {
485 	DXFreeArrayHandle(ti->pHandle);
486 	ti->pHandle = NULL;
487     }
488 
489     if (ti->dHandle)
490     {
491 	DXFreeArrayHandle(ti->dHandle);
492 	ti->dHandle = NULL;
493     }
494 
495     if (ti->dArray)
496     {
497 	DXDelete((Object)ti->dArray);
498 	ti->dArray = NULL;
499     }
500 
501     if (ti->pArray)
502     {
503 	DXDelete((Object)ti->pArray);
504 	ti->pArray = NULL;
505     }
506 
507     if (ti->nArray)
508     {
509 	DXDelete((Object)ti->nArray);
510 	ti->nArray = NULL;
511     }
512 
513     if (ti->tArray)
514     {
515 	DXDelete((Object)ti->tArray);
516 	ti->tArray = NULL;
517     }
518 
519     if (ti->grid)
520     {
521 	_dxfFreeSearchGrid(ti->grid);
522 	ti->grid = NULL;
523     }
524 
525     return OK;
526 }
527 
528 #define ON_EDGE(q, r, s) \
529     (((q) == 0.0) && ((((r) <= 0.0) && ((s) <= 0.0)) || (((r) >= 0.0) && ((s) >= 0.0))))
530 
_dxftriangular_coords(float * pt,float * p0,float * p1,float * p2,TriCoord * b,float fuzz)531 static int _dxftriangular_coords (float *pt, float *p0,
532 			float *p1, float *p2, TriCoord *b, float fuzz)
533 {
534     double 	a, a0, a1, a2;
535     double	x, x0, x1, x2;
536     double	y, y0, y1, y2;
537 
538     x  = pt[0];    y  = pt[1];
539     x0 = p0[0];    y0 = p0[1];
540     x1 = p1[0];    y1 = p1[1];
541     x2 = p2[0];    y2 = p2[1];
542 
543     a  = (x0*y1 + x1*y2 + x2*y0 - y0*x1 - y1*x2 - y2*x0) / 2.0;
544 
545     a0 = (x *y1 + x1*y2 + x2*y  - y *x1 - y1*x2 - y2*x ) / 2.0;
546     a1 = (x0*y  + x *y2 + x2*y0 - y0*x  - y *x2 - y2*x0) / 2.0;
547     a2 = (x0*y1 + x1*y  + x *y0 - y0*x1 - y1*x  - y *x0) / 2.0;
548 
549     b->p = a0 / a;
550     b->q = a1 / a;
551     b->r = a2 / a;
552 
553     if (ON_EDGE(a0, a1, a2) || ON_EDGE(a1, a2, a0) || ON_EDGE(a2, a0, a1))
554         return 0;
555 
556     if ((b->p >=  0.0 && b->q >=  0.0 && b->r >=  0.0) ||
557 	(b->p <=  0.0 && b->q <=  0.0 && b->r <=  0.0))
558     {
559 	return 0;
560     }
561     else if ((b->p >= -fuzz && b->q >= -fuzz && b->r >= -fuzz) ||
562 	     (b->p <=  fuzz && b->q <=  fuzz && b->r <=  fuzz))
563     {
564 	if (a > 0)
565 	    return 2;
566 	else
567 	    return -2;
568     }
569     else if (a > 0)
570     {
571 	return 1;
572     }
573     else
574     {
575 	return -1;
576     }
577 }
578 
579 static int
_dxftriExit(int side,TriCoord * be,int * face)580 _dxftriExit(int side, TriCoord *be, int *face)
581 {
582     float best;		/* best choice so far */
583     int f;
584 
585     best = 0;
586     f = -1;
587 
588     if (side < 0)
589     {
590 	if (be->p > best)
591 	{
592 	    best = be->p;
593 	    f = 0;
594 	}
595 	if (be->q > best)
596 	{
597 	    best = be->q;
598 	    f = 1;
599 	}
600 	if (be->r > best)
601 	{
602 	    best = be->r;
603 	    f = 2;
604 	}
605     }
606     else
607     {
608 	if (be->p < best)
609 	{
610 	    best = be->p;
611 	    f = 0;
612 	}
613 
614 	if (be->q < best)
615 	{
616 	    best = be->q;
617 	    f = 1;
618 	}
619 	if (be->r < best)
620 	{
621 	    best = be->r;
622 	    f = 2;
623 	}
624     }
625 
626     if (f == -1)
627 	return 0;
628 
629     *face = f;
630     return 1;
631 }
632 
633 static int
_dxfTrisSearch(TrisRI2DInterpolator ti,float * point,int triIndex,TriCoord * triCoord,int fuzzFlag)634 _dxfTrisSearch(TrisRI2DInterpolator ti, float *point,
635 			int triIndex, TriCoord *triCoord, int fuzzFlag)
636 {
637     int  	face;
638     float	*p0, *p1, *p2;
639     int  	side;
640     Triangle	*tri;
641     float	pbuf[6];
642 
643     while (triIndex != -1)
644     {
645 	tri = ti->triangles + triIndex;
646 
647 	p0 = (float *)DXGetArrayEntry(ti->pHandle,
648 					tri->p, (Pointer)(pbuf));
649 	p1 = (float *)DXGetArrayEntry(ti->pHandle,
650 					tri->q, (Pointer)(pbuf+2));
651 	p2 = (float *)DXGetArrayEntry(ti->pHandle,
652 					tri->r, (Pointer)(pbuf+4));
653 
654 	side = _dxftriangular_coords(point, p0, p1, p2, triCoord,
655 						ti->fieldInterpolator.fuzz);
656 
657 	if (side == 0)
658 	{
659 	    return triIndex;
660 	}
661 
662 	else if (fuzzFlag == FUZZ_ON && (side == 2 || side == -2))
663 	{
664 	    if (!_dxftriExit(side, triCoord, &face))
665 	    {
666 		return triIndex;
667 	    }
668 	}
669 
670 	if (!_dxftriExit(side, triCoord, &face))
671 	{
672 	    return -1;
673 	}
674 
675 	triIndex = ((int *)(ti->neighbors))[(triIndex*3) + face];
676     };
677 
678 
679     return -1;
680 }
681 
682 static int
_dxfTrisWalk(TrisRI2DInterpolator ti,float * point,int triIndex,TriCoord * triCoord)683 _dxfTrisWalk(TrisRI2DInterpolator ti, float *point,
684 				int triIndex, TriCoord *triCoord)
685 {
686     int  	face;
687     float	*p0, *p1, *p2;
688     int  	side;
689     Triangle	*tri;
690     float	pbuf[6];
691 
692     while (triIndex != -1)
693     {
694 	tri = ti->triangles + triIndex;
695 
696 	p0 = (float *)DXGetArrayEntry(ti->pHandle,
697 					tri->p, (Pointer)(pbuf));
698 	p1 = (float *)DXGetArrayEntry(ti->pHandle,
699 					tri->q, (Pointer)(pbuf+2));
700 	p2 = (float *)DXGetArrayEntry(ti->pHandle,
701 					tri->r, (Pointer)(pbuf+4));
702 
703 	side = _dxftriangular_coords(point, p0, p1, p2, triCoord,
704 						ti->fieldInterpolator.fuzz);
705 
706 	if (side == 0)
707 	    return triIndex;
708 
709 	if (!_dxftriExit(side, triCoord, &face))
710 	    return -1;
711 
712 	triIndex = ((int *)(ti->neighbors))[(triIndex*3) + face];
713     };
714 
715     return -1;
716 }
717 
718 Object
_dxfTrisRI2DInterpolator_Copy(TrisRI2DInterpolator old,enum _dxd_copy copy)719 _dxfTrisRI2DInterpolator_Copy(TrisRI2DInterpolator old, enum _dxd_copy copy)
720 {
721     TrisRI2DInterpolator new;
722 
723     new = (TrisRI2DInterpolator)
724 	    _dxf_NewObject((struct object_class *)&_dxdtrisri2dinterpolator_class);
725 
726     if (!(_dxf_CopyTrisRI2DInterpolator(new, old, copy)))
727     {
728 	DXDelete((Object)new);
729 	return NULL;
730     }
731     else
732 	return (Object)new;
733 }
734 
735 TrisRI2DInterpolator
_dxf_CopyTrisRI2DInterpolator(TrisRI2DInterpolator new,TrisRI2DInterpolator old,enum _dxd_copy copy)736 _dxf_CopyTrisRI2DInterpolator(TrisRI2DInterpolator new,
737 				TrisRI2DInterpolator old, enum _dxd_copy copy)
738 {
739 
740     if (! _dxf_CopyFieldInterpolator((FieldInterpolator)new,
741 					(FieldInterpolator)old, copy))
742 	return NULL;
743 
744     new->nPoints    = old->nPoints;
745     new->nTriangles = old->nTriangles;
746     new->nElements  = old->nElements;
747     new->hint       = old->hint;
748 
749     if (new->fieldInterpolator.initialized)
750     {
751 	new->pArray    = (Array)DXReference((Object)old->pArray);
752 	new->tArray = (Array)DXReference((Object)old->tArray);
753 	new->dArray      = (Array)DXReference((Object)old->dArray);
754 	new->nArray = (Array)DXReference((Object)old->nArray);
755 
756 	if (new->fieldInterpolator.localized)
757 	{
758 	    new->triangles = (Triangle *)DXGetArrayDataLocal(new->tArray);
759 	    new->neighbors = (Triangle *)DXGetArrayDataLocal(new->nArray);
760 	}
761 	else
762 	{
763 	    new->triangles = (Triangle *)DXGetArrayData(new->tArray);
764 	    new->neighbors = (Triangle *)DXGetArrayData(new->nArray);
765 	}
766 
767 	new->pHandle = DXCreateArrayHandle(new->pArray);
768 	new->dHandle = DXCreateArrayHandle(new->dArray);
769 	if (! new->pHandle || ! new->dHandle)
770 	    return NULL;
771 
772 	new->grid = _dxfCopySearchGrid(old->grid);
773 	if (! new->grid)
774 	    return NULL;
775     }
776     else
777     {
778 	new->pArray    = NULL;
779 	new->tArray    = NULL;
780 	new->dArray    = NULL;
781 	new->nArray    = NULL;
782 	new->pHandle   = NULL;
783 	new->triangles = NULL;
784 	new->dHandle   = NULL;
785 	new->grid      = NULL;
786     }
787 
788     if (DXGetError())
789 	return NULL;
790 
791     return new;
792 }
793 
794 Interpolator
_dxfTrisRI2DInterpolator_LocalizeInterpolator(TrisRI2DInterpolator ti)795 _dxfTrisRI2DInterpolator_LocalizeInterpolator(TrisRI2DInterpolator ti)
796 {
797     if (ti->fieldInterpolator.localized)
798 	return (Interpolator)ti;
799 
800     ti->fieldInterpolator.localized = 1;
801 
802     if (ti->fieldInterpolator.initialized)
803     {
804         ti->triangles = (Triangle *)DXGetArrayDataLocal(ti->tArray);
805         ti->neighbors = (Triangle *)DXGetArrayDataLocal(ti->nArray);
806     }
807 
808     if (DXGetError())
809         return NULL;
810     else
811         return (Interpolator)ti;
812 }
813