GRASS Programmer's Manual
6.4.2(2012)
|
00001 #include <grass/gis.h> 00002 #include <stdlib.h> 00003 00004 #define LOOKUP_COLORS 2048 00005 00006 static int organizing = 0; 00007 static int organize_lookup(struct Colors *, int); 00008 static int organize_fp_lookup(struct Colors *, int); 00009 static int double_comp(const void *, const void *); 00010 00011 int G__organize_colors(struct Colors *colors) 00012 { 00013 /* don't do anything if called recursively */ 00014 if (!organizing) { 00015 organizing = 1; 00016 00017 organize_lookup(colors, 0); 00018 organize_lookup(colors, 1); 00019 00020 organize_fp_lookup(colors, 0); 00021 organize_fp_lookup(colors, 1); 00022 00023 organizing = 0; 00024 } 00025 00026 return 0; 00027 } 00028 00029 static int organize_fp_lookup(struct Colors *colors, int mod) 00030 { 00031 int i; 00032 DCELL val; 00033 struct _Color_Info_ *cp; 00034 struct _Color_Rule_ *rule; 00035 00036 if (mod) 00037 cp = &colors->modular; 00038 else 00039 cp = &colors->fixed; 00040 00041 /* if one of the lookup tables exist, don't do anything */ 00042 if (cp->lookup.active || cp->fp_lookup.active) 00043 return 1; 00044 if (cp->n_rules == 0) 00045 return 1; 00046 00047 cp->fp_lookup.vals = (DCELL *) 00048 G_calloc(cp->n_rules * 2, sizeof(DCELL)); 00049 /* 2 endpoints for each rule */ 00050 cp->fp_lookup.rules = (struct _Color_Rule_ **) 00051 G_calloc(cp->n_rules * 2, sizeof(struct _Color_Rule_ *)); 00052 00053 /* get the list of DCELL values from set of all lows and highs 00054 of all rules */ 00055 /* NOTE: if low==high in a rule, the value appears twice in a list 00056 but if low==high of the previous, rule the value appears only once */ 00057 00058 i = 0; 00059 /* go through the list of rules from end to beginning, 00060 because rules are sored in reverse order of reading, 00061 and we want to read the in correct order, to ignore 00062 the same values in the end of rule and beginning of next rule */ 00063 00064 /* first go to the last rules */ 00065 for (rule = cp->rules; rule->next; rule = rule->next) ; 00066 /* now traverse from the last to the first rule */ 00067 for (; rule; rule = rule->prev) { 00068 /* check if the min is the same as previous maximum */ 00069 if (i == 0 || rule->low.value != cp->fp_lookup.vals[i - 1]) 00070 cp->fp_lookup.vals[i++] = rule->low.value; 00071 cp->fp_lookup.vals[i++] = rule->high.value; 00072 } 00073 cp->fp_lookup.nalloc = i; 00074 00075 /* now sort the values */ 00076 qsort((char *)cp->fp_lookup.vals, cp->fp_lookup.nalloc, 00077 sizeof(DCELL), &double_comp); 00078 00079 /* now find the rule to apply inbetween each 2 values in a list */ 00080 for (i = 0; i < cp->fp_lookup.nalloc - 1; i++) { 00081 val = (cp->fp_lookup.vals[i] + cp->fp_lookup.vals[i + 1]) / 2.; 00082 /* fprintf (stderr, "%lf %lf ", cp->fp_lookup.vals[i], cp->fp_lookup.vals[i+1]); */ 00083 00084 for (rule = cp->rules; rule; rule = rule->next) 00085 if (rule->low.value <= val && val <= rule->high.value) 00086 break; 00087 /* if(rule) fprintf (stderr, "%d %lf %lf %d\n", i, rule->low.value, rule->high.value, rule); 00088 else fprintf (stderr, "null\n"); 00089 */ 00090 cp->fp_lookup.rules[i] = rule; 00091 } 00092 cp->fp_lookup.active = 1; 00093 00094 return 0; 00095 } 00096 00097 static int organize_lookup(struct Colors *colors, int mod) 00098 { 00099 int i, n; 00100 CELL x; 00101 CELL cat[LOOKUP_COLORS]; 00102 struct _Color_Info_ *cp; 00103 00104 /* don't do anything if the color structure is float */ 00105 if (colors->is_float) 00106 return 0; 00107 00108 if (mod) 00109 cp = &colors->modular; 00110 else 00111 cp = &colors->fixed; 00112 00113 if (cp->lookup.active) 00114 return 0; 00115 00116 n = (CELL) cp->max - (CELL) cp->min + 1; 00117 if (n >= LOOKUP_COLORS || n <= 0) 00118 return 0; 00119 00120 x = (CELL) cp->min; 00121 for (i = 0; i < n; i++) 00122 cat[i] = x++;; 00123 00124 cp->lookup.nalloc = n; 00125 cp->lookup.red = (unsigned char *)G_malloc(n); 00126 cp->lookup.grn = (unsigned char *)G_malloc(n); 00127 cp->lookup.blu = (unsigned char *)G_malloc(n); 00128 cp->lookup.set = (unsigned char *)G_malloc(n); 00129 00130 G_zero(cp->lookup.set, n * sizeof(unsigned char)); 00131 G__lookup_colors((void *)cat, 00132 cp->lookup.red, cp->lookup.grn, cp->lookup.blu, 00133 cp->lookup.set, n, colors, mod, 1, CELL_TYPE); 00134 00135 cp->lookup.active = 1; 00136 00137 return 0; 00138 } 00139 00140 static int double_comp(const void *xx, const void *yy) 00141 { 00142 const DCELL *x = xx, *y = yy; 00143 00144 if (*x < *y) 00145 return -1; 00146 else if (*x == *y) 00147 return 0; 00148 else 00149 return 1; 00150 }