## Code Excerpt for Texture Model Cellular

    Scalar PointDensity; // in [1 .. 6] stepsize 0.25
    Scalar Jitter;       // in [0 .. 1] stepsize 0.1
    Scalar InnerWidth;   // in [0 .. 1] stepsize 0.05
    Scalar OuterWidth;   // in [0 .. 1] stepsize 0.05

    void TextureCellular::setupParameter(){

      // ad-hoc perceptual scaling
      Scalar num_points_x = pow(2, PointDensity);
      Scalar num_points_y = num_points_x;

      Scalar jitter = Jitter * 2.5;

      if(OuterWidth > InnerWidth) {
        width_inner_ = InnerWidth;
        width_outer_ = OuterWidth;
      } else {
        width_inner_ = OuterWidth;
        width_outer_ = InnerWidth;
      }

      // setup data
      distance_min_ = std::numeric_limits<float>::infinity();
      distance_max_ = -std::numeric_limits<float>::infinity();

      // calculate distances for an image size that contains all possible rotations
      size_ = getImageSizeForRotation(settings_.resolution_x, settings_.resolution_y, rotation_);
      int w = size_.x();
      int h = size_.y();

      imglib::Image<Scalar>tmp(w,h,1);
      img_distances_ = tmp;

      vector<vector<Scalar> > coords(ceil(num_points_x+2)*ceil(num_points_y+2), vector<Scalar>(2));

      generator_.seed(0);
      boost::uniform_real<> uni_dist(0,1);

      // generate point list
      Scalar p0, p1;

      for (size_t i = 0; i < coords.size(); ++i) {
        int x = i % ((int) ceil(num_points_x+2));
        int y = i / ((int) ceil(num_points_x+2));
        float sx = float (x-1) / (num_points_x);
        float sy = float (y-1) / (num_points_y);

        p0 = sx * w;
        p1 = sy * h;
        coords[i][0] = p0;
        coords[i][1] = p1;
      }

      // add jitter
      for (size_t i = 0; i < coords.size(); ++i) {
        boost::variate_generator<boost::minstd_rand&, boost::uniform_real<> > valx(generator_, uni_dist);
        p0=(valx() * w);
        boost::variate_generator<boost::minstd_rand&, boost::uniform_real<> > valy(generator_, uni_dist);
        p1=(valy() * h);

        p0 *= jitter / num_points_x;
        p1 *= jitter / num_points_x;
        coords[i][0] += p0;
        coords[i][1] += p1;

        if (coords[i][0] > w + w / (float) (num_points_x)){
          coords[i][0] -= w;
        }
        if (coords[i][1] > h + h / (float) (num_points_y)) {
          coords[i][1] -= h;
        }

      }

      // calculate distances to all pixel
      Scalar distance_tmp = 0;
      for(int y=0; y < h; ++y) {
        for(int x=0; x < w; ++x) {
          distance_tmp = distanceNearestPoint(x, y, coords, ceil(num_points_x+2), ceil(num_points_y+2));
          img_distances_(x,y,0)= distance_tmp;
          if (distance_tmp < distance_min_) distance_min_ = distance_tmp;
          if (distance_tmp > distance_max_) distance_max_ = distance_tmp;
        }
      }
    }

    Scalar TextureCellular::evaluate(const Scalar &x_norm, const Scalar &y_norm){

      Scalar value = 0.0;
      // offset for converting coordinates to only positive numbers
      int offset_x = 0.5*(size_.x() - settings_.resolution_x);
      int offset_y = 0.5*(size_.y() - settings_.resolution_y);

      // coordinates in pixel sizes
      int coord_x = boost::math::iround(x_norm * settings_.resolution_x) + offset_x;
      int coord_y = boost::math::iround(y_norm * settings_.resolution_y) + offset_y;

      if(coord_x < size_.x() && coord_x >= 0 && coord_y < size_.y()  && coord_y >= 0) {
        value = (1 - (img_distances_(coord_x, coord_y,0) - distance_min_) / (distance_max_- distance_min_));
        value = (value - width_inner_) / (std::max) ((Scalar) 10e-8, (width_outer_ - width_inner_));
        value = (std::min) ( (Scalar) 1.0, (std::max) ( (Scalar) 0.0, value));
      }

      return value;

    }