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