static inline double interpolate_point_internal(const stp_curve_t *curve, double where) { int integer = where; double frac = where - (double) integer; double bhi, blo; if (frac == 0.0) { double val; if ((stp_sequence_get_point(curve->seq, integer, &val)) == 0) return HUGE_VAL; /* Infinity */ return val; } if (curve->recompute_interval) compute_intervals((stpi_cast_safe(curve))); if (curve->curve_type == STP_CURVE_TYPE_LINEAR) { double val; if ((stp_sequence_get_point(curve->seq, integer, &val)) == 0) return HUGE_VAL; /* Infinity */ return val + frac * curve->interval[integer]; } else { size_t point_count; double ival, ip1val; double retval; int i = integer; int ip1 = integer + 1; point_count = get_point_count(curve); if (ip1 >= point_count) ip1 -= point_count; if ((stp_sequence_get_point(curve->seq, i, &ival)) == 0 || (stp_sequence_get_point(curve->seq, ip1, &ip1val)) == 0) return HUGE_VAL; /* Infinity */ retval = do_interpolate_spline(ival, ip1val, frac, curve->interval[i], curve->interval[ip1], 1.0); stp_sequence_get_bounds(curve->seq, &blo, &bhi); if (retval > bhi) retval = bhi; if (retval < blo) retval = blo; return retval; } }
int stp_curve_get_point(const stp_curve_t *curve, size_t where, double *data) { CHECK_CURVE(curve); if (where >= get_point_count(curve)) return 0; if (curve->piecewise) return 0; return stp_sequence_get_point(curve->seq, where, data); }
int stp_array_get_point(const stp_array_t *array, int x, int y, double *data) { check_array(array); if (((array->x_size * x) + y) >= array->x_size * array->y_size) return 0; return stp_sequence_get_point(array->data, (array->x_size * x) + y, data); }
int stp_curve_resample(stp_curve_t *curve, size_t points) { size_t limit = points; size_t old; size_t i; double *new_vec; CHECK_CURVE(curve); if (points == get_point_count(curve) && curve->seq && !(curve->piecewise)) return 1; if (points < 2) return 1; if (curve->wrap_mode == STP_CURVE_WRAP_AROUND) limit++; if (limit > curve_point_limit) return 0; old = get_real_point_count(curve); if (old) old--; if (!old) old = 1; new_vec = stp_malloc(sizeof(double) * limit); /* * Be very careful how we calculate the location along the scale! * If we're not careful how we do it, we might get a small roundoff * error */ if (curve->piecewise) { double blo, bhi; int curpos = 0; stp_sequence_get_bounds(curve->seq, &blo, &bhi); if (curve->recompute_interval) compute_intervals(curve); for (i = 0; i < old; i++) { double low; double high; double low_y; double high_y; double x_delta; if (!stp_sequence_get_point(curve->seq, i * 2, &low)) { stp_free(new_vec); return 0; } if (i == old - 1) high = 1.0; else if (!stp_sequence_get_point(curve->seq, ((i + 1) * 2), &high)) { stp_free(new_vec); return 0; } if (!stp_sequence_get_point(curve->seq, (i * 2) + 1, &low_y)) { stp_free(new_vec); return 0; } if (!stp_sequence_get_point(curve->seq, ((i + 1) * 2) + 1, &high_y)) { stp_free(new_vec); return 0; } stp_deprintf(STP_DBG_CURVE, "Filling slots at %ld %d: %f %f %f %f %ld\n", (long)i,curpos, high, low, high_y, low_y, (long)limit); x_delta = high - low; high *= (limit - 1); low *= (limit - 1); while (curpos <= high) { double frac = (curpos - low) / (high - low); if (curve->curve_type == STP_CURVE_TYPE_LINEAR) new_vec[curpos] = low_y + frac * (high_y - low_y); else new_vec[curpos] = do_interpolate_spline(low_y, high_y, frac, curve->interval[i], curve->interval[i + 1], x_delta); if (new_vec[curpos] < blo) new_vec[curpos] = blo; if (new_vec[curpos] > bhi) new_vec[curpos] = bhi; stp_deprintf(STP_DBG_CURVE, " Filling slot %d %f %f\n", curpos, frac, new_vec[curpos]); curpos++; } } curve->piecewise = 0; } else { for (i = 0; i < limit; i++) if (curve->gamma) new_vec[i] = interpolate_gamma_internal(curve, ((double) i * (double) old / (double) (limit - 1))); else new_vec[i] = interpolate_point_internal(curve, ((double) i * (double) old / (double) (limit - 1))); } stpi_curve_set_points(curve, points); stp_sequence_set_subrange(curve->seq, 0, limit, new_vec); curve->recompute_interval = 1; stp_free(new_vec); return 1; }