Exemplo n.º 1
0
static void
compute_linear_deltas(stp_curve_t *curve)
{
  int i;
  size_t delta_count;
  size_t seq_point_count;
  const double *data;

  stp_sequence_get_data(curve->seq, &seq_point_count, &data);
  if (data == NULL)
    return;

  delta_count = get_real_point_count(curve);

  if (delta_count <= 1) /* No intervals can be computed */
    return;
  delta_count--; /* One less than the real point count.  Note size_t
		    is unsigned. */

  curve->interval = stp_malloc(sizeof(double) * delta_count);
  for (i = 0; i < delta_count; i++)
    {
      if (curve->piecewise)
	curve->interval[i] = data[(2 * (i + 1)) + 1] - data[(2 * i) + 1];
      else
	curve->interval[i] = data[i + 1] - data[i];
    }
}
Exemplo n.º 2
0
/*
 * Get the number of points used by the curve (that are visible to the
 * user).  This is the real point count, but is decreased by 1 if the
 * curve wraps around.
 */
static size_t
get_point_count(const stp_curve_t *curve)
{
  size_t count = get_real_point_count(curve);
  if (curve->wrap_mode == STP_CURVE_WRAP_AROUND)
    count -= 1;

  return count;
}
Exemplo n.º 3
0
int
stp_curve_interpolate_value(const stp_curve_t *curve, double where,
			    double *result)
{
  size_t limit;

  CHECK_CURVE(curve);
  if (curve->piecewise)
    return 0;

  limit = get_real_point_count(curve);

  if (where < 0 || where > limit)
    return 0;
  if (curve->gamma)	/* this means a pure gamma curve */
    *result = interpolate_gamma_internal(curve, where);
  else
    *result = interpolate_point_internal(curve, where);
  return 1;
}
Exemplo n.º 4
0
static inline double
interpolate_gamma_internal(const stp_curve_t *curve, double where)
{
  double fgamma = curve->gamma;
  double blo, bhi;
  size_t real_point_count;

  real_point_count = get_real_point_count(curve);;

  if (real_point_count)
    where /= (real_point_count - 1);
  if (fgamma < 0)
    {
      where = 1.0 - where;
      fgamma = -fgamma;
    }
  stp_sequence_get_bounds(curve->seq, &blo, &bhi);
  stp_deprintf(STP_DBG_CURVE,
	       "interpolate_gamma %f %f %f %f %f\n", where, fgamma,
	       blo, bhi, pow(where, fgamma));
  return blo + (bhi - blo) * pow(where, fgamma);
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
int
stp_curve_rescale(stp_curve_t *curve, double scale,
		  stp_curve_compose_t mode, stp_curve_bounds_t bounds_mode)
{
  size_t real_point_count;
  int i;
  double nblo;
  double nbhi;
  size_t count;

  CHECK_CURVE(curve);

  real_point_count = get_real_point_count(curve);

  stp_sequence_get_bounds(curve->seq, &nblo, &nbhi);
  if (bounds_mode == STP_CURVE_BOUNDS_RESCALE)
    {
      switch (mode)
	{
	case STP_CURVE_COMPOSE_ADD:
	  nblo += scale;
	  nbhi += scale;
	  break;
	case STP_CURVE_COMPOSE_MULTIPLY:
	  if (scale < 0)
	    {
	      double tmp = nblo * scale;
	      nblo = nbhi * scale;
	      nbhi = tmp;
	    }
	  else
	    {
	      nblo *= scale;
	      nbhi *= scale;
	    }
	  break;
	case STP_CURVE_COMPOSE_EXPONENTIATE:
	  if (scale == 0.0)
	    return 0;
	  if (nblo < 0)
	    return 0;
	  nblo = pow(nblo, scale);
	  nbhi = pow(nbhi, scale);
	  break;
	default:
	  return 0;
	}
    }

  if (! isfinite(nbhi) || ! isfinite(nblo))
    return 0;

  count = get_point_count(curve);
  if (count)
    {
      double *tmp;
      size_t scount;
      int stride = 1;
      int offset = 0;
      const double *data;
      if (curve->piecewise)
	{
	  stride = 2;
	  offset = 1;
	}
      stp_sequence_get_data(curve->seq, &scount, &data);
      tmp = stp_malloc(sizeof(double) * scount);
      memcpy(tmp, data, scount * sizeof(double));
      for (i = offset; i < scount; i += stride)
	{
	  switch (mode)
	    {
	    case STP_CURVE_COMPOSE_ADD:
	      tmp[i] = tmp[i] + scale;
	      break;
	    case STP_CURVE_COMPOSE_MULTIPLY:
	      tmp[i] = tmp[i] * scale;
	      break;
	    case STP_CURVE_COMPOSE_EXPONENTIATE:
	      tmp[i] = pow(tmp[i], scale);
	      break;
	    }
	  if (tmp[i] > nbhi || tmp[i] < nblo)
	    {
	      if (bounds_mode == STP_CURVE_BOUNDS_ERROR)
		{
		  stp_free(tmp);
		  return(0);
		}
	      else if (tmp[i] > nbhi)
		tmp[i] = nbhi;
	      else
		tmp[i] = nblo;
	    }
	}
      stp_sequence_set_bounds(curve->seq, nblo, nbhi);
      curve->gamma = 0.0;
      stpi_curve_set_points(curve, count);
      stp_sequence_set_subrange(curve->seq, 0, scount, tmp);
      stp_free(tmp);
      curve->recompute_interval = 1;
      invalidate_auxiliary_data(curve);
    }
  return 1;
}