## Code Excerpt for Functions PatternBrick

    PatternBrick::PatternBrick(){

        mortar_w_ = 0.01;
        mortar_h_ = mortar_w_;
        shift_ = 0.5;
        brick_mortar_w_ = 0.25 + mortar_w_;
        brick_mortar_h_ = 0.2 + mortar_h_;
        step_type_ = 0;
        shift_noise_ = 0;
        add_noise_ = 0;

    }

    void PatternBrick::setupParameter(const Scalar &brick_w,
                                      const Scalar &brick_h,
                                      const Scalar &mortar,
                                      const Scalar &shift,
                                      const size_t &step_type,
                                      const size_t &shift_noise,
                                      const size_t &add_noise){

        mortar_w_ = mortar;
        mortar_h_ = mortar;
        shift_ = shift;
        brick_mortar_w_ = brick_w + mortar;
        brick_mortar_h_ = brick_h + mortar;
        mortar_w_ = (mortar *0.5)/brick_mortar_w_;
        mortar_h_ = (mortar *0.5)/brick_mortar_h_;
        step_type_ = step_type;
        shift_noise_ = shift_noise;
        add_noise_ = add_noise;

    }

    Scalar PatternBrick::smoothStep(const Scalar& i, const Scalar& a, const Scalar& b){

        if(a==b) return 0;
        if(i<a) return 0;
        if(b<i) return 1;

        Scalar p = (i-a)/(b-a);
        return (p*p*(3-2*p));

    }

    Scalar PatternBrick::step(const Scalar& i, const Scalar& a){
        return (Scalar)(i >= a);
    }

    //Implementation based on:
    //Ebert, David S. Texturing & Modeling a Procedural Approach. San Francisco, Calif.: Morgan Kaufmann, 2003.

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

        Scalar value = 0.0;
        float xx, yy, w, h;

        xx = x_norm / brick_mortar_w_;
        yy = y_norm / brick_mortar_h_;
        y_brick_index_ = floor(yy);

        // shift the brick x position per row
        // check for negative coordinates
        if(y_norm >= 0.0){
            xx+=shift_;
        }

        if (fmod(fabs(yy)*0.5,1) > 0.5) xx += shift_;

        if(shift_noise_ == 1){
            // a bit of randomness for the position of the bricks per row
            Scalar noise = perlin_.noiseNormalized(0.1,y_brick_index_,0.2) * 0.3;
            if(shift_<0.5) noise*=0.5;
            xx += noise;
        }

        x_brick_index_ = floor(xx);

        xx -= x_brick_index_;
        yy -= y_brick_index_;

        w = step(mortar_w_,xx) - step(1-mortar_w_,xx);
        h = step(mortar_h_,yy) - step(1-mortar_h_,yy);

        value = w*h;

        Scalar brick_noise = 0.32;
        Scalar mortar_noise = 0.14;

        // on the mortar
        if(value < 1){
          if(step_type_ == 1){
            // simulate shadow between the bricks
            xx-=(0.25 * mortar_w_);
            yy-=(0.25 * mortar_h_);

            w = (smoothStep(xx, 0, mortar_w_) - smoothStep(xx,  1-mortar_w_, 1)) ;
            h = (smoothStep(yy, 0, mortar_h_) - smoothStep(yy,  1-mortar_h_, 1)) ;
            value = (1 - w*h) / 1.3;
            value = 0.2 + value *0.7;
          }
          mortar_noise = 0.22;
          brick_noise = 0.15;
        } else {
          value -= 0.4*perlin_.noiseNormalized(x_brick_index_, y_brick_index_+1000, 0.2);
        }

        if(add_noise_) {
          Scalar brick_noise_size = (1-brick_mortar_w_*brick_mortar_h_);
          value -= brick_noise * turbulence_.turbulence(x_norm * brick_noise_size, y_norm* brick_noise_size, 1.3);

          Scalar mortar_noise_size = 120;
          value += mortar_noise * perlin_.noiseNormalized(mortar_noise_size*x_norm, mortar_noise_size*y_norm, 0.2);

          value-= 0.01*turbulence_.turbulence(1.5*x_norm, 1.5*y_norm, 15);
        }

        return value;

    }