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