1 #include <stdlib.h>
2 
3 #include <grass/gis.h>
4 #include <grass/raster.h>
5 
6 #define LOOKUP_COLORS 2048
7 
8 static void organize_lookup(struct Colors *, int);
9 static int organize_fp_lookup(struct Colors *, int);
10 static int double_comp(const void *, const void *);
11 
Rast__organize_colors(struct Colors * colors)12 void Rast__organize_colors(struct Colors *colors)
13 {
14     /* don't do anything if called recursively */
15     if (!colors->organizing) {
16 	colors->organizing = 1;
17 
18 	organize_lookup(colors, 0);
19 	organize_lookup(colors, 1);
20 
21 	organize_fp_lookup(colors, 0);
22 	organize_fp_lookup(colors, 1);
23 
24 	colors->organizing = 0;
25     }
26 }
27 
organize_fp_lookup(struct Colors * colors,int mod)28 static int organize_fp_lookup(struct Colors *colors, int mod)
29 {
30     int i;
31     DCELL val;
32     struct _Color_Info_ *cp;
33     struct _Color_Rule_ *rule;
34 
35     if (mod)
36 	cp = &colors->modular;
37     else
38 	cp = &colors->fixed;
39 
40     /* if one of the lookup tables exist, don't do anything */
41     if (cp->lookup.active || cp->fp_lookup.active)
42 	return 1;
43     if (cp->n_rules == 0)
44 	return 1;
45 
46     cp->fp_lookup.vals = (DCELL *)
47 	G_calloc(cp->n_rules * 2, sizeof(DCELL));
48     /* 2 endpoints for each rule */
49     cp->fp_lookup.rules = (struct _Color_Rule_ **)
50 	G_calloc(cp->n_rules * 2, sizeof(struct _Color_Rule_ *));
51 
52     /* get the list of DCELL values from set of all lows and highs
53        of all rules */
54     /* NOTE: if low==high in a rule, the value appears twice in a list
55        but if low==high of the previous, rule the value appears only once */
56 
57     i = 0;
58     /* go through the list of rules from end to beginning,
59        because rules are sored in reverse order of reading,
60        and we want to read the in correct order, to ignore
61        the same values in the end of rule and beginning of next rule */
62 
63     /* first go to the last rules */
64     for (rule = cp->rules; rule->next; rule = rule->next) ;
65     /* now traverse from the last to the first rule */
66     for (; rule; rule = rule->prev) {
67 	/* check if the min is the same as previous maximum */
68 	if (i == 0 || rule->low.value != cp->fp_lookup.vals[i - 1])
69 	    cp->fp_lookup.vals[i++] = rule->low.value;
70 	cp->fp_lookup.vals[i++] = rule->high.value;
71     }
72     cp->fp_lookup.nalloc = i;
73 
74     /* now sort the values */
75     qsort((char *)cp->fp_lookup.vals, cp->fp_lookup.nalloc,
76 	  sizeof(DCELL), &double_comp);
77 
78     /* now find the rule to apply between each 2 values in a list */
79     for (i = 0; i < cp->fp_lookup.nalloc - 1; i++) {
80 	val = (cp->fp_lookup.vals[i] + cp->fp_lookup.vals[i + 1]) / 2.;
81 	/* fprintf (stderr, "%lf %lf ", cp->fp_lookup.vals[i], cp->fp_lookup.vals[i+1]); */
82 
83 	for (rule = cp->rules; rule; rule = rule->next)
84 	    if (rule->low.value <= val && val <= rule->high.value)
85 		break;
86 	/* if(rule) fprintf (stderr, "%d %lf %lf %d\n", i, rule->low.value, rule->high.value, rule);
87 	   else fprintf (stderr, "null\n");
88 	 */
89 	cp->fp_lookup.rules[i] = rule;
90     }
91     cp->fp_lookup.active = 1;
92 
93     return 0;
94 }
95 
organize_lookup(struct Colors * colors,int mod)96 static void organize_lookup(struct Colors *colors, int mod)
97 {
98     int i, n;
99     CELL x;
100     CELL cat[LOOKUP_COLORS];
101     struct _Color_Info_ *cp;
102 
103     /* don't do anything if the color structure is float */
104     if (colors->is_float)
105 	return;
106 
107     if (mod)
108 	cp = &colors->modular;
109     else
110 	cp = &colors->fixed;
111 
112     if (cp->lookup.active)
113 	return;
114 
115     n = (CELL) cp->max - (CELL) cp->min + 1;
116     if (n >= LOOKUP_COLORS || n <= 0)
117 	return;
118 
119     x = (CELL) cp->min;
120     for (i = 0; i < n; i++)
121 	cat[i] = x++;;
122 
123     cp->lookup.nalloc = n;
124     cp->lookup.red = (unsigned char *)G_malloc(n);
125     cp->lookup.grn = (unsigned char *)G_malloc(n);
126     cp->lookup.blu = (unsigned char *)G_malloc(n);
127     cp->lookup.set = (unsigned char *)G_malloc(n);
128 
129     G_zero(cp->lookup.set, n * sizeof(unsigned char));
130     Rast__lookup_colors((void *)cat,
131 			cp->lookup.red, cp->lookup.grn, cp->lookup.blu,
132 			cp->lookup.set, n, colors, mod, 1, CELL_TYPE);
133 
134     cp->lookup.active = 1;
135 }
136 
double_comp(const void * xx,const void * yy)137 static int double_comp(const void *xx, const void *yy)
138 {
139     const DCELL *x = xx, *y = yy;
140 
141     if (*x < *y)
142 	return -1;
143     else if (*x == *y)
144 	return 0;
145     else
146 	return 1;
147 }
148