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: /usr/people/gresh/code/svs/src/libdx/RCS/autocolor.c,v 5.0 92/11/12
10 09:07:29 svs Exp Locker: gresh
11  */
12 
13 #include <dxconfig.h>
14 
15 #include <stdio.h>
16 #include <dx/dx.h>
17 #include <math.h>
18 #include <string.h>
19 #include "_autocolor.h"
20 
21 typedef struct {
22     Field a_f;
23     Object a_color;
24     Object a_opacity;
25 } arg;
26 
27 typedef struct {
28     Field a_f;
29     int a_setopacities;
30     float a_min;
31     float a_max;
32     int a_surface;
33     float a_opacity;
34     float a_huestart;
35     float a_huerange;
36     float a_saturation;
37     float a_intensity;
38     RGBColor   a_lowerrgb;
39     RGBColor   a_upperrgb;
40 } arg_byte;
41 
42 #define LN(x) log((double)x)
43 #define ABS(a)	((a)>0.0 ? (a) : -(a))
44 
45 static float ValueFcn(float, float, float);
46 static Error AutoColorDelayedObject(Object, int, float, float, int, float,
47                    float, float, float, float, RGBColor,
48                    RGBColor);
49 static Error RecurseToIndividual(Object, float, float, float,
50      	           float, float, float *, float *, Object *, int, RGBColor,
51                    RGBColor);
52 static Error MakeMapAndColor(Object, float, float, float, float,
53 	           float, float *, float *, Object *, int, RGBColor, RGBColor);
54 
55 static Error RemoveOpacities(Object);
56 static Error AutoColorField(Pointer);
57 static Error AutoColorDelayedField(Pointer);
58 static Error GoodField(Field);
59 static int   direction(int);
60 static int   sign(int);
61 
62 #if 0
63 static Error MakeMapAndColorMGrid(Object, float, float, float, float,
64 	           float, float *, float *, Object *, int, RGBColor, RGBColor);
65 #endif
66 
67 
68 /* extern somewhere */
69 extern Object _dxfDXEmptyObject(Object); /* from libdx/component.c */
70 extern Object DXMap(Object, Object, char *, char *); /* from libdx/map.c */
71 extern Array DXScalarConvert(Array); /* from libdx/stats.h */
72 
73 
74 /*
75  * public entry point:
76  *
77  *  parameters are an input group containing at least 1 field with a 'data'
78  *  component, an opacity, intensity, phase, range, saturation, and
79  *  inputmin and inputmax, and delayed (a flag).
80  */
81 
_dxfAutoColor(Object g,float opacity,float intensity,float phase,float range,float saturation,float * inputmin,float * inputmax,Object * outcolorfield,int delayed,RGBColor colormin,RGBColor colormax)82 Group _dxfAutoColor(Object g,  float opacity, float intensity, float phase,
83 	            float range, float saturation, float *inputmin,
84                     float *inputmax, Object *outcolorfield, int delayed,
85                     RGBColor colormin, RGBColor colormax)
86 {
87   Class class;
88   Group g_out;
89 
90 
91   /* quick parm check */
92   if(!g) {
93     DXSetError(ERROR_BAD_PARAMETER, "NULL input");
94     return ERROR;
95   }
96 
97   class = DXGetObjectClass((Object)g);
98   if((class != CLASS_GROUP)  &&  (class != CLASS_FIELD) &&
99      (class != CLASS_XFORM) && (class != CLASS_SCREEN) &&
100      (class !=CLASS_CLIPPED)) {
101     /* data is not a group or a field */
102     DXSetError(ERROR_BAD_PARAMETER,"#10190", "data");
103     return ERROR;
104   }
105 
106   /* duplicate input group */
107   if (!(g_out = (Group)DXCopy((Object)g, COPY_STRUCTURE))) {
108     return ERROR;
109   }
110 
111   if (!(RecurseToIndividual((Object)g_out, opacity, intensity,
112         phase, range, saturation, inputmin, inputmax, outcolorfield,
113         delayed, colormin, colormax)))
114      return ERROR;
115 
116   return (g_out);
117 
118 }
119 
120 
RecurseToIndividual(Object g_out,float opacity,float intensity,float phase,float range,float saturation,float * inputmin,float * inputmax,Object * outcolormap,int delayed,RGBColor colorvecmin,RGBColor colorvecmax)121 static Error RecurseToIndividual(Object g_out, float opacity,
122 	  	  float intensity, float phase, float range, float saturation,
123 	    	  float *inputmin, float *inputmax, Object *outcolormap,
124                   int delayed, RGBColor colorvecmin,
125                   RGBColor colorvecmax)
126 
127 /* this function will recurse to the level of an "individual"; that is,
128    a composite field, a series, a multigrid,
129    or a single field.  Generic groups will thus
130    be broken apart, and each of the individuals in the group will have its
131    own map created. */
132 
133 {
134   int i, empty;
135   Object subo;
136   Group outcolorgroup;
137   Class class, groupclass;
138 
139 
140   if (!(class = DXGetObjectClass(g_out)))
141     return ERROR;
142 
143   if (_dxfDXEmptyObject((Object)g_out))
144     empty = 1;
145   else
146     empty = 0;
147 
148   if (empty) {
149      *outcolormap = (Object)DXNewField();
150      return OK;
151   }
152 
153   switch(class) {
154   case CLASS_GROUP:
155     if (!(groupclass = DXGetGroupClass((Group)g_out)))
156       return ERROR;
157     switch(groupclass) {
158 
159     case CLASS_SERIES:
160     case CLASS_MULTIGRID:
161     case CLASS_COMPOSITEFIELD:
162       if (!(MakeMapAndColor(g_out, opacity, intensity, phase, range,
163                             saturation, inputmin, inputmax, outcolormap,
164                             delayed, colorvecmin, colorvecmax)))
165 	return ERROR;
166       break;
167 
168 
169     /*
170      * this was here when I thought that multigrids could be mixed
171      * volumes and surfaces. They can't.
172     case CLASS_MULTIGRID:
173       if (!(MakeMapAndColorMGrid(g_out, opacity, intensity, phase, range,
174                                  saturation, inputmin, inputmax, outcolormap,
175                                  delayed, colorvecmin, colorvecmax)))
176 	return ERROR;
177       break;
178     */
179 
180     default:
181 
182       /* generic group;  continue recursing  */
183       if (!(outcolorgroup = DXNewGroup()))
184 	return ERROR;
185       for (i=0; (subo=DXGetEnumeratedMember((Group)g_out, i, NULL)); i++){
186 	if (!RecurseToIndividual(subo, opacity, intensity, phase, range,
187 				 saturation, inputmin, inputmax,
188 				 outcolormap,delayed,colorvecmin,
189                                  colorvecmax))
190           return ERROR;
191         if (!(DXSetMember(outcolorgroup, NULL, *outcolormap)))
192 	  return ERROR;
193       }
194       *outcolormap = (Object)outcolorgroup;
195       break;
196     }
197     break;
198   case CLASS_FIELD:
199     if (!(MakeMapAndColor(g_out, opacity, intensity, phase,
200 			  range, saturation, inputmin, inputmax,
201 			  outcolormap, delayed, colorvecmin,
202                           colorvecmax)))
203       return ERROR;
204     break;
205 
206   case CLASS_SCREEN:
207     if (!(DXGetScreenInfo((Screen)g_out, &subo, NULL, NULL)))
208       return ERROR;
209     if (!RecurseToIndividual(subo, opacity, intensity, phase, range,
210 			     saturation, inputmin, inputmax,
211 			     outcolormap, delayed, colorvecmin,
212                              colorvecmax))
213       return ERROR;
214     break;
215   case CLASS_CLIPPED:
216     if (!(DXGetClippedInfo((Clipped)g_out, &subo, NULL)))
217       return ERROR;
218     if (!RecurseToIndividual(subo, opacity, intensity, phase, range,
219 			     saturation, inputmin, inputmax,
220 			     outcolormap, delayed, colorvecmin,
221                              colorvecmax))
222       return ERROR;
223     break;
224   case CLASS_XFORM:
225     if (!(DXGetXformInfo((Xform)g_out, &subo, NULL)))
226       return ERROR;
227     if (!RecurseToIndividual(subo, opacity, intensity, phase, range,
228 			     saturation, inputmin, inputmax,
229 			     outcolormap, delayed, colorvecmin,
230                              colorvecmax))
231       return ERROR;
232     break;
233 
234 
235   default:
236     /* set error here */
237     DXSetError(ERROR_BAD_CLASS,
238                "not a group, field, xform, clipped, or screen object");
239     return ERROR;
240   }
241   return OK;
242 }
243 
244 #if 0
245 static Error MakeMapAndColorMGrid(Object g_out, float opacity_i,
246                              float intensity_i,
247 			     float phase, float range, float saturation,
248 			     float *inputmin, float *inputmax,
249 			     Object *outcolorfield, int delayed,
250                              RGBColor colorvecmin, RGBColor colorvecmax)
251 {
252   float minvalue, maxvalue, min, max;
253   int i;
254   Object subo;
255 
256   /* multigrids may have mixed volumes and surfaces. The purpose of this
257      routine is to use the stats of the entire field to set the colors,
258      but then do the pieces of the multigrid separately */
259 
260 
261     if ((!delayed)||(!inputmin)||(!inputmax)) {
262     /* get data statistices */
263     if (!DXStatistics((Object)g_out, "data", &minvalue,
264 		      &maxvalue, NULL, NULL)) {
265       return ERROR;
266     }
267   }
268 
269   /* if not provided, set the min and max based on the statistics */
270   /* else use the ones given */
271   if (!inputmin) {
272     min = minvalue;
273   }
274   else {
275     min = *inputmin;
276   }
277 
278 
279   if (!inputmax) {
280     max = maxvalue;
281   }
282   else {
283     max = *inputmax;
284   }
285 
286   /* work on the members */
287   for (i=0; subo = DXGetEnumeratedMember((Group)g_out, i, NULL); i++){
288      if (!MakeMapAndColor(subo, opacity_i, intensity_i, phase, range,
289                           saturation, &min, &max,
290                           outcolorfield, delayed, colorvecmin, colorvecmax))
291         return ERROR;
292   }
293   return OK;
294 }
295 #endif
296 
297 
MakeMapAndColor(Object g_out,float opacity_i,float intensity_i,float phase,float range,float saturation,float * inputmin,float * inputmax,Object * outcolorfield,int delayed,RGBColor colorvecmin,RGBColor colorvecmax)298 static Error MakeMapAndColor(Object g_out, float opacity_i,
299                              float intensity_i,
300 			     float phase, float range, float saturation,
301 			     float *inputmin,float *inputmax,
302 			     Object *outcolorfield, int delayed,
303                              RGBColor colorvecmin, RGBColor colorvecmax)
304 
305 {
306   int surface, setopacities, compactopacities, ii;
307   int allblue, count, icount;
308   float huestart, hueend, hue ;
309   float red, blue, green, r, g, b;
310   float givenmin, givenmax, tmp;
311   float dmin, dmax;
312   int datamin, datamax, numentries;
313   float minvalue, maxvalue;
314   float unitopacity=0, unitvalue=0, thickness;
315   float avg, standdev;
316   Field  OpacityField, ColorField, newcolorfield;
317   float *odata_ptr, *opos_ptr, *cpos_ptr;
318   RGBColor *cdata_ptr;
319   Array a_colordata=NULL;
320   Array a_opacitydata=NULL;
321   Array a_colorpositions=NULL;
322   Array a_opacitypositions=NULL;
323   Array a_colorconnections=NULL;
324   Array a_opacityconnections=NULL;
325   Array colorfield_positions=NULL;
326   Array colorfield_connections=NULL;
327   Array colorfield_data=NULL;
328   RGBColor corigin, colorval;
329   float oorigin, opval, dataval, fuzz, opacity, intensity;
330   float *colorfield_posptr, h, s, v;
331   RGBColor *colorfield_dataptr, lowerhsv, upperhsv, lowerrgb, upperrgb;
332   Object bytecolorfield;
333 
334   ColorField = NULL;
335   OpacityField = NULL;
336   newcolorfield = NULL;
337 
338   if (!(_dxfIsVolume((Object)g_out, &surface)))  return ERROR;
339 
340 
341   opacity = opacity_i;
342   intensity = intensity_i;
343   /*  determine the object's maximum thickness, for volume rendering only */
344   if (!(surface))  {
345     if (!(_dxfBoundingBoxDiagonal((Object)g_out,&thickness))) return ERROR;
346   }
347 
348   /* for surfaces, opacity is equal to the user specified value, and
349      the value is set to the user-given "intensity" parameter */
350   if (surface) {
351     if (opacity == 1.0) {
352       /* we need to recursively remove any opacity components */
353       if (!(RemoveOpacities((Object)g_out)))
354 	return ERROR;
355     }
356     if (opacity == -1.0) opacity = 1.0;
357     if (intensity == -1.0) intensity = 1.0;
358   }
359   /* for volumes, the opacity per unit length is set using the
360      user-given value for the opacity of light from the
361      back of the object. The value per unit length is set using
362      the user-given maximum brightness (intensity). */
363   else {
364     if (opacity == -1.0) {
365       unitopacity = -LN(0.5)/thickness;
366       unitvalue = unitopacity/0.5;
367       opacity = 1.0;
368       if (intensity == -1.0) intensity = 1.0;
369     }
370     else if (opacity >= 0.99) {
371       unitopacity = -LN(0.01)/thickness;
372       unitvalue = unitopacity;
373       if (intensity == -1.0) intensity = 1.0;
374     }
375     else if (opacity == 0.0) {
376       unitopacity = 0.0;
377       unitvalue = 1.0/thickness;
378       if (intensity == -1.0) intensity = 1.0;
379     }
380     else {
381       unitopacity = -LN(1.0 - opacity)/(thickness * opacity);
382       if (intensity == -1.0) intensity = 1.0;
383       unitvalue = unitopacity;
384     }
385   }
386 
387 
388 
389   if (surface) {
390     if (!_dxfRGBtoHSV(colorvecmin.r, colorvecmin.g, colorvecmin.b, &h, &s, &v))
391        return ERROR;
392     lowerhsv = DXRGB(h,s,v);
393     if (!_dxfRGBtoHSV(colorvecmax.r, colorvecmax.g, colorvecmax.b, &h, &s, &v))
394        return ERROR;
395     upperhsv = DXRGB(h,s,v);
396     lowerrgb = colorvecmin;
397     upperrgb = colorvecmax;
398   }
399   else {
400     lowerrgb = DXRGB(0.0, 0.0, 0.0);
401     lowerhsv = DXRGB(0.0, 0.0, 0.0);
402     upperrgb = DXRGB(0.0, 0.0, 0.0);
403     upperhsv = DXRGB(0.0, 0.0, 0.0);
404   }
405 
406   if (delayed) {
407     /* Check if it's a valid field for delayed colors */
408     if (!_dxfDelayedOK((Object)g_out))
409       return ERROR;
410   }
411 
412   huestart = phase;
413   hueend = phase + range;
414 
415 
416   if ((!delayed)||(!inputmin)||(!inputmax)) {
417     /* get data statistices */
418     if (!DXStatistics((Object)g_out, "data", &minvalue,
419 		      &maxvalue, &avg, &standdev)) {
420       return ERROR;
421     }
422   }
423   /* if not provided, set the min and max based on the statistics */
424   /* else use the ones given */
425   if (!inputmin)
426     givenmin = minvalue;
427   else {
428     givenmin = *inputmin;
429     if (delayed) minvalue = givenmin;
430   }
431 
432   if (!inputmax)
433     givenmax = maxvalue;
434   else {
435     givenmax = *inputmax;
436     if (delayed) maxvalue = givenmax;
437   }
438 
439   /* check that if delayed, the min and max lie in 0 - 255 */
440   if (delayed) {
441      if (givenmin < 0) {
442          givenmin = 0;
443          DXWarning("AutoColor min clamped to 0 for delayed colors");
444      }
445      if (givenmin > 255) {
446          givenmin = 255;
447          DXWarning("AutoColor min clamped to 255 for delayed colors");
448      }
449      if (givenmax < 0) {
450          givenmax = 0;
451          DXWarning("AutoColor max clamped to 0 for delayed colors");
452      }
453      if (givenmax > 255) {
454          givenmax = 255;
455          DXWarning("AutoColor max clamped to 255 for delayed colors");
456      }
457   }
458 
459   if (givenmin > givenmax) {
460     DXWarning("min is greater than max--exchanging min and max");
461     tmp = givenmin;
462     givenmin = givenmax;
463     givenmax = tmp;
464   }
465 
466   fuzz = 0.0;
467 
468   if (opacity == 1.0)
469     setopacities = 0;
470   else
471     setopacities = 1;
472 
473 
474   /* if it's a surface, we can always make a compact opacities array */
475   /* if it's a volume, we can make a compact opacities array only if
476      the min to max of the data are within the min to max set by the
477      user. Otherwise, there will be opacities of 0.0 in there and
478      a compact array is impossible */
479   if ((!surface)&&((givenmin > minvalue)||(givenmax < maxvalue)))
480     compactopacities = 0;
481   else
482     compactopacities = 1;
483 
484 
485   /* if all the points are outside the range, we can make quick work
486      of this */
487   if ((givenmin > maxvalue)||(givenmax < minvalue)) {
488     count = 1;
489     /* make simple maps of opacity and color */
490     if (surface) {
491       if (setopacities) {
492 	oorigin = opacity;
493 	/*odelta = 0.0;*/
494         if (!(a_opacitydata =
495 	      (Array)DXNewConstantArray(count, (Pointer)&oorigin,
496 					TYPE_FLOAT, CATEGORY_REAL,
497 					0, NULL))) {
498 	  goto cleanup;
499 	}
500       }
501       corigin = lowerrgb;
502       /*cdelta = DXRGB(0.0, 0.0, 0.0);*/
503       if (!(a_colordata =
504 	    (Array)DXNewConstantArray(count, (Pointer)&corigin,
505 				      TYPE_FLOAT, CATEGORY_REAL,
506 				      1, 3))) {
507 	goto cleanup;
508       }
509     }
510     /* else it is a volume */
511     else {
512       if (setopacities) {
513 	oorigin = 0.0;
514 	/*odelta = 0.0;*/
515         if (!(a_opacitydata =
516 	      (Array)DXNewConstantArray(count, (Pointer)&oorigin,
517 					TYPE_FLOAT, CATEGORY_REAL,
518 					0, NULL))) {
519 	  goto cleanup;
520 	}
521       }
522       /* for volumes, out of range points are invisible */
523       corigin = DXRGB(0.0, 0.0, 0.0);
524       /*cdelta = DXRGB(0.0, 0.0, 0.0);*/
525       if (!(a_colordata =
526 	    (Array)DXNewConstantArray(count, (Pointer)&corigin,
527 				      TYPE_FLOAT, CATEGORY_REAL,
528 				      1, 3))) {
529 	goto cleanup;
530       }
531     }
532     if (!(DXCreateTaskGroup())) {
533       goto cleanup;
534     }
535     if (!delayed) {
536       if (!(_dxfAutoColorObject((Object)g_out, (Object)a_colordata,
537 				(Object)a_opacitydata))) {
538 	goto cleanup;
539       }
540     }
541     else {
542       if (!(AutoColorDelayedObject((Object)g_out,
543 				   setopacities, givenmin, givenmax, surface,
544 				   opacity, huestart, range, saturation,
545 				   intensity, lowerrgb, upperrgb))) {
546 	goto cleanup;
547       }
548     }
549     if (!(DXExecuteTaskGroup())) {
550       goto cleanup;
551     }
552     *outcolorfield = (Object)a_colordata;
553     DXDelete((Object)ColorField);
554     DXDelete((Object)OpacityField);
555     if (!surface) {
556       if (!(_dxfSetMultipliers(g_out, unitvalue, unitopacity))) {
557 	goto cleanup;
558       }
559     }
560     goto returnok;
561   }
562   else if ((minvalue==givenmin)&&(minvalue==maxvalue)&&(maxvalue==givenmax)) {
563     count = 1;
564     /* make simple maps of opacity and color */
565     if (surface) {
566       if (setopacities) {
567 	oorigin = opacity;
568 	/*odelta = 0.0;*/
569         if (!(a_opacitydata =
570 	      (Array)DXNewConstantArray(count, (Pointer)&oorigin,
571 					TYPE_FLOAT, CATEGORY_REAL,
572 					0, NULL))) {
573 	  goto cleanup;
574 	}
575       }
576 
577       if (!(_dxfHSVtoRGB(huestart, saturation, intensity,&red,&green,&blue))) {
578 	goto cleanup;
579       }
580 
581       corigin = DXRGB(red, green, blue);
582       /*cdelta = DXRGB(0.0, 0.0, 0.0);*/
583       if (!(a_colordata =
584 	    (Array)DXNewConstantArray(count, (Pointer)&corigin,
585 				      TYPE_FLOAT, CATEGORY_REAL,
586 				      1, 3))) {
587 	goto cleanup;
588       }
589     }
590     /* else it is a volume */
591     else {
592       if (setopacities) {
593 	oorigin = opacity;
594 	/*odelta = 0.0;*/
595         if (!(a_opacitydata =
596 	      (Array)DXNewConstantArray(count, (Pointer)&oorigin,
597 					TYPE_FLOAT, CATEGORY_REAL,
598 					0, NULL))) {
599 	  goto cleanup;
600 	}
601       }
602       if (!(_dxfHSVtoRGB(huestart, saturation, intensity,&red,&green,&blue))) {
603 	goto cleanup;
604       }
605 
606       corigin = DXRGB(red, green, blue);
607       /*cdelta = DXRGB(0.0, 0.0, 0.0);*/
608       if (!(a_colordata =
609 	    (Array)DXNewConstantArray(count, (Pointer)&corigin,
610 				      TYPE_FLOAT, CATEGORY_REAL,
611 				      1, 3))) {
612 	goto cleanup;
613       }
614     }
615     if (!(DXCreateTaskGroup())) {
616       goto cleanup;
617     }
618     if (!delayed) {
619       if (!(_dxfAutoColorObject((Object)g_out, (Object)a_colordata,
620 				(Object)a_opacitydata))) {
621 	goto cleanup;
622       }
623     }
624     else {
625       if (!(AutoColorDelayedObject((Object)g_out,
626 				   setopacities, givenmin, givenmax, surface,
627 				   opacity, huestart, range, saturation,
628 				   intensity, lowerrgb, upperrgb))) {
629 	goto cleanup;
630       }
631     }
632     if (!(DXExecuteTaskGroup())) {
633       goto cleanup;
634     }
635     *outcolorfield = (Object)a_colordata;
636     DXDelete((Object)ColorField);
637     DXDelete((Object)OpacityField);
638     if (!surface) {
639       if (!(_dxfSetMultipliers(g_out, unitvalue, unitopacity))) {
640 	goto cleanup;
641       }
642     }
643     goto returnok;
644   }
645 
646   /* else not all points are out of range */
647   else {
648     if (!delayed) {
649       /* make the maps */
650       if ((setopacities)&&(!(compactopacities))) {
651 	if (!(OpacityField = DXNewField())) {
652 	  goto cleanup;
653 	}
654       }
655       if (!(ColorField = DXNewField())) {
656 	goto cleanup;
657       }
658 
659       /* first make opacity map, if necessary */
660       if (setopacities) {
661 	if (compactopacities) {
662 	  count = 1;
663 	  oorigin = opacity;
664 	  /*odelta = 0.0;*/
665           if (!(a_opacitydata =
666                 (Array)DXNewConstantArray(count, (Pointer)&oorigin,
667 					  TYPE_FLOAT, CATEGORY_REAL,
668 					  0, NULL))) {
669 	    goto cleanup;
670 	  }
671 	}
672 	/* else opacity array is not compact, because some volume points
673 	   are out of range */
674 	else {
675 	  /* figure out the number of items in the array */
676 	  if ((givenmin > minvalue)&&(givenmax < maxvalue))
677 	    count = 6;
678 	  else if (givenmin > minvalue)
679 	    count = 4;
680 	  else if (givenmax < maxvalue)
681 	    count = 4;
682 	  else
683 	    count = 2;
684 
685 	  /* special case */
686 	  if ((minvalue == givenmin)&&(givenmin == givenmax)&&
687 	      (maxvalue == givenmax)){
688             count = 2;
689             allblue = 1;
690 	  }
691 	  else
692             allblue = 0;
693 
694 
695 	  /* create the array */
696 	  if (!(a_opacitydata = DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 1, 1)))
697 	    goto cleanup;
698           if (!DXAddArrayData(a_opacitydata,0,count,NULL))
699             goto cleanup;
700           odata_ptr=(float *)DXGetArrayData(a_opacitydata);
701 
702 	  if (!(a_opacitypositions =
703 		DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 1, 1)))
704 	    goto cleanup;
705           if (!DXAddArrayData(a_opacitypositions,0,count,NULL))
706             goto cleanup;
707           opos_ptr=(float *)DXGetArrayData(a_opacitypositions);
708 
709 
710 	  if (!(a_opacityconnections =  DXMakeGridConnectionsV(1, &count)))
711 	    goto cleanup;
712 
713 
714 	  /* now put the constructed arrays in the maps */
715 	  if (!(DXSetComponentValue((Field)OpacityField, "data",
716 				    (Object)a_opacitydata)))
717 	    goto cleanup;
718 	  a_opacitydata=NULL;
719 
720 
721 	  if (!(DXSetComponentValue((Field)OpacityField, "positions",
722 				    (Object)a_opacitypositions)))
723 	    goto cleanup;
724 	  a_opacitypositions=NULL;
725 
726 
727 	  if (!(DXSetComponentValue((Field)OpacityField, "connections",
728 				    (Object)a_opacityconnections)))
729 	    goto cleanup;
730 	  a_opacityconnections=NULL;
731 
732 
733 	  if (!(DXSetComponentAttribute((Field)OpacityField, "data", "dep",
734 					(Object)DXNewString("positions"))))
735 	    goto cleanup;
736 
737 
738 	  if (!(DXSetComponentAttribute((Field)OpacityField,"connections",
739 					"ref",
740 					(Object)DXNewString("positions"))))
741 	    goto cleanup;
742 
743 
744 	  if (!(DXSetComponentAttribute((Field)OpacityField,"connections",
745 					"element type",
746 					(Object)DXNewString("lines")) ))
747 	    goto cleanup;
748 
749 
750 	  /* now add the data to the arrays */
751 	  icount = 0;
752 	  /* first deal with the first two invisible points, if necessary */
753 	  if (givenmin > minvalue) {
754 	    opval = 0.0;
755 	    dataval = minvalue - fuzz;
756 
757             odata_ptr[icount]=opval;
758             opos_ptr[icount]=dataval;
759 
760 	    icount++;
761 	    dataval = givenmin - fuzz;
762 
763             odata_ptr[icount]=opval;
764             opos_ptr[icount]=dataval;
765 
766 	    icount++;
767 	  }
768 
769 
770 	  /* now do the part between givenmin and givenmax*/
771 	  opval = opacity;
772 	  dataval = givenmin-fuzz;
773 
774           odata_ptr[icount]=opval;
775           opos_ptr[icount]=dataval;
776 
777           icount++;
778 	  dataval = givenmax+fuzz;
779 
780           odata_ptr[icount]=opval;
781           opos_ptr[icount]=dataval;
782 
783           icount++;
784 
785 
786 	  /* now deal with the last two invisible points, if necessary */
787 	  if (givenmax < maxvalue) {
788 	    opval = 0.0;
789 	    dataval = givenmax + 2*fuzz;
790 
791             odata_ptr[icount]=opval;
792             opos_ptr[icount]=dataval;
793 
794 	    icount ++;
795 	    dataval = maxvalue + fuzz;
796 
797             odata_ptr[icount]=opval;
798             opos_ptr[icount]=dataval;
799 
800 	    icount++;
801 	  }
802 	}
803       }
804 
805       /* now do colors */
806       /* figure out the number of items in the array */
807       if ((givenmin > minvalue)&&(givenmax < maxvalue))
808 	count = 6;
809       else if (givenmin > minvalue)
810 	count = 4;
811       else if (givenmax < maxvalue)
812 	count = 4;
813       else
814 	count = 2;
815 
816       /* special case */
817       if ((minvalue==givenmin)&&(givenmin == givenmax)&&(maxvalue==givenmax)) {
818 	count = 2;
819 	allblue = 1;
820       }
821       else
822 	allblue = 0;
823 
824 
825       /* create the arrays */
826       if (!(a_colordata = DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 1, 3)))
827 	goto cleanup;
828       if (!DXAddArrayData(a_colordata,0,count,NULL))
829         goto cleanup;
830       cdata_ptr=(RGBColor *)DXGetArrayData(a_colordata);
831 
832 
833       if (!(a_colorpositions =
834 	    DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 1, 1)))
835 	goto cleanup;
836       if (!DXAddArrayData(a_colorpositions,0,count,NULL))
837         goto cleanup;
838       cpos_ptr = (float *)DXGetArrayData(a_colorpositions);
839 
840       if (!(a_colorconnections =  DXMakeGridConnectionsV(1, &count)))
841 	goto cleanup;
842 
843 
844       /* add to the field */
845       if (!(DXSetComponentValue((Field)ColorField, "data",
846 				(Object)a_colordata)))
847 	goto cleanup;
848       a_colordata=NULL;
849 
850 
851       if (!(DXSetComponentValue((Field)ColorField, "positions",
852 				(Object)a_colorpositions)))
853 	goto cleanup;
854       a_colorpositions=NULL;
855 
856 
857       if (!(DXSetComponentValue((Field)ColorField, "connections",
858 				(Object)a_colorconnections)))
859 	goto cleanup;
860       a_colorconnections=NULL;
861 
862 
863       if (!(DXSetComponentAttribute((Field)ColorField,"data", "dep",
864                                     (Object)DXNewString("positions")) ))
865 	goto cleanup;
866 
867       if (!(DXSetComponentAttribute((Field)ColorField,"connections",
868 				    "ref",
869 				    (Object)DXNewString("positions")) ))
870 	goto cleanup;
871 
872       if (!(DXSetComponentAttribute((Field)ColorField,"connections",
873 				    "element type",
874 				    (Object)DXNewString("lines")) ))
875 	goto cleanup;
876 
877 
878       /* now add the data to the arrays */
879       icount = 0;
880       /* first deal with the first two invisible points, if necessary */
881       if (givenmin > minvalue) {
882 	dataval = minvalue - fuzz;
883 
884         cdata_ptr[icount]=lowerhsv;
885         cpos_ptr[icount]=dataval;
886 
887 	icount++;
888 	dataval = givenmin - 2*fuzz;
889 
890         cdata_ptr[icount]=lowerhsv;
891         cpos_ptr[icount]=dataval;
892 
893 	icount++;
894       }
895 
896 
897       /* now do the part between givenmin and givenmax*/
898       hue = huestart;
899       dataval = givenmin - fuzz;
900       colorval = DXRGB(hue, saturation, intensity);
901 
902       cdata_ptr[icount]=colorval;
903       cpos_ptr[icount]=dataval;
904 
905       icount++;
906       if (!(allblue)) hue = hueend;
907       else hue = huestart;
908       dataval = givenmax + fuzz;
909       colorval = DXRGB(hue, saturation, intensity);
910 
911 
912       cdata_ptr[icount]=colorval;
913       cpos_ptr[icount]=dataval;
914 
915       icount++;
916 
917       /* now deal with the last two invisible points, if necessary */
918       if (givenmax < maxvalue) {
919 	dataval = givenmax + 2*fuzz;
920 
921         cdata_ptr[icount]=upperhsv;
922         cpos_ptr[icount]=dataval;
923 
924 	icount ++;
925 	dataval = maxvalue + fuzz;
926 
927         cdata_ptr[icount]=upperhsv;
928         cpos_ptr[icount]=dataval;
929 
930 	icount ++;
931       }
932 
933 
934       if (ColorField) {
935 	if (!(DXEndField(ColorField))) {
936 	  goto cleanup;
937 	}
938       }
939       if (OpacityField) {
940 	if (!(DXEndField(OpacityField))) {
941 	  goto cleanup;
942 	}
943       }
944 
945       /* now convert the created color map to an rgb map */
946       if (!(newcolorfield = _dxfMakeRGBColorMap(ColorField))) {
947 	goto cleanup;
948       }
949 
950       if (!(DXCreateTaskGroup())) {
951 	goto cleanup;
952       }
953       /* if compact opacities, just pass the array */
954       if (compactopacities) {
955 	if (!(_dxfAutoColorObject((Object)g_out,
956 				  (Object)newcolorfield,
957 				  (Object)a_opacitydata))) {
958 	  goto cleanup;
959 	}
960       }
961       /* else, pass the opacity field */
962       else {
963 	if (!(_dxfAutoColorObject((Object)g_out,
964 				  (Object)newcolorfield,
965 				  (Object)OpacityField))) {
966 	  goto cleanup;
967 	}
968       }
969       if (!(DXExecuteTaskGroup())) {
970 	goto cleanup;
971       }
972 
973       DXDelete((Object)ColorField);
974       DXDelete((Object)OpacityField);
975       *outcolorfield = (Object)newcolorfield;
976       if (!surface) {
977 	if (!(_dxfSetMultipliers(g_out, unitvalue, unitopacity))) {
978 	  goto cleanup;
979 	}
980       }
981       if (compactopacities) {
982          DXDelete((Object)a_opacitydata);
983          a_opacitydata = NULL;
984       }
985       goto returnok;
986     }
987     /* else delayed */
988     else {
989       /* create outcolorfield */
990       bytecolorfield = (Object)DXNewField();
991       colorfield_positions = (Array)DXNewArray(TYPE_FLOAT,CATEGORY_REAL,1,1);
992       /* need the actual min and max of the field */
993       if (!DXStatistics((Object)g_out, "data", &dmin, &dmax, NULL, NULL))
994         goto cleanup;
995       datamin=dmin;
996       datamax=dmax;
997       /* for now, set to 0-255 */
998       datamin=0;
999       datamax=255;
1000       numentries = datamax - datamin + 1;
1001       colorfield_connections = (Array)DXNewPathArray(numentries);
1002       colorfield_data = (Array)DXNewArray(TYPE_FLOAT,CATEGORY_REAL,1,3);
1003 
1004       if (!(DXAddArrayData(colorfield_positions, 0, numentries, NULL)))
1005         goto cleanup;
1006 
1007       if (!(DXAddArrayData(colorfield_data, 0, numentries, NULL)))
1008         goto cleanup;
1009 
1010       colorfield_posptr = (float *)DXGetArrayData(colorfield_positions);
1011       colorfield_dataptr = (RGBColor *)DXGetArrayData(colorfield_data);
1012 
1013       if (!(DXSetComponentValue((Field)bytecolorfield,"positions",
1014 				(Object)colorfield_positions)))
1015         goto cleanup;
1016       colorfield_positions=NULL;
1017 
1018 
1019       if (!(DXSetComponentValue((Field)bytecolorfield,"connections",
1020 				(Object)colorfield_connections)))
1021         goto cleanup;
1022       colorfield_connections=NULL;
1023 
1024 
1025       if (!(DXSetComponentValue((Field)bytecolorfield,"data",
1026 				(Object)colorfield_data)))
1027         goto cleanup;
1028       colorfield_data=NULL;
1029 
1030 
1031       if (!(DXSetComponentAttribute((Field)bytecolorfield, "data","dep",
1032 				    (Object)DXNewString("positions"))))
1033 	goto cleanup;
1034 
1035 
1036       if (!(DXSetComponentAttribute((Field)bytecolorfield, "connections",
1037 				    "ref",
1038 				    (Object)DXNewString("positions"))))
1039 	goto cleanup;
1040 
1041 
1042       if (!(DXSetComponentAttribute((Field)bytecolorfield,
1043 					"connections",
1044 					"element type",
1045 					(Object)DXNewString("lines"))))
1046 	goto cleanup;
1047 
1048 
1049       for (ii=datamin; ii<givenmin; ii++) {
1050 	colorfield_posptr[ii-datamin] = (float)ii;
1051         colorfield_dataptr[ii-datamin] = lowerrgb;
1052       }
1053       for (ii=givenmin; ii<=givenmax; ii++) {
1054 	colorfield_posptr[ii-datamin] = (float)ii;
1055 	hue = huestart + ((ii-givenmin)/(givenmax-givenmin))*range;
1056 	if (!_dxfHSVtoRGB(hue,saturation,intensity,&r,&g,&b))
1057 	  goto cleanup;
1058 	colorfield_dataptr[ii-datamin] =  DXRGB(r, g, b);
1059       }
1060       for (ii=givenmax+1; ii<=datamax; ii++) {
1061 	colorfield_posptr[ii-datamin] = (float)ii;
1062 	colorfield_dataptr[ii-datamin] =  upperrgb;
1063       }
1064 
1065       *outcolorfield=bytecolorfield;
1066 
1067 
1068       if (!(DXCreateTaskGroup())) {
1069 	goto cleanup;
1070       }
1071       if (!(AutoColorDelayedObject((Object)g_out,
1072 			 	setopacities, givenmin, givenmax, surface,
1073 				opacity, huestart, range, saturation,
1074                                 intensity, lowerrgb, upperrgb)))
1075 	goto cleanup;
1076 
1077       if (!(DXExecuteTaskGroup()))
1078 	goto cleanup;
1079 
1080       if (!surface) {
1081 	if (!(_dxfSetMultipliers(g_out, unitvalue, unitopacity)))
1082 	  goto cleanup;
1083       }
1084       goto returnok;
1085     }
1086   }
1087 
1088  returnok:
1089    DXDelete((Object)a_opacitydata);
1090    return OK;
1091 
1092  cleanup: {
1093    DXDelete((Object)ColorField);
1094    DXDelete((Object)OpacityField);
1095    DXDelete((Object)a_colordata);
1096    DXDelete((Object)a_colorpositions);
1097    DXDelete((Object)a_colorconnections);
1098    DXDelete((Object)a_opacitydata);
1099    DXDelete((Object)a_opacitypositions);
1100    DXDelete((Object)a_opacityconnections);
1101    DXDelete((Object)colorfield_data);
1102    DXDelete((Object)colorfield_positions);
1103    DXDelete((Object)colorfield_connections);
1104    return ERROR;
1105  }
1106 }
1107 
1108 
1109 
RemoveOpacities(Object o)1110 static Error RemoveOpacities(Object o)
1111 {
1112   int i;
1113   Object subo;
1114 
1115 
1116   switch(DXGetObjectClass(o)) {
1117   case CLASS_GROUP:
1118     /* get children and call RemoveOpacities(subo); */
1119     for (i=0; (subo=DXGetEnumeratedMember((Group)o, i, NULL)); i++){
1120       if (!RemoveOpacities(subo))
1121 	return ERROR;
1122     }
1123     break;
1124   case CLASS_FIELD:
1125     if (DXGetComponentValue((Field)o,"opacities"))
1126        DXDeleteComponent((Field)o,"opacities");
1127     break;
1128   default:
1129     /* set error here */
1130     DXSetError(ERROR_BAD_CLASS,"not a group or field");
1131     return ERROR;
1132   }
1133   return OK;
1134 }
1135 
1136 
_dxfAutoColorObject(Object o,Object Color,Object Opacity)1137 Error _dxfAutoColorObject(Object o, Object Color, Object Opacity)
1138 {
1139   int i;
1140   Object subo;
1141   arg a;
1142 
1143 
1144   switch(DXGetObjectClass(o)) {
1145   case CLASS_XFORM:
1146     if (!DXGetXformInfo((Xform)o, &subo, NULL))
1147 	return ERROR;
1148     if (!_dxfAutoColorObject(subo, Color, Opacity))
1149 	return ERROR;
1150     break;
1151   case CLASS_CLIPPED:
1152     if (!DXGetClippedInfo((Clipped)o, &subo, NULL))
1153 	return ERROR;
1154     if (!_dxfAutoColorObject(subo, Color, Opacity))
1155 	return ERROR;
1156     break;
1157   case CLASS_SCREEN:
1158     if (!DXGetScreenInfo((Screen)o, &subo, NULL, NULL))
1159 	return ERROR;
1160     if (!_dxfAutoColorObject(subo, Color, Opacity))
1161 	return ERROR;
1162     break;
1163   case CLASS_GROUP:
1164     /* get children and call AutoColorObject(subo); */
1165     for (i=0; (subo=DXGetEnumeratedMember((Group)o, i, NULL)); i++){
1166       if (!_dxfAutoColorObject(subo, Color, Opacity))
1167 	return ERROR;
1168     }
1169     break;
1170   case CLASS_FIELD:
1171     a.a_f = (Field)o;
1172     a.a_color = Color;
1173     a.a_opacity = Opacity;
1174 
1175     /* and schedule autocolorfield to be called */
1176     if (!(DXAddTask(AutoColorField, (Pointer)&a, sizeof(a), 1.0))) {
1177        return ERROR;
1178     }
1179     break;
1180   default:
1181     /* set error here */
1182     DXSetError(ERROR_BAD_CLASS,"not a group or field");
1183     return ERROR;
1184   }
1185   return OK;
1186 }
1187 
1188 
1189 
AutoColorField(Pointer ptr)1190 static Error AutoColorField(Pointer ptr)
1191 
1192 
1193 {
1194   Field f, savedfield;
1195   Object ColorMap, OpacityMap;
1196   Interpolator i;
1197   int scalar, floatflag;
1198   Array newdata, olddata;
1199   arg *a;
1200 
1201   a = (arg *)ptr;
1202   f = a->a_f;
1203   ColorMap = a->a_color;
1204   OpacityMap = a->a_opacity;
1205   newdata = NULL;
1206   olddata = NULL;
1207   savedfield = NULL;
1208 
1209   /* if it's an empty field, or a field without data, ignore it */
1210   if (!(GoodField(f))) return OK;
1211 
1212   /* if it's not a good data field, return on ERROR */
1213   if (!(_dxfScalarField(f, &scalar))) return ERROR;
1214 
1215   /* because a map's positions represent the data values, and because
1216      positions are float, I need to convert the data array to float to
1217      use map to do the color mapping */
1218   if (!(_dxfFloatField((Object)f,&floatflag))) return ERROR;
1219 
1220   if ((!scalar)||(!floatflag)) {
1221      /* only bother to convert the data if you need to, that is, either
1222       * opacity map or color map is a real map, not just a vector */
1223      if (((OpacityMap)&&(DXGetObjectClass(OpacityMap)!=CLASS_ARRAY)) ||
1224            ((ColorMap)&&(DXGetObjectClass(ColorMap)!=CLASS_ARRAY))) {
1225         /* copy the field and make a new data component for map to work on */
1226         savedfield = (Field)DXCopy((Object)f,COPY_STRUCTURE);
1227         if (!(olddata = (Array)DXGetComponentValue((Field)f, "data"))) {
1228             return ERROR;
1229         }
1230         if (!(newdata = DXScalarConvert(olddata))) {
1231            return ERROR;
1232         }
1233         if (!(DXSetComponentValue((Field)f, "data", (Object)newdata)))
1234             return ERROR;
1235      }
1236   }
1237 
1238   if (OpacityMap) {
1239 
1240     /* don't make the interpolator if it's a simple vector for the map */
1241     if (DXGetObjectClass((Object)OpacityMap) == CLASS_ARRAY)
1242     {
1243       /*f = (Field)DXMap((Object)f, (Object)OpacityMap, "data", "opacities");*/
1244       if (!DXMap((Object)f, (Object)OpacityMap, "data", "opacities"))
1245       {
1246 	goto error;
1247       }
1248     }
1249     else
1250     {
1251       if (! DXMapCheck((Object)f, OpacityMap, "data", NULL, NULL, NULL, NULL))
1252       {
1253 	goto error;
1254       }
1255 
1256       i = DXNewInterpolator((Object)OpacityMap, INTERP_INIT_IMMEDIATE, 0.0);
1257       if (! i)
1258          goto error;
1259 
1260       /*f = (Field)DXMap((Object)f, (Object)i, "data", "opacities");*/
1261       if (!DXMap((Object)f, (Object)i, "data", "opacities"))
1262       {
1263 	goto error;
1264       }
1265 
1266       DXDelete((Object)i);
1267     }
1268   }
1269 
1270   if (ColorMap) {
1271 
1272     /* don't make the interpolator if it's a simple vector for the map */
1273     if (DXGetObjectClass((Object)ColorMap) == CLASS_ARRAY)
1274     {
1275       /*f = (Field)DXMap((Object)f, (Object)ColorMap, "data", "colors");*/
1276       if (!DXMap((Object)f, (Object)ColorMap, "data", "colors"))
1277       {
1278 	goto error;
1279       }
1280     }
1281     else
1282     {
1283       if (! DXMapCheck((Object)f, ColorMap, "data",  NULL, NULL, NULL, NULL))
1284       {
1285 	goto error;
1286       }
1287 
1288       i = DXNewInterpolator((Object)ColorMap, INTERP_INIT_IMMEDIATE, 0.0);
1289       if (! i)
1290 	goto error;
1291 
1292       /*f = (Field)DXMap((Object)f, (Object)i, "data", "colors"); */
1293       if (!DXMap((Object)f, (Object)i, "data", "colors"))
1294       {
1295 	goto error;
1296       }
1297 
1298       DXDelete((Object)i);
1299     }
1300   }
1301 
1302   /* now remove any "front colors" or "back colors" components which
1303      may be hanging around */
1304      if (DXGetComponentValue((Field)f,"front colors"))
1305          if( !(DXDeleteComponent((Field)f, "front colors"))) goto error;
1306      if (DXGetComponentValue((Field)f,"back colors"))
1307          if (!(DXDeleteComponent((Field)f, "back colors"))) goto error;
1308 
1309   if (savedfield) {
1310      /* we need to get the data from savedfield and put it in f, then
1311       * delete savedfield */
1312       f =
1313 	  (Field)DXReplace((Object)f, (Object)savedfield, "data", "data");
1314       if (!f) {
1315 	     DXSetError(ERROR_INTERNAL,"can't replace data in field");
1316 	     goto error;
1317       }
1318       DXDelete((Object)savedfield);
1319   }
1320 
1321   DXDeleteComponent(f,"color map");
1322   if (OpacityMap) DXDeleteComponent(f,"opacity map");
1323   if (!DXEndField(f))
1324      goto error;
1325   return OK;
1326 
1327   error:
1328     return ERROR;
1329 }
1330 
1331 
AutoColorDelayedObject(Object o,int setopacities,float givenmin,float givenmax,int surface,float opacity,float huestart,float range,float saturation,float intensity,RGBColor lowerrgb,RGBColor upperrgb)1332 static Error AutoColorDelayedObject(Object o, int setopacities,
1333                                  float givenmin, float givenmax, int surface,
1334 				 float opacity, float huestart, float range,
1335                                  float saturation, float intensity,
1336                                  RGBColor lowerrgb, RGBColor upperrgb)
1337 {
1338   int i;
1339   Object subo;
1340   arg_byte a;
1341 
1342 
1343   switch(DXGetObjectClass(o)) {
1344   case CLASS_GROUP:
1345     /* get children and call AutoColorObject(subo); */
1346     for (i=0; (subo=DXGetEnumeratedMember((Group)o, i, NULL)); i++){
1347       if (!AutoColorDelayedObject(subo, setopacities, givenmin, givenmax,
1348                                   surface, opacity, huestart, range,
1349                                   saturation, intensity, lowerrgb, upperrgb))
1350 	return ERROR;
1351     }
1352     break;
1353   case CLASS_FIELD:
1354     a.a_f = (Field)o;
1355     a.a_setopacities = setopacities;
1356     a.a_min = givenmin;
1357     a.a_max = givenmax;
1358     a.a_surface = surface;
1359     a.a_opacity = opacity;
1360     a.a_huestart = huestart;
1361     a.a_huerange = range;
1362     a.a_saturation = saturation;
1363     a.a_intensity = intensity;
1364     a.a_lowerrgb = lowerrgb;
1365     a.a_upperrgb = upperrgb;
1366 
1367     /* and schedule autocolorfield to be called */
1368     if (!(DXAddTask(AutoColorDelayedField, (Pointer)&a, sizeof(a), 1.0))) {
1369        return ERROR;
1370     }
1371     break;
1372   default:
1373     /* set error here */
1374     DXSetError(ERROR_BAD_CLASS,"not a group or field");
1375     return ERROR;
1376   }
1377   return OK;
1378 }
1379 
1380 
1381 
AutoColorDelayedField(Pointer ptr)1382 static Error AutoColorDelayedField(Pointer ptr)
1383 
1384 
1385 {
1386   Field f;
1387   int scalar, i, setopacities, surface,numentries;
1388   float givenmin, givenmax,opacity,r,g,b;
1389   float *opacityarray=NULL, huestart, range,saturation,intensity,hue;
1390   float dmin, dmax;
1391   int datamin, datamax;
1392   RGBColor *colorarray=NULL;
1393   RGBColor lowerrgb, upperrgb;
1394   Array a_data;
1395   Array deferredcolors, deferredopacities;
1396   arg_byte *a;
1397 
1398   a = (arg_byte *)ptr;
1399   f = a->a_f;
1400   setopacities = a->a_setopacities;
1401   surface = a->a_surface;
1402   opacity = a->a_opacity;
1403   givenmin = a->a_min;
1404   givenmax = a->a_max;
1405   huestart = a->a_huestart;
1406   range = a->a_huerange;
1407   saturation = a->a_saturation;
1408   intensity = a->a_intensity;
1409   lowerrgb = a->a_lowerrgb;
1410   upperrgb = a->a_upperrgb;
1411   deferredcolors = NULL;
1412   deferredopacities = NULL;
1413 
1414   /* if it's an empty field, or a field without data, ignore it */
1415   if (!(GoodField(f))) return OK;
1416 
1417   a_data = (Array)DXGetComponentValue((Field)f,"data");
1418   if (!a_data) {
1419     /* "missing data component" */
1420     DXSetError(ERROR_MISSING_DATA,"#10240","data");
1421     return ERROR;
1422   }
1423   /* need the actual min and max of the field */
1424   if (!DXStatistics((Object)f, "data", &dmin, &dmax, NULL, NULL)) {
1425     return ERROR;
1426   }
1427   datamin=dmin;
1428   datamax=dmax;
1429   /* for now, set to 0-255 */
1430   datamin=0;
1431   datamax=255;
1432   numentries = datamax - datamin + 1;
1433 
1434   /* if it's not a good data field, return on ERROR */
1435   if (!(_dxfScalarField(f, &scalar))) return ERROR;
1436 
1437   /* make the maps */
1438   /* first make opacity map, if necessary */
1439   if (setopacities) {
1440     /* need to figure out how many entries I need */
1441     opacityarray = DXAllocateLocal(numentries*sizeof(float));
1442     if (!opacityarray) {
1443       DXAddMessage("cannot allocate delayed opacity map with %d entries",
1444 		   numentries);
1445       goto error;
1446     }
1447     if (surface) {
1448       for(i=0; i<=numentries; i++) {
1449 	opacityarray[i]=opacity;
1450       }
1451     }
1452     else {
1453       for (i=datamin; i< givenmin; i++) {
1454 	opacityarray[i-datamin]=0;
1455       }
1456       for (i=givenmin; i<=givenmax; i++) {
1457 	opacityarray[i-datamin]=opacity;
1458       }
1459       for (i=givenmax+1; i<= datamax; i++) {
1460 	opacityarray[i-datamin]=0;
1461       }
1462     }
1463   }
1464   /* now do colors */
1465   colorarray = DXAllocateLocal(numentries*sizeof(RGBColor));
1466   if (!colorarray) {
1467     DXAddMessage("cannot allocate delayed color map with %d entries",
1468 		 numentries);
1469     goto error;
1470   }
1471   for (i=datamin; i< givenmin; i++) {
1472     if (surface)
1473       colorarray[i-datamin]=lowerrgb;
1474     else
1475       colorarray[i-datamin]=DXRGB(0.0,0.0,0.0);
1476   }
1477   /* now do the part between givenmin and givenmax*/
1478   for (i=givenmin; i<= givenmax; i++) {
1479     if (givenmin==givenmax) hue = huestart;
1480     else hue =huestart + (i-givenmin)/(givenmax-givenmin)*range;
1481     if (!_dxfHSVtoRGB(hue,saturation,intensity,&r,&g,&b))
1482       goto error;
1483     colorarray[i-datamin]=DXRGB(r,g,b);
1484   }
1485   for (i=givenmax+1; i<= datamax; i++) {
1486     if (surface)
1487       colorarray[i-datamin]=upperrgb;
1488     else
1489       colorarray[i-datamin]=DXRGB(0.0,0.0,0.0);
1490   }
1491 
1492 
1493   if (!(deferredcolors = (Array)DXNewArray(TYPE_FLOAT,
1494 					   CATEGORY_REAL,  1, 3)))
1495     goto error;
1496 
1497   if (!(DXAddArrayData(deferredcolors,0,numentries,(Pointer)colorarray)))
1498     goto error;
1499 
1500   if (!(DXSetComponentValue((Field)f, "color map",
1501 			    (Object)deferredcolors)))
1502     goto error;
1503 
1504   /* need to delete the old colors component first. This is because
1505    * it may have an incorrect attribute which will screw up (believe me
1506    * it will) both the new colors component AND the data component, since
1507    * they are now the same */
1508   if (!(DXSetComponentValue((Field)f, "colors", NULL)))
1509     goto error;
1510   if (!(DXSetComponentValue((Field)f, "colors", (Object)a_data)))
1511     goto error;
1512 
1513   if (setopacities) {
1514     if (!(deferredopacities = (Array)DXNewArray(TYPE_FLOAT,
1515                                                 CATEGORY_REAL,0,NULL)))
1516       goto error;
1517 
1518     if (!(DXAddArrayData(deferredopacities,0,numentries,
1519 			 (Pointer)opacityarray)))
1520 	goto error;
1521 
1522     if (!(DXSetComponentValue((Field)f, "opacity map",
1523 			      (Object)deferredopacities)))
1524       goto error;
1525 
1526     if (!(DXSetComponentValue((Field)f, "opacities", (Object)a_data)))
1527 	goto error;
1528 
1529   }
1530 
1531 
1532   DXEndField(f);
1533   DXFree((Pointer)colorarray);
1534   return OK;
1535 
1536  error:
1537   DXDelete((Object)deferredopacities);
1538   DXDelete((Object)deferredcolors);
1539   DXFree((Pointer)opacityarray);
1540   DXFree((Pointer)colorarray);
1541   return ERROR;
1542 }
1543 
1544 
GoodField(Field f)1545 static Error GoodField(Field f)
1546 {
1547   if (DXEmptyField(f))
1548      return ERROR;
1549   if (!(DXGetComponentValue(f, "data")))
1550      return ERROR;
1551   return OK;
1552 }
1553 
1554 
1555 
_dxfIsTextField(Field f,int * text)1556 Error _dxfIsTextField(Field f, int *text)
1557 {
1558   Array a;
1559   Type type;
1560 
1561   if (!(a = (Array)DXGetComponentValue(f,"data"))) {
1562     *text = 0;
1563     return OK;
1564   }
1565   if (!DXGetArrayInfo((Array)a, NULL, &type, NULL, NULL, NULL))
1566     return ERROR;
1567   if (type == TYPE_STRING)
1568     *text=1;
1569   else
1570     *text=0;
1571   return OK;
1572 }
1573 
1574 
_dxfScalarField(Field f,int * scalar)1575 Error _dxfScalarField(Field f, int *scalar)
1576 {
1577   Array a;
1578   Type type;
1579   Category category;
1580   int rank, shape;
1581 
1582 
1583   if (!(a = (Array)(DXGetComponentValue(f, "data")))) {
1584      *scalar=1;
1585      return OK;
1586   }
1587   if (!(DXGetArrayInfo((Array)a, NULL, &type, &category, &rank, &shape))) {
1588      DXSetError(ERROR_BAD_PARAMETER,"bad data component");
1589      return ERROR;
1590   }
1591   if (!(category == CATEGORY_REAL)) {
1592      DXSetError(ERROR_BAD_PARAMETER,"non-real data field");
1593      return ERROR;
1594   }
1595   if ((rank == 0) || ((rank == 1)&&(shape == 1))) {
1596      *scalar = 1;
1597      return OK;
1598   }
1599   if (rank>=1) {
1600      *scalar = 0;
1601      return OK;
1602   }
1603   /*
1604   DXSetError(ERROR_BAD_PARAMETER,"data field not scalar or vector");
1605   return ERROR;
1606   */
1607   return OK;
1608 }
1609 
1610 
1611 
_dxfFloatField(Object f,int * floatflag)1612 Error _dxfFloatField(Object f, int *floatflag)
1613 {
1614   Array a;
1615   Type type;
1616   int i;
1617   Object sub;
1618 
1619   *floatflag = 1;
1620 
1621   switch (DXGetObjectClass(f)) {
1622     case (CLASS_FIELD):
1623      if (DXEmptyField((Field)f)) return OK;
1624 
1625      if (!(a = (Array)(DXGetComponentValue((Field)f, "data")))) {
1626        return OK;
1627      }
1628      if (!(DXGetArrayInfo((Array)a, NULL, &type, NULL, NULL, NULL))) {
1629        DXSetError(ERROR_BAD_PARAMETER,"bad data component");
1630        return ERROR;
1631      }
1632      if (type != TYPE_FLOAT) {
1633        *floatflag = 0;
1634      }
1635      break;
1636     case (CLASS_GROUP):
1637      /* if any member of the group has a non-float data component, set
1638         the flag to 0 */
1639      i = 0;
1640      while ((sub=(Object)DXGetPart((Object)f, i))) {
1641        i++;
1642        if (!(a = (Array)(DXGetComponentValue((Field)sub, "data")))) {
1643          continue;
1644        }
1645        if (!(DXGetArrayInfo((Array)a, NULL, &type, NULL, NULL, NULL))) {
1646          DXSetError(ERROR_BAD_PARAMETER,"bad data component");
1647          return ERROR;
1648        }
1649        if (type != TYPE_FLOAT) {
1650          *floatflag = 0;
1651          goto done;
1652        }
1653      }
1654      break;
1655      default:
1656      break;
1657    }
1658 done:
1659    return OK;
1660 }
1661 
1662 
1663 
_dxfByteField(Object g_out,int * byteflag)1664 Error _dxfByteField(Object g_out, int *byteflag)
1665 {
1666   int foundone, i, rank, shape;
1667   Field f;
1668   Class class;
1669   Array a;
1670   Category category;
1671   Type type;
1672 
1673   *byteflag = 0;
1674   if (!(class=DXGetObjectClass((Object)g_out)))
1675      return ERROR;
1676   if (class == CLASS_FIELD) {
1677      if (DXEmptyField((Field)g_out)) {
1678         return OK;
1679      }
1680   }
1681 
1682   /*  I'm just getting the first part that I find.  */
1683   foundone = 0;
1684   i = 0;
1685   while ((f=DXGetPart((Object)g_out, i))) {
1686     i++;
1687     if (DXEmptyField(f))
1688       continue;
1689     else {
1690       foundone = 1;
1691       break;
1692     }
1693   }
1694   /* presumably all empty */
1695   if (!(foundone)) {
1696    *byteflag = 0;
1697    return OK;
1698   }
1699 
1700   if (!(a = (Array)(DXGetComponentValue(f, "data")))) {
1701      return OK;
1702   }
1703   if (!(DXGetArrayInfo((Array)a, NULL, &type, &category, &rank, &shape))) {
1704      DXSetError(ERROR_BAD_PARAMETER,"bad data component");
1705      return ERROR;
1706   }
1707   if (type == TYPE_UBYTE) {
1708      if (!((rank==0)||((rank==1)&&(shape==1)))) {
1709          /* byte vectors are to be treated at floats (no lookup) */
1710          *byteflag=0;
1711          return OK;
1712      }
1713      *byteflag=1;
1714      if (!(category==CATEGORY_REAL)) {
1715 	  DXSetError(ERROR_BAD_PARAMETER,"must be category real");
1716           return ERROR;
1717      }
1718   }
1719   return OK;
1720 }
1721 
1722 
_dxfDelayedOK(Object g_out)1723 Error _dxfDelayedOK(Object g_out)
1724 {
1725   int foundone, i, rank, shape;
1726   Field f;
1727   Class class;
1728   Array a;
1729   Category category;
1730   Type type;
1731 
1732   if (!(class=DXGetObjectClass((Object)g_out)))
1733      return ERROR;
1734   if (class == CLASS_FIELD) {
1735      if (DXEmptyField((Field)g_out)) {
1736         return OK;
1737      }
1738   }
1739 
1740   /*  I'm just getting the first part that I find.  */
1741   foundone = 0;
1742   i = 0;
1743   while ((f=DXGetPart((Object)g_out, i))) {
1744     i++;
1745     if (DXEmptyField(f))
1746       continue;
1747     else {
1748       foundone = 1;
1749       break;
1750     }
1751   }
1752   /* presumably all empty */
1753   if (!(foundone)) {
1754    return OK;
1755   }
1756 
1757   if (!(a = (Array)(DXGetComponentValue(f, "data")))) {
1758      return OK;
1759   }
1760   if (!(DXGetArrayInfo((Array)a, NULL, &type, &category, &rank, &shape))) {
1761      DXSetError(ERROR_BAD_PARAMETER,"bad data component");
1762      return ERROR;
1763   }
1764   /*
1765   if ((type != TYPE_UBYTE)&&(type != TYPE_BYTE)&&(type != TYPE_INT)&&
1766       (type != TYPE_UINT)&&(type != TYPE_SHORT)&&(type != TYPE_USHORT)) {
1767          DXSetError(ERROR_BAD_PARAMETER,
1768                     "delayed option only valid for byte, integer, and short scalar data");
1769          return ERROR;
1770   }
1771   */
1772   if (type != TYPE_UBYTE) {
1773          DXSetError(ERROR_BAD_PARAMETER,"#11821");
1774          return ERROR;
1775   }
1776   if (!((rank==0)||((rank==1)&&(shape==1)))) {
1777          DXSetError(ERROR_BAD_PARAMETER,
1778                     "delayed option only valid for scalar data");
1779          return ERROR;
1780   }
1781   return OK;
1782 }
1783 
_dxfIsVolume(Object g_out,int * surface)1784 int _dxfIsVolume(Object g_out, int *surface)
1785 {
1786   int foundone, i;
1787   Field f;
1788   char *el_type;
1789   Class class;
1790 
1791   if (!(class=DXGetObjectClass((Object)g_out)))
1792      return ERROR;
1793   if (class == CLASS_FIELD) {
1794      if (DXEmptyField((Field)g_out)) {
1795         *surface = 1;
1796         return OK;
1797      }
1798   }
1799 
1800   /*  I'm just getting the first part that I find.  */
1801   *surface = 0;
1802   foundone = 0;
1803   i = 0;
1804   while ((f=DXGetPart((Object)g_out, i))) {
1805     i++;
1806     if (DXEmptyField(f))
1807       continue;
1808     else {
1809       foundone = 1;
1810       break;
1811     }
1812   }
1813   if (!(foundone)) {
1814     *surface = 1;
1815     return OK;
1816   }
1817 
1818   el_type  = NULL;
1819   if ((el_type= DXGetString((String)DXGetComponentAttribute((Field)f,
1820 		       "connections", "element type"))) != NULL) {
1821     if ( !strcmp(el_type,"triangles") || !strcmp(el_type,"quads") ||
1822 	!strcmp(el_type,"faces") || !strcmp(el_type,"lines") )
1823       *surface = 1;
1824     else if ( !strcmp(el_type,"cubes") || !strcmp(el_type,"tetrahedra") )
1825       *surface = 0;
1826     else {
1827       DXSetError(ERROR_DATA_INVALID,"unrecognized connections");
1828       return ERROR;
1829     }
1830   }
1831   else  {
1832     /*    if no connections, assume surface */
1833     *surface = 1;
1834   }
1835   return OK;
1836 }
1837 
1838 
1839 Error
_dxfHSVtoRGB(float h,float s,float v,float * red,float * green,float * blue)1840 _dxfHSVtoRGB(float h, float s, float v, float *red, float *green, float *blue)
1841 /*   algorithm is from Fundamentals of Interactive Computer Graphics
1842      by Foley and Van Dam, 1984   */
1843 {
1844 
1845   int i;
1846   float f,p,q,t,valfactor;
1847 
1848   /* first convert from 0 -> 1 to 0 -> 360 */
1849   h = h*360.0;
1850 
1851   if (h < 0.0)   h = h + ((int)(-h/360)+1)*  360.0;
1852   if (h > 360.0) h = h - ((int)( h/360))  *  360.0;
1853 
1854   /* do the checking */
1855   if ((s < 0.0)||(s > 1.0)) {
1856      DXSetError(ERROR_BAD_PARAMETER,"bad SATURATION value");
1857      return ERROR;
1858   }
1859   if (v < 0.0) {
1860      DXSetError(ERROR_BAD_PARAMETER,"bad VALUE value");
1861      return ERROR;
1862   }
1863   valfactor = 1.0;
1864   if (v > 1.0) {
1865      valfactor = v;
1866      v = 1.0;
1867   }
1868 
1869   if (s==0.0)
1870     {
1871       *red = v*valfactor;
1872       *green = v*valfactor;
1873       *blue = v*valfactor;
1874     }
1875   else
1876     {
1877       if (h==360.0) h=0.0;
1878       h=h/60.0;
1879       i=h;
1880       f=h-i;
1881       p=v*(1.0-s);
1882       q=v*(1.0-(s*f));
1883       t=v*(1.0-(s*(1.0-f)));
1884       switch(i)
1885         {
1886 	case 0:
1887 	  *red=v*valfactor; *green=t*valfactor,*blue=p*valfactor;
1888 	  break;
1889 	case 1:
1890 	  *red=q*valfactor; *green=v*valfactor,*blue=p*valfactor;
1891 	  break;
1892 	case 2:
1893 	  *red=p*valfactor; *green=v*valfactor,*blue=t*valfactor;
1894 	  break;
1895 	case 3:
1896 	  *red=p*valfactor; *green=q*valfactor,*blue=v*valfactor;
1897 	  break;
1898 	case 4:
1899 	  *red=t*valfactor; *green=p*valfactor,*blue=v*valfactor;
1900 	  break;
1901 	case 5:
1902 	  *red=v*valfactor; *green=p*valfactor,*blue=q*valfactor;
1903 	  break;
1904 	};
1905 
1906     }
1907     return OK;
1908 }
1909 
1910 
1911 
1912 
1913 
1914 
1915 
1916 Error
RGBtoHLS(float r,float g,float b,float * h,float * l,float * s)1917 RGBtoHLS(float r, float g, float b, float *h, float *l, float *s)
1918 /*   algorithm is from Fundamentals of Interactive Computer Graphics
1919      by Foley and Van Dam, 1984   */
1920 {
1921   float min, max, delta;
1922 
1923   min = r;
1924   if (g < min) min = g;
1925   if (b < min) min = b;
1926 
1927   max = r;
1928   if (g > max) max = g;
1929   if (b > max) max = b;
1930 
1931   if ((min < 0.0)||(max > 1.0)) {
1932      DXSetError (ERROR_BAD_PARAMETER,"bad rgb value");
1933      return ERROR;
1934   }
1935 
1936   *l = (max + min)/2.0;
1937 
1938   if (max == min) {
1939      *s = 0.0;
1940      *h = 0.0;
1941   }
1942 
1943   else {
1944      delta = max - min;
1945      if (*l <= 0.5)
1946 	*s = delta/(max + min);
1947      else
1948 	*s = delta/(2.0 - max - min);
1949      if (r == max)
1950 	*h = (g - b)/delta;
1951      else if (g == max)
1952 	*h = 2.0 + (b - r)/delta;
1953      else if (b == max)
1954 	*h = 4.0 + (r - g)/delta;
1955      *h = *h * 60.0;
1956      if (*h < 0.0) *h = *h + 360;
1957   }
1958   return OK;
1959 }
1960 
1961 Error
HLStoRGB(float h,float l,float s,float * r,float * g,float * b)1962 HLStoRGB(float h, float l, float s, float *r, float *g, float *b)
1963 /*   algorithm is from Fundamentals of Interactive Computer Graphics
1964      by Foley and Van Dam, 1984   */
1965 {
1966   float m2, m1;
1967 
1968   if (h < 0.0)   h = h + ((int)(-h/360)+1)*  360.0;
1969   if (h > 360.0) h = h - ((int)( h/360))  *  360.0;
1970 
1971   if (l <= 0.5)
1972      m2 = l*(1.0 + s);
1973   else
1974      m2 = l + s - l*s;
1975   m1 = 2.0*l - m2;
1976   if (s == 0.0) {
1977      *r = l;
1978      *g = l;
1979      *b = l;
1980   }
1981   else {
1982      *r = ValueFcn(m1,m2, h + 120.0);
1983      *g = ValueFcn(m1, m2, h);
1984      *b = ValueFcn(m1, m2, h - 120.0);
1985   }
1986   return OK;
1987 }
1988 
ValueFcn(float n1,float n2,float hue)1989 static float ValueFcn(float n1, float n2, float hue)
1990 {
1991    if (hue > 360.0)
1992       hue = hue - 360.0;
1993    else if (hue < 0.0)
1994       hue = hue + 360.0;
1995    if (hue < 60.0)
1996       return (n1 + (n2 - n1)*(240.0 - hue)/60.0);
1997    else if (hue < 180.0)
1998       return n2;
1999    else if (hue < 240.0)
2000       return (n1 + (n2 - n1)*(240.0 - hue)/60.0);
2001    else
2002       return n1;
2003 }
2004 
2005 
2006 
2007 
2008 
2009 Error
_dxfRGBtoHSV(float r,float g,float b,float * h,float * s,float * v)2010 _dxfRGBtoHSV(float r, float g, float b, float *h, float *s, float *v)
2011 /*   algorithm is from Fundamentals of Interactive Computer Graphics
2012      by Foley and Van Dam, 1984   */
2013 {
2014 
2015   float max, min, delta;
2016 
2017   max = r;
2018   if (g > max) max = g;
2019   if (b > max) max = b;
2020 
2021   min = r;
2022   if (g < min) min = g;
2023   if (b < min) min = b;
2024 
2025   if ((max > 1.0)||(min < 0.0)) {
2026      DXSetError(ERROR_BAD_PARAMETER,"#10110", "r g b values", 0, 1);
2027      return ERROR;
2028   }
2029 
2030   *v = max;
2031 
2032   if (max != 0.0)
2033      *s = (max - min)/max;
2034   else
2035      *s = 0.0;
2036 
2037   if (max == 0.0)
2038      *h = 0.0;
2039   else {
2040      delta = max - min;
2041      if (delta != 0.0) {
2042        if (r == max)
2043   	  *h = (g - b)/delta;
2044        else if (g == max)
2045 	  *h = 2.0 + (b - r)/delta;
2046        else if (b == max)
2047 	  *h = 4.0 + (r - g)/delta;
2048        *h = *h*60.0;
2049 
2050        if (*h < 0.0)
2051   	  *h = *h + 360.0;
2052        }
2053        else
2054 	  *h = 0.0;
2055     }
2056     /* convert from 0 to 360 to 0 to 1 */
2057     *h = *h/ 360.0;
2058 
2059     return OK;
2060 }
2061 
_dxfBoundingBoxDiagonal(Object ob,float * thickness)2062 Error _dxfBoundingBoxDiagonal(Object ob, float *thickness)
2063 {
2064   Point boxpoint[8];
2065 
2066   if (!DXBoundingBox((Object)ob, boxpoint)) {
2067     return ERROR;
2068   }
2069 
2070   *thickness = DXLength(DXSub(boxpoint[7], boxpoint[0]));
2071   if (*thickness == 0.0) {
2072     DXSetError(ERROR_DATA_INVALID,
2073 	     "bounding box for volume has zero thickness");
2074     return ERROR;
2075   }
2076   return OK;
2077 }
2078 
2079 
direction(int value)2080 static int direction(int value)
2081 {
2082   if (value >= 0)
2083       return 1;
2084   else
2085       return 0;
2086 }
2087 
sign(int value)2088 static int sign(int value)
2089 {
2090   if (value >= 0)
2091       return 1;
2092   else
2093       return -1;
2094 }
2095 
2096 
_dxfFieldWithInformation(Object ob)2097 int _dxfFieldWithInformation(Object ob)
2098 {
2099   Object subo;
2100   int i;
2101 
2102 
2103   switch(DXGetObjectClass(ob)) {
2104   case CLASS_GROUP:
2105     /* get children; */
2106     for (i=0; (subo=DXGetEnumeratedMember((Group)ob, i, NULL)); i++)
2107       if (_dxfFieldWithInformation(subo))
2108          return 1;
2109       break;
2110 
2111   case CLASS_FIELD:
2112     if (!(DXEmptyField((Field)ob)))
2113       return 1;
2114     break;
2115 
2116   case CLASS_XFORM:
2117     if (!(DXGetXformInfo((Xform)ob, &subo, NULL)))
2118       return 0;
2119     if (_dxfFieldWithInformation(subo))
2120       return 1;
2121     break;
2122 
2123   case CLASS_CLIPPED:
2124     if (!(DXGetClippedInfo((Clipped)ob, &subo, NULL)))
2125       return 0;
2126     if (_dxfFieldWithInformation(subo))
2127       return 1;
2128     break;
2129   default:
2130     return 1;
2131   }
2132   return 0;
2133 }
2134 
2135 
2136 
2137 
2138 
_dxfMakeRGBColorMap(Field mapfield)2139 Field _dxfMakeRGBColorMap(Field mapfield)
2140      /* converts an hsv color map to an rgb color map */
2141 {
2142   int icountnew, icountoriginal, i, countpos, countdata, rank, shape, j;
2143   int numnew, numnew1, numnew2, numnew3;
2144   int huestep0, huestep1, huestepdiff, deppos;
2145   float *dp_f=NULL, *pp;
2146   int *dp_i=NULL;
2147   uint *dp_ui=NULL;
2148   short *dp_s=NULL;
2149   ushort *dp_us=NULL;
2150   byte *dp_b=NULL;
2151   ubyte *dp_ub=NULL;
2152   Type type, datatype;
2153   char *datadep;
2154   Category category;
2155   float lasthue=0, lastsat=0, lastval=0;
2156   float tmphue, tmpsat, tmpval, tmppos, lasttmppos;
2157   float lastpos, pos, dpos;
2158   float red, green, blue;
2159   float abshue, abssat, absval;
2160   float hue=0, sat=0, val=0;
2161   float dhue, dsat, dval;
2162   float maxhuediff, maxsatdiff, maxvaldiff, fuzz;
2163   RGBColor newcolor;
2164   Array a_positions, a_data, a_newpositions, a_newdata, a_newconnections;
2165   Field newmapfield;
2166 
2167   fuzz = 0.0;
2168   datadep = NULL;
2169 
2170   if (!(datadep=DXGetString((String)
2171 			  DXGetComponentAttribute(mapfield,"data","dep")))) {
2172     DXSetError(ERROR_DATA_INVALID,"missing data dependent attribute");
2173     return ERROR;
2174   }
2175   if (strcmp(datadep,"positions"))
2176     deppos = 0;
2177   else
2178     deppos = 1;
2179 
2180   if (!(newmapfield = DXNewField())) {
2181     return ERROR;
2182   }
2183 
2184   a_newdata = NULL;
2185   a_newpositions = NULL;
2186   a_newconnections = NULL;
2187 
2188 
2189   /* set the criteria for adding new points to the map */
2190   /* this should result in max error of 0.001 in r, g, and b
2191      from an exact transformation from a straight line in hsv
2192      maxhuediff = 0.01306;
2193      maxsatdiff = 0.013;
2194      maxvaldiff = 0.013;
2195      */
2196 
2197   /* set the criteria for adding new points to the map */
2198   /* this should result in max error of 0.01 in r, g, and b
2199      from an exact transformation from a straight line in hsv */
2200   if (deppos) {
2201     maxhuediff = 0.0389;
2202     maxsatdiff = 0.04;
2203     maxvaldiff = 0.04;
2204   }
2205   else {
2206     maxhuediff = DXD_MAX_FLOAT;
2207     maxsatdiff = DXD_MAX_FLOAT;
2208     maxvaldiff = DXD_MAX_FLOAT;
2209   }
2210 
2211 
2212 
2213   if (!(a_positions =
2214 	(Array)DXGetComponentValue((Field)mapfield,"positions"))) {
2215     DXSetError(ERROR_BAD_PARAMETER,"map has no positions component");
2216     goto cleanup;
2217   }
2218   if (!DXGetComponentValue((Field)mapfield,"connections")) {
2219     DXSetError(ERROR_BAD_PARAMETER,"map has no connections component");
2220     goto cleanup;
2221   }
2222   if (!(a_data = (Array)DXGetComponentValue((Field)mapfield,"data"))) {
2223     DXSetError(ERROR_BAD_PARAMETER,"map has no data component");
2224     goto cleanup;
2225   }
2226   if (DXGetArrayClass(a_data) != CLASS_ARRAY) {
2227     DXSetError(ERROR_BAD_PARAMETER,"map is bad class");
2228     goto cleanup;
2229   }
2230   /* get size and shape */
2231   if (!(DXGetArrayInfo(a_data, &countdata, &datatype, &category,
2232 		     &rank, &shape)))  goto cleanup;
2233   if((rank != 1) || (category != CATEGORY_REAL) || (shape != 3)) {
2234     DXSetError(ERROR_BAD_PARAMETER,
2235 	    "data (rank != 1) or (non-real) or (vec len != 3)");
2236     goto cleanup;
2237   }
2238 
2239   /* make the new arrays*/
2240   if (!(a_newdata = DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 1, 3))) goto cleanup;
2241   if (!(a_newpositions = DXNewArray(TYPE_FLOAT,
2242 				  CATEGORY_REAL, 1, 1)))  {
2243     DXDelete((Object)a_newdata);
2244     return ERROR;
2245   }
2246 
2247   if (DXGetArrayClass(a_positions) != CLASS_ARRAY) {
2248     DXSetError(ERROR_BAD_PARAMETER,"map positions are bad class");
2249     goto cleanupnofield;
2250   }
2251   /* get size and shape */
2252   if (!(DXGetArrayInfo(a_positions,
2253          &countpos, &type, &category, &rank, &shape)))
2254      goto cleanup;
2255   if ((category != CATEGORY_REAL) || (type != TYPE_FLOAT)) {
2256     DXSetError(ERROR_BAD_PARAMETER, "positions (non-real) or (not float)");
2257     goto cleanupnofield;
2258   }
2259   if (!( (rank == 0) || ((rank == 1)&&(shape == 1)))) {
2260     DXSetError(ERROR_BAD_PARAMETER, "non-scalar positions");
2261     goto cleanupnofield;
2262   }
2263 
2264   switch (datatype) {
2265     case (TYPE_FLOAT):
2266        dp_f = (float *)DXGetArrayData(a_data);
2267        if (!dp_f) goto cleanupnofield;
2268        break;
2269     case (TYPE_INT):
2270        dp_i = (int *)DXGetArrayData(a_data);
2271        if (!dp_i) goto cleanupnofield;
2272        break;
2273     case (TYPE_UINT):
2274        dp_ui = (uint *)DXGetArrayData(a_data);
2275        if (!dp_ui) goto cleanupnofield;
2276        break;
2277     case (TYPE_SHORT):
2278        dp_s = (short *)DXGetArrayData(a_data);
2279        if (!dp_s) goto cleanupnofield;
2280        break;
2281     case (TYPE_USHORT):
2282        dp_us = (ushort *)DXGetArrayData(a_data);
2283        if (!dp_us) goto cleanupnofield;
2284        break;
2285     case (TYPE_BYTE):
2286        dp_b = (byte *)DXGetArrayData(a_data);
2287        if (!dp_b) goto cleanupnofield;
2288        break;
2289     case (TYPE_UBYTE):
2290        dp_ub = (ubyte *)DXGetArrayData(a_data);
2291        if (!dp_ub) goto cleanupnofield;
2292        break;
2293     default:
2294        DXSetError(ERROR_BAD_PARAMETER,"unknown data type");
2295        goto cleanupnofield;
2296     }
2297   if (!(pp= (float *)DXGetArrayData(a_positions))) {
2298     goto cleanupnofield;
2299   }
2300 
2301 
2302   if (deppos) {
2303     icountnew = 0;
2304     icountoriginal = 0;
2305     switch (datatype) {
2306       case (TYPE_FLOAT):
2307         lasthue = dp_f[0];
2308         lastsat = dp_f[1];
2309         lastval = dp_f[2];
2310         break;
2311       case (TYPE_INT):
2312         lasthue = (float)dp_i[0];
2313         lastsat = (float)dp_i[1];
2314         lastval = (float)dp_i[2];
2315         break;
2316       case (TYPE_UINT):
2317         lasthue = (float)dp_ui[0];
2318         lastsat = (float)dp_ui[1];
2319         lastval = (float)dp_ui[2];
2320         break;
2321       case (TYPE_SHORT):
2322         lasthue = (float)dp_s[0];
2323         lastsat = (float)dp_s[1];
2324         lastval = (float)dp_s[2];
2325         break;
2326       case (TYPE_USHORT):
2327         lasthue = (float)dp_us[0];
2328         lastsat = (float)dp_us[1];
2329         lastval = (float)dp_us[2];
2330         break;
2331       case (TYPE_BYTE):
2332         lasthue = (float)dp_b[0];
2333         lastsat = (float)dp_b[1];
2334         lastval = (float)dp_b[2];
2335         break;
2336       case (TYPE_UBYTE):
2337         lasthue = (float)dp_ub[0];
2338         lastsat = (float)dp_ub[1];
2339         lastval = (float)dp_ub[2];
2340         break;
2341       default:
2342         break;
2343     }
2344     lastpos = pp[0];
2345     if (!(_dxfHSVtoRGB(lasthue, lastsat, lastval,
2346 		   &red, &green, &blue))) goto cleanupnofield;
2347 
2348     newcolor = DXRGB(red,green,blue);
2349     if (!(DXAddArrayData(a_newdata,icountnew,1,(Pointer)&newcolor)))
2350       goto cleanupnofield;
2351     if (!(DXAddArrayData(a_newpositions,icountnew,
2352 		       1,(Pointer)&lastpos))) goto cleanupnofield;
2353     icountnew++;
2354     icountoriginal++;
2355 
2356 
2357     /* run through the original map */
2358     for (i = 3; i < 3*countpos; i=i+3) {
2359     switch (datatype) {
2360       case (TYPE_FLOAT):
2361         hue = dp_f[i];
2362         sat = dp_f[i+1];
2363         val = dp_f[i+2];
2364         break;
2365       case (TYPE_INT):
2366         hue = (float)dp_i[i];
2367         sat = (float)dp_i[i+1];
2368         val = (float)dp_i[i+2];
2369         break;
2370       case (TYPE_UINT):
2371         hue = (float)dp_ui[i];
2372         sat = (float)dp_ui[i+1];
2373         val = (float)dp_ui[i+2];
2374         break;
2375       case (TYPE_SHORT):
2376         hue = (float)dp_s[i];
2377         sat = (float)dp_s[i+1];
2378         val = (float)dp_s[i+2];
2379         break;
2380       case (TYPE_USHORT):
2381         hue = (float)dp_us[i];
2382         sat = (float)dp_us[i+1];
2383         val = (float)dp_us[i+2];
2384         break;
2385       case (TYPE_BYTE):
2386         hue = (float)dp_b[i];
2387         sat = (float)dp_b[i+1];
2388         val = (float)dp_b[i+2];
2389         break;
2390       case (TYPE_UBYTE):
2391         hue = (float)dp_ub[i];
2392         sat = (float)dp_ub[i+1];
2393         val = (float)dp_ub[i+2];
2394         break;
2395       default:
2396         break;
2397     }
2398       pos = pp[icountoriginal];
2399       dhue = hue - lasthue;
2400       abshue = ABS(dhue);
2401       dsat = sat - lastsat;
2402       abssat = ABS(dsat);
2403       dval = val - lastval;
2404       absval = ABS(dval);
2405       dpos = pos - lastpos;
2406 
2407       /* see if we are about to cross discontinuity */
2408       huestep1 = floor(hue/60.0);
2409       huestep0 = floor(lasthue/60.0);
2410       huestepdiff = (huestep1 - huestep0);
2411 
2412       if ((abshue < maxhuediff)&&(abssat < maxsatdiff)&&
2413   	  (absval < maxvaldiff) && (huestepdiff == 0)) {
2414 	if (!(_dxfHSVtoRGB(hue, sat, val, &red, &green, &blue)))
2415 	  goto cleanupnofield;
2416 	newcolor = DXRGB(red,green,blue);
2417 	if (!(DXAddArrayData(a_newdata,icountnew,
2418 			   1,(Pointer)&newcolor))) goto cleanupnofield;
2419         if (!(DXAddArrayData(a_newpositions,icountnew,
2420 			   1,(Pointer)&pos))) goto cleanupnofield;
2421         icountnew++;
2422         icountoriginal++;
2423         lasthue = hue;
2424         lastsat = sat;
2425         lastval = val;
2426         lastpos = pos;
2427       }
2428       /* we need to do some interpolation */
2429       else {
2430         numnew1 = 0;
2431         numnew2 = 0;
2432         numnew3 = 0;
2433         if (abshue > maxhuediff) numnew1 = abshue/maxhuediff;
2434         if (abssat > maxsatdiff) numnew2 = abssat/maxsatdiff;
2435         if (abshue > maxvaldiff) numnew3 = absval/maxvaldiff;
2436         numnew = 1;
2437         if (numnew1 > numnew) numnew = numnew1;
2438         if (numnew2 > numnew) numnew = numnew2;
2439         if (numnew3 > numnew) numnew = numnew3;
2440         numnew++;
2441         tmppos = lastpos;
2442         for (j = 1; j < numnew; j++) {
2443    	  tmphue = lasthue + (((float)j)/((float)numnew))*dhue;
2444 	  huestep1 = floor(tmphue/60.0);
2445           huestepdiff = huestep1 - huestep0;
2446 	  /* first do the discontinuity if necessary */
2447 	  if (huestepdiff != 0) {
2448 	    tmphue = (huestep0 + direction(huestepdiff))*60.0;
2449             huestep0 = huestep0 + sign(huestepdiff);
2450             lasttmppos = tmppos;
2451             tmpsat = lastsat + ((tmphue-lasthue)/(dhue))*dsat;
2452             tmpval = lastval + ((tmphue-lasthue)/(dhue))*dval;
2453             tmppos = lastpos + ((tmphue-lasthue)/(dhue))*dpos;
2454 	    if (!(_dxfHSVtoRGB(tmphue, tmpsat, tmpval, &red,
2455 	  	 	   &green, &blue)))  goto cleanupnofield;
2456 	    newcolor = DXRGB(red,green,blue);
2457             /* don't add it if it is the same as the previous one or
2458              * one of the two end points */
2459             if ((ABS(((double)(tmppos - lastpos))) > fuzz) &&
2460                 (ABS(((double)(pos - tmppos))) > fuzz) &&
2461                 (ABS(((double)(tmppos - lasttmppos))) > fuzz)) {
2462 	      if (!(DXAddArrayData(a_newdata,icountnew,
2463 				 1,(Pointer)&newcolor))) goto cleanupnofield;
2464 	      if (!(DXAddArrayData(a_newpositions,icountnew,
2465 				 1, (Pointer)&tmppos)))  goto cleanupnofield;
2466 	      icountnew++;
2467             }
2468 	  }
2469 	  /* now do the others */
2470 	  tmphue = lasthue + (((float)j)/((float)numnew))*dhue;
2471 	  tmpsat = lastsat + (((float)j)/((float)numnew))*dsat;
2472 	  tmpval = lastval + (((float)j)/((float)numnew))*dval;
2473           lasttmppos = tmppos;
2474 	  tmppos = lastpos + (((float)j)/((float)numnew))*dpos;
2475 	  if (!(_dxfHSVtoRGB(tmphue, tmpsat, tmpval, &red,
2476 	  	         &green, &blue)))  goto cleanupnofield;
2477 	  newcolor = DXRGB(red,green,blue);
2478           if ((ABS(tmppos - lastpos) > fuzz)&&(ABS(pos - tmppos) > fuzz)&&
2479 	      (ABS(tmppos - lasttmppos) > fuzz)) {
2480 	    if (!(DXAddArrayData(a_newdata,icountnew,
2481 			       1,(Pointer)&newcolor))) goto cleanupnofield;
2482 	    if (!(DXAddArrayData(a_newpositions,icountnew,
2483 			       1,(Pointer)&tmppos)))  goto cleanupnofield;
2484 	    icountnew++;
2485           }
2486         }
2487         /* now do the one I was originally going to do */
2488         if (!(_dxfHSVtoRGB(hue, sat, val, &red, &green, &blue)))
2489 	  goto cleanupnofield;
2490         newcolor = DXRGB(red,green,blue);
2491         if (!(DXAddArrayData(a_newdata,icountnew,
2492 			   1,(Pointer)&newcolor))) goto cleanupnofield;
2493         if (!(DXAddArrayData(a_newpositions,icountnew,
2494 			   1,(Pointer)&pos))) goto cleanupnofield;
2495         icountnew++;
2496         icountoriginal++;
2497         lasthue = hue;
2498         lastsat = sat;
2499         lastval = val;
2500         lastpos = pos;
2501       }
2502     }
2503     if (!(a_newconnections = DXMakeGridConnectionsV(1, &icountnew))) goto cleanup;
2504   }
2505   else {
2506     /* run through the original map */
2507     icountnew=0;
2508     for (i = 0; i < 3*countdata; i=i+3) {
2509       switch (datatype) {
2510         case (TYPE_FLOAT):
2511          lasthue = dp_f[i];
2512          lastsat = dp_f[i+1];
2513          lastval = dp_f[i+2];
2514          break;
2515         case (TYPE_INT):
2516          lasthue = (float)dp_i[i];
2517          lastsat = (float)dp_i[i+1];
2518          lastval = (float)dp_i[i+2];
2519          break;
2520         case (TYPE_UINT):
2521          lasthue = (float)dp_ui[i];
2522          lastsat = (float)dp_ui[i+1];
2523          lastval = (float)dp_ui[i+2];
2524          break;
2525         case (TYPE_SHORT):
2526          lasthue = (float)dp_s[i];
2527          lastsat = (float)dp_s[i+1];
2528          lastval = (float)dp_s[i+2];
2529          break;
2530         case (TYPE_USHORT):
2531          lasthue = (float)dp_us[i];
2532          lastsat = (float)dp_us[i+1];
2533          lastval = (float)dp_us[i+2];
2534          break;
2535         case (TYPE_BYTE):
2536          lasthue = (float)dp_b[i];
2537          lastsat = (float)dp_b[i+1];
2538          lastval = (float)dp_b[i+2];
2539          break;
2540         case (TYPE_UBYTE):
2541          lasthue = (float)dp_ub[i];
2542          lastsat = (float)dp_ub[i+1];
2543          lastval = (float)dp_ub[i+2];
2544          break;
2545         default:
2546 	 break;
2547       }
2548       if (!(_dxfHSVtoRGB(lasthue, lastsat, lastval,
2549 		     &red, &green, &blue))) goto cleanupnofield;
2550       newcolor = DXRGB(red,green,blue);
2551       if (!(DXAddArrayData(a_newdata,icountnew,1,(Pointer)&newcolor)))
2552 	goto cleanupnofield;
2553       icountnew++;
2554     }
2555     for (i=0; i< countpos; i++) {
2556       if (!(DXAddArrayData(a_newpositions,i,1,(Pointer)&pp[i])))
2557 	goto cleanupnofield;
2558     }
2559     if (!(a_newconnections = DXMakeGridConnectionsV(1, &countpos))) goto cleanup;
2560   }
2561   if (!(DXSetComponentValue((Field)newmapfield, "data",
2562 			  (Object)a_newdata))) {
2563     DXDelete((Object)a_newpositions);
2564     goto cleanup;
2565   }
2566   if (!(DXSetComponentValue((Field)newmapfield,
2567 			  "positions",(Object)a_newpositions))) {
2568     goto cleanup;
2569   }
2570   if (!(DXSetComponentValue((Field)newmapfield, "connections",
2571 			  (Object)a_newconnections))) {
2572     DXDelete((Object)a_newconnections);
2573     goto cleanup;
2574   }
2575   if (deppos) {
2576     if (!(DXSetComponentAttribute((Field)newmapfield,"data", "dep",
2577 				(Object)DXNewString("positions"))))
2578       goto cleanup;
2579   }
2580   else {
2581     if (!(DXSetComponentAttribute((Field)newmapfield,"data", "dep",
2582 				(Object)DXNewString(datadep))))  goto cleanup;
2583   }
2584 
2585   if (!(DXSetComponentAttribute((Field)newmapfield,"connections","ref",
2586 			      (Object)DXNewString("positions"))))   goto cleanup;
2587   if (!(DXSetComponentAttribute((Field)newmapfield,"connections","element type",
2588 			      (Object)DXNewString("lines"))))    goto cleanup;
2589 
2590   if (!DXEndField((Field)newmapfield))
2591      goto cleanup;
2592 
2593 
2594   return newmapfield;
2595 
2596  cleanupnofield:
2597   DXDelete ((Object)newmapfield);
2598   DXDelete ((Object)a_newdata);
2599   DXDelete ((Object)a_newpositions);
2600   DXDelete ((Object)a_newconnections);
2601   return ERROR;
2602 
2603  cleanup:
2604   DXDelete ((Object)newmapfield);
2605   return ERROR;
2606 }
2607 
2608 
2609 
2610 
_dxfMakeHSVfromRGB(Field mapfield)2611 Field _dxfMakeHSVfromRGB(Field mapfield)
2612 /* converts an hsv color map to an rgb color map */
2613 {
2614   Type type;
2615   Category category;
2616   Array a_positions, a_data, a_newpositions, a_newdata, a_newconnections;
2617   float *dp, *pp, maxsteprgb, newr, newg, newb, biggest;
2618   float hue, saturation, value, newpos, fuzz;
2619   float lastr, lastg, lastb, lastp;
2620   RGBColor newcolor;
2621   Field newmapfield;
2622   int count, rank, shape, i, j, icountnew, numnewsteps;
2623 
2624   fuzz = 0.0;
2625 
2626   if (!(newmapfield = DXNewField())) {
2627     return ERROR;
2628   }
2629 
2630   a_newdata = NULL;
2631   a_newpositions = NULL;
2632   a_newconnections = NULL;
2633 
2634   /* set the criteria for adding new points to the map */
2635 
2636   /* I changed this on 10/18/94 to a larger number. Seems ok from
2637    * tests I've run */
2638   maxsteprgb = 0.08;
2639 
2640 
2641 
2642   if (!(a_positions =
2643 	(Array)DXGetComponentValue((Field)mapfield,"positions"))) {
2644     DXSetError(ERROR_BAD_PARAMETER,"map has no positions component");
2645     goto cleanupnofield;
2646   }
2647   if (!(a_data = (Array)DXGetComponentValue((Field)mapfield,"data"))) {
2648     DXSetError(ERROR_BAD_PARAMETER,"map has no data component");
2649     goto cleanupnofield;
2650   }
2651   if (DXGetArrayClass(a_data) != CLASS_ARRAY) {
2652     DXSetError(ERROR_BAD_PARAMETER,"map is bad class");
2653     goto cleanupnofield;
2654   }
2655   /* get size and shape */
2656   if (!(DXGetArrayInfo(a_data, &count, &type, &category,
2657 		     &rank, &shape)))  goto cleanupnofield;
2658   if((rank != 1) || (category != CATEGORY_REAL) || (type != TYPE_FLOAT) ||
2659      (shape != 3)) {
2660     DXSetError(ERROR_BAD_PARAMETER,
2661 	    "data (rank != 1) or (non-real) or (not float) or (vec len != 3)");
2662     goto cleanupnofield;
2663   }
2664 
2665   /* make the new arrays*/
2666   if (!(a_newdata = DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 1, 3))) goto cleanup;
2667   if (!(a_newpositions = DXNewArray(TYPE_FLOAT,
2668 				  CATEGORY_REAL, 1, 1)))
2669     goto cleanupnofield;
2670 
2671   /* get size and shape */
2672   if (!(DXGetArrayInfo(a_positions,
2673 		     &count, &type, &category, &rank, &shape))) goto cleanup;
2674   if ((category != CATEGORY_REAL) || (type != TYPE_FLOAT)) {
2675     DXSetError(ERROR_BAD_PARAMETER, "positions (non-real) or (not float)");
2676     goto cleanupnofield;
2677   }
2678   if (!( (rank == 0) || ((rank == 1)&&(shape == 1)))) {
2679     DXSetError(ERROR_BAD_PARAMETER, "non-scalar positions");
2680     goto cleanupnofield;
2681   }
2682   if (!(dp = (float *)DXGetArrayData(a_data))) {
2683     goto cleanupnofield;
2684   }
2685   if (!(pp= (float *)DXGetArrayData(a_positions))) {
2686     goto cleanupnofield;
2687   }
2688 
2689 
2690   /* run through the original map */
2691   icountnew = 0;
2692   /* do the first point */
2693   if (!(_dxfRGBtoHSV(dp[0], dp[1], dp[2], &hue, &saturation, &value)))
2694     goto cleanupnofield;
2695   newcolor = DXRGB(hue,saturation,value);
2696   if (!(DXAddArrayData(a_newdata,icountnew,1,(Pointer)&newcolor)))
2697     goto cleanupnofield;
2698   if (!(DXAddArrayData(a_newpositions,icountnew,
2699 		     1,(Pointer)&pp[0]))) goto cleanupnofield;
2700   icountnew++;
2701   lastr = dp[0];
2702   lastg = dp[1];
2703   lastb = dp[2];
2704   lastp = pp[0];
2705   for (i = 3; i < 3*count; i=i+3) {
2706     if ((ABS(dp[i]-lastr) > maxsteprgb)||
2707 	(ABS(dp[i+1]-lastg) > maxsteprgb) ||
2708 	(ABS(dp[i+2]-lastb) > maxsteprgb)) {
2709 	  biggest = ABS(dp[i]-lastr);
2710 	  if (ABS(dp[i+1]-lastg) > biggest) biggest = ABS(dp[i+1] - lastg);
2711 	  if (ABS(dp[i+2]-lastb) > biggest) biggest = ABS(dp[i+2] - lastb);
2712 	  numnewsteps = biggest/maxsteprgb + 1;
2713 	  for (j=1; j<numnewsteps; j++) {
2714 	    newr = j*(dp[i]-lastr)/numnewsteps + lastr;
2715 	    newg = j*(dp[i+1]-lastg)/numnewsteps + lastg;
2716 	    newb = j*(dp[i+2]-lastb)/numnewsteps + lastb;
2717 	    newpos = j*(pp[i/3]-lastp)/numnewsteps + lastp;
2718 	    if (ABS(newpos - lastp)>fuzz) {
2719 	    if (!(_dxfRGBtoHSV(newr, newg, newb,
2720 			   &hue, &saturation, &value))) goto cleanupnofield;
2721 	    newcolor = DXRGB(hue,saturation,value);
2722 	    if (!(DXAddArrayData(a_newdata,icountnew,1,(Pointer)&newcolor)))
2723 	      goto cleanupnofield;
2724 	    if (!(DXAddArrayData(a_newpositions,icountnew,
2725 			       1,(Pointer)&newpos))) goto cleanupnofield;
2726 	    icountnew++;
2727 	    }
2728 	  }
2729           if (!(_dxfRGBtoHSV(dp[i], dp[i+1], dp[i+2], &hue, &saturation, &value)))
2730 	      goto cleanupnofield;
2731           newcolor = DXRGB(hue,saturation,value);
2732           newpos = pp[i/3];
2733           if (!(DXAddArrayData(a_newdata,icountnew,1,(Pointer)&newcolor)))
2734 	     goto cleanupnofield;
2735           if (!(DXAddArrayData(a_newpositions,icountnew, 1,(Pointer)&newpos)))
2736 	     goto cleanupnofield;
2737           icountnew++;
2738 	}
2739     else {
2740       if (!(_dxfRGBtoHSV(dp[i], dp[i+1], dp[i+2], &hue, &saturation, &value)))
2741 	goto cleanupnofield;
2742       newcolor = DXRGB(hue,saturation,value);
2743       newpos = pp[i/3];
2744       if (!(DXAddArrayData(a_newdata,icountnew,1,(Pointer)&newcolor)))
2745 	goto cleanupnofield;
2746       if (!(DXAddArrayData(a_newpositions,icountnew, 1,(Pointer)&newpos)))
2747 	goto cleanupnofield;
2748       icountnew++;
2749     }
2750     lastr = dp[i];
2751     lastg = dp[i+1];
2752     lastb = dp[i+2];
2753     lastp = pp[i/3];
2754   }
2755 
2756 
2757   if (!(DXSetComponentValue((Field)newmapfield, "data",
2758 			  (Object)a_newdata)))
2759     goto cleanupnofield;
2760   if (!(DXSetComponentValue((Field)newmapfield,
2761 			  "positions",(Object)a_newpositions))) {
2762     DXDelete((Object)a_newpositions);
2763     DXDelete((Object)a_newconnections);
2764     goto cleanup;
2765   }
2766   if (!(a_newconnections = DXMakeGridConnectionsV(1, &icountnew)))  {
2767     DXDelete((Object)a_newconnections);
2768     goto cleanup;
2769   }
2770   if (!(DXSetComponentValue((Field)newmapfield, "connections",
2771 			  (Object)a_newconnections))) {
2772     DXDelete((Object)a_newconnections);
2773     goto cleanup;
2774   }
2775   if (!(DXSetComponentAttribute((Field)newmapfield,"data", "dep",
2776 			      (Object)DXNewString("positions"))))  goto cleanup;
2777   if (!(DXSetComponentAttribute((Field)newmapfield,"connections","ref",
2778 			      (Object)DXNewString("positions"))))   goto cleanup;
2779   if (!(DXSetComponentAttribute((Field)newmapfield,"connections","element type",
2780 			      (Object)DXNewString("lines"))))    goto cleanup;
2781 
2782 
2783   return newmapfield;
2784 
2785  cleanupnofield:
2786   DXDelete ((Object)newmapfield);
2787   DXDelete ((Object)a_newdata);
2788   DXDelete ((Object)a_newpositions);
2789   DXDelete ((Object)a_newconnections);
2790   return ERROR;
2791 
2792  cleanup:
2793   DXDelete ((Object)newmapfield);
2794   return ERROR;
2795 }
2796 
2797 
2798 
2799 
2800 
2801 
2802 
_dxfSetMultipliers(Object g_out,float unitvalue,float unitopacity)2803 Error _dxfSetMultipliers(Object g_out, float unitvalue, float unitopacity)
2804 {
2805    Class class, groupclass;
2806    int i;
2807    Object subo;
2808 
2809 
2810 
2811    if (!(class = DXGetObjectClass((Object)g_out))) {
2812       return ERROR;
2813    }
2814    if (class == CLASS_GROUP) {
2815       if (!(groupclass = DXGetGroupClass((Group)g_out))) {
2816           return ERROR;
2817       }
2818 
2819       /* put the multiplier attribute on each member of the series, 'cause
2820          someone might extract them down the road */
2821       if (groupclass == CLASS_SERIES) {
2822          for (i=0; (subo=DXGetEnumeratedMember((Group)g_out, i, NULL)); i++){
2823              if (!(DXSetAttribute((Object)subo, "color multiplier",
2824                  (Object)DXAddArrayData(DXNewArray(TYPE_FLOAT,
2825                                                    CATEGORY_REAL, 0),
2826                                       0, 1, (Pointer)&unitvalue))))
2827                    return ERROR;
2828              if (!(DXSetAttribute((Object)subo, "opacity multiplier",
2829                  (Object)DXAddArrayData(DXNewArray(TYPE_FLOAT,
2830                                                    CATEGORY_REAL, 0),
2831                                       0, 1, (Pointer)&unitopacity))))
2832                    return ERROR;
2833          }
2834       }
2835 
2836 
2837       else {
2838              if (!(DXSetAttribute((Object)g_out, "color multiplier",
2839                  (Object)DXAddArrayData(DXNewArray(TYPE_FLOAT,
2840                                                    CATEGORY_REAL, 0),
2841                                       0, 1, (Pointer)&unitvalue))))
2842                   return ERROR;
2843              if (!(DXSetAttribute((Object)g_out, "opacity multiplier",
2844                  (Object)DXAddArrayData(DXNewArray(TYPE_FLOAT,
2845                                                    CATEGORY_REAL, 0),
2846                                       0, 1, (Pointer)&unitopacity))))
2847                   return ERROR;
2848       }
2849    }
2850    else {
2851       if (!(DXSetAttribute((Object)g_out, "color multiplier",
2852            (Object)DXAddArrayData(DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 0),
2853                                   0, 1, (Pointer)&unitvalue))))
2854                   return ERROR;
2855       if (!(DXSetAttribute((Object)g_out, "opacity multiplier",
2856            (Object)DXAddArrayData(DXNewArray(TYPE_FLOAT, CATEGORY_REAL, 0),
2857                                   0, 1, (Pointer)&unitopacity))))
2858                   return ERROR;
2859    }
2860    return OK;
2861 }
2862