GRASS Programmer's Manual
6.4.1(2011)
|
00001 00002 /********************************************************************** 00003 * 00004 * G_quant_init (quant) 00005 * struct Quant *quant; 00006 * 00007 * initializes new quantization structure. calls 00008 * G_quant_clear() before it returns. 00009 * 00010 * note: dies if G_malloc dies. 00011 * 00012 ********************************************************************** 00013 * 00014 * G_quant_is_truncate (quant) 00015 * struct Quant *quant; 00016 * 00017 * Returns wether or not quant rules are set to truncate map 00018 * 00019 ********************************************************************** 00020 * 00021 * G_quant_is_round (quant) 00022 * struct Quant *quant; 00023 * 00024 * Returns wether or not quant rules are set to round map 00025 * 00026 ********************************************************************** 00027 * 00028 * G_quant_truncate (quant) 00029 * struct Quant *quant; 00030 * 00031 * sets the quant rules to perform simple truncation on floats. 00032 * 00033 ********************************************************************** 00034 * 00035 * G_quant_round (quant) 00036 * struct Quant *quant; 00037 * 00038 * sets the quant rules to perform simple rounding on floats. 00039 * 00040 ********************************************************************** 00041 * 00042 * G_quant_organize_fp_lookup (quant) 00043 * struct Quant *quant; 00044 * 00045 * Organizes fp_lookup table for faster (logarithmic) lookup time 00046 * G_quant_organize_fp_lookup() creates a list of min and max for 00047 * each quant rule, sorts this list, and stores the pointer to quant 00048 * rule that should be used inbetween any 2 numbers in this list. 00049 * Also it stores extreme points for 2 infinite rules, if exist. 00050 * After the call to G_quant_organize_fp_lookup() 00051 * instead of linearly searching through list of rules to find 00052 * a rule to apply, quant lookup will perform a binary search 00053 * to find an interval containing floating point value, and then use 00054 * the rule associated with this interval. 00055 * when the value doesn't fall within any interval, check for the 00056 * infinite rules. 00057 * 00058 ********************************************************************** 00059 * 00060 * void 00061 * G_quant_free (q) 00062 * 00063 * struct Quant *q; 00064 * 00065 * resets the number of defined rules to 0 and free's space allocated 00066 * for rules. calls G_quant_clear (). 00067 * 00068 ********************************************************************** 00069 * 00070 * void 00071 * G_quant_clear (q) 00072 * 00073 * struct Quant *q; 00074 * 00075 * resets the number of defined rules and number of infinite rules to 0. 00076 * 00077 ********************************************************************** 00078 * 00079 * int 00080 * G_quant_get_limits (q, dMin, dMax, cMin, cMax) 00081 * 00082 * struct Quant *q; 00083 * DCELL *dMin, *dMax; 00084 * CELL *cMin, *cMax; 00085 * 00086 * returns the minimum and maximum cell and dcell values of all 00087 * the ranges defined. 00088 * 00089 * returns: -1 if q->truncate or q->round are true or 00090 after G_quant_init (), or any call to 00091 * G_quant_clear () or G_quant_free () 00092 * no explicit rules have been added 00093 * In this case the returned minimum and maximum 00094 * CELL and DCELL values are null. 00095 * 1 otherwise. in this case the values returned correspond 00096 * to the extreme values of the defined rules 00097 * 00098 ********************************************************************** 00099 * 00100 * int 00101 * G_quant_nof_rules (q) 00102 * 00103 * struct Quant *q; 00104 * 00105 * returns the number of quantization rules defined. This number does 00106 * not include the 2 infinite intervals. 00107 * 00108 ********************************************************************** 00109 * 00110 * void 00111 * G_quant_get_ith_rule (q, i, dLow, dHigh, cLow, cHigh) 00112 * 00113 * struct Quant *q; 00114 * int i; 00115 * DCELL *dLow, *dHigh; 00116 * CELL *cLow, *cHigh; 00117 * 00118 * returns the i'th quantization rule, for 0 <= i < G_quant_nof_rules(). 00119 * a larger value for i means that the rule has been added later. 00120 * 00121 ********************************************************************** 00122 * void 00123 * G_quant_set_neg_infinite_rule (q, dLeft, c) 00124 * 00125 * struct Quant *q; 00126 * DCELL dLeft; 00127 * CELL c; 00128 * 00129 * defines a rule for values "dLeft" and smaller. values in this range 00130 * are mapped to "c" if none of the "finite" quantization rules applies. 00131 * 00132 * ********************************************************************** 00133 * 00134 * int 00135 * G_quant_get_neg_infinite_rule (q, dLeft, c) 00136 * 00137 * struct Quant *q; 00138 * DCELL *dLeft; 00139 * CELL *c; 00140 * 00141 * returns in "dLeft" and "c" the rule values for the negative infinite 00142 * interval (see G_quant_set_neg_infinite_rule ()). 00143 * 00144 * returns: 0 if this rule is not defined 00145 * 1 otherwise. 00146 * 00147 * ********************************************************************** 00148 * 00149 * struct Quant_table * 00150 * G__quant_get_rule_for_d_raster_val (q, val) 00151 * 00152 * struct Quant *q; 00153 * DCELL val; 00154 * 00155 * returns quant rule which will be applied when looking up the 00156 * integer quant value for val. (used when organizing fp_lookup. 00157 * 00158 * returns: pointer to the Quant_table (color rule) 00159 * NULL otherwise. 00160 * 00161 ********************************************************************** 00162 * void 00163 * G_quant_set_pos_infinite_rule (q, dRight, c) 00164 * 00165 * struct Quant *q; 00166 * DCELL dRight; 00167 * CELL c; 00168 * 00169 * defines a rule for values "dRight" and larger. values in this range 00170 * are mapped to "c" if none of the "finite" quantization rules or the 00171 * negative infinite rule applies. 00172 * 00173 * ********************************************************************** 00174 * 00175 * int 00176 * G_quant_get_pos_infinite_rule (q, dRight, c) 00177 * 00178 * struct Quant *q; 00179 * DCELL *dRight; 00180 * CELL *c; 00181 * 00182 * returns in "dRight" and "c" the rule values for the positive infinite 00183 * interval (see G_quant_set_pos_infinite_rule ()). 00184 * 00185 * returns: 0 if this rule is not defined 00186 * 1 otherwise. 00187 * 00188 ********************************************************************** 00189 * 00190 * void 00191 * G_quant_reverse_rule_order (q) 00192 * 00193 * struct Quant *q; 00194 * 00195 * reverses the order in which the qunatization rules are stored. (see 00196 * also G_quant_get_ith_rule () and G_quant_perform_d ()). 00197 * 00198 ********************************************************************** 00199 * 00200 * void 00201 * G_quant_add_rule (q, dLow, dHigh, cLow, cHigh) 00202 * 00203 * struct Quant *q; 00204 * DCELL dLow, dHigh; 00205 * CELL cLow, cHigh; 00206 * 00207 * adds a new rule to the set of quantization rules. if dLow < dHigh 00208 * the rule will be stored with the low and high values interchanged. 00209 * 00210 * Note: currently no cleanup of rules is performed, i.e. redundant 00211 * rules are not removed. This can't be changed because Categories 00212 * structure HEAVILY depends of quant rules stored in exactly the 00213 * same order they are entered. So if the cleanup or rearrangement 00214 * is done in the future make a flag for add_rule wether or not 00215 * to do it, then quant will not set this flag. 00216 * 00217 ********************************************************************** 00218 * 00219 * CELL 00220 * G_quant_get_cell_value (q, cellValue) 00221 * 00222 * struct Quant *q; 00223 * DCELL *cellValue; 00224 * 00225 * returns in "cell" the quantized CELL values corresponding to the 00226 * DCELL value "cellValue". 00227 * 00228 * if several quantization rules apply for cellValue, the one which has 00229 * been inserted latest (i.e. the one of them which is returned by 00230 * G_quant_get_ith_rule() for the largest i) is used. if no such rule 00231 * applies the cellValue is first tested against the negative infinite 00232 * rule, and finally against the positive infinite rule. if none of 00233 * these rules apply, NO_DATA is returned. the actual value of NO_DATA 00234 * is found by calling G_c_set_null_value(). 00235 * 00236 * NOTE: see G_quant_organize_fp_lookup() for details on how 00237 * the values are looked up from fp_lookup table when it is active. 00238 * 00239 * if after G_quant_init (), or any call to G_quant_clear () or 00240 * G_quant_free () neither G_quant_add_rule (), 00241 * G_quant_set_neg_infinite_rule (), G_quant_set_pos_infinite_rule () 00242 * are used NO_DATA is returned independently 00243 * of cellValue. 00244 * 00245 ********************************************************************** 00246 * 00247 * void 00248 * G_quant_perform_d (q, dcell, cell, n) 00249 * 00250 * struct Quant *q; 00251 * DCELL *dcell; 00252 * CELL *cell; 00253 * int n; 00254 * 00255 * returns in "cell" the quantized CELL values corresponding to the 00256 * DCELL values stored in "dcell". the number of elements quantized 00257 * is n. quantization is performed by repeated application of 00258 * G_quant_get_cell_value (). 00259 * 00260 ********************************************************************** 00261 * 00262 * void 00263 * G_quant_perform_f (q, fcell, cell, n) 00264 * 00265 * struct Quant *q; 00266 * FCELL *fcell; 00267 * CELL *cell; 00268 * int n; 00269 * 00270 * same as G_quant_perform_d (), except the type. 00271 * 00272 **********************************************************************/ 00273 00274 /*--------------------------------------------------------------------------*/ 00275 00276 /* 00277 the quantization table is stored as a linear array. rules are added starting 00278 from index 0. redundant rules are not eliminated. rules are tested from the 00279 highest index downto 0. there are two "infinite" rules. support is provided 00280 to reverse the order of the rules. 00281 */ 00282 00283 /*--------------------------------------------------------------------------*/ 00284 00285 #include <stdlib.h> 00286 #include <grass/gis.h> 00287 00288 /*--------------------------------------------------------------------------*/ 00289 static int double_comp(const void *, const void *); 00290 00291 #define USE_LOOKUP 1 00292 #define MAX_LOOKUP_TABLE_SIZE 2048 00293 #define NO_DATA (G_set_c_null_value (&tmp, 1), (CELL) tmp) 00294 00295 #undef MIN 00296 #undef MAX 00297 #define MIN(a,b) ((a) < (b) ? (a) : (b)) 00298 #define MAX(a,b) ((a) > (b) ? (a) : (b)) 00299 00300 #define NO_LEFT_INFINITE_RULE (! q->infiniteLeftSet) 00301 #define NO_RIGHT_INFINITE_RULE (! q->infiniteRightSet) 00302 #define NO_FINITE_RULE (q->nofRules <= 0) 00303 #define NO_EXPLICIT_RULE (NO_FINITE_RULE && \ 00304 NO_LEFT_INFINITE_RULE && NO_RIGHT_INFINITE_RULE) 00305 00306 /*--------------------------------------------------------------------------*/ 00307 00308 void G_quant_clear(struct Quant *q) 00309 { 00310 q->nofRules = 0; 00311 q->infiniteRightSet = q->infiniteLeftSet = 0; 00312 } 00313 00314 /*--------------------------------------------------------------------------*/ 00315 00316 void G_quant_free(struct Quant *q) 00317 { 00318 G_quant_clear(q); 00319 00320 if (q->maxNofRules > 0) 00321 G_free(q->table); 00322 if (q->fp_lookup.active) { 00323 G_free(q->fp_lookup.vals); 00324 G_free(q->fp_lookup.rules); 00325 q->fp_lookup.nalloc = 0; 00326 q->fp_lookup.active = 0; 00327 } 00328 q->maxNofRules = 0; 00329 } 00330 00331 /*--------------------------------------------------------------------------*/ 00332 00333 int G__quant_organize_fp_lookup(struct Quant *q) 00334 { 00335 int i; 00336 DCELL val; 00337 CELL tmp; 00338 struct Quant_table *p; 00339 00340 if (q->nofRules * 2 > MAX_LOOKUP_TABLE_SIZE) 00341 return -1; 00342 if (q->nofRules == 0) 00343 return -1; 00344 q->fp_lookup.vals = (DCELL *) 00345 G_calloc(q->nofRules * 2, sizeof(DCELL)); 00346 /* 2 endpoints for each rule */ 00347 q->fp_lookup.rules = (struct Quant_table **) 00348 G_calloc(q->nofRules * 2, sizeof(struct Quant_table *)); 00349 00350 /* first we organize finite rules into a table */ 00351 if (!NO_FINITE_RULE) { 00352 i = 0; 00353 /* get the list of DCELL values from set of all dLows and dHighs 00354 of all rules */ 00355 /* NOTE: if dLow==DHigh in a rule, the value appears twice in a list 00356 but if dLow==DHigh of the previous, rule the value appears only once */ 00357 00358 for (p = &(q->table[q->nofRules - 1]); p >= q->table; p--) { 00359 /* check if the min is the same as previous maximum */ 00360 if (i == 0 || p->dLow != q->fp_lookup.vals[i - 1]) 00361 q->fp_lookup.vals[i++] = p->dLow; 00362 q->fp_lookup.vals[i++] = p->dHigh; 00363 } 00364 q->fp_lookup.nalloc = i; 00365 00366 /* now sort the values */ 00367 qsort((char *)q->fp_lookup.vals, q->fp_lookup.nalloc, 00368 sizeof(DCELL), double_comp); 00369 00370 /* now find the rule to apply inbetween each 2 values in a list */ 00371 for (i = 0; i < q->fp_lookup.nalloc - 1; i++) { 00372 /*debug 00373 fprintf (stderr, "%lf %lf ", q->fp_lookup.vals[i], q->fp_lookup.vals[i+1]); 00374 */ 00375 val = (q->fp_lookup.vals[i] + q->fp_lookup.vals[i + 1]) / 2.; 00376 q->fp_lookup.rules[i] = 00377 G__quant_get_rule_for_d_raster_val(q, val); 00378 /* debug 00379 if(q->fp_lookup.rules[i]) 00380 fprintf (stderr, "%lf %lf %d %d\n", q->fp_lookup.rules[i]->dLow, q->fp_lookup.rules[i]->dHigh, q->fp_lookup.rules[i]->cLow, q->fp_lookup.rules[i]->cHigh); 00381 else fprintf (stderr, "null\n"); 00382 */ 00383 00384 } 00385 } /* organizing finite rules */ 00386 00387 if (!NO_LEFT_INFINITE_RULE) { 00388 q->fp_lookup.inf_dmin = q->infiniteDLeft; 00389 q->fp_lookup.inf_min = q->infiniteCLeft; 00390 } 00391 else { 00392 if (q->fp_lookup.nalloc) 00393 q->fp_lookup.inf_dmin = q->fp_lookup.vals[0]; 00394 q->fp_lookup.inf_min = NO_DATA; 00395 } 00396 00397 if (!NO_RIGHT_INFINITE_RULE) { 00398 if (q->fp_lookup.nalloc) 00399 q->fp_lookup.inf_dmax = q->infiniteDRight; 00400 q->fp_lookup.inf_max = q->infiniteCRight; 00401 } 00402 else { 00403 q->fp_lookup.inf_dmax = q->fp_lookup.vals[q->fp_lookup.nalloc - 1]; 00404 q->fp_lookup.inf_max = NO_DATA; 00405 } 00406 q->fp_lookup.active = 1; 00407 return 1; 00408 } 00409 00410 /*--------------------------------------------------------------------------*/ 00411 00412 00422 int G_quant_init(struct Quant *quant) 00423 { 00424 quant->fp_lookup.active = 0; 00425 quant->maxNofRules = 0; 00426 quant->truncate_only = 0; 00427 quant->round_only = 0; 00428 G_quant_clear(quant); 00429 00430 return 1; 00431 } 00432 00433 /*--------------------------------------------------------------------------*/ 00434 00435 int G_quant_is_truncate(const struct Quant *quant) 00436 { 00437 return quant->truncate_only; 00438 } 00439 00440 /*--------------------------------------------------------------------------*/ 00441 00442 int G_quant_is_round(const struct Quant *quant) 00443 { 00444 return quant->round_only; 00445 } 00446 00447 /*--------------------------------------------------------------------------*/ 00448 00449 00471 int G_quant_truncate(struct Quant *quant) 00472 { 00473 quant->truncate_only = 1; 00474 return 1; 00475 } 00476 00477 /*--------------------------------------------------------------------------*/ 00478 00479 int G_quant_round(struct Quant *quant) 00480 { 00481 quant->round_only = 1; 00482 return 1; 00483 } 00484 00485 /*--------------------------------------------------------------------------*/ 00486 00487 static void quant_set_limits(struct Quant *q, 00488 DCELL dLow, DCELL dHigh, CELL cLow, CELL cHigh) 00489 { 00490 q->dMin = dLow; 00491 q->dMax = dHigh; 00492 q->cMin = cLow; 00493 q->cMax = cHigh; 00494 } 00495 00496 /*--------------------------------------------------------------------------*/ 00497 00498 static void quant_update_limits(struct Quant *q, 00499 DCELL dLow, DCELL dHigh, 00500 CELL cLow, DCELL cHigh) 00501 { 00502 if (NO_EXPLICIT_RULE) { 00503 quant_set_limits(q, dLow, dHigh, cLow, cHigh); 00504 return; 00505 } 00506 00507 q->dMin = MIN(q->dMin, MIN(dLow, dHigh)); 00508 q->dMax = MAX(q->dMax, MAX(dLow, dHigh)); 00509 q->cMin = MIN(q->cMin, MIN(cLow, cHigh)); 00510 q->cMax = MAX(q->cMax, MAX(cLow, cHigh)); 00511 } 00512 00513 /*--------------------------------------------------------------------------*/ 00514 00515 00534 int G_quant_get_limits(const struct Quant *q, 00535 DCELL * dMin, DCELL * dMax, CELL * cMin, CELL * cMax) 00536 { 00537 if (NO_EXPLICIT_RULE) { 00538 G_set_c_null_value(cMin, 1); 00539 G_set_c_null_value(cMax, 1); 00540 G_set_d_null_value(dMin, 1); 00541 G_set_d_null_value(dMax, 1); 00542 return -1; 00543 } 00544 00545 *dMin = q->dMin; 00546 *dMax = q->dMax; 00547 *cMin = q->cMin; 00548 *cMax = q->cMax; 00549 00550 return 1; 00551 } 00552 00553 /*--------------------------------------------------------------------------*/ 00554 00555 int G_quant_nof_rules(const struct Quant *q) 00556 { 00557 return q->nofRules; 00558 } 00559 00560 /*--------------------------------------------------------------------------*/ 00561 00562 void G_quant_get_ith_rule(const struct Quant *q, 00563 int i, 00564 DCELL * dLow, DCELL * dHigh, 00565 CELL * cLow, CELL * cHigh) 00566 { 00567 *dLow = q->table[i].dLow; 00568 *dHigh = q->table[i].dHigh; 00569 *cLow = q->table[i].cLow; 00570 *cHigh = q->table[i].cHigh; 00571 } 00572 00573 /*--------------------------------------------------------------------------*/ 00574 00575 static void quant_table_increase(struct Quant *q) 00576 { 00577 if (q->nofRules < q->maxNofRules) 00578 return; 00579 00580 if (q->maxNofRules == 0) { 00581 q->maxNofRules = 50; 00582 q->table = (struct Quant_table *) 00583 G_malloc(q->maxNofRules * sizeof(struct Quant_table)); 00584 } 00585 else { 00586 q->maxNofRules += 50; 00587 q->table = (struct Quant_table *) 00588 G_realloc((char *)q->table, 00589 q->maxNofRules * sizeof(struct Quant_table)); 00590 } 00591 } 00592 00593 /*--------------------------------------------------------------------------*/ 00594 00595 void G_quant_set_neg_infinite_rule(struct Quant *q, DCELL dLeft, CELL c) 00596 { 00597 q->infiniteDLeft = dLeft; 00598 q->infiniteCLeft = c; 00599 quant_update_limits(q, dLeft, dLeft, c, c); 00600 00601 /* update lookup table */ 00602 if (q->fp_lookup.active) { 00603 q->fp_lookup.inf_dmin = q->infiniteDLeft; 00604 q->fp_lookup.inf_min = q->infiniteCLeft; 00605 } 00606 q->infiniteLeftSet = 1; 00607 } 00608 00609 /*--------------------------------------------------------------------------*/ 00610 00611 int G_quant_get_neg_infinite_rule(const struct Quant *q, 00612 DCELL * dLeft, CELL * c) 00613 { 00614 if (q->infiniteLeftSet == 0) 00615 return 0; 00616 00617 *dLeft = q->infiniteDLeft; 00618 *c = q->infiniteCLeft; 00619 00620 return 1; 00621 } 00622 00623 /*--------------------------------------------------------------------------*/ 00624 00625 void G_quant_set_pos_infinite_rule(struct Quant *q, DCELL dRight, CELL c) 00626 { 00627 q->infiniteDRight = dRight; 00628 q->infiniteCRight = c; 00629 quant_update_limits(q, dRight, dRight, c, c); 00630 00631 /* update lookup table */ 00632 if (q->fp_lookup.active) { 00633 q->fp_lookup.inf_dmax = q->infiniteDRight; 00634 q->fp_lookup.inf_max = q->infiniteCRight; 00635 } 00636 q->infiniteRightSet = 1; 00637 } 00638 00639 /*--------------------------------------------------------------------------*/ 00640 00641 int G_quant_get_pos_infinite_rule(const struct Quant *q, 00642 DCELL * dRight, CELL * c) 00643 { 00644 if (q->infiniteRightSet == 0) 00645 return 0; 00646 00647 *dRight = q->infiniteDRight; 00648 *c = q->infiniteCRight; 00649 00650 return 1; 00651 } 00652 00653 /*--------------------------------------------------------------------------*/ 00654 00655 void G_quant_add_rule(struct Quant *q, 00656 DCELL dLow, DCELL dHigh, CELL cLow, CELL cHigh) 00657 { 00658 int i; 00659 struct Quant_table *p; 00660 00661 quant_table_increase(q); 00662 00663 i = q->nofRules; 00664 00665 p = &(q->table[i]); 00666 if (dHigh >= dLow) { 00667 p->dLow = dLow; 00668 p->dHigh = dHigh; 00669 p->cLow = cLow; 00670 p->cHigh = cHigh; 00671 } 00672 else { 00673 p->dLow = dHigh; 00674 p->dHigh = dLow; 00675 p->cLow = cHigh; 00676 p->cHigh = cLow; 00677 } 00678 00679 /* destroy lookup table, it has to be rebuilt */ 00680 if (q->fp_lookup.active) { 00681 G_free(q->fp_lookup.vals); 00682 G_free(q->fp_lookup.rules); 00683 q->fp_lookup.active = 0; 00684 q->fp_lookup.nalloc = 0; 00685 } 00686 00687 quant_update_limits(q, dLow, dHigh, cLow, cHigh); 00688 00689 q->nofRules++; 00690 } 00691 00692 /*--------------------------------------------------------------------------*/ 00693 00694 void G_quant_reverse_rule_order(struct Quant *q) 00695 { 00696 struct Quant_table tmp; 00697 struct Quant_table *pLeft, *pRight; 00698 00699 pLeft = q->table; 00700 pRight = &(q->table[q->nofRules - 1]); 00701 00702 while (pLeft < pRight) { 00703 tmp.dLow = pLeft->dLow; 00704 tmp.dHigh = pLeft->dHigh; 00705 tmp.cLow = pLeft->cLow; 00706 tmp.cHigh = pLeft->cHigh; 00707 00708 pLeft->dLow = pRight->dLow; 00709 pLeft->dHigh = pRight->dHigh; 00710 pLeft->cLow = pRight->cLow; 00711 pLeft->cHigh = pRight->cHigh; 00712 00713 pRight->dLow = tmp.dLow; 00714 pRight->dHigh = tmp.dHigh; 00715 pRight->cLow = tmp.cLow; 00716 pRight->cHigh = tmp.cHigh; 00717 00718 pLeft++; 00719 pRight--; 00720 } 00721 } 00722 00723 /*--------------------------------------------------------------------------*/ 00724 00725 static CELL quant_interpolate(DCELL dLow, DCELL dHigh, 00726 CELL cLow, CELL cHigh, DCELL dValue) 00727 { 00728 if (cLow == cHigh) 00729 return cLow; 00730 if (dLow == dHigh) 00731 return cLow; 00732 00733 return (CELL) ((dValue - dLow) / (dHigh - dLow) * (DCELL) (cHigh - cLow) + 00734 (DCELL) cLow); 00735 } 00736 00737 /*--------------------------------------------------------------------------*/ 00738 static int less_or_equal(double x, double y) 00739 { 00740 if (x <= y) 00741 return 1; 00742 else 00743 return 0; 00744 } 00745 00746 static int less(double x, double y) 00747 { 00748 if (x < y) 00749 return 1; 00750 else 00751 return 0; 00752 } 00753 00754 00775 CELL G_quant_get_cell_value(struct Quant * q, DCELL dcellVal) 00776 { 00777 CELL tmp; 00778 DCELL dtmp; 00779 int try, min_ind, max_ind; 00780 struct Quant_table *p; 00781 int (*lower) (); 00782 00783 dtmp = dcellVal; 00784 /* I know the functions which call me already check for null values, 00785 but I am a public function, and can be called from outside */ 00786 if (G_is_d_null_value(&dtmp)) 00787 return NO_DATA; 00788 00789 if (q->truncate_only) 00790 return (CELL) dtmp; 00791 00792 if (q->round_only) { 00793 if (dcellVal > 0) 00794 return (CELL) (dcellVal + .5); 00795 return (CELL) (dcellVal - .5); 00796 } 00797 00798 if (NO_EXPLICIT_RULE) 00799 return NO_DATA; 00800 if (NO_EXPLICIT_RULE) 00801 return NO_DATA; 00802 00803 if (USE_LOOKUP && 00804 (q->fp_lookup.active || G__quant_organize_fp_lookup(q) > 0)) { 00805 /* first check if values fall within range */ 00806 /* if value is below the range */ 00807 if (dcellVal < q->fp_lookup.vals[0]) { 00808 if (dcellVal <= q->fp_lookup.inf_dmin) 00809 return q->fp_lookup.inf_min; 00810 else 00811 return NO_DATA; 00812 } 00813 /* if value is below above range */ 00814 if (dcellVal > q->fp_lookup.vals[q->fp_lookup.nalloc - 1]) { 00815 if (dcellVal >= q->fp_lookup.inf_dmax) 00816 return q->fp_lookup.inf_max; 00817 else 00818 return NO_DATA; 00819 } 00820 /* make binary search to find which interval our value belongs to 00821 and apply the rule for this interval */ 00822 try = (q->fp_lookup.nalloc - 1) / 2; 00823 min_ind = 0; 00824 max_ind = q->fp_lookup.nalloc - 2; 00825 while (1) { 00826 /* DEBUG 00827 fprintf (stderr, "%d %d %d\n", min_ind, max_ind, try); 00828 */ 00829 /* when the ruke for the interval is NULL, we exclude the end points. 00830 when it exists, we include the end-points */ 00831 if (q->fp_lookup.rules[try]) 00832 lower = less; 00833 else 00834 lower = less_or_equal; 00835 00836 if (lower(q->fp_lookup.vals[try + 1], dcellVal)) { /* recurse to the second half */ 00837 min_ind = try + 1; 00838 /* must be still < nalloc-1, since number is within the range */ 00839 try = (max_ind + min_ind) / 2; 00840 continue; 00841 } 00842 if (lower(dcellVal, q->fp_lookup.vals[try])) { /* recurse to the second half */ 00843 max_ind = try - 1; 00844 /* must be still >= 0, since number is within the range */ 00845 try = (max_ind + min_ind) / 2; 00846 continue; 00847 } 00848 /* the value fits into the interval! */ 00849 p = q->fp_lookup.rules[try]; 00850 if (p) 00851 return quant_interpolate(p->dLow, p->dHigh, p->cLow, p->cHigh, 00852 dcellVal); 00853 /* otherwise when finite rule for this interval doesn't exist */ 00854 else { /* first check if maybe infinite rule applies */ 00855 if (dcellVal <= q->fp_lookup.inf_dmin) 00856 return q->fp_lookup.inf_min; 00857 if (dcellVal >= q->fp_lookup.inf_dmax) 00858 return q->fp_lookup.inf_max; 00859 else 00860 return NO_DATA; 00861 } 00862 } /* while */ 00863 } /* looking up in fp_lookup */ 00864 00865 if (!NO_FINITE_RULE) { 00866 p = G__quant_get_rule_for_d_raster_val(q, dcellVal); 00867 if (!p) 00868 return NO_DATA; 00869 return quant_interpolate(p->dLow, p->dHigh, p->cLow, p->cHigh, 00870 dcellVal); 00871 } 00872 00873 if ((!NO_LEFT_INFINITE_RULE) && (dcellVal <= q->infiniteDLeft)) 00874 return q->infiniteCLeft; 00875 00876 if ((NO_RIGHT_INFINITE_RULE) || (dcellVal < q->infiniteDRight)) 00877 return NO_DATA; 00878 00879 return q->infiniteCRight; 00880 } 00881 00882 /*--------------------------------------------------------------------------*/ 00883 00884 void G_quant_perform_d(struct Quant *q, 00885 const DCELL * dcell, CELL * cell, int n) 00886 { 00887 int i; 00888 00889 for (i = 0; i < n; i++, dcell++) 00890 if (!G_is_d_null_value(dcell)) 00891 *cell++ = G_quant_get_cell_value(q, *dcell); 00892 else 00893 G_set_c_null_value(cell++, 1); 00894 } 00895 00896 /*--------------------------------------------------------------------------*/ 00897 00898 void G_quant_perform_f(struct Quant *q, 00899 const FCELL * fcell, CELL * cell, int n) 00900 { 00901 int i; 00902 00903 for (i = 0; i < n; i++, fcell++) 00904 if (!G_is_f_null_value(fcell)) 00905 *cell++ = G_quant_get_cell_value(q, (DCELL) * fcell); 00906 else 00907 G_set_c_null_value(cell++, 1); 00908 } 00909 00910 /*--------------------------------------------------------------------------*/ 00911 00912 static int double_comp(const void *xx, const void *yy) 00913 { 00914 const DCELL *x = xx; 00915 const DCELL *y = yy; 00916 00917 if (G_is_d_null_value(x)) 00918 return 0; 00919 if (*x < *y) 00920 return -1; 00921 else if (*x == *y) 00922 return 0; 00923 else 00924 return 1; 00925 } 00926 00927 /*--------------------------------------------------------------------------*/ 00928 00929 struct Quant_table *G__quant_get_rule_for_d_raster_val(const struct Quant *q, 00930 DCELL val) 00931 { 00932 const struct Quant_table *p; 00933 00934 for (p = &(q->table[q->nofRules - 1]); p >= q->table; p--) 00935 if ((val >= p->dLow) && (val <= p->dHigh)) 00936 break; 00937 if (p >= q->table) 00938 return (struct Quant_table *)p; 00939 else 00940 return (struct Quant_table *)NULL; 00941 } 00942 00943 /*--------------------------------------------------------------------------*/ 00944 00945 /*--------------------------------------------------------------------------*/ 00946 00947 /*--------------------------------------------------------------------------*/